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