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