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 android.Manifest; 20 import android.app.ActivityManager; 21 import android.app.AppOpsManager; 22 import android.app.IUidObserver; 23 import android.app.PendingIntent; 24 import android.app.admin.DeviceAdminInfo; 25 import android.app.admin.DevicePolicyManagerInternal; 26 import android.app.usage.AppStandbyInfo; 27 import android.app.usage.ConfigurationStats; 28 import android.app.usage.EventStats; 29 import android.app.usage.IUsageStatsManager; 30 import android.app.usage.UsageEvents; 31 import android.app.usage.UsageStatsManager; 32 import android.app.usage.UsageStatsManager.StandbyBuckets; 33 import android.app.usage.UsageEvents.Event; 34 import android.app.usage.UsageStats; 35 import android.app.usage.UsageStatsManagerInternal; 36 import android.content.BroadcastReceiver; 37 import android.content.ComponentName; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.IntentFilter; 41 import android.content.pm.PackageManager; 42 import android.content.pm.PackageManagerInternal; 43 import android.content.pm.ParceledListSlice; 44 import android.content.pm.UserInfo; 45 import android.content.res.Configuration; 46 import android.os.Binder; 47 import android.os.Environment; 48 import android.os.FileUtils; 49 import android.os.Handler; 50 import android.os.IDeviceIdleController; 51 import android.os.Looper; 52 import android.os.Message; 53 import android.os.Process; 54 import android.os.RemoteException; 55 import android.os.ServiceManager; 56 import android.os.SystemClock; 57 import android.os.SystemProperties; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.util.ArraySet; 61 import android.util.Slog; 62 import android.util.SparseArray; 63 import android.util.SparseIntArray; 64 65 import com.android.internal.content.PackageMonitor; 66 import com.android.internal.os.BackgroundThread; 67 import com.android.internal.util.DumpUtils; 68 import com.android.internal.util.IndentingPrintWriter; 69 import com.android.server.LocalServices; 70 import com.android.server.SystemService; 71 72 import java.io.File; 73 import java.io.FileDescriptor; 74 import java.io.IOException; 75 import java.io.PrintWriter; 76 import java.util.Arrays; 77 import java.util.List; 78 import java.util.Map; 79 import java.util.Set; 80 import java.util.concurrent.TimeUnit; 81 82 /** 83 * A service that collects, aggregates, and persists application usage data. 84 * This data can be queried by apps that have been granted permission by AppOps. 85 */ 86 public class UsageStatsService extends SystemService implements 87 UserUsageStatsService.StatsUpdatedListener { 88 89 static final String TAG = "UsageStatsService"; 90 public static final boolean ENABLE_TIME_CHANGE_CORRECTION 91 = SystemProperties.getBoolean("persist.debug.time_correction", true); 92 93 static final boolean DEBUG = false; // Never submit with true 94 static final boolean COMPRESS_TIME = false; 95 96 private static final long TEN_SECONDS = 10 * 1000; 97 private static final long TWENTY_MINUTES = 20 * 60 * 1000; 98 private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; 99 private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. 100 101 private static final boolean ENABLE_KERNEL_UPDATES = true; 102 private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); 103 104 // Handler message types. 105 static final int MSG_REPORT_EVENT = 0; 106 static final int MSG_FLUSH_TO_DISK = 1; 107 static final int MSG_REMOVE_USER = 2; 108 static final int MSG_UID_STATE_CHANGED = 3; 109 110 private final Object mLock = new Object(); 111 Handler mHandler; 112 AppOpsManager mAppOps; 113 UserManager mUserManager; 114 PackageManager mPackageManager; 115 PackageManagerInternal mPackageManagerInternal; 116 PackageMonitor mPackageMonitor; 117 IDeviceIdleController mDeviceIdleController; 118 // Do not use directly. Call getDpmInternal() instead 119 DevicePolicyManagerInternal mDpmInternal; 120 121 private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); 122 private final SparseIntArray mUidToKernelCounter = new SparseIntArray(); 123 private File mUsageStatsDir; 124 long mRealTimeSnapshot; 125 long mSystemTimeSnapshot; 126 127 /** Manages the standby state of apps. */ 128 AppStandbyController mAppStandby; 129 130 /** Manages app time limit observers */ 131 AppTimeLimitController mAppTimeLimit; 132 133 private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener = 134 new UsageStatsManagerInternal.AppIdleStateChangeListener() { 135 @Override 136 public void onAppIdleStateChanged(String packageName, int userId, boolean idle, 137 int bucket, int reason) { 138 Event event = new Event(); 139 event.mEventType = Event.STANDBY_BUCKET_CHANGED; 140 event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF); 141 event.mPackage = packageName; 142 // This will later be converted to system time. 143 event.mTimeStamp = SystemClock.elapsedRealtime(); 144 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 145 } 146 147 @Override 148 public void onParoleStateChanged(boolean isParoleOn) { 149 150 } 151 }; 152 UsageStatsService(Context context)153 public UsageStatsService(Context context) { 154 super(context); 155 } 156 157 @Override onStart()158 public void onStart() { 159 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); 160 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 161 mPackageManager = getContext().getPackageManager(); 162 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); 163 mHandler = new H(BackgroundThread.get().getLooper()); 164 165 mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper()); 166 167 mAppTimeLimit = new AppTimeLimitController( 168 (observerId, userId, timeLimit, timeElapsed, callbackIntent) -> { 169 Intent intent = new Intent(); 170 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId); 171 intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit); 172 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed); 173 try { 174 callbackIntent.send(getContext(), 0, intent); 175 } catch (PendingIntent.CanceledException e) { 176 Slog.w(TAG, "Couldn't deliver callback: " 177 + callbackIntent); 178 } 179 }, mHandler.getLooper()); 180 181 mAppStandby.addListener(mStandbyChangeListener); 182 File systemDataDir = new File(Environment.getDataDirectory(), "system"); 183 mUsageStatsDir = new File(systemDataDir, "usagestats"); 184 mUsageStatsDir.mkdirs(); 185 if (!mUsageStatsDir.exists()) { 186 throw new IllegalStateException("Usage stats directory does not exist: " 187 + mUsageStatsDir.getAbsolutePath()); 188 } 189 190 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED); 191 filter.addAction(Intent.ACTION_USER_STARTED); 192 getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter, 193 null, mHandler); 194 195 synchronized (mLock) { 196 cleanUpRemovedUsersLocked(); 197 } 198 199 mRealTimeSnapshot = SystemClock.elapsedRealtime(); 200 mSystemTimeSnapshot = System.currentTimeMillis(); 201 202 publishLocalService(UsageStatsManagerInternal.class, new LocalService()); 203 publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); 204 // Make sure we initialize the data, in case job scheduler needs it early. 205 getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot); 206 } 207 208 @Override onBootPhase(int phase)209 public void onBootPhase(int phase) { 210 if (phase == PHASE_SYSTEM_SERVICES_READY) { 211 mAppStandby.onBootPhase(phase); 212 // initialize mDpmInternal 213 getDpmInternal(); 214 215 mDeviceIdleController = IDeviceIdleController.Stub.asInterface( 216 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 217 218 if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) { 219 try { 220 ActivityManager.getService().registerUidObserver(mUidObserver, 221 ActivityManager.UID_OBSERVER_PROCSTATE 222 | ActivityManager.UID_OBSERVER_GONE, 223 ActivityManager.PROCESS_STATE_UNKNOWN, null); 224 } catch (RemoteException e) { 225 throw new RuntimeException(e); 226 } 227 } else { 228 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE); 229 } 230 } 231 } 232 getDpmInternal()233 private DevicePolicyManagerInternal getDpmInternal() { 234 if (mDpmInternal == null) { 235 mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class); 236 } 237 return mDpmInternal; 238 } 239 240 private class UserActionsReceiver extends BroadcastReceiver { 241 @Override onReceive(Context context, Intent intent)242 public void onReceive(Context context, Intent intent) { 243 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 244 final String action = intent.getAction(); 245 if (Intent.ACTION_USER_REMOVED.equals(action)) { 246 if (userId >= 0) { 247 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 248 } 249 } else if (Intent.ACTION_USER_STARTED.equals(action)) { 250 if (userId >=0) { 251 mAppStandby.postCheckIdleStates(userId); 252 } 253 } 254 } 255 } 256 257 private final IUidObserver mUidObserver = new IUidObserver.Stub() { 258 @Override 259 public void onUidStateChanged(int uid, int procState, long procStateSeq) { 260 mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget(); 261 } 262 263 @Override 264 public void onUidIdle(int uid, boolean disabled) { 265 // Ignored 266 } 267 268 @Override 269 public void onUidGone(int uid, boolean disabled) { 270 onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0); 271 } 272 273 @Override 274 public void onUidActive(int uid) { 275 // Ignored 276 } 277 278 @Override public void onUidCachedChanged(int uid, boolean cached) { 279 } 280 }; 281 282 @Override onStatsUpdated()283 public void onStatsUpdated() { 284 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 285 } 286 287 @Override onStatsReloaded()288 public void onStatsReloaded() { 289 mAppStandby.postOneTimeCheckIdleStates(); 290 } 291 292 @Override onNewUpdate(int userId)293 public void onNewUpdate(int userId) { 294 mAppStandby.initializeDefaultsForSystemApps(userId); 295 } 296 shouldObfuscateInstantAppsForCaller(int callingUid, int userId)297 private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) { 298 return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId); 299 } 300 cleanUpRemovedUsersLocked()301 private void cleanUpRemovedUsersLocked() { 302 final List<UserInfo> users = mUserManager.getUsers(true); 303 if (users == null || users.size() == 0) { 304 throw new IllegalStateException("There can't be no users"); 305 } 306 307 ArraySet<String> toDelete = new ArraySet<>(); 308 String[] fileNames = mUsageStatsDir.list(); 309 if (fileNames == null) { 310 // No users to delete. 311 return; 312 } 313 314 toDelete.addAll(Arrays.asList(fileNames)); 315 316 final int userCount = users.size(); 317 for (int i = 0; i < userCount; i++) { 318 final UserInfo userInfo = users.get(i); 319 toDelete.remove(Integer.toString(userInfo.id)); 320 } 321 322 final int deleteCount = toDelete.size(); 323 for (int i = 0; i < deleteCount; i++) { 324 deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i))); 325 } 326 } 327 deleteRecursively(File f)328 private static void deleteRecursively(File f) { 329 File[] files = f.listFiles(); 330 if (files != null) { 331 for (File subFile : files) { 332 deleteRecursively(subFile); 333 } 334 } 335 336 if (!f.delete()) { 337 Slog.e(TAG, "Failed to delete " + f); 338 } 339 } 340 getUserDataAndInitializeIfNeededLocked(int userId, long currentTimeMillis)341 private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, 342 long currentTimeMillis) { 343 UserUsageStatsService service = mUserState.get(userId); 344 if (service == null) { 345 service = new UserUsageStatsService(getContext(), userId, 346 new File(mUsageStatsDir, Integer.toString(userId)), this); 347 service.init(currentTimeMillis); 348 mUserState.put(userId, service); 349 } 350 return service; 351 } 352 353 /** 354 * This should be the only way to get the time from the system. 355 */ checkAndGetTimeLocked()356 private long checkAndGetTimeLocked() { 357 final long actualSystemTime = System.currentTimeMillis(); 358 final long actualRealtime = SystemClock.elapsedRealtime(); 359 final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 360 final long diffSystemTime = actualSystemTime - expectedSystemTime; 361 if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS 362 && ENABLE_TIME_CHANGE_CORRECTION) { 363 // The time has changed. 364 Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds"); 365 final int userCount = mUserState.size(); 366 for (int i = 0; i < userCount; i++) { 367 final UserUsageStatsService service = mUserState.valueAt(i); 368 service.onTimeChanged(expectedSystemTime, actualSystemTime); 369 } 370 mRealTimeSnapshot = actualRealtime; 371 mSystemTimeSnapshot = actualSystemTime; 372 } 373 return actualSystemTime; 374 } 375 376 /** 377 * Assuming the event's timestamp is measured in milliseconds since boot, 378 * convert it to a system wall time. 379 */ convertToSystemTimeLocked(UsageEvents.Event event)380 private void convertToSystemTimeLocked(UsageEvents.Event event) { 381 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 382 } 383 384 /** 385 * Called by the Binder stub 386 */ shutdown()387 void shutdown() { 388 synchronized (mLock) { 389 mHandler.removeMessages(MSG_REPORT_EVENT); 390 flushToDiskLocked(); 391 } 392 } 393 394 /** 395 * Called by the Binder stub. 396 */ reportEvent(UsageEvents.Event event, int userId)397 void reportEvent(UsageEvents.Event event, int userId) { 398 synchronized (mLock) { 399 final long timeNow = checkAndGetTimeLocked(); 400 final long elapsedRealtime = SystemClock.elapsedRealtime(); 401 convertToSystemTimeLocked(event); 402 403 if (event.getPackageName() != null 404 && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) { 405 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP; 406 } 407 408 final UserUsageStatsService service = 409 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 410 service.reportEvent(event); 411 412 mAppStandby.reportEvent(event, elapsedRealtime, userId); 413 switch (event.mEventType) { 414 case Event.MOVE_TO_FOREGROUND: 415 mAppTimeLimit.moveToForeground(event.getPackageName(), event.getClassName(), 416 userId); 417 break; 418 case Event.MOVE_TO_BACKGROUND: 419 mAppTimeLimit.moveToBackground(event.getPackageName(), event.getClassName(), 420 userId); 421 break; 422 } 423 } 424 } 425 426 /** 427 * Called by the Binder stub. 428 */ flushToDisk()429 void flushToDisk() { 430 synchronized (mLock) { 431 flushToDiskLocked(); 432 } 433 } 434 435 /** 436 * Called by the Binder stub. 437 */ onUserRemoved(int userId)438 void onUserRemoved(int userId) { 439 synchronized (mLock) { 440 Slog.i(TAG, "Removing user " + userId + " and all data."); 441 mUserState.remove(userId); 442 mAppStandby.onUserRemoved(userId); 443 mAppTimeLimit.onUserRemoved(userId); 444 cleanUpRemovedUsersLocked(); 445 } 446 } 447 448 /** 449 * Called by the Binder stub. 450 */ queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)451 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime, 452 boolean obfuscateInstantApps) { 453 synchronized (mLock) { 454 final long timeNow = checkAndGetTimeLocked(); 455 if (!validRange(timeNow, beginTime, endTime)) { 456 return null; 457 } 458 459 final UserUsageStatsService service = 460 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 461 List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime); 462 if (list == null) { 463 return null; 464 } 465 466 // Mangle instant app names *using their current state (not whether they were ephemeral 467 // when the data was recorded)*. 468 if (obfuscateInstantApps) { 469 for (int i = list.size() - 1; i >= 0; i--) { 470 final UsageStats stats = list.get(i); 471 if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) { 472 list.set(i, stats.getObfuscatedForInstantApp()); 473 } 474 } 475 } 476 477 return list; 478 } 479 } 480 481 /** 482 * Called by the Binder stub. 483 */ queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)484 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 485 long endTime) { 486 synchronized (mLock) { 487 final long timeNow = checkAndGetTimeLocked(); 488 if (!validRange(timeNow, beginTime, endTime)) { 489 return null; 490 } 491 492 final UserUsageStatsService service = 493 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 494 return service.queryConfigurationStats(bucketType, beginTime, endTime); 495 } 496 } 497 498 /** 499 * Called by the Binder stub. 500 */ queryEventStats(int userId, int bucketType, long beginTime, long endTime)501 List<EventStats> queryEventStats(int userId, int bucketType, long beginTime, 502 long endTime) { 503 synchronized (mLock) { 504 final long timeNow = checkAndGetTimeLocked(); 505 if (!validRange(timeNow, beginTime, endTime)) { 506 return null; 507 } 508 509 final UserUsageStatsService service = 510 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 511 return service.queryEventStats(bucketType, beginTime, endTime); 512 } 513 } 514 515 /** 516 * Called by the Binder stub. 517 */ queryEvents(int userId, long beginTime, long endTime, boolean shouldObfuscateInstantApps)518 UsageEvents queryEvents(int userId, long beginTime, long endTime, 519 boolean shouldObfuscateInstantApps) { 520 synchronized (mLock) { 521 final long timeNow = checkAndGetTimeLocked(); 522 if (!validRange(timeNow, beginTime, endTime)) { 523 return null; 524 } 525 526 final UserUsageStatsService service = 527 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 528 return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps); 529 } 530 } 531 532 /** 533 * Called by the Binder stub. 534 */ queryEventsForPackage(int userId, long beginTime, long endTime, String packageName)535 UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime, 536 String packageName) { 537 synchronized (mLock) { 538 final long timeNow = checkAndGetTimeLocked(); 539 if (!validRange(timeNow, beginTime, endTime)) { 540 return null; 541 } 542 543 final UserUsageStatsService service = 544 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 545 return service.queryEventsForPackage(beginTime, endTime, packageName); 546 } 547 } 548 validRange(long currentTime, long beginTime, long endTime)549 private static boolean validRange(long currentTime, long beginTime, long endTime) { 550 return beginTime <= currentTime && beginTime < endTime; 551 } 552 flushToDiskLocked()553 private void flushToDiskLocked() { 554 final int userCount = mUserState.size(); 555 for (int i = 0; i < userCount; i++) { 556 UserUsageStatsService service = mUserState.valueAt(i); 557 service.persistActiveStats(); 558 mAppStandby.flushToDisk(mUserState.keyAt(i)); 559 } 560 mAppStandby.flushDurationsToDisk(); 561 562 mHandler.removeMessages(MSG_FLUSH_TO_DISK); 563 } 564 565 /** 566 * Called by the Binder stub. 567 */ dump(String[] args, PrintWriter pw)568 void dump(String[] args, PrintWriter pw) { 569 synchronized (mLock) { 570 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 571 572 boolean checkin = false; 573 boolean compact = false; 574 String pkg = null; 575 576 if (args != null) { 577 for (int i = 0; i < args.length; i++) { 578 String arg = args[i]; 579 if ("--checkin".equals(arg)) { 580 checkin = true; 581 } else 582 if ("-c".equals(arg)) { 583 compact = true; 584 } else if ("flush".equals(arg)) { 585 flushToDiskLocked(); 586 pw.println("Flushed stats to disk"); 587 return; 588 } else if ("is-app-standby-enabled".equals(arg)) { 589 pw.println(mAppStandby.mAppIdleEnabled); 590 return; 591 } else if (arg != null && !arg.startsWith("-")) { 592 // Anything else that doesn't start with '-' is a pkg to filter 593 pkg = arg; 594 break; 595 } 596 } 597 } 598 599 final int userCount = mUserState.size(); 600 for (int i = 0; i < userCount; i++) { 601 int userId = mUserState.keyAt(i); 602 idpw.printPair("user", userId); 603 idpw.println(); 604 idpw.increaseIndent(); 605 if (checkin) { 606 mUserState.valueAt(i).checkin(idpw); 607 } else { 608 mUserState.valueAt(i).dump(idpw, pkg, compact); 609 idpw.println(); 610 } 611 mAppStandby.dumpUser(idpw, userId, pkg); 612 idpw.decreaseIndent(); 613 } 614 615 if (pkg == null) { 616 pw.println(); 617 mAppStandby.dumpState(args, pw); 618 } 619 620 mAppTimeLimit.dump(pw); 621 } 622 } 623 624 class H extends Handler { H(Looper looper)625 public H(Looper looper) { 626 super(looper); 627 } 628 629 @Override handleMessage(Message msg)630 public void handleMessage(Message msg) { 631 switch (msg.what) { 632 case MSG_REPORT_EVENT: 633 reportEvent((UsageEvents.Event) msg.obj, msg.arg1); 634 break; 635 636 case MSG_FLUSH_TO_DISK: 637 flushToDisk(); 638 break; 639 640 case MSG_REMOVE_USER: 641 onUserRemoved(msg.arg1); 642 break; 643 644 case MSG_UID_STATE_CHANGED: { 645 final int uid = msg.arg1; 646 final int procState = msg.arg2; 647 648 final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1; 649 synchronized (mUidToKernelCounter) { 650 final int oldCounter = mUidToKernelCounter.get(uid, 0); 651 if (newCounter != oldCounter) { 652 mUidToKernelCounter.put(uid, newCounter); 653 try { 654 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter); 655 } catch (IOException e) { 656 Slog.w(TAG, "Failed to update counter set: " + e); 657 } 658 } 659 } 660 break; 661 } 662 663 default: 664 super.handleMessage(msg); 665 break; 666 } 667 } 668 } 669 670 private final class BinderService extends IUsageStatsManager.Stub { 671 hasPermission(String callingPackage)672 private boolean hasPermission(String callingPackage) { 673 final int callingUid = Binder.getCallingUid(); 674 if (callingUid == Process.SYSTEM_UID) { 675 return true; 676 } 677 final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 678 callingUid, callingPackage); 679 if (mode == AppOpsManager.MODE_DEFAULT) { 680 // The default behavior here is to check if PackageManager has given the app 681 // permission. 682 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 683 == PackageManager.PERMISSION_GRANTED; 684 } 685 return mode == AppOpsManager.MODE_ALLOWED; 686 } 687 hasObserverPermission(String callingPackage)688 private boolean hasObserverPermission(String callingPackage) { 689 final int callingUid = Binder.getCallingUid(); 690 DevicePolicyManagerInternal dpmInternal = getDpmInternal(); 691 if (callingUid == Process.SYSTEM_UID 692 || (dpmInternal != null 693 && dpmInternal.isActiveAdminWithPolicy(callingUid, 694 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER))) { 695 // Caller is the system or the profile owner, so proceed. 696 return true; 697 } 698 return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE) 699 == PackageManager.PERMISSION_GRANTED; 700 } 701 checkCallerIsSystemOrSameApp(String pkg)702 private void checkCallerIsSystemOrSameApp(String pkg) { 703 if (isCallingUidSystem()) { 704 return; 705 } 706 checkCallerIsSameApp(pkg); 707 } 708 checkCallerIsSameApp(String pkg)709 private void checkCallerIsSameApp(String pkg) { 710 final int callingUid = Binder.getCallingUid(); 711 final int callingUserId = UserHandle.getUserId(callingUid); 712 713 if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0, 714 callingUserId) != callingUid) { 715 throw new SecurityException("Calling uid " + pkg + " cannot query events" 716 + "for package " + pkg); 717 } 718 } 719 isCallingUidSystem()720 private boolean isCallingUidSystem() { 721 final int uid = Binder.getCallingUid(); 722 return uid == Process.SYSTEM_UID; 723 } 724 725 @Override queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage)726 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 727 long endTime, String callingPackage) { 728 if (!hasPermission(callingPackage)) { 729 return null; 730 } 731 732 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 733 Binder.getCallingUid(), UserHandle.getCallingUserId()); 734 735 final int userId = UserHandle.getCallingUserId(); 736 final long token = Binder.clearCallingIdentity(); 737 try { 738 final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 739 userId, bucketType, beginTime, endTime, obfuscateInstantApps); 740 if (results != null) { 741 return new ParceledListSlice<>(results); 742 } 743 } finally { 744 Binder.restoreCallingIdentity(token); 745 } 746 return null; 747 } 748 749 @Override queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)750 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 751 long beginTime, long endTime, String callingPackage) throws RemoteException { 752 if (!hasPermission(callingPackage)) { 753 return null; 754 } 755 756 final int userId = UserHandle.getCallingUserId(); 757 final long token = Binder.clearCallingIdentity(); 758 try { 759 final List<ConfigurationStats> results = 760 UsageStatsService.this.queryConfigurationStats(userId, bucketType, 761 beginTime, endTime); 762 if (results != null) { 763 return new ParceledListSlice<>(results); 764 } 765 } finally { 766 Binder.restoreCallingIdentity(token); 767 } 768 return null; 769 } 770 771 @Override queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)772 public ParceledListSlice<EventStats> queryEventStats(int bucketType, 773 long beginTime, long endTime, String callingPackage) throws RemoteException { 774 if (!hasPermission(callingPackage)) { 775 return null; 776 } 777 778 final int userId = UserHandle.getCallingUserId(); 779 final long token = Binder.clearCallingIdentity(); 780 try { 781 final List<EventStats> results = 782 UsageStatsService.this.queryEventStats(userId, bucketType, 783 beginTime, endTime); 784 if (results != null) { 785 return new ParceledListSlice<>(results); 786 } 787 } finally { 788 Binder.restoreCallingIdentity(token); 789 } 790 return null; 791 } 792 793 @Override queryEvents(long beginTime, long endTime, String callingPackage)794 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 795 if (!hasPermission(callingPackage)) { 796 return null; 797 } 798 799 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 800 Binder.getCallingUid(), UserHandle.getCallingUserId()); 801 802 final int userId = UserHandle.getCallingUserId(); 803 final long token = Binder.clearCallingIdentity(); 804 try { 805 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, 806 obfuscateInstantApps); 807 } finally { 808 Binder.restoreCallingIdentity(token); 809 } 810 } 811 812 @Override queryEventsForPackage(long beginTime, long endTime, String callingPackage)813 public UsageEvents queryEventsForPackage(long beginTime, long endTime, 814 String callingPackage) { 815 final int callingUid = Binder.getCallingUid(); 816 final int callingUserId = UserHandle.getUserId(callingUid); 817 818 checkCallerIsSameApp(callingPackage); 819 final long token = Binder.clearCallingIdentity(); 820 try { 821 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime, 822 endTime, callingPackage); 823 } finally { 824 Binder.restoreCallingIdentity(token); 825 } 826 } 827 828 @Override queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)829 public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, 830 String callingPackage) { 831 if (!hasPermission(callingPackage)) { 832 return null; 833 } 834 835 if (userId != UserHandle.getCallingUserId()) { 836 getContext().enforceCallingPermission( 837 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 838 "No permission to query usage stats for this user"); 839 } 840 841 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 842 Binder.getCallingUid(), UserHandle.getCallingUserId()); 843 844 final long token = Binder.clearCallingIdentity(); 845 try { 846 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, 847 obfuscateInstantApps); 848 } finally { 849 Binder.restoreCallingIdentity(token); 850 } 851 } 852 853 @Override queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)854 public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, 855 int userId, String pkg, String callingPackage) { 856 if (!hasPermission(callingPackage)) { 857 return null; 858 } 859 if (userId != UserHandle.getCallingUserId()) { 860 getContext().enforceCallingPermission( 861 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 862 "No permission to query usage stats for this user"); 863 } 864 checkCallerIsSystemOrSameApp(pkg); 865 866 final long token = Binder.clearCallingIdentity(); 867 try { 868 return UsageStatsService.this.queryEventsForPackage(userId, beginTime, 869 endTime, callingPackage); 870 } finally { 871 Binder.restoreCallingIdentity(token); 872 } 873 } 874 875 @Override isAppInactive(String packageName, int userId)876 public boolean isAppInactive(String packageName, int userId) { 877 try { 878 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(), 879 Binder.getCallingUid(), userId, false, false, "isAppInactive", null); 880 } catch (RemoteException re) { 881 throw re.rethrowFromSystemServer(); 882 } 883 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller( 884 Binder.getCallingUid(), userId); 885 final long token = Binder.clearCallingIdentity(); 886 try { 887 return mAppStandby.isAppIdleFilteredOrParoled( 888 packageName, userId, 889 SystemClock.elapsedRealtime(), obfuscateInstantApps); 890 } finally { 891 Binder.restoreCallingIdentity(token); 892 } 893 } 894 895 @Override setAppInactive(String packageName, boolean idle, int userId)896 public void setAppInactive(String packageName, boolean idle, int userId) { 897 final int callingUid = Binder.getCallingUid(); 898 try { 899 userId = ActivityManager.getService().handleIncomingUser( 900 Binder.getCallingPid(), callingUid, userId, false, true, 901 "setAppInactive", null); 902 } catch (RemoteException re) { 903 throw re.rethrowFromSystemServer(); 904 } 905 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 906 "No permission to change app idle state"); 907 final long token = Binder.clearCallingIdentity(); 908 try { 909 final int appId = mAppStandby.getAppId(packageName); 910 if (appId < 0) return; 911 mAppStandby.setAppIdleAsync(packageName, idle, userId); 912 } finally { 913 Binder.restoreCallingIdentity(token); 914 } 915 } 916 917 @Override getAppStandbyBucket(String packageName, String callingPackage, int userId)918 public int getAppStandbyBucket(String packageName, String callingPackage, int userId) { 919 final int callingUid = Binder.getCallingUid(); 920 try { 921 userId = ActivityManager.getService().handleIncomingUser( 922 Binder.getCallingPid(), callingUid, userId, false, false, 923 "getAppStandbyBucket", null); 924 } catch (RemoteException re) { 925 throw re.rethrowFromSystemServer(); 926 } 927 final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId); 928 // If the calling app is asking about itself, continue, else check for permission. 929 if (packageUid != callingUid) { 930 if (!hasPermission(callingPackage)) { 931 throw new SecurityException( 932 "Don't have permission to query app standby bucket"); 933 } 934 } 935 if (packageUid < 0) { 936 throw new IllegalArgumentException( 937 "Cannot get standby bucket for non existent package (" + packageName + ")"); 938 } 939 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid, 940 userId); 941 final long token = Binder.clearCallingIdentity(); 942 try { 943 return mAppStandby.getAppStandbyBucket(packageName, userId, 944 SystemClock.elapsedRealtime(), obfuscateInstantApps); 945 } finally { 946 Binder.restoreCallingIdentity(token); 947 } 948 } 949 950 @Override setAppStandbyBucket(String packageName, int bucket, int userId)951 public void setAppStandbyBucket(String packageName, 952 int bucket, int userId) { 953 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 954 "No permission to change app standby state"); 955 956 if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE 957 || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) { 958 throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket); 959 } 960 final int callingUid = Binder.getCallingUid(); 961 try { 962 userId = ActivityManager.getService().handleIncomingUser( 963 Binder.getCallingPid(), callingUid, userId, false, true, 964 "setAppStandbyBucket", null); 965 } catch (RemoteException re) { 966 throw re.rethrowFromSystemServer(); 967 } 968 final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID; 969 final boolean systemCaller = UserHandle.isCore(callingUid); 970 final int reason = systemCaller 971 ? UsageStatsManager.REASON_MAIN_FORCED 972 : UsageStatsManager.REASON_MAIN_PREDICTED; 973 final long token = Binder.clearCallingIdentity(); 974 try { 975 final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 976 PackageManager.MATCH_ANY_USER, userId); 977 // Caller cannot set their own standby state 978 if (packageUid == callingUid) { 979 throw new IllegalArgumentException("Cannot set your own standby bucket"); 980 } 981 if (packageUid < 0) { 982 throw new IllegalArgumentException( 983 "Cannot set standby bucket for non existent package (" + packageName 984 + ")"); 985 } 986 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason, 987 SystemClock.elapsedRealtime(), shellCaller); 988 } finally { 989 Binder.restoreCallingIdentity(token); 990 } 991 } 992 993 @Override getAppStandbyBuckets(String callingPackageName, int userId)994 public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName, 995 int userId) { 996 final int callingUid = Binder.getCallingUid(); 997 try { 998 userId = ActivityManager.getService().handleIncomingUser( 999 Binder.getCallingPid(), callingUid, userId, false, false, 1000 "getAppStandbyBucket", null); 1001 } catch (RemoteException re) { 1002 throw re.rethrowFromSystemServer(); 1003 } 1004 if (!hasPermission(callingPackageName)) { 1005 throw new SecurityException( 1006 "Don't have permission to query app standby bucket"); 1007 } 1008 final long token = Binder.clearCallingIdentity(); 1009 try { 1010 final List<AppStandbyInfo> standbyBucketList = 1011 mAppStandby.getAppStandbyBuckets(userId); 1012 return (standbyBucketList == null) ? ParceledListSlice.emptyList() 1013 : new ParceledListSlice<>(standbyBucketList); 1014 } finally { 1015 Binder.restoreCallingIdentity(token); 1016 } 1017 } 1018 1019 @Override setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)1020 public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) { 1021 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1022 "No permission to change app standby state"); 1023 1024 final int callingUid = Binder.getCallingUid(); 1025 try { 1026 userId = ActivityManager.getService().handleIncomingUser( 1027 Binder.getCallingPid(), callingUid, userId, false, true, 1028 "setAppStandbyBucket", null); 1029 } catch (RemoteException re) { 1030 throw re.rethrowFromSystemServer(); 1031 } 1032 final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID; 1033 final int reason = shellCaller 1034 ? UsageStatsManager.REASON_MAIN_FORCED 1035 : UsageStatsManager.REASON_MAIN_PREDICTED; 1036 final long token = Binder.clearCallingIdentity(); 1037 try { 1038 final long elapsedRealtime = SystemClock.elapsedRealtime(); 1039 List<AppStandbyInfo> bucketList = appBuckets.getList(); 1040 for (AppStandbyInfo bucketInfo : bucketList) { 1041 final String packageName = bucketInfo.mPackageName; 1042 final int bucket = bucketInfo.mStandbyBucket; 1043 if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE 1044 || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) { 1045 throw new IllegalArgumentException( 1046 "Cannot set the standby bucket to " + bucket); 1047 } 1048 // Caller cannot set their own standby state 1049 if (mPackageManagerInternal.getPackageUid(packageName, 1050 PackageManager.MATCH_ANY_USER, userId) == callingUid) { 1051 throw new IllegalArgumentException("Cannot set your own standby bucket"); 1052 } 1053 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason, 1054 elapsedRealtime, shellCaller); 1055 } 1056 } finally { 1057 Binder.restoreCallingIdentity(token); 1058 } 1059 } 1060 1061 @Override whitelistAppTemporarily(String packageName, long duration, int userId)1062 public void whitelistAppTemporarily(String packageName, long duration, int userId) 1063 throws RemoteException { 1064 StringBuilder reason = new StringBuilder(32); 1065 reason.append("from:"); 1066 UserHandle.formatUid(reason, Binder.getCallingUid()); 1067 mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId, 1068 reason.toString()); 1069 } 1070 1071 @Override onCarrierPrivilegedAppsChanged()1072 public void onCarrierPrivilegedAppsChanged() { 1073 if (DEBUG) { 1074 Slog.i(TAG, "Carrier privileged apps changed"); 1075 } 1076 getContext().enforceCallingOrSelfPermission( 1077 android.Manifest.permission.BIND_CARRIER_SERVICES, 1078 "onCarrierPrivilegedAppsChanged can only be called by privileged apps."); 1079 mAppStandby.clearCarrierPrivilegedApps(); 1080 } 1081 1082 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1083 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1084 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return; 1085 UsageStatsService.this.dump(args, pw); 1086 } 1087 1088 @Override reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1089 public void reportChooserSelection(String packageName, int userId, String contentType, 1090 String[] annotations, String action) { 1091 if (packageName == null) { 1092 Slog.w(TAG, "Event report user selecting a null package"); 1093 return; 1094 } 1095 1096 UsageEvents.Event event = new UsageEvents.Event(); 1097 event.mPackage = packageName; 1098 1099 // This will later be converted to system time. 1100 event.mTimeStamp = SystemClock.elapsedRealtime(); 1101 1102 event.mEventType = Event.CHOOSER_ACTION; 1103 1104 event.mAction = action; 1105 1106 event.mContentType = contentType; 1107 1108 event.mContentAnnotations = annotations; 1109 1110 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1111 } 1112 1113 @Override registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)1114 public void registerAppUsageObserver(int observerId, 1115 String[] packages, long timeLimitMs, PendingIntent 1116 callbackIntent, String callingPackage) { 1117 if (!hasObserverPermission(callingPackage)) { 1118 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 1119 } 1120 1121 if (packages == null || packages.length == 0) { 1122 throw new IllegalArgumentException("Must specify at least one package"); 1123 } 1124 if (callbackIntent == null) { 1125 throw new NullPointerException("callbackIntent can't be null"); 1126 } 1127 final int callingUid = Binder.getCallingUid(); 1128 final int userId = UserHandle.getUserId(callingUid); 1129 final long token = Binder.clearCallingIdentity(); 1130 try { 1131 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId, 1132 packages, timeLimitMs, callbackIntent, userId); 1133 } finally { 1134 Binder.restoreCallingIdentity(token); 1135 } 1136 } 1137 1138 @Override unregisterAppUsageObserver(int observerId, String callingPackage)1139 public void unregisterAppUsageObserver(int observerId, String callingPackage) { 1140 if (!hasObserverPermission(callingPackage)) { 1141 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission"); 1142 } 1143 1144 final int callingUid = Binder.getCallingUid(); 1145 final int userId = UserHandle.getUserId(callingUid); 1146 final long token = Binder.clearCallingIdentity(); 1147 try { 1148 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId); 1149 } finally { 1150 Binder.restoreCallingIdentity(token); 1151 } 1152 } 1153 } 1154 registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)1155 void registerAppUsageObserver(int callingUid, int observerId, String[] packages, 1156 long timeLimitMs, PendingIntent callbackIntent, int userId) { 1157 mAppTimeLimit.addObserver(callingUid, observerId, packages, timeLimitMs, callbackIntent, 1158 userId); 1159 } 1160 unregisterAppUsageObserver(int callingUid, int observerId, int userId)1161 void unregisterAppUsageObserver(int callingUid, int observerId, int userId) { 1162 mAppTimeLimit.removeObserver(callingUid, observerId, userId); 1163 } 1164 1165 /** 1166 * This local service implementation is primarily used by ActivityManagerService. 1167 * ActivityManagerService will call these methods holding the 'am' lock, which means we 1168 * shouldn't be doing any IO work or other long running tasks in these methods. 1169 */ 1170 private final class LocalService extends UsageStatsManagerInternal { 1171 1172 @Override reportEvent(ComponentName component, int userId, int eventType)1173 public void reportEvent(ComponentName component, int userId, int eventType) { 1174 if (component == null) { 1175 Slog.w(TAG, "Event reported without a component name"); 1176 return; 1177 } 1178 1179 UsageEvents.Event event = new UsageEvents.Event(); 1180 event.mPackage = component.getPackageName(); 1181 event.mClass = component.getClassName(); 1182 1183 // This will later be converted to system time. 1184 event.mTimeStamp = SystemClock.elapsedRealtime(); 1185 1186 event.mEventType = eventType; 1187 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1188 } 1189 1190 @Override reportEvent(String packageName, int userId, int eventType)1191 public void reportEvent(String packageName, int userId, int eventType) { 1192 if (packageName == null) { 1193 Slog.w(TAG, "Event reported without a package name"); 1194 return; 1195 } 1196 1197 UsageEvents.Event event = new UsageEvents.Event(); 1198 event.mPackage = packageName; 1199 1200 // This will later be converted to system time. 1201 event.mTimeStamp = SystemClock.elapsedRealtime(); 1202 1203 event.mEventType = eventType; 1204 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1205 } 1206 1207 @Override reportConfigurationChange(Configuration config, int userId)1208 public void reportConfigurationChange(Configuration config, int userId) { 1209 if (config == null) { 1210 Slog.w(TAG, "Configuration event reported with a null config"); 1211 return; 1212 } 1213 1214 UsageEvents.Event event = new UsageEvents.Event(); 1215 event.mPackage = "android"; 1216 1217 // This will later be converted to system time. 1218 event.mTimeStamp = SystemClock.elapsedRealtime(); 1219 1220 event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; 1221 event.mConfiguration = new Configuration(config); 1222 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1223 } 1224 1225 @Override reportInterruptiveNotification(String packageName, String channelId, int userId)1226 public void reportInterruptiveNotification(String packageName, String channelId, 1227 int userId) { 1228 if (packageName == null || channelId == null) { 1229 Slog.w(TAG, "Event reported without a package name or a channel ID"); 1230 return; 1231 } 1232 1233 UsageEvents.Event event = new UsageEvents.Event(); 1234 event.mPackage = packageName.intern(); 1235 event.mNotificationChannelId = channelId.intern(); 1236 1237 // This will later be converted to system time. 1238 event.mTimeStamp = SystemClock.elapsedRealtime(); 1239 1240 event.mEventType = Event.NOTIFICATION_INTERRUPTION; 1241 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1242 } 1243 1244 @Override reportShortcutUsage(String packageName, String shortcutId, int userId)1245 public void reportShortcutUsage(String packageName, String shortcutId, int userId) { 1246 if (packageName == null || shortcutId == null) { 1247 Slog.w(TAG, "Event reported without a package name or a shortcut ID"); 1248 return; 1249 } 1250 1251 UsageEvents.Event event = new UsageEvents.Event(); 1252 event.mPackage = packageName.intern(); 1253 event.mShortcutId = shortcutId.intern(); 1254 1255 // This will later be converted to system time. 1256 event.mTimeStamp = SystemClock.elapsedRealtime(); 1257 1258 event.mEventType = Event.SHORTCUT_INVOCATION; 1259 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1260 } 1261 1262 @Override reportContentProviderUsage(String name, String packageName, int userId)1263 public void reportContentProviderUsage(String name, String packageName, int userId) { 1264 mAppStandby.postReportContentProviderUsage(name, packageName, userId); 1265 } 1266 1267 @Override isAppIdle(String packageName, int uidForAppId, int userId)1268 public boolean isAppIdle(String packageName, int uidForAppId, int userId) { 1269 return mAppStandby.isAppIdleFiltered(packageName, uidForAppId, 1270 userId, SystemClock.elapsedRealtime()); 1271 } 1272 1273 @Override getAppStandbyBucket(String packageName, int userId, long nowElapsed)1274 @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId, 1275 long nowElapsed) { 1276 return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false); 1277 } 1278 1279 @Override getIdleUidsForUser(int userId)1280 public int[] getIdleUidsForUser(int userId) { 1281 return mAppStandby.getIdleUidsForUser(userId); 1282 } 1283 1284 @Override isAppIdleParoleOn()1285 public boolean isAppIdleParoleOn() { 1286 return mAppStandby.isParoledOrCharging(); 1287 } 1288 1289 @Override prepareShutdown()1290 public void prepareShutdown() { 1291 // This method *WILL* do IO work, but we must block until it is finished or else 1292 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 1293 // we are shutting down. 1294 shutdown(); 1295 } 1296 1297 @Override addAppIdleStateChangeListener(AppIdleStateChangeListener listener)1298 public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { 1299 mAppStandby.addListener(listener); 1300 listener.onParoleStateChanged(isAppIdleParoleOn()); 1301 } 1302 1303 @Override removeAppIdleStateChangeListener( AppIdleStateChangeListener listener)1304 public void removeAppIdleStateChangeListener( 1305 AppIdleStateChangeListener listener) { 1306 mAppStandby.removeListener(listener); 1307 } 1308 1309 @Override getBackupPayload(int user, String key)1310 public byte[] getBackupPayload(int user, String key) { 1311 // Check to ensure that only user 0's data is b/r for now 1312 synchronized (mLock) { 1313 if (user == UserHandle.USER_SYSTEM) { 1314 final UserUsageStatsService userStats = 1315 getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); 1316 return userStats.getBackupPayload(key); 1317 } else { 1318 return null; 1319 } 1320 } 1321 } 1322 1323 @Override applyRestoredPayload(int user, String key, byte[] payload)1324 public void applyRestoredPayload(int user, String key, byte[] payload) { 1325 synchronized (mLock) { 1326 if (user == UserHandle.USER_SYSTEM) { 1327 final UserUsageStatsService userStats = 1328 getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); 1329 userStats.applyRestoredPayload(key, payload); 1330 } 1331 } 1332 } 1333 1334 @Override queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)1335 public List<UsageStats> queryUsageStatsForUser( 1336 int userId, int intervalType, long beginTime, long endTime, 1337 boolean obfuscateInstantApps) { 1338 return UsageStatsService.this.queryUsageStats( 1339 userId, intervalType, beginTime, endTime, obfuscateInstantApps); 1340 } 1341 1342 @Override setLastJobRunTime(String packageName, int userId, long elapsedRealtime)1343 public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) { 1344 mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime); 1345 } 1346 1347 @Override getTimeSinceLastJobRun(String packageName, int userId)1348 public long getTimeSinceLastJobRun(String packageName, int userId) { 1349 return mAppStandby.getTimeSinceLastJobRun(packageName, userId); 1350 } 1351 1352 @Override reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)1353 public void reportAppJobState(String packageName, int userId, 1354 int numDeferredJobs, long timeSinceLastJobRun) { 1355 } 1356 1357 @Override onActiveAdminAdded(String packageName, int userId)1358 public void onActiveAdminAdded(String packageName, int userId) { 1359 mAppStandby.addActiveDeviceAdmin(packageName, userId); 1360 } 1361 1362 @Override setActiveAdminApps(Set<String> packageNames, int userId)1363 public void setActiveAdminApps(Set<String> packageNames, int userId) { 1364 mAppStandby.setActiveAdminApps(packageNames, userId); 1365 } 1366 1367 @Override onAdminDataAvailable()1368 public void onAdminDataAvailable() { 1369 mAppStandby.onAdminDataAvailable(); 1370 } 1371 1372 @Override reportExemptedSyncScheduled(String packageName, int userId)1373 public void reportExemptedSyncScheduled(String packageName, int userId) { 1374 mAppStandby.postReportExemptedSyncScheduled(packageName, userId); 1375 } 1376 1377 @Override reportExemptedSyncStart(String packageName, int userId)1378 public void reportExemptedSyncStart(String packageName, int userId) { 1379 mAppStandby.postReportExemptedSyncStart(packageName, userId); 1380 } 1381 } 1382 } 1383