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 mLastAppIdleParoledTime = checkAndGetTimeLocked(); 318 postNextParoleTimeout(); 319 } 320 postParoleStateChanged(); 321 } 322 } 323 } 324 325 private void postNextParoleTimeout() { 326 if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT"); 327 mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT); 328 // Compute when the next parole needs to happen. We check more frequently than necessary 329 // since the message handler delays are based on elapsedRealTime and not wallclock time. 330 // The comparison is done in wallclock time. 331 long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) 332 - checkAndGetTimeLocked(); 333 if (timeLeft < 0) { 334 timeLeft = 0; 335 } 336 mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10); 337 } 338 339 private void postParoleEndTimeout() { 340 if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT"); 341 mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT); 342 mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis); 343 } 344 345 private void postParoleStateChanged() { 346 if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED"); 347 mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED); 348 mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED); 349 } 350 351 void postCheckIdleStates(int userId) { 352 mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0)); 353 } 354 355 /** Check all running users' or specified user's apps to see if they enter an idle state. */ 356 void checkIdleStates(int checkUserId) { 357 if (!mAppIdleEnabled) { 358 return; 359 } 360 361 final int[] userIds; 362 try { 363 if (checkUserId == UserHandle.USER_ALL) { 364 userIds = ActivityManagerNative.getDefault().getRunningUserIds(); 365 } else { 366 userIds = new int[] { checkUserId }; 367 } 368 } catch (RemoteException re) { 369 return; 370 } 371 372 for (int i = 0; i < userIds.length; i++) { 373 final int userId = userIds[i]; 374 List<PackageInfo> packages = 375 getContext().getPackageManager().getInstalledPackages( 376 PackageManager.GET_DISABLED_COMPONENTS 377 | PackageManager.GET_UNINSTALLED_PACKAGES, 378 userId); 379 synchronized (mLock) { 380 final long timeNow = checkAndGetTimeLocked(); 381 final long screenOnTime = getScreenOnTimeLocked(timeNow); 382 UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId, 383 timeNow); 384 final int packageCount = packages.size(); 385 for (int p = 0; p < packageCount; p++) { 386 final String packageName = packages.get(p).packageName; 387 final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow, 388 screenOnTime); 389 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, 390 userId, isIdle ? 1 : 0, packageName)); 391 mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow); 392 } 393 } 394 } 395 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0), 396 mCheckIdleIntervalMillis); 397 } 398 399 /** Check if it's been a while since last parole and let idle apps do some work */ 400 void checkParoleTimeout() { 401 synchronized (mLock) { 402 if (!mAppIdleParoled) { 403 final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime; 404 if (timeSinceLastParole > mAppIdleParoleIntervalMillis) { 405 if (DEBUG) Slog.d(TAG, "Crossed default parole interval"); 406 setAppIdleParoled(true); 407 // Make sure it ends at some point 408 postParoleEndTimeout(); 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 postNextParoleTimeout(); 496 setAppIdleParoled(true); 497 } else if (deviceIdle) { 498 if (DEBUG) Slog.i(TAG, "Device idle, back to prison"); 499 setAppIdleParoled(false); 500 } 501 } 502 } 503 504 private static void deleteRecursively(File f) { 505 File[] files = f.listFiles(); 506 if (files != null) { 507 for (File subFile : files) { 508 deleteRecursively(subFile); 509 } 510 } 511 512 if (!f.delete()) { 513 Slog.e(TAG, "Failed to delete " + f); 514 } 515 } 516 517 private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, 518 long currentTimeMillis) { 519 UserUsageStatsService service = mUserState.get(userId); 520 if (service == null) { 521 service = new UserUsageStatsService(getContext(), userId, 522 new File(mUsageStatsDir, Integer.toString(userId)), this); 523 service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis)); 524 mUserState.put(userId, service); 525 } 526 return service; 527 } 528 529 /** 530 * This should be the only way to get the time from the system. 531 */ 532 private long checkAndGetTimeLocked() { 533 final long actualSystemTime = System.currentTimeMillis(); 534 final long actualRealtime = SystemClock.elapsedRealtime(); 535 final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 536 boolean resetBeginIdleTime = false; 537 if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { 538 // The time has changed. 539 540 // Check if it's severe enough a change to reset screenOnTime 541 if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) { 542 mScreenOnSystemTimeSnapshot = actualSystemTime; 543 mScreenOnTime = 0; 544 resetBeginIdleTime = true; 545 } 546 final int userCount = mUserState.size(); 547 for (int i = 0; i < userCount; i++) { 548 final UserUsageStatsService service = mUserState.valueAt(i); 549 service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime); 550 } 551 mRealTimeSnapshot = actualRealtime; 552 mSystemTimeSnapshot = actualSystemTime; 553 } 554 return actualSystemTime; 555 } 556 557 /** 558 * Assuming the event's timestamp is measured in milliseconds since boot, 559 * convert it to a system wall time. 560 */ 561 private void convertToSystemTimeLocked(UsageEvents.Event event) { 562 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 563 } 564 565 /** 566 * Called by the Binder stub 567 */ 568 void shutdown() { 569 synchronized (mLock) { 570 mHandler.removeMessages(MSG_REPORT_EVENT); 571 flushToDiskLocked(); 572 } 573 } 574 575 /** 576 * Called by the Binder stub. 577 */ 578 void reportEvent(UsageEvents.Event event, int userId) { 579 synchronized (mLock) { 580 final long timeNow = checkAndGetTimeLocked(); 581 final long screenOnTime = getScreenOnTimeLocked(timeNow); 582 convertToSystemTimeLocked(event); 583 584 final UserUsageStatsService service = 585 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 586 final long beginIdleTime = service.getBeginIdleTime(event.mPackage); 587 final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage); 588 final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, 589 lastUsedTime, screenOnTime, timeNow); 590 service.reportEvent(event, screenOnTime); 591 // Inform listeners if necessary 592 if ((event.mEventType == Event.MOVE_TO_FOREGROUND 593 || event.mEventType == Event.MOVE_TO_BACKGROUND 594 || event.mEventType == Event.SYSTEM_INTERACTION 595 || event.mEventType == Event.USER_INTERACTION)) { 596 if (previouslyIdle) { 597 // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage); 598 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, 599 /* idle = */ 0, event.mPackage)); 600 notifyBatteryStats(event.mPackage, userId, false); 601 mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow); 602 } 603 } 604 } 605 } 606 607 void reportContentProviderUsage(String authority, String providerPkgName, int userId) { 608 // Get sync adapters for the authority 609 String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser( 610 authority, userId); 611 for (String packageName: packages) { 612 // Only force the sync adapters to active if the provider is not in the same package and 613 // the sync adapter is a system package. 614 try { 615 PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo( 616 packageName, 0, userId); 617 if (pi == null || pi.applicationInfo == null 618 || !pi.applicationInfo.isSystemApp()) { 619 continue; 620 } 621 if (!packageName.equals(providerPkgName)) { 622 forceIdleState(packageName, userId, false); 623 } 624 } catch (RemoteException re) { 625 // Shouldn't happen 626 } 627 } 628 } 629 630 /** 631 * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle, 632 * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind 633 * the threshold for idle. 634 */ 635 void forceIdleState(String packageName, int userId, boolean idle) { 636 synchronized (mLock) { 637 final long timeNow = checkAndGetTimeLocked(); 638 final long screenOnTime = getScreenOnTimeLocked(timeNow); 639 final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000; 640 641 final UserUsageStatsService service = 642 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 643 final long beginIdleTime = service.getBeginIdleTime(packageName); 644 final long lastUsedTime = service.getSystemLastUsedTime(packageName); 645 final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime, 646 lastUsedTime, screenOnTime, timeNow); 647 service.setBeginIdleTime(packageName, deviceUsageTime); 648 service.setSystemLastUsedTime(packageName, 649 timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000); 650 // Inform listeners if necessary 651 if (previouslyIdle != idle) { 652 // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName); 653 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId, 654 /* idle = */ idle ? 1 : 0, packageName)); 655 if (!idle) { 656 notifyBatteryStats(packageName, userId, idle); 657 } 658 mAppIdleHistory.addEntry(packageName, userId, idle, timeNow); 659 } 660 } 661 } 662 663 /** 664 * Called by the Binder stub. 665 */ 666 void flushToDisk() { 667 synchronized (mLock) { 668 flushToDiskLocked(); 669 } 670 } 671 672 /** 673 * Called by the Binder stub. 674 */ 675 void removeUser(int userId) { 676 synchronized (mLock) { 677 Slog.i(TAG, "Removing user " + userId + " and all data."); 678 mUserState.remove(userId); 679 cleanUpRemovedUsersLocked(); 680 } 681 } 682 683 /** 684 * Called by the Binder stub. 685 */ 686 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) { 687 synchronized (mLock) { 688 final long timeNow = checkAndGetTimeLocked(); 689 if (!validRange(timeNow, beginTime, endTime)) { 690 return null; 691 } 692 693 final UserUsageStatsService service = 694 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 695 return service.queryUsageStats(bucketType, beginTime, endTime); 696 } 697 } 698 699 /** 700 * Called by the Binder stub. 701 */ 702 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 703 long endTime) { 704 synchronized (mLock) { 705 final long timeNow = checkAndGetTimeLocked(); 706 if (!validRange(timeNow, beginTime, endTime)) { 707 return null; 708 } 709 710 final UserUsageStatsService service = 711 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 712 return service.queryConfigurationStats(bucketType, beginTime, endTime); 713 } 714 } 715 716 /** 717 * Called by the Binder stub. 718 */ 719 UsageEvents queryEvents(int userId, long beginTime, long endTime) { 720 synchronized (mLock) { 721 final long timeNow = checkAndGetTimeLocked(); 722 if (!validRange(timeNow, beginTime, endTime)) { 723 return null; 724 } 725 726 final UserUsageStatsService service = 727 getUserDataAndInitializeIfNeededLocked(userId, timeNow); 728 return service.queryEvents(beginTime, endTime); 729 } 730 } 731 732 private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService, 733 long timeNow, long screenOnTime) { 734 synchronized (mLock) { 735 long beginIdleTime = userService.getBeginIdleTime(packageName); 736 long lastUsedTime = userService.getSystemLastUsedTime(packageName); 737 return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, 738 timeNow); 739 } 740 } 741 742 /** 743 * @param beginIdleTime when the app was last used in device usage timebase 744 * @param lastUsedTime wallclock time of when the app was last used 745 * @param screenOnTime screen-on timebase time 746 * @param currentTime current time in device usage timebase 747 * @return whether it's been used far enough in the past to be considered inactive 748 */ 749 boolean hasPassedIdleTimeoutLocked(long beginIdleTime, long lastUsedTime, 750 long screenOnTime, long currentTime) { 751 return (beginIdleTime <= screenOnTime - mAppIdleDurationMillis) 752 && (lastUsedTime <= currentTime - mAppIdleWallclockThresholdMillis); 753 } 754 755 void addListener(AppIdleStateChangeListener listener) { 756 synchronized (mLock) { 757 if (!mPackageAccessListeners.contains(listener)) { 758 mPackageAccessListeners.add(listener); 759 } 760 } 761 } 762 763 void removeListener(AppIdleStateChangeListener listener) { 764 synchronized (mLock) { 765 mPackageAccessListeners.remove(listener); 766 } 767 } 768 769 boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) { 770 if (mAppIdleParoled) { 771 return false; 772 } 773 return isAppIdleFiltered(packageName, userId, timeNow); 774 } 775 776 boolean isAppIdleFiltered(String packageName, int userId, long timeNow) { 777 final UserUsageStatsService userService; 778 final long screenOnTime; 779 synchronized (mLock) { 780 if (timeNow == -1) { 781 timeNow = checkAndGetTimeLocked(); 782 } 783 userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); 784 screenOnTime = getScreenOnTimeLocked(timeNow); 785 } 786 return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime); 787 } 788 789 /** 790 * Checks if an app has been idle for a while and filters out apps that are excluded. 791 * It returns false if the current system state allows all apps to be considered active. 792 * This happens if the device is plugged in or temporarily allowed to make exceptions. 793 * Called by interface impls. 794 */ 795 private boolean isAppIdleFiltered(String packageName, int userId, 796 UserUsageStatsService userService, long timeNow, long screenOnTime) { 797 if (packageName == null) return false; 798 // If not enabled at all, of course nobody is ever idle. 799 if (!mAppIdleEnabled) { 800 return false; 801 } 802 if (packageName.equals("android")) return false; 803 try { 804 // We allow all whitelisted apps, including those that don't want to be whitelisted 805 // for idle mode, because app idle (aka app standby) is really not as big an issue 806 // for controlling who participates vs. doze mode. 807 if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) { 808 return false; 809 } 810 } catch (RemoteException re) { 811 } 812 // TODO: Optimize this check 813 if (isActiveDeviceAdmin(packageName, userId)) { 814 return false; 815 } 816 817 if (isCarrierApp(packageName)) { 818 return false; 819 } 820 821 if (isActiveNetworkScorer(packageName)) { 822 return false; 823 } 824 825 if (mAppWidgetManager != null 826 && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) { 827 return false; 828 } 829 830 return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime); 831 } 832 833 int[] getIdleUidsForUser(int userId) { 834 if (!mAppIdleEnabled) { 835 return new int[0]; 836 } 837 838 final long timeNow; 839 final UserUsageStatsService userService; 840 final long screenOnTime; 841 synchronized (mLock) { 842 timeNow = checkAndGetTimeLocked(); 843 userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow); 844 screenOnTime = getScreenOnTimeLocked(timeNow); 845 } 846 847 List<ApplicationInfo> apps; 848 try { 849 ParceledListSlice<ApplicationInfo> slice 850 = AppGlobals.getPackageManager().getInstalledApplications(0, userId); 851 if (slice == null) { 852 return new int[0]; 853 } 854 apps = slice.getList(); 855 } catch (RemoteException e) { 856 return new int[0]; 857 } 858 859 // State of each uid. Key is the uid. Value lower 16 bits is the number of apps 860 // associated with that uid, upper 16 bits is the number of those apps that is idle. 861 SparseIntArray uidStates = new SparseIntArray(); 862 863 // Now resolve all app state. Iterating over all apps, keeping track of how many 864 // we find for each uid and how many of those are idle. 865 for (int i = apps.size()-1; i >= 0; i--) { 866 ApplicationInfo ai = apps.get(i); 867 868 // Check whether this app is idle. 869 boolean idle = isAppIdleFiltered(ai.packageName, userId, userService, timeNow, 870 screenOnTime); 871 872 int index = uidStates.indexOfKey(ai.uid); 873 if (index < 0) { 874 uidStates.put(ai.uid, 1 + (idle ? 1<<16 : 0)); 875 } else { 876 int value = uidStates.valueAt(index); 877 uidStates.setValueAt(index, value + 1 + (idle ? 1<<16 : 0)); 878 } 879 } 880 881 int numIdle = 0; 882 for (int i = uidStates.size() - 1; i >= 0; i--) { 883 int value = uidStates.valueAt(i); 884 if ((value&0x7fff) == (value>>16)) { 885 numIdle++; 886 } 887 } 888 889 int[] res = new int[numIdle]; 890 numIdle = 0; 891 for (int i = uidStates.size() - 1; i >= 0; i--) { 892 int value = uidStates.valueAt(i); 893 if ((value&0x7fff) == (value>>16)) { 894 res[numIdle] = uidStates.keyAt(i); 895 numIdle++; 896 } 897 } 898 899 return res; 900 } 901 902 void setAppIdle(String packageName, boolean idle, int userId) { 903 if (packageName == null) return; 904 905 mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName) 906 .sendToTarget(); 907 } 908 909 private boolean isActiveDeviceAdmin(String packageName, int userId) { 910 DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class); 911 if (dpm == null) return false; 912 List<ComponentName> components = dpm.getActiveAdminsAsUser(userId); 913 if (components == null) return false; 914 final int size = components.size(); 915 for (int i = 0; i < size; i++) { 916 if (components.get(i).getPackageName().equals(packageName)) { 917 return true; 918 } 919 } 920 return false; 921 } 922 923 private boolean isCarrierApp(String packageName) { 924 TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class); 925 return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName) 926 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 927 } 928 929 private boolean isActiveNetworkScorer(String packageName) { 930 NetworkScoreManager nsm = (NetworkScoreManager) getContext().getSystemService( 931 Context.NETWORK_SCORE_SERVICE); 932 return packageName != null && packageName.equals(nsm.getActiveScorerPackage()); 933 } 934 935 void informListeners(String packageName, int userId, boolean isIdle) { 936 for (AppIdleStateChangeListener listener : mPackageAccessListeners) { 937 listener.onAppIdleStateChanged(packageName, userId, isIdle); 938 } 939 } 940 941 void informParoleStateChanged() { 942 for (AppIdleStateChangeListener listener : mPackageAccessListeners) { 943 listener.onParoleStateChanged(mAppIdleParoled); 944 } 945 } 946 947 private static boolean validRange(long currentTime, long beginTime, long endTime) { 948 return beginTime <= currentTime && beginTime < endTime; 949 } 950 951 private void flushToDiskLocked() { 952 final int userCount = mUserState.size(); 953 for (int i = 0; i < userCount; i++) { 954 UserUsageStatsService service = mUserState.valueAt(i); 955 service.persistActiveStats(); 956 } 957 958 mHandler.removeMessages(MSG_FLUSH_TO_DISK); 959 } 960 961 /** 962 * Called by the Binder stub. 963 */ 964 void dump(String[] args, PrintWriter pw) { 965 synchronized (mLock) { 966 final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked()); 967 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 968 ArraySet<String> argSet = new ArraySet<>(); 969 argSet.addAll(Arrays.asList(args)); 970 971 final int userCount = mUserState.size(); 972 for (int i = 0; i < userCount; i++) { 973 idpw.printPair("user", mUserState.keyAt(i)); 974 idpw.println(); 975 idpw.increaseIndent(); 976 if (argSet.contains("--checkin")) { 977 mUserState.valueAt(i).checkin(idpw, screenOnTime); 978 } else { 979 mUserState.valueAt(i).dump(idpw, screenOnTime); 980 idpw.println(); 981 if (args.length > 0 && "history".equals(args[0])) { 982 mAppIdleHistory.dump(idpw, mUserState.keyAt(i)); 983 } 984 } 985 idpw.decreaseIndent(); 986 } 987 pw.println("Screen On Timebase:" + mScreenOnTime); 988 989 pw.println(); 990 pw.println("Settings:"); 991 992 pw.print(" mAppIdleDurationMillis="); 993 TimeUtils.formatDuration(mAppIdleDurationMillis, pw); 994 pw.println(); 995 996 pw.print(" mAppIdleWallclockThresholdMillis="); 997 TimeUtils.formatDuration(mAppIdleWallclockThresholdMillis, pw); 998 pw.println(); 999 1000 pw.print(" mCheckIdleIntervalMillis="); 1001 TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw); 1002 pw.println(); 1003 1004 pw.print(" mAppIdleParoleIntervalMillis="); 1005 TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw); 1006 pw.println(); 1007 1008 pw.print(" mAppIdleParoleDurationMillis="); 1009 TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw); 1010 pw.println(); 1011 1012 pw.println(); 1013 pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled); 1014 pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled); 1015 pw.print(" mScreenOn="); pw.println(mScreenOn); 1016 pw.print("mLastAppIdleParoledTime="); 1017 TimeUtils.formatDuration(mLastAppIdleParoledTime, pw); 1018 pw.println(); 1019 pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw); 1020 pw.println(); 1021 pw.print("mScreenOnSystemTimeSnapshot="); 1022 TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw); 1023 pw.println(); 1024 } 1025 } 1026 1027 class H extends Handler { 1028 public H(Looper looper) { 1029 super(looper); 1030 } 1031 1032 @Override 1033 public void handleMessage(Message msg) { 1034 switch (msg.what) { 1035 case MSG_REPORT_EVENT: 1036 reportEvent((UsageEvents.Event) msg.obj, msg.arg1); 1037 break; 1038 1039 case MSG_FLUSH_TO_DISK: 1040 flushToDisk(); 1041 break; 1042 1043 case MSG_REMOVE_USER: 1044 removeUser(msg.arg1); 1045 break; 1046 1047 case MSG_INFORM_LISTENERS: 1048 informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1); 1049 break; 1050 1051 case MSG_FORCE_IDLE_STATE: 1052 forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1); 1053 break; 1054 1055 case MSG_CHECK_IDLE_STATES: 1056 checkIdleStates(msg.arg1); 1057 break; 1058 1059 case MSG_CHECK_PAROLE_TIMEOUT: 1060 checkParoleTimeout(); 1061 break; 1062 1063 case MSG_PAROLE_END_TIMEOUT: 1064 if (DEBUG) Slog.d(TAG, "Ending parole"); 1065 setAppIdleParoled(false); 1066 break; 1067 1068 case MSG_REPORT_CONTENT_PROVIDER_USAGE: 1069 SomeArgs args = (SomeArgs) msg.obj; 1070 reportContentProviderUsage((String) args.arg1, // authority name 1071 (String) args.arg2, // package name 1072 (int) args.arg3); // userId 1073 args.recycle(); 1074 break; 1075 1076 case MSG_PAROLE_STATE_CHANGED: 1077 if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled); 1078 informParoleStateChanged(); 1079 break; 1080 1081 default: 1082 super.handleMessage(msg); 1083 break; 1084 } 1085 } 1086 } 1087 1088 /** 1089 * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}. 1090 */ 1091 private class SettingsObserver extends ContentObserver { 1092 private static final String KEY_IDLE_DURATION = "idle_duration"; 1093 private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold"; 1094 private static final String KEY_PAROLE_INTERVAL = "parole_interval"; 1095 private static final String KEY_PAROLE_DURATION = "parole_duration"; 1096 1097 private final KeyValueListParser mParser = new KeyValueListParser(','); 1098 1099 SettingsObserver(Handler handler) { 1100 super(handler); 1101 } 1102 1103 void registerObserver() { 1104 getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor( 1105 Settings.Global.APP_IDLE_CONSTANTS), false, this); 1106 } 1107 1108 @Override 1109 public void onChange(boolean selfChange) { 1110 updateSettings(); 1111 postCheckIdleStates(UserHandle.USER_ALL); 1112 } 1113 1114 void updateSettings() { 1115 synchronized (mLock) { 1116 // Look at global settings for this. 1117 // TODO: Maybe apply different thresholds for different users. 1118 try { 1119 mParser.setString(Settings.Global.getString(getContext().getContentResolver(), 1120 Settings.Global.APP_IDLE_CONSTANTS)); 1121 } catch (IllegalArgumentException e) { 1122 Slog.e(TAG, "Bad value for app idle settings: " + e.getMessage()); 1123 // fallthrough, mParser is empty and all defaults will be returned. 1124 } 1125 1126 // Default: 12 hours of screen-on time sans dream-time 1127 mAppIdleDurationMillis = mParser.getLong(KEY_IDLE_DURATION, 1128 COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE); 1129 1130 mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD, 1131 COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days 1132 1133 mCheckIdleIntervalMillis = Math.min(mAppIdleDurationMillis / 4, 1134 COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours 1135 1136 // Default: 24 hours between paroles 1137 mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL, 1138 COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE); 1139 1140 mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION, 1141 COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes 1142 } 1143 } 1144 } 1145 1146 private final class BinderService extends IUsageStatsManager.Stub { 1147 1148 private boolean hasPermission(String callingPackage) { 1149 final int callingUid = Binder.getCallingUid(); 1150 if (callingUid == Process.SYSTEM_UID) { 1151 return true; 1152 } 1153 final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, 1154 callingUid, callingPackage); 1155 if (mode == AppOpsManager.MODE_DEFAULT) { 1156 // The default behavior here is to check if PackageManager has given the app 1157 // permission. 1158 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 1159 == PackageManager.PERMISSION_GRANTED; 1160 } 1161 return mode == AppOpsManager.MODE_ALLOWED; 1162 } 1163 1164 @Override 1165 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 1166 long endTime, String callingPackage) { 1167 if (!hasPermission(callingPackage)) { 1168 return null; 1169 } 1170 1171 final int userId = UserHandle.getCallingUserId(); 1172 final long token = Binder.clearCallingIdentity(); 1173 try { 1174 final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 1175 userId, bucketType, beginTime, endTime); 1176 if (results != null) { 1177 return new ParceledListSlice<>(results); 1178 } 1179 } finally { 1180 Binder.restoreCallingIdentity(token); 1181 } 1182 return null; 1183 } 1184 1185 @Override 1186 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 1187 long beginTime, long endTime, String callingPackage) throws RemoteException { 1188 if (!hasPermission(callingPackage)) { 1189 return null; 1190 } 1191 1192 final int userId = UserHandle.getCallingUserId(); 1193 final long token = Binder.clearCallingIdentity(); 1194 try { 1195 final List<ConfigurationStats> results = 1196 UsageStatsService.this.queryConfigurationStats(userId, bucketType, 1197 beginTime, endTime); 1198 if (results != null) { 1199 return new ParceledListSlice<>(results); 1200 } 1201 } finally { 1202 Binder.restoreCallingIdentity(token); 1203 } 1204 return null; 1205 } 1206 1207 @Override 1208 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 1209 if (!hasPermission(callingPackage)) { 1210 return null; 1211 } 1212 1213 final int userId = UserHandle.getCallingUserId(); 1214 final long token = Binder.clearCallingIdentity(); 1215 try { 1216 return UsageStatsService.this.queryEvents(userId, beginTime, endTime); 1217 } finally { 1218 Binder.restoreCallingIdentity(token); 1219 } 1220 } 1221 1222 @Override 1223 public boolean isAppInactive(String packageName, int userId) { 1224 try { 1225 userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(), 1226 Binder.getCallingUid(), userId, false, true, "isAppInactive", null); 1227 } catch (RemoteException re) { 1228 return false; 1229 } 1230 final long token = Binder.clearCallingIdentity(); 1231 try { 1232 return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1); 1233 } finally { 1234 Binder.restoreCallingIdentity(token); 1235 } 1236 } 1237 1238 @Override 1239 public void setAppInactive(String packageName, boolean idle, int userId) { 1240 final int callingUid = Binder.getCallingUid(); 1241 try { 1242 userId = ActivityManagerNative.getDefault().handleIncomingUser( 1243 Binder.getCallingPid(), callingUid, userId, false, true, 1244 "setAppIdle", null); 1245 } catch (RemoteException re) { 1246 return; 1247 } 1248 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE, 1249 "No permission to change app idle state"); 1250 final long token = Binder.clearCallingIdentity(); 1251 try { 1252 PackageInfo pi = AppGlobals.getPackageManager() 1253 .getPackageInfo(packageName, 0, userId); 1254 if (pi == null) return; 1255 UsageStatsService.this.setAppIdle(packageName, idle, userId); 1256 } catch (RemoteException re) { 1257 } finally { 1258 Binder.restoreCallingIdentity(token); 1259 } 1260 } 1261 1262 @Override 1263 public void whitelistAppTemporarily(String packageName, long duration, int userId) 1264 throws RemoteException { 1265 StringBuilder reason = new StringBuilder(32); 1266 reason.append("from:"); 1267 UserHandle.formatUid(reason, Binder.getCallingUid()); 1268 mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId, 1269 reason.toString()); 1270 } 1271 1272 @Override 1273 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1274 if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1275 != PackageManager.PERMISSION_GRANTED) { 1276 pw.println("Permission Denial: can't dump UsageStats from pid=" 1277 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 1278 + " without permission " + android.Manifest.permission.DUMP); 1279 return; 1280 } 1281 UsageStatsService.this.dump(args, pw); 1282 } 1283 } 1284 1285 /** 1286 * This local service implementation is primarily used by ActivityManagerService. 1287 * ActivityManagerService will call these methods holding the 'am' lock, which means we 1288 * shouldn't be doing any IO work or other long running tasks in these methods. 1289 */ 1290 private final class LocalService extends UsageStatsManagerInternal { 1291 1292 @Override 1293 public void reportEvent(ComponentName component, int userId, int eventType) { 1294 if (component == null) { 1295 Slog.w(TAG, "Event reported without a component name"); 1296 return; 1297 } 1298 1299 UsageEvents.Event event = new UsageEvents.Event(); 1300 event.mPackage = component.getPackageName(); 1301 event.mClass = component.getClassName(); 1302 1303 // This will later be converted to system time. 1304 event.mTimeStamp = SystemClock.elapsedRealtime(); 1305 1306 event.mEventType = eventType; 1307 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1308 } 1309 1310 @Override 1311 public void reportEvent(String packageName, int userId, int eventType) { 1312 if (packageName == null) { 1313 Slog.w(TAG, "Event reported without a package name"); 1314 return; 1315 } 1316 1317 UsageEvents.Event event = new UsageEvents.Event(); 1318 event.mPackage = packageName; 1319 1320 // This will later be converted to system time. 1321 event.mTimeStamp = SystemClock.elapsedRealtime(); 1322 1323 event.mEventType = eventType; 1324 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1325 } 1326 1327 @Override 1328 public void reportConfigurationChange(Configuration config, int userId) { 1329 if (config == null) { 1330 Slog.w(TAG, "Configuration event reported with a null config"); 1331 return; 1332 } 1333 1334 UsageEvents.Event event = new UsageEvents.Event(); 1335 event.mPackage = "android"; 1336 1337 // This will later be converted to system time. 1338 event.mTimeStamp = SystemClock.elapsedRealtime(); 1339 1340 event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; 1341 event.mConfiguration = new Configuration(config); 1342 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 1343 } 1344 1345 @Override 1346 public void reportContentProviderUsage(String name, String packageName, int userId) { 1347 SomeArgs args = SomeArgs.obtain(); 1348 args.arg1 = name; 1349 args.arg2 = packageName; 1350 args.arg3 = userId; 1351 mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args) 1352 .sendToTarget(); 1353 } 1354 1355 @Override 1356 public boolean isAppIdle(String packageName, int userId) { 1357 return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1); 1358 } 1359 1360 @Override 1361 public int[] getIdleUidsForUser(int userId) { 1362 return UsageStatsService.this.getIdleUidsForUser(userId); 1363 } 1364 1365 @Override 1366 public boolean isAppIdleParoleOn() { 1367 return mAppIdleParoled; 1368 } 1369 1370 @Override 1371 public void prepareShutdown() { 1372 // This method *WILL* do IO work, but we must block until it is finished or else 1373 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 1374 // we are shutting down. 1375 shutdown(); 1376 } 1377 1378 @Override 1379 public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { 1380 UsageStatsService.this.addListener(listener); 1381 listener.onParoleStateChanged(isAppIdleParoleOn()); 1382 } 1383 1384 @Override 1385 public void removeAppIdleStateChangeListener( 1386 AppIdleStateChangeListener listener) { 1387 UsageStatsService.this.removeListener(listener); 1388 } 1389 } 1390} 1391