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