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