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