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