UsageStatsService.java revision 92617036fcc9b25378c8448c923d6346a012346b
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 17package com.android.server.usage; 18 19import android.Manifest; 20import android.app.ActivityManagerNative; 21import android.app.AppGlobals; 22import android.app.AppOpsManager; 23import android.app.admin.DevicePolicyManager; 24import android.app.usage.ConfigurationStats; 25import android.app.usage.IUsageStatsManager; 26import android.app.usage.UsageEvents; 27import android.app.usage.UsageEvents.Event; 28import android.app.usage.UsageStats; 29import android.app.usage.UsageStatsManagerInternal; 30import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; 31import android.appwidget.AppWidgetManager; 32import android.content.BroadcastReceiver; 33import android.content.ComponentName; 34import android.content.ContentResolver; 35import android.content.Context; 36import android.content.Intent; 37import android.content.IntentFilter; 38import android.content.pm.PackageInfo; 39import android.content.pm.PackageManager; 40import android.content.pm.ParceledListSlice; 41import android.content.pm.UserInfo; 42import android.content.res.Configuration; 43import android.database.ContentObserver; 44import android.hardware.display.DisplayManager; 45import android.os.BatteryManager; 46import android.os.BatteryStats; 47import android.os.Binder; 48import android.os.Environment; 49import android.os.Handler; 50import android.os.IDeviceIdleController; 51import android.os.Looper; 52import android.os.Message; 53import android.os.PowerManager; 54import android.os.Process; 55import android.os.RemoteException; 56import android.os.ServiceManager; 57import android.os.SystemClock; 58import android.os.UserHandle; 59import android.os.UserManager; 60import android.provider.Settings; 61import android.telephony.TelephonyManager; 62import android.util.ArraySet; 63import android.util.AtomicFile; 64import android.util.KeyValueListParser; 65import android.util.Slog; 66import android.util.SparseArray; 67import android.util.TimeUtils; 68import android.view.Display; 69 70import com.android.internal.annotations.GuardedBy; 71import com.android.internal.app.IBatteryStats; 72import com.android.internal.os.BackgroundThread; 73import com.android.internal.os.SomeArgs; 74import com.android.internal.util.IndentingPrintWriter; 75import com.android.server.SystemService; 76 77import java.io.BufferedReader; 78import java.io.File; 79import java.io.FileDescriptor; 80import java.io.FileOutputStream; 81import java.io.FileReader; 82import java.io.IOException; 83import java.io.PrintWriter; 84import java.util.ArrayList; 85import java.util.Arrays; 86import java.util.List; 87 88/** 89 * A service that collects, aggregates, and persists application usage data. 90 * This data can be queried by apps that have been granted permission by AppOps. 91 */ 92public class UsageStatsService extends SystemService implements 93 UserUsageStatsService.StatsUpdatedListener { 94 95 static final String TAG = "UsageStatsService"; 96 97 static final boolean DEBUG = false; 98 static final boolean COMPRESS_TIME = false; 99 100 private static final long TEN_SECONDS = 10 * 1000; 101 private static final long ONE_MINUTE = 60 * 1000; 102 private static final long TWENTY_MINUTES = 20 * 60 * 1000; 103 private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES; 104 private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. 105 106 long mAppIdleDurationMillis; 107 long mCheckIdleIntervalMillis; 108 long mAppIdleWallclockThresholdMillis; 109 long mAppIdleParoleIntervalMillis; 110 long mAppIdleParoleDurationMillis; 111 112 // Handler message types. 113 static final int MSG_REPORT_EVENT = 0; 114 static final int MSG_FLUSH_TO_DISK = 1; 115 static final int MSG_REMOVE_USER = 2; 116 static final int MSG_INFORM_LISTENERS = 3; 117 static final int MSG_FORCE_IDLE_STATE = 4; 118 static final int MSG_CHECK_IDLE_STATES = 5; 119 static final int MSG_CHECK_PAROLE_TIMEOUT = 6; 120 static final int MSG_PAROLE_END_TIMEOUT = 7; 121 static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8; 122 123 private final Object mLock = new Object(); 124 Handler mHandler; 125 AppOpsManager mAppOps; 126 UserManager mUserManager; 127 AppWidgetManager mAppWidgetManager; 128 IDeviceIdleController mDeviceIdleController; 129 private DisplayManager mDisplayManager; 130 private PowerManager mPowerManager; 131 private IBatteryStats mBatteryStats; 132 133 private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); 134 private File mUsageStatsDir; 135 long mRealTimeSnapshot; 136 long mSystemTimeSnapshot; 137 138 boolean mAppIdleEnabled; 139 boolean mAppIdleParoled; 140 private boolean mScreenOn; 141 private long mLastAppIdleParoledTime; 142 143 long mScreenOnTime; 144 long mScreenOnSystemTimeSnapshot; 145 146 @GuardedBy("mLock") 147 private AppIdleHistory mAppIdleHistory = new AppIdleHistory(); 148 149 private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener> 150 mPackageAccessListeners = new ArrayList<>(); 151 152 public UsageStatsService(Context context) { 153 super(context); 154 } 155 156 @Override 157 public void onStart() { 158 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); 159 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 160 161 mHandler = new H(BackgroundThread.get().getLooper()); 162 163 File systemDataDir = new File(Environment.getDataDirectory(), "system"); 164 mUsageStatsDir = new File(systemDataDir, "usagestats"); 165 mUsageStatsDir.mkdirs(); 166 if (!mUsageStatsDir.exists()) { 167 throw new IllegalStateException("Usage stats directory does not exist: " 168 + mUsageStatsDir.getAbsolutePath()); 169 } 170 171 IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED); 172 userActions.addAction(Intent.ACTION_USER_STARTED); 173 getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions, 174 null, null); 175 176 mAppIdleEnabled = getContext().getResources().getBoolean( 177 com.android.internal.R.bool.config_enableAutoPowerModes); 178 if (mAppIdleEnabled) { 179 IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING); 180 deviceStates.addAction(BatteryManager.ACTION_DISCHARGING); 181 deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 182 getContext().registerReceiver(new DeviceStateReceiver(), deviceStates); 183 } 184 185 synchronized (mLock) { 186 cleanUpRemovedUsersLocked(); 187 } 188 189 mRealTimeSnapshot = SystemClock.elapsedRealtime(); 190 mSystemTimeSnapshot = System.currentTimeMillis(); 191 192 publishLocalService(UsageStatsManagerInternal.class, new LocalService()); 193 publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); 194 } 195 196 @Override 197 public void onBootPhase(int phase) { 198 if (phase == PHASE_SYSTEM_SERVICES_READY) { 199 // Observe changes to the threshold 200 SettingsObserver settingsObserver = new SettingsObserver(mHandler); 201 settingsObserver.registerObserver(); 202 settingsObserver.updateSettings(); 203 204 mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class); 205 mDeviceIdleController = IDeviceIdleController.Stub.asInterface( 206 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 207 mBatteryStats = IBatteryStats.Stub.asInterface( 208 ServiceManager.getService(BatteryStats.SERVICE_NAME)); 209 mDisplayManager = (DisplayManager) getContext().getSystemService( 210 Context.DISPLAY_SERVICE); 211 mPowerManager = getContext().getSystemService(PowerManager.class); 212 213 mScreenOnSystemTimeSnapshot = System.currentTimeMillis(); 214 synchronized (this) { 215 mScreenOnTime = readScreenOnTimeLocked(); 216 } 217 mDisplayManager.registerDisplayListener(mDisplayListener, null); 218 synchronized (this) { 219 updateDisplayLocked(); 220 } 221 } else if (phase == PHASE_BOOT_COMPLETED) { 222 setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging()); 223 } 224 } 225 226 private class UserActionsReceiver extends BroadcastReceiver { 227 228 @Override 229 public void onReceive(Context context, Intent intent) { 230 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 231 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) { 232 if (userId >= 0) { 233 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 234 } 235 } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { 236 if (userId >=0) { 237 postCheckIdleStates(userId); 238 } 239 } 240 } 241 } 242 243 private class DeviceStateReceiver extends BroadcastReceiver { 244 @Override 245 public void onReceive(Context context, Intent intent) { 246 final String action = intent.getAction(); 247 if (BatteryManager.ACTION_CHARGING.equals(action) 248 || BatteryManager.ACTION_DISCHARGING.equals(action)) { 249 setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action)); 250 } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) { 251 onDeviceIdleModeChanged(); 252 } 253 } 254 } 255 256 private final DisplayManager.DisplayListener mDisplayListener 257 = new DisplayManager.DisplayListener() { 258 259 @Override public void onDisplayAdded(int displayId) { 260 } 261 262 @Override public void onDisplayRemoved(int displayId) { 263 } 264 265 @Override public void onDisplayChanged(int displayId) { 266 if (displayId == Display.DEFAULT_DISPLAY) { 267 synchronized (UsageStatsService.this.mLock) { 268 updateDisplayLocked(); 269 } 270 } 271 } 272 }; 273 274 @Override 275 public void onStatsUpdated() { 276 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 277 } 278 279 private void cleanUpRemovedUsersLocked() { 280 final List<UserInfo> users = mUserManager.getUsers(true); 281 if (users == null || users.size() == 0) { 282 throw new IllegalStateException("There can't be no users"); 283 } 284 285 ArraySet<String> toDelete = new ArraySet<>(); 286 String[] fileNames = mUsageStatsDir.list(); 287 if (fileNames == null) { 288 // No users to delete. 289 return; 290 } 291 292 toDelete.addAll(Arrays.asList(fileNames)); 293 294 final int userCount = users.size(); 295 for (int i = 0; i < userCount; i++) { 296 final UserInfo userInfo = users.get(i); 297 toDelete.remove(Integer.toString(userInfo.id)); 298 } 299 300 final int deleteCount = toDelete.size(); 301 for (int i = 0; i < deleteCount; i++) { 302 deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i))); 303 } 304 } 305 306 /** Paroled here means temporary pardon from being inactive */ 307 void setAppIdleParoled(boolean paroled) { 308 synchronized (mLock) { 309 if (mAppIdleParoled != paroled) { 310 mAppIdleParoled = paroled; 311 if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled); 312 if (paroled) { 313 mLastAppIdleParoledTime = checkAndGetTimeLocked(); 314 postNextParoleTimeout(); 315 } 316 postCheckIdleStates(UserHandle.USER_ALL); 317 } 318 } 319 } 320 321 private void postNextParoleTimeout() { 322 if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT"); 323 mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT); 324 // Compute when the next parole needs to happen. We check more frequently than necessary 325 // since the message handler delays are based on elapsedRealTime and not wallclock time. 326 // The comparison is done in wallclock time. 327 long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) 328 - checkAndGetTimeLocked(); 329 if (timeLeft < 0) { 330 timeLeft = 0; 331 } 332 mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10); 333 } 334 335 private void postParoleEndTimeout() { 336 if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT"); 337 mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT); 338 mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis); 339 } 340 341 void postCheckIdleStates(int userId) { 342 mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); 343 } 344 345 /** Check all running users' or specified user's apps to see if they enter an idle state. */ 346 void checkIdleStates(int checkUserId) { 347 if (!mAppIdleEnabled) { 348 return; 349 } 350 351 final int[] userIds; 352 try { 353 if (checkUserId == UserHandle.USER_ALL) { 354 userIds = ActivityManagerNative.getDefault().getRunningUserIds(); 355 } else { 356 userIds = new int[] { checkUserId }; 357 } 358 } catch (RemoteException re) { 359 return; 360 } 361 362 for (int i = 0; i < userIds.length; i++) { 363 final int userId = userIds[i]; 364 List<PackageInfo> packages = 365 getContext().getPackageManager().getInstalledPackages( 366 PackageManager.GET_DISABLED_COMPONENTS 367 | PackageManager.GET_UNINSTALLED_PACKAGES, 368 userId); 369 synchronized (mLock) { 370 final long timeNow = checkAndGetTimeLocked(); 371 final long screenOnTime = getScreenOnTimeLocked(timeNow); 372 UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, 373 timeNow); 374 final int packageCount = packages.size(); 375 for (int p = 0; p < packageCount; p++) { 376 final String packageName = packages.get(p).packageName; 377 final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow, 378 screenOnTime); 379 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, 380 userId, isIdle ? 1 : 0, packageName)); 381 mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow); 382 } 383 } 384 } 385 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0), 386 mCheckIdleIntervalMillis); 387 } 388 389 /** Check if it's been a while since last parole and let idle apps do some work */ 390 void checkParoleTimeout() { 391 synchronized (mLock) { 392 if (!mAppIdleParoled) { 393 final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; 394 if (timeSinceLastParole > mAppIdleParoleIntervalMillis) { 395 if (DEBUG) Slog.d(TAG, "Crossed default parole interval"); 396 setAppIdleParoled(true); 397 // Make sure it ends at some point 398 postParoleEndTimeout(); 399 } else { 400 if (DEBUG) Slog.d(TAG, "Not long enough to go to parole"); 401 postNextParoleTimeout(); 402 } 403 } 404 } 405 } 406 407 private void notifyBatteryStats(String packageName, int userId, boolean idle) { 408 try { 409 int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId); 410 if (idle) { 411 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE, 412 packageName, uid); 413 } else { 414 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE, 415 packageName, uid); 416 } 417 } catch (RemoteException re) { 418 } 419 } 420 421 void updateDisplayLocked() { 422 boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() 423 == Display.STATE_ON; 424 425 if (screenOn == mScreenOn) return; 426 427 mScreenOn = screenOn; 428 long now = System.currentTimeMillis(); 429 if (mScreenOn) { 430 mScreenOnSystemTimeSnapshot = now; 431 } else { 432 mScreenOnTime += now - mScreenOnSystemTimeSnapshot; 433 writeScreenOnTimeLocked(mScreenOnTime); 434 } 435 } 436 437 private long getScreenOnTimeLocked(long now) { 438 if (mScreenOn) { 439 return now - mScreenOnSystemTimeSnapshot + mScreenOnTime; 440 } else { 441 return mScreenOnTime; 442 } 443 } 444 445 private File getScreenOnTimeFile() { 446 return new File(mUsageStatsDir, UserHandle.USER_OWNER + "/screen_on_time"); 447 } 448 449 private long readScreenOnTimeLocked() { 450 long screenOnTime = 0; 451 File screenOnTimeFile = getScreenOnTimeFile(); 452 if (screenOnTimeFile.exists()) { 453 try { 454 BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile)); 455 screenOnTime = Long.parseLong(reader.readLine()); 456 reader.close(); 457 } catch (IOException | NumberFormatException e) { 458 } 459 } else { 460 writeScreenOnTimeLocked(screenOnTime); 461 } 462 return screenOnTime; 463 } 464 465 private void writeScreenOnTimeLocked(long screenOnTime) { 466 AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile()); 467 FileOutputStream fos = null; 468 try { 469 fos = screenOnTimeFile.startWrite(); 470 fos.write(Long.toString(screenOnTime).getBytes()); 471 screenOnTimeFile.finishWrite(fos); 472 } catch (IOException ioe) { 473 screenOnTimeFile.failWrite(fos); 474 } 475 } 476 477 void onDeviceIdleModeChanged() { 478 final boolean deviceIdle = mPowerManager.isDeviceIdleMode(); 479 if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle); 480 synchronized (mLock) { 481 final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; 482 if (!deviceIdle 483 && timeSinceLastParole >= mAppIdleParoleIntervalMillis) { 484 if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false"); 485 postNextParoleTimeout(); 486 setAppIdleParoled(true); 487 } else if (deviceIdle) { 488 if (DEBUG) Slog.i(TAG, "Device idle, back to prison"); 489 setAppIdleParoled(false); 490 } 491 } 492 } 493 494 private static void deleteRecursively(File f) { 495 File[] files = f.listFiles(); 496 if (files != null) { 497 for (File subFile : files) { 498 deleteRecursively(subFile); 499 } 500 } 501 502 if (!f.delete()) { 503 Slog.e(TAG, "Failed to delete " + f); 504 } 505 } 506 507 private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, 508 long currentTimeMillis) { 509 UserUsageStatsService service = mUserState.get(userId); 510 if (service == null) { 511 service = new UserUsageStatsService(getContext(), userId, 512 new File(mUsageStatsDir, Integer.toString(userId)), this); 513 service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis)); 514 mUserState.put(userId, service); 515 } 516 return service; 517 } 518 519 /** 520 * This should be the only way to get the time from the system. 521 */ 522 private long checkAndGetTimeLocked() { 523 final long actualSystemTime = System.currentTimeMillis(); 524 final long actualRealtime = SystemClock.elapsedRealtime(); 525 final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 526 boolean resetBeginIdleTime = false; 527 if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { 528 // The time has changed. 529 530 // Check if it's severe enough a change to reset screenOnTime 531 if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) { 532 mScreenOnSystemTimeSnapshot = actualSystemTime; 533 mScreenOnTime = 0; 534 resetBeginIdleTime = true; 535 } 536 final int userCount = mUserState.size(); 537 for (int i = 0; i < userCount; i++) { 538 final UserUsageStatsService service = mUserState.valueAt(i); 539 service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); 540 } 541 mRealTimeSnapshot = actualRealtime; 542 mSystemTimeSnapshot = actualSystemTime; 543 } 544 return actualSystemTime; 545 } 546 547 /** 548 * Assuming the event's timestamp is measured in milliseconds since boot, 549 * convert it to a system wall time. 550 */ 551 private void convertToSystemTimeLocked(UsageEvents.Event event) { 552 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 553 } 554 555 /** 556 * Called by the Binder stub 557 */ 558 void shutdown() { 559 synchronized (mLock) { 560 mHandler.removeMessages(MSG_REPORT_EVENT); 561 flushToDiskLocked(); 562 } 563 } 564 565 /** 566 * Called by the Binder stub. 567 */ 568 void reportEvent(UsageEvents.Event event, int userId) { 569 synchronized (mLock) { 570 final long timeNow = checkAndGetTimeLocked(); 571 final long screenOnTime = getScreenOnTimeLocked(timeNow); 572 convertToSystemTimeLocked(event); 573 574 final UserUsageStatsService service = 575 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 576 final long beginIdleTime = service.getBeginIdleTime(event.mPackage); 577 final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage); 578 final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, 579 lastUsedTime, screenOnTime, timeNow); 580 service.reportEvent(event, screenOnTime); 581 // Inform listeners if necessary 582 if ((event.mEventType == Event.MOVE_TO_FOREGROUND 583 || event.mEventType == Event.MOVE_TO_BACKGROUND 584 || event.mEventType == Event.SYSTEM_INTERACTION 585 || event.mEventType == Event.USER_INTERACTION)) { 586 if (previouslyIdle) { 587 // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); 588 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, 589 /* idle = */ 0, event.mPackage)); 590 notifyBatteryStats(event.mPackage, userId, false); 591 mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow); 592 } 593 } 594 } 595 } 596 597 void reportContentProviderUsage(String authority, String providerPkgName, int userId) { 598 // Get sync adapters for the authority 599 String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser( 600 authority, userId); 601 for (String packageName: packages) { 602 // Only force the sync adapters to active if the provider is not in the same package and 603 // the sync adapter is a system package. 604 try { 605 PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo( 606 packageName, 0, userId); 607 if (pi == null || pi.applicationInfo == null 608 || !pi.applicationInfo.isSystemApp()) { 609 continue; 610 } 611 if (!packageName.equals(providerPkgName)) { 612 forceIdleState(packageName, userId, false); 613 } 614 } catch (RemoteException re) { 615 // Shouldn't happen 616 } 617 } 618 } 619 620 /** 621 * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle, 622 * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind 623 * the threshold for idle. 624 */ 625 void forceIdleState(String packageName, int userId, boolean idle) { 626 synchronized (mLock) { 627 final long timeNow = checkAndGetTimeLocked(); 628 final long screenOnTime = getScreenOnTimeLocked(timeNow); 629 final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000; 630 631 final UserUsageStatsService service = 632 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 633 final long beginIdleTime = service.getBeginIdleTime(packageName); 634 final long lastUsedTime = service.getSystemLastUsedTime(packageName); 635 final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, 636 lastUsedTime, screenOnTime, timeNow); 637 service.setBeginIdleTime(packageName, deviceUsageTime); 638 service.setSystemLastUsedTime(packageName, 639 timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000); 640 // Inform listeners if necessary 641 if (previouslyIdle != idle) { 642 // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName); 643 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, 644 /* idle = */ idle ? 1 : 0, packageName)); 645 if (!idle) { 646 notifyBatteryStats(packageName, userId, idle); 647 } 648 mAppIdleHistory.addEntry(packageName, userId, idle, timeNow); 649 } 650 } 651 } 652 653 /** 654 * Called by the Binder stub. 655 */ 656 void flushToDisk() { 657 synchronized (mLock) { 658 flushToDiskLocked(); 659 } 660 } 661 662 /** 663 * Called by the Binder stub. 664 */ 665 void removeUser(int userId) { 666 synchronized (mLock) { 667 Slog.i(TAG, "Removing user " + userId + " and all data."); 668 mUserState.remove(userId); 669 cleanUpRemovedUsersLocked(); 670 } 671 } 672 673 /** 674 * Called by the Binder stub. 675 */ 676 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) { 677 synchronized (mLock) { 678 final long timeNow = checkAndGetTimeLocked(); 679 if (!validRange(timeNow, beginTime, endTime)) { 680 return null; 681 } 682 683 final UserUsageStatsService service = 684 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 685 return service.queryUsageStats(bucketType, beginTime, endTime); 686 } 687 } 688 689 /** 690 * Called by the Binder stub. 691 */ 692 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 693 long endTime) { 694 synchronized (mLock) { 695 final long timeNow = checkAndGetTimeLocked(); 696 if (!validRange(timeNow, beginTime, endTime)) { 697 return null; 698 } 699 700 final UserUsageStatsService service = 701 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 702 return service.queryConfigurationStats(bucketType, beginTime, endTime); 703 } 704 } 705 706 /** 707 * Called by the Binder stub. 708 */ 709 UsageEvents queryEvents(int userId, long beginTime, long endTime) { 710 synchronized (mLock) { 711 final long timeNow = checkAndGetTimeLocked(); 712 if (!validRange(timeNow, beginTime, endTime)) { 713 return null; 714 } 715 716 final UserUsageStatsService service = 717 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 718 return service.queryEvents(beginTime, endTime); 719 } 720 } 721 722 private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService, 723 long timeNow, long screenOnTime) { 724 synchronized (mLock) { 725 long beginIdleTime = userService.getBeginIdleTime(packageName); 726 long lastUsedTime = userService.getSystemLastUsedTime(packageName); 727 return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, 728 timeNow); 729 } 730 } 731 732 /** 733 * @param beginIdleTime when the app was last used in device usage timebase 734 * @param lastUsedTime wallclock time of when the app was last used 735 * @param screenOnTime screen-on timebase time 736 * @param currentTime current time in device usage timebase 737 * @return whether it's been used far enough in the past to be considered inactive 738 */ 739 boolean hasPassedIdleTimeoutLocked(long beginIdleTime, long lastUsedTime, 740 long screenOnTime, long currentTime) { 741 return (beginIdleTime <= screenOnTime - mAppIdleDurationMillis) 742 && (lastUsedTime <= currentTime - mAppIdleWallclockThresholdMillis); 743 } 744 745 void addListener(AppIdleStateChangeListener listener) { 746 synchronized (mLock) { 747 if (!mPackageAccessListeners.contains(listener)) { 748 mPackageAccessListeners.add(listener); 749 } 750 } 751 } 752 753 void removeListener(AppIdleStateChangeListener listener) { 754 synchronized (mLock) { 755 mPackageAccessListeners.remove(listener); 756 } 757 } 758 759 boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { 760 final UserUsageStatsService userService; 761 final long screenOnTime; 762 synchronized (mLock) { 763 if (timeNow == -1) { 764 timeNow = checkAndGetTimeLocked(); 765 } 766 userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); 767 screenOnTime = getScreenOnTimeLocked(timeNow); 768 } 769 return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime); 770 } 771 772 /** 773 * Checks if an app has been idle for a while and filters out apps that are excluded. 774 * It returns false if the current system state allows all apps to be considered active. 775 * This happens if the device is plugged in or temporarily allowed to make exceptions. 776 * Called by interface impls. 777 */ 778 private boolean isAppIdleFiltered(String packageName, int userId, 779 UserUsageStatsService userService, long timeNow, long screenOnTime) { 780 if (packageName == null) return false; 781 // If not enabled at all, of course nobody is ever idle. 782 if (!mAppIdleEnabled) { 783 return false; 784 } 785 synchronized (mLock) { 786 // Temporary exemption, probably due to device charging or occasional allowance to 787 // be allowed to sync, etc. 788 if (mAppIdleParoled) { 789 return false; 790 } 791 } 792 if (packageName.equals("android")) return false; 793 try { 794 if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) { 795 return false; 796 } 797 } catch (RemoteException re) { 798 } 799 // TODO: Optimize this check 800 if (isActiveDeviceAdmin(packageName, userId)) { 801 return false; 802 } 803 804 if (isCarrierApp(packageName)) { 805 return false; 806 } 807 808 if (mAppWidgetManager != null 809 && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) { 810 return false; 811 } 812 813 return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime); 814 } 815 816 void setAppIdle(String packageName, boolean idle, int userId) { 817 if (packageName == null) return; 818 819 mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName) 820 .sendToTarget(); 821 } 822 823 private boolean isActiveDeviceAdmin(String packageName, int userId) { 824 DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class); 825 if (dpm == null) return false; 826 List<ComponentName> components = dpm.getActiveAdminsAsUser(userId); 827 if (components == null) return false; 828 final int size = components.size(); 829 for (int i = 0; i < size; i++) { 830 if (components.get(i).getPackageName().equals(packageName)) { 831 return true; 832 } 833 } 834 return false; 835 } 836 837 private boolean isCarrierApp(String packageName) { 838 TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class); 839 return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) 840 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 841 } 842 843 void informListeners(String packageName, int userId, boolean isIdle) { 844 for (AppIdleStateChangeListener listener : mPackageAccessListeners) { 845 listener.onAppIdleStateChanged(packageName, userId, isIdle); 846 } 847 } 848 849 private static boolean validRange(long currentTime, long beginTime, long endTime) { 850 return beginTime <= currentTime && beginTime < endTime; 851 } 852 853 private void flushToDiskLocked() { 854 final int userCount = mUserState.size(); 855 for (int i = 0; i < userCount; i++) { 856 UserUsageStatsService service = mUserState.valueAt(i); 857 service.persistActiveStats(); 858 } 859 860 mHandler.removeMessages(MSG_FLUSH_TO_DISK); 861 } 862 863 /** 864 * Called by the Binder stub. 865 */ 866 void dump(String[] args, PrintWriter pw) { 867 synchronized (mLock) { 868 final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked()); 869 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 870 ArraySet<String> argSet = new ArraySet<>(); 871 argSet.addAll(Arrays.asList(args)); 872 873 final int userCount = mUserState.size(); 874 for (int i = 0; i < userCount; i++) { 875 idpw.printPair("user", mUserState.keyAt(i)); 876 idpw.println(); 877 idpw.increaseIndent(); 878 if (argSet.contains("--checkin")) { 879 mUserState.valueAt(i).checkin(idpw, screenOnTime); 880 } else { 881 mUserState.valueAt(i).dump(idpw, screenOnTime); 882 idpw.println(); 883 if (args.length > 0 && "history".equals(args[0])) { 884 mAppIdleHistory.dump(idpw, mUserState.keyAt(i)); 885 } 886 } 887 idpw.decreaseIndent(); 888 } 889 pw.println("Screen On Timebase:" + mScreenOnTime); 890 891 pw.println(); 892 pw.println("Settings:"); 893 894 pw.print(" mAppIdleDurationMillis="); 895 TimeUtils.formatDuration(mAppIdleDurationMillis, pw); 896 pw.println(); 897 898 pw.print(" mAppIdleWallclockThresholdMillis="); 899 TimeUtils.formatDuration(mAppIdleWallclockThresholdMillis, pw); 900 pw.println(); 901 902 pw.print(" mCheckIdleIntervalMillis="); 903 TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw); 904 pw.println(); 905 906 pw.print(" mAppIdleParoleIntervalMillis="); 907 TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw); 908 pw.println(); 909 910 pw.print(" mAppIdleParoleDurationMillis="); 911 TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw); 912 pw.println(); 913 914 pw.println(); 915 pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled); 916 pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled); 917 pw.print(" mScreenOn="); pw.println(mScreenOn); 918 pw.print("mLastAppIdleParoledTime="); 919 TimeUtils.formatDuration(mLastAppIdleParoledTime, pw); 920 pw.println(); 921 pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw); 922 pw.println(); 923 pw.print("mScreenOnSystemTimeSnapshot="); 924 TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw); 925 pw.println(); 926 } 927 } 928 929 class H extends Handler { 930 public H(Looper looper) { 931 super(looper); 932 } 933 934 @Override 935 public void handleMessage(Message msg) { 936 switch (msg.what) { 937 case MSG_REPORT_EVENT: 938 reportEvent((UsageEvents.Event) msg.obj, msg.arg1); 939 break; 940 941 case MSG_FLUSH_TO_DISK: 942 flushToDisk(); 943 break; 944 945 case MSG_REMOVE_USER: 946 removeUser(msg.arg1); 947 break; 948 949 case MSG_INFORM_LISTENERS: 950 informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1); 951 break; 952 953 case MSG_FORCE_IDLE_STATE: 954 forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1); 955 break; 956 957 case MSG_CHECK_IDLE_STATES: 958 checkIdleStates(msg.arg1); 959 break; 960 961 case MSG_CHECK_PAROLE_TIMEOUT: 962 checkParoleTimeout(); 963 break; 964 965 case MSG_PAROLE_END_TIMEOUT: 966 if (DEBUG) Slog.d(TAG, "Ending parole"); 967 setAppIdleParoled(false); 968 break; 969 970 case MSG_REPORT_CONTENT_PROVIDER_USAGE: 971 SomeArgs args = (SomeArgs) msg.obj; 972 reportContentProviderUsage((String) args.arg1, // authority name 973 (String) args.arg2, // package name 974 (int) args.arg3); // userId 975 args.recycle(); 976 break; 977 978 default: 979 super.handleMessage(msg); 980 break; 981 } 982 } 983 } 984 985 /** 986 * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}. 987 */ 988 private class SettingsObserver extends ContentObserver { 989 private static final String KEY_IDLE_DURATION = "idle_duration"; 990 private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold"; 991 private static final String KEY_PAROLE_INTERVAL = "parole_interval"; 992 private static final String KEY_PAROLE_DURATION = "parole_duration"; 993 994 private final KeyValueListParser mParser = new KeyValueListParser(','); 995 996 SettingsObserver(Handler handler) { 997 super(handler); 998 } 999 1000 void registerObserver() { 1001 getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor( 1002 Settings.Global.APP_IDLE_CONSTANTS), false, this); 1003 } 1004 1005 @Override 1006 public void onChange(boolean selfChange) { 1007 updateSettings(); 1008 postCheckIdleStates(UserHandle.USER_ALL); 1009 } 1010 1011 void updateSettings() { 1012 synchronized (mLock) { 1013 // Look at global settings for this. 1014 // TODO: Maybe apply different thresholds for different users. 1015 try { 1016 mParser.setString(Settings.Global.getString(getContext().getContentResolver(), 1017 Settings.Global.APP_IDLE_CONSTANTS)); 1018 } catch (IllegalArgumentException e) { 1019 Slog.e(TAG, "Bad value for app idle settings: " + e.getMessage()); 1020 // fallthrough, mParser is empty and all defaults will be returned. 1021 } 1022 1023 // Default: 12 hours of screen-on time sans dream-time 1024 mAppIdleDurationMillis = mParser.getLong(KEY_IDLE_DURATION, 1025 COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE); 1026 1027 mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD, 1028 COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days 1029 1030 mCheckIdleIntervalMillis = Math.min(mAppIdleDurationMillis / 4, 1031 COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours 1032 1033 // Default: 24 hours between paroles 1034 mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL, 1035 COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE); 1036 1037 mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION, 1038 COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes 1039 } 1040 } 1041 } 1042 1043 private final class BinderService extends IUsageStatsManager.Stub { 1044 1045 private boolean hasPermission(String callingPackage) { 1046 final int callingUid = Binder.getCallingUid(); 1047 if (callingUid == Process.SYSTEM_UID) { 1048 return true; 1049 } 1050 final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, 1051 callingUid, callingPackage); 1052 if (mode == AppOpsManager.MODE_DEFAULT) { 1053 // The default behavior here is to check if PackageManager has given the app 1054 // permission. 1055 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 1056 == PackageManager.PERMISSION_GRANTED; 1057 } 1058 return mode == AppOpsManager.MODE_ALLOWED; 1059 } 1060 1061 @Override 1062 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 1063 long endTime, String callingPackage) { 1064 if (!hasPermission(callingPackage)) { 1065 return null; 1066 } 1067 1068 final int userId = UserHandle.getCallingUserId(); 1069 final long token = Binder.clearCallingIdentity(); 1070 try { 1071 final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 1072 userId, bucketType, beginTime, endTime); 1073 if (results != null) { 1074 return new ParceledListSlice<>(results); 1075 } 1076 } finally { 1077 Binder.restoreCallingIdentity(token); 1078 } 1079 return null; 1080 } 1081 1082 @Override 1083 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 1084 long beginTime, long endTime, String callingPackage) throws RemoteException { 1085 if (!hasPermission(callingPackage)) { 1086 return null; 1087 } 1088 1089 final int userId = UserHandle.getCallingUserId(); 1090 final long token = Binder.clearCallingIdentity(); 1091 try { 1092 final List<ConfigurationStats> results = 1093 UsageStatsService.this.queryConfigurationStats(userId, bucketType, 1094 beginTime, endTime); 1095 if (results != null) { 1096 return new ParceledListSlice<>(results); 1097 } 1098 } finally { 1099 Binder.restoreCallingIdentity(token); 1100 } 1101 return null; 1102 } 1103 1104 @Override 1105 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 1106 if (!hasPermission(callingPackage)) { 1107 return null; 1108 } 1109 1110 final int userId = UserHandle.getCallingUserId(); 1111 final long token = Binder.clearCallingIdentity(); 1112 try { 1113 return UsageStatsService.this.queryEvents(userId, beginTime, endTime); 1114 } finally { 1115 Binder.restoreCallingIdentity(token); 1116 } 1117 } 1118 1119 @Override 1120 public boolean isAppInactive(String packageName, int userId) { 1121 try { 1122 userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(), 1123 Binder.getCallingUid(), userId, false, true, "isAppInactive", null); 1124 } catch (RemoteException re) { 1125 return false; 1126 } 1127 final long token = Binder.clearCallingIdentity(); 1128 try { 1129 return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); 1130 } finally { 1131 Binder.restoreCallingIdentity(token); 1132 } 1133 } 1134 1135 @Override 1136 public void setAppInactive(String packageName, boolean idle, int userId) { 1137 final int callingUid = Binder.getCallingUid(); 1138 try { 1139 userId = ActivityManagerNative.getDefault().handleIncomingUser( 1140 Binder.getCallingPid(), callingUid, userId, false, true, 1141 "setAppIdle", null); 1142 } catch (RemoteException re) { 1143 return; 1144 } 1145 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1146 "No permission to change app idle state"); 1147 final long token = Binder.clearCallingIdentity(); 1148 try { 1149 PackageInfo pi = AppGlobals.getPackageManager() 1150 .getPackageInfo(packageName, 0, userId); 1151 if (pi == null) return; 1152 UsageStatsService.this.setAppIdle(packageName, idle, userId); 1153 } catch (RemoteException re) { 1154 } finally { 1155 Binder.restoreCallingIdentity(token); 1156 } 1157 } 1158 1159 @Override 1160 public void whitelistAppTemporarily(String packageName, long duration, int userId) 1161 throws RemoteException { 1162 mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId); 1163 } 1164 1165 @Override 1166 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1167 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1168 != PackageManager.PERMISSION_GRANTED) { 1169 pw.println("Permission Denial: can't dump UsageStats from pid=" 1170 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1171 + " without permission " + android.Manifest.permission.DUMP); 1172 return; 1173 } 1174 UsageStatsService.this.dump(args, pw); 1175 } 1176 } 1177 1178 /** 1179 * This local service implementation is primarily used by ActivityManagerService. 1180 * ActivityManagerService will call these methods holding the 'am' lock, which means we 1181 * shouldn't be doing any IO work or other long running tasks in these methods. 1182 */ 1183 private final class LocalService extends UsageStatsManagerInternal { 1184 1185 @Override 1186 public void reportEvent(ComponentName component, int userId, int eventType) { 1187 if (component == null) { 1188 Slog.w(TAG, "Event reported without a component name"); 1189 return; 1190 } 1191 1192 UsageEvents.Event event = new UsageEvents.Event(); 1193 event.mPackage = component.getPackageName(); 1194 event.mClass = component.getClassName(); 1195 1196 // This will later be converted to system time. 1197 event.mTimeStamp = SystemClock.elapsedRealtime(); 1198 1199 event.mEventType = eventType; 1200 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1201 } 1202 1203 @Override 1204 public void reportEvent(String packageName, int userId, int eventType) { 1205 if (packageName == null) { 1206 Slog.w(TAG, "Event reported without a package name"); 1207 return; 1208 } 1209 1210 UsageEvents.Event event = new UsageEvents.Event(); 1211 event.mPackage = packageName; 1212 1213 // This will later be converted to system time. 1214 event.mTimeStamp = SystemClock.elapsedRealtime(); 1215 1216 event.mEventType = eventType; 1217 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1218 } 1219 1220 @Override 1221 public void reportConfigurationChange(Configuration config, int userId) { 1222 if (config == null) { 1223 Slog.w(TAG, "Configuration event reported with a null config"); 1224 return; 1225 } 1226 1227 UsageEvents.Event event = new UsageEvents.Event(); 1228 event.mPackage = "android"; 1229 1230 // This will later be converted to system time. 1231 event.mTimeStamp = SystemClock.elapsedRealtime(); 1232 1233 event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; 1234 event.mConfiguration = new Configuration(config); 1235 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1236 } 1237 1238 @Override 1239 public void reportContentProviderUsage(String name, String packageName, int userId) { 1240 SomeArgs args = SomeArgs.obtain(); 1241 args.arg1 = name; 1242 args.arg2 = packageName; 1243 args.arg3 = userId; 1244 mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args) 1245 .sendToTarget(); 1246 } 1247 1248 @Override 1249 public boolean isAppIdle(String packageName, int userId) { 1250 return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); 1251 } 1252 1253 @Override 1254 public void prepareShutdown() { 1255 // This method *WILL* do IO work, but we must block until it is finished or else 1256 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 1257 // we are shutting down. 1258 shutdown(); 1259 } 1260 1261 @Override 1262 public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { 1263 UsageStatsService.this.addListener(listener); 1264 } 1265 1266 @Override 1267 public void removeAppIdleStateChangeListener( 1268 AppIdleStateChangeListener listener) { 1269 UsageStatsService.this.removeListener(listener); 1270 } 1271 } 1272} 1273