2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.server.usage;
19 import android.Manifest;
20 import android.app.ActivityManager;
21 import android.app.AppOpsManager;
22 import android.app.IUidObserver;
23 import android.app.PendingIntent;
24 import android.app.admin.DeviceAdminInfo;
25 import android.app.admin.DevicePolicyManagerInternal;
26 import android.app.usage.AppStandbyInfo;
27 import android.app.usage.ConfigurationStats;
28 import android.app.usage.EventStats;
29 import android.app.usage.IUsageStatsManager;
30 import android.app.usage.UsageEvents;
31 import android.app.usage.UsageStatsManager;
32 import android.app.usage.UsageStatsManager.StandbyBuckets;
33 import android.app.usage.UsageEvents.Event;
34 import android.app.usage.UsageStats;
35 import android.app.usage.UsageStatsManagerInternal;
36 import android.content.BroadcastReceiver;
37 import android.content.ComponentName;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.IntentFilter;
41 import android.content.pm.PackageManager;
42 import android.content.pm.PackageManagerInternal;
43 import android.content.pm.ParceledListSlice;
44 import android.content.pm.UserInfo;
45 import android.content.res.Configuration;
46 import android.os.Binder;
47 import android.os.Environment;
48 import android.os.FileUtils;
49 import android.os.Handler;
50 import android.os.IDeviceIdleController;
51 import android.os.Looper;
52 import android.os.Message;
53 import android.os.Process;
54 import android.os.RemoteException;
55 import android.os.ServiceManager;
56 import android.os.SystemClock;
57 import android.os.SystemProperties;
58 import android.os.UserHandle;
59 import android.os.UserManager;
60 import android.util.ArraySet;
61 import android.util.Slog;
62 import android.util.SparseArray;
63 import android.util.SparseIntArray;
65 import com.android.internal.os.BackgroundThread;
66 import com.android.internal.util.DumpUtils;
67 import com.android.internal.util.IndentingPrintWriter;
68 import com.android.server.LocalServices;
69 import com.android.server.SystemService;
72 import java.io.FileDescriptor;
73 import java.io.IOException;
74 import java.io.PrintWriter;
75 import java.util.Arrays;
76 import java.util.List;
79 import java.util.concurrent.TimeUnit;
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.
85 public class UsageStatsService extends SystemService implements
86 UserUsageStatsService.StatsUpdatedListener {
88 static final String TAG = "UsageStatsService";
89 public static final boolean ENABLE_TIME_CHANGE_CORRECTION
90 = SystemProperties.getBoolean("persist.debug.time_correction", true);
92 static final boolean DEBUG = false; // Never submit with true
93 static final boolean COMPRESS_TIME = false;
95 private static final long TEN_SECONDS = 10 * 1000;
96 private static final long TWENTY_MINUTES = 20 * 60 * 1000;
97 private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
98 private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
100 private static final boolean ENABLE_KERNEL_UPDATES = true;
101 private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
103 // Handler message types.
104 static final int MSG_REPORT_EVENT = 0;
105 static final int MSG_FLUSH_TO_DISK = 1;
106 static final int MSG_REMOVE_USER = 2;
107 static final int MSG_UID_STATE_CHANGED = 3;
109 private final Object mLock = new Object();
111 AppOpsManager mAppOps;
112 UserManager mUserManager;
113 PackageManager mPackageManager;
114 PackageManagerInternal mPackageManagerInternal;
115 IDeviceIdleController mDeviceIdleController;
116 DevicePolicyManagerInternal mDpmInternal;
118 private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
119 private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
120 private File mUsageStatsDir;
121 long mRealTimeSnapshot;
122 long mSystemTimeSnapshot;
124 /** Manages the standby state of apps. */
125 AppStandbyController mAppStandby;
127 /** Manages app time limit observers */
128 AppTimeLimitController mAppTimeLimit;
130 private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
131 new UsageStatsManagerInternal.AppIdleStateChangeListener() {
133 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
134 int bucket, int reason) {
135 Event event = new Event();
136 event.mEventType = Event.STANDBY_BUCKET_CHANGED;
137 event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF);
138 event.mPackage = packageName;
139 // This will later be converted to system time.
140 event.mTimeStamp = SystemClock.elapsedRealtime();
141 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
145 public void onParoleStateChanged(boolean isParoleOn) {
150 public UsageStatsService(Context context) {
155 public void onStart() {
156 mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
157 mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
158 mPackageManager = getContext().getPackageManager();
159 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
160 mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
161 mHandler = new H(BackgroundThread.get().getLooper());
163 mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
165 mAppTimeLimit = new AppTimeLimitController(
166 (observerId, userId, timeLimit, timeElapsed, callbackIntent) -> {
167 Intent intent = new Intent();
168 intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
169 intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
170 intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
172 callbackIntent.send(getContext(), 0, intent);
173 } catch (PendingIntent.CanceledException e) {
174 Slog.w(TAG, "Couldn't deliver callback: "
177 }, mHandler.getLooper());
179 mAppStandby.addListener(mStandbyChangeListener);
180 File systemDataDir = new File(Environment.getDataDirectory(), "system");
181 mUsageStatsDir = new File(systemDataDir, "usagestats");
182 mUsageStatsDir.mkdirs();
183 if (!mUsageStatsDir.exists()) {
184 throw new IllegalStateException("Usage stats directory does not exist: "
185 + mUsageStatsDir.getAbsolutePath());
188 IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
189 filter.addAction(Intent.ACTION_USER_STARTED);
190 getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
193 synchronized (mLock) {
194 cleanUpRemovedUsersLocked();
197 mRealTimeSnapshot = SystemClock.elapsedRealtime();
198 mSystemTimeSnapshot = System.currentTimeMillis();
200 publishLocalService(UsageStatsManagerInternal.class, new LocalService());
201 publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
202 // Make sure we initialize the data, in case job scheduler needs it early.
203 getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot);
207 public void onBootPhase(int phase) {
208 if (phase == PHASE_SYSTEM_SERVICES_READY) {
209 mAppStandby.onBootPhase(phase);
211 mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
212 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
214 if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
216 ActivityManager.getService().registerUidObserver(mUidObserver,
217 ActivityManager.UID_OBSERVER_PROCSTATE
218 | ActivityManager.UID_OBSERVER_GONE,
219 ActivityManager.PROCESS_STATE_UNKNOWN, null);
220 } catch (RemoteException e) {
221 throw new RuntimeException(e);
224 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE);
229 private class UserActionsReceiver extends BroadcastReceiver {
231 public void onReceive(Context context, Intent intent) {
232 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
233 final String action = intent.getAction();
234 if (Intent.ACTION_USER_REMOVED.equals(action)) {
236 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
238 } else if (Intent.ACTION_USER_STARTED.equals(action)) {
240 mAppStandby.postCheckIdleStates(userId);
246 private final IUidObserver mUidObserver = new IUidObserver.Stub() {
248 public void onUidStateChanged(int uid, int procState, long procStateSeq) {
249 mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
253 public void onUidIdle(int uid, boolean disabled) {
258 public void onUidGone(int uid, boolean disabled) {
259 onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
263 public void onUidActive(int uid) {
267 @Override public void onUidCachedChanged(int uid, boolean cached) {
272 public void onStatsUpdated() {
273 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
277 public void onStatsReloaded() {
278 mAppStandby.postOneTimeCheckIdleStates();
282 public void onNewUpdate(int userId) {
283 mAppStandby.initializeDefaultsForSystemApps(userId);
286 private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
287 return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
290 private void cleanUpRemovedUsersLocked() {
291 final List<UserInfo> users = mUserManager.getUsers(true);
292 if (users == null || users.size() == 0) {
293 throw new IllegalStateException("There can't be no users");
296 ArraySet<String> toDelete = new ArraySet<>();
297 String[] fileNames = mUsageStatsDir.list();
298 if (fileNames == null) {
299 // No users to delete.
303 toDelete.addAll(Arrays.asList(fileNames));
305 final int userCount = users.size();
306 for (int i = 0; i < userCount; i++) {
307 final UserInfo userInfo = users.get(i);
308 toDelete.remove(Integer.toString(userInfo.id));
311 final int deleteCount = toDelete.size();
312 for (int i = 0; i < deleteCount; i++) {
313 deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
317 private static void deleteRecursively(File f) {
318 File[] files = f.listFiles();
320 for (File subFile : files) {
321 deleteRecursively(subFile);
326 Slog.e(TAG, "Failed to delete " + f);
330 private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
331 long currentTimeMillis) {
332 UserUsageStatsService service = mUserState.get(userId);
333 if (service == null) {
334 service = new UserUsageStatsService(getContext(), userId,
335 new File(mUsageStatsDir, Integer.toString(userId)), this);
336 service.init(currentTimeMillis);
337 mUserState.put(userId, service);
343 * This should be the only way to get the time from the system.
345 private long checkAndGetTimeLocked() {
346 final long actualSystemTime = System.currentTimeMillis();
347 final long actualRealtime = SystemClock.elapsedRealtime();
348 final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
349 final long diffSystemTime = actualSystemTime - expectedSystemTime;
350 if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS
351 && ENABLE_TIME_CHANGE_CORRECTION) {
352 // The time has changed.
353 Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
354 final int userCount = mUserState.size();
355 for (int i = 0; i < userCount; i++) {
356 final UserUsageStatsService service = mUserState.valueAt(i);
357 service.onTimeChanged(expectedSystemTime, actualSystemTime);
359 mRealTimeSnapshot = actualRealtime;
360 mSystemTimeSnapshot = actualSystemTime;
362 return actualSystemTime;
366 * Assuming the event's timestamp is measured in milliseconds since boot,
367 * convert it to a system wall time.
369 private void convertToSystemTimeLocked(UsageEvents.Event event) {
370 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
374 * Called by the Binder stub
377 synchronized (mLock) {
378 mHandler.removeMessages(MSG_REPORT_EVENT);
384 * Called by the Binder stub.
386 void reportEvent(UsageEvents.Event event, int userId) {
387 synchronized (mLock) {
388 final long timeNow = checkAndGetTimeLocked();
389 final long elapsedRealtime = SystemClock.elapsedRealtime();
390 convertToSystemTimeLocked(event);
392 if (event.getPackageName() != null
393 && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
394 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
397 final UserUsageStatsService service =
398 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
399 service.reportEvent(event);
401 mAppStandby.reportEvent(event, elapsedRealtime, userId);
402 switch (event.mEventType) {
403 case Event.MOVE_TO_FOREGROUND:
404 mAppTimeLimit.moveToForeground(event.getPackageName(), event.getClassName(),
407 case Event.MOVE_TO_BACKGROUND:
408 mAppTimeLimit.moveToBackground(event.getPackageName(), event.getClassName(),
416 * Called by the Binder stub.
419 synchronized (mLock) {
425 * Called by the Binder stub.
427 void onUserRemoved(int userId) {
428 synchronized (mLock) {
429 Slog.i(TAG, "Removing user " + userId + " and all data.");
430 mUserState.remove(userId);
431 mAppStandby.onUserRemoved(userId);
432 mAppTimeLimit.onUserRemoved(userId);
433 cleanUpRemovedUsersLocked();
438 * Called by the Binder stub.
440 List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
441 boolean obfuscateInstantApps) {
442 synchronized (mLock) {
443 final long timeNow = checkAndGetTimeLocked();
444 if (!validRange(timeNow, beginTime, endTime)) {
448 final UserUsageStatsService service =
449 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
450 List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
455 // Mangle instant app names *using their current state (not whether they were ephemeral
456 // when the data was recorded)*.
457 if (obfuscateInstantApps) {
458 for (int i = list.size() - 1; i >= 0; i--) {
459 final UsageStats stats = list.get(i);
460 if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
461 list.set(i, stats.getObfuscatedForInstantApp());
471 * Called by the Binder stub.
473 List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
475 synchronized (mLock) {
476 final long timeNow = checkAndGetTimeLocked();
477 if (!validRange(timeNow, beginTime, endTime)) {
481 final UserUsageStatsService service =
482 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
483 return service.queryConfigurationStats(bucketType, beginTime, endTime);
488 * Called by the Binder stub.
490 List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
492 synchronized (mLock) {
493 final long timeNow = checkAndGetTimeLocked();
494 if (!validRange(timeNow, beginTime, endTime)) {
498 final UserUsageStatsService service =
499 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
500 return service.queryEventStats(bucketType, beginTime, endTime);
505 * Called by the Binder stub.
507 UsageEvents queryEvents(int userId, long beginTime, long endTime,
508 boolean shouldObfuscateInstantApps) {
509 synchronized (mLock) {
510 final long timeNow = checkAndGetTimeLocked();
511 if (!validRange(timeNow, beginTime, endTime)) {
515 final UserUsageStatsService service =
516 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
517 return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
522 * Called by the Binder stub.
524 UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
525 String packageName) {
526 synchronized (mLock) {
527 final long timeNow = checkAndGetTimeLocked();
528 if (!validRange(timeNow, beginTime, endTime)) {
532 final UserUsageStatsService service =
533 getUserDataAndInitializeIfNeededLocked(userId, timeNow);
534 return service.queryEventsForPackage(beginTime, endTime, packageName);
538 private static boolean validRange(long currentTime, long beginTime, long endTime) {
539 return beginTime <= currentTime && beginTime < endTime;
542 private void flushToDiskLocked() {
543 final int userCount = mUserState.size();
544 for (int i = 0; i < userCount; i++) {
545 UserUsageStatsService service = mUserState.valueAt(i);
546 service.persistActiveStats();
547 mAppStandby.flushToDisk(mUserState.keyAt(i));
549 mAppStandby.flushDurationsToDisk();
551 mHandler.removeMessages(MSG_FLUSH_TO_DISK);
555 * Called by the Binder stub.
557 void dump(String[] args, PrintWriter pw) {
558 synchronized (mLock) {
559 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " ");
561 boolean checkin = false;
562 boolean compact = false;
566 for (int i = 0; i < args.length; i++) {
567 String arg = args[i];
568 if ("--checkin".equals(arg)) {
571 if ("-c".equals(arg)) {
573 } else if ("flush".equals(arg)) {
575 pw.println("Flushed stats to disk");
577 } else if (arg != null && !arg.startsWith("-")) {
578 // Anything else that doesn't start with '-' is a pkg to filter
585 final int userCount = mUserState.size();
586 for (int i = 0; i < userCount; i++) {
587 int userId = mUserState.keyAt(i);
588 idpw.printPair("user", userId);
590 idpw.increaseIndent();
592 mUserState.valueAt(i).checkin(idpw);
594 mUserState.valueAt(i).dump(idpw, pkg, compact);
597 mAppStandby.dumpUser(idpw, userId, pkg);
598 idpw.decreaseIndent();
603 mAppStandby.dumpState(args, pw);
606 mAppTimeLimit.dump(pw);
610 class H extends Handler {
611 public H(Looper looper) {
616 public void handleMessage(Message msg) {
618 case MSG_REPORT_EVENT:
619 reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
622 case MSG_FLUSH_TO_DISK:
626 case MSG_REMOVE_USER:
627 onUserRemoved(msg.arg1);
630 case MSG_UID_STATE_CHANGED: {
631 final int uid = msg.arg1;
632 final int procState = msg.arg2;
634 final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
635 synchronized (mUidToKernelCounter) {
636 final int oldCounter = mUidToKernelCounter.get(uid, 0);
637 if (newCounter != oldCounter) {
638 mUidToKernelCounter.put(uid, newCounter);
640 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter);
641 } catch (IOException e) {
642 Slog.w(TAG, "Failed to update counter set: " + e);
650 super.handleMessage(msg);
656 private final class BinderService extends IUsageStatsManager.Stub {
658 private boolean hasPermission(String callingPackage) {
659 final int callingUid = Binder.getCallingUid();
660 if (callingUid == Process.SYSTEM_UID) {
663 final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
664 callingUid, callingPackage);
665 if (mode == AppOpsManager.MODE_DEFAULT) {
666 // The default behavior here is to check if PackageManager has given the app
668 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
669 == PackageManager.PERMISSION_GRANTED;
671 return mode == AppOpsManager.MODE_ALLOWED;
674 private boolean hasObserverPermission(String callingPackage) {
675 final int callingUid = Binder.getCallingUid();
676 if (callingUid == Process.SYSTEM_UID
677 || (mDpmInternal != null
678 && mDpmInternal.isActiveAdminWithPolicy(callingUid,
679 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER))) {
680 // Caller is the system or the profile owner, so proceed.
683 return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE)
684 == PackageManager.PERMISSION_GRANTED;
688 public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
689 long endTime, String callingPackage) {
690 if (!hasPermission(callingPackage)) {
694 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
695 Binder.getCallingUid(), UserHandle.getCallingUserId());
697 final int userId = UserHandle.getCallingUserId();
698 final long token = Binder.clearCallingIdentity();
700 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
701 userId, bucketType, beginTime, endTime, obfuscateInstantApps);
702 if (results != null) {
703 return new ParceledListSlice<>(results);
706 Binder.restoreCallingIdentity(token);
712 public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
713 long beginTime, long endTime, String callingPackage) throws RemoteException {
714 if (!hasPermission(callingPackage)) {
718 final int userId = UserHandle.getCallingUserId();
719 final long token = Binder.clearCallingIdentity();
721 final List<ConfigurationStats> results =
722 UsageStatsService.this.queryConfigurationStats(userId, bucketType,
724 if (results != null) {
725 return new ParceledListSlice<>(results);
728 Binder.restoreCallingIdentity(token);
734 public ParceledListSlice<EventStats> queryEventStats(int bucketType,
735 long beginTime, long endTime, String callingPackage) throws RemoteException {
736 if (!hasPermission(callingPackage)) {
740 final int userId = UserHandle.getCallingUserId();
741 final long token = Binder.clearCallingIdentity();
743 final List<EventStats> results =
744 UsageStatsService.this.queryEventStats(userId, bucketType,
746 if (results != null) {
747 return new ParceledListSlice<>(results);
750 Binder.restoreCallingIdentity(token);
756 public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
757 if (!hasPermission(callingPackage)) {
761 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
762 Binder.getCallingUid(), UserHandle.getCallingUserId());
764 final int userId = UserHandle.getCallingUserId();
765 final long token = Binder.clearCallingIdentity();
767 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
768 obfuscateInstantApps);
770 Binder.restoreCallingIdentity(token);
775 public UsageEvents queryEventsForPackage(long beginTime, long endTime,
776 String callingPackage) {
777 final int callingUid = Binder.getCallingUid();
778 final int callingUserId = UserHandle.getUserId(callingUid);
780 if (mPackageManagerInternal.getPackageUid(callingPackage, PackageManager.MATCH_ANY_USER,
781 callingUserId) != callingUid) {
782 throw new SecurityException("Calling uid " + callingPackage + " cannot query events"
783 + "for package " + callingPackage);
785 final long token = Binder.clearCallingIdentity();
787 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
788 endTime, callingPackage);
790 Binder.restoreCallingIdentity(token);
795 public boolean isAppInactive(String packageName, int userId) {
797 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
798 Binder.getCallingUid(), userId, false, false, "isAppInactive", null);
799 } catch (RemoteException re) {
800 throw re.rethrowFromSystemServer();
802 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
803 Binder.getCallingUid(), userId);
804 final long token = Binder.clearCallingIdentity();
806 return mAppStandby.isAppIdleFilteredOrParoled(
808 SystemClock.elapsedRealtime(), obfuscateInstantApps);
810 Binder.restoreCallingIdentity(token);
815 public void setAppInactive(String packageName, boolean idle, int userId) {
816 final int callingUid = Binder.getCallingUid();
818 userId = ActivityManager.getService().handleIncomingUser(
819 Binder.getCallingPid(), callingUid, userId, false, true,
820 "setAppInactive", null);
821 } catch (RemoteException re) {
822 throw re.rethrowFromSystemServer();
824 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
825 "No permission to change app idle state");
826 final long token = Binder.clearCallingIdentity();
828 final int appId = mAppStandby.getAppId(packageName);
829 if (appId < 0) return;
830 mAppStandby.setAppIdleAsync(packageName, idle, userId);
832 Binder.restoreCallingIdentity(token);
837 public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
838 final int callingUid = Binder.getCallingUid();
840 userId = ActivityManager.getService().handleIncomingUser(
841 Binder.getCallingPid(), callingUid, userId, false, false,
842 "getAppStandbyBucket", null);
843 } catch (RemoteException re) {
844 throw re.rethrowFromSystemServer();
846 // If the calling app is asking about itself, continue, else check for permission.
847 if (mPackageManagerInternal.getPackageUid(packageName, PackageManager.MATCH_ANY_USER,
848 userId) != callingUid) {
849 if (!hasPermission(callingPackage)) {
850 throw new SecurityException(
851 "Don't have permission to query app standby bucket");
854 final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
856 final long token = Binder.clearCallingIdentity();
858 return mAppStandby.getAppStandbyBucket(packageName, userId,
859 SystemClock.elapsedRealtime(), obfuscateInstantApps);
861 Binder.restoreCallingIdentity(token);
866 public void setAppStandbyBucket(String packageName,
867 int bucket, int userId) {
868 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
869 "No permission to change app standby state");
871 if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
872 || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
873 throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
875 final int callingUid = Binder.getCallingUid();
877 userId = ActivityManager.getService().handleIncomingUser(
878 Binder.getCallingPid(), callingUid, userId, false, true,
879 "setAppStandbyBucket", null);
880 } catch (RemoteException re) {
881 throw re.rethrowFromSystemServer();
883 final boolean systemCaller = UserHandle.isCore(callingUid);
884 final int reason = systemCaller
885 ? UsageStatsManager.REASON_MAIN_FORCED
886 : UsageStatsManager.REASON_MAIN_PREDICTED;
887 final long token = Binder.clearCallingIdentity();
889 // Caller cannot set their own standby state
890 if (mPackageManagerInternal.getPackageUid(packageName,
891 PackageManager.MATCH_ANY_USER, userId) == callingUid) {
892 throw new IllegalArgumentException("Cannot set your own standby bucket");
894 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
895 SystemClock.elapsedRealtime());
897 Binder.restoreCallingIdentity(token);
902 public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName,
904 final int callingUid = Binder.getCallingUid();
906 userId = ActivityManager.getService().handleIncomingUser(
907 Binder.getCallingPid(), callingUid, userId, false, false,
908 "getAppStandbyBucket", null);
909 } catch (RemoteException re) {
910 throw re.rethrowFromSystemServer();
912 if (!hasPermission(callingPackageName)) {
913 throw new SecurityException(
914 "Don't have permission to query app standby bucket");
916 final long token = Binder.clearCallingIdentity();
918 final List<AppStandbyInfo> standbyBucketList =
919 mAppStandby.getAppStandbyBuckets(userId);
920 return (standbyBucketList == null) ? ParceledListSlice.emptyList()
921 : new ParceledListSlice<>(standbyBucketList);
923 Binder.restoreCallingIdentity(token);
928 public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) {
929 getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
930 "No permission to change app standby state");
932 final int callingUid = Binder.getCallingUid();
934 userId = ActivityManager.getService().handleIncomingUser(
935 Binder.getCallingPid(), callingUid, userId, false, true,
936 "setAppStandbyBucket", null);
937 } catch (RemoteException re) {
938 throw re.rethrowFromSystemServer();
940 final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
941 final int reason = shellCaller
942 ? UsageStatsManager.REASON_MAIN_FORCED
943 : UsageStatsManager.REASON_MAIN_PREDICTED;
944 final long token = Binder.clearCallingIdentity();
946 final long elapsedRealtime = SystemClock.elapsedRealtime();
947 List<AppStandbyInfo> bucketList = appBuckets.getList();
948 for (AppStandbyInfo bucketInfo : bucketList) {
949 final String packageName = bucketInfo.mPackageName;
950 final int bucket = bucketInfo.mStandbyBucket;
951 if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
952 || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
953 throw new IllegalArgumentException(
954 "Cannot set the standby bucket to " + bucket);
956 // Caller cannot set their own standby state
957 if (mPackageManagerInternal.getPackageUid(packageName,
958 PackageManager.MATCH_ANY_USER, userId) == callingUid) {
959 throw new IllegalArgumentException("Cannot set your own standby bucket");
961 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
965 Binder.restoreCallingIdentity(token);
970 public void whitelistAppTemporarily(String packageName, long duration, int userId)
971 throws RemoteException {
972 StringBuilder reason = new StringBuilder(32);
973 reason.append("from:");
974 UserHandle.formatUid(reason, Binder.getCallingUid());
975 mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
980 public void onCarrierPrivilegedAppsChanged() {
982 Slog.i(TAG, "Carrier privileged apps changed");
984 getContext().enforceCallingOrSelfPermission(
985 android.Manifest.permission.BIND_CARRIER_SERVICES,
986 "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
987 mAppStandby.clearCarrierPrivilegedApps();
991 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
992 if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
993 UsageStatsService.this.dump(args, pw);
997 public void reportChooserSelection(String packageName, int userId, String contentType,
998 String[] annotations, String action) {
999 if (packageName == null) {
1000 Slog.w(TAG, "Event report user selecting a null package");
1004 UsageEvents.Event event = new UsageEvents.Event();
1005 event.mPackage = packageName;
1007 // This will later be converted to system time.
1008 event.mTimeStamp = SystemClock.elapsedRealtime();
1010 event.mEventType = Event.CHOOSER_ACTION;
1012 event.mAction = action;
1014 event.mContentType = contentType;
1016 event.mContentAnnotations = annotations;
1018 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1022 public void registerAppUsageObserver(int observerId,
1023 String[] packages, long timeLimitMs, PendingIntent
1024 callbackIntent, String callingPackage) {
1025 if (!hasObserverPermission(callingPackage)) {
1026 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1029 if (packages == null || packages.length == 0) {
1030 throw new IllegalArgumentException("Must specify at least one package");
1032 if (timeLimitMs <= 0) {
1033 throw new IllegalArgumentException("Time limit must be > 0");
1035 if (callbackIntent == null) {
1036 throw new NullPointerException("callbackIntent can't be null");
1038 final int callingUid = Binder.getCallingUid();
1039 final int userId = UserHandle.getUserId(callingUid);
1040 final long token = Binder.clearCallingIdentity();
1042 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId,
1043 packages, timeLimitMs, callbackIntent, userId);
1045 Binder.restoreCallingIdentity(token);
1050 public void unregisterAppUsageObserver(int observerId, String callingPackage) {
1051 if (!hasObserverPermission(callingPackage)) {
1052 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1055 final int callingUid = Binder.getCallingUid();
1056 final int userId = UserHandle.getUserId(callingUid);
1057 final long token = Binder.clearCallingIdentity();
1059 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId);
1061 Binder.restoreCallingIdentity(token);
1066 void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
1067 long timeLimitMs, PendingIntent callbackIntent, int userId) {
1068 mAppTimeLimit.addObserver(callingUid, observerId, packages, timeLimitMs, callbackIntent,
1072 void unregisterAppUsageObserver(int callingUid, int observerId, int userId) {
1073 mAppTimeLimit.removeObserver(callingUid, observerId, userId);
1077 * This local service implementation is primarily used by ActivityManagerService.
1078 * ActivityManagerService will call these methods holding the 'am' lock, which means we
1079 * shouldn't be doing any IO work or other long running tasks in these methods.
1081 private final class LocalService extends UsageStatsManagerInternal {
1084 public void reportEvent(ComponentName component, int userId, int eventType) {
1085 if (component == null) {
1086 Slog.w(TAG, "Event reported without a component name");
1090 UsageEvents.Event event = new UsageEvents.Event();
1091 event.mPackage = component.getPackageName();
1092 event.mClass = component.getClassName();
1094 // This will later be converted to system time.
1095 event.mTimeStamp = SystemClock.elapsedRealtime();
1097 event.mEventType = eventType;
1098 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1102 public void reportEvent(String packageName, int userId, int eventType) {
1103 if (packageName == null) {
1104 Slog.w(TAG, "Event reported without a package name");
1108 UsageEvents.Event event = new UsageEvents.Event();
1109 event.mPackage = packageName;
1111 // This will later be converted to system time.
1112 event.mTimeStamp = SystemClock.elapsedRealtime();
1114 event.mEventType = eventType;
1115 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1119 public void reportConfigurationChange(Configuration config, int userId) {
1120 if (config == null) {
1121 Slog.w(TAG, "Configuration event reported with a null config");
1125 UsageEvents.Event event = new UsageEvents.Event();
1126 event.mPackage = "android";
1128 // This will later be converted to system time.
1129 event.mTimeStamp = SystemClock.elapsedRealtime();
1131 event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
1132 event.mConfiguration = new Configuration(config);
1133 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1137 public void reportInterruptiveNotification(String packageName, String channelId,
1139 if (packageName == null || channelId == null) {
1140 Slog.w(TAG, "Event reported without a package name or a channel ID");
1144 UsageEvents.Event event = new UsageEvents.Event();
1145 event.mPackage = packageName.intern();
1146 event.mNotificationChannelId = channelId.intern();
1148 // This will later be converted to system time.
1149 event.mTimeStamp = SystemClock.elapsedRealtime();
1151 event.mEventType = Event.NOTIFICATION_INTERRUPTION;
1152 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1156 public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
1157 if (packageName == null || shortcutId == null) {
1158 Slog.w(TAG, "Event reported without a package name or a shortcut ID");
1162 UsageEvents.Event event = new UsageEvents.Event();
1163 event.mPackage = packageName.intern();
1164 event.mShortcutId = shortcutId.intern();
1166 // This will later be converted to system time.
1167 event.mTimeStamp = SystemClock.elapsedRealtime();
1169 event.mEventType = Event.SHORTCUT_INVOCATION;
1170 mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1174 public void reportContentProviderUsage(String name, String packageName, int userId) {
1175 mAppStandby.postReportContentProviderUsage(name, packageName, userId);
1179 public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
1180 return mAppStandby.isAppIdleFiltered(packageName, uidForAppId,
1181 userId, SystemClock.elapsedRealtime());
1185 @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
1187 return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false);
1191 public int[] getIdleUidsForUser(int userId) {
1192 return mAppStandby.getIdleUidsForUser(userId);
1196 public boolean isAppIdleParoleOn() {
1197 return mAppStandby.isParoledOrCharging();
1201 public void prepareShutdown() {
1202 // This method *WILL* do IO work, but we must block until it is finished or else
1203 // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1204 // we are shutting down.
1209 public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1210 mAppStandby.addListener(listener);
1211 listener.onParoleStateChanged(isAppIdleParoleOn());
1215 public void removeAppIdleStateChangeListener(
1216 AppIdleStateChangeListener listener) {
1217 mAppStandby.removeListener(listener);
1221 public byte[] getBackupPayload(int user, String key) {
1222 // Check to ensure that only user 0's data is b/r for now
1223 synchronized (mLock) {
1224 if (user == UserHandle.USER_SYSTEM) {
1225 final UserUsageStatsService userStats =
1226 getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1227 return userStats.getBackupPayload(key);
1235 public void applyRestoredPayload(int user, String key, byte[] payload) {
1236 synchronized (mLock) {
1237 if (user == UserHandle.USER_SYSTEM) {
1238 final UserUsageStatsService userStats =
1239 getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1240 userStats.applyRestoredPayload(key, payload);
1246 public List<UsageStats> queryUsageStatsForUser(
1247 int userId, int intervalType, long beginTime, long endTime,
1248 boolean obfuscateInstantApps) {
1249 return UsageStatsService.this.queryUsageStats(
1250 userId, intervalType, beginTime, endTime, obfuscateInstantApps);
1254 public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
1255 mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime);
1259 public long getTimeSinceLastJobRun(String packageName, int userId) {
1260 return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
1264 public void reportAppJobState(String packageName, int userId,
1265 int numDeferredJobs, long timeSinceLastJobRun) {
1269 public void onActiveAdminAdded(String packageName, int userId) {
1270 mAppStandby.addActiveDeviceAdmin(packageName, userId);
1274 public void setActiveAdminApps(Set<String> packageNames, int userId) {
1275 mAppStandby.setActiveAdminApps(packageNames, userId);
1279 public void onAdminDataAvailable() {
1280 mAppStandby.onAdminDataAvailable();
1284 public void reportExemptedSyncStart(String packageName, int userId) {
1285 mAppStandby.postReportExemptedSyncStart(packageName, userId);