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