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