• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.usage;
18 
19 import static android.app.usage.UsageEvents.Event.CHOOSER_ACTION;
20 import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE;
21 import static android.app.usage.UsageEvents.Event.DEVICE_EVENT_PACKAGE_NAME;
22 import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
23 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
24 import static android.app.usage.UsageEvents.Event.LOCUS_ID_SET;
25 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
26 import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
27 import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
28 import static android.app.usage.UsageEvents.Event.USER_STOPPED;
29 import static android.app.usage.UsageEvents.Event.USER_UNLOCKED;
30 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
31 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
32 
33 import android.Manifest;
34 import android.annotation.NonNull;
35 import android.annotation.Nullable;
36 import android.annotation.UserIdInt;
37 import android.app.ActivityManager;
38 import android.app.AppOpsManager;
39 import android.app.IUidObserver;
40 import android.app.PendingIntent;
41 import android.app.admin.DevicePolicyManagerInternal;
42 import android.app.usage.AppStandbyInfo;
43 import android.app.usage.ConfigurationStats;
44 import android.app.usage.EventStats;
45 import android.app.usage.IUsageStatsManager;
46 import android.app.usage.UsageEvents;
47 import android.app.usage.UsageEvents.Event;
48 import android.app.usage.UsageStats;
49 import android.app.usage.UsageStatsManager;
50 import android.app.usage.UsageStatsManager.StandbyBuckets;
51 import android.app.usage.UsageStatsManager.UsageSource;
52 import android.app.usage.UsageStatsManagerInternal;
53 import android.content.BroadcastReceiver;
54 import android.content.ComponentName;
55 import android.content.Context;
56 import android.content.Intent;
57 import android.content.IntentFilter;
58 import android.content.LocusId;
59 import android.content.pm.PackageInfo;
60 import android.content.pm.PackageManager;
61 import android.content.pm.PackageManagerInternal;
62 import android.content.pm.ParceledListSlice;
63 import android.content.pm.ShortcutServiceInternal;
64 import android.content.res.Configuration;
65 import android.os.Binder;
66 import android.os.Environment;
67 import android.os.FileUtils;
68 import android.os.Handler;
69 import android.os.IBinder;
70 import android.os.Looper;
71 import android.os.Message;
72 import android.os.Process;
73 import android.os.RemoteException;
74 import android.os.SystemClock;
75 import android.os.SystemProperties;
76 import android.os.UserHandle;
77 import android.os.UserManager;
78 import android.provider.Settings;
79 import android.text.TextUtils;
80 import android.util.ArrayMap;
81 import android.util.ArraySet;
82 import android.util.AtomicFile;
83 import android.util.Slog;
84 import android.util.SparseArray;
85 import android.util.SparseIntArray;
86 
87 import com.android.internal.annotations.VisibleForTesting;
88 import com.android.internal.content.PackageMonitor;
89 import com.android.internal.os.BackgroundThread;
90 import com.android.internal.util.CollectionUtils;
91 import com.android.internal.util.DumpUtils;
92 import com.android.internal.util.FrameworkStatsLog;
93 import com.android.internal.util.IndentingPrintWriter;
94 import com.android.server.LocalServices;
95 import com.android.server.SystemService;
96 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
97 
98 import java.io.BufferedReader;
99 import java.io.BufferedWriter;
100 import java.io.File;
101 import java.io.FileDescriptor;
102 import java.io.FileInputStream;
103 import java.io.FileOutputStream;
104 import java.io.FileReader;
105 import java.io.FileWriter;
106 import java.io.IOException;
107 import java.io.PrintWriter;
108 import java.nio.file.Files;
109 import java.nio.file.StandardCopyOption;
110 import java.util.ArrayList;
111 import java.util.Arrays;
112 import java.util.HashMap;
113 import java.util.LinkedList;
114 import java.util.List;
115 import java.util.Map;
116 import java.util.Objects;
117 import java.util.Set;
118 import java.util.concurrent.CopyOnWriteArraySet;
119 import java.util.concurrent.TimeUnit;
120 
121 /**
122  * A service that collects, aggregates, and persists application usage data.
123  * This data can be queried by apps that have been granted permission by AppOps.
124  */
125 public class UsageStatsService extends SystemService implements
126         UserUsageStatsService.StatsUpdatedListener {
127 
128     static final String TAG = "UsageStatsService";
129     public static final boolean ENABLE_TIME_CHANGE_CORRECTION
130             = SystemProperties.getBoolean("persist.debug.time_correction", true);
131 
132     static final boolean DEBUG = false; // Never submit with true
133     static final boolean COMPRESS_TIME = false;
134 
135     private static final long TEN_SECONDS = 10 * 1000;
136     private static final long TWENTY_MINUTES = 20 * 60 * 1000;
137     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
138     static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
139 
140     private static final boolean ENABLE_KERNEL_UPDATES = true;
141     private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
142 
143     private static final File USAGE_STATS_LEGACY_DIR = new File(
144             Environment.getDataSystemDirectory(), "usagestats");
145     // For migration purposes, indicates whether to keep the legacy usage stats directory or not
146     private static final boolean KEEP_LEGACY_DIR = false;
147 
148     private static final File COMMON_USAGE_STATS_DE_DIR =
149             new File(Environment.getDataSystemDeDirectory(), "usagestats");
150     private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage";
151 
152     private static final char TOKEN_DELIMITER = '/';
153 
154     // Handler message types.
155     static final int MSG_REPORT_EVENT = 0;
156     static final int MSG_FLUSH_TO_DISK = 1;
157     static final int MSG_REMOVE_USER = 2;
158     static final int MSG_UID_STATE_CHANGED = 3;
159     static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4;
160     static final int MSG_UNLOCKED_USER = 5;
161     static final int MSG_PACKAGE_REMOVED = 6;
162     static final int MSG_ON_START = 7;
163 
164     private final Object mLock = new Object();
165     Handler mHandler;
166     AppOpsManager mAppOps;
167     UserManager mUserManager;
168     PackageManager mPackageManager;
169     PackageManagerInternal mPackageManagerInternal;
170     // Do not use directly. Call getDpmInternal() instead
171     DevicePolicyManagerInternal mDpmInternal;
172     // Do not use directly. Call getShortcutServiceInternal() instead
173     ShortcutServiceInternal mShortcutServiceInternal;
174 
175     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
176     private final CopyOnWriteArraySet<Integer> mUserUnlockedStates = new CopyOnWriteArraySet<>();
177     private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
178     int mUsageSource;
179 
180     private long mRealTimeSnapshot;
181     private long mSystemTimeSnapshot;
182     // A map storing last time global usage of packages, measured in milliseconds since the epoch.
183     private final Map<String, Long> mLastTimeComponentUsedGlobal = new ArrayMap<>();
184 
185     /** Manages the standby state of apps. */
186     AppStandbyInternal mAppStandby;
187 
188     /** Manages app time limit observers */
189     AppTimeLimitController mAppTimeLimit;
190 
191     private final PackageMonitor mPackageMonitor = new MyPackageMonitor();
192 
193     // A map maintaining a queue of events to be reported per user.
194     private final SparseArray<LinkedList<Event>> mReportedEvents = new SparseArray<>();
195     final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray();
196     final SparseArray<ActivityData> mVisibleActivities = new SparseArray();
197     private final ArraySet<UsageStatsManagerInternal.UsageEventListener> mUsageEventListeners =
198             new ArraySet<>();
199 
200     private static class ActivityData {
201         private final String mTaskRootPackage;
202         private final String mTaskRootClass;
203         private final String mUsageSourcePackage;
204         public int lastEvent = Event.NONE;
ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage)205         private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) {
206             mTaskRootPackage = taskRootPackage;
207             mTaskRootClass = taskRootClass;
208             mUsageSourcePackage = sourcePackage;
209         }
210     }
211 
212     private AppIdleStateChangeListener mStandbyChangeListener =
213             new AppIdleStateChangeListener() {
214                 @Override
215                 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
216                         int bucket, int reason) {
217                     Event event = new Event(Event.STANDBY_BUCKET_CHANGED,
218                             SystemClock.elapsedRealtime());
219                     event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF);
220                     event.mPackage = packageName;
221                     reportEventOrAddToQueue(userId, event);
222                 }
223             };
224 
225     @VisibleForTesting
226     static class Injector {
getAppStandbyController(Context context)227         AppStandbyInternal getAppStandbyController(Context context) {
228             return AppStandbyInternal.newAppStandbyController(
229                     UsageStatsService.class.getClassLoader(), context);
230         }
231     }
232 
233     private final Injector mInjector;
234 
UsageStatsService(Context context)235     public UsageStatsService(Context context) {
236         this(context, new Injector());
237     }
238 
239     @VisibleForTesting
UsageStatsService(Context context, Injector injector)240     UsageStatsService(Context context, Injector injector) {
241         super(context);
242         mInjector = injector;
243     }
244 
245     @Override
onStart()246     public void onStart() {
247         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
248         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
249         mPackageManager = getContext().getPackageManager();
250         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
251         mHandler = new H(BackgroundThread.get().getLooper());
252 
253         mAppStandby = mInjector.getAppStandbyController(getContext());
254 
255         mAppTimeLimit = new AppTimeLimitController(getContext(),
256                 new AppTimeLimitController.TimeLimitCallbackListener() {
257                     @Override
258                     public void onLimitReached(int observerId, int userId, long timeLimit,
259                             long timeElapsed, PendingIntent callbackIntent) {
260                         if (callbackIntent == null) return;
261                         Intent intent = new Intent();
262                         intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
263                         intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
264                         intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
265                         try {
266                             callbackIntent.send(getContext(), 0, intent);
267                         } catch (PendingIntent.CanceledException e) {
268                             Slog.w(TAG, "Couldn't deliver callback: "
269                                     + callbackIntent);
270                         }
271                     }
272 
273                     @Override
274                     public void onSessionEnd(int observerId, int userId, long timeElapsed,
275                             PendingIntent callbackIntent) {
276                         if (callbackIntent == null) return;
277                         Intent intent = new Intent();
278                         intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
279                         intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
280                         try {
281                             callbackIntent.send(getContext(), 0, intent);
282                         } catch (PendingIntent.CanceledException e) {
283                             Slog.w(TAG, "Couldn't deliver callback: "
284                                     + callbackIntent);
285                         }
286                     }
287                 }, mHandler.getLooper());
288 
289         mAppStandby.addListener(mStandbyChangeListener);
290 
291         mPackageMonitor.register(getContext(), null, UserHandle.ALL, true);
292 
293         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
294         filter.addAction(Intent.ACTION_USER_STARTED);
295         getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
296                 null, mHandler);
297 
298         mRealTimeSnapshot = SystemClock.elapsedRealtime();
299         mSystemTimeSnapshot = System.currentTimeMillis();
300 
301         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
302         publishLocalService(AppStandbyInternal.class, mAppStandby);
303         publishBinderServices();
304 
305         mHandler.obtainMessage(MSG_ON_START).sendToTarget();
306     }
307 
308     @VisibleForTesting
publishBinderServices()309     void publishBinderServices() {
310         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
311     }
312 
313     @Override
onBootPhase(int phase)314     public void onBootPhase(int phase) {
315         mAppStandby.onBootPhase(phase);
316         if (phase == PHASE_SYSTEM_SERVICES_READY) {
317             // initialize mDpmInternal
318             getDpmInternal();
319             // initialize mShortcutServiceInternal
320             getShortcutServiceInternal();
321 
322             if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
323                 try {
324                     ActivityManager.getService().registerUidObserver(mUidObserver,
325                             ActivityManager.UID_OBSERVER_PROCSTATE
326                                     | ActivityManager.UID_OBSERVER_GONE,
327                             ActivityManager.PROCESS_STATE_UNKNOWN, null);
328                 } catch (RemoteException e) {
329                     throw new RuntimeException(e);
330                 }
331             } else {
332                 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE);
333             }
334             readUsageSourceSetting();
335         }
336     }
337 
338     @Override
onUserStarting(@onNull TargetUser user)339     public void onUserStarting(@NonNull TargetUser user) {
340         // Create an entry in the user state map to indicate that the user has been started but
341         // not necessarily unlocked. This will ensure that reported events are flushed to disk
342         // event if the user is never unlocked (following the logic in #flushToDiskLocked)
343         mUserState.put(user.getUserIdentifier(), null);
344     }
345 
346     @Override
onUserUnlocking(@onNull TargetUser user)347     public void onUserUnlocking(@NonNull TargetUser user) {
348         mHandler.obtainMessage(MSG_UNLOCKED_USER, user.getUserIdentifier(), 0).sendToTarget();
349     }
350 
351     @Override
onUserStopping(@onNull TargetUser user)352     public void onUserStopping(@NonNull TargetUser user) {
353         final int userId = user.getUserIdentifier();
354 
355         synchronized (mLock) {
356             // User was started but never unlocked so no need to report a user stopped event
357             if (!mUserUnlockedStates.contains(userId)) {
358                 persistPendingEventsLocked(userId);
359                 return;
360             }
361 
362             // Report a user stopped event before persisting all stats to disk via the user service
363             final Event event = new Event(USER_STOPPED, SystemClock.elapsedRealtime());
364             event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
365             reportEvent(event, userId);
366             final UserUsageStatsService userService = mUserState.get(userId);
367             if (userService != null) {
368                 userService.userStopped();
369             }
370             mUserUnlockedStates.remove(userId);
371             mUserState.put(userId, null); // release the service (mainly for GC)
372         }
373     }
374 
onUserUnlocked(int userId)375     private void onUserUnlocked(int userId) {
376         // fetch the installed packages outside the lock so it doesn't block package manager.
377         final HashMap<String, Long> installedPackages = getInstalledPackages(userId);
378         // delay updating of package mappings for user 0 since their data is not likely to be stale.
379         // this also makes it less likely for restored data to be erased on unexpected reboots.
380         if (userId == UserHandle.USER_SYSTEM) {
381             UsageStatsIdleService.scheduleUpdateMappingsJob(getContext());
382         }
383         synchronized (mLock) {
384             // This should be safe to add this early. Other than reportEventOrAddToQueue, every
385             // other user grabs the lock before accessing
386             // mUserUnlockedStates. reportEventOrAddToQueue does not depend on anything other than
387             // mUserUnlockedStates, and the lock will protect the handler.
388             mUserUnlockedStates.add(userId);
389             // Create a user unlocked event to report
390             final Event unlockEvent = new Event(USER_UNLOCKED, SystemClock.elapsedRealtime());
391             unlockEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
392 
393             migrateStatsToSystemCeIfNeededLocked(userId);
394 
395             // Read pending reported events from disk and merge them with those stored in memory
396             final LinkedList<Event> pendingEvents = new LinkedList<>();
397             loadPendingEventsLocked(userId, pendingEvents);
398             final LinkedList<Event> eventsInMem = mReportedEvents.get(userId);
399             if (eventsInMem != null) {
400                 pendingEvents.addAll(eventsInMem);
401             }
402             boolean needToFlush = !pendingEvents.isEmpty();
403 
404             initializeUserUsageStatsServiceLocked(userId, System.currentTimeMillis(),
405                     installedPackages);
406             final UserUsageStatsService userService = getUserUsageStatsServiceLocked(userId);
407             if (userService == null) {
408                 Slog.i(TAG, "Attempted to unlock stopped or removed user " + userId);
409                 return;
410             }
411 
412             // Process all the pending reported events
413             while (pendingEvents.peek() != null) {
414                 reportEvent(pendingEvents.poll(), userId);
415             }
416             reportEvent(unlockEvent, userId);
417 
418             // Remove all the stats stored in memory and in system DE.
419             mReportedEvents.remove(userId);
420             deleteRecursively(new File(Environment.getDataSystemDeDirectory(userId), "usagestats"));
421             // Force a flush to disk for the current user to ensure important events are persisted.
422             // Note: there is a very very small chance that the system crashes between deleting
423             // the stats above from DE and persisting them to CE here in which case we will lose
424             // those events that were in memory and deleted from DE. (b/139836090)
425             if (needToFlush) {
426                 userService.persistActiveStats();
427             }
428         }
429     }
430 
431     /**
432      * Fetches a map (package_name:install_time) of installed packages for the given user. This
433      * map contains all installed packages, including those packages which have been uninstalled
434      * with the DELETE_KEEP_DATA flag.
435      * This is a helper method which should only be called when the given user's usage stats service
436      * is initialized; it performs a heavy query to package manager so do not call it otherwise.
437      * <br/>
438      * Note: DO NOT call this while holding the usage stats lock ({@code mLock}).
439      */
getInstalledPackages(int userId)440     private HashMap<String, Long> getInstalledPackages(int userId) {
441         if (mPackageManager == null) {
442             return null;
443         }
444         final List<PackageInfo> installedPackages = mPackageManager.getInstalledPackagesAsUser(
445                 PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
446         final HashMap<String, Long> packagesMap = new HashMap<>();
447         for (int i = installedPackages.size() - 1; i >= 0; i--) {
448             final PackageInfo packageInfo = installedPackages.get(i);
449             packagesMap.put(packageInfo.packageName, packageInfo.firstInstallTime);
450         }
451         return packagesMap;
452     }
453 
getDpmInternal()454     private DevicePolicyManagerInternal getDpmInternal() {
455         if (mDpmInternal == null) {
456             mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
457         }
458         return mDpmInternal;
459     }
460 
getShortcutServiceInternal()461     private ShortcutServiceInternal getShortcutServiceInternal() {
462         if (mShortcutServiceInternal == null) {
463             mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
464         }
465         return mShortcutServiceInternal;
466     }
467 
readUsageSourceSetting()468     private void readUsageSourceSetting() {
469         synchronized (mLock) {
470             mUsageSource = Settings.Global.getInt(getContext().getContentResolver(),
471                     Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY);
472         }
473     }
474 
475     private class UserActionsReceiver extends BroadcastReceiver {
476         @Override
onReceive(Context context, Intent intent)477         public void onReceive(Context context, Intent intent) {
478             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
479             final String action = intent.getAction();
480             if (Intent.ACTION_USER_REMOVED.equals(action)) {
481                 if (userId >= 0) {
482                     mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
483                 }
484             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
485                 if (userId >= 0) {
486                     mAppStandby.postCheckIdleStates(userId);
487                 }
488             }
489         }
490     }
491 
492     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
493         @Override
494         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
495             mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
496         }
497 
498         @Override
499         public void onUidIdle(int uid, boolean disabled) {
500             // Ignored
501         }
502 
503         @Override
504         public void onUidGone(int uid, boolean disabled) {
505             onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0,
506                     ActivityManager.PROCESS_CAPABILITY_NONE);
507         }
508 
509         @Override
510         public void onUidActive(int uid) {
511             // Ignored
512         }
513 
514         @Override public void onUidCachedChanged(int uid, boolean cached) {
515         }
516     };
517 
518     @Override
onStatsUpdated()519     public void onStatsUpdated() {
520         mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
521     }
522 
523     @Override
onStatsReloaded()524     public void onStatsReloaded() {
525         mAppStandby.postOneTimeCheckIdleStates();
526     }
527 
528     @Override
onNewUpdate(int userId)529     public void onNewUpdate(int userId) {
530         mAppStandby.initializeDefaultsForSystemApps(userId);
531     }
532 
shouldObfuscateInstantAppsForCaller(int callingUid, int userId)533     private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
534         return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
535     }
536 
shouldHideShortcutInvocationEvents(int userId, String callingPackage, int callingPid, int callingUid)537     private boolean shouldHideShortcutInvocationEvents(int userId, String callingPackage,
538             int callingPid, int callingUid) {
539         final ShortcutServiceInternal shortcutServiceInternal = getShortcutServiceInternal();
540         if (shortcutServiceInternal != null) {
541             return !shortcutServiceInternal.hasShortcutHostPermission(userId, callingPackage,
542                     callingPid, callingUid);
543         }
544         return true; // hide by default if we can't verify visibility
545     }
546 
shouldHideLocusIdEvents(int callingPid, int callingUid)547     private boolean shouldHideLocusIdEvents(int callingPid, int callingUid) {
548         if (callingUid == Process.SYSTEM_UID) {
549             return false;
550         }
551         return !(getContext().checkPermission(
552                 android.Manifest.permission.ACCESS_LOCUS_ID_USAGE_STATS, callingPid, callingUid)
553                 == PackageManager.PERMISSION_GRANTED);
554     }
555 
556     /**
557      * Obfuscate both {@link UsageEvents.Event#NOTIFICATION_SEEN} and
558      * {@link UsageEvents.Event#NOTIFICATION_INTERRUPTION} events if the provided calling uid does
559      * not hold the {@link android.Manifest.permission.MANAGE_NOTIFICATIONS} permission.
560      */
shouldObfuscateNotificationEvents(int callingPid, int callingUid)561     private boolean shouldObfuscateNotificationEvents(int callingPid, int callingUid) {
562         if (callingUid == Process.SYSTEM_UID) {
563             return false;
564         }
565         return !(getContext().checkPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS,
566                 callingPid, callingUid) == PackageManager.PERMISSION_GRANTED);
567     }
568 
deleteRecursively(File f)569     private static void deleteRecursively(File f) {
570         File[] files = f.listFiles();
571         if (files != null) {
572             for (File subFile : files) {
573                 deleteRecursively(subFile);
574             }
575         }
576 
577         if (f.exists() && !f.delete()) {
578             Slog.e(TAG, "Failed to delete " + f);
579         }
580     }
581 
582     /**
583      * This should the be only way to fetch the usage stats service for a specific user.
584      */
getUserUsageStatsServiceLocked(int userId)585     private UserUsageStatsService getUserUsageStatsServiceLocked(int userId) {
586         final UserUsageStatsService service = mUserState.get(userId);
587         if (service == null) {
588             Slog.wtf(TAG, "Failed to fetch usage stats service for user " + userId + ". "
589                     + "The user might not have been initialized yet.");
590         }
591         return service;
592     }
593 
594     /**
595      * Initializes the given user's usage stats service - this should ideally only be called once,
596      * when the user is initially unlocked.
597      */
initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis, HashMap<String, Long> installedPackages)598     private void initializeUserUsageStatsServiceLocked(int userId, long currentTimeMillis,
599             HashMap<String, Long> installedPackages) {
600         final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId),
601                 "usagestats");
602         final UserUsageStatsService service = new UserUsageStatsService(getContext(), userId,
603                 usageStatsDir, this);
604         try {
605             service.init(currentTimeMillis, installedPackages);
606             mUserState.put(userId, service);
607         } catch (Exception e) {
608             if (mUserManager.isUserUnlocked(userId)) {
609                 Slog.w(TAG, "Failed to initialized unlocked user " + userId);
610                 throw e; // rethrow the exception - user is unlocked
611             } else {
612                 Slog.w(TAG, "Attempted to initialize service for stopped or removed user "
613                         + userId);
614             }
615         }
616     }
617 
migrateStatsToSystemCeIfNeededLocked(int userId)618     private void migrateStatsToSystemCeIfNeededLocked(int userId) {
619         final File usageStatsDir = new File(Environment.getDataSystemCeDirectory(userId),
620                 "usagestats");
621         if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) {
622             throw new IllegalStateException("Usage stats directory does not exist: "
623                     + usageStatsDir.getAbsolutePath());
624         }
625         // Check if the migrated status file exists - if not, migrate usage stats.
626         final File migrated = new File(usageStatsDir, "migrated");
627         if (migrated.exists()) {
628             try (BufferedReader reader = new BufferedReader(new FileReader(migrated))) {
629                 final int previousVersion = Integer.parseInt(reader.readLine());
630                 // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE.
631                 if (previousVersion >= 4) {
632                     deleteLegacyDir(userId);
633                     return;
634                 }
635                 // If migration logic needs to be changed in a future version, do it here.
636             } catch (NumberFormatException | IOException e) {
637                 Slog.e(TAG, "Failed to read migration status file, possibly corrupted.");
638                 deleteRecursively(usageStatsDir);
639                 if (usageStatsDir.exists()) {
640                     Slog.e(TAG, "Unable to delete usage stats CE directory.");
641                     throw new RuntimeException(e);
642                 } else {
643                     // Make the directory again since previous migration was not complete
644                     if (!usageStatsDir.mkdirs() && !usageStatsDir.exists()) {
645                         throw new IllegalStateException("Usage stats directory does not exist: "
646                                 + usageStatsDir.getAbsolutePath());
647                     }
648                 }
649             }
650         }
651 
652         Slog.i(TAG, "Starting migration to system CE for user " + userId);
653         final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId));
654         if (legacyUserDir.exists()) {
655             copyRecursively(usageStatsDir, legacyUserDir);
656         }
657         // Create a status file to indicate that the migration to CE has been completed.
658         try (BufferedWriter writer = new BufferedWriter(new FileWriter(migrated))) {
659             writer.write(Integer.toString(UsageStatsDatabase.BACKUP_VERSION));
660             writer.write("\n");
661             writer.flush();
662         } catch (IOException e) {
663             Slog.e(TAG, "Failed to write migrated status file");
664             throw new RuntimeException(e);
665         }
666         Slog.i(TAG, "Finished migration to system CE for user " + userId);
667 
668         // Migration was successful - delete the legacy directory
669         deleteLegacyDir(userId);
670     }
671 
copyRecursively(final File parent, File f)672     private static void copyRecursively(final File parent, File f) {
673         final File[] files = f.listFiles();
674         if (files == null) {
675             try {
676                 Files.copy(f.toPath(), new File(parent, f.getName()).toPath(),
677                         StandardCopyOption.REPLACE_EXISTING);
678             } catch (IOException e) {
679                 Slog.e(TAG, "Failed to move usage stats file : " + f.toString());
680                 throw new RuntimeException(e);
681             }
682             return;
683         }
684 
685         for (int i = files.length - 1; i >= 0; i--) {
686             File newParent = parent;
687             if (files[i].isDirectory()) {
688                 newParent = new File(parent, files[i].getName());
689                 final boolean mkdirSuccess = newParent.mkdirs();
690                 if (!mkdirSuccess && !newParent.exists()) {
691                     throw new IllegalStateException(
692                             "Failed to create usage stats directory during migration: "
693                             + newParent.getAbsolutePath());
694                 }
695             }
696             copyRecursively(newParent, files[i]);
697         }
698     }
699 
deleteLegacyDir(int userId)700     private void deleteLegacyDir(int userId) {
701         final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId));
702         if (!KEEP_LEGACY_DIR && legacyUserDir.exists()) {
703             deleteRecursively(legacyUserDir);
704             if (legacyUserDir.exists()) {
705                 Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats "
706                         + "dir for user " + userId);
707             }
708             // If all users have been migrated, delete the parent legacy usage stats directory
709             if (USAGE_STATS_LEGACY_DIR.list() != null
710                     && USAGE_STATS_LEGACY_DIR.list().length == 0) {
711                 if (!USAGE_STATS_LEGACY_DIR.delete()) {
712                     Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats dir");
713                 }
714             }
715         }
716     }
717 
718     /**
719      * Called by the Binder stub
720      */
shutdown()721     void shutdown() {
722         synchronized (mLock) {
723             mHandler.removeMessages(MSG_REPORT_EVENT);
724             Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
725             event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
726             // orderly shutdown, the last event is DEVICE_SHUTDOWN.
727             reportEventToAllUserId(event);
728             flushToDiskLocked();
729             persistGlobalComponentUsageLocked();
730         }
731 
732         mAppStandby.flushToDisk();
733     }
734 
735     /**
736      * After power button is pressed for 3.5 seconds
737      * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}),
738      * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10
739      * seconds and the device is shutdown, the database is already persisted and we are not losing
740      * data.
741      * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise
742      * PhoneWindowManager may be blocked.
743      */
prepareForPossibleShutdown()744     void prepareForPossibleShutdown() {
745         Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
746         event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
747         mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget();
748         mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK);
749     }
750 
loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents)751     private void loadPendingEventsLocked(int userId, LinkedList<Event> pendingEvents) {
752         final File usageStatsDeDir = new File(Environment.getDataSystemDeDirectory(userId),
753                 "usagestats");
754         final File[] pendingEventsFiles = usageStatsDeDir.listFiles();
755         if (pendingEventsFiles == null || pendingEventsFiles.length == 0) {
756             return;
757         }
758         Arrays.sort(pendingEventsFiles);
759 
760         final int numFiles = pendingEventsFiles.length;
761         for (int i = 0; i < numFiles; i++) {
762             final AtomicFile af = new AtomicFile(pendingEventsFiles[i]);
763             final LinkedList<Event> tmpEvents = new LinkedList<>();
764             try {
765                 try (FileInputStream in = af.openRead()) {
766                     UsageStatsProtoV2.readPendingEvents(in, tmpEvents);
767                 }
768                 // only add to the pending events if the read was successful
769                 pendingEvents.addAll(tmpEvents);
770             } catch (Exception e) {
771                 // Most likely trying to read a corrupted file - log the failure and continue
772                 // reading the other pending event files.
773                 Slog.e(TAG, "Could not read " + pendingEventsFiles[i] + " for user " + userId);
774             }
775         }
776     }
777 
persistPendingEventsLocked(int userId)778     private void persistPendingEventsLocked(int userId) {
779         final LinkedList<Event> pendingEvents = mReportedEvents.get(userId);
780         if (pendingEvents == null || pendingEvents.isEmpty()) {
781             return;
782         }
783 
784         final File usageStatsDeDir = new File(Environment.getDataSystemDeDirectory(userId),
785                 "usagestats");
786         if (!usageStatsDeDir.mkdirs() && !usageStatsDeDir.exists()) {
787             throw new IllegalStateException("Usage stats DE directory does not exist: "
788                     + usageStatsDeDir.getAbsolutePath());
789         }
790         final File pendingEventsFile = new File(usageStatsDeDir,
791                 "pendingevents_" + System.currentTimeMillis());
792         final AtomicFile af = new AtomicFile(pendingEventsFile);
793         FileOutputStream fos = null;
794         try {
795             fos = af.startWrite();
796             UsageStatsProtoV2.writePendingEvents(fos, pendingEvents);
797             af.finishWrite(fos);
798             fos = null;
799             pendingEvents.clear();
800         } catch (Exception e) {
801             Slog.e(TAG, "Failed to write " + pendingEventsFile.getAbsolutePath()
802                     + " for user " + userId);
803         } finally {
804             af.failWrite(fos); // when fos is null (successful write), this will no-op
805         }
806     }
807 
loadGlobalComponentUsageLocked()808     private void loadGlobalComponentUsageLocked() {
809         final File[] packageUsageFile = COMMON_USAGE_STATS_DE_DIR.listFiles(
810                 (dir, name) -> TextUtils.equals(name, GLOBAL_COMPONENT_USAGE_FILE_NAME));
811         if (packageUsageFile == null || packageUsageFile.length == 0) {
812             return;
813         }
814 
815         final AtomicFile af = new AtomicFile(packageUsageFile[0]);
816         final Map<String, Long> tmpUsage = new ArrayMap<>();
817         try {
818             try (FileInputStream in = af.openRead()) {
819                 UsageStatsProtoV2.readGlobalComponentUsage(in, tmpUsage);
820             }
821             // only add to in memory map if the read was successful
822             final Map.Entry<String, Long>[] entries =
823                     (Map.Entry<String, Long>[]) tmpUsage.entrySet().toArray();
824             final int size = entries.length;
825             for (int i = 0; i < size; ++i) {
826                 // In memory data is usually the most up-to-date, so skip the packages which already
827                 // have usage data.
828                 mLastTimeComponentUsedGlobal.putIfAbsent(
829                         entries[i].getKey(), entries[i].getValue());
830             }
831         } catch (Exception e) {
832             // Most likely trying to read a corrupted file - log the failure
833             Slog.e(TAG, "Could not read " + packageUsageFile[0]);
834         }
835     }
836 
persistGlobalComponentUsageLocked()837     private void persistGlobalComponentUsageLocked() {
838         if (mLastTimeComponentUsedGlobal.isEmpty()) {
839             return;
840         }
841 
842         if (!COMMON_USAGE_STATS_DE_DIR.mkdirs() && !COMMON_USAGE_STATS_DE_DIR.exists()) {
843             throw new IllegalStateException("Common usage stats DE directory does not exist: "
844                     + COMMON_USAGE_STATS_DE_DIR.getAbsolutePath());
845         }
846         final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DE_DIR,
847                 GLOBAL_COMPONENT_USAGE_FILE_NAME);
848         final AtomicFile af = new AtomicFile(lastTimePackageFile);
849         FileOutputStream fos = null;
850         try {
851             fos = af.startWrite();
852             UsageStatsProtoV2.writeGlobalComponentUsage(fos, mLastTimeComponentUsedGlobal);
853             af.finishWrite(fos);
854             fos = null;
855         } catch (Exception e) {
856             Slog.e(TAG, "Failed to write " + lastTimePackageFile.getAbsolutePath());
857         } finally {
858             af.failWrite(fos); // when fos is null (successful write), this will no-op
859         }
860     }
861 
reportEventOrAddToQueue(int userId, Event event)862     private void reportEventOrAddToQueue(int userId, Event event) {
863         if (mUserUnlockedStates.contains(userId)) {
864             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
865             return;
866         }
867         synchronized (mLock) {
868             LinkedList<Event> events = mReportedEvents.get(userId);
869             if (events == null) {
870                 events = new LinkedList<>();
871                 mReportedEvents.put(userId, events);
872             }
873             events.add(event);
874             if (events.size() == 1) {
875                 // Every time a file is persisted to disk, mReportedEvents is cleared for this user
876                 // so trigger a flush to disk every time the first event has been added.
877                 mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
878             }
879         }
880     }
881 
882     /**
883      * Assuming the event's timestamp is measured in milliseconds since boot,
884      * convert it to a system wall time. System and real time snapshots are updated before
885      * conversion.
886      */
convertToSystemTimeLocked(Event event)887     private void convertToSystemTimeLocked(Event event) {
888         final long actualSystemTime = System.currentTimeMillis();
889         if (ENABLE_TIME_CHANGE_CORRECTION) {
890             final long actualRealtime = SystemClock.elapsedRealtime();
891             final long expectedSystemTime =
892                     (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
893             final long diffSystemTime = actualSystemTime - expectedSystemTime;
894             if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
895                 // The time has changed.
896                 Slog.i(TAG, "Time changed in by " + (diffSystemTime / 1000) + " seconds");
897                 mRealTimeSnapshot = actualRealtime;
898                 mSystemTimeSnapshot = actualSystemTime;
899             }
900         }
901         event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
902     }
903 
904     /**
905      * Called by the Binder stub.
906      */
reportEvent(Event event, int userId)907     void reportEvent(Event event, int userId) {
908         final int uid;
909         // Acquire uid outside of mLock for events that need it
910         switch (event.mEventType) {
911             case Event.ACTIVITY_RESUMED:
912             case Event.ACTIVITY_PAUSED:
913             case Event.ACTIVITY_STOPPED:
914                 uid = mPackageManagerInternal.getPackageUid(event.mPackage, 0, userId);
915                 break;
916             default:
917                 uid = 0;
918         }
919 
920         if (event.mPackage != null
921                 && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
922             event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
923         }
924 
925         synchronized (mLock) {
926             // This should never be called directly when the user is locked
927             if (!mUserUnlockedStates.contains(userId)) {
928                 Slog.wtf(TAG, "Failed to report event for locked user " + userId
929                         + " (" + event.mPackage + "/" + event.mClass
930                         + " eventType:" + event.mEventType
931                         + " instanceId:" + event.mInstanceId + ")");
932                 return;
933             }
934 
935             switch (event.mEventType) {
936                 case Event.ACTIVITY_RESUMED:
937                     FrameworkStatsLog.write(
938                             FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
939                             uid,
940                             event.mPackage,
941                             event.mClass,
942                             FrameworkStatsLog
943                                     .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
944                     // check if this activity has already been resumed
945                     if (mVisibleActivities.get(event.mInstanceId) != null) break;
946                     final String usageSourcePackage = getUsageSourcePackage(event);
947                     try {
948                         mAppTimeLimit.noteUsageStart(usageSourcePackage, userId);
949                     } catch (IllegalArgumentException iae) {
950                         Slog.e(TAG, "Failed to note usage start", iae);
951                     }
952                     final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
953                             event.mTaskRootClass, usageSourcePackage);
954                     resumedData.lastEvent = Event.ACTIVITY_RESUMED;
955                     mVisibleActivities.put(event.mInstanceId, resumedData);
956                     break;
957                 case Event.ACTIVITY_PAUSED:
958                     ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
959                     if (pausedData == null) {
960                         // Must have transitioned from Stopped/Destroyed to Paused state.
961                         final String usageSourcePackage2 = getUsageSourcePackage(event);
962                         try {
963                             mAppTimeLimit.noteUsageStart(usageSourcePackage2, userId);
964                         } catch (IllegalArgumentException iae) {
965                             Slog.e(TAG, "Failed to note usage start", iae);
966                         }
967                         pausedData = new ActivityData(event.mTaskRootPackage, event.mTaskRootClass,
968                                 usageSourcePackage2);
969                         mVisibleActivities.put(event.mInstanceId, pausedData);
970                     } else {
971                         FrameworkStatsLog.write(
972                                 FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
973                                 uid,
974                                 event.mPackage,
975                                 event.mClass,
976                                 FrameworkStatsLog
977                                         .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
978                     }
979 
980                     pausedData.lastEvent = Event.ACTIVITY_PAUSED;
981                     if (event.mTaskRootPackage == null) {
982                         // Task Root info is missing. Repair the event based on previous data
983                         event.mTaskRootPackage = pausedData.mTaskRootPackage;
984                         event.mTaskRootClass = pausedData.mTaskRootClass;
985                     }
986                     break;
987                 case Event.ACTIVITY_DESTROYED:
988                     // Treat activity destroys like activity stops.
989                     event.mEventType = Event.ACTIVITY_STOPPED;
990                     // Fallthrough
991                 case Event.ACTIVITY_STOPPED:
992                     final ActivityData prevData =
993                             mVisibleActivities.removeReturnOld(event.mInstanceId);
994                     if (prevData == null) {
995                         Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
996                                 + "/" + event.mClass + " event : " + event.mEventType
997                                 + " instanceId : " + event.mInstanceId + ")");
998                         return;
999                     }
1000 
1001                     if (prevData.lastEvent != Event.ACTIVITY_PAUSED) {
1002                         FrameworkStatsLog.write(
1003                                 FrameworkStatsLog.APP_USAGE_EVENT_OCCURRED,
1004                                 uid,
1005                                 event.mPackage,
1006                                 event.mClass,
1007                                 FrameworkStatsLog
1008                                         .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_BACKGROUND);
1009                     }
1010 
1011                     ArraySet<String> tokens;
1012                     synchronized (mUsageReporters) {
1013                         tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
1014                     }
1015                     if (tokens != null) {
1016                         synchronized (tokens) {
1017                             final int size = tokens.size();
1018                             // Stop usage on behalf of a UsageReporter that stopped
1019                             for (int i = 0; i < size; i++) {
1020                                 final String token = tokens.valueAt(i);
1021                                 try {
1022                                     mAppTimeLimit.noteUsageStop(
1023                                             buildFullToken(event.mPackage, token), userId);
1024                                 } catch (IllegalArgumentException iae) {
1025                                     Slog.w(TAG, "Failed to stop usage for during reporter death: "
1026                                             + iae);
1027                                 }
1028                             }
1029                         }
1030                     }
1031                     if (event.mTaskRootPackage == null) {
1032                         // Task Root info is missing. Repair the event based on previous data
1033                         event.mTaskRootPackage = prevData.mTaskRootPackage;
1034                         event.mTaskRootClass = prevData.mTaskRootClass;
1035                     }
1036                     try {
1037                         mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId);
1038                     } catch (IllegalArgumentException iae) {
1039                         Slog.w(TAG, "Failed to note usage stop", iae);
1040                     }
1041                     break;
1042                 case Event.USER_INTERACTION:
1043                     // Fall through
1044                 case Event.APP_COMPONENT_USED:
1045                     convertToSystemTimeLocked(event);
1046                     mLastTimeComponentUsedGlobal.put(event.mPackage, event.mTimeStamp);
1047                     break;
1048             }
1049 
1050             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1051             if (service == null) {
1052                 return; // user was stopped or removed
1053             }
1054             service.reportEvent(event);
1055         }
1056 
1057         final int size = mUsageEventListeners.size();
1058         for (int i = 0; i < size; ++i) {
1059             mUsageEventListeners.valueAt(i).onUsageEvent(userId, event);
1060         }
1061     }
1062 
getUsageSourcePackage(Event event)1063     private String getUsageSourcePackage(Event event) {
1064         switch(mUsageSource) {
1065             case USAGE_SOURCE_CURRENT_ACTIVITY:
1066                 return event.mPackage;
1067             case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
1068             default:
1069                 return event.mTaskRootPackage;
1070         }
1071     }
1072 
1073     /**
1074      * Some events like FLUSH_TO_DISK need to be sent to all userId.
1075      * @param event
1076      */
reportEventToAllUserId(Event event)1077     void reportEventToAllUserId(Event event) {
1078         synchronized (mLock) {
1079             final int userCount = mUserState.size();
1080             for (int i = 0; i < userCount; i++) {
1081                 Event copy = new Event(event);
1082                 reportEventOrAddToQueue(mUserState.keyAt(i), copy);
1083             }
1084         }
1085     }
1086 
1087     /**
1088      * Called by the Handler for message MSG_FLUSH_TO_DISK.
1089      */
flushToDisk()1090     void flushToDisk() {
1091         synchronized (mLock) {
1092             // Before flush to disk, report FLUSH_TO_DISK event to signal UsageStats to update app
1093             // usage. In case of abrupt power shutdown like battery drain or cold temperature,
1094             // all UsageStats has correct data up to last flush to disk.
1095             // The FLUSH_TO_DISK event is an internal event, it will not show up in IntervalStats'
1096             // EventList.
1097             Event event = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime());
1098             event.mPackage = DEVICE_EVENT_PACKAGE_NAME;
1099             reportEventToAllUserId(event);
1100             flushToDiskLocked();
1101         }
1102         mAppStandby.flushToDisk();
1103     }
1104 
1105     /**
1106      * Called by the Binder stub.
1107      */
onUserRemoved(int userId)1108     void onUserRemoved(int userId) {
1109         synchronized (mLock) {
1110             Slog.i(TAG, "Removing user " + userId + " and all data.");
1111             mUserState.remove(userId);
1112             mAppTimeLimit.onUserRemoved(userId);
1113         }
1114         mAppStandby.onUserRemoved(userId);
1115         // Cancel any scheduled jobs for this user since the user is being removed.
1116         UsageStatsIdleService.cancelJob(getContext(), userId);
1117         UsageStatsIdleService.cancelUpdateMappingsJob(getContext());
1118     }
1119 
1120     /**
1121      * Called by the Handler for message MSG_PACKAGE_REMOVED.
1122      */
onPackageRemoved(int userId, String packageName)1123     private void onPackageRemoved(int userId, String packageName) {
1124         final int tokenRemoved;
1125         synchronized (mLock) {
1126             final long timeRemoved = System.currentTimeMillis();
1127             if (!mUserUnlockedStates.contains(userId)) {
1128                 // If user is not unlocked and a package is removed for them, we will handle it
1129                 // when the user service is initialized and package manager is queried.
1130                 return;
1131             }
1132             final UserUsageStatsService userService = mUserState.get(userId);
1133             if (userService == null) {
1134                 return;
1135             }
1136 
1137             tokenRemoved = userService.onPackageRemoved(packageName, timeRemoved);
1138         }
1139 
1140         // Schedule a job to prune any data related to this package.
1141         if (tokenRemoved != PackagesTokenData.UNASSIGNED_TOKEN) {
1142             UsageStatsIdleService.scheduleJob(getContext(), userId);
1143         }
1144     }
1145 
1146     /**
1147      * Called by the Binder stub.
1148      */
pruneUninstalledPackagesData(int userId)1149     private boolean pruneUninstalledPackagesData(int userId) {
1150         synchronized (mLock) {
1151             if (!mUserUnlockedStates.contains(userId)) {
1152                 return false; // user is no longer unlocked
1153             }
1154 
1155             final UserUsageStatsService userService = mUserState.get(userId);
1156             if (userService == null) {
1157                 return false; // user was stopped or removed
1158             }
1159 
1160             return userService.pruneUninstalledPackagesData();
1161         }
1162     }
1163 
1164     /**
1165      * Called by the Binder stub.
1166      */
updatePackageMappingsData()1167     private boolean updatePackageMappingsData() {
1168         // fetch the installed packages outside the lock so it doesn't block package manager.
1169         final HashMap<String, Long> installedPkgs = getInstalledPackages(UserHandle.USER_SYSTEM);
1170         synchronized (mLock) {
1171             if (!mUserUnlockedStates.contains(UserHandle.USER_SYSTEM)) {
1172                 return false; // user is no longer unlocked
1173             }
1174 
1175             final UserUsageStatsService userService = mUserState.get(UserHandle.USER_SYSTEM);
1176             if (userService == null) {
1177                 return false; // user was stopped or removed
1178             }
1179 
1180             return userService.updatePackageMappingsLocked(installedPkgs);
1181         }
1182     }
1183 
1184     /**
1185      * Called by the Binder stub.
1186      */
queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)1187     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
1188             boolean obfuscateInstantApps) {
1189         synchronized (mLock) {
1190             if (!mUserUnlockedStates.contains(userId)) {
1191                 Slog.w(TAG, "Failed to query usage stats for locked user " + userId);
1192                 return null;
1193             }
1194 
1195             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1196             if (service == null) {
1197                 return null; // user was stopped or removed
1198             }
1199             List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
1200             if (list == null) {
1201                 return null;
1202             }
1203 
1204             // Mangle instant app names *using their current state (not whether they were ephemeral
1205             // when the data was recorded)*.
1206             if (obfuscateInstantApps) {
1207                 for (int i = list.size() - 1; i >= 0; i--) {
1208                     final UsageStats stats = list.get(i);
1209                     if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
1210                         list.set(i, stats.getObfuscatedForInstantApp());
1211                     }
1212                 }
1213             }
1214             return list;
1215         }
1216     }
1217 
1218     /**
1219      * Called by the Binder stub.
1220      */
queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)1221     List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
1222             long endTime) {
1223         synchronized (mLock) {
1224             if (!mUserUnlockedStates.contains(userId)) {
1225                 Slog.w(TAG, "Failed to query configuration stats for locked user " + userId);
1226                 return null;
1227             }
1228 
1229             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1230             if (service == null) {
1231                 return null; // user was stopped or removed
1232             }
1233             return service.queryConfigurationStats(bucketType, beginTime, endTime);
1234         }
1235     }
1236 
1237     /**
1238      * Called by the Binder stub.
1239      */
queryEventStats(int userId, int bucketType, long beginTime, long endTime)1240     List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
1241             long endTime) {
1242         synchronized (mLock) {
1243             if (!mUserUnlockedStates.contains(userId)) {
1244                 Slog.w(TAG, "Failed to query event stats for locked user " + userId);
1245                 return null;
1246             }
1247 
1248             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1249             if (service == null) {
1250                 return null; // user was stopped or removed
1251             }
1252             return service.queryEventStats(bucketType, beginTime, endTime);
1253         }
1254     }
1255 
1256     /**
1257      * Called by the Binder stub.
1258      */
queryEvents(int userId, long beginTime, long endTime, int flags)1259     UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) {
1260         synchronized (mLock) {
1261             if (!mUserUnlockedStates.contains(userId)) {
1262                 Slog.w(TAG, "Failed to query events for locked user " + userId);
1263                 return null;
1264             }
1265 
1266             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1267             if (service == null) {
1268                 return null; // user was stopped or removed
1269             }
1270             return service.queryEvents(beginTime, endTime, flags);
1271         }
1272     }
1273 
1274     /**
1275      * Called by the Binder stub.
1276      */
queryEventsForPackage(int userId, long beginTime, long endTime, String packageName, boolean includeTaskRoot)1277     UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
1278             String packageName, boolean includeTaskRoot) {
1279         synchronized (mLock) {
1280             if (!mUserUnlockedStates.contains(userId)) {
1281                 Slog.w(TAG, "Failed to query package events for locked user " + userId);
1282                 return null;
1283             }
1284 
1285             final UserUsageStatsService service = getUserUsageStatsServiceLocked(userId);
1286             if (service == null) {
1287                 return null; // user was stopped or removed
1288             }
1289             return service.queryEventsForPackage(beginTime, endTime, packageName, includeTaskRoot);
1290         }
1291     }
1292 
1293     /**
1294      * Called via the local interface.
1295      */
registerListener(@onNull UsageStatsManagerInternal.UsageEventListener listener)1296     private void registerListener(@NonNull UsageStatsManagerInternal.UsageEventListener listener) {
1297         synchronized (mLock) {
1298             mUsageEventListeners.add(listener);
1299         }
1300     }
1301 
1302     /**
1303      * Called via the local interface.
1304      */
unregisterListener( @onNull UsageStatsManagerInternal.UsageEventListener listener)1305     private void unregisterListener(
1306             @NonNull UsageStatsManagerInternal.UsageEventListener listener) {
1307         synchronized (mLock) {
1308             mUsageEventListeners.remove(listener);
1309         }
1310     }
1311 
buildFullToken(String packageName, String token)1312     private String buildFullToken(String packageName, String token) {
1313         final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1);
1314         sb.append(packageName);
1315         sb.append(TOKEN_DELIMITER);
1316         sb.append(token);
1317         return sb.toString();
1318     }
1319 
flushToDiskLocked()1320     private void flushToDiskLocked() {
1321         final int userCount = mUserState.size();
1322         for (int i = 0; i < userCount; i++) {
1323             final int userId = mUserState.keyAt(i);
1324             if (!mUserUnlockedStates.contains(userId)) {
1325                 persistPendingEventsLocked(userId);
1326                 continue;
1327             }
1328             UserUsageStatsService service = mUserState.get(userId);
1329             if (service != null) {
1330                 service.persistActiveStats();
1331             }
1332         }
1333         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
1334     }
1335 
1336     /**
1337      * Called by the Binder stub.
1338      */
dump(String[] args, PrintWriter pw)1339     void dump(String[] args, PrintWriter pw) {
1340         IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
1341 
1342         boolean checkin = false;
1343         boolean compact = false;
1344         final ArrayList<String> pkgs = new ArrayList<>();
1345 
1346         if (args != null) {
1347             for (int i = 0; i < args.length; i++) {
1348                 String arg = args[i];
1349                 if ("--checkin".equals(arg)) {
1350                     checkin = true;
1351                 } else if ("-c".equals(arg)) {
1352                     compact = true;
1353                 } else if ("flush".equals(arg)) {
1354                     synchronized (mLock) {
1355                         flushToDiskLocked();
1356                     }
1357                     mAppStandby.flushToDisk();
1358                     pw.println("Flushed stats to disk");
1359                     return;
1360                 } else if ("is-app-standby-enabled".equals(arg)) {
1361                     pw.println(mAppStandby.isAppIdleEnabled());
1362                     return;
1363                 } else if ("apptimelimit".equals(arg)) {
1364                     synchronized (mLock) {
1365                         if (i + 1 >= args.length) {
1366                             mAppTimeLimit.dump(null, pw);
1367                         } else {
1368                             final String[] remainingArgs =
1369                                     Arrays.copyOfRange(args, i + 1, args.length);
1370                             mAppTimeLimit.dump(remainingArgs, pw);
1371                         }
1372                         return;
1373                     }
1374                 } else if ("file".equals(arg)) {
1375                     final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1376                     synchronized (mLock) {
1377                         if (i + 1 >= args.length) {
1378                             // dump everything for all users
1379                             final int numUsers = mUserState.size();
1380                             for (int user = 0; user < numUsers; user++) {
1381                                 final int userId = mUserState.keyAt(user);
1382                                 if (!mUserUnlockedStates.contains(userId)) {
1383                                     continue;
1384                                 }
1385                                 ipw.println("user=" + userId);
1386                                 ipw.increaseIndent();
1387                                 mUserState.valueAt(user).dumpFile(ipw, null);
1388                                 ipw.decreaseIndent();
1389                             }
1390                         } else {
1391                             final int user = parseUserIdFromArgs(args, i, ipw);
1392                             if (user != UserHandle.USER_NULL) {
1393                                 final String[] remainingArgs = Arrays.copyOfRange(
1394                                         args, i + 2, args.length);
1395                                 // dump everything for the specified user
1396                                 mUserState.get(user).dumpFile(ipw, remainingArgs);
1397                             }
1398                         }
1399                         return;
1400                     }
1401                 } else if ("database-info".equals(arg)) {
1402                     final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1403                     synchronized (mLock) {
1404                         if (i + 1 >= args.length) {
1405                             // dump info for all users
1406                             final int numUsers = mUserState.size();
1407                             for (int user = 0; user < numUsers; user++) {
1408                                 final int userId = mUserState.keyAt(user);
1409                                 if (!mUserUnlockedStates.contains(userId)) {
1410                                     continue;
1411                                 }
1412                                 ipw.println("user=" + userId);
1413                                 ipw.increaseIndent();
1414                                 mUserState.valueAt(user).dumpDatabaseInfo(ipw);
1415                                 ipw.decreaseIndent();
1416                             }
1417                         } else {
1418                             final int user = parseUserIdFromArgs(args, i, ipw);
1419                             if (user != UserHandle.USER_NULL) {
1420                                 // dump info only for the specified user
1421                                 mUserState.get(user).dumpDatabaseInfo(ipw);
1422                             }
1423                         }
1424                         return;
1425                     }
1426                 } else if ("appstandby".equals(arg)) {
1427                     mAppStandby.dumpState(args, pw);
1428                     return;
1429                 } else if ("stats-directory".equals(arg)) {
1430                     final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1431                     synchronized (mLock) {
1432                         final int userId = parseUserIdFromArgs(args, i, ipw);
1433                         if (userId != UserHandle.USER_NULL) {
1434                             ipw.println(new File(Environment.getDataSystemCeDirectory(userId),
1435                                     "usagestats").getAbsolutePath());
1436                         }
1437                         return;
1438                     }
1439                 } else if ("mappings".equals(arg)) {
1440                     final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
1441                     final int userId = parseUserIdFromArgs(args, i, ipw);
1442                     synchronized (mLock) {
1443                         if (userId != UserHandle.USER_NULL) {
1444                             mUserState.get(userId).dumpMappings(ipw);
1445                         }
1446                         return;
1447                     }
1448                 } else if (arg != null && !arg.startsWith("-")) {
1449                     // Anything else that doesn't start with '-' is a pkg to filter
1450                     pkgs.add(arg);
1451                 }
1452             }
1453         }
1454 
1455         final int[] userIds;
1456         synchronized (mLock) {
1457             final int userCount = mUserState.size();
1458             userIds = new int[userCount];
1459             for (int i = 0; i < userCount; i++) {
1460                 final int userId = mUserState.keyAt(i);
1461                 userIds[i] = userId;
1462                 idpw.printPair("user", userId);
1463                 idpw.println();
1464                 idpw.increaseIndent();
1465                 if (mUserUnlockedStates.contains(userId)) {
1466                     if (checkin) {
1467                         mUserState.valueAt(i).checkin(idpw);
1468                     } else {
1469                         mUserState.valueAt(i).dump(idpw, pkgs, compact);
1470                         idpw.println();
1471                     }
1472                 }
1473                 idpw.decreaseIndent();
1474             }
1475 
1476             idpw.println();
1477             idpw.printPair("Usage Source", UsageStatsManager.usageSourceToString(mUsageSource));
1478             idpw.println();
1479 
1480             mAppTimeLimit.dump(null, pw);
1481         }
1482 
1483         mAppStandby.dumpUsers(idpw, userIds, pkgs);
1484 
1485         if (CollectionUtils.isEmpty(pkgs)) {
1486             pw.println();
1487             mAppStandby.dumpState(args, pw);
1488         }
1489     }
1490 
parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw)1491     private int parseUserIdFromArgs(String[] args, int index, IndentingPrintWriter ipw) {
1492         final int userId;
1493         try {
1494             userId = Integer.parseInt(args[index + 1]);
1495         } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
1496             ipw.println("invalid user specified.");
1497             return UserHandle.USER_NULL;
1498         }
1499         if (mUserState.indexOfKey(userId) < 0) {
1500             ipw.println("the specified user does not exist.");
1501             return UserHandle.USER_NULL;
1502         }
1503         if (!mUserUnlockedStates.contains(userId)) {
1504             ipw.println("the specified user is currently in a locked state.");
1505             return UserHandle.USER_NULL;
1506         }
1507         return userId;
1508     }
1509 
1510     class H extends Handler {
H(Looper looper)1511         public H(Looper looper) {
1512             super(looper);
1513         }
1514 
1515         @Override
handleMessage(Message msg)1516         public void handleMessage(Message msg) {
1517             switch (msg.what) {
1518                 case MSG_REPORT_EVENT:
1519                     reportEvent((Event) msg.obj, msg.arg1);
1520                     break;
1521                 case MSG_REPORT_EVENT_TO_ALL_USERID:
1522                     reportEventToAllUserId((Event) msg.obj);
1523                     break;
1524                 case MSG_FLUSH_TO_DISK:
1525                     flushToDisk();
1526                     break;
1527                 case MSG_UNLOCKED_USER:
1528                     try {
1529                         onUserUnlocked(msg.arg1);
1530                     } catch (Exception e) {
1531                         if (mUserManager.isUserUnlocked(msg.arg1)) {
1532                             throw e; // rethrow exception - user is unlocked
1533                         } else {
1534                             Slog.w(TAG, "Attempted to unlock stopped or removed user " + msg.arg1);
1535                         }
1536                     }
1537                     break;
1538                 case MSG_REMOVE_USER:
1539                     onUserRemoved(msg.arg1);
1540                     break;
1541                 case MSG_PACKAGE_REMOVED:
1542                     onPackageRemoved(msg.arg1, (String) msg.obj);
1543                     break;
1544                 case MSG_UID_STATE_CHANGED: {
1545                     final int uid = msg.arg1;
1546                     final int procState = msg.arg2;
1547 
1548                     final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
1549                     synchronized (mUidToKernelCounter) {
1550                         final int oldCounter = mUidToKernelCounter.get(uid, 0);
1551                         if (newCounter != oldCounter) {
1552                             mUidToKernelCounter.put(uid, newCounter);
1553                             try {
1554                                 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter);
1555                             } catch (IOException e) {
1556                                 Slog.w(TAG, "Failed to update counter set: " + e);
1557                             }
1558                         }
1559                     }
1560                     break;
1561                 }
1562                 case MSG_ON_START:
1563                     synchronized (mLock) {
1564                         loadGlobalComponentUsageLocked();
1565                     }
1566                     break;
1567                 default:
1568                     super.handleMessage(msg);
1569                     break;
1570             }
1571         }
1572     }
1573 
1574     private final class BinderService extends IUsageStatsManager.Stub {
1575 
hasPermission(String callingPackage)1576         private boolean hasPermission(String callingPackage) {
1577             final int callingUid = Binder.getCallingUid();
1578             if (callingUid == Process.SYSTEM_UID) {
1579                 return true;
1580             }
1581             final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
1582                     callingUid, callingPackage);
1583             if (mode == AppOpsManager.MODE_DEFAULT) {
1584                 // The default behavior here is to check if PackageManager has given the app
1585                 // permission.
1586                 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
1587                         == PackageManager.PERMISSION_GRANTED;
1588             }
1589             return mode == AppOpsManager.MODE_ALLOWED;
1590         }
1591 
hasObserverPermission()1592         private boolean hasObserverPermission() {
1593             final int callingUid = Binder.getCallingUid();
1594             DevicePolicyManagerInternal dpmInternal = getDpmInternal();
1595             //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode.
1596             if (callingUid == Process.SYSTEM_UID
1597                     || (dpmInternal != null
1598                         && (dpmInternal.isActiveProfileOwner(callingUid)
1599                         || dpmInternal.isActiveDeviceOwner(callingUid)))) {
1600                 // Caller is the system or the profile owner, so proceed.
1601                 return true;
1602             }
1603             return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE)
1604                     == PackageManager.PERMISSION_GRANTED;
1605         }
1606 
hasPermissions(String callingPackage, String... permissions)1607         private boolean hasPermissions(String callingPackage, String... permissions) {
1608             final int callingUid = Binder.getCallingUid();
1609             if (callingUid == Process.SYSTEM_UID) {
1610                 // Caller is the system, so proceed.
1611                 return true;
1612             }
1613 
1614             boolean hasPermissions = true;
1615             final Context context = getContext();
1616             for (int i = 0; i < permissions.length; i++) {
1617                 hasPermissions = hasPermissions && (context.checkCallingPermission(permissions[i])
1618                         == PackageManager.PERMISSION_GRANTED);
1619             }
1620             return hasPermissions;
1621         }
1622 
checkCallerIsSystemOrSameApp(String pkg)1623         private void checkCallerIsSystemOrSameApp(String pkg) {
1624             if (isCallingUidSystem()) {
1625                 return;
1626             }
1627             checkCallerIsSameApp(pkg);
1628         }
1629 
checkCallerIsSameApp(String pkg)1630         private void checkCallerIsSameApp(String pkg) {
1631             final int callingUid = Binder.getCallingUid();
1632             final int callingUserId = UserHandle.getUserId(callingUid);
1633 
1634             if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0,
1635                     callingUserId) != callingUid) {
1636                 throw new SecurityException("Calling uid " + callingUid + " cannot query events"
1637                         + "for package " + pkg);
1638             }
1639         }
1640 
isCallingUidSystem()1641         private boolean isCallingUidSystem() {
1642             final int uid = UserHandle.getAppId(Binder.getCallingUid()); // ignores user
1643             return uid == Process.SYSTEM_UID;
1644         }
1645 
1646         @Override
queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage, int userId)1647         public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
1648                 long endTime, String callingPackage, int userId) {
1649             if (!hasPermission(callingPackage)) {
1650                 return null;
1651             }
1652 
1653             final int callingUid = Binder.getCallingUid();
1654             userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), callingUid,
1655                     userId, false, true, "queryUsageStats", callingPackage);
1656 
1657             // Check the caller's userId for obfuscation decision, not the user being queried
1658             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1659                     callingUid, UserHandle.getCallingUserId());
1660 
1661             final long token = Binder.clearCallingIdentity();
1662             try {
1663                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
1664                         userId, bucketType, beginTime, endTime, obfuscateInstantApps);
1665                 if (results != null) {
1666                     return new ParceledListSlice<>(results);
1667                 }
1668             } finally {
1669                 Binder.restoreCallingIdentity(token);
1670             }
1671             return null;
1672         }
1673 
1674         @Override
queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)1675         public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
1676                 long beginTime, long endTime, String callingPackage) throws RemoteException {
1677             if (!hasPermission(callingPackage)) {
1678                 return null;
1679             }
1680 
1681             final int userId = UserHandle.getCallingUserId();
1682             final long token = Binder.clearCallingIdentity();
1683             try {
1684                 final List<ConfigurationStats> results =
1685                         UsageStatsService.this.queryConfigurationStats(userId, bucketType,
1686                                 beginTime, endTime);
1687                 if (results != null) {
1688                     return new ParceledListSlice<>(results);
1689                 }
1690             } finally {
1691                 Binder.restoreCallingIdentity(token);
1692             }
1693             return null;
1694         }
1695 
1696         @Override
queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)1697         public ParceledListSlice<EventStats> queryEventStats(int bucketType,
1698                 long beginTime, long endTime, String callingPackage) throws RemoteException {
1699             if (!hasPermission(callingPackage)) {
1700                 return null;
1701             }
1702 
1703             final int userId = UserHandle.getCallingUserId();
1704             final long token = Binder.clearCallingIdentity();
1705             try {
1706                 final List<EventStats> results =
1707                         UsageStatsService.this.queryEventStats(userId, bucketType,
1708                                 beginTime, endTime);
1709                 if (results != null) {
1710                     return new ParceledListSlice<>(results);
1711                 }
1712             } finally {
1713                 Binder.restoreCallingIdentity(token);
1714             }
1715             return null;
1716         }
1717 
1718         @Override
queryEvents(long beginTime, long endTime, String callingPackage)1719         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
1720             if (!hasPermission(callingPackage)) {
1721                 return null;
1722             }
1723 
1724             final int userId = UserHandle.getCallingUserId();
1725             final int callingUid = Binder.getCallingUid();
1726             final int callingPid = Binder.getCallingPid();
1727             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1728                     callingUid, userId);
1729 
1730             final long token = Binder.clearCallingIdentity();
1731             try {
1732                 final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
1733                         userId, callingPackage, callingPid, callingUid);
1734                 final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
1735                 final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
1736                         callingPid, callingUid);
1737                 int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
1738                 if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
1739                 if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
1740                 if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
1741                 if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
1742                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
1743             } finally {
1744                 Binder.restoreCallingIdentity(token);
1745             }
1746         }
1747 
1748         @Override
queryEventsForPackage(long beginTime, long endTime, String callingPackage)1749         public UsageEvents queryEventsForPackage(long beginTime, long endTime,
1750                 String callingPackage) {
1751             final int callingUid = Binder.getCallingUid();
1752             final int callingUserId = UserHandle.getUserId(callingUid);
1753 
1754             checkCallerIsSameApp(callingPackage);
1755             final boolean includeTaskRoot = hasPermission(callingPackage);
1756 
1757             final long token = Binder.clearCallingIdentity();
1758             try {
1759                 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
1760                         endTime, callingPackage, includeTaskRoot);
1761             } finally {
1762                 Binder.restoreCallingIdentity(token);
1763             }
1764         }
1765 
1766         @Override
queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)1767         public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId,
1768                 String callingPackage) {
1769             if (!hasPermission(callingPackage)) {
1770                 return null;
1771             }
1772 
1773             final int callingUserId = UserHandle.getCallingUserId();
1774             if (userId != callingUserId) {
1775                 getContext().enforceCallingPermission(
1776                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1777                         "No permission to query usage stats for this user");
1778             }
1779 
1780             final int callingUid = Binder.getCallingUid();
1781             final int callingPid = Binder.getCallingPid();
1782             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1783                     callingUid, callingUserId);
1784 
1785             final long token = Binder.clearCallingIdentity();
1786             try {
1787                 final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
1788                         userId, callingPackage, callingPid, callingUid);
1789                 final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
1790                         callingPid, callingUid);
1791                 boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
1792                 int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
1793                 if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
1794                 if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
1795                 if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
1796                 if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
1797                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
1798             } finally {
1799                 Binder.restoreCallingIdentity(token);
1800             }
1801         }
1802 
1803         @Override
queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)1804         public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime,
1805                 int userId, String pkg, String callingPackage) {
1806             if (!hasPermission(callingPackage)) {
1807                 return null;
1808             }
1809             if (userId != UserHandle.getCallingUserId()) {
1810                 getContext().enforceCallingPermission(
1811                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1812                         "No permission to query usage stats for this user");
1813             }
1814             checkCallerIsSystemOrSameApp(pkg);
1815 
1816             final long token = Binder.clearCallingIdentity();
1817             try {
1818                 return UsageStatsService.this.queryEventsForPackage(userId, beginTime,
1819                         endTime, pkg, true);
1820             } finally {
1821                 Binder.restoreCallingIdentity(token);
1822             }
1823         }
1824 
1825         @Override
isAppInactive(String packageName, int userId, String callingPackage)1826         public boolean isAppInactive(String packageName, int userId, String callingPackage) {
1827             final int callingUid = Binder.getCallingUid();
1828             try {
1829                 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
1830                         callingUid, userId, false, false, "isAppInactive", null);
1831             } catch (RemoteException re) {
1832                 throw re.rethrowFromSystemServer();
1833             }
1834 
1835             // If the calling app is asking about itself, continue, else check for permission.
1836             if (packageName.equals(callingPackage)) {
1837                 final int actualCallingUid = mPackageManagerInternal.getPackageUid(
1838                         callingPackage, /* flags= */ 0, userId);
1839                 if (actualCallingUid != callingUid) {
1840                     return false;
1841                 }
1842             } else if (!hasPermission(callingPackage)) {
1843                 return false;
1844             }
1845             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1846                     callingUid, userId);
1847             final long token = Binder.clearCallingIdentity();
1848             try {
1849                 return mAppStandby.isAppIdleFiltered(
1850                         packageName, userId,
1851                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
1852             } finally {
1853                 Binder.restoreCallingIdentity(token);
1854             }
1855         }
1856 
1857         @Override
setAppInactive(String packageName, boolean idle, int userId)1858         public void setAppInactive(String packageName, boolean idle, int userId) {
1859             final int callingUid = Binder.getCallingUid();
1860             try {
1861                 userId = ActivityManager.getService().handleIncomingUser(
1862                         Binder.getCallingPid(), callingUid, userId, false, true,
1863                         "setAppInactive", null);
1864             } catch (RemoteException re) {
1865                 throw re.rethrowFromSystemServer();
1866             }
1867             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1868                     "No permission to change app idle state");
1869             final long token = Binder.clearCallingIdentity();
1870             try {
1871                 final int appId = mAppStandby.getAppId(packageName);
1872                 if (appId < 0) return;
1873                 mAppStandby.setAppIdleAsync(packageName, idle, userId);
1874             } finally {
1875                 Binder.restoreCallingIdentity(token);
1876             }
1877         }
1878 
1879         @Override
getAppStandbyBucket(String packageName, String callingPackage, int userId)1880         public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
1881             final int callingUid = Binder.getCallingUid();
1882             try {
1883                 userId = ActivityManager.getService().handleIncomingUser(
1884                         Binder.getCallingPid(), callingUid, userId, false, false,
1885                         "getAppStandbyBucket", null);
1886             } catch (RemoteException re) {
1887                 throw re.rethrowFromSystemServer();
1888             }
1889             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
1890             // If the calling app is asking about itself, continue, else check for permission.
1891             if (packageUid != callingUid) {
1892                 if (!hasPermission(callingPackage)) {
1893                     throw new SecurityException(
1894                             "Don't have permission to query app standby bucket");
1895                 }
1896             }
1897             if (packageUid < 0) {
1898                 throw new IllegalArgumentException(
1899                         "Cannot get standby bucket for non existent package (" + packageName + ")");
1900             }
1901             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
1902                     userId);
1903             final long token = Binder.clearCallingIdentity();
1904             try {
1905                 return mAppStandby.getAppStandbyBucket(packageName, userId,
1906                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
1907             } finally {
1908                 Binder.restoreCallingIdentity(token);
1909             }
1910         }
1911 
1912         @Override
setAppStandbyBucket(String packageName, int bucket, int userId)1913         public void setAppStandbyBucket(String packageName, int bucket, int userId) {
1914             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1915                     "No permission to change app standby state");
1916 
1917             final int callingUid = Binder.getCallingUid();
1918             final int callingPid = Binder.getCallingPid();
1919             final long token = Binder.clearCallingIdentity();
1920             try {
1921                 mAppStandby.setAppStandbyBucket(packageName, bucket, userId,
1922                         callingUid, callingPid);
1923             } finally {
1924                 Binder.restoreCallingIdentity(token);
1925             }
1926         }
1927 
1928         @Override
getAppStandbyBuckets(String callingPackageName, int userId)1929         public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName,
1930                 int userId) {
1931             final int callingUid = Binder.getCallingUid();
1932             try {
1933                 userId = ActivityManager.getService().handleIncomingUser(
1934                         Binder.getCallingPid(), callingUid, userId, false, false,
1935                         "getAppStandbyBucket", null);
1936             } catch (RemoteException re) {
1937                 throw re.rethrowFromSystemServer();
1938             }
1939             if (!hasPermission(callingPackageName)) {
1940                 throw new SecurityException(
1941                         "Don't have permission to query app standby bucket");
1942             }
1943             final long token = Binder.clearCallingIdentity();
1944             try {
1945                 final List<AppStandbyInfo> standbyBucketList =
1946                         mAppStandby.getAppStandbyBuckets(userId);
1947                 return (standbyBucketList == null) ? ParceledListSlice.emptyList()
1948                         : new ParceledListSlice<>(standbyBucketList);
1949             } finally {
1950                 Binder.restoreCallingIdentity(token);
1951             }
1952         }
1953 
1954         @Override
setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)1955         public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) {
1956             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1957                     "No permission to change app standby state");
1958 
1959             final int callingUid = Binder.getCallingUid();
1960             final int callingPid = Binder.getCallingPid();
1961             final long token = Binder.clearCallingIdentity();
1962             try {
1963                 mAppStandby.setAppStandbyBuckets(appBuckets.getList(), userId,
1964                         callingUid, callingPid);
1965             } finally {
1966                 Binder.restoreCallingIdentity(token);
1967             }
1968         }
1969 
1970         @Override
onCarrierPrivilegedAppsChanged()1971         public void onCarrierPrivilegedAppsChanged() {
1972             if (DEBUG) {
1973                 Slog.i(TAG, "Carrier privileged apps changed");
1974             }
1975             getContext().enforceCallingOrSelfPermission(
1976                     android.Manifest.permission.BIND_CARRIER_SERVICES,
1977                     "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
1978             mAppStandby.clearCarrierPrivilegedApps();
1979         }
1980 
1981         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1982         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1983             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
1984             UsageStatsService.this.dump(args, pw);
1985         }
1986 
1987         @Override
reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1988         public void reportChooserSelection(String packageName, int userId, String contentType,
1989                                            String[] annotations, String action) {
1990             if (packageName == null) {
1991                 Slog.w(TAG, "Event report user selecting a null package");
1992                 return;
1993             }
1994 
1995             Event event = new Event(CHOOSER_ACTION, SystemClock.elapsedRealtime());
1996             event.mPackage = packageName;
1997             event.mAction = action;
1998             event.mContentType = contentType;
1999             event.mContentAnnotations = annotations;
2000             reportEventOrAddToQueue(userId, event);
2001         }
2002 
2003         @Override
reportUserInteraction(String packageName, int userId)2004         public void reportUserInteraction(String packageName, int userId) {
2005             Objects.requireNonNull(packageName);
2006             if (!isCallingUidSystem()) {
2007                 throw new SecurityException("Only system is allowed to call reportUserInteraction");
2008             }
2009             final Event event = new Event(USER_INTERACTION, SystemClock.elapsedRealtime());
2010             event.mPackage = packageName;
2011             reportEventOrAddToQueue(userId, event);
2012         }
2013 
2014         @Override
registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)2015         public void registerAppUsageObserver(int observerId,
2016                 String[] packages, long timeLimitMs, PendingIntent
2017                 callbackIntent, String callingPackage) {
2018             if (!hasObserverPermission()) {
2019                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
2020             }
2021 
2022             if (packages == null || packages.length == 0) {
2023                 throw new IllegalArgumentException("Must specify at least one package");
2024             }
2025             if (callbackIntent == null) {
2026                 throw new NullPointerException("callbackIntent can't be null");
2027             }
2028             final int callingUid = Binder.getCallingUid();
2029             final int userId = UserHandle.getUserId(callingUid);
2030             final long token = Binder.clearCallingIdentity();
2031             try {
2032                 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId,
2033                         packages, timeLimitMs, callbackIntent, userId);
2034             } finally {
2035                 Binder.restoreCallingIdentity(token);
2036             }
2037         }
2038 
2039         @Override
unregisterAppUsageObserver(int observerId, String callingPackage)2040         public void unregisterAppUsageObserver(int observerId, String callingPackage) {
2041             if (!hasObserverPermission()) {
2042                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
2043             }
2044 
2045             final int callingUid = Binder.getCallingUid();
2046             final int userId = UserHandle.getUserId(callingUid);
2047             final long token = Binder.clearCallingIdentity();
2048             try {
2049                 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId);
2050             } finally {
2051                 Binder.restoreCallingIdentity(token);
2052             }
2053         }
2054 
2055         @Override
registerUsageSessionObserver(int sessionObserverId, String[] observed, long timeLimitMs, long sessionThresholdTimeMs, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, String callingPackage)2056         public void registerUsageSessionObserver(int sessionObserverId, String[] observed,
2057                 long timeLimitMs, long sessionThresholdTimeMs,
2058                 PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent,
2059                 String callingPackage) {
2060             if (!hasObserverPermission()) {
2061                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
2062             }
2063 
2064             if (observed == null || observed.length == 0) {
2065                 throw new IllegalArgumentException("Must specify at least one observed entity");
2066             }
2067             if (limitReachedCallbackIntent == null) {
2068                 throw new NullPointerException("limitReachedCallbackIntent can't be null");
2069             }
2070             final int callingUid = Binder.getCallingUid();
2071             final int userId = UserHandle.getUserId(callingUid);
2072             final long token = Binder.clearCallingIdentity();
2073             try {
2074                 UsageStatsService.this.registerUsageSessionObserver(callingUid, sessionObserverId,
2075                         observed, timeLimitMs, sessionThresholdTimeMs, limitReachedCallbackIntent,
2076                         sessionEndCallbackIntent, userId);
2077             } finally {
2078                 Binder.restoreCallingIdentity(token);
2079             }
2080         }
2081 
2082         @Override
unregisterUsageSessionObserver(int sessionObserverId, String callingPackage)2083         public void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage) {
2084             if (!hasObserverPermission()) {
2085                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
2086             }
2087 
2088             final int callingUid = Binder.getCallingUid();
2089             final int userId = UserHandle.getUserId(callingUid);
2090             final long token = Binder.clearCallingIdentity();
2091             try {
2092                 UsageStatsService.this.unregisterUsageSessionObserver(callingUid, sessionObserverId,
2093                         userId);
2094             } finally {
2095                 Binder.restoreCallingIdentity(token);
2096             }
2097         }
2098 
2099         @Override
registerAppUsageLimitObserver(int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, String callingPackage)2100         public void registerAppUsageLimitObserver(int observerId, String[] packages,
2101                 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent,
2102                 String callingPackage) {
2103             final int callingUid = Binder.getCallingUid();
2104             final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
2105             if (!hasPermissions(callingPackage,
2106                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
2107                     && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
2108                 throw new SecurityException("Caller must be the active supervision app or "
2109                         + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
2110             }
2111 
2112             if (packages == null || packages.length == 0) {
2113                 throw new IllegalArgumentException("Must specify at least one package");
2114             }
2115             if (callbackIntent == null && timeUsedMs < timeLimitMs) {
2116                 throw new NullPointerException("callbackIntent can't be null");
2117             }
2118             final int userId = UserHandle.getUserId(callingUid);
2119             final long token = Binder.clearCallingIdentity();
2120             try {
2121                 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId,
2122                         packages, timeLimitMs, timeUsedMs, callbackIntent, userId);
2123             } finally {
2124                 Binder.restoreCallingIdentity(token);
2125             }
2126         }
2127 
2128         @Override
unregisterAppUsageLimitObserver(int observerId, String callingPackage)2129         public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) {
2130             final int callingUid = Binder.getCallingUid();
2131             final DevicePolicyManagerInternal dpmInternal = getDpmInternal();
2132             if (!hasPermissions(callingPackage,
2133                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)
2134                     && (dpmInternal == null || !dpmInternal.isActiveSupervisionApp(callingUid))) {
2135                 throw new SecurityException("Caller must be the active supervision app or "
2136                         + "it must have both SUSPEND_APPS and OBSERVE_APP_USAGE permissions");
2137             }
2138 
2139             final int userId = UserHandle.getUserId(callingUid);
2140             final long token = Binder.clearCallingIdentity();
2141             try {
2142                 UsageStatsService.this.unregisterAppUsageLimitObserver(
2143                         callingUid, observerId, userId);
2144             } finally {
2145                 Binder.restoreCallingIdentity(token);
2146             }
2147         }
2148 
2149         @Override
reportUsageStart(IBinder activity, String token, String callingPackage)2150         public void reportUsageStart(IBinder activity, String token, String callingPackage) {
2151             reportPastUsageStart(activity, token, 0, callingPackage);
2152         }
2153 
2154         @Override
reportPastUsageStart(IBinder activity, String token, long timeAgoMs, String callingPackage)2155         public void reportPastUsageStart(IBinder activity, String token, long timeAgoMs,
2156                 String callingPackage) {
2157 
2158             final int callingUid = Binder.getCallingUid();
2159             final int userId = UserHandle.getUserId(callingUid);
2160             final long binderToken = Binder.clearCallingIdentity();
2161             try {
2162                 ArraySet<String> tokens;
2163                 synchronized (mUsageReporters) {
2164                     tokens = mUsageReporters.get(activity.hashCode());
2165                     if (tokens == null) {
2166                         tokens = new ArraySet();
2167                         mUsageReporters.put(activity.hashCode(), tokens);
2168                     }
2169                 }
2170 
2171                 synchronized (tokens) {
2172                     if (!tokens.add(token)) {
2173                         throw new IllegalArgumentException(token + " for " + callingPackage
2174                                 + " is already reported as started for this activity");
2175                     }
2176                 }
2177 
2178                 mAppTimeLimit.noteUsageStart(buildFullToken(callingPackage, token),
2179                         userId, timeAgoMs);
2180             } finally {
2181                 Binder.restoreCallingIdentity(binderToken);
2182             }
2183         }
2184 
2185         @Override
reportUsageStop(IBinder activity, String token, String callingPackage)2186         public void reportUsageStop(IBinder activity, String token, String callingPackage) {
2187             final int callingUid = Binder.getCallingUid();
2188             final int userId = UserHandle.getUserId(callingUid);
2189             final long binderToken = Binder.clearCallingIdentity();
2190             try {
2191                 ArraySet<String> tokens;
2192                 synchronized (mUsageReporters) {
2193                     tokens = mUsageReporters.get(activity.hashCode());
2194                     if (tokens == null) {
2195                         throw new IllegalArgumentException(
2196                                 "Unknown reporter trying to stop token " + token + " for "
2197                                         + callingPackage);
2198                     }
2199                 }
2200 
2201                 synchronized (tokens) {
2202                     if (!tokens.remove(token)) {
2203                         throw new IllegalArgumentException(token + " for " + callingPackage
2204                                 + " is already reported as stopped for this activity");
2205                     }
2206                 }
2207                 mAppTimeLimit.noteUsageStop(buildFullToken(callingPackage, token), userId);
2208             } finally {
2209                 Binder.restoreCallingIdentity(binderToken);
2210             }
2211         }
2212 
2213         @Override
getUsageSource()2214         public @UsageSource int getUsageSource() {
2215             if (!hasObserverPermission()) {
2216                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
2217             }
2218             synchronized (mLock) {
2219                 return mUsageSource;
2220             }
2221         }
2222 
2223         @Override
forceUsageSourceSettingRead()2224         public void forceUsageSourceSettingRead() {
2225             readUsageSourceSetting();
2226         }
2227 
2228         @Override
getLastTimeAnyComponentUsed(String packageName, String callingPackage)2229         public long getLastTimeAnyComponentUsed(String packageName, String callingPackage) {
2230             if (!hasPermissions(
2231                     callingPackage, android.Manifest.permission.INTERACT_ACROSS_USERS)) {
2232                 throw new SecurityException("Caller doesn't have INTERACT_ACROSS_USERS permission");
2233             }
2234             if (!hasPermission(callingPackage)) {
2235                 throw new SecurityException("Don't have permission to query usage stats");
2236             }
2237             synchronized (mLock) {
2238                 // Truncate the returned milliseconds to the boundary of the last day before exact
2239                 // time for privacy reasons.
2240                 return mLastTimeComponentUsedGlobal.getOrDefault(packageName, 0L)
2241                         / TimeUnit.DAYS.toMillis(1) * TimeUnit.DAYS.toMillis(1);
2242             }
2243         }
2244     }
2245 
registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)2246     void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
2247             long timeLimitMs, PendingIntent callbackIntent, int userId) {
2248         mAppTimeLimit.addAppUsageObserver(callingUid, observerId, packages, timeLimitMs,
2249                 callbackIntent,
2250                 userId);
2251     }
2252 
unregisterAppUsageObserver(int callingUid, int observerId, int userId)2253     void unregisterAppUsageObserver(int callingUid, int observerId, int userId) {
2254         mAppTimeLimit.removeAppUsageObserver(callingUid, observerId, userId);
2255     }
2256 
registerUsageSessionObserver(int callingUid, int observerId, String[] observed, long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, int userId)2257     void registerUsageSessionObserver(int callingUid, int observerId, String[] observed,
2258             long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent,
2259             PendingIntent sessionEndCallbackIntent, int userId) {
2260         mAppTimeLimit.addUsageSessionObserver(callingUid, observerId, observed, timeLimitMs,
2261                 sessionThresholdTime, limitReachedCallbackIntent, sessionEndCallbackIntent, userId);
2262     }
2263 
unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId)2264     void unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId) {
2265         mAppTimeLimit.removeUsageSessionObserver(callingUid, sessionObserverId, userId);
2266     }
2267 
registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId)2268     void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages,
2269             long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId) {
2270         mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages,
2271                 timeLimitMs, timeUsedMs, callbackIntent, userId);
2272     }
2273 
unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId)2274     void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) {
2275         mAppTimeLimit.removeAppUsageLimitObserver(callingUid, observerId, userId);
2276     }
2277 
2278     /**
2279      * This local service implementation is primarily used by ActivityManagerService.
2280      * ActivityManagerService will call these methods holding the 'am' lock, which means we
2281      * shouldn't be doing any IO work or other long running tasks in these methods.
2282      */
2283     private final class LocalService extends UsageStatsManagerInternal {
2284 
2285         @Override
reportEvent(ComponentName component, int userId, int eventType, int instanceId, ComponentName taskRoot)2286         public void reportEvent(ComponentName component, int userId, int eventType,
2287                 int instanceId, ComponentName taskRoot) {
2288             if (component == null) {
2289                 Slog.w(TAG, "Event reported without a component name");
2290                 return;
2291             }
2292 
2293             Event event = new Event(eventType, SystemClock.elapsedRealtime());
2294             event.mPackage = component.getPackageName();
2295             event.mClass = component.getClassName();
2296             event.mInstanceId = instanceId;
2297             if (taskRoot == null) {
2298                 event.mTaskRootPackage = null;
2299                 event.mTaskRootClass = null;
2300             } else {
2301                 event.mTaskRootPackage = taskRoot.getPackageName();
2302                 event.mTaskRootClass = taskRoot.getClassName();
2303             }
2304             reportEventOrAddToQueue(userId, event);
2305         }
2306 
2307         @Override
reportEvent(String packageName, int userId, int eventType)2308         public void reportEvent(String packageName, int userId, int eventType) {
2309             if (packageName == null) {
2310                 Slog.w(TAG, "Event reported without a package name, eventType:" + eventType);
2311                 return;
2312             }
2313 
2314             Event event = new Event(eventType, SystemClock.elapsedRealtime());
2315             event.mPackage = packageName;
2316             reportEventOrAddToQueue(userId, event);
2317         }
2318 
2319         @Override
reportConfigurationChange(Configuration config, int userId)2320         public void reportConfigurationChange(Configuration config, int userId) {
2321             if (config == null) {
2322                 Slog.w(TAG, "Configuration event reported with a null config");
2323                 return;
2324             }
2325 
2326             Event event = new Event(CONFIGURATION_CHANGE, SystemClock.elapsedRealtime());
2327             event.mPackage = "android";
2328             event.mConfiguration = new Configuration(config);
2329             reportEventOrAddToQueue(userId, event);
2330         }
2331 
2332         @Override
reportInterruptiveNotification(String packageName, String channelId, int userId)2333         public void reportInterruptiveNotification(String packageName, String channelId,
2334                 int userId) {
2335             if (packageName == null || channelId == null) {
2336                 Slog.w(TAG, "Event reported without a package name or a channel ID");
2337                 return;
2338             }
2339 
2340             Event event = new Event(NOTIFICATION_INTERRUPTION, SystemClock.elapsedRealtime());
2341             event.mPackage = packageName.intern();
2342             event.mNotificationChannelId = channelId.intern();
2343             reportEventOrAddToQueue(userId, event);
2344         }
2345 
2346         @Override
reportShortcutUsage(String packageName, String shortcutId, int userId)2347         public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
2348             if (packageName == null || shortcutId == null) {
2349                 Slog.w(TAG, "Event reported without a package name or a shortcut ID");
2350                 return;
2351             }
2352 
2353             Event event = new Event(SHORTCUT_INVOCATION, SystemClock.elapsedRealtime());
2354             event.mPackage = packageName.intern();
2355             event.mShortcutId = shortcutId.intern();
2356             reportEventOrAddToQueue(userId, event);
2357         }
2358 
2359         @Override
reportLocusUpdate(@onNull ComponentName activity, @UserIdInt int userId, @Nullable LocusId locusId, @NonNull IBinder appToken)2360         public void reportLocusUpdate(@NonNull ComponentName activity, @UserIdInt int userId,
2361                 @Nullable LocusId locusId, @NonNull  IBinder appToken) {
2362             if (locusId == null) return;
2363             Event event = new Event(LOCUS_ID_SET, SystemClock.elapsedRealtime());
2364             event.mLocusId = locusId.getId();
2365             event.mPackage = activity.getPackageName();
2366             event.mClass = activity.getClassName();
2367             event.mInstanceId = appToken.hashCode();
2368             reportEventOrAddToQueue(userId, event);
2369         }
2370 
2371         @Override
reportContentProviderUsage(String name, String packageName, int userId)2372         public void reportContentProviderUsage(String name, String packageName, int userId) {
2373             mAppStandby.postReportContentProviderUsage(name, packageName, userId);
2374         }
2375 
2376         @Override
isAppIdle(String packageName, int uidForAppId, int userId)2377         public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
2378             return mAppStandby.isAppIdleFiltered(packageName, uidForAppId,
2379                     userId, SystemClock.elapsedRealtime());
2380         }
2381 
2382         @Override
getAppStandbyBucket(String packageName, int userId, long nowElapsed)2383         @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
2384                 long nowElapsed) {
2385             return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false);
2386         }
2387 
2388         @Override
getIdleUidsForUser(int userId)2389         public int[] getIdleUidsForUser(int userId) {
2390             return mAppStandby.getIdleUidsForUser(userId);
2391         }
2392 
2393         @Override
prepareShutdown()2394         public void prepareShutdown() {
2395             // This method *WILL* do IO work, but we must block until it is finished or else
2396             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
2397             // we are shutting down.
2398             UsageStatsService.this.shutdown();
2399         }
2400 
2401         @Override
prepareForPossibleShutdown()2402         public void prepareForPossibleShutdown() {
2403             UsageStatsService.this.prepareForPossibleShutdown();
2404         }
2405 
2406         @Override
getBackupPayload(int user, String key)2407         public byte[] getBackupPayload(int user, String key) {
2408             if (!mUserUnlockedStates.contains(user)) {
2409                 Slog.w(TAG, "Failed to get backup payload for locked user " + user);
2410                 return null;
2411             }
2412             synchronized (mLock) {
2413                 // Check to ensure that only user 0's data is b/r for now
2414                 // Note: if backup and restore is enabled for users other than the system user, the
2415                 // #onUserUnlocked logic, specifically when the update mappings job is scheduled via
2416                 // UsageStatsIdleService.scheduleUpdateMappingsJob, will have to be updated.
2417                 if (user == UserHandle.USER_SYSTEM) {
2418                     final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(user);
2419                     if (userStats == null) {
2420                         return null; // user was stopped or removed
2421                     }
2422                     return userStats.getBackupPayload(key);
2423                 } else {
2424                     return null;
2425                 }
2426             }
2427         }
2428 
2429         @Override
applyRestoredPayload(int user, String key, byte[] payload)2430         public void applyRestoredPayload(int user, String key, byte[] payload) {
2431             synchronized (mLock) {
2432                 if (!mUserUnlockedStates.contains(user)) {
2433                     Slog.w(TAG, "Failed to apply restored payload for locked user " + user);
2434                     return;
2435                 }
2436 
2437                 if (user == UserHandle.USER_SYSTEM) {
2438                     final UserUsageStatsService userStats = getUserUsageStatsServiceLocked(user);
2439                     if (userStats == null) {
2440                         return; // user was stopped or removed
2441                     }
2442                     userStats.applyRestoredPayload(key, payload);
2443                 }
2444             }
2445         }
2446 
2447         @Override
queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)2448         public List<UsageStats> queryUsageStatsForUser(
2449                 int userId, int intervalType, long beginTime, long endTime,
2450                 boolean obfuscateInstantApps) {
2451             return UsageStatsService.this.queryUsageStats(
2452                     userId, intervalType, beginTime, endTime, obfuscateInstantApps);
2453         }
2454 
2455         @Override
queryEventsForUser(int userId, long beginTime, long endTime, int flags)2456         public UsageEvents queryEventsForUser(int userId, long beginTime, long endTime, int flags) {
2457             return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
2458         }
2459 
2460         @Override
setLastJobRunTime(String packageName, int userId, long elapsedRealtime)2461         public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
2462             mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime);
2463         }
2464 
2465         @Override
getTimeSinceLastJobRun(String packageName, int userId)2466         public long getTimeSinceLastJobRun(String packageName, int userId) {
2467             return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
2468         }
2469 
2470         @Override
reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)2471         public void reportAppJobState(String packageName, int userId,
2472                 int numDeferredJobs, long timeSinceLastJobRun) {
2473         }
2474 
2475         @Override
onActiveAdminAdded(String packageName, int userId)2476         public void onActiveAdminAdded(String packageName, int userId) {
2477             mAppStandby.addActiveDeviceAdmin(packageName, userId);
2478         }
2479 
2480         @Override
setActiveAdminApps(Set<String> packageNames, int userId)2481         public void setActiveAdminApps(Set<String> packageNames, int userId) {
2482             mAppStandby.setActiveAdminApps(packageNames, userId);
2483         }
2484 
2485         @Override
onAdminDataAvailable()2486         public void onAdminDataAvailable() {
2487             mAppStandby.onAdminDataAvailable();
2488         }
2489 
2490         @Override
reportSyncScheduled(String packageName, int userId, boolean exempted)2491         public void reportSyncScheduled(String packageName, int userId, boolean exempted) {
2492             mAppStandby.postReportSyncScheduled(packageName, userId, exempted);
2493         }
2494 
2495         @Override
reportExemptedSyncStart(String packageName, int userId)2496         public void reportExemptedSyncStart(String packageName, int userId) {
2497             mAppStandby.postReportExemptedSyncStart(packageName, userId);
2498         }
2499 
2500         @Override
getAppUsageLimit(String packageName, UserHandle user)2501         public AppUsageLimitData getAppUsageLimit(String packageName, UserHandle user) {
2502             return mAppTimeLimit.getAppUsageLimit(packageName, user);
2503         }
2504 
2505         @Override
pruneUninstalledPackagesData(int userId)2506         public boolean pruneUninstalledPackagesData(int userId) {
2507             return UsageStatsService.this.pruneUninstalledPackagesData(userId);
2508         }
2509 
2510         @Override
updatePackageMappingsData()2511         public boolean updatePackageMappingsData() {
2512             return UsageStatsService.this.updatePackageMappingsData();
2513         }
2514 
2515         /**
2516          * Register a listener that will be notified of every new usage event.
2517          */
2518         @Override
registerListener(@onNull UsageEventListener listener)2519         public void registerListener(@NonNull UsageEventListener listener) {
2520             UsageStatsService.this.registerListener(listener);
2521         }
2522 
2523         /**
2524          * Unregister a listener from being notified of every new usage event.
2525          */
2526         @Override
unregisterListener(@onNull UsageEventListener listener)2527         public void unregisterListener(@NonNull UsageEventListener listener) {
2528             UsageStatsService.this.unregisterListener(listener);
2529         }
2530     }
2531 
2532     private class MyPackageMonitor extends PackageMonitor {
2533         @Override
onPackageRemoved(String packageName, int uid)2534         public void onPackageRemoved(String packageName, int uid) {
2535             mHandler.obtainMessage(MSG_PACKAGE_REMOVED, getChangingUserId(), 0, packageName)
2536                     .sendToTarget();
2537             super.onPackageRemoved(packageName, uid);
2538         }
2539     }
2540 }
2541