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_SHUTDOWN;
22 import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
23 import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION;
24 import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
25 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_CURRENT_ACTIVITY;
26 import static android.app.usage.UsageStatsManager.USAGE_SOURCE_TASK_ROOT_ACTIVITY;
27 
28 import android.Manifest;
29 import android.app.ActivityManager;
30 import android.app.AppOpsManager;
31 import android.app.IUidObserver;
32 import android.app.PendingIntent;
33 import android.app.admin.DeviceAdminInfo;
34 import android.app.admin.DevicePolicyManagerInternal;
35 import android.app.usage.AppStandbyInfo;
36 import android.app.usage.ConfigurationStats;
37 import android.app.usage.EventStats;
38 import android.app.usage.IUsageStatsManager;
39 import android.app.usage.UsageEvents;
40 import android.app.usage.UsageEvents.Event;
41 import android.app.usage.UsageStats;
42 import android.app.usage.UsageStatsManager;
43 import android.app.usage.UsageStatsManager.StandbyBuckets;
44 import android.app.usage.UsageStatsManager.UsageSource;
45 import android.app.usage.UsageStatsManagerInternal;
46 import android.content.BroadcastReceiver;
47 import android.content.ComponentName;
48 import android.content.Context;
49 import android.content.Intent;
50 import android.content.IntentFilter;
51 import android.content.pm.PackageManager;
52 import android.content.pm.PackageManagerInternal;
53 import android.content.pm.ParceledListSlice;
54 import android.content.pm.UserInfo;
55 import android.content.res.Configuration;
56 import android.os.Binder;
57 import android.os.Environment;
58 import android.os.FileUtils;
59 import android.os.Handler;
60 import android.os.IBinder;
61 import android.os.IDeviceIdleController;
62 import android.os.Looper;
63 import android.os.Message;
64 import android.os.Process;
65 import android.os.RemoteException;
66 import android.os.ServiceManager;
67 import android.os.SystemClock;
68 import android.os.SystemProperties;
69 import android.os.UserHandle;
70 import android.os.UserManager;
71 import android.provider.Settings;
72 import android.util.ArraySet;
73 import android.util.Slog;
74 import android.util.SparseArray;
75 import android.util.SparseIntArray;
76 
77 import com.android.internal.content.PackageMonitor;
78 import com.android.internal.os.BackgroundThread;
79 import com.android.internal.util.DumpUtils;
80 import com.android.internal.util.IndentingPrintWriter;
81 import com.android.server.LocalServices;
82 import com.android.server.SystemService;
83 
84 import java.io.File;
85 import java.io.FileDescriptor;
86 import java.io.IOException;
87 import java.io.PrintWriter;
88 import java.util.Arrays;
89 import java.util.List;
90 import java.util.Set;
91 
92 /**
93  * A service that collects, aggregates, and persists application usage data.
94  * This data can be queried by apps that have been granted permission by AppOps.
95  */
96 public class UsageStatsService extends SystemService implements
97         UserUsageStatsService.StatsUpdatedListener {
98 
99     static final String TAG = "UsageStatsService";
100     public static final boolean ENABLE_TIME_CHANGE_CORRECTION
101             = SystemProperties.getBoolean("persist.debug.time_correction", true);
102 
103     static final boolean DEBUG = false; // Never submit with true
104     static final boolean COMPRESS_TIME = false;
105 
106     private static final long TEN_SECONDS = 10 * 1000;
107     private static final long TWENTY_MINUTES = 20 * 60 * 1000;
108     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
109     private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
110 
111     private static final boolean ENABLE_KERNEL_UPDATES = true;
112     private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
113 
114     private static final char TOKEN_DELIMITER = '/';
115 
116     // Handler message types.
117     static final int MSG_REPORT_EVENT = 0;
118     static final int MSG_FLUSH_TO_DISK = 1;
119     static final int MSG_REMOVE_USER = 2;
120     static final int MSG_UID_STATE_CHANGED = 3;
121     static final int MSG_REPORT_EVENT_TO_ALL_USERID = 4;
122 
123     private final Object mLock = new Object();
124     Handler mHandler;
125     AppOpsManager mAppOps;
126     UserManager mUserManager;
127     PackageManager mPackageManager;
128     PackageManagerInternal mPackageManagerInternal;
129     PackageMonitor mPackageMonitor;
130     IDeviceIdleController mDeviceIdleController;
131     // Do not use directly. Call getDpmInternal() instead
132     DevicePolicyManagerInternal mDpmInternal;
133 
134     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
135     private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
136     private File mUsageStatsDir;
137     long mRealTimeSnapshot;
138     long mSystemTimeSnapshot;
139     int mUsageSource;
140 
141     /** Manages the standby state of apps. */
142     AppStandbyController mAppStandby;
143 
144     /** Manages app time limit observers */
145     AppTimeLimitController mAppTimeLimit;
146 
147     final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray();
148     final SparseArray<ActivityData> mVisibleActivities = new SparseArray();
149 
150     private static class ActivityData {
151         private final String mTaskRootPackage;
152         private final String mTaskRootClass;
ActivityData(String taskRootPackage, String taskRootClass)153         private ActivityData(String taskRootPackage, String taskRootClass) {
154             mTaskRootPackage = taskRootPackage;
155             mTaskRootClass = taskRootClass;
156         }
157     }
158 
159     private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
160             new UsageStatsManagerInternal.AppIdleStateChangeListener() {
161                 @Override
162                 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
163                         int bucket, int reason) {
164                     Event event = new Event(Event.STANDBY_BUCKET_CHANGED,
165                             SystemClock.elapsedRealtime());
166                     event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF);
167                     event.mPackage = packageName;
168                     mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
169                 }
170 
171                 @Override
172                 public void onParoleStateChanged(boolean isParoleOn) {
173 
174                 }
175             };
176 
UsageStatsService(Context context)177     public UsageStatsService(Context context) {
178         super(context);
179     }
180 
181     @Override
onStart()182     public void onStart() {
183         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
184         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
185         mPackageManager = getContext().getPackageManager();
186         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
187         mHandler = new H(BackgroundThread.get().getLooper());
188 
189         mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
190 
191         mAppTimeLimit = new AppTimeLimitController(
192                 new AppTimeLimitController.TimeLimitCallbackListener() {
193                     @Override
194                     public void onLimitReached(int observerId, int userId, long timeLimit,
195                             long timeElapsed, PendingIntent callbackIntent) {
196                         if (callbackIntent == null) return;
197                         Intent intent = new Intent();
198                         intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
199                         intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
200                         intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
201                         try {
202                             callbackIntent.send(getContext(), 0, intent);
203                         } catch (PendingIntent.CanceledException e) {
204                             Slog.w(TAG, "Couldn't deliver callback: "
205                                     + callbackIntent);
206                         }
207                     }
208 
209                     @Override
210                     public void onSessionEnd(int observerId, int userId, long timeElapsed,
211                             PendingIntent callbackIntent) {
212                         if (callbackIntent == null) return;
213                         Intent intent = new Intent();
214                         intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
215                         intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
216                         try {
217                             callbackIntent.send(getContext(), 0, intent);
218                         } catch (PendingIntent.CanceledException e) {
219                             Slog.w(TAG, "Couldn't deliver callback: "
220                                     + callbackIntent);
221                         }
222                     }
223                 }, mHandler.getLooper());
224 
225         mAppStandby.addListener(mStandbyChangeListener);
226         File systemDataDir = new File(Environment.getDataDirectory(), "system");
227         mUsageStatsDir = new File(systemDataDir, "usagestats");
228         mUsageStatsDir.mkdirs();
229         if (!mUsageStatsDir.exists()) {
230             throw new IllegalStateException("Usage stats directory does not exist: "
231                     + mUsageStatsDir.getAbsolutePath());
232         }
233 
234         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
235         filter.addAction(Intent.ACTION_USER_STARTED);
236         getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
237                 null, mHandler);
238 
239         synchronized (mLock) {
240             cleanUpRemovedUsersLocked();
241         }
242 
243         mRealTimeSnapshot = SystemClock.elapsedRealtime();
244         mSystemTimeSnapshot = System.currentTimeMillis();
245 
246         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
247         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
248         // Make sure we initialize the data, in case job scheduler needs it early.
249         getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot);
250     }
251 
252     @Override
onBootPhase(int phase)253     public void onBootPhase(int phase) {
254         mAppStandby.onBootPhase(phase);
255         if (phase == PHASE_SYSTEM_SERVICES_READY) {
256             // initialize mDpmInternal
257             getDpmInternal();
258 
259             mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
260                     ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
261 
262             if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
263                 try {
264                     ActivityManager.getService().registerUidObserver(mUidObserver,
265                             ActivityManager.UID_OBSERVER_PROCSTATE
266                                     | ActivityManager.UID_OBSERVER_GONE,
267                             ActivityManager.PROCESS_STATE_UNKNOWN, null);
268                 } catch (RemoteException e) {
269                     throw new RuntimeException(e);
270                 }
271             } else {
272                 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE);
273             }
274             readUsageSourceSetting();
275         }
276     }
277 
getDpmInternal()278     private DevicePolicyManagerInternal getDpmInternal() {
279         if (mDpmInternal == null) {
280             mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
281         }
282         return mDpmInternal;
283     }
284 
readUsageSourceSetting()285     private void readUsageSourceSetting() {
286         synchronized (mLock) {
287             mUsageSource = Settings.Global.getInt(getContext().getContentResolver(),
288                     Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE, USAGE_SOURCE_TASK_ROOT_ACTIVITY);
289         }
290     }
291 
292     private class UserActionsReceiver extends BroadcastReceiver {
293         @Override
onReceive(Context context, Intent intent)294         public void onReceive(Context context, Intent intent) {
295             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
296             final String action = intent.getAction();
297             if (Intent.ACTION_USER_REMOVED.equals(action)) {
298                 if (userId >= 0) {
299                     mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
300                 }
301             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
302                 if (userId >= 0) {
303                     mAppStandby.postCheckIdleStates(userId);
304                 }
305             }
306         }
307     }
308 
309     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
310         @Override
311         public void onUidStateChanged(int uid, int procState, long procStateSeq) {
312             mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
313         }
314 
315         @Override
316         public void onUidIdle(int uid, boolean disabled) {
317             // Ignored
318         }
319 
320         @Override
321         public void onUidGone(int uid, boolean disabled) {
322             onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
323         }
324 
325         @Override
326         public void onUidActive(int uid) {
327             // Ignored
328         }
329 
330         @Override public void onUidCachedChanged(int uid, boolean cached) {
331         }
332     };
333 
334     @Override
onStatsUpdated()335     public void onStatsUpdated() {
336         mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
337     }
338 
339     @Override
onStatsReloaded()340     public void onStatsReloaded() {
341         mAppStandby.postOneTimeCheckIdleStates();
342     }
343 
344     @Override
onNewUpdate(int userId)345     public void onNewUpdate(int userId) {
346         mAppStandby.initializeDefaultsForSystemApps(userId);
347     }
348 
shouldObfuscateInstantAppsForCaller(int callingUid, int userId)349     private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
350         return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
351     }
352 
cleanUpRemovedUsersLocked()353     private void cleanUpRemovedUsersLocked() {
354         final List<UserInfo> users = mUserManager.getUsers(true);
355         if (users == null || users.size() == 0) {
356             throw new IllegalStateException("There can't be no users");
357         }
358 
359         ArraySet<String> toDelete = new ArraySet<>();
360         String[] fileNames = mUsageStatsDir.list();
361         if (fileNames == null) {
362             // No users to delete.
363             return;
364         }
365 
366         toDelete.addAll(Arrays.asList(fileNames));
367 
368         final int userCount = users.size();
369         for (int i = 0; i < userCount; i++) {
370             final UserInfo userInfo = users.get(i);
371             toDelete.remove(Integer.toString(userInfo.id));
372         }
373 
374         final int deleteCount = toDelete.size();
375         for (int i = 0; i < deleteCount; i++) {
376             deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
377         }
378     }
379 
deleteRecursively(File f)380     private static void deleteRecursively(File f) {
381         File[] files = f.listFiles();
382         if (files != null) {
383             for (File subFile : files) {
384                 deleteRecursively(subFile);
385             }
386         }
387 
388         if (!f.delete()) {
389             Slog.e(TAG, "Failed to delete " + f);
390         }
391     }
392 
getUserDataAndInitializeIfNeededLocked(int userId, long currentTimeMillis)393     private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
394             long currentTimeMillis) {
395         UserUsageStatsService service = mUserState.get(userId);
396         if (service == null) {
397             service = new UserUsageStatsService(getContext(), userId,
398                     new File(mUsageStatsDir, Integer.toString(userId)), this);
399             service.init(currentTimeMillis);
400             mUserState.put(userId, service);
401         }
402         return service;
403     }
404 
405     /**
406      * This should be the only way to get the time from the system.
407      */
checkAndGetTimeLocked()408     private long checkAndGetTimeLocked() {
409         final long actualSystemTime = System.currentTimeMillis();
410         final long actualRealtime = SystemClock.elapsedRealtime();
411         final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
412         final long diffSystemTime = actualSystemTime - expectedSystemTime;
413         if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS
414                 && ENABLE_TIME_CHANGE_CORRECTION) {
415             // The time has changed.
416             Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
417             final int userCount = mUserState.size();
418             for (int i = 0; i < userCount; i++) {
419                 final UserUsageStatsService service = mUserState.valueAt(i);
420                 service.onTimeChanged(expectedSystemTime, actualSystemTime);
421             }
422             mRealTimeSnapshot = actualRealtime;
423             mSystemTimeSnapshot = actualSystemTime;
424         }
425         return actualSystemTime;
426     }
427 
428     /**
429      * Assuming the event's timestamp is measured in milliseconds since boot,
430      * convert it to a system wall time.
431      */
convertToSystemTimeLocked(Event event)432     private void convertToSystemTimeLocked(Event event) {
433         event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
434     }
435 
436     /**
437      * Called by the Binder stub
438      */
shutdown()439     void shutdown() {
440         synchronized (mLock) {
441             mHandler.removeMessages(MSG_REPORT_EVENT);
442             Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
443             event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
444             // orderly shutdown, the last event is DEVICE_SHUTDOWN.
445             reportEventToAllUserId(event);
446             flushToDiskLocked();
447         }
448     }
449 
450     /**
451      * After power button is pressed for 3.5 seconds
452      * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}),
453      * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10
454      * seconds and the device is shutdown, the database is already persisted and we are not losing
455      * data.
456      * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise
457      * PhoneWindowManager may be blocked.
458      */
prepareForPossibleShutdown()459     void prepareForPossibleShutdown() {
460         Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime());
461         event.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
462         mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget();
463         mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK);
464     }
465 
466     /**
467      * Called by the Binder stub.
468      */
reportEvent(Event event, int userId)469     void reportEvent(Event event, int userId) {
470         synchronized (mLock) {
471             final long timeNow = checkAndGetTimeLocked();
472             final long elapsedRealtime = SystemClock.elapsedRealtime();
473             convertToSystemTimeLocked(event);
474 
475             if (event.mPackage != null
476                     && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
477                 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
478             }
479 
480             switch (event.mEventType) {
481                 case Event.ACTIVITY_RESUMED:
482                     // check if this activity has already been resumed
483                     if (mVisibleActivities.get(event.mInstanceId) != null) break;
484                     mVisibleActivities.put(event.mInstanceId,
485                             new ActivityData(event.mTaskRootPackage, event.mTaskRootClass));
486                     try {
487                         switch(mUsageSource) {
488                             case USAGE_SOURCE_CURRENT_ACTIVITY:
489                                 mAppTimeLimit.noteUsageStart(event.mPackage, userId);
490                                 break;
491                             case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
492                             default:
493                                 mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId);
494                                 break;
495                         }
496                     } catch (IllegalArgumentException iae) {
497                         Slog.e(TAG, "Failed to note usage start", iae);
498                     }
499                     break;
500                 case Event.ACTIVITY_PAUSED:
501                     if (event.mTaskRootPackage == null) {
502                         // Task Root info is missing. Repair the event based on previous data
503                         final ActivityData prevData = mVisibleActivities.get(event.mInstanceId);
504                         if (prevData == null) {
505                             Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
506                                     + "/" + event.mClass + " event : " + event.mEventType
507                                     + " instanceId : " + event.mInstanceId + ")");
508                         } else {
509                             event.mTaskRootPackage = prevData.mTaskRootPackage;
510                             event.mTaskRootClass = prevData.mTaskRootClass;
511                         }
512                     }
513                     break;
514                 case Event.ACTIVITY_DESTROYED:
515                     // Treat activity destroys like activity stops.
516                     event.mEventType = Event.ACTIVITY_STOPPED;
517                     // Fallthrough
518                 case Event.ACTIVITY_STOPPED:
519                     final ActivityData prevData =
520                             mVisibleActivities.removeReturnOld(event.mInstanceId);
521                     if (prevData == null) {
522                         // The activity stop was already handled.
523                         return;
524                     }
525 
526                     ArraySet<String> tokens;
527                     synchronized (mUsageReporters) {
528                         tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
529                     }
530                     if (tokens != null) {
531                         synchronized (tokens) {
532                             final int size = tokens.size();
533                             // Stop usage on behalf of a UsageReporter that stopped
534                             for (int i = 0; i < size; i++) {
535                                 final String token = tokens.valueAt(i);
536                                 try {
537                                     mAppTimeLimit.noteUsageStop(
538                                             buildFullToken(event.mPackage, token), userId);
539                                 } catch (IllegalArgumentException iae) {
540                                     Slog.w(TAG, "Failed to stop usage for during reporter death: "
541                                             + iae);
542                                 }
543                             }
544                         }
545                     }
546                     if (event.mTaskRootPackage == null) {
547                         // Task Root info is missing. Repair the event based on previous data
548                         event.mTaskRootPackage = prevData.mTaskRootPackage;
549                         event.mTaskRootClass = prevData.mTaskRootClass;
550                     }
551                     try {
552                         switch(mUsageSource) {
553                             case USAGE_SOURCE_CURRENT_ACTIVITY:
554                                 mAppTimeLimit.noteUsageStop(event.mPackage, userId);
555                                 break;
556                             case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
557                             default:
558                                 mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId);
559                                 break;
560                         }
561                     } catch (IllegalArgumentException iae) {
562                         Slog.w(TAG, "Failed to note usage stop", iae);
563                     }
564                     break;
565             }
566 
567             final UserUsageStatsService service =
568                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
569             service.reportEvent(event);
570 
571             mAppStandby.reportEvent(event, elapsedRealtime, userId);
572         }
573     }
574 
575     /**
576      * Some events like FLUSH_TO_DISK need to be sent to all userId.
577      * @param event
578      */
reportEventToAllUserId(Event event)579     void reportEventToAllUserId(Event event) {
580         synchronized (mLock) {
581             final int userCount = mUserState.size();
582             for (int i = 0; i < userCount; i++) {
583                 Event copy = new Event(event);
584                 reportEvent(copy, mUserState.keyAt(i));
585             }
586         }
587     }
588 
589     /**
590      * Called by the Handler for message MSG_FLUSH_TO_DISK.
591      */
flushToDisk()592     void flushToDisk() {
593         synchronized (mLock) {
594             // Before flush to disk, report FLUSH_TO_DISK event to signal UsageStats to update app
595             // usage. In case of abrupt power shutdown like battery drain or cold temperature,
596             // all UsageStats has correct data up to last flush to disk.
597             // The FLUSH_TO_DISK event is an internal event, it will not show up in IntervalStats'
598             // EventList.
599             Event event = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime());
600             reportEventToAllUserId(event);
601             flushToDiskLocked();
602         }
603     }
604 
605     /**
606      * Called by the Binder stub.
607      */
onUserRemoved(int userId)608     void onUserRemoved(int userId) {
609         synchronized (mLock) {
610             Slog.i(TAG, "Removing user " + userId + " and all data.");
611             mUserState.remove(userId);
612             mAppStandby.onUserRemoved(userId);
613             mAppTimeLimit.onUserRemoved(userId);
614             cleanUpRemovedUsersLocked();
615         }
616     }
617 
618     /**
619      * Called by the Binder stub.
620      */
queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)621     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
622             boolean obfuscateInstantApps) {
623         synchronized (mLock) {
624             final long timeNow = checkAndGetTimeLocked();
625             if (!validRange(timeNow, beginTime, endTime)) {
626                 return null;
627             }
628 
629             final UserUsageStatsService service =
630                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
631             List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
632             if (list == null) {
633                 return null;
634             }
635 
636             // Mangle instant app names *using their current state (not whether they were ephemeral
637             // when the data was recorded)*.
638             if (obfuscateInstantApps) {
639                 for (int i = list.size() - 1; i >= 0; i--) {
640                     final UsageStats stats = list.get(i);
641                     if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
642                         list.set(i, stats.getObfuscatedForInstantApp());
643                     }
644                 }
645             }
646 
647             return list;
648         }
649     }
650 
651     /**
652      * Called by the Binder stub.
653      */
queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)654     List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
655             long endTime) {
656         synchronized (mLock) {
657             final long timeNow = checkAndGetTimeLocked();
658             if (!validRange(timeNow, beginTime, endTime)) {
659                 return null;
660             }
661 
662             final UserUsageStatsService service =
663                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
664             return service.queryConfigurationStats(bucketType, beginTime, endTime);
665         }
666     }
667 
668     /**
669      * Called by the Binder stub.
670      */
queryEventStats(int userId, int bucketType, long beginTime, long endTime)671     List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
672             long endTime) {
673         synchronized (mLock) {
674             final long timeNow = checkAndGetTimeLocked();
675             if (!validRange(timeNow, beginTime, endTime)) {
676                 return null;
677             }
678 
679             final UserUsageStatsService service =
680                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
681             return service.queryEventStats(bucketType, beginTime, endTime);
682         }
683     }
684 
685     /**
686      * Called by the Binder stub.
687      */
queryEvents(int userId, long beginTime, long endTime, boolean shouldObfuscateInstantApps)688     UsageEvents queryEvents(int userId, long beginTime, long endTime,
689             boolean shouldObfuscateInstantApps) {
690         synchronized (mLock) {
691             final long timeNow = checkAndGetTimeLocked();
692             if (!validRange(timeNow, beginTime, endTime)) {
693                 return null;
694             }
695 
696             final UserUsageStatsService service =
697                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
698             return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
699         }
700     }
701 
702     /**
703      * Called by the Binder stub.
704      */
queryEventsForPackage(int userId, long beginTime, long endTime, String packageName, boolean includeTaskRoot)705     UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
706             String packageName, boolean includeTaskRoot) {
707         synchronized (mLock) {
708             final long timeNow = checkAndGetTimeLocked();
709             if (!validRange(timeNow, beginTime, endTime)) {
710                 return null;
711             }
712 
713             final UserUsageStatsService service =
714                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
715             return service.queryEventsForPackage(beginTime, endTime, packageName, includeTaskRoot);
716         }
717     }
718 
validRange(long currentTime, long beginTime, long endTime)719     private static boolean validRange(long currentTime, long beginTime, long endTime) {
720         return beginTime <= currentTime && beginTime < endTime;
721     }
722 
buildFullToken(String packageName, String token)723     private String buildFullToken(String packageName, String token) {
724         final StringBuilder sb = new StringBuilder(packageName.length() + token.length() + 1);
725         sb.append(packageName);
726         sb.append(TOKEN_DELIMITER);
727         sb.append(token);
728         return sb.toString();
729     }
730 
flushToDiskLocked()731     private void flushToDiskLocked() {
732         final int userCount = mUserState.size();
733         for (int i = 0; i < userCount; i++) {
734             UserUsageStatsService service = mUserState.valueAt(i);
735             service.persistActiveStats();
736             mAppStandby.flushToDisk(mUserState.keyAt(i));
737         }
738         mAppStandby.flushDurationsToDisk();
739 
740         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
741     }
742 
743     /**
744      * Called by the Binder stub.
745      */
dump(String[] args, PrintWriter pw)746     void dump(String[] args, PrintWriter pw) {
747         synchronized (mLock) {
748             IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
749 
750             boolean checkin = false;
751             boolean compact = false;
752             String pkg = null;
753 
754             if (args != null) {
755                 for (int i = 0; i < args.length; i++) {
756                     String arg = args[i];
757                     if ("--checkin".equals(arg)) {
758                         checkin = true;
759                     } else if ("-c".equals(arg)) {
760                         compact = true;
761                     } else if ("flush".equals(arg)) {
762                         flushToDiskLocked();
763                         pw.println("Flushed stats to disk");
764                         return;
765                     } else if ("is-app-standby-enabled".equals(arg)) {
766                         pw.println(mAppStandby.mAppIdleEnabled);
767                         return;
768                     } else if ("apptimelimit".equals(arg)) {
769                         if (i + 1 >= args.length) {
770                             mAppTimeLimit.dump(null, pw);
771                         } else {
772                             final String[] remainingArgs =
773                                     Arrays.copyOfRange(args, i + 1, args.length);
774                             mAppTimeLimit.dump(remainingArgs, pw);
775                         }
776                         return;
777                     } else if ("file".equals(arg)) {
778                         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
779                         if (i + 1 >= args.length) {
780                             // dump everything for all users
781                             final int numUsers = mUserState.size();
782                             for (int user = 0; user < numUsers; user++) {
783                                 ipw.println("user=" + mUserState.keyAt(user));
784                                 ipw.increaseIndent();
785                                 mUserState.valueAt(user).dumpFile(ipw, null);
786                                 ipw.decreaseIndent();
787                             }
788                         } else {
789                             final int user;
790                             try {
791                                 user = Integer.valueOf(args[i + 1]);
792                             } catch (NumberFormatException nfe) {
793                                 ipw.println("invalid user specified.");
794                                 return;
795                             }
796                             if (mUserState.indexOfKey(user) < 0) {
797                                 ipw.println("the specified user does not exist.");
798                                 return;
799                             }
800                             final String[] remainingArgs = Arrays.copyOfRange(
801                                     args, i + 2, args.length);
802                             // dump everything for the specified user
803                             mUserState.get(user).dumpFile(ipw, remainingArgs);
804                         }
805                         return;
806                     } else if ("database-info".equals(arg)) {
807                         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
808                         if (i + 1 >= args.length) {
809                             // dump info for all users
810                             final int numUsers = mUserState.size();
811                             for (int user = 0; user < numUsers; user++) {
812                                 ipw.println("user=" + mUserState.keyAt(user));
813                                 ipw.increaseIndent();
814                                 mUserState.valueAt(user).dumpDatabaseInfo(ipw);
815                                 ipw.decreaseIndent();
816                             }
817                         } else {
818                             final int user;
819                             try {
820                                 user = Integer.valueOf(args[i + 1]);
821                             } catch (NumberFormatException nfe) {
822                                 ipw.println("invalid user specified.");
823                                 return;
824                             }
825                             if (mUserState.indexOfKey(user) < 0) {
826                                 ipw.println("the specified user does not exist.");
827                                 return;
828                             }
829                             // dump info only for the specified user
830                             mUserState.get(user).dumpDatabaseInfo(ipw);
831                         }
832                         return;
833                     } else if (arg != null && !arg.startsWith("-")) {
834                         // Anything else that doesn't start with '-' is a pkg to filter
835                         pkg = arg;
836                         break;
837                     }
838                 }
839             }
840 
841             final int userCount = mUserState.size();
842             for (int i = 0; i < userCount; i++) {
843                 int userId = mUserState.keyAt(i);
844                 idpw.printPair("user", userId);
845                 idpw.println();
846                 idpw.increaseIndent();
847                 if (checkin) {
848                     mUserState.valueAt(i).checkin(idpw);
849                 } else {
850                     mUserState.valueAt(i).dump(idpw, pkg, compact);
851                     idpw.println();
852                 }
853                 mAppStandby.dumpUser(idpw, userId, pkg);
854                 idpw.decreaseIndent();
855             }
856 
857             if (pkg == null) {
858                 pw.println();
859                 mAppStandby.dumpState(args, pw);
860             }
861 
862             idpw.println();
863             idpw.printPair("Usage Source", UsageStatsManager.usageSourceToString(mUsageSource));
864             idpw.println();
865 
866             mAppTimeLimit.dump(null, pw);
867         }
868     }
869 
870     class H extends Handler {
H(Looper looper)871         public H(Looper looper) {
872             super(looper);
873         }
874 
875         @Override
handleMessage(Message msg)876         public void handleMessage(Message msg) {
877             switch (msg.what) {
878                 case MSG_REPORT_EVENT:
879                     reportEvent((Event) msg.obj, msg.arg1);
880                     break;
881                 case MSG_REPORT_EVENT_TO_ALL_USERID:
882                     reportEventToAllUserId((Event) msg.obj);
883                     break;
884                 case MSG_FLUSH_TO_DISK:
885                     flushToDisk();
886                     break;
887 
888                 case MSG_REMOVE_USER:
889                     onUserRemoved(msg.arg1);
890                     break;
891 
892                 case MSG_UID_STATE_CHANGED: {
893                     final int uid = msg.arg1;
894                     final int procState = msg.arg2;
895 
896                     final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
897                     synchronized (mUidToKernelCounter) {
898                         final int oldCounter = mUidToKernelCounter.get(uid, 0);
899                         if (newCounter != oldCounter) {
900                             mUidToKernelCounter.put(uid, newCounter);
901                             try {
902                                 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter);
903                             } catch (IOException e) {
904                                 Slog.w(TAG, "Failed to update counter set: " + e);
905                             }
906                         }
907                     }
908                     break;
909                 }
910 
911                 default:
912                     super.handleMessage(msg);
913                     break;
914             }
915         }
916     }
917 
918     private final class BinderService extends IUsageStatsManager.Stub {
919 
hasPermission(String callingPackage)920         private boolean hasPermission(String callingPackage) {
921             final int callingUid = Binder.getCallingUid();
922             if (callingUid == Process.SYSTEM_UID) {
923                 return true;
924             }
925             final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
926                     callingUid, callingPackage);
927             if (mode == AppOpsManager.MODE_DEFAULT) {
928                 // The default behavior here is to check if PackageManager has given the app
929                 // permission.
930                 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
931                         == PackageManager.PERMISSION_GRANTED;
932             }
933             return mode == AppOpsManager.MODE_ALLOWED;
934         }
935 
hasObserverPermission()936         private boolean hasObserverPermission() {
937             final int callingUid = Binder.getCallingUid();
938             DevicePolicyManagerInternal dpmInternal = getDpmInternal();
939             if (callingUid == Process.SYSTEM_UID
940                     || (dpmInternal != null
941                         && dpmInternal.isActiveAdminWithPolicy(callingUid,
942                             DeviceAdminInfo.USES_POLICY_PROFILE_OWNER))) {
943                 // Caller is the system or the profile owner, so proceed.
944                 return true;
945             }
946             return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE)
947                     == PackageManager.PERMISSION_GRANTED;
948         }
949 
hasPermissions(String callingPackage, String... permissions)950         private boolean hasPermissions(String callingPackage, String... permissions) {
951             final int callingUid = Binder.getCallingUid();
952             if (callingUid == Process.SYSTEM_UID) {
953                 // Caller is the system, so proceed.
954                 return true;
955             }
956 
957             boolean hasPermissions = true;
958             final Context context = getContext();
959             for (int i = 0; i < permissions.length; i++) {
960                 hasPermissions = hasPermissions && (context.checkCallingPermission(permissions[i])
961                         == PackageManager.PERMISSION_GRANTED);
962             }
963             return hasPermissions;
964         }
965 
checkCallerIsSystemOrSameApp(String pkg)966         private void checkCallerIsSystemOrSameApp(String pkg) {
967             if (isCallingUidSystem()) {
968                 return;
969             }
970             checkCallerIsSameApp(pkg);
971         }
972 
checkCallerIsSameApp(String pkg)973         private void checkCallerIsSameApp(String pkg) {
974             final int callingUid = Binder.getCallingUid();
975             final int callingUserId = UserHandle.getUserId(callingUid);
976 
977             if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0,
978                     callingUserId) != callingUid) {
979                 throw new SecurityException("Calling uid " + callingUid + " cannot query events"
980                         + "for package " + pkg);
981             }
982         }
983 
isCallingUidSystem()984         private boolean isCallingUidSystem() {
985             final int uid = UserHandle.getAppId(Binder.getCallingUid()); // ignores user
986             return uid == Process.SYSTEM_UID;
987         }
988 
989         @Override
queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage)990         public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
991                 long endTime, String callingPackage) {
992             if (!hasPermission(callingPackage)) {
993                 return null;
994             }
995 
996             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
997                     Binder.getCallingUid(), UserHandle.getCallingUserId());
998 
999             final int userId = UserHandle.getCallingUserId();
1000             final long token = Binder.clearCallingIdentity();
1001             try {
1002                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
1003                         userId, bucketType, beginTime, endTime, obfuscateInstantApps);
1004                 if (results != null) {
1005                     return new ParceledListSlice<>(results);
1006                 }
1007             } finally {
1008                 Binder.restoreCallingIdentity(token);
1009             }
1010             return null;
1011         }
1012 
1013         @Override
queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)1014         public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
1015                 long beginTime, long endTime, String callingPackage) throws RemoteException {
1016             if (!hasPermission(callingPackage)) {
1017                 return null;
1018             }
1019 
1020             final int userId = UserHandle.getCallingUserId();
1021             final long token = Binder.clearCallingIdentity();
1022             try {
1023                 final List<ConfigurationStats> results =
1024                         UsageStatsService.this.queryConfigurationStats(userId, bucketType,
1025                                 beginTime, endTime);
1026                 if (results != null) {
1027                     return new ParceledListSlice<>(results);
1028                 }
1029             } finally {
1030                 Binder.restoreCallingIdentity(token);
1031             }
1032             return null;
1033         }
1034 
1035         @Override
queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)1036         public ParceledListSlice<EventStats> queryEventStats(int bucketType,
1037                 long beginTime, long endTime, String callingPackage) throws RemoteException {
1038             if (!hasPermission(callingPackage)) {
1039                 return null;
1040             }
1041 
1042             final int userId = UserHandle.getCallingUserId();
1043             final long token = Binder.clearCallingIdentity();
1044             try {
1045                 final List<EventStats> results =
1046                         UsageStatsService.this.queryEventStats(userId, bucketType,
1047                                 beginTime, endTime);
1048                 if (results != null) {
1049                     return new ParceledListSlice<>(results);
1050                 }
1051             } finally {
1052                 Binder.restoreCallingIdentity(token);
1053             }
1054             return null;
1055         }
1056 
1057         @Override
queryEvents(long beginTime, long endTime, String callingPackage)1058         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
1059             if (!hasPermission(callingPackage)) {
1060                 return null;
1061             }
1062 
1063             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1064                     Binder.getCallingUid(), UserHandle.getCallingUserId());
1065 
1066             final int userId = UserHandle.getCallingUserId();
1067             final long token = Binder.clearCallingIdentity();
1068             try {
1069                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
1070                         obfuscateInstantApps);
1071             } finally {
1072                 Binder.restoreCallingIdentity(token);
1073             }
1074         }
1075 
1076         @Override
queryEventsForPackage(long beginTime, long endTime, String callingPackage)1077         public UsageEvents queryEventsForPackage(long beginTime, long endTime,
1078                 String callingPackage) {
1079             final int callingUid = Binder.getCallingUid();
1080             final int callingUserId = UserHandle.getUserId(callingUid);
1081 
1082             checkCallerIsSameApp(callingPackage);
1083             final boolean includeTaskRoot = hasPermission(callingPackage);
1084 
1085             final long token = Binder.clearCallingIdentity();
1086             try {
1087                 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
1088                         endTime, callingPackage, includeTaskRoot);
1089             } finally {
1090                 Binder.restoreCallingIdentity(token);
1091             }
1092         }
1093 
1094         @Override
queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)1095         public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId,
1096                 String callingPackage) {
1097             if (!hasPermission(callingPackage)) {
1098                 return null;
1099             }
1100 
1101             if (userId != UserHandle.getCallingUserId()) {
1102                 getContext().enforceCallingPermission(
1103                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1104                         "No permission to query usage stats for this user");
1105             }
1106 
1107             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1108                     Binder.getCallingUid(), UserHandle.getCallingUserId());
1109 
1110             final long token = Binder.clearCallingIdentity();
1111             try {
1112                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
1113                         obfuscateInstantApps);
1114             } finally {
1115                 Binder.restoreCallingIdentity(token);
1116             }
1117         }
1118 
1119         @Override
queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)1120         public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime,
1121                 int userId, String pkg, String callingPackage) {
1122             if (!hasPermission(callingPackage)) {
1123                 return null;
1124             }
1125             if (userId != UserHandle.getCallingUserId()) {
1126                 getContext().enforceCallingPermission(
1127                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1128                         "No permission to query usage stats for this user");
1129             }
1130             checkCallerIsSystemOrSameApp(pkg);
1131 
1132             final long token = Binder.clearCallingIdentity();
1133             try {
1134                 return UsageStatsService.this.queryEventsForPackage(userId, beginTime,
1135                         endTime, pkg, true);
1136             } finally {
1137                 Binder.restoreCallingIdentity(token);
1138             }
1139         }
1140 
1141         @Override
isAppInactive(String packageName, int userId)1142         public boolean isAppInactive(String packageName, int userId) {
1143             try {
1144                 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
1145                         Binder.getCallingUid(), userId, false, false, "isAppInactive", null);
1146             } catch (RemoteException re) {
1147                 throw re.rethrowFromSystemServer();
1148             }
1149             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1150                     Binder.getCallingUid(), userId);
1151             final long token = Binder.clearCallingIdentity();
1152             try {
1153                 return mAppStandby.isAppIdleFilteredOrParoled(
1154                         packageName, userId,
1155                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
1156             } finally {
1157                 Binder.restoreCallingIdentity(token);
1158             }
1159         }
1160 
1161         @Override
setAppInactive(String packageName, boolean idle, int userId)1162         public void setAppInactive(String packageName, boolean idle, int userId) {
1163             final int callingUid = Binder.getCallingUid();
1164             try {
1165                 userId = ActivityManager.getService().handleIncomingUser(
1166                         Binder.getCallingPid(), callingUid, userId, false, true,
1167                         "setAppInactive", null);
1168             } catch (RemoteException re) {
1169                 throw re.rethrowFromSystemServer();
1170             }
1171             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1172                     "No permission to change app idle state");
1173             final long token = Binder.clearCallingIdentity();
1174             try {
1175                 final int appId = mAppStandby.getAppId(packageName);
1176                 if (appId < 0) return;
1177                 mAppStandby.setAppIdleAsync(packageName, idle, userId);
1178             } finally {
1179                 Binder.restoreCallingIdentity(token);
1180             }
1181         }
1182 
1183         @Override
getAppStandbyBucket(String packageName, String callingPackage, int userId)1184         public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
1185             final int callingUid = Binder.getCallingUid();
1186             try {
1187                 userId = ActivityManager.getService().handleIncomingUser(
1188                         Binder.getCallingPid(), callingUid, userId, false, false,
1189                         "getAppStandbyBucket", null);
1190             } catch (RemoteException re) {
1191                 throw re.rethrowFromSystemServer();
1192             }
1193             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
1194             // If the calling app is asking about itself, continue, else check for permission.
1195             if (packageUid != callingUid) {
1196                 if (!hasPermission(callingPackage)) {
1197                     throw new SecurityException(
1198                             "Don't have permission to query app standby bucket");
1199                 }
1200             }
1201             if (packageUid < 0) {
1202                 throw new IllegalArgumentException(
1203                         "Cannot get standby bucket for non existent package (" + packageName + ")");
1204             }
1205             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
1206                     userId);
1207             final long token = Binder.clearCallingIdentity();
1208             try {
1209                 return mAppStandby.getAppStandbyBucket(packageName, userId,
1210                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
1211             } finally {
1212                 Binder.restoreCallingIdentity(token);
1213             }
1214         }
1215 
1216         @Override
setAppStandbyBucket(String packageName, int bucket, int userId)1217         public void setAppStandbyBucket(String packageName,
1218                 int bucket, int userId) {
1219             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1220                     "No permission to change app standby state");
1221 
1222             if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
1223                     || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
1224                 throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
1225             }
1226             final int callingUid = Binder.getCallingUid();
1227             try {
1228                 userId = ActivityManager.getService().handleIncomingUser(
1229                         Binder.getCallingPid(), callingUid, userId, false, true,
1230                         "setAppStandbyBucket", null);
1231             } catch (RemoteException re) {
1232                 throw re.rethrowFromSystemServer();
1233             }
1234             final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
1235             final boolean systemCaller = UserHandle.isCore(callingUid);
1236             final int reason = systemCaller
1237                     ? UsageStatsManager.REASON_MAIN_FORCED
1238                     : UsageStatsManager.REASON_MAIN_PREDICTED;
1239             final long token = Binder.clearCallingIdentity();
1240             try {
1241                 final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
1242                         PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
1243                         | PackageManager.MATCH_DIRECT_BOOT_AWARE, userId);
1244                 // Caller cannot set their own standby state
1245                 if (packageUid == callingUid) {
1246                     throw new IllegalArgumentException("Cannot set your own standby bucket");
1247                 }
1248                 if (packageUid < 0) {
1249                     throw new IllegalArgumentException(
1250                             "Cannot set standby bucket for non existent package (" + packageName
1251                                     + ")");
1252                 }
1253                 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
1254                         SystemClock.elapsedRealtime(), shellCaller);
1255             } finally {
1256                 Binder.restoreCallingIdentity(token);
1257             }
1258         }
1259 
1260         @Override
getAppStandbyBuckets(String callingPackageName, int userId)1261         public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName,
1262                 int userId) {
1263             final int callingUid = Binder.getCallingUid();
1264             try {
1265                 userId = ActivityManager.getService().handleIncomingUser(
1266                         Binder.getCallingPid(), callingUid, userId, false, false,
1267                         "getAppStandbyBucket", null);
1268             } catch (RemoteException re) {
1269                 throw re.rethrowFromSystemServer();
1270             }
1271             if (!hasPermission(callingPackageName)) {
1272                 throw new SecurityException(
1273                         "Don't have permission to query app standby bucket");
1274             }
1275             final long token = Binder.clearCallingIdentity();
1276             try {
1277                 final List<AppStandbyInfo> standbyBucketList =
1278                         mAppStandby.getAppStandbyBuckets(userId);
1279                 return (standbyBucketList == null) ? ParceledListSlice.emptyList()
1280                         : new ParceledListSlice<>(standbyBucketList);
1281             } finally {
1282                 Binder.restoreCallingIdentity(token);
1283             }
1284         }
1285 
1286         @Override
setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)1287         public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) {
1288             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1289                     "No permission to change app standby state");
1290 
1291             final int callingUid = Binder.getCallingUid();
1292             try {
1293                 userId = ActivityManager.getService().handleIncomingUser(
1294                         Binder.getCallingPid(), callingUid, userId, false, true,
1295                         "setAppStandbyBucket", null);
1296             } catch (RemoteException re) {
1297                 throw re.rethrowFromSystemServer();
1298             }
1299             final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
1300             final int reason = shellCaller
1301                     ? UsageStatsManager.REASON_MAIN_FORCED
1302                     : UsageStatsManager.REASON_MAIN_PREDICTED;
1303             final long token = Binder.clearCallingIdentity();
1304             try {
1305                 final long elapsedRealtime = SystemClock.elapsedRealtime();
1306                 List<AppStandbyInfo> bucketList = appBuckets.getList();
1307                 for (AppStandbyInfo bucketInfo : bucketList) {
1308                     final String packageName = bucketInfo.mPackageName;
1309                     final int bucket = bucketInfo.mStandbyBucket;
1310                     if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
1311                             || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
1312                         throw new IllegalArgumentException(
1313                                 "Cannot set the standby bucket to " + bucket);
1314                     }
1315                     // Caller cannot set their own standby state
1316                     if (mPackageManagerInternal.getPackageUid(packageName,
1317                             PackageManager.MATCH_ANY_USER, userId) == callingUid) {
1318                         throw new IllegalArgumentException("Cannot set your own standby bucket");
1319                     }
1320                     mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
1321                             elapsedRealtime, shellCaller);
1322                 }
1323             } finally {
1324                 Binder.restoreCallingIdentity(token);
1325             }
1326         }
1327 
1328         @Override
whitelistAppTemporarily(String packageName, long duration, int userId)1329         public void whitelistAppTemporarily(String packageName, long duration, int userId)
1330                 throws RemoteException {
1331             StringBuilder reason = new StringBuilder(32);
1332             reason.append("from:");
1333             UserHandle.formatUid(reason, Binder.getCallingUid());
1334             mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
1335                     reason.toString());
1336         }
1337 
1338         @Override
onCarrierPrivilegedAppsChanged()1339         public void onCarrierPrivilegedAppsChanged() {
1340             if (DEBUG) {
1341                 Slog.i(TAG, "Carrier privileged apps changed");
1342             }
1343             getContext().enforceCallingOrSelfPermission(
1344                     android.Manifest.permission.BIND_CARRIER_SERVICES,
1345                     "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
1346             mAppStandby.clearCarrierPrivilegedApps();
1347         }
1348 
1349         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1350         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1351             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
1352             UsageStatsService.this.dump(args, pw);
1353         }
1354 
1355         @Override
reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1356         public void reportChooserSelection(String packageName, int userId, String contentType,
1357                                            String[] annotations, String action) {
1358             if (packageName == null) {
1359                 Slog.w(TAG, "Event report user selecting a null package");
1360                 return;
1361             }
1362 
1363             Event event = new Event(CHOOSER_ACTION, SystemClock.elapsedRealtime());
1364             event.mPackage = packageName;
1365             event.mAction = action;
1366             event.mContentType = contentType;
1367             event.mContentAnnotations = annotations;
1368             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1369         }
1370 
1371         @Override
registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)1372         public void registerAppUsageObserver(int observerId,
1373                 String[] packages, long timeLimitMs, PendingIntent
1374                 callbackIntent, String callingPackage) {
1375             if (!hasObserverPermission()) {
1376                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1377             }
1378 
1379             if (packages == null || packages.length == 0) {
1380                 throw new IllegalArgumentException("Must specify at least one package");
1381             }
1382             if (callbackIntent == null) {
1383                 throw new NullPointerException("callbackIntent can't be null");
1384             }
1385             final int callingUid = Binder.getCallingUid();
1386             final int userId = UserHandle.getUserId(callingUid);
1387             final long token = Binder.clearCallingIdentity();
1388             try {
1389                 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId,
1390                         packages, timeLimitMs, callbackIntent, userId);
1391             } finally {
1392                 Binder.restoreCallingIdentity(token);
1393             }
1394         }
1395 
1396         @Override
unregisterAppUsageObserver(int observerId, String callingPackage)1397         public void unregisterAppUsageObserver(int observerId, String callingPackage) {
1398             if (!hasObserverPermission()) {
1399                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1400             }
1401 
1402             final int callingUid = Binder.getCallingUid();
1403             final int userId = UserHandle.getUserId(callingUid);
1404             final long token = Binder.clearCallingIdentity();
1405             try {
1406                 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId);
1407             } finally {
1408                 Binder.restoreCallingIdentity(token);
1409             }
1410         }
1411 
1412         @Override
registerUsageSessionObserver(int sessionObserverId, String[] observed, long timeLimitMs, long sessionThresholdTimeMs, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, String callingPackage)1413         public void registerUsageSessionObserver(int sessionObserverId, String[] observed,
1414                 long timeLimitMs, long sessionThresholdTimeMs,
1415                 PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent,
1416                 String callingPackage) {
1417             if (!hasObserverPermission()) {
1418                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1419             }
1420 
1421             if (observed == null || observed.length == 0) {
1422                 throw new IllegalArgumentException("Must specify at least one observed entity");
1423             }
1424             if (limitReachedCallbackIntent == null) {
1425                 throw new NullPointerException("limitReachedCallbackIntent can't be null");
1426             }
1427             final int callingUid = Binder.getCallingUid();
1428             final int userId = UserHandle.getUserId(callingUid);
1429             final long token = Binder.clearCallingIdentity();
1430             try {
1431                 UsageStatsService.this.registerUsageSessionObserver(callingUid, sessionObserverId,
1432                         observed, timeLimitMs, sessionThresholdTimeMs, limitReachedCallbackIntent,
1433                         sessionEndCallbackIntent, userId);
1434             } finally {
1435                 Binder.restoreCallingIdentity(token);
1436             }
1437         }
1438 
1439         @Override
unregisterUsageSessionObserver(int sessionObserverId, String callingPackage)1440         public void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage) {
1441             if (!hasObserverPermission()) {
1442                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1443             }
1444 
1445             final int callingUid = Binder.getCallingUid();
1446             final int userId = UserHandle.getUserId(callingUid);
1447             final long token = Binder.clearCallingIdentity();
1448             try {
1449                 UsageStatsService.this.unregisterUsageSessionObserver(callingUid, sessionObserverId,
1450                         userId);
1451             } finally {
1452                 Binder.restoreCallingIdentity(token);
1453             }
1454         }
1455 
1456         @Override
registerAppUsageLimitObserver(int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, String callingPackage)1457         public void registerAppUsageLimitObserver(int observerId, String[] packages,
1458                 long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent,
1459                 String callingPackage) {
1460             if (!hasPermissions(callingPackage,
1461                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
1462                 throw new SecurityException("Caller doesn't have both SUSPEND_APPS and "
1463                         + "OBSERVE_APP_USAGE permissions");
1464             }
1465 
1466             if (packages == null || packages.length == 0) {
1467                 throw new IllegalArgumentException("Must specify at least one package");
1468             }
1469             if (callbackIntent == null && timeUsedMs < timeLimitMs) {
1470                 throw new NullPointerException("callbackIntent can't be null");
1471             }
1472             final int callingUid = Binder.getCallingUid();
1473             final int userId = UserHandle.getUserId(callingUid);
1474             final long token = Binder.clearCallingIdentity();
1475             try {
1476                 UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId,
1477                         packages, timeLimitMs, timeUsedMs, callbackIntent, userId);
1478             } finally {
1479                 Binder.restoreCallingIdentity(token);
1480             }
1481         }
1482 
1483         @Override
unregisterAppUsageLimitObserver(int observerId, String callingPackage)1484         public void unregisterAppUsageLimitObserver(int observerId, String callingPackage) {
1485             if (!hasPermissions(callingPackage,
1486                     Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) {
1487                 throw new SecurityException("Caller doesn't have both SUSPEND_APPS and "
1488                         + "OBSERVE_APP_USAGE permissions");
1489             }
1490 
1491             final int callingUid = Binder.getCallingUid();
1492             final int userId = UserHandle.getUserId(callingUid);
1493             final long token = Binder.clearCallingIdentity();
1494             try {
1495                 UsageStatsService.this.unregisterAppUsageLimitObserver(
1496                         callingUid, observerId, userId);
1497             } finally {
1498                 Binder.restoreCallingIdentity(token);
1499             }
1500         }
1501 
1502         @Override
reportUsageStart(IBinder activity, String token, String callingPackage)1503         public void reportUsageStart(IBinder activity, String token, String callingPackage) {
1504             reportPastUsageStart(activity, token, 0, callingPackage);
1505         }
1506 
1507         @Override
reportPastUsageStart(IBinder activity, String token, long timeAgoMs, String callingPackage)1508         public void reportPastUsageStart(IBinder activity, String token, long timeAgoMs,
1509                 String callingPackage) {
1510 
1511             final int callingUid = Binder.getCallingUid();
1512             final int userId = UserHandle.getUserId(callingUid);
1513             final long binderToken = Binder.clearCallingIdentity();
1514             try {
1515                 ArraySet<String> tokens;
1516                 synchronized (mUsageReporters) {
1517                     tokens = mUsageReporters.get(activity.hashCode());
1518                     if (tokens == null) {
1519                         tokens = new ArraySet();
1520                         mUsageReporters.put(activity.hashCode(), tokens);
1521                     }
1522                 }
1523 
1524                 synchronized (tokens) {
1525                     if (!tokens.add(token)) {
1526                         throw new IllegalArgumentException(token + " for " + callingPackage
1527                                 + " is already reported as started for this activity");
1528                     }
1529                 }
1530 
1531                 mAppTimeLimit.noteUsageStart(buildFullToken(callingPackage, token),
1532                         userId, timeAgoMs);
1533             } finally {
1534                 Binder.restoreCallingIdentity(binderToken);
1535             }
1536         }
1537 
1538         @Override
reportUsageStop(IBinder activity, String token, String callingPackage)1539         public void reportUsageStop(IBinder activity, String token, String callingPackage) {
1540             final int callingUid = Binder.getCallingUid();
1541             final int userId = UserHandle.getUserId(callingUid);
1542             final long binderToken = Binder.clearCallingIdentity();
1543             try {
1544                 ArraySet<String> tokens;
1545                 synchronized (mUsageReporters) {
1546                     tokens = mUsageReporters.get(activity.hashCode());
1547                     if (tokens == null) {
1548                         throw new IllegalArgumentException(
1549                                 "Unknown reporter trying to stop token " + token + " for "
1550                                         + callingPackage);
1551                     }
1552                 }
1553 
1554                 synchronized (tokens) {
1555                     if (!tokens.remove(token)) {
1556                         throw new IllegalArgumentException(token + " for " + callingPackage
1557                                 + " is already reported as stopped for this activity");
1558                     }
1559                 }
1560                 mAppTimeLimit.noteUsageStop(buildFullToken(callingPackage, token), userId);
1561             } finally {
1562                 Binder.restoreCallingIdentity(binderToken);
1563             }
1564         }
1565 
1566         @Override
getUsageSource()1567         public @UsageSource int getUsageSource() {
1568             if (!hasObserverPermission()) {
1569                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1570             }
1571             synchronized (mLock) {
1572                 return mUsageSource;
1573             }
1574         }
1575 
1576         @Override
forceUsageSourceSettingRead()1577         public void forceUsageSourceSettingRead() {
1578             readUsageSourceSetting();
1579         }
1580     }
1581 
registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)1582     void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
1583             long timeLimitMs, PendingIntent callbackIntent, int userId) {
1584         mAppTimeLimit.addAppUsageObserver(callingUid, observerId, packages, timeLimitMs,
1585                 callbackIntent,
1586                 userId);
1587     }
1588 
unregisterAppUsageObserver(int callingUid, int observerId, int userId)1589     void unregisterAppUsageObserver(int callingUid, int observerId, int userId) {
1590         mAppTimeLimit.removeAppUsageObserver(callingUid, observerId, userId);
1591     }
1592 
registerUsageSessionObserver(int callingUid, int observerId, String[] observed, long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent, int userId)1593     void registerUsageSessionObserver(int callingUid, int observerId, String[] observed,
1594             long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent,
1595             PendingIntent sessionEndCallbackIntent, int userId) {
1596         mAppTimeLimit.addUsageSessionObserver(callingUid, observerId, observed, timeLimitMs,
1597                 sessionThresholdTime, limitReachedCallbackIntent, sessionEndCallbackIntent, userId);
1598     }
1599 
unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId)1600     void unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId) {
1601         mAppTimeLimit.removeUsageSessionObserver(callingUid, sessionObserverId, userId);
1602     }
1603 
registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId)1604     void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages,
1605             long timeLimitMs, long timeUsedMs, PendingIntent callbackIntent, int userId) {
1606         mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages,
1607                 timeLimitMs, timeUsedMs, callbackIntent, userId);
1608     }
1609 
unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId)1610     void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) {
1611         mAppTimeLimit.removeAppUsageLimitObserver(callingUid, observerId, userId);
1612     }
1613 
1614     /**
1615      * This local service implementation is primarily used by ActivityManagerService.
1616      * ActivityManagerService will call these methods holding the 'am' lock, which means we
1617      * shouldn't be doing any IO work or other long running tasks in these methods.
1618      */
1619     private final class LocalService extends UsageStatsManagerInternal {
1620 
1621         @Override
reportEvent(ComponentName component, int userId, int eventType, int instanceId, ComponentName taskRoot)1622         public void reportEvent(ComponentName component, int userId, int eventType,
1623                 int instanceId, ComponentName taskRoot) {
1624             if (component == null) {
1625                 Slog.w(TAG, "Event reported without a component name");
1626                 return;
1627             }
1628 
1629             Event event = new Event(eventType, SystemClock.elapsedRealtime());
1630             event.mPackage = component.getPackageName();
1631             event.mClass = component.getClassName();
1632             event.mInstanceId = instanceId;
1633             if (taskRoot == null) {
1634                 event.mTaskRootPackage = null;
1635                 event.mTaskRootClass = null;
1636             } else {
1637                 event.mTaskRootPackage = taskRoot.getPackageName();
1638                 event.mTaskRootClass = taskRoot.getClassName();
1639             }
1640             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1641         }
1642 
1643         @Override
reportEvent(String packageName, int userId, int eventType)1644         public void reportEvent(String packageName, int userId, int eventType) {
1645             if (packageName == null) {
1646                 Slog.w(TAG, "Event reported without a package name, eventType:" + eventType);
1647                 return;
1648             }
1649 
1650             Event event = new Event(eventType, SystemClock.elapsedRealtime());
1651             event.mPackage = packageName;
1652             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1653         }
1654 
1655         @Override
reportConfigurationChange(Configuration config, int userId)1656         public void reportConfigurationChange(Configuration config, int userId) {
1657             if (config == null) {
1658                 Slog.w(TAG, "Configuration event reported with a null config");
1659                 return;
1660             }
1661 
1662             Event event = new Event(CONFIGURATION_CHANGE, SystemClock.elapsedRealtime());
1663             event.mPackage = "android";
1664             event.mConfiguration = new Configuration(config);
1665             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1666         }
1667 
1668         @Override
reportInterruptiveNotification(String packageName, String channelId, int userId)1669         public void reportInterruptiveNotification(String packageName, String channelId,
1670                 int userId) {
1671             if (packageName == null || channelId == null) {
1672                 Slog.w(TAG, "Event reported without a package name or a channel ID");
1673                 return;
1674             }
1675 
1676             Event event = new Event(NOTIFICATION_INTERRUPTION, SystemClock.elapsedRealtime());
1677             event.mPackage = packageName.intern();
1678             event.mNotificationChannelId = channelId.intern();
1679             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1680         }
1681 
1682         @Override
reportShortcutUsage(String packageName, String shortcutId, int userId)1683         public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
1684             if (packageName == null || shortcutId == null) {
1685                 Slog.w(TAG, "Event reported without a package name or a shortcut ID");
1686                 return;
1687             }
1688 
1689             Event event = new Event(SHORTCUT_INVOCATION, SystemClock.elapsedRealtime());
1690             event.mPackage = packageName.intern();
1691             event.mShortcutId = shortcutId.intern();
1692             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1693         }
1694 
1695         @Override
reportContentProviderUsage(String name, String packageName, int userId)1696         public void reportContentProviderUsage(String name, String packageName, int userId) {
1697             mAppStandby.postReportContentProviderUsage(name, packageName, userId);
1698         }
1699 
1700         @Override
isAppIdle(String packageName, int uidForAppId, int userId)1701         public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
1702             return mAppStandby.isAppIdleFiltered(packageName, uidForAppId,
1703                     userId, SystemClock.elapsedRealtime());
1704         }
1705 
1706         @Override
getAppStandbyBucket(String packageName, int userId, long nowElapsed)1707         @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
1708                 long nowElapsed) {
1709             return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false);
1710         }
1711 
1712         @Override
getIdleUidsForUser(int userId)1713         public int[] getIdleUidsForUser(int userId) {
1714             return mAppStandby.getIdleUidsForUser(userId);
1715         }
1716 
1717         @Override
isAppIdleParoleOn()1718         public boolean isAppIdleParoleOn() {
1719             return mAppStandby.isParoledOrCharging();
1720         }
1721 
1722         @Override
prepareShutdown()1723         public void prepareShutdown() {
1724             // This method *WILL* do IO work, but we must block until it is finished or else
1725             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1726             // we are shutting down.
1727             UsageStatsService.this.shutdown();
1728         }
1729 
1730         @Override
prepareForPossibleShutdown()1731         public void prepareForPossibleShutdown() {
1732             UsageStatsService.this.prepareForPossibleShutdown();
1733         }
1734 
1735         @Override
addAppIdleStateChangeListener(AppIdleStateChangeListener listener)1736         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1737             mAppStandby.addListener(listener);
1738             listener.onParoleStateChanged(isAppIdleParoleOn());
1739         }
1740 
1741         @Override
removeAppIdleStateChangeListener( AppIdleStateChangeListener listener)1742         public void removeAppIdleStateChangeListener(
1743                 AppIdleStateChangeListener listener) {
1744             mAppStandby.removeListener(listener);
1745         }
1746 
1747         @Override
getBackupPayload(int user, String key)1748         public byte[] getBackupPayload(int user, String key) {
1749             // Check to ensure that only user 0's data is b/r for now
1750             synchronized (mLock) {
1751                 if (user == UserHandle.USER_SYSTEM) {
1752                     final UserUsageStatsService userStats =
1753                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1754                     return userStats.getBackupPayload(key);
1755                 } else {
1756                     return null;
1757                 }
1758             }
1759         }
1760 
1761         @Override
applyRestoredPayload(int user, String key, byte[] payload)1762         public void applyRestoredPayload(int user, String key, byte[] payload) {
1763             synchronized (mLock) {
1764                 if (user == UserHandle.USER_SYSTEM) {
1765                     final UserUsageStatsService userStats =
1766                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1767                     userStats.applyRestoredPayload(key, payload);
1768                 }
1769             }
1770         }
1771 
1772         @Override
queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)1773         public List<UsageStats> queryUsageStatsForUser(
1774                 int userId, int intervalType, long beginTime, long endTime,
1775                 boolean obfuscateInstantApps) {
1776             return UsageStatsService.this.queryUsageStats(
1777                     userId, intervalType, beginTime, endTime, obfuscateInstantApps);
1778         }
1779 
1780         @Override
setLastJobRunTime(String packageName, int userId, long elapsedRealtime)1781         public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
1782             mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime);
1783         }
1784 
1785         @Override
getTimeSinceLastJobRun(String packageName, int userId)1786         public long getTimeSinceLastJobRun(String packageName, int userId) {
1787             return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
1788         }
1789 
1790         @Override
reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)1791         public void reportAppJobState(String packageName, int userId,
1792                 int numDeferredJobs, long timeSinceLastJobRun) {
1793         }
1794 
1795         @Override
onActiveAdminAdded(String packageName, int userId)1796         public void onActiveAdminAdded(String packageName, int userId) {
1797             mAppStandby.addActiveDeviceAdmin(packageName, userId);
1798         }
1799 
1800         @Override
setActiveAdminApps(Set<String> packageNames, int userId)1801         public void setActiveAdminApps(Set<String> packageNames, int userId) {
1802             mAppStandby.setActiveAdminApps(packageNames, userId);
1803         }
1804 
1805         @Override
onAdminDataAvailable()1806         public void onAdminDataAvailable() {
1807             mAppStandby.onAdminDataAvailable();
1808         }
1809 
1810         @Override
reportSyncScheduled(String packageName, int userId, boolean exempted)1811         public void reportSyncScheduled(String packageName, int userId, boolean exempted) {
1812             mAppStandby.postReportSyncScheduled(packageName, userId, exempted);
1813         }
1814 
1815         @Override
reportExemptedSyncStart(String packageName, int userId)1816         public void reportExemptedSyncStart(String packageName, int userId) {
1817             mAppStandby.postReportExemptedSyncStart(packageName, userId);
1818         }
1819 
1820         @Override
getAppUsageLimit(String packageName, UserHandle user)1821         public AppUsageLimitData getAppUsageLimit(String packageName, UserHandle user) {
1822             return mAppTimeLimit.getAppUsageLimit(packageName, user);
1823         }
1824     }
1825 }
1826