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