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