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