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 33 import android.Manifest; 34 import android.annotation.NonNull; 35 import android.annotation.Nullable; 36 import android.annotation.UserIdInt; 37 import android.app.ActivityManager; 38 import android.app.AppOpsManager; 39 import android.app.IUidObserver; 40 import android.app.PendingIntent; 41 import android.app.admin.DevicePolicyManagerInternal; 42 import android.app.usage.AppStandbyInfo; 43 import android.app.usage.ConfigurationStats; 44 import android.app.usage.EventStats; 45 import android.app.usage.IUsageStatsManager; 46 import android.app.usage.UsageEvents; 47 import android.app.usage.UsageEvents.Event; 48 import android.app.usage.UsageStats; 49 import android.app.usage.UsageStatsManager; 50 import android.app.usage.UsageStatsManager.StandbyBuckets; 51 import android.app.usage.UsageStatsManager.UsageSource; 52 import android.app.usage.UsageStatsManagerInternal; 53 import android.content.BroadcastReceiver; 54 import android.content.ComponentName; 55 import android.content.Context; 56 import android.content.Intent; 57 import android.content.IntentFilter; 58 import android.content.LocusId; 59 import android.content.pm.PackageInfo; 60 import android.content.pm.PackageManager; 61 import android.content.pm.PackageManagerInternal; 62 import android.content.pm.ParceledListSlice; 63 import android.content.pm.ShortcutServiceInternal; 64 import android.content.res.Configuration; 65 import android.os.Binder; 66 import android.os.Environment; 67 import android.os.FileUtils; 68 import android.os.Handler; 69 import android.os.IBinder; 70 import android.os.Looper; 71 import android.os.Message; 72 import android.os.Process; 73 import android.os.RemoteException; 74 import android.os.SystemClock; 75 import android.os.SystemProperties; 76 import android.os.UserHandle; 77 import android.os.UserManager; 78 import android.provider.Settings; 79 import android.text.TextUtils; 80 import android.util.ArrayMap; 81 import android.util.ArraySet; 82 import android.util.AtomicFile; 83 import android.util.Slog; 84 import android.util.SparseArray; 85 import android.util.SparseIntArray; 86 87 import com.android.internal.annotations.VisibleForTesting; 88 import com.android.internal.content.PackageMonitor; 89 import com.android.internal.os.BackgroundThread; 90 import com.android.internal.util.CollectionUtils; 91 import com.android.internal.util.DumpUtils; 92 import com.android.internal.util.FrameworkStatsLog; 93 import com.android.internal.util.IndentingPrintWriter; 94 import com.android.server.LocalServices; 95 import com.android.server.SystemService; 96 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; 97 98 import java.io.BufferedReader; 99 import java.io.BufferedWriter; 100 import java.io.File; 101 import java.io.FileDescriptor; 102 import java.io.FileInputStream; 103 import java.io.FileOutputStream; 104 import java.io.FileReader; 105 import java.io.FileWriter; 106 import java.io.IOException; 107 import java.io.PrintWriter; 108 import java.nio.file.Files; 109 import java.nio.file.StandardCopyOption; 110 import java.util.ArrayList; 111 import java.util.Arrays; 112 import java.util.HashMap; 113 import java.util.LinkedList; 114 import java.util.List; 115 import java.util.Map; 116 import java.util.Objects; 117 import java.util.Set; 118 import java.util.concurrent.CopyOnWriteArraySet; 119 import java.util.concurrent.TimeUnit; 120 121 /** 122 * A service that collects, aggregates, and persists application usage data. 123 * This data can be queried by apps that have been granted permission by AppOps. 124 */ 125 public class UsageStatsService extends SystemService implements 126 UserUsageStatsService.StatsUpdatedListener { 127 128 static final String TAG = "UsageStatsService"; 129 public static final boolean ENABLE_TIME_CHANGE_CORRECTION 130 = SystemProperties.getBoolean("persist.debug.time_correction", true); 131 132 static final boolean DEBUG = false; // Never submit with true 133 static final boolean COMPRESS_TIME = false; 134 135 private static final long TEN_SECONDS = 10 * 1000; 136 private static final long TWENTY_MINUTES = 20 * 60 * 1000; 137 private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; 138 static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. 139 140 private static final boolean ENABLE_KERNEL_UPDATES = true; 141 private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); 142 143 private static final File USAGE_STATS_LEGACY_DIR = new File( 144 Environment.getDataSystemDirectory(), "usagestats"); 145 // For migration purposes, indicates whether to keep the legacy usage stats directory or not 146 private static final boolean KEEP_LEGACY_DIR = false; 147 148 private static final File COMMON_USAGE_STATS_DE_DIR = 149 new File(Environment.getDataSystemDeDirectory(), "usagestats"); 150 private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; 151 152 private static final char TOKEN_DELIMITER = '/'; 153 154 // Handler message types. 155 static final int MSG_REPORT_EVENT = 0; 156 static final int MSG_FLUSH_TO_DISK = 1; 157 static final int MSG_REMOVE_USER = 2; 158 static final int MSG_UID_STATE_CHANGED = 3; 159 static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4; 160 static final int MSG_UNLOCKED_USER = 5; 161 static final int MSG_PACKAGE_REMOVED = 6; 162 static final int MSG_ON_START = 7; 163 164 private final Object mLock = new Object(); 165 Handler mHandler; 166 AppOpsManager mAppOps; 167 UserManager mUserManager; 168 PackageManager mPackageManager; 169 PackageManagerInternal mPackageManagerInternal; 170 // Do not use directly. Call getDpmInternal() instead 171 DevicePolicyManagerInternal mDpmInternal; 172 // Do not use directly. Call getShortcutServiceInternal() instead 173 ShortcutServiceInternal mShortcutServiceInternal; 174 175 private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); 176 private final CopyOnWriteArraySet<Integer> mUserUnlockedStates = new CopyOnWriteArraySet<>(); 177 private final SparseIntArray mUidToKernelCounter = new SparseIntArray(); 178 int mUsageSource; 179 180 private long mRealTimeSnapshot; 181 private long mSystemTimeSnapshot; 182 // A map storing last time global usage of packages, measured in milliseconds since the epoch. 183 private final Map<String, Long> mLastTimeComponentUsedGlobal = new ArrayMap<>(); 184 185 /** Manages the standby state of apps. */ 186 AppStandbyInternal mAppStandby; 187 188 /** Manages app time limit observers */ 189 AppTimeLimitController mAppTimeLimit; 190 191 private final PackageMonitor mPackageMonitor = new MyPackageMonitor(); 192 193 // A map maintaining a queue of events to be reported per user. 194 private final SparseArray<LinkedList<Event>> mReportedEvents = new SparseArray<>(); 195 final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray(); 196 final SparseArray<ActivityData> mVisibleActivities = new SparseArray(); 197 private final ArraySet<UsageStatsManagerInternal.UsageEventListener> mUsageEventListeners = 198 new ArraySet<>(); 199 200 private static class ActivityData { 201 private final String mTaskRootPackage; 202 private final String mTaskRootClass; 203 private final String mUsageSourcePackage; 204 public int lastEvent = Event.NONE; ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage)205 private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) { 206 mTaskRootPackage = taskRootPackage; 207 mTaskRootClass = taskRootClass; 208 mUsageSourcePackage = sourcePackage; 209 } 210 } 211 212 private AppIdleStateChangeListener mStandbyChangeListener = 213 new AppIdleStateChangeListener() { 214 @Override 215 public void onAppIdleStateChanged(String packageName, int userId, boolean idle, 216 int bucket, int reason) { 217 Event event = new Event(Event.STANDBY_BUCKET_CHANGED, 218 SystemClock.elapsedRealtime()); 219 event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF); 220 event.mPackage = packageName; 221 reportEventOrAddToQueue(userId, event); 222 } 223 }; 224 225 @VisibleForTesting 226 static class Injector { getAppStandbyController(Context context)227 AppStandbyInternal getAppStandbyController(Context context) { 228 return AppStandbyInternal.newAppStandbyController( 229 UsageStatsService.class.getClassLoader(), context); 230 } 231 } 232 233 private final Injector mInjector; 234 UsageStatsService(Context context)235 public UsageStatsService(Context context) { 236 this(context, new Injector()); 237 } 238 239 @VisibleForTesting UsageStatsService(Context context, Injector injector)240 UsageStatsService(Context context, Injector injector) { 241 super(context); 242 mInjector = injector; 243 } 244 245 @Override onStart()246 public void onStart() { 247 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); 248 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 249 mPackageManager = getContext().getPackageManager(); 250 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 251 mHandler = new H(BackgroundThread.get().getLooper()); 252 253 mAppStandby = mInjector.getAppStandbyController(getContext()); 254 255 mAppTimeLimit = new AppTimeLimitController(getContext(), 256 new AppTimeLimitController.TimeLimitCallbackListener() { 257 @Override 258 public void onLimitReached(int observerId, int userId, long timeLimit, 259 long timeElapsed, PendingIntent callbackIntent) { 260 if (callbackIntent == null) return; 261 Intent intent = new Intent(); 262 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId); 263 intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit); 264 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed); 265 try { 266 callbackIntent.send(getContext(), 0, intent); 267 } catch (PendingIntent.CanceledException e) { 268 Slog.w(TAG, "Couldn't deliver callback: " 269 + callbackIntent); 270 } 271 } 272 273 @Override 274 public void onSessionEnd(int observerId, int userId, long timeElapsed, 275 PendingIntent callbackIntent) { 276 if (callbackIntent == null) return; 277 Intent intent = new Intent(); 278 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId); 279 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed); 280 try { 281 callbackIntent.send(getContext(), 0, intent); 282 } catch (PendingIntent.CanceledException e) { 283 Slog.w(TAG, "Couldn't deliver callback: " 284 + callbackIntent); 285 } 286 } 287 }, mHandler.getLooper()); 288 289 mAppStandby.addListener(mStandbyChangeListener); 290 291 mPackageMonitor.register(getContext(), null, UserHandle.ALL, true); 292 293 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED); 294 filter.addAction(Intent.ACTION_USER_STARTED); 295 getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter, 296 null, mHandler); 297 298 mRealTimeSnapshot = SystemClock.elapsedRealtime(); 299 mSystemTimeSnapshot = System.currentTimeMillis(); 300 301 publishLocalService(UsageStatsManagerInternal.class, new LocalService()); 302 publishLocalService(AppStandbyInternal.class, mAppStandby); 303 publishBinderServices(); 304 305 mHandler.obtainMessage(MSG_ON_START).sendToTarget(); 306 } 307 308 @VisibleForTesting publishBinderServices()309 void publishBinderServices() { 310 publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); 311 } 312 313 @Override onBootPhase(int phase)314 public void onBootPhase(int phase) { 315 mAppStandby.onBootPhase(phase); 316 if (phase == PHASE_SYSTEM_SERVICES_READY) { 317 // initialize mDpmInternal 318 getDpmInternal(); 319 // initialize mShortcutServiceInternal 320 getShortcutServiceInternal(); 321 322 if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) { 323 try { 324 ActivityManager.getService().registerUidObserver(mUidObserver, 325 ActivityManager.UID_OBSERVER_PROCSTATE 326 | ActivityManager.UID_OBSERVER_GONE, 327 ActivityManager.PROCESS_STATE_UNKNOWN, null); 328 } catch (RemoteException e) { 329 throw new RuntimeException(e); 330 } 331 } else { 332 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE); 333 } 334 readUsageSourceSetting(); 335 } 336 } 337 338 @Override onUserStarting(@onNull TargetUser user)339 public void onUserStarting(@NonNull TargetUser user) { 340 // Create an entry in the user state map to indicate that the user has been started but 341 // not necessarily unlocked. This will ensure that reported events are flushed to disk 342 // event if the user is never unlocked (following the logic in #flushToDiskLocked) 343 mUserState.put(user.getUserIdentifier(), null); 344 } 345 346 @Override onUserUnlocking(@onNull TargetUser user)347 public void onUserUnlocking(@NonNull TargetUser user) { 348 mHandler.obtainMessage(MSG_UNLOCKED_USER, user.getUserIdentifier(), 0).sendToTarget(); 349 } 350 351 @Override onUserStopping(@onNull TargetUser user)352 public void onUserStopping(@NonNull TargetUser user) { 353 final int userId = user.getUserIdentifier(); 354 355 synchronized (mLock) { 356 // User was started but never unlocked so no need to report a user stopped event 357 if (!mUserUnlockedStates.contains(userId)) { 358 persistPendingEventsLocked(userId); 359 return; 360 } 361 362 // Report a user stopped event before persisting all stats to disk via the user service 363 final Event event = new Event(USER_STOPPED, SystemClock.elapsedRealtime()); 364 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 365 reportEvent(event, userId); 366 final UserUsageStatsService userService = mUserState.get(userId); 367 if (userService != null) { 368 userService.userStopped(); 369 } 370 mUserUnlockedStates.remove(userId); 371 mUserState.put(userId, null); // release the service (mainly for GC) 372 } 373 } 374 onUserUnlocked(int userId)375 private void onUserUnlocked(int userId) { 376 // fetch the installed packages outside the lock so it doesn't block package manager. 377 final HashMap<String, Long> installedPackages = getInstalledPackages(userId); 378 // delay updating of package mappings for user 0 since their data is not likely to be stale. 379 // this also makes it less likely for restored data to be erased on unexpected reboots. 380 if (userId == UserHandle.USER_SYSTEM) { 381 UsageStatsIdleService.scheduleUpdateMappingsJob(getContext()); 382 } 383 synchronized (mLock) { 384 // This should be safe to add this early. Other than reportEventOrAddToQueue, every 385 // other user grabs the lock before accessing 386 // mUserUnlockedStates. reportEventOrAddToQueue does not depend on anything other than 387 // mUserUnlockedStates, and the lock will protect the handler. 388 mUserUnlockedStates.add(userId); 389 // Create a user unlocked event to report 390 final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime()); 391 unlockEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 392 393 migrateStatsToSystemCeIfNeededLocked(userId); 394 395 // Read pending reported events from disk and merge them with those stored in memory 396 final LinkedList<Event> pendingEvents = new LinkedList<>(); 397 loadPendingEventsLocked(userId, pendingEvents); 398 final LinkedList<Event> eventsInMem = mReportedEvents.get(userId); 399 if (eventsInMem != null) { 400 pendingEvents.addAll(eventsInMem); 401 } 402 boolean needToFlush = !pendingEvents.isEmpty(); 403 404 initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(), 405 installedPackages); 406 final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId); 407 if (userService == null) { 408 Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId); 409 return; 410 } 411 412 // Process all the pending reported events 413 while (pendingEvents.peek() != null) { 414 reportEvent(pendingEvents.poll(), userId); 415 } 416 reportEvent(unlockEvent, userId); 417 418 // Remove all the stats stored in memory and in system DE. 419 mReportedEvents.remove(userId); 420 deleteRecursively(new File(Environment.getDataSystemDeDirectory(userId), "usagestats")); 421 // Force a flush to disk for the current user to ensure important events are persisted. 422 // Note: there is a very very small chance that the system crashes between deleting 423 // the stats above from DE and persisting them to CE here in which case we will lose 424 // those events that were in memory and deleted from DE. (b/139836090) 425 if (needToFlush) { 426 userService.persistActiveStats(); 427 } 428 } 429 } 430 431 /** 432 * Fetches a map (package_name:install_time) of installed packages for the given user. This 433 * map contains all installed packages, including those packages which have been uninstalled 434 * with the DELETE_KEEP_DATA flag. 435 * This is a helper method which should only be called when the given user's usage stats service 436 * is initialized; it performs a heavy query to package manager so do not call it otherwise. 437 * <br/> 438 * Note: DO NOT call this while holding the usage stats lock ({@code mLock}). 439 */ getInstalledPackages(int userId)440 private HashMap<String, Long> getInstalledPackages(int userId) { 441 if (mPackageManager == null) { 442 return null; 443 } 444 final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser( 445 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); 446 final HashMap<String, Long> packagesMap = new HashMap<>(); 447 for (int i = installedPackages.size() - 1; i >= 0; i--) { 448 final PackageInfo packageInfo = installedPackages.get(i); 449 packagesMap.put(packageInfo.packageName, packageInfo.firstInstallTime); 450 } 451 return packagesMap; 452 } 453 getDpmInternal()454 private DevicePolicyManagerInternal getDpmInternal() { 455 if (mDpmInternal == null) { 456 mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class); 457 } 458 return mDpmInternal; 459 } 460 getShortcutServiceInternal()461 private ShortcutServiceInternal getShortcutServiceInternal() { 462 if (mShortcutServiceInternal == null) { 463 mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class); 464 } 465 return mShortcutServiceInternal; 466 } 467 readUsageSourceSetting()468 private void readUsageSourceSetting() { 469 synchronized (mLock) { 470 mUsageSource = Settings.Global.getInt(getContext().getContentResolver(), 471 Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY); 472 } 473 } 474 475 private class UserActionsReceiver extends BroadcastReceiver { 476 @Override onReceive(Context context, Intent intent)477 public void onReceive(Context context, Intent intent) { 478 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 479 final String action = intent.getAction(); 480 if (Intent.ACTION_USER_REMOVED.equals(action)) { 481 if (userId >= 0) { 482 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 483 } 484 } else if (Intent.ACTION_USER_STARTED.equals(action)) { 485 if (userId >= 0) { 486 mAppStandby.postCheckIdleStates(userId); 487 } 488 } 489 } 490 } 491 492 private final IUidObserver mUidObserver = new IUidObserver.Stub() { 493 @Override 494 public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { 495 mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); 496 } 497 498 @Override 499 public void onUidIdle(int uid, boolean disabled) { 500 // Ignored 501 } 502 503 @Override 504 public void onUidGone(int uid, boolean disabled) { 505 onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0, 506 ActivityManager.PROCESS_CAPABILITY_NONE); 507 } 508 509 @Override 510 public void onUidActive(int uid) { 511 // Ignored 512 } 513 514 @Override public void onUidCachedChanged(int uid, boolean cached) { 515 } 516 }; 517 518 @Override onStatsUpdated()519 public void onStatsUpdated() { 520 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 521 } 522 523 @Override onStatsReloaded()524 public void onStatsReloaded() { 525 mAppStandby.postOneTimeCheckIdleStates(); 526 } 527 528 @Override onNewUpdate(int userId)529 public void onNewUpdate(int userId) { 530 mAppStandby.initializeDefaultsForSystemApps(userId); 531 } 532 shouldObfuscateInstantAppsForCaller(int callingUid, int userId)533 private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) { 534 return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId); 535 } 536 shouldHideShortcutInvocationEvents(int userId, String callingPackage, int callingPid, int callingUid)537 private boolean shouldHideShortcutInvocationEvents(int userId, String callingPackage, 538 int callingPid, int callingUid) { 539 final ShortcutServiceInternal shortcutServiceInternal = getShortcutServiceInternal(); 540 if (shortcutServiceInternal != null) { 541 return !shortcutServiceInternal.hasShortcutHostPermission(userId, callingPackage, 542 callingPid, callingUid); 543 } 544 return true; // hide by default if we can't verify visibility 545 } 546 shouldHideLocusIdEvents(int callingPid, int callingUid)547 private boolean shouldHideLocusIdEvents(int callingPid, int callingUid) { 548 if (callingUid == Process.SYSTEM_UID) { 549 return false; 550 } 551 return !(getContext().checkPermission( 552 android.Manifest.permission.ACCESS_LOCUS_ID_USAGE_STATS, callingPid, callingUid) 553 == PackageManager.PERMISSION_GRANTED); 554 } 555 556 /** 557 * Obfuscate both {@link UsageEvents.Event#NOTIFICATION_SEEN} and 558 * {@link UsageEvents.Event#NOTIFICATION_INTERRUPTION} events if the provided calling uid does 559 * not hold the {@link android.Manifest.permission.MANAGE_NOTIFICATIONS} permission. 560 */ shouldObfuscateNotificationEvents(int callingPid, int callingUid)561 private boolean shouldObfuscateNotificationEvents(int callingPid, int callingUid) { 562 if (callingUid == Process.SYSTEM_UID) { 563 return false; 564 } 565 return !(getContext().checkPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS, 566 callingPid, callingUid) == PackageManager.PERMISSION_GRANTED); 567 } 568 deleteRecursively(File f)569 private static void deleteRecursively(File f) { 570 File[] files = f.listFiles(); 571 if (files != null) { 572 for (File subFile : files) { 573 deleteRecursively(subFile); 574 } 575 } 576 577 if (f.exists() && !f.delete()) { 578 Slog.e(TAG, "Failed to delete " + f); 579 } 580 } 581 582 /** 583 * This should the be only way to fetch the usage stats service for a specific user. 584 */ getUserUsageStatsServiceLocked(int userId)585 private UserUsageStatsService getUserUsageStatsServiceLocked(int userId) { 586 final UserUsageStatsService service = mUserState.get(userId); 587 if (service == null) { 588 Slog.wtf(TAG, "Failed to fetch usage stats service for user " + userId + ". " 589 + "The user might not have been initialized yet."); 590 } 591 return service; 592 } 593 594 /** 595 * Initializes the given user's usage stats service - this should ideally only be called once, 596 * when the user is initially unlocked. 597 */ initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, HashMap<String, Long> installedPackages)598 private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, 599 HashMap<String, Long> installedPackages) { 600 final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId), 601 "usagestats"); 602 final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId, 603 usageStatsDir, this); 604 try { 605 service.init(currentTimeMillis, installedPackages); 606 mUserState.put(userId, service); 607 } catch (Exception e) { 608 if (mUserManager.isUserUnlocked(userId)) { 609 Slog.w(TAG, "Failed to initialized unlocked user " + userId); 610 throw e; // rethrow the exception - user is unlocked 611 } else { 612 Slog.w(TAG, "Attempted to initialize service for stopped or removed user " 613 + userId); 614 } 615 } 616 } 617 migrateStatsToSystemCeIfNeededLocked(int userId)618 private void migrateStatsToSystemCeIfNeededLocked(int userId) { 619 final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId), 620 "usagestats"); 621 if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) { 622 throw new IllegalStateException("Usage stats directory does not exist: " 623 + usageStatsDir.getAbsolutePath()); 624 } 625 // Check if the migrated status file exists - if not, migrate usage stats. 626 final File migrated = new File(usageStatsDir, "migrated"); 627 if (migrated.exists()) { 628 try (BufferedReader reader = new BufferedReader(new FileReader(migrated))) { 629 final int previousVersion = Integer.parseInt(reader.readLine()); 630 // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. 631 if (previousVersion >= 4) { 632 deleteLegacyDir(userId); 633 return; 634 } 635 // If migration logic needs to be changed in a future version, do it here. 636 } catch (NumberFormatException | IOException e) { 637 Slog.e(TAG, "Failed to read migration status file, possibly corrupted."); 638 deleteRecursively(usageStatsDir); 639 if (usageStatsDir.exists()) { 640 Slog.e(TAG, "Unable to delete usage stats CE directory."); 641 throw new RuntimeException(e); 642 } else { 643 // Make the directory again since previous migration was not complete 644 if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) { 645 throw new IllegalStateException("Usage stats directory does not exist: " 646 + usageStatsDir.getAbsolutePath()); 647 } 648 } 649 } 650 } 651 652 Slog.i(TAG, "Starting migration to system CE for user " + userId); 653 final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); 654 if (legacyUserDir.exists()) { 655 copyRecursively(usageStatsDir, legacyUserDir); 656 } 657 // Create a status file to indicate that the migration to CE has been completed. 658 try (BufferedWriter writer = new BufferedWriter(new FileWriter(migrated))) { 659 writer.write(Integer.toString(UsageStatsDatabase.BACKUP_VERSION)); 660 writer.write("\n"); 661 writer.flush(); 662 } catch (IOException e) { 663 Slog.e(TAG, "Failed to write migrated status file"); 664 throw new RuntimeException(e); 665 } 666 Slog.i(TAG, "Finished migration to system CE for user " + userId); 667 668 // Migration was successful - delete the legacy directory 669 deleteLegacyDir(userId); 670 } 671 copyRecursively(final File parent, File f)672 private static void copyRecursively(final File parent, File f) { 673 final File[] files = f.listFiles(); 674 if (files == null) { 675 try { 676 Files.copy(f.toPath(), new File(parent, f.getName()).toPath(), 677 StandardCopyOption.REPLACE_EXISTING); 678 } catch (IOException e) { 679 Slog.e(TAG, "Failed to move usage stats file : " + f.toString()); 680 throw new RuntimeException(e); 681 } 682 return; 683 } 684 685 for (int i = files.length - 1; i >= 0; i--) { 686 File newParent = parent; 687 if (files[i].isDirectory()) { 688 newParent = new File(parent, files[i].getName()); 689 final boolean mkdirSuccess = newParent.mkdirs(); 690 if (!mkdirSuccess && !newParent.exists()) { 691 throw new IllegalStateException( 692 "Failed to create usage stats directory during migration: " 693 + newParent.getAbsolutePath()); 694 } 695 } 696 copyRecursively(newParent, files[i]); 697 } 698 } 699 deleteLegacyDir(int userId)700 private void deleteLegacyDir(int userId) { 701 final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); 702 if (!KEEP_LEGACY_DIR && legacyUserDir.exists()) { 703 deleteRecursively(legacyUserDir); 704 if (legacyUserDir.exists()) { 705 Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " 706 + "dir for user " + userId); 707 } 708 // If all users have been migrated, delete the parent legacy usage stats directory 709 if (USAGE_STATS_LEGACY_DIR.list() != null 710 && USAGE_STATS_LEGACY_DIR.list().length == 0) { 711 if (!USAGE_STATS_LEGACY_DIR.delete()) { 712 Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats dir"); 713 } 714 } 715 } 716 } 717 718 /** 719 * Called by the Binder stub 720 */ shutdown()721 void shutdown() { 722 synchronized (mLock) { 723 mHandler.removeMessages(MSG_REPORT_EVENT); 724 Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); 725 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 726 // orderly shutdown, the last event is DEVICE_SHUTDOWN. 727 reportEventToAllUserId(event); 728 flushToDiskLocked(); 729 persistGlobalComponentUsageLocked(); 730 } 731 732 mAppStandby.flushToDisk(); 733 } 734 735 /** 736 * After power button is pressed for 3.5 seconds 737 * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}), 738 * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10 739 * seconds and the device is shutdown, the database is already persisted and we are not losing 740 * data. 741 * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise 742 * PhoneWindowManager may be blocked. 743 */ prepareForPossibleShutdown()744 void prepareForPossibleShutdown() { 745 Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); 746 event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME; 747 mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget(); 748 mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK); 749 } 750 loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents)751 private void loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents) { 752 final File usageStatsDeDir = new File(Environment.getDataSystemDeDirectory(userId), 753 "usagestats"); 754 final File[] pendingEventsFiles = usageStatsDeDir.listFiles(); 755 if (pendingEventsFiles == null || pendingEventsFiles.length == 0) { 756 return; 757 } 758 Arrays.sort(pendingEventsFiles); 759 760 final int numFiles = pendingEventsFiles.length; 761 for (int i = 0; i < numFiles; i++) { 762 final AtomicFile af = new AtomicFile(pendingEventsFiles[i]); 763 final LinkedList<Event> tmpEvents = new LinkedList<>(); 764 try { 765 try (FileInputStream in = af.openRead()) { 766 UsageStatsProtoV2.readPendingEvents(in, tmpEvents); 767 } 768 // only add to the pending events if the read was successful 769 pendingEvents.addAll(tmpEvents); 770 } catch (Exception e) { 771 // Most likely trying to read a corrupted file - log the failure and continue 772 // reading the other pending event files. 773 Slog.e(TAG, "Could not read " + pendingEventsFiles[i] + " for user " + userId); 774 } 775 } 776 } 777 persistPendingEventsLocked(int userId)778 private void persistPendingEventsLocked(int userId) { 779 final LinkedList<Event> pendingEvents = mReportedEvents.get(userId); 780 if (pendingEvents == null || pendingEvents.isEmpty()) { 781 return; 782 } 783 784 final File usageStatsDeDir = new File(Environment.getDataSystemDeDirectory(userId), 785 "usagestats"); 786 if (!usageStatsDeDir.mkdirs() && !usageStatsDeDir.exists()) { 787 throw new IllegalStateException("Usage stats DE directory does not exist: " 788 + usageStatsDeDir.getAbsolutePath()); 789 } 790 final File pendingEventsFile = new File(usageStatsDeDir, 791 "pendingevents_" + System.currentTimeMillis()); 792 final AtomicFile af = new AtomicFile(pendingEventsFile); 793 FileOutputStream fos = null; 794 try { 795 fos = af.startWrite(); 796 UsageStatsProtoV2.writePendingEvents(fos, pendingEvents); 797 af.finishWrite(fos); 798 fos = null; 799 pendingEvents.clear(); 800 } catch (Exception e) { 801 Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath() 802 + " for user " + userId); 803 } finally { 804 af.failWrite(fos); // when fos is null (successful write), this will no-op 805 } 806 } 807 loadGlobalComponentUsageLocked()808 private void loadGlobalComponentUsageLocked() { 809 final File[] packageUsageFile = COMMON_USAGE_STATS_DE_DIR.listFiles( 810 (dir, name) -> TextUtils.equals(name, GLOBAL_COMPONENT_USAGE_FILE_NAME)); 811 if (packageUsageFile == null || packageUsageFile.length == 0) { 812 return; 813 } 814 815 final AtomicFile af = new AtomicFile(packageUsageFile[0]); 816 final Map<String, Long> tmpUsage = new ArrayMap<>(); 817 try { 818 try (FileInputStream in = af.openRead()) { 819 UsageStatsProtoV2.readGlobalComponentUsage(in, tmpUsage); 820 } 821 // only add to in memory map if the read was successful 822 final Map.Entry<String, Long>[] entries = 823 (Map.Entry<String, Long>[]) tmpUsage.entrySet().toArray(); 824 final int size = entries.length; 825 for (int i = 0; i < size; ++i) { 826 // In memory data is usually the most up-to-date, so skip the packages which already 827 // have usage data. 828 mLastTimeComponentUsedGlobal.putIfAbsent( 829 entries[i].getKey(), entries[i].getValue()); 830 } 831 } catch (Exception e) { 832 // Most likely trying to read a corrupted file - log the failure 833 Slog.e(TAG, "Could not read " + packageUsageFile[0]); 834 } 835 } 836 persistGlobalComponentUsageLocked()837 private void persistGlobalComponentUsageLocked() { 838 if (mLastTimeComponentUsedGlobal.isEmpty()) { 839 return; 840 } 841 842 if (!COMMON_USAGE_STATS_DE_DIR.mkdirs() && !COMMON_USAGE_STATS_DE_DIR.exists()) { 843 throw new IllegalStateException("Common usage stats DE directory does not exist: " 844 + COMMON_USAGE_STATS_DE_DIR.getAbsolutePath()); 845 } 846 final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DE_DIR, 847 GLOBAL_COMPONENT_USAGE_FILE_NAME); 848 final AtomicFile af = new AtomicFile(lastTimePackageFile); 849 FileOutputStream fos = null; 850 try { 851 fos = af.startWrite(); 852 UsageStatsProtoV2.writeGlobalComponentUsage(fos, mLastTimeComponentUsedGlobal); 853 af.finishWrite(fos); 854 fos = null; 855 } catch (Exception e) { 856 Slog.e(TAG, "Failed to write " + lastTimePackageFile.getAbsolutePath()); 857 } finally { 858 af.failWrite(fos); // when fos is null (successful write), this will no-op 859 } 860 } 861 reportEventOrAddToQueue(int userId, Event event)862 private void reportEventOrAddToQueue(int userId, Event event) { 863 if (mUserUnlockedStates.contains(userId)) { 864 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 865 return; 866 } 867 synchronized (mLock) { 868 LinkedList<Event> events = mReportedEvents.get(userId); 869 if (events == null) { 870 events = new LinkedList<>(); 871 mReportedEvents.put(userId, events); 872 } 873 events.add(event); 874 if (events.size() == 1) { 875 // Every time a file is persisted to disk, mReportedEvents is cleared for this user 876 // so trigger a flush to disk every time the first event has been added. 877 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 878 } 879 } 880 } 881 882 /** 883 * Assuming the event's timestamp is measured in milliseconds since boot, 884 * convert it to a system wall time. System and real time snapshots are updated before 885 * conversion. 886 */ convertToSystemTimeLocked(Event event)887 private void convertToSystemTimeLocked(Event event) { 888 final long actualSystemTime = System.currentTimeMillis(); 889 if (ENABLE_TIME_CHANGE_CORRECTION) { 890 final long actualRealtime = SystemClock.elapsedRealtime(); 891 final long expectedSystemTime = 892 (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 893 final long diffSystemTime = actualSystemTime - expectedSystemTime; 894 if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { 895 // The time has changed. 896 Slog.i(TAG, "Time changed in by " + (diffSystemTime / 1000) + " seconds"); 897 mRealTimeSnapshot = actualRealtime; 898 mSystemTimeSnapshot = actualSystemTime; 899 } 900 } 901 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 902 } 903 904 /** 905 * Called by the Binder stub. 906 */ reportEvent(Event event, int userId)907 void reportEvent(Event event, int userId) { 908 final int uid; 909 // Acquire uid outside of mLock for events that need it 910 switch (event.mEventType) { 911 case Event.ACTIVITY_RESUMED: 912 case Event.ACTIVITY_PAUSED: 913 case Event.ACTIVITY_STOPPED: 914 uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId); 915 break; 916 default: 917 uid = 0; 918 } 919 920 if (event.mPackage != null 921 && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) { 922 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP; 923 } 924 925 synchronized (mLock) { 926 // This should never be called directly when the user is locked 927 if (!mUserUnlockedStates.contains(userId)) { 928 Slog.wtf(TAG, "Failed to report event for locked user " + userId 929 + " (" + event.mPackage + "/" + event.mClass 930 + " eventType:" + event.mEventType 931 + " instanceId:" + event.mInstanceId + ")"); 932 return; 933 } 934 935 switch (event.mEventType) { 936 case Event.ACTIVITY_RESUMED: 937 FrameworkStatsLog.write( 938 FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED, 939 uid, 940 event.mPackage, 941 event.mClass, 942 FrameworkStatsLog 943 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND); 944 // check if this activity has already been resumed 945 if (mVisibleActivities.get(event.mInstanceId) != null) break; 946 final String usageSourcePackage = getUsageSourcePackage(event); 947 try { 948 mAppTimeLimit.noteUsageStart(usageSourcePackage, userId); 949 } catch (IllegalArgumentException iae) { 950 Slog.e(TAG, "Failed to note usage start", iae); 951 } 952 final ActivityData resumedData = new ActivityData(event.mTaskRootPackage, 953 event.mTaskRootClass, usageSourcePackage); 954 resumedData.lastEvent = Event.ACTIVITY_RESUMED; 955 mVisibleActivities.put(event.mInstanceId, resumedData); 956 break; 957 case Event.ACTIVITY_PAUSED: 958 ActivityData pausedData = mVisibleActivities.get(event.mInstanceId); 959 if (pausedData == null) { 960 // Must have transitioned from Stopped/Destroyed to Paused state. 961 final String usageSourcePackage2 = getUsageSourcePackage(event); 962 try { 963 mAppTimeLimit.noteUsageStart(usageSourcePackage2, userId); 964 } catch (IllegalArgumentException iae) { 965 Slog.e(TAG, "Failed to note usage start", iae); 966 } 967 pausedData = new ActivityData(event.mTaskRootPackage, event.mTaskRootClass, 968 usageSourcePackage2); 969 mVisibleActivities.put(event.mInstanceId, pausedData); 970 } else { 971 FrameworkStatsLog.write( 972 FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED, 973 uid, 974 event.mPackage, 975 event.mClass, 976 FrameworkStatsLog 977 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND); 978 } 979 980 pausedData.lastEvent = Event.ACTIVITY_PAUSED; 981 if (event.mTaskRootPackage == null) { 982 // Task Root info is missing. Repair the event based on previous data 983 event.mTaskRootPackage = pausedData.mTaskRootPackage; 984 event.mTaskRootClass = pausedData.mTaskRootClass; 985 } 986 break; 987 case Event.ACTIVITY_DESTROYED: 988 // Treat activity destroys like activity stops. 989 event.mEventType = Event.ACTIVITY_STOPPED; 990 // Fallthrough 991 case Event.ACTIVITY_STOPPED: 992 final ActivityData prevData = 993 mVisibleActivities.removeReturnOld(event.mInstanceId); 994 if (prevData == null) { 995 Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage 996 + "/" + event.mClass + " event : " + event.mEventType 997 + " instanceId : " + event.mInstanceId + ")"); 998 return; 999 } 1000 1001 if (prevData.lastEvent != Event.ACTIVITY_PAUSED) { 1002 FrameworkStatsLog.write( 1003 FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED, 1004 uid, 1005 event.mPackage, 1006 event.mClass, 1007 FrameworkStatsLog 1008 .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND); 1009 } 1010 1011 ArraySet<String> tokens; 1012 synchronized (mUsageReporters) { 1013 tokens = mUsageReporters.removeReturnOld(event.mInstanceId); 1014 } 1015 if (tokens != null) { 1016 synchronized (tokens) { 1017 final int size = tokens.size(); 1018 // Stop usage on behalf of a UsageReporter that stopped 1019 for (int i = 0; i < size; i++) { 1020 final String token = tokens.valueAt(i); 1021 try { 1022 mAppTimeLimit.noteUsageStop( 1023 buildFullToken(event.mPackage, token), userId); 1024 } catch (IllegalArgumentException iae) { 1025 Slog.w(TAG, "Failed to stop usage for during reporter death: " 1026 + iae); 1027 } 1028 } 1029 } 1030 } 1031 if (event.mTaskRootPackage == null) { 1032 // Task Root info is missing. Repair the event based on previous data 1033 event.mTaskRootPackage = prevData.mTaskRootPackage; 1034 event.mTaskRootClass = prevData.mTaskRootClass; 1035 } 1036 try { 1037 mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId); 1038 } catch (IllegalArgumentException iae) { 1039 Slog.w(TAG, "Failed to note usage stop", iae); 1040 } 1041 break; 1042 case Event.USER_INTERACTION: 1043 // Fall through 1044 case Event.APP_COMPONENT_USED: 1045 convertToSystemTimeLocked(event); 1046 mLastTimeComponentUsedGlobal.put(event.mPackage, event.mTimeStamp); 1047 break; 1048 } 1049 1050 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1051 if (service == null) { 1052 return; // user was stopped or removed 1053 } 1054 service.reportEvent(event); 1055 } 1056 1057 final int size = mUsageEventListeners.size(); 1058 for (int i = 0; i < size; ++i) { 1059 mUsageEventListeners.valueAt(i).onUsageEvent(userId, event); 1060 } 1061 } 1062 getUsageSourcePackage(Event event)1063 private String getUsageSourcePackage(Event event) { 1064 switch(mUsageSource) { 1065 case USAGE_SOURCE_CURRENT_ACTIVITY: 1066 return event.mPackage; 1067 case USAGE_SOURCE_TASK_ROOT_ACTIVITY: 1068 default: 1069 return event.mTaskRootPackage; 1070 } 1071 } 1072 1073 /** 1074 * Some events like FLUSH_TO_DISK need to be sent to all userId. 1075 * @param event 1076 */ reportEventToAllUserId(Event event)1077 void reportEventToAllUserId(Event event) { 1078 synchronized (mLock) { 1079 final int userCount = mUserState.size(); 1080 for (int i = 0; i < userCount; i++) { 1081 Event copy = new Event(event); 1082 reportEventOrAddToQueue(mUserState.keyAt(i), copy); 1083 } 1084 } 1085 } 1086 1087 /** 1088 * Called by the Handler for message MSG_FLUSH_TO_DISK. 1089 */ flushToDisk()1090 void flushToDisk() { 1091 synchronized (mLock) { 1092 // Before flush to disk, report FLUSH_TO_DISK event to signal UsageStats to update app 1093 // usage. In case of abrupt power shutdown like battery drain or cold temperature, 1094 // all UsageStats has correct data up to last flush to disk. 1095 // The FLUSH_TO_DISK event is an internal event, it will not show up in IntervalStats' 1096 // EventList. 1097 Event event = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime()); 1098 event.mPackage = DEVICE_EVENT_PACKAGE_NAME; 1099 reportEventToAllUserId(event); 1100 flushToDiskLocked(); 1101 } 1102 mAppStandby.flushToDisk(); 1103 } 1104 1105 /** 1106 * Called by the Binder stub. 1107 */ onUserRemoved(int userId)1108 void onUserRemoved(int userId) { 1109 synchronized (mLock) { 1110 Slog.i(TAG, "Removing user " + userId + " and all data."); 1111 mUserState.remove(userId); 1112 mAppTimeLimit.onUserRemoved(userId); 1113 } 1114 mAppStandby.onUserRemoved(userId); 1115 // Cancel any scheduled jobs for this user since the user is being removed. 1116 UsageStatsIdleService.cancelJob(getContext(), userId); 1117 UsageStatsIdleService.cancelUpdateMappingsJob(getContext()); 1118 } 1119 1120 /** 1121 * Called by the Handler for message MSG_PACKAGE_REMOVED. 1122 */ onPackageRemoved(int userId, String packageName)1123 private void onPackageRemoved(int userId, String packageName) { 1124 final int tokenRemoved; 1125 synchronized (mLock) { 1126 final long timeRemoved = System.currentTimeMillis(); 1127 if (!mUserUnlockedStates.contains(userId)) { 1128 // If user is not unlocked and a package is removed for them, we will handle it 1129 // when the user service is initialized and package manager is queried. 1130 return; 1131 } 1132 final UserUsageStatsService userService = mUserState.get(userId); 1133 if (userService == null) { 1134 return; 1135 } 1136 1137 tokenRemoved = userService.onPackageRemoved(packageName, timeRemoved); 1138 } 1139 1140 // Schedule a job to prune any data related to this package. 1141 if (tokenRemoved != PackagesTokenData.UNASSIGNED_TOKEN) { 1142 UsageStatsIdleService.scheduleJob(getContext(), userId); 1143 } 1144 } 1145 1146 /** 1147 * Called by the Binder stub. 1148 */ pruneUninstalledPackagesData(int userId)1149 private boolean pruneUninstalledPackagesData(int userId) { 1150 synchronized (mLock) { 1151 if (!mUserUnlockedStates.contains(userId)) { 1152 return false; // user is no longer unlocked 1153 } 1154 1155 final UserUsageStatsService userService = mUserState.get(userId); 1156 if (userService == null) { 1157 return false; // user was stopped or removed 1158 } 1159 1160 return userService.pruneUninstalledPackagesData(); 1161 } 1162 } 1163 1164 /** 1165 * Called by the Binder stub. 1166 */ updatePackageMappingsData()1167 private boolean updatePackageMappingsData() { 1168 // fetch the installed packages outside the lock so it doesn't block package manager. 1169 final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM); 1170 synchronized (mLock) { 1171 if (!mUserUnlockedStates.contains(UserHandle.USER_SYSTEM)) { 1172 return false; // user is no longer unlocked 1173 } 1174 1175 final UserUsageStatsService userService = mUserState.get(UserHandle.USER_SYSTEM); 1176 if (userService == null) { 1177 return false; // user was stopped or removed 1178 } 1179 1180 return userService.updatePackageMappingsLocked(installedPkgs); 1181 } 1182 } 1183 1184 /** 1185 * Called by the Binder stub. 1186 */ queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)1187 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime, 1188 boolean obfuscateInstantApps) { 1189 synchronized (mLock) { 1190 if (!mUserUnlockedStates.contains(userId)) { 1191 Slog.w(TAG, "Failed to query usage stats for locked user " + userId); 1192 return null; 1193 } 1194 1195 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1196 if (service == null) { 1197 return null; // user was stopped or removed 1198 } 1199 List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime); 1200 if (list == null) { 1201 return null; 1202 } 1203 1204 // Mangle instant app names *using their current state (not whether they were ephemeral 1205 // when the data was recorded)*. 1206 if (obfuscateInstantApps) { 1207 for (int i = list.size() - 1; i >= 0; i--) { 1208 final UsageStats stats = list.get(i); 1209 if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) { 1210 list.set(i, stats.getObfuscatedForInstantApp()); 1211 } 1212 } 1213 } 1214 return list; 1215 } 1216 } 1217 1218 /** 1219 * Called by the Binder stub. 1220 */ queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)1221 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 1222 long endTime) { 1223 synchronized (mLock) { 1224 if (!mUserUnlockedStates.contains(userId)) { 1225 Slog.w(TAG, "Failed to query configuration stats for locked user " + userId); 1226 return null; 1227 } 1228 1229 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1230 if (service == null) { 1231 return null; // user was stopped or removed 1232 } 1233 return service.queryConfigurationStats(bucketType, beginTime, endTime); 1234 } 1235 } 1236 1237 /** 1238 * Called by the Binder stub. 1239 */ queryEventStats(int userId, int bucketType, long beginTime, long endTime)1240 List<EventStats> queryEventStats(int userId, int bucketType, long beginTime, 1241 long endTime) { 1242 synchronized (mLock) { 1243 if (!mUserUnlockedStates.contains(userId)) { 1244 Slog.w(TAG, "Failed to query event stats for locked user " + userId); 1245 return null; 1246 } 1247 1248 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1249 if (service == null) { 1250 return null; // user was stopped or removed 1251 } 1252 return service.queryEventStats(bucketType, beginTime, endTime); 1253 } 1254 } 1255 1256 /** 1257 * Called by the Binder stub. 1258 */ queryEvents(int userId, long beginTime, long endTime, int flags)1259 UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) { 1260 synchronized (mLock) { 1261 if (!mUserUnlockedStates.contains(userId)) { 1262 Slog.w(TAG, "Failed to query events for locked user " + userId); 1263 return null; 1264 } 1265 1266 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1267 if (service == null) { 1268 return null; // user was stopped or removed 1269 } 1270 return service.queryEvents(beginTime, endTime, flags); 1271 } 1272 } 1273 1274 /** 1275 * Called by the Binder stub. 1276 */ queryEventsForPackage(int userId, long beginTime, long endTime, String packageName, boolean includeTaskRoot)1277 UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime, 1278 String packageName, boolean includeTaskRoot) { 1279 synchronized (mLock) { 1280 if (!mUserUnlockedStates.contains(userId)) { 1281 Slog.w(TAG, "Failed to query package events for locked user " + userId); 1282 return null; 1283 } 1284 1285 final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId); 1286 if (service == null) { 1287 return null; // user was stopped or removed 1288 } 1289 return service.queryEventsForPackage(beginTime, endTime, packageName, includeTaskRoot); 1290 } 1291 } 1292 1293 /** 1294 * Called via the local interface. 1295 */ registerListener(@onNull UsageStatsManagerInternal.UsageEventListener listener)1296 private void registerListener(@NonNull UsageStatsManagerInternal.UsageEventListener listener) { 1297 synchronized (mLock) { 1298 mUsageEventListeners.add(listener); 1299 } 1300 } 1301 1302 /** 1303 * Called via the local interface. 1304 */ unregisterListener( @onNull UsageStatsManagerInternal.UsageEventListener listener)1305 private void unregisterListener( 1306 @NonNull UsageStatsManagerInternal.UsageEventListener listener) { 1307 synchronized (mLock) { 1308 mUsageEventListeners.remove(listener); 1309 } 1310 } 1311 buildFullToken(String packageName, String token)1312 private String buildFullToken(String packageName, String token) { 1313 final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1); 1314 sb.append(packageName); 1315 sb.append(TOKEN_DELIMITER); 1316 sb.append(token); 1317 return sb.toString(); 1318 } 1319 flushToDiskLocked()1320 private void flushToDiskLocked() { 1321 final int userCount = mUserState.size(); 1322 for (int i = 0; i < userCount; i++) { 1323 final int userId = mUserState.keyAt(i); 1324 if (!mUserUnlockedStates.contains(userId)) { 1325 persistPendingEventsLocked(userId); 1326 continue; 1327 } 1328 UserUsageStatsService service = mUserState.get(userId); 1329 if (service != null) { 1330 service.persistActiveStats(); 1331 } 1332 } 1333 mHandler.removeMessages(MSG_FLUSH_TO_DISK); 1334 } 1335 1336 /** 1337 * Called by the Binder stub. 1338 */ dump(String[] args, PrintWriter pw)1339 void dump(String[] args, PrintWriter pw) { 1340 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 1341 1342 boolean checkin = false; 1343 boolean compact = false; 1344 final ArrayList<String> pkgs = new ArrayList<>(); 1345 1346 if (args != null) { 1347 for (int i = 0; i < args.length; i++) { 1348 String arg = args[i]; 1349 if ("--checkin".equals(arg)) { 1350 checkin = true; 1351 } else if ("-c".equals(arg)) { 1352 compact = true; 1353 } else if ("flush".equals(arg)) { 1354 synchronized (mLock) { 1355 flushToDiskLocked(); 1356 } 1357 mAppStandby.flushToDisk(); 1358 pw.println("Flushed stats to disk"); 1359 return; 1360 } else if ("is-app-standby-enabled".equals(arg)) { 1361 pw.println(mAppStandby.isAppIdleEnabled()); 1362 return; 1363 } else if ("apptimelimit".equals(arg)) { 1364 synchronized (mLock) { 1365 if (i + 1 >= args.length) { 1366 mAppTimeLimit.dump(null, pw); 1367 } else { 1368 final String[] remainingArgs = 1369 Arrays.copyOfRange(args, i + 1, args.length); 1370 mAppTimeLimit.dump(remainingArgs, pw); 1371 } 1372 return; 1373 } 1374 } else if ("file".equals(arg)) { 1375 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1376 synchronized (mLock) { 1377 if (i + 1 >= args.length) { 1378 // dump everything for all users 1379 final int numUsers = mUserState.size(); 1380 for (int user = 0; user < numUsers; user++) { 1381 final int userId = mUserState.keyAt(user); 1382 if (!mUserUnlockedStates.contains(userId)) { 1383 continue; 1384 } 1385 ipw.println("user=" + userId); 1386 ipw.increaseIndent(); 1387 mUserState.valueAt(user).dumpFile(ipw, null); 1388 ipw.decreaseIndent(); 1389 } 1390 } else { 1391 final int user = parseUserIdFromArgs(args, i, ipw); 1392 if (user != UserHandle.USER_NULL) { 1393 final String[] remainingArgs = Arrays.copyOfRange( 1394 args, i + 2, args.length); 1395 // dump everything for the specified user 1396 mUserState.get(user).dumpFile(ipw, remainingArgs); 1397 } 1398 } 1399 return; 1400 } 1401 } else if ("database-info".equals(arg)) { 1402 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1403 synchronized (mLock) { 1404 if (i + 1 >= args.length) { 1405 // dump info for all users 1406 final int numUsers = mUserState.size(); 1407 for (int user = 0; user < numUsers; user++) { 1408 final int userId = mUserState.keyAt(user); 1409 if (!mUserUnlockedStates.contains(userId)) { 1410 continue; 1411 } 1412 ipw.println("user=" + userId); 1413 ipw.increaseIndent(); 1414 mUserState.valueAt(user).dumpDatabaseInfo(ipw); 1415 ipw.decreaseIndent(); 1416 } 1417 } else { 1418 final int user = parseUserIdFromArgs(args, i, ipw); 1419 if (user != UserHandle.USER_NULL) { 1420 // dump info only for the specified user 1421 mUserState.get(user).dumpDatabaseInfo(ipw); 1422 } 1423 } 1424 return; 1425 } 1426 } else if ("appstandby".equals(arg)) { 1427 mAppStandby.dumpState(args, pw); 1428 return; 1429 } else if ("stats-directory".equals(arg)) { 1430 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1431 synchronized (mLock) { 1432 final int userId = parseUserIdFromArgs(args, i, ipw); 1433 if (userId != UserHandle.USER_NULL) { 1434 ipw.println(new File(Environment.getDataSystemCeDirectory(userId), 1435 "usagestats").getAbsolutePath()); 1436 } 1437 return; 1438 } 1439 } else if ("mappings".equals(arg)) { 1440 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1441 final int userId = parseUserIdFromArgs(args, i, ipw); 1442 synchronized (mLock) { 1443 if (userId != UserHandle.USER_NULL) { 1444 mUserState.get(userId).dumpMappings(ipw); 1445 } 1446 return; 1447 } 1448 } else if (arg != null && !arg.startsWith("-")) { 1449 // Anything else that doesn't start with '-' is a pkg to filter 1450 pkgs.add(arg); 1451 } 1452 } 1453 } 1454 1455 final int[] userIds; 1456 synchronized (mLock) { 1457 final int userCount = mUserState.size(); 1458 userIds = new int[userCount]; 1459 for (int i = 0; i < userCount; i++) { 1460 final int userId = mUserState.keyAt(i); 1461 userIds[i] = userId; 1462 idpw.printPair("user", userId); 1463 idpw.println(); 1464 idpw.increaseIndent(); 1465 if (mUserUnlockedStates.contains(userId)) { 1466 if (checkin) { 1467 mUserState.valueAt(i).checkin(idpw); 1468 } else { 1469 mUserState.valueAt(i).dump(idpw, pkgs, compact); 1470 idpw.println(); 1471 } 1472 } 1473 idpw.decreaseIndent(); 1474 } 1475 1476 idpw.println(); 1477 idpw.printPair("Usage Source", UsageStatsManager.usageSourceToString(mUsageSource)); 1478 idpw.println(); 1479 1480 mAppTimeLimit.dump(null, pw); 1481 } 1482 1483 mAppStandby.dumpUsers(idpw, userIds, pkgs); 1484 1485 if (CollectionUtils.isEmpty(pkgs)) { 1486 pw.println(); 1487 mAppStandby.dumpState(args, pw); 1488 } 1489 } 1490 parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw)1491 private int parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw) { 1492 final int userId; 1493 try { 1494 userId = Integer.parseInt(args[index + 1]); 1495 } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { 1496 ipw.println("invalid user specified."); 1497 return UserHandle.USER_NULL; 1498 } 1499 if (mUserState.indexOfKey(userId) < 0) { 1500 ipw.println("the specified user does not exist."); 1501 return UserHandle.USER_NULL; 1502 } 1503 if (!mUserUnlockedStates.contains(userId)) { 1504 ipw.println("the specified user is currently in a locked state."); 1505 return UserHandle.USER_NULL; 1506 } 1507 return userId; 1508 } 1509 1510 class H extends Handler { H(Looper looper)1511 public H(Looper looper) { 1512 super(looper); 1513 } 1514 1515 @Override handleMessage(Message msg)1516 public void handleMessage(Message msg) { 1517 switch (msg.what) { 1518 case MSG_REPORT_EVENT: 1519 reportEvent((Event) msg.obj, msg.arg1); 1520 break; 1521 case MSG_REPORT_EVENT_TO_ALL_USERID: 1522 reportEventToAllUserId((Event) msg.obj); 1523 break; 1524 case MSG_FLUSH_TO_DISK: 1525 flushToDisk(); 1526 break; 1527 case MSG_UNLOCKED_USER: 1528 try { 1529 onUserUnlocked(msg.arg1); 1530 } catch (Exception e) { 1531 if (mUserManager.isUserUnlocked(msg.arg1)) { 1532 throw e; // rethrow exception - user is unlocked 1533 } else { 1534 Slog.w(TAG, "Attempted to unlock stopped or removed user " + msg.arg1); 1535 } 1536 } 1537 break; 1538 case MSG_REMOVE_USER: 1539 onUserRemoved(msg.arg1); 1540 break; 1541 case MSG_PACKAGE_REMOVED: 1542 onPackageRemoved(msg.arg1, (String) msg.obj); 1543 break; 1544 case MSG_UID_STATE_CHANGED: { 1545 final int uid = msg.arg1; 1546 final int procState = msg.arg2; 1547 1548 final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1; 1549 synchronized (mUidToKernelCounter) { 1550 final int oldCounter = mUidToKernelCounter.get(uid, 0); 1551 if (newCounter != oldCounter) { 1552 mUidToKernelCounter.put(uid, newCounter); 1553 try { 1554 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter); 1555 } catch (IOException e) { 1556 Slog.w(TAG, "Failed to update counter set: " + e); 1557 } 1558 } 1559 } 1560 break; 1561 } 1562 case MSG_ON_START: 1563 synchronized (mLock) { 1564 loadGlobalComponentUsageLocked(); 1565 } 1566 break; 1567 default: 1568 super.handleMessage(msg); 1569 break; 1570 } 1571 } 1572 } 1573 1574 private final class BinderService extends IUsageStatsManager.Stub { 1575 hasPermission(String callingPackage)1576 private boolean hasPermission(String callingPackage) { 1577 final int callingUid = Binder.getCallingUid(); 1578 if (callingUid == Process.SYSTEM_UID) { 1579 return true; 1580 } 1581 final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 1582 callingUid, callingPackage); 1583 if (mode == AppOpsManager.MODE_DEFAULT) { 1584 // The default behavior here is to check if PackageManager has given the app 1585 // permission. 1586 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 1587 == PackageManager.PERMISSION_GRANTED; 1588 } 1589 return mode == AppOpsManager.MODE_ALLOWED; 1590 } 1591 hasObserverPermission()1592 private boolean hasObserverPermission() { 1593 final int callingUid = Binder.getCallingUid(); 1594 DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 1595 //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. 1596 if (callingUid == Process.SYSTEM_UID 1597 || (dpmInternal != null 1598 && (dpmInternal.isActiveProfileOwner(callingUid) 1599 || dpmInternal.isActiveDeviceOwner(callingUid)))) { 1600 // Caller is the system or the profile owner, so proceed. 1601 return true; 1602 } 1603 return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE) 1604 == PackageManager.PERMISSION_GRANTED; 1605 } 1606 hasPermissions(String callingPackage, String... permissions)1607 private boolean hasPermissions(String callingPackage, String... permissions) { 1608 final int callingUid = Binder.getCallingUid(); 1609 if (callingUid == Process.SYSTEM_UID) { 1610 // Caller is the system, so proceed. 1611 return true; 1612 } 1613 1614 boolean hasPermissions = true; 1615 final Context context = getContext(); 1616 for (int i = 0; i < permissions.length; i++) { 1617 hasPermissions = hasPermissions && (context.checkCallingPermission(permissions[i]) 1618 == PackageManager.PERMISSION_GRANTED); 1619 } 1620 return hasPermissions; 1621 } 1622 checkCallerIsSystemOrSameApp(String pkg)1623 private void checkCallerIsSystemOrSameApp(String pkg) { 1624 if (isCallingUidSystem()) { 1625 return; 1626 } 1627 checkCallerIsSameApp(pkg); 1628 } 1629 checkCallerIsSameApp(String pkg)1630 private void checkCallerIsSameApp(String pkg) { 1631 final int callingUid = Binder.getCallingUid(); 1632 final int callingUserId = UserHandle.getUserId(callingUid); 1633 1634 if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0, 1635 callingUserId) != callingUid) { 1636 throw new SecurityException("Calling uid " + callingUid + " cannot query events" 1637 + "for package " + pkg); 1638 } 1639 } 1640 isCallingUidSystem()1641 private boolean isCallingUidSystem() { 1642 final int uid = UserHandle.getAppId(Binder.getCallingUid()); // ignores user 1643 return uid == Process.SYSTEM_UID; 1644 } 1645 1646 @Override queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage, int userId)1647 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 1648 long endTime, String callingPackage, int userId) { 1649 if (!hasPermission(callingPackage)) { 1650 return null; 1651 } 1652 1653 final int callingUid = Binder.getCallingUid(); 1654 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid, 1655 userId, false, true, "queryUsageStats", callingPackage); 1656 1657 // Check the caller's userId for obfuscation decision, not the user being queried 1658 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 1659 callingUid, UserHandle.getCallingUserId()); 1660 1661 final long token = Binder.clearCallingIdentity(); 1662 try { 1663 final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 1664 userId, bucketType, beginTime, endTime, obfuscateInstantApps); 1665 if (results != null) { 1666 return new ParceledListSlice<>(results); 1667 } 1668 } finally { 1669 Binder.restoreCallingIdentity(token); 1670 } 1671 return null; 1672 } 1673 1674 @Override queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)1675 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 1676 long beginTime, long endTime, String callingPackage) throws RemoteException { 1677 if (!hasPermission(callingPackage)) { 1678 return null; 1679 } 1680 1681 final int userId = UserHandle.getCallingUserId(); 1682 final long token = Binder.clearCallingIdentity(); 1683 try { 1684 final List<ConfigurationStats> results = 1685 UsageStatsService.this.queryConfigurationStats(userId, bucketType, 1686 beginTime, endTime); 1687 if (results != null) { 1688 return new ParceledListSlice<>(results); 1689 } 1690 } finally { 1691 Binder.restoreCallingIdentity(token); 1692 } 1693 return null; 1694 } 1695 1696 @Override queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)1697 public ParceledListSlice<EventStats> queryEventStats(int bucketType, 1698 long beginTime, long endTime, String callingPackage) throws RemoteException { 1699 if (!hasPermission(callingPackage)) { 1700 return null; 1701 } 1702 1703 final int userId = UserHandle.getCallingUserId(); 1704 final long token = Binder.clearCallingIdentity(); 1705 try { 1706 final List<EventStats> results = 1707 UsageStatsService.this.queryEventStats(userId, bucketType, 1708 beginTime, endTime); 1709 if (results != null) { 1710 return new ParceledListSlice<>(results); 1711 } 1712 } finally { 1713 Binder.restoreCallingIdentity(token); 1714 } 1715 return null; 1716 } 1717 1718 @Override queryEvents(long beginTime, long endTime, String callingPackage)1719 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 1720 if (!hasPermission(callingPackage)) { 1721 return null; 1722 } 1723 1724 final int userId = UserHandle.getCallingUserId(); 1725 final int callingUid = Binder.getCallingUid(); 1726 final int callingPid = Binder.getCallingPid(); 1727 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 1728 callingUid, userId); 1729 1730 final long token = Binder.clearCallingIdentity(); 1731 try { 1732 final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents( 1733 userId, callingPackage, callingPid, callingUid); 1734 final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid); 1735 final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents( 1736 callingPid, callingUid); 1737 int flags = UsageEvents.SHOW_ALL_EVENT_DATA; 1738 if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS; 1739 if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS; 1740 if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS; 1741 if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS; 1742 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags); 1743 } finally { 1744 Binder.restoreCallingIdentity(token); 1745 } 1746 } 1747 1748 @Override queryEventsForPackage(long beginTime, long endTime, String callingPackage)1749 public UsageEvents queryEventsForPackage(long beginTime, long endTime, 1750 String callingPackage) { 1751 final int callingUid = Binder.getCallingUid(); 1752 final int callingUserId = UserHandle.getUserId(callingUid); 1753 1754 checkCallerIsSameApp(callingPackage); 1755 final boolean includeTaskRoot = hasPermission(callingPackage); 1756 1757 final long token = Binder.clearCallingIdentity(); 1758 try { 1759 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime, 1760 endTime, callingPackage, includeTaskRoot); 1761 } finally { 1762 Binder.restoreCallingIdentity(token); 1763 } 1764 } 1765 1766 @Override queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)1767 public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, 1768 String callingPackage) { 1769 if (!hasPermission(callingPackage)) { 1770 return null; 1771 } 1772 1773 final int callingUserId = UserHandle.getCallingUserId(); 1774 if (userId != callingUserId) { 1775 getContext().enforceCallingPermission( 1776 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 1777 "No permission to query usage stats for this user"); 1778 } 1779 1780 final int callingUid = Binder.getCallingUid(); 1781 final int callingPid = Binder.getCallingPid(); 1782 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 1783 callingUid, callingUserId); 1784 1785 final long token = Binder.clearCallingIdentity(); 1786 try { 1787 final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents( 1788 userId, callingPackage, callingPid, callingUid); 1789 final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents( 1790 callingPid, callingUid); 1791 boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid); 1792 int flags = UsageEvents.SHOW_ALL_EVENT_DATA; 1793 if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS; 1794 if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS; 1795 if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS; 1796 if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS; 1797 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags); 1798 } finally { 1799 Binder.restoreCallingIdentity(token); 1800 } 1801 } 1802 1803 @Override queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)1804 public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, 1805 int userId, String pkg, String callingPackage) { 1806 if (!hasPermission(callingPackage)) { 1807 return null; 1808 } 1809 if (userId != UserHandle.getCallingUserId()) { 1810 getContext().enforceCallingPermission( 1811 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 1812 "No permission to query usage stats for this user"); 1813 } 1814 checkCallerIsSystemOrSameApp(pkg); 1815 1816 final long token = Binder.clearCallingIdentity(); 1817 try { 1818 return UsageStatsService.this.queryEventsForPackage(userId, beginTime, 1819 endTime, pkg, true); 1820 } finally { 1821 Binder.restoreCallingIdentity(token); 1822 } 1823 } 1824 1825 @Override isAppInactive(String packageName, int userId, String callingPackage)1826 public boolean isAppInactive(String packageName, int userId, String callingPackage) { 1827 final int callingUid = Binder.getCallingUid(); 1828 try { 1829 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(), 1830 callingUid, userId, false, false, "isAppInactive", null); 1831 } catch (RemoteException re) { 1832 throw re.rethrowFromSystemServer(); 1833 } 1834 1835 // If the calling app is asking about itself, continue, else check for permission. 1836 if (packageName.equals(callingPackage)) { 1837 final int actualCallingUid = mPackageManagerInternal.getPackageUid( 1838 callingPackage, /* flags= */ 0, userId); 1839 if (actualCallingUid != callingUid) { 1840 return false; 1841 } 1842 } else if (!hasPermission(callingPackage)) { 1843 return false; 1844 } 1845 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 1846 callingUid, userId); 1847 final long token = Binder.clearCallingIdentity(); 1848 try { 1849 return mAppStandby.isAppIdleFiltered( 1850 packageName, userId, 1851 SystemClock.elapsedRealtime(), obfuscateInstantApps); 1852 } finally { 1853 Binder.restoreCallingIdentity(token); 1854 } 1855 } 1856 1857 @Override setAppInactive(String packageName, boolean idle, int userId)1858 public void setAppInactive(String packageName, boolean idle, int userId) { 1859 final int callingUid = Binder.getCallingUid(); 1860 try { 1861 userId = ActivityManager.getService().handleIncomingUser( 1862 Binder.getCallingPid(), callingUid, userId, false, true, 1863 "setAppInactive", null); 1864 } catch (RemoteException re) { 1865 throw re.rethrowFromSystemServer(); 1866 } 1867 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1868 "No permission to change app idle state"); 1869 final long token = Binder.clearCallingIdentity(); 1870 try { 1871 final int appId = mAppStandby.getAppId(packageName); 1872 if (appId < 0) return; 1873 mAppStandby.setAppIdleAsync(packageName, idle, userId); 1874 } finally { 1875 Binder.restoreCallingIdentity(token); 1876 } 1877 } 1878 1879 @Override getAppStandbyBucket(String packageName, String callingPackage, int userId)1880 public int getAppStandbyBucket(String packageName, String callingPackage, int userId) { 1881 final int callingUid = Binder.getCallingUid(); 1882 try { 1883 userId = ActivityManager.getService().handleIncomingUser( 1884 Binder.getCallingPid(), callingUid, userId, false, false, 1885 "getAppStandbyBucket", null); 1886 } catch (RemoteException re) { 1887 throw re.rethrowFromSystemServer(); 1888 } 1889 final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId); 1890 // If the calling app is asking about itself, continue, else check for permission. 1891 if (packageUid != callingUid) { 1892 if (!hasPermission(callingPackage)) { 1893 throw new SecurityException( 1894 "Don't have permission to query app standby bucket"); 1895 } 1896 } 1897 if (packageUid < 0) { 1898 throw new IllegalArgumentException( 1899 "Cannot get standby bucket for non existent package (" + packageName + ")"); 1900 } 1901 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid, 1902 userId); 1903 final long token = Binder.clearCallingIdentity(); 1904 try { 1905 return mAppStandby.getAppStandbyBucket(packageName, userId, 1906 SystemClock.elapsedRealtime(), obfuscateInstantApps); 1907 } finally { 1908 Binder.restoreCallingIdentity(token); 1909 } 1910 } 1911 1912 @Override setAppStandbyBucket(String packageName, int bucket, int userId)1913 public void setAppStandbyBucket(String packageName, int bucket, int userId) { 1914 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1915 "No permission to change app standby state"); 1916 1917 final int callingUid = Binder.getCallingUid(); 1918 final int callingPid = Binder.getCallingPid(); 1919 final long token = Binder.clearCallingIdentity(); 1920 try { 1921 mAppStandby.setAppStandbyBucket(packageName, bucket, userId, 1922 callingUid, callingPid); 1923 } finally { 1924 Binder.restoreCallingIdentity(token); 1925 } 1926 } 1927 1928 @Override getAppStandbyBuckets(String callingPackageName, int userId)1929 public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName, 1930 int userId) { 1931 final int callingUid = Binder.getCallingUid(); 1932 try { 1933 userId = ActivityManager.getService().handleIncomingUser( 1934 Binder.getCallingPid(), callingUid, userId, false, false, 1935 "getAppStandbyBucket", null); 1936 } catch (RemoteException re) { 1937 throw re.rethrowFromSystemServer(); 1938 } 1939 if (!hasPermission(callingPackageName)) { 1940 throw new SecurityException( 1941 "Don't have permission to query app standby bucket"); 1942 } 1943 final long token = Binder.clearCallingIdentity(); 1944 try { 1945 final List<AppStandbyInfo> standbyBucketList = 1946 mAppStandby.getAppStandbyBuckets(userId); 1947 return (standbyBucketList == null) ? ParceledListSlice.emptyList() 1948 : new ParceledListSlice<>(standbyBucketList); 1949 } finally { 1950 Binder.restoreCallingIdentity(token); 1951 } 1952 } 1953 1954 @Override setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)1955 public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) { 1956 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1957 "No permission to change app standby state"); 1958 1959 final int callingUid = Binder.getCallingUid(); 1960 final int callingPid = Binder.getCallingPid(); 1961 final long token = Binder.clearCallingIdentity(); 1962 try { 1963 mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId, 1964 callingUid, callingPid); 1965 } finally { 1966 Binder.restoreCallingIdentity(token); 1967 } 1968 } 1969 1970 @Override onCarrierPrivilegedAppsChanged()1971 public void onCarrierPrivilegedAppsChanged() { 1972 if (DEBUG) { 1973 Slog.i(TAG, "Carrier privileged apps changed"); 1974 } 1975 getContext().enforceCallingOrSelfPermission( 1976 android.Manifest.permission.BIND_CARRIER_SERVICES, 1977 "onCarrierPrivilegedAppsChanged can only be called by privileged apps."); 1978 mAppStandby.clearCarrierPrivilegedApps(); 1979 } 1980 1981 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1982 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1983 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return; 1984 UsageStatsService.this.dump(args, pw); 1985 } 1986 1987 @Override reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1988 public void reportChooserSelection(String packageName, int userId, String contentType, 1989 String[] annotations, String action) { 1990 if (packageName == null) { 1991 Slog.w(TAG, "Event report user selecting a null package"); 1992 return; 1993 } 1994 1995 Event event = new Event(CHOOSER_ACTION, SystemClock.elapsedRealtime()); 1996 event.mPackage = packageName; 1997 event.mAction = action; 1998 event.mContentType = contentType; 1999 event.mContentAnnotations = annotations; 2000 reportEventOrAddToQueue(userId, event); 2001 } 2002 2003 @Override reportUserInteraction(String packageName, int userId)2004 public void reportUserInteraction(String packageName, int userId) { 2005 Objects.requireNonNull(packageName); 2006 if (!isCallingUidSystem()) { 2007 throw new SecurityException("Only system is allowed to call reportUserInteraction"); 2008 } 2009 final Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime()); 2010 event.mPackage = packageName; 2011 reportEventOrAddToQueue(userId, event); 2012 } 2013 2014 @Override registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)2015 public void registerAppUsageObserver(int observerId, 2016 String[] packages, long timeLimitMs, PendingIntent 2017 callbackIntent, String callingPackage) { 2018 if (!hasObserverPermission()) { 2019 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2020 } 2021 2022 if (packages == null || packages.length == 0) { 2023 throw new IllegalArgumentException("Must specify at least one package"); 2024 } 2025 if (callbackIntent == null) { 2026 throw new NullPointerException("callbackIntent can't be null"); 2027 } 2028 final int callingUid = Binder.getCallingUid(); 2029 final int userId = UserHandle.getUserId(callingUid); 2030 final long token = Binder.clearCallingIdentity(); 2031 try { 2032 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId, 2033 packages, timeLimitMs, callbackIntent, userId); 2034 } finally { 2035 Binder.restoreCallingIdentity(token); 2036 } 2037 } 2038 2039 @Override unregisterAppUsageObserver(int observerId, String callingPackage)2040 public void unregisterAppUsageObserver(int observerId, String callingPackage) { 2041 if (!hasObserverPermission()) { 2042 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2043 } 2044 2045 final int callingUid = Binder.getCallingUid(); 2046 final int userId = UserHandle.getUserId(callingUid); 2047 final long token = Binder.clearCallingIdentity(); 2048 try { 2049 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId); 2050 } finally { 2051 Binder.restoreCallingIdentity(token); 2052 } 2053 } 2054 2055 @Override registerUsageSessionObserver(int sessionObserverId, String[] observed, long timeLimitMs, long sessionThresholdTimeMs, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, String callingPackage)2056 public void registerUsageSessionObserver(int sessionObserverId, String[] observed, 2057 long timeLimitMs, long sessionThresholdTimeMs, 2058 PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, 2059 String callingPackage) { 2060 if (!hasObserverPermission()) { 2061 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2062 } 2063 2064 if (observed == null || observed.length == 0) { 2065 throw new IllegalArgumentException("Must specify at least one observed entity"); 2066 } 2067 if (limitReachedCallbackIntent == null) { 2068 throw new NullPointerException("limitReachedCallbackIntent can't be null"); 2069 } 2070 final int callingUid = Binder.getCallingUid(); 2071 final int userId = UserHandle.getUserId(callingUid); 2072 final long token = Binder.clearCallingIdentity(); 2073 try { 2074 UsageStatsService.this.registerUsageSessionObserver(callingUid, sessionObserverId, 2075 observed, timeLimitMs, sessionThresholdTimeMs, limitReachedCallbackIntent, 2076 sessionEndCallbackIntent, userId); 2077 } finally { 2078 Binder.restoreCallingIdentity(token); 2079 } 2080 } 2081 2082 @Override unregisterUsageSessionObserver(int sessionObserverId, String callingPackage)2083 public void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage) { 2084 if (!hasObserverPermission()) { 2085 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2086 } 2087 2088 final int callingUid = Binder.getCallingUid(); 2089 final int userId = UserHandle.getUserId(callingUid); 2090 final long token = Binder.clearCallingIdentity(); 2091 try { 2092 UsageStatsService.this.unregisterUsageSessionObserver(callingUid, sessionObserverId, 2093 userId); 2094 } finally { 2095 Binder.restoreCallingIdentity(token); 2096 } 2097 } 2098 2099 @Override registerAppUsageLimitObserver(int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, String callingPackage)2100 public void registerAppUsageLimitObserver(int observerId, String[] packages, 2101 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, 2102 String callingPackage) { 2103 final int callingUid = Binder.getCallingUid(); 2104 final DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 2105 if (!hasPermissions(callingPackage, 2106 Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE) 2107 && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) { 2108 throw new SecurityException("Caller must be the active supervision app or " 2109 + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions"); 2110 } 2111 2112 if (packages == null || packages.length == 0) { 2113 throw new IllegalArgumentException("Must specify at least one package"); 2114 } 2115 if (callbackIntent == null && timeUsedMs < timeLimitMs) { 2116 throw new NullPointerException("callbackIntent can't be null"); 2117 } 2118 final int userId = UserHandle.getUserId(callingUid); 2119 final long token = Binder.clearCallingIdentity(); 2120 try { 2121 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId, 2122 packages, timeLimitMs, timeUsedMs, callbackIntent, userId); 2123 } finally { 2124 Binder.restoreCallingIdentity(token); 2125 } 2126 } 2127 2128 @Override unregisterAppUsageLimitObserver(int observerId, String callingPackage)2129 public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) { 2130 final int callingUid = Binder.getCallingUid(); 2131 final DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 2132 if (!hasPermissions(callingPackage, 2133 Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE) 2134 && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) { 2135 throw new SecurityException("Caller must be the active supervision app or " 2136 + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions"); 2137 } 2138 2139 final int userId = UserHandle.getUserId(callingUid); 2140 final long token = Binder.clearCallingIdentity(); 2141 try { 2142 UsageStatsService.this.unregisterAppUsageLimitObserver( 2143 callingUid, observerId, userId); 2144 } finally { 2145 Binder.restoreCallingIdentity(token); 2146 } 2147 } 2148 2149 @Override reportUsageStart(IBinder activity, String token, String callingPackage)2150 public void reportUsageStart(IBinder activity, String token, String callingPackage) { 2151 reportPastUsageStart(activity, token, 0, callingPackage); 2152 } 2153 2154 @Override reportPastUsageStart(IBinder activity, String token, long timeAgoMs, String callingPackage)2155 public void reportPastUsageStart(IBinder activity, String token, long timeAgoMs, 2156 String callingPackage) { 2157 2158 final int callingUid = Binder.getCallingUid(); 2159 final int userId = UserHandle.getUserId(callingUid); 2160 final long binderToken = Binder.clearCallingIdentity(); 2161 try { 2162 ArraySet<String> tokens; 2163 synchronized (mUsageReporters) { 2164 tokens = mUsageReporters.get(activity.hashCode()); 2165 if (tokens == null) { 2166 tokens = new ArraySet(); 2167 mUsageReporters.put(activity.hashCode(), tokens); 2168 } 2169 } 2170 2171 synchronized (tokens) { 2172 if (!tokens.add(token)) { 2173 throw new IllegalArgumentException(token + " for " + callingPackage 2174 + " is already reported as started for this activity"); 2175 } 2176 } 2177 2178 mAppTimeLimit.noteUsageStart(buildFullToken(callingPackage, token), 2179 userId, timeAgoMs); 2180 } finally { 2181 Binder.restoreCallingIdentity(binderToken); 2182 } 2183 } 2184 2185 @Override reportUsageStop(IBinder activity, String token, String callingPackage)2186 public void reportUsageStop(IBinder activity, String token, String callingPackage) { 2187 final int callingUid = Binder.getCallingUid(); 2188 final int userId = UserHandle.getUserId(callingUid); 2189 final long binderToken = Binder.clearCallingIdentity(); 2190 try { 2191 ArraySet<String> tokens; 2192 synchronized (mUsageReporters) { 2193 tokens = mUsageReporters.get(activity.hashCode()); 2194 if (tokens == null) { 2195 throw new IllegalArgumentException( 2196 "Unknown reporter trying to stop token " + token + " for " 2197 + callingPackage); 2198 } 2199 } 2200 2201 synchronized (tokens) { 2202 if (!tokens.remove(token)) { 2203 throw new IllegalArgumentException(token + " for " + callingPackage 2204 + " is already reported as stopped for this activity"); 2205 } 2206 } 2207 mAppTimeLimit.noteUsageStop(buildFullToken(callingPackage, token), userId); 2208 } finally { 2209 Binder.restoreCallingIdentity(binderToken); 2210 } 2211 } 2212 2213 @Override getUsageSource()2214 public @UsageSource int getUsageSource() { 2215 if (!hasObserverPermission()) { 2216 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 2217 } 2218 synchronized (mLock) { 2219 return mUsageSource; 2220 } 2221 } 2222 2223 @Override forceUsageSourceSettingRead()2224 public void forceUsageSourceSettingRead() { 2225 readUsageSourceSetting(); 2226 } 2227 2228 @Override getLastTimeAnyComponentUsed(String packageName, String callingPackage)2229 public long getLastTimeAnyComponentUsed(String packageName, String callingPackage) { 2230 if (!hasPermissions( 2231 callingPackage, android.Manifest.permission.INTERACT_ACROSS_USERS)) { 2232 throw new SecurityException("Caller doesn't have INTERACT_ACROSS_USERS permission"); 2233 } 2234 if (!hasPermission(callingPackage)) { 2235 throw new SecurityException("Don't have permission to query usage stats"); 2236 } 2237 synchronized (mLock) { 2238 // Truncate the returned milliseconds to the boundary of the last day before exact 2239 // time for privacy reasons. 2240 return mLastTimeComponentUsedGlobal.getOrDefault(packageName, 0L) 2241 / TimeUnit.DAYS.toMillis(1) * TimeUnit.DAYS.toMillis(1); 2242 } 2243 } 2244 } 2245 registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)2246 void registerAppUsageObserver(int callingUid, int observerId, String[] packages, 2247 long timeLimitMs, PendingIntent callbackIntent, int userId) { 2248 mAppTimeLimit.addAppUsageObserver(callingUid, observerId, packages, timeLimitMs, 2249 callbackIntent, 2250 userId); 2251 } 2252 unregisterAppUsageObserver(int callingUid, int observerId, int userId)2253 void unregisterAppUsageObserver(int callingUid, int observerId, int userId) { 2254 mAppTimeLimit.removeAppUsageObserver(callingUid, observerId, userId); 2255 } 2256 registerUsageSessionObserver(int callingUid, int observerId, String[] observed, long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, int userId)2257 void registerUsageSessionObserver(int callingUid, int observerId, String[] observed, 2258 long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, 2259 PendingIntent sessionEndCallbackIntent, int userId) { 2260 mAppTimeLimit.addUsageSessionObserver(callingUid, observerId, observed, timeLimitMs, 2261 sessionThresholdTime, limitReachedCallbackIntent, sessionEndCallbackIntent, userId); 2262 } 2263 unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId)2264 void unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId) { 2265 mAppTimeLimit.removeUsageSessionObserver(callingUid, sessionObserverId, userId); 2266 } 2267 registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId)2268 void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, 2269 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId) { 2270 mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages, 2271 timeLimitMs, timeUsedMs, callbackIntent, userId); 2272 } 2273 unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId)2274 void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) { 2275 mAppTimeLimit.removeAppUsageLimitObserver(callingUid, observerId, userId); 2276 } 2277 2278 /** 2279 * This local service implementation is primarily used by ActivityManagerService. 2280 * ActivityManagerService will call these methods holding the 'am' lock, which means we 2281 * shouldn't be doing any IO work or other long running tasks in these methods. 2282 */ 2283 private final class LocalService extends UsageStatsManagerInternal { 2284 2285 @Override reportEvent(ComponentName component, int userId, int eventType, int instanceId, ComponentName taskRoot)2286 public void reportEvent(ComponentName component, int userId, int eventType, 2287 int instanceId, ComponentName taskRoot) { 2288 if (component == null) { 2289 Slog.w(TAG, "Event reported without a component name"); 2290 return; 2291 } 2292 2293 Event event = new Event(eventType, SystemClock.elapsedRealtime()); 2294 event.mPackage = component.getPackageName(); 2295 event.mClass = component.getClassName(); 2296 event.mInstanceId = instanceId; 2297 if (taskRoot == null) { 2298 event.mTaskRootPackage = null; 2299 event.mTaskRootClass = null; 2300 } else { 2301 event.mTaskRootPackage = taskRoot.getPackageName(); 2302 event.mTaskRootClass = taskRoot.getClassName(); 2303 } 2304 reportEventOrAddToQueue(userId, event); 2305 } 2306 2307 @Override reportEvent(String packageName, int userId, int eventType)2308 public void reportEvent(String packageName, int userId, int eventType) { 2309 if (packageName == null) { 2310 Slog.w(TAG, "Event reported without a package name, eventType:" + eventType); 2311 return; 2312 } 2313 2314 Event event = new Event(eventType, SystemClock.elapsedRealtime()); 2315 event.mPackage = packageName; 2316 reportEventOrAddToQueue(userId, event); 2317 } 2318 2319 @Override reportConfigurationChange(Configuration config, int userId)2320 public void reportConfigurationChange(Configuration config, int userId) { 2321 if (config == null) { 2322 Slog.w(TAG, "Configuration event reported with a null config"); 2323 return; 2324 } 2325 2326 Event event = new Event(CONFIGURATION_CHANGE, SystemClock.elapsedRealtime()); 2327 event.mPackage = "android"; 2328 event.mConfiguration = new Configuration(config); 2329 reportEventOrAddToQueue(userId, event); 2330 } 2331 2332 @Override reportInterruptiveNotification(String packageName, String channelId, int userId)2333 public void reportInterruptiveNotification(String packageName, String channelId, 2334 int userId) { 2335 if (packageName == null || channelId == null) { 2336 Slog.w(TAG, "Event reported without a package name or a channel ID"); 2337 return; 2338 } 2339 2340 Event event = new Event(NOTIFICATION_INTERRUPTION, SystemClock.elapsedRealtime()); 2341 event.mPackage = packageName.intern(); 2342 event.mNotificationChannelId = channelId.intern(); 2343 reportEventOrAddToQueue(userId, event); 2344 } 2345 2346 @Override reportShortcutUsage(String packageName, String shortcutId, int userId)2347 public void reportShortcutUsage(String packageName, String shortcutId, int userId) { 2348 if (packageName == null || shortcutId == null) { 2349 Slog.w(TAG, "Event reported without a package name or a shortcut ID"); 2350 return; 2351 } 2352 2353 Event event = new Event(SHORTCUT_INVOCATION, SystemClock.elapsedRealtime()); 2354 event.mPackage = packageName.intern(); 2355 event.mShortcutId = shortcutId.intern(); 2356 reportEventOrAddToQueue(userId, event); 2357 } 2358 2359 @Override reportLocusUpdate(@onNull ComponentName activity, @UserIdInt int userId, @Nullable LocusId locusId, @NonNull IBinder appToken)2360 public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId, 2361 @Nullable LocusId locusId, @NonNull IBinder appToken) { 2362 if (locusId == null) return; 2363 Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime()); 2364 event.mLocusId = locusId.getId(); 2365 event.mPackage = activity.getPackageName(); 2366 event.mClass = activity.getClassName(); 2367 event.mInstanceId = appToken.hashCode(); 2368 reportEventOrAddToQueue(userId, event); 2369 } 2370 2371 @Override reportContentProviderUsage(String name, String packageName, int userId)2372 public void reportContentProviderUsage(String name, String packageName, int userId) { 2373 mAppStandby.postReportContentProviderUsage(name, packageName, userId); 2374 } 2375 2376 @Override isAppIdle(String packageName, int uidForAppId, int userId)2377 public boolean isAppIdle(String packageName, int uidForAppId, int userId) { 2378 return mAppStandby.isAppIdleFiltered(packageName, uidForAppId, 2379 userId, SystemClock.elapsedRealtime()); 2380 } 2381 2382 @Override getAppStandbyBucket(String packageName, int userId, long nowElapsed)2383 @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId, 2384 long nowElapsed) { 2385 return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false); 2386 } 2387 2388 @Override getIdleUidsForUser(int userId)2389 public int[] getIdleUidsForUser(int userId) { 2390 return mAppStandby.getIdleUidsForUser(userId); 2391 } 2392 2393 @Override prepareShutdown()2394 public void prepareShutdown() { 2395 // This method *WILL* do IO work, but we must block until it is finished or else 2396 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 2397 // we are shutting down. 2398 UsageStatsService.this.shutdown(); 2399 } 2400 2401 @Override prepareForPossibleShutdown()2402 public void prepareForPossibleShutdown() { 2403 UsageStatsService.this.prepareForPossibleShutdown(); 2404 } 2405 2406 @Override getBackupPayload(int user, String key)2407 public byte[] getBackupPayload(int user, String key) { 2408 if (!mUserUnlockedStates.contains(user)) { 2409 Slog.w(TAG, "Failed to get backup payload for locked user " + user); 2410 return null; 2411 } 2412 synchronized (mLock) { 2413 // Check to ensure that only user 0's data is b/r for now 2414 // Note: if backup and restore is enabled for users other than the system user, the 2415 // #onUserUnlocked logic, specifically when the update mappings job is scheduled via 2416 // UsageStatsIdleService.scheduleUpdateMappingsJob, will have to be updated. 2417 if (user == UserHandle.USER_SYSTEM) { 2418 final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(user); 2419 if (userStats == null) { 2420 return null; // user was stopped or removed 2421 } 2422 return userStats.getBackupPayload(key); 2423 } else { 2424 return null; 2425 } 2426 } 2427 } 2428 2429 @Override applyRestoredPayload(int user, String key, byte[] payload)2430 public void applyRestoredPayload(int user, String key, byte[] payload) { 2431 synchronized (mLock) { 2432 if (!mUserUnlockedStates.contains(user)) { 2433 Slog.w(TAG, "Failed to apply restored payload for locked user " + user); 2434 return; 2435 } 2436 2437 if (user == UserHandle.USER_SYSTEM) { 2438 final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(user); 2439 if (userStats == null) { 2440 return; // user was stopped or removed 2441 } 2442 userStats.applyRestoredPayload(key, payload); 2443 } 2444 } 2445 } 2446 2447 @Override queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)2448 public List<UsageStats> queryUsageStatsForUser( 2449 int userId, int intervalType, long beginTime, long endTime, 2450 boolean obfuscateInstantApps) { 2451 return UsageStatsService.this.queryUsageStats( 2452 userId, intervalType, beginTime, endTime, obfuscateInstantApps); 2453 } 2454 2455 @Override queryEventsForUser(int userId, long beginTime, long endTime, int flags)2456 public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime, int flags) { 2457 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags); 2458 } 2459 2460 @Override setLastJobRunTime(String packageName, int userId, long elapsedRealtime)2461 public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) { 2462 mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime); 2463 } 2464 2465 @Override getTimeSinceLastJobRun(String packageName, int userId)2466 public long getTimeSinceLastJobRun(String packageName, int userId) { 2467 return mAppStandby.getTimeSinceLastJobRun(packageName, userId); 2468 } 2469 2470 @Override reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)2471 public void reportAppJobState(String packageName, int userId, 2472 int numDeferredJobs, long timeSinceLastJobRun) { 2473 } 2474 2475 @Override onActiveAdminAdded(String packageName, int userId)2476 public void onActiveAdminAdded(String packageName, int userId) { 2477 mAppStandby.addActiveDeviceAdmin(packageName, userId); 2478 } 2479 2480 @Override setActiveAdminApps(Set<String> packageNames, int userId)2481 public void setActiveAdminApps(Set<String> packageNames, int userId) { 2482 mAppStandby.setActiveAdminApps(packageNames, userId); 2483 } 2484 2485 @Override onAdminDataAvailable()2486 public void onAdminDataAvailable() { 2487 mAppStandby.onAdminDataAvailable(); 2488 } 2489 2490 @Override reportSyncScheduled(String packageName, int userId, boolean exempted)2491 public void reportSyncScheduled(String packageName, int userId, boolean exempted) { 2492 mAppStandby.postReportSyncScheduled(packageName, userId, exempted); 2493 } 2494 2495 @Override reportExemptedSyncStart(String packageName, int userId)2496 public void reportExemptedSyncStart(String packageName, int userId) { 2497 mAppStandby.postReportExemptedSyncStart(packageName, userId); 2498 } 2499 2500 @Override getAppUsageLimit(String packageName, UserHandle user)2501 public AppUsageLimitData getAppUsageLimit(String packageName, UserHandle user) { 2502 return mAppTimeLimit.getAppUsageLimit(packageName, user); 2503 } 2504 2505 @Override pruneUninstalledPackagesData(int userId)2506 public boolean pruneUninstalledPackagesData(int userId) { 2507 return UsageStatsService.this.pruneUninstalledPackagesData(userId); 2508 } 2509 2510 @Override updatePackageMappingsData()2511 public boolean updatePackageMappingsData() { 2512 return UsageStatsService.this.updatePackageMappingsData(); 2513 } 2514 2515 /** 2516 * Register a listener that will be notified of every new usage event. 2517 */ 2518 @Override registerListener(@onNull UsageEventListener listener)2519 public void registerListener(@NonNull UsageEventListener listener) { 2520 UsageStatsService.this.registerListener(listener); 2521 } 2522 2523 /** 2524 * Unregister a listener from being notified of every new usage event. 2525 */ 2526 @Override unregisterListener(@onNull UsageEventListener listener)2527 public void unregisterListener(@NonNull UsageEventListener listener) { 2528 UsageStatsService.this.unregisterListener(listener); 2529 } 2530 } 2531 2532 private class MyPackageMonitor extends PackageMonitor { 2533 @Override onPackageRemoved(String packageName, int uid)2534 public void onPackageRemoved(String packageName, int uid) { 2535 mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 0, packageName) 2536 .sendToTarget(); 2537 super.onPackageRemoved(packageName, uid); 2538 } 2539 } 2540 } 2541