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