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