OSDN Git Service

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