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