• 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 android.Manifest;
20 import android.app.ActivityManager;
21 import android.app.AppOpsManager;
22 import android.app.IUidObserver;
23 import android.app.PendingIntent;
24 import android.app.admin.DeviceAdminInfo;
25 import android.app.admin.DevicePolicyManagerInternal;
26 import android.app.usage.AppStandbyInfo;
27 import android.app.usage.ConfigurationStats;
28 import android.app.usage.EventStats;
29 import android.app.usage.IUsageStatsManager;
30 import android.app.usage.UsageEvents;
31 import android.app.usage.UsageStatsManager;
32 import android.app.usage.UsageStatsManager.StandbyBuckets;
33 import android.app.usage.UsageEvents.Event;
34 import android.app.usage.UsageStats;
35 import android.app.usage.UsageStatsManagerInternal;
36 import android.content.BroadcastReceiver;
37 import android.content.ComponentName;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.content.IntentFilter;
41 import android.content.pm.PackageManager;
42 import android.content.pm.PackageManagerInternal;
43 import android.content.pm.ParceledListSlice;
44 import android.content.pm.UserInfo;
45 import android.content.res.Configuration;
46 import android.os.Binder;
47 import android.os.Environment;
48 import android.os.FileUtils;
49 import android.os.Handler;
50 import android.os.IDeviceIdleController;
51 import android.os.Looper;
52 import android.os.Message;
53 import android.os.Process;
54 import android.os.RemoteException;
55 import android.os.ServiceManager;
56 import android.os.SystemClock;
57 import android.os.SystemProperties;
58 import android.os.UserHandle;
59 import android.os.UserManager;
60 import android.util.ArraySet;
61 import android.util.Slog;
62 import android.util.SparseArray;
63 import android.util.SparseIntArray;
64 
65 import com.android.internal.content.PackageMonitor;
66 import com.android.internal.os.BackgroundThread;
67 import com.android.internal.util.DumpUtils;
68 import com.android.internal.util.IndentingPrintWriter;
69 import com.android.server.LocalServices;
70 import com.android.server.SystemService;
71 
72 import java.io.File;
73 import java.io.FileDescriptor;
74 import java.io.IOException;
75 import java.io.PrintWriter;
76 import java.util.Arrays;
77 import java.util.List;
78 import java.util.Map;
79 import java.util.Set;
80 import java.util.concurrent.TimeUnit;
81 
82 /**
83  * A service that collects, aggregates, and persists application usage data.
84  * This data can be queried by apps that have been granted permission by AppOps.
85  */
86 public class UsageStatsService extends SystemService implements
87         UserUsageStatsService.StatsUpdatedListener {
88 
89     static final String TAG = "UsageStatsService";
90     public static final boolean ENABLE_TIME_CHANGE_CORRECTION
91             = SystemProperties.getBoolean("persist.debug.time_correction", true);
92 
93     static final boolean DEBUG = false; // Never submit with true
94     static final boolean COMPRESS_TIME = false;
95 
96     private static final long TEN_SECONDS = 10 * 1000;
97     private static final long TWENTY_MINUTES = 20 * 60 * 1000;
98     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
99     private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
100 
101     private static final boolean ENABLE_KERNEL_UPDATES = true;
102     private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
103 
104     // Handler message types.
105     static final int MSG_REPORT_EVENT = 0;
106     static final int MSG_FLUSH_TO_DISK = 1;
107     static final int MSG_REMOVE_USER = 2;
108     static final int MSG_UID_STATE_CHANGED = 3;
109 
110     private final Object mLock = new Object();
111     Handler mHandler;
112     AppOpsManager mAppOps;
113     UserManager mUserManager;
114     PackageManager mPackageManager;
115     PackageManagerInternal mPackageManagerInternal;
116     PackageMonitor mPackageMonitor;
117     IDeviceIdleController mDeviceIdleController;
118     // Do not use directly. Call getDpmInternal() instead
119     DevicePolicyManagerInternal mDpmInternal;
120 
121     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
122     private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
123     private File mUsageStatsDir;
124     long mRealTimeSnapshot;
125     long mSystemTimeSnapshot;
126 
127     /** Manages the standby state of apps. */
128     AppStandbyController mAppStandby;
129 
130     /** Manages app time limit observers */
131     AppTimeLimitController mAppTimeLimit;
132 
133     private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
134             new UsageStatsManagerInternal.AppIdleStateChangeListener() {
135                 @Override
136                 public void onAppIdleStateChanged(String packageName, int userId, boolean idle,
137                         int bucket, int reason) {
138                     Event event = new Event();
139                     event.mEventType = Event.STANDBY_BUCKET_CHANGED;
140                     event.mBucketAndReason = (bucket << 16) | (reason & 0xFFFF);
141                     event.mPackage = packageName;
142                     // This will later be converted to system time.
143                     event.mTimeStamp = SystemClock.elapsedRealtime();
144                     mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
145                 }
146 
147                 @Override
148                 public void onParoleStateChanged(boolean isParoleOn) {
149 
150                 }
151             };
152 
UsageStatsService(Context context)153     public UsageStatsService(Context context) {
154         super(context);
155     }
156 
157     @Override
onStart()158     public void onStart() {
159         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
160         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
161         mPackageManager = getContext().getPackageManager();
162         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
163         mHandler = new H(BackgroundThread.get().getLooper());
164 
165         mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
166 
167         mAppTimeLimit = new AppTimeLimitController(
168                 (observerId, userId, timeLimit, timeElapsed, callbackIntent) -> {
169                     Intent intent = new Intent();
170                     intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
171                     intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
172                     intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
173                     try {
174                         callbackIntent.send(getContext(), 0, intent);
175                     } catch (PendingIntent.CanceledException e) {
176                         Slog.w(TAG, "Couldn't deliver callback: "
177                                 + callbackIntent);
178                     }
179                 }, mHandler.getLooper());
180 
181         mAppStandby.addListener(mStandbyChangeListener);
182         File systemDataDir = new File(Environment.getDataDirectory(), "system");
183         mUsageStatsDir = new File(systemDataDir, "usagestats");
184         mUsageStatsDir.mkdirs();
185         if (!mUsageStatsDir.exists()) {
186             throw new IllegalStateException("Usage stats directory does not exist: "
187                     + mUsageStatsDir.getAbsolutePath());
188         }
189 
190         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
191         filter.addAction(Intent.ACTION_USER_STARTED);
192         getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
193                 null, mHandler);
194 
195         synchronized (mLock) {
196             cleanUpRemovedUsersLocked();
197         }
198 
199         mRealTimeSnapshot = SystemClock.elapsedRealtime();
200         mSystemTimeSnapshot = System.currentTimeMillis();
201 
202         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
203         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
204         // Make sure we initialize the data, in case job scheduler needs it early.
205         getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot);
206     }
207 
208     @Override
onBootPhase(int phase)209     public void onBootPhase(int phase) {
210         if (phase == PHASE_SYSTEM_SERVICES_READY) {
211             mAppStandby.onBootPhase(phase);
212             // initialize mDpmInternal
213             getDpmInternal();
214 
215             mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
216                     ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
217 
218             if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
219                 try {
220                     ActivityManager.getService().registerUidObserver(mUidObserver,
221                             ActivityManager.UID_OBSERVER_PROCSTATE
222                                     | ActivityManager.UID_OBSERVER_GONE,
223                             ActivityManager.PROCESS_STATE_UNKNOWN, null);
224                 } catch (RemoteException e) {
225                     throw new RuntimeException(e);
226                 }
227             } else {
228                 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE);
229             }
230         }
231     }
232 
getDpmInternal()233     private DevicePolicyManagerInternal getDpmInternal() {
234         if (mDpmInternal == null) {
235             mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
236         }
237         return mDpmInternal;
238     }
239 
240     private class UserActionsReceiver extends BroadcastReceiver {
241         @Override
onReceive(Context context, Intent intent)242         public void onReceive(Context context, Intent intent) {
243             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
244             final String action = intent.getAction();
245             if (Intent.ACTION_USER_REMOVED.equals(action)) {
246                 if (userId >= 0) {
247                     mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
248                 }
249             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
250                 if (userId >=0) {
251                     mAppStandby.postCheckIdleStates(userId);
252                 }
253             }
254         }
255     }
256 
257     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
258         @Override
259         public void onUidStateChanged(int uid, int procState, long procStateSeq) {
260             mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
261         }
262 
263         @Override
264         public void onUidIdle(int uid, boolean disabled) {
265             // Ignored
266         }
267 
268         @Override
269         public void onUidGone(int uid, boolean disabled) {
270             onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
271         }
272 
273         @Override
274         public void onUidActive(int uid) {
275             // Ignored
276         }
277 
278         @Override public void onUidCachedChanged(int uid, boolean cached) {
279         }
280     };
281 
282     @Override
onStatsUpdated()283     public void onStatsUpdated() {
284         mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
285     }
286 
287     @Override
onStatsReloaded()288     public void onStatsReloaded() {
289         mAppStandby.postOneTimeCheckIdleStates();
290     }
291 
292     @Override
onNewUpdate(int userId)293     public void onNewUpdate(int userId) {
294         mAppStandby.initializeDefaultsForSystemApps(userId);
295     }
296 
shouldObfuscateInstantAppsForCaller(int callingUid, int userId)297     private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
298         return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
299     }
300 
cleanUpRemovedUsersLocked()301     private void cleanUpRemovedUsersLocked() {
302         final List<UserInfo> users = mUserManager.getUsers(true);
303         if (users == null || users.size() == 0) {
304             throw new IllegalStateException("There can't be no users");
305         }
306 
307         ArraySet<String> toDelete = new ArraySet<>();
308         String[] fileNames = mUsageStatsDir.list();
309         if (fileNames == null) {
310             // No users to delete.
311             return;
312         }
313 
314         toDelete.addAll(Arrays.asList(fileNames));
315 
316         final int userCount = users.size();
317         for (int i = 0; i < userCount; i++) {
318             final UserInfo userInfo = users.get(i);
319             toDelete.remove(Integer.toString(userInfo.id));
320         }
321 
322         final int deleteCount = toDelete.size();
323         for (int i = 0; i < deleteCount; i++) {
324             deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
325         }
326     }
327 
deleteRecursively(File f)328     private static void deleteRecursively(File f) {
329         File[] files = f.listFiles();
330         if (files != null) {
331             for (File subFile : files) {
332                 deleteRecursively(subFile);
333             }
334         }
335 
336         if (!f.delete()) {
337             Slog.e(TAG, "Failed to delete " + f);
338         }
339     }
340 
getUserDataAndInitializeIfNeededLocked(int userId, long currentTimeMillis)341     private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
342             long currentTimeMillis) {
343         UserUsageStatsService service = mUserState.get(userId);
344         if (service == null) {
345             service = new UserUsageStatsService(getContext(), userId,
346                     new File(mUsageStatsDir, Integer.toString(userId)), this);
347             service.init(currentTimeMillis);
348             mUserState.put(userId, service);
349         }
350         return service;
351     }
352 
353     /**
354      * This should be the only way to get the time from the system.
355      */
checkAndGetTimeLocked()356     private long checkAndGetTimeLocked() {
357         final long actualSystemTime = System.currentTimeMillis();
358         final long actualRealtime = SystemClock.elapsedRealtime();
359         final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
360         final long diffSystemTime = actualSystemTime - expectedSystemTime;
361         if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS
362                 && ENABLE_TIME_CHANGE_CORRECTION) {
363             // The time has changed.
364             Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
365             final int userCount = mUserState.size();
366             for (int i = 0; i < userCount; i++) {
367                 final UserUsageStatsService service = mUserState.valueAt(i);
368                 service.onTimeChanged(expectedSystemTime, actualSystemTime);
369             }
370             mRealTimeSnapshot = actualRealtime;
371             mSystemTimeSnapshot = actualSystemTime;
372         }
373         return actualSystemTime;
374     }
375 
376     /**
377      * Assuming the event's timestamp is measured in milliseconds since boot,
378      * convert it to a system wall time.
379      */
convertToSystemTimeLocked(UsageEvents.Event event)380     private void convertToSystemTimeLocked(UsageEvents.Event event) {
381         event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
382     }
383 
384     /**
385      * Called by the Binder stub
386      */
shutdown()387     void shutdown() {
388         synchronized (mLock) {
389             mHandler.removeMessages(MSG_REPORT_EVENT);
390             flushToDiskLocked();
391         }
392     }
393 
394     /**
395      * Called by the Binder stub.
396      */
reportEvent(UsageEvents.Event event, int userId)397     void reportEvent(UsageEvents.Event event, int userId) {
398         synchronized (mLock) {
399             final long timeNow = checkAndGetTimeLocked();
400             final long elapsedRealtime = SystemClock.elapsedRealtime();
401             convertToSystemTimeLocked(event);
402 
403             if (event.getPackageName() != null
404                     && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
405                 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
406             }
407 
408             final UserUsageStatsService service =
409                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
410             service.reportEvent(event);
411 
412             mAppStandby.reportEvent(event, elapsedRealtime, userId);
413             switch (event.mEventType) {
414                 case Event.MOVE_TO_FOREGROUND:
415                     mAppTimeLimit.moveToForeground(event.getPackageName(), event.getClassName(),
416                             userId);
417                     break;
418                 case Event.MOVE_TO_BACKGROUND:
419                     mAppTimeLimit.moveToBackground(event.getPackageName(), event.getClassName(),
420                             userId);
421                     break;
422             }
423         }
424     }
425 
426     /**
427      * Called by the Binder stub.
428      */
flushToDisk()429     void flushToDisk() {
430         synchronized (mLock) {
431             flushToDiskLocked();
432         }
433     }
434 
435     /**
436      * Called by the Binder stub.
437      */
onUserRemoved(int userId)438     void onUserRemoved(int userId) {
439         synchronized (mLock) {
440             Slog.i(TAG, "Removing user " + userId + " and all data.");
441             mUserState.remove(userId);
442             mAppStandby.onUserRemoved(userId);
443             mAppTimeLimit.onUserRemoved(userId);
444             cleanUpRemovedUsersLocked();
445         }
446     }
447 
448     /**
449      * Called by the Binder stub.
450      */
queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)451     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
452             boolean obfuscateInstantApps) {
453         synchronized (mLock) {
454             final long timeNow = checkAndGetTimeLocked();
455             if (!validRange(timeNow, beginTime, endTime)) {
456                 return null;
457             }
458 
459             final UserUsageStatsService service =
460                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
461             List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
462             if (list == null) {
463                 return null;
464             }
465 
466             // Mangle instant app names *using their current state (not whether they were ephemeral
467             // when the data was recorded)*.
468             if (obfuscateInstantApps) {
469                 for (int i = list.size() - 1; i >= 0; i--) {
470                     final UsageStats stats = list.get(i);
471                     if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
472                         list.set(i, stats.getObfuscatedForInstantApp());
473                     }
474                 }
475             }
476 
477             return list;
478         }
479     }
480 
481     /**
482      * Called by the Binder stub.
483      */
queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)484     List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
485             long endTime) {
486         synchronized (mLock) {
487             final long timeNow = checkAndGetTimeLocked();
488             if (!validRange(timeNow, beginTime, endTime)) {
489                 return null;
490             }
491 
492             final UserUsageStatsService service =
493                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
494             return service.queryConfigurationStats(bucketType, beginTime, endTime);
495         }
496     }
497 
498     /**
499      * Called by the Binder stub.
500      */
queryEventStats(int userId, int bucketType, long beginTime, long endTime)501     List<EventStats> queryEventStats(int userId, int bucketType, long beginTime,
502             long endTime) {
503         synchronized (mLock) {
504             final long timeNow = checkAndGetTimeLocked();
505             if (!validRange(timeNow, beginTime, endTime)) {
506                 return null;
507             }
508 
509             final UserUsageStatsService service =
510                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
511             return service.queryEventStats(bucketType, beginTime, endTime);
512         }
513     }
514 
515     /**
516      * Called by the Binder stub.
517      */
queryEvents(int userId, long beginTime, long endTime, boolean shouldObfuscateInstantApps)518     UsageEvents queryEvents(int userId, long beginTime, long endTime,
519             boolean shouldObfuscateInstantApps) {
520         synchronized (mLock) {
521             final long timeNow = checkAndGetTimeLocked();
522             if (!validRange(timeNow, beginTime, endTime)) {
523                 return null;
524             }
525 
526             final UserUsageStatsService service =
527                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
528             return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
529         }
530     }
531 
532     /**
533      * Called by the Binder stub.
534      */
queryEventsForPackage(int userId, long beginTime, long endTime, String packageName)535     UsageEvents queryEventsForPackage(int userId, long beginTime, long endTime,
536             String packageName) {
537         synchronized (mLock) {
538             final long timeNow = checkAndGetTimeLocked();
539             if (!validRange(timeNow, beginTime, endTime)) {
540                 return null;
541             }
542 
543             final UserUsageStatsService service =
544                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
545             return service.queryEventsForPackage(beginTime, endTime, packageName);
546         }
547     }
548 
validRange(long currentTime, long beginTime, long endTime)549     private static boolean validRange(long currentTime, long beginTime, long endTime) {
550         return beginTime <= currentTime && beginTime < endTime;
551     }
552 
flushToDiskLocked()553     private void flushToDiskLocked() {
554         final int userCount = mUserState.size();
555         for (int i = 0; i < userCount; i++) {
556             UserUsageStatsService service = mUserState.valueAt(i);
557             service.persistActiveStats();
558             mAppStandby.flushToDisk(mUserState.keyAt(i));
559         }
560         mAppStandby.flushDurationsToDisk();
561 
562         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
563     }
564 
565     /**
566      * Called by the Binder stub.
567      */
dump(String[] args, PrintWriter pw)568     void dump(String[] args, PrintWriter pw) {
569         synchronized (mLock) {
570             IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
571 
572             boolean checkin = false;
573             boolean compact = false;
574             String pkg = null;
575 
576             if (args != null) {
577                 for (int i = 0; i < args.length; i++) {
578                     String arg = args[i];
579                     if ("--checkin".equals(arg)) {
580                         checkin = true;
581                     } else
582                     if ("-c".equals(arg)) {
583                         compact = true;
584                     } else if ("flush".equals(arg)) {
585                         flushToDiskLocked();
586                         pw.println("Flushed stats to disk");
587                         return;
588                     } else if ("is-app-standby-enabled".equals(arg)) {
589                         pw.println(mAppStandby.mAppIdleEnabled);
590                         return;
591                     } else if (arg != null && !arg.startsWith("-")) {
592                         // Anything else that doesn't start with '-' is a pkg to filter
593                         pkg = arg;
594                         break;
595                     }
596                 }
597             }
598 
599             final int userCount = mUserState.size();
600             for (int i = 0; i < userCount; i++) {
601                 int userId = mUserState.keyAt(i);
602                 idpw.printPair("user", userId);
603                 idpw.println();
604                 idpw.increaseIndent();
605                 if (checkin) {
606                     mUserState.valueAt(i).checkin(idpw);
607                 } else {
608                     mUserState.valueAt(i).dump(idpw, pkg, compact);
609                     idpw.println();
610                 }
611                 mAppStandby.dumpUser(idpw, userId, pkg);
612                 idpw.decreaseIndent();
613             }
614 
615             if (pkg == null) {
616                 pw.println();
617                 mAppStandby.dumpState(args, pw);
618             }
619 
620             mAppTimeLimit.dump(pw);
621         }
622     }
623 
624     class H extends Handler {
H(Looper looper)625         public H(Looper looper) {
626             super(looper);
627         }
628 
629         @Override
handleMessage(Message msg)630         public void handleMessage(Message msg) {
631             switch (msg.what) {
632                 case MSG_REPORT_EVENT:
633                     reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
634                     break;
635 
636                 case MSG_FLUSH_TO_DISK:
637                     flushToDisk();
638                     break;
639 
640                 case MSG_REMOVE_USER:
641                     onUserRemoved(msg.arg1);
642                     break;
643 
644                 case MSG_UID_STATE_CHANGED: {
645                     final int uid = msg.arg1;
646                     final int procState = msg.arg2;
647 
648                     final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
649                     synchronized (mUidToKernelCounter) {
650                         final int oldCounter = mUidToKernelCounter.get(uid, 0);
651                         if (newCounter != oldCounter) {
652                             mUidToKernelCounter.put(uid, newCounter);
653                             try {
654                                 FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter);
655                             } catch (IOException e) {
656                                 Slog.w(TAG, "Failed to update counter set: " + e);
657                             }
658                         }
659                     }
660                     break;
661                 }
662 
663                 default:
664                     super.handleMessage(msg);
665                     break;
666             }
667         }
668     }
669 
670     private final class BinderService extends IUsageStatsManager.Stub {
671 
hasPermission(String callingPackage)672         private boolean hasPermission(String callingPackage) {
673             final int callingUid = Binder.getCallingUid();
674             if (callingUid == Process.SYSTEM_UID) {
675                 return true;
676             }
677             final int mode = mAppOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
678                     callingUid, callingPackage);
679             if (mode == AppOpsManager.MODE_DEFAULT) {
680                 // The default behavior here is to check if PackageManager has given the app
681                 // permission.
682                 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
683                         == PackageManager.PERMISSION_GRANTED;
684             }
685             return mode == AppOpsManager.MODE_ALLOWED;
686         }
687 
hasObserverPermission(String callingPackage)688         private boolean hasObserverPermission(String callingPackage) {
689             final int callingUid = Binder.getCallingUid();
690             DevicePolicyManagerInternal dpmInternal = getDpmInternal();
691             if (callingUid == Process.SYSTEM_UID
692                     || (dpmInternal != null
693                         && dpmInternal.isActiveAdminWithPolicy(callingUid,
694                             DeviceAdminInfo.USES_POLICY_PROFILE_OWNER))) {
695                 // Caller is the system or the profile owner, so proceed.
696                 return true;
697             }
698             return getContext().checkCallingPermission(Manifest.permission.OBSERVE_APP_USAGE)
699                     == PackageManager.PERMISSION_GRANTED;
700         }
701 
checkCallerIsSystemOrSameApp(String pkg)702         private void checkCallerIsSystemOrSameApp(String pkg) {
703             if (isCallingUidSystem()) {
704                 return;
705             }
706             checkCallerIsSameApp(pkg);
707         }
708 
checkCallerIsSameApp(String pkg)709         private void checkCallerIsSameApp(String pkg) {
710             final int callingUid = Binder.getCallingUid();
711             final int callingUserId = UserHandle.getUserId(callingUid);
712 
713             if (mPackageManagerInternal.getPackageUid(pkg, /*flags=*/ 0,
714                     callingUserId) != callingUid) {
715                 throw new SecurityException("Calling uid " + pkg + " cannot query events"
716                         + "for package " + pkg);
717             }
718         }
719 
isCallingUidSystem()720         private boolean isCallingUidSystem() {
721             final int uid = Binder.getCallingUid();
722             return uid == Process.SYSTEM_UID;
723         }
724 
725         @Override
queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage)726         public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
727                 long endTime, String callingPackage) {
728             if (!hasPermission(callingPackage)) {
729                 return null;
730             }
731 
732             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
733                     Binder.getCallingUid(), UserHandle.getCallingUserId());
734 
735             final int userId = UserHandle.getCallingUserId();
736             final long token = Binder.clearCallingIdentity();
737             try {
738                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
739                         userId, bucketType, beginTime, endTime, obfuscateInstantApps);
740                 if (results != null) {
741                     return new ParceledListSlice<>(results);
742                 }
743             } finally {
744                 Binder.restoreCallingIdentity(token);
745             }
746             return null;
747         }
748 
749         @Override
queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)750         public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
751                 long beginTime, long endTime, String callingPackage) throws RemoteException {
752             if (!hasPermission(callingPackage)) {
753                 return null;
754             }
755 
756             final int userId = UserHandle.getCallingUserId();
757             final long token = Binder.clearCallingIdentity();
758             try {
759                 final List<ConfigurationStats> results =
760                         UsageStatsService.this.queryConfigurationStats(userId, bucketType,
761                                 beginTime, endTime);
762                 if (results != null) {
763                     return new ParceledListSlice<>(results);
764                 }
765             } finally {
766                 Binder.restoreCallingIdentity(token);
767             }
768             return null;
769         }
770 
771         @Override
queryEventStats(int bucketType, long beginTime, long endTime, String callingPackage)772         public ParceledListSlice<EventStats> queryEventStats(int bucketType,
773                 long beginTime, long endTime, String callingPackage) throws RemoteException {
774             if (!hasPermission(callingPackage)) {
775                 return null;
776             }
777 
778             final int userId = UserHandle.getCallingUserId();
779             final long token = Binder.clearCallingIdentity();
780             try {
781                 final List<EventStats> results =
782                         UsageStatsService.this.queryEventStats(userId, bucketType,
783                                 beginTime, endTime);
784                 if (results != null) {
785                     return new ParceledListSlice<>(results);
786                 }
787             } finally {
788                 Binder.restoreCallingIdentity(token);
789             }
790             return null;
791         }
792 
793         @Override
queryEvents(long beginTime, long endTime, String callingPackage)794         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
795             if (!hasPermission(callingPackage)) {
796                 return null;
797             }
798 
799             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
800                     Binder.getCallingUid(), UserHandle.getCallingUserId());
801 
802             final int userId = UserHandle.getCallingUserId();
803             final long token = Binder.clearCallingIdentity();
804             try {
805                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
806                         obfuscateInstantApps);
807             } finally {
808                 Binder.restoreCallingIdentity(token);
809             }
810         }
811 
812         @Override
queryEventsForPackage(long beginTime, long endTime, String callingPackage)813         public UsageEvents queryEventsForPackage(long beginTime, long endTime,
814                 String callingPackage) {
815             final int callingUid = Binder.getCallingUid();
816             final int callingUserId = UserHandle.getUserId(callingUid);
817 
818             checkCallerIsSameApp(callingPackage);
819             final long token = Binder.clearCallingIdentity();
820             try {
821                 return UsageStatsService.this.queryEventsForPackage(callingUserId, beginTime,
822                         endTime, callingPackage);
823             } finally {
824                 Binder.restoreCallingIdentity(token);
825             }
826         }
827 
828         @Override
queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage)829         public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId,
830                 String callingPackage) {
831             if (!hasPermission(callingPackage)) {
832                 return null;
833             }
834 
835             if (userId != UserHandle.getCallingUserId()) {
836                 getContext().enforceCallingPermission(
837                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
838                         "No permission to query usage stats for this user");
839             }
840 
841             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
842                     Binder.getCallingUid(), UserHandle.getCallingUserId());
843 
844             final long token = Binder.clearCallingIdentity();
845             try {
846                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
847                         obfuscateInstantApps);
848             } finally {
849                 Binder.restoreCallingIdentity(token);
850             }
851         }
852 
853         @Override
queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage)854         public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime,
855                 int userId, String pkg, String callingPackage) {
856             if (!hasPermission(callingPackage)) {
857                 return null;
858             }
859             if (userId != UserHandle.getCallingUserId()) {
860                 getContext().enforceCallingPermission(
861                         Manifest.permission.INTERACT_ACROSS_USERS_FULL,
862                         "No permission to query usage stats for this user");
863             }
864             checkCallerIsSystemOrSameApp(pkg);
865 
866             final long token = Binder.clearCallingIdentity();
867             try {
868                 return UsageStatsService.this.queryEventsForPackage(userId, beginTime,
869                         endTime, callingPackage);
870             } finally {
871                 Binder.restoreCallingIdentity(token);
872             }
873         }
874 
875         @Override
isAppInactive(String packageName, int userId)876         public boolean isAppInactive(String packageName, int userId) {
877             try {
878                 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
879                         Binder.getCallingUid(), userId, false, false, "isAppInactive", null);
880             } catch (RemoteException re) {
881                 throw re.rethrowFromSystemServer();
882             }
883             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
884                     Binder.getCallingUid(), userId);
885             final long token = Binder.clearCallingIdentity();
886             try {
887                 return mAppStandby.isAppIdleFilteredOrParoled(
888                         packageName, userId,
889                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
890             } finally {
891                 Binder.restoreCallingIdentity(token);
892             }
893         }
894 
895         @Override
setAppInactive(String packageName, boolean idle, int userId)896         public void setAppInactive(String packageName, boolean idle, int userId) {
897             final int callingUid = Binder.getCallingUid();
898             try {
899                 userId = ActivityManager.getService().handleIncomingUser(
900                         Binder.getCallingPid(), callingUid, userId, false, true,
901                         "setAppInactive", null);
902             } catch (RemoteException re) {
903                 throw re.rethrowFromSystemServer();
904             }
905             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
906                     "No permission to change app idle state");
907             final long token = Binder.clearCallingIdentity();
908             try {
909                 final int appId = mAppStandby.getAppId(packageName);
910                 if (appId < 0) return;
911                 mAppStandby.setAppIdleAsync(packageName, idle, userId);
912             } finally {
913                 Binder.restoreCallingIdentity(token);
914             }
915         }
916 
917         @Override
getAppStandbyBucket(String packageName, String callingPackage, int userId)918         public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
919             final int callingUid = Binder.getCallingUid();
920             try {
921                 userId = ActivityManager.getService().handleIncomingUser(
922                         Binder.getCallingPid(), callingUid, userId, false, false,
923                         "getAppStandbyBucket", null);
924             } catch (RemoteException re) {
925                 throw re.rethrowFromSystemServer();
926             }
927             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
928             // If the calling app is asking about itself, continue, else check for permission.
929             if (packageUid != callingUid) {
930                 if (!hasPermission(callingPackage)) {
931                     throw new SecurityException(
932                             "Don't have permission to query app standby bucket");
933                 }
934             }
935             if (packageUid < 0) {
936                 throw new IllegalArgumentException(
937                         "Cannot get standby bucket for non existent package (" + packageName + ")");
938             }
939             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
940                     userId);
941             final long token = Binder.clearCallingIdentity();
942             try {
943                 return mAppStandby.getAppStandbyBucket(packageName, userId,
944                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
945             } finally {
946                 Binder.restoreCallingIdentity(token);
947             }
948         }
949 
950         @Override
setAppStandbyBucket(String packageName, int bucket, int userId)951         public void setAppStandbyBucket(String packageName,
952                 int bucket, int userId) {
953             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
954                     "No permission to change app standby state");
955 
956             if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
957                     || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
958                 throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
959             }
960             final int callingUid = Binder.getCallingUid();
961             try {
962                 userId = ActivityManager.getService().handleIncomingUser(
963                         Binder.getCallingPid(), callingUid, userId, false, true,
964                         "setAppStandbyBucket", null);
965             } catch (RemoteException re) {
966                 throw re.rethrowFromSystemServer();
967             }
968             final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
969             final boolean systemCaller = UserHandle.isCore(callingUid);
970             final int reason = systemCaller
971                     ? UsageStatsManager.REASON_MAIN_FORCED
972                     : UsageStatsManager.REASON_MAIN_PREDICTED;
973             final long token = Binder.clearCallingIdentity();
974             try {
975                 final int packageUid = mPackageManagerInternal.getPackageUid(packageName,
976                         PackageManager.MATCH_ANY_USER, userId);
977                 // Caller cannot set their own standby state
978                 if (packageUid == callingUid) {
979                     throw new IllegalArgumentException("Cannot set your own standby bucket");
980                 }
981                 if (packageUid < 0) {
982                     throw new IllegalArgumentException(
983                             "Cannot set standby bucket for non existent package (" + packageName
984                                     + ")");
985                 }
986                 mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
987                         SystemClock.elapsedRealtime(), shellCaller);
988             } finally {
989                 Binder.restoreCallingIdentity(token);
990             }
991         }
992 
993         @Override
getAppStandbyBuckets(String callingPackageName, int userId)994         public ParceledListSlice<AppStandbyInfo> getAppStandbyBuckets(String callingPackageName,
995                 int userId) {
996             final int callingUid = Binder.getCallingUid();
997             try {
998                 userId = ActivityManager.getService().handleIncomingUser(
999                         Binder.getCallingPid(), callingUid, userId, false, false,
1000                         "getAppStandbyBucket", null);
1001             } catch (RemoteException re) {
1002                 throw re.rethrowFromSystemServer();
1003             }
1004             if (!hasPermission(callingPackageName)) {
1005                 throw new SecurityException(
1006                         "Don't have permission to query app standby bucket");
1007             }
1008             final long token = Binder.clearCallingIdentity();
1009             try {
1010                 final List<AppStandbyInfo> standbyBucketList =
1011                         mAppStandby.getAppStandbyBuckets(userId);
1012                 return (standbyBucketList == null) ? ParceledListSlice.emptyList()
1013                         : new ParceledListSlice<>(standbyBucketList);
1014             } finally {
1015                 Binder.restoreCallingIdentity(token);
1016             }
1017         }
1018 
1019         @Override
setAppStandbyBuckets(ParceledListSlice appBuckets, int userId)1020         public void setAppStandbyBuckets(ParceledListSlice appBuckets, int userId) {
1021             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1022                     "No permission to change app standby state");
1023 
1024             final int callingUid = Binder.getCallingUid();
1025             try {
1026                 userId = ActivityManager.getService().handleIncomingUser(
1027                         Binder.getCallingPid(), callingUid, userId, false, true,
1028                         "setAppStandbyBucket", null);
1029             } catch (RemoteException re) {
1030                 throw re.rethrowFromSystemServer();
1031             }
1032             final boolean shellCaller = callingUid == 0 || callingUid == Process.SHELL_UID;
1033             final int reason = shellCaller
1034                     ? UsageStatsManager.REASON_MAIN_FORCED
1035                     : UsageStatsManager.REASON_MAIN_PREDICTED;
1036             final long token = Binder.clearCallingIdentity();
1037             try {
1038                 final long elapsedRealtime = SystemClock.elapsedRealtime();
1039                 List<AppStandbyInfo> bucketList = appBuckets.getList();
1040                 for (AppStandbyInfo bucketInfo : bucketList) {
1041                     final String packageName = bucketInfo.mPackageName;
1042                     final int bucket = bucketInfo.mStandbyBucket;
1043                     if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
1044                             || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
1045                         throw new IllegalArgumentException(
1046                                 "Cannot set the standby bucket to " + bucket);
1047                     }
1048                     // Caller cannot set their own standby state
1049                     if (mPackageManagerInternal.getPackageUid(packageName,
1050                             PackageManager.MATCH_ANY_USER, userId) == callingUid) {
1051                         throw new IllegalArgumentException("Cannot set your own standby bucket");
1052                     }
1053                     mAppStandby.setAppStandbyBucket(packageName, userId, bucket, reason,
1054                             elapsedRealtime, shellCaller);
1055                 }
1056             } finally {
1057                 Binder.restoreCallingIdentity(token);
1058             }
1059         }
1060 
1061         @Override
whitelistAppTemporarily(String packageName, long duration, int userId)1062         public void whitelistAppTemporarily(String packageName, long duration, int userId)
1063                 throws RemoteException {
1064             StringBuilder reason = new StringBuilder(32);
1065             reason.append("from:");
1066             UserHandle.formatUid(reason, Binder.getCallingUid());
1067             mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
1068                     reason.toString());
1069         }
1070 
1071         @Override
onCarrierPrivilegedAppsChanged()1072         public void onCarrierPrivilegedAppsChanged() {
1073             if (DEBUG) {
1074                 Slog.i(TAG, "Carrier privileged apps changed");
1075             }
1076             getContext().enforceCallingOrSelfPermission(
1077                     android.Manifest.permission.BIND_CARRIER_SERVICES,
1078                     "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
1079             mAppStandby.clearCarrierPrivilegedApps();
1080         }
1081 
1082         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1083         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1084             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
1085             UsageStatsService.this.dump(args, pw);
1086         }
1087 
1088         @Override
reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1089         public void reportChooserSelection(String packageName, int userId, String contentType,
1090                                            String[] annotations, String action) {
1091             if (packageName == null) {
1092                 Slog.w(TAG, "Event report user selecting a null package");
1093                 return;
1094             }
1095 
1096             UsageEvents.Event event = new UsageEvents.Event();
1097             event.mPackage = packageName;
1098 
1099             // This will later be converted to system time.
1100             event.mTimeStamp = SystemClock.elapsedRealtime();
1101 
1102             event.mEventType = Event.CHOOSER_ACTION;
1103 
1104             event.mAction = action;
1105 
1106             event.mContentType = contentType;
1107 
1108             event.mContentAnnotations = annotations;
1109 
1110             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1111         }
1112 
1113         @Override
registerAppUsageObserver(int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, String callingPackage)1114         public void registerAppUsageObserver(int observerId,
1115                 String[] packages, long timeLimitMs, PendingIntent
1116                 callbackIntent, String callingPackage) {
1117             if (!hasObserverPermission(callingPackage)) {
1118                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1119             }
1120 
1121             if (packages == null || packages.length == 0) {
1122                 throw new IllegalArgumentException("Must specify at least one package");
1123             }
1124             if (callbackIntent == null) {
1125                 throw new NullPointerException("callbackIntent can't be null");
1126             }
1127             final int callingUid = Binder.getCallingUid();
1128             final int userId = UserHandle.getUserId(callingUid);
1129             final long token = Binder.clearCallingIdentity();
1130             try {
1131                 UsageStatsService.this.registerAppUsageObserver(callingUid, observerId,
1132                         packages, timeLimitMs, callbackIntent, userId);
1133             } finally {
1134                 Binder.restoreCallingIdentity(token);
1135             }
1136         }
1137 
1138         @Override
unregisterAppUsageObserver(int observerId, String callingPackage)1139         public void unregisterAppUsageObserver(int observerId, String callingPackage) {
1140             if (!hasObserverPermission(callingPackage)) {
1141                 throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
1142             }
1143 
1144             final int callingUid = Binder.getCallingUid();
1145             final int userId = UserHandle.getUserId(callingUid);
1146             final long token = Binder.clearCallingIdentity();
1147             try {
1148                 UsageStatsService.this.unregisterAppUsageObserver(callingUid, observerId, userId);
1149             } finally {
1150                 Binder.restoreCallingIdentity(token);
1151             }
1152         }
1153     }
1154 
registerAppUsageObserver(int callingUid, int observerId, String[] packages, long timeLimitMs, PendingIntent callbackIntent, int userId)1155     void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
1156             long timeLimitMs, PendingIntent callbackIntent, int userId) {
1157         mAppTimeLimit.addObserver(callingUid, observerId, packages, timeLimitMs, callbackIntent,
1158                 userId);
1159     }
1160 
unregisterAppUsageObserver(int callingUid, int observerId, int userId)1161     void unregisterAppUsageObserver(int callingUid, int observerId, int userId) {
1162         mAppTimeLimit.removeObserver(callingUid, observerId, userId);
1163     }
1164 
1165     /**
1166      * This local service implementation is primarily used by ActivityManagerService.
1167      * ActivityManagerService will call these methods holding the 'am' lock, which means we
1168      * shouldn't be doing any IO work or other long running tasks in these methods.
1169      */
1170     private final class LocalService extends UsageStatsManagerInternal {
1171 
1172         @Override
reportEvent(ComponentName component, int userId, int eventType)1173         public void reportEvent(ComponentName component, int userId, int eventType) {
1174             if (component == null) {
1175                 Slog.w(TAG, "Event reported without a component name");
1176                 return;
1177             }
1178 
1179             UsageEvents.Event event = new UsageEvents.Event();
1180             event.mPackage = component.getPackageName();
1181             event.mClass = component.getClassName();
1182 
1183             // This will later be converted to system time.
1184             event.mTimeStamp = SystemClock.elapsedRealtime();
1185 
1186             event.mEventType = eventType;
1187             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1188         }
1189 
1190         @Override
reportEvent(String packageName, int userId, int eventType)1191         public void reportEvent(String packageName, int userId, int eventType) {
1192             if (packageName == null) {
1193                 Slog.w(TAG, "Event reported without a package name");
1194                 return;
1195             }
1196 
1197             UsageEvents.Event event = new UsageEvents.Event();
1198             event.mPackage = packageName;
1199 
1200             // This will later be converted to system time.
1201             event.mTimeStamp = SystemClock.elapsedRealtime();
1202 
1203             event.mEventType = eventType;
1204             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1205         }
1206 
1207         @Override
reportConfigurationChange(Configuration config, int userId)1208         public void reportConfigurationChange(Configuration config, int userId) {
1209             if (config == null) {
1210                 Slog.w(TAG, "Configuration event reported with a null config");
1211                 return;
1212             }
1213 
1214             UsageEvents.Event event = new UsageEvents.Event();
1215             event.mPackage = "android";
1216 
1217             // This will later be converted to system time.
1218             event.mTimeStamp = SystemClock.elapsedRealtime();
1219 
1220             event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
1221             event.mConfiguration = new Configuration(config);
1222             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1223         }
1224 
1225         @Override
reportInterruptiveNotification(String packageName, String channelId, int userId)1226         public void reportInterruptiveNotification(String packageName, String channelId,
1227                 int userId) {
1228             if (packageName == null || channelId == null) {
1229                 Slog.w(TAG, "Event reported without a package name or a channel ID");
1230                 return;
1231             }
1232 
1233             UsageEvents.Event event = new UsageEvents.Event();
1234             event.mPackage = packageName.intern();
1235             event.mNotificationChannelId = channelId.intern();
1236 
1237             // This will later be converted to system time.
1238             event.mTimeStamp = SystemClock.elapsedRealtime();
1239 
1240             event.mEventType = Event.NOTIFICATION_INTERRUPTION;
1241             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1242         }
1243 
1244         @Override
reportShortcutUsage(String packageName, String shortcutId, int userId)1245         public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
1246             if (packageName == null || shortcutId == null) {
1247                 Slog.w(TAG, "Event reported without a package name or a shortcut ID");
1248                 return;
1249             }
1250 
1251             UsageEvents.Event event = new UsageEvents.Event();
1252             event.mPackage = packageName.intern();
1253             event.mShortcutId = shortcutId.intern();
1254 
1255             // This will later be converted to system time.
1256             event.mTimeStamp = SystemClock.elapsedRealtime();
1257 
1258             event.mEventType = Event.SHORTCUT_INVOCATION;
1259             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1260         }
1261 
1262         @Override
reportContentProviderUsage(String name, String packageName, int userId)1263         public void reportContentProviderUsage(String name, String packageName, int userId) {
1264             mAppStandby.postReportContentProviderUsage(name, packageName, userId);
1265         }
1266 
1267         @Override
isAppIdle(String packageName, int uidForAppId, int userId)1268         public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
1269             return mAppStandby.isAppIdleFiltered(packageName, uidForAppId,
1270                     userId, SystemClock.elapsedRealtime());
1271         }
1272 
1273         @Override
getAppStandbyBucket(String packageName, int userId, long nowElapsed)1274         @StandbyBuckets public int getAppStandbyBucket(String packageName, int userId,
1275                 long nowElapsed) {
1276             return mAppStandby.getAppStandbyBucket(packageName, userId, nowElapsed, false);
1277         }
1278 
1279         @Override
getIdleUidsForUser(int userId)1280         public int[] getIdleUidsForUser(int userId) {
1281             return mAppStandby.getIdleUidsForUser(userId);
1282         }
1283 
1284         @Override
isAppIdleParoleOn()1285         public boolean isAppIdleParoleOn() {
1286             return mAppStandby.isParoledOrCharging();
1287         }
1288 
1289         @Override
prepareShutdown()1290         public void prepareShutdown() {
1291             // This method *WILL* do IO work, but we must block until it is finished or else
1292             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1293             // we are shutting down.
1294             shutdown();
1295         }
1296 
1297         @Override
addAppIdleStateChangeListener(AppIdleStateChangeListener listener)1298         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1299             mAppStandby.addListener(listener);
1300             listener.onParoleStateChanged(isAppIdleParoleOn());
1301         }
1302 
1303         @Override
removeAppIdleStateChangeListener( AppIdleStateChangeListener listener)1304         public void removeAppIdleStateChangeListener(
1305                 AppIdleStateChangeListener listener) {
1306             mAppStandby.removeListener(listener);
1307         }
1308 
1309         @Override
getBackupPayload(int user, String key)1310         public byte[] getBackupPayload(int user, String key) {
1311             // Check to ensure that only user 0's data is b/r for now
1312             synchronized (mLock) {
1313                 if (user == UserHandle.USER_SYSTEM) {
1314                     final UserUsageStatsService userStats =
1315                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1316                     return userStats.getBackupPayload(key);
1317                 } else {
1318                     return null;
1319                 }
1320             }
1321         }
1322 
1323         @Override
applyRestoredPayload(int user, String key, byte[] payload)1324         public void applyRestoredPayload(int user, String key, byte[] payload) {
1325             synchronized (mLock) {
1326                 if (user == UserHandle.USER_SYSTEM) {
1327                     final UserUsageStatsService userStats =
1328                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1329                     userStats.applyRestoredPayload(key, payload);
1330                 }
1331             }
1332         }
1333 
1334         @Override
queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)1335         public List<UsageStats> queryUsageStatsForUser(
1336                 int userId, int intervalType, long beginTime, long endTime,
1337                 boolean obfuscateInstantApps) {
1338             return UsageStatsService.this.queryUsageStats(
1339                     userId, intervalType, beginTime, endTime, obfuscateInstantApps);
1340         }
1341 
1342         @Override
setLastJobRunTime(String packageName, int userId, long elapsedRealtime)1343         public void setLastJobRunTime(String packageName, int userId, long elapsedRealtime) {
1344             mAppStandby.setLastJobRunTime(packageName, userId, elapsedRealtime);
1345         }
1346 
1347         @Override
getTimeSinceLastJobRun(String packageName, int userId)1348         public long getTimeSinceLastJobRun(String packageName, int userId) {
1349             return mAppStandby.getTimeSinceLastJobRun(packageName, userId);
1350         }
1351 
1352         @Override
reportAppJobState(String packageName, int userId, int numDeferredJobs, long timeSinceLastJobRun)1353         public void reportAppJobState(String packageName, int userId,
1354                 int numDeferredJobs, long timeSinceLastJobRun) {
1355         }
1356 
1357         @Override
onActiveAdminAdded(String packageName, int userId)1358         public void onActiveAdminAdded(String packageName, int userId) {
1359             mAppStandby.addActiveDeviceAdmin(packageName, userId);
1360         }
1361 
1362         @Override
setActiveAdminApps(Set<String> packageNames, int userId)1363         public void setActiveAdminApps(Set<String> packageNames, int userId) {
1364             mAppStandby.setActiveAdminApps(packageNames, userId);
1365         }
1366 
1367         @Override
onAdminDataAvailable()1368         public void onAdminDataAvailable() {
1369             mAppStandby.onAdminDataAvailable();
1370         }
1371 
1372         @Override
reportExemptedSyncScheduled(String packageName, int userId)1373         public void reportExemptedSyncScheduled(String packageName, int userId) {
1374             mAppStandby.postReportExemptedSyncScheduled(packageName, userId);
1375         }
1376 
1377         @Override
reportExemptedSyncStart(String packageName, int userId)1378         public void reportExemptedSyncStart(String packageName, int userId) {
1379             mAppStandby.postReportExemptedSyncStart(packageName, userId);
1380         }
1381     }
1382 }
1383