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