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.AppGlobals;
22 import android.app.AppOpsManager;
23 import android.app.IUidObserver;
24 import android.app.admin.DevicePolicyManager;
25 import android.app.usage.ConfigurationStats;
26 import android.app.usage.IUsageStatsManager;
27 import android.app.usage.UsageEvents;
28 import android.app.usage.UsageEvents.Event;
29 import android.app.usage.UsageStats;
30 import android.app.usage.UsageStatsManagerInternal;
31 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
32 import android.appwidget.AppWidgetManager;
33 import android.content.BroadcastReceiver;
34 import android.content.ComponentName;
35 import android.content.ContentResolver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.IntentFilter;
39 import android.content.pm.ApplicationInfo;
40 import android.content.pm.PackageInfo;
41 import android.content.pm.PackageManager;
42 import android.content.pm.PackageManagerInternal;
43 import android.content.pm.PackageManager.NameNotFoundException;
44 import android.content.pm.ParceledListSlice;
45 import android.content.pm.UserInfo;
46 import android.content.res.Configuration;
47 import android.database.ContentObserver;
48 import android.hardware.display.DisplayManager;
49 import android.net.NetworkScoreManager;
50 import android.os.BatteryManager;
51 import android.os.BatteryStats;
52 import android.os.Binder;
53 import android.os.Environment;
54 import android.os.FileUtils;
55 import android.os.Handler;
56 import android.os.IDeviceIdleController;
57 import android.os.Looper;
58 import android.os.Message;
59 import android.os.PowerManager;
60 import android.os.Process;
61 import android.os.RemoteException;
62 import android.os.ServiceManager;
63 import android.os.SystemClock;
64 import android.os.SystemProperties;
65 import android.os.UserHandle;
66 import android.os.UserManager;
67 import android.provider.Settings;
68 import android.telephony.TelephonyManager;
69 import android.util.ArraySet;
70 import android.util.KeyValueListParser;
71 import android.util.Slog;
72 import android.util.SparseArray;
73 import android.util.SparseIntArray;
74 import android.util.TimeUtils;
75 import android.view.Display;
76 
77 import com.android.internal.annotations.GuardedBy;
78 import com.android.internal.app.IBatteryStats;
79 import com.android.internal.os.BackgroundThread;
80 import com.android.internal.os.SomeArgs;
81 import com.android.internal.util.ArrayUtils;
82 import com.android.internal.util.DumpUtils;
83 import com.android.internal.util.IndentingPrintWriter;
84 import com.android.server.LocalServices;
85 import com.android.server.SystemService;
86 
87 import java.io.File;
88 import java.io.FileDescriptor;
89 import java.io.IOException;
90 import java.io.PrintWriter;
91 import java.util.ArrayList;
92 import java.util.Arrays;
93 import java.util.List;
94 
95 /**
96  * A service that collects, aggregates, and persists application usage data.
97  * This data can be queried by apps that have been granted permission by AppOps.
98  */
99 public class UsageStatsService extends SystemService implements
100         UserUsageStatsService.StatsUpdatedListener {
101 
102     static final String TAG = "UsageStatsService";
103     public static final boolean ENABLE_TIME_CHANGE_CORRECTION
104             = SystemProperties.getBoolean("persist.debug.time_correction", true);
105 
106     static final boolean DEBUG = false; // Never submit with true
107     static final boolean COMPRESS_TIME = false;
108 
109     private static final long TEN_SECONDS = 10 * 1000;
110     private static final long ONE_MINUTE = 60 * 1000;
111     private static final long TWENTY_MINUTES = 20 * 60 * 1000;
112     private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
113     private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
114 
115     private static final boolean ENABLE_KERNEL_UPDATES = true;
116     private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set");
117 
118     long mAppIdleScreenThresholdMillis;
119     long mCheckIdleIntervalMillis;
120     long mAppIdleWallclockThresholdMillis;
121     long mAppIdleParoleIntervalMillis;
122     long mAppIdleParoleDurationMillis;
123 
124     // Handler message types.
125     static final int MSG_REPORT_EVENT = 0;
126     static final int MSG_FLUSH_TO_DISK = 1;
127     static final int MSG_REMOVE_USER = 2;
128     static final int MSG_INFORM_LISTENERS = 3;
129     static final int MSG_FORCE_IDLE_STATE = 4;
130     static final int MSG_CHECK_IDLE_STATES = 5;
131     static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
132     static final int MSG_PAROLE_END_TIMEOUT = 7;
133     static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
134     static final int MSG_PAROLE_STATE_CHANGED = 9;
135     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
136 
137     private final Object mLock = new Object();
138     Handler mHandler;
139     AppOpsManager mAppOps;
140     UserManager mUserManager;
141     PackageManager mPackageManager;
142     PackageManagerInternal mPackageManagerInternal;
143     AppWidgetManager mAppWidgetManager;
144     IDeviceIdleController mDeviceIdleController;
145     private DisplayManager mDisplayManager;
146     private PowerManager mPowerManager;
147     private IBatteryStats mBatteryStats;
148 
149     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
150     private final SparseIntArray mUidToKernelCounter = new SparseIntArray();
151     private File mUsageStatsDir;
152     long mRealTimeSnapshot;
153     long mSystemTimeSnapshot;
154 
155     boolean mAppIdleEnabled;
156     boolean mAppIdleTempParoled;
157     boolean mCharging;
158     private long mLastAppIdleParoledTime;
159 
160     private volatile boolean mPendingOneTimeCheckIdleStates;
161     private boolean mSystemServicesReady = false;
162 
163     private final Object mAppIdleLock = new Object();
164     @GuardedBy("mAppIdleLock")
165     private AppIdleHistory mAppIdleHistory;
166 
167     @GuardedBy("mAppIdleLock")
168     private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
169             mPackageAccessListeners = new ArrayList<>();
170 
171     @GuardedBy("mAppIdleLock")
172     private boolean mHaveCarrierPrivilegedApps;
173     @GuardedBy("mAppIdleLock")
174     private List<String> mCarrierPrivilegedApps;
175 
UsageStatsService(Context context)176     public UsageStatsService(Context context) {
177         super(context);
178     }
179 
180     @Override
onStart()181     public void onStart() {
182         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
183         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
184         mPackageManager = getContext().getPackageManager();
185         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
186         mHandler = new H(BackgroundThread.get().getLooper());
187 
188         File systemDataDir = new File(Environment.getDataDirectory(), "system");
189         mUsageStatsDir = new File(systemDataDir, "usagestats");
190         mUsageStatsDir.mkdirs();
191         if (!mUsageStatsDir.exists()) {
192             throw new IllegalStateException("Usage stats directory does not exist: "
193                     + mUsageStatsDir.getAbsolutePath());
194         }
195 
196         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_REMOVED);
197         filter.addAction(Intent.ACTION_USER_STARTED);
198         getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, filter,
199                 null, mHandler);
200 
201         IntentFilter packageFilter = new IntentFilter();
202         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
203         packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
204         packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
205         packageFilter.addDataScheme("package");
206 
207         getContext().registerReceiverAsUser(new PackageReceiver(), UserHandle.ALL, packageFilter,
208                 null, mHandler);
209 
210         mAppIdleEnabled = getContext().getResources().getBoolean(
211                 com.android.internal.R.bool.config_enableAutoPowerModes);
212         if (mAppIdleEnabled) {
213             IntentFilter deviceStates = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
214             deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
215             deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
216             getContext().registerReceiver(new DeviceStateReceiver(), deviceStates);
217         }
218 
219         synchronized (mLock) {
220             cleanUpRemovedUsersLocked();
221         }
222         synchronized (mAppIdleLock) {
223             mAppIdleHistory = new AppIdleHistory(SystemClock.elapsedRealtime());
224         }
225 
226         mRealTimeSnapshot = SystemClock.elapsedRealtime();
227         mSystemTimeSnapshot = System.currentTimeMillis();
228 
229         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
230         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
231     }
232 
233     @Override
onBootPhase(int phase)234     public void onBootPhase(int phase) {
235         if (phase == PHASE_SYSTEM_SERVICES_READY) {
236             // Observe changes to the threshold
237             SettingsObserver settingsObserver = new SettingsObserver(mHandler);
238             settingsObserver.registerObserver();
239             settingsObserver.updateSettings();
240 
241             mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
242             mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
243                     ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
244             mBatteryStats = IBatteryStats.Stub.asInterface(
245                     ServiceManager.getService(BatteryStats.SERVICE_NAME));
246             mDisplayManager = (DisplayManager) getContext().getSystemService(
247                     Context.DISPLAY_SERVICE);
248             mPowerManager = getContext().getSystemService(PowerManager.class);
249 
250             mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
251             synchronized (mAppIdleLock) {
252                 mAppIdleHistory.updateDisplay(isDisplayOn(), SystemClock.elapsedRealtime());
253             }
254 
255             if (mPendingOneTimeCheckIdleStates) {
256                 postOneTimeCheckIdleStates();
257             }
258 
259             if (ENABLE_KERNEL_UPDATES && KERNEL_COUNTER_FILE.exists()) {
260                 try {
261                     ActivityManager.getService().registerUidObserver(mUidObserver,
262                             ActivityManager.UID_OBSERVER_PROCSTATE
263                                     | ActivityManager.UID_OBSERVER_GONE,
264                             ActivityManager.PROCESS_STATE_UNKNOWN, null);
265                 } catch (RemoteException e) {
266                     throw new RuntimeException(e);
267                 }
268             } else {
269                 Slog.w(TAG, "Missing procfs interface: " + KERNEL_COUNTER_FILE);
270             }
271 
272             mSystemServicesReady = true;
273         } else if (phase == PHASE_BOOT_COMPLETED) {
274             setChargingState(getContext().getSystemService(BatteryManager.class).isCharging());
275         }
276     }
277 
isDisplayOn()278     private boolean isDisplayOn() {
279         return mDisplayManager
280                 .getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON;
281     }
282 
283     private class UserActionsReceiver extends BroadcastReceiver {
284         @Override
onReceive(Context context, Intent intent)285         public void onReceive(Context context, Intent intent) {
286             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
287             final String action = intent.getAction();
288             if (Intent.ACTION_USER_REMOVED.equals(action)) {
289                 if (userId >= 0) {
290                     mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
291                 }
292             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
293                 if (userId >=0) {
294                     postCheckIdleStates(userId);
295                 }
296             }
297         }
298     }
299 
300     private class PackageReceiver extends BroadcastReceiver {
301         @Override
onReceive(Context context, Intent intent)302         public void onReceive(Context context, Intent intent) {
303             final String action = intent.getAction();
304             if (Intent.ACTION_PACKAGE_ADDED.equals(action)
305                     || Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
306                 clearCarrierPrivilegedApps();
307             }
308             if ((Intent.ACTION_PACKAGE_REMOVED.equals(action) ||
309                     Intent.ACTION_PACKAGE_ADDED.equals(action))
310                     && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
311                 clearAppIdleForPackage(intent.getData().getSchemeSpecificPart(),
312                         getSendingUserId());
313             }
314         }
315     }
316 
317     private class DeviceStateReceiver extends BroadcastReceiver {
318         @Override
onReceive(Context context, Intent intent)319         public void onReceive(Context context, Intent intent) {
320             final String action = intent.getAction();
321             if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
322                 setChargingState(intent.getIntExtra("plugged", 0) != 0);
323             } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
324                 onDeviceIdleModeChanged();
325             }
326         }
327     }
328 
329     private final DisplayManager.DisplayListener mDisplayListener
330             = new DisplayManager.DisplayListener() {
331 
332         @Override public void onDisplayAdded(int displayId) {
333         }
334 
335         @Override public void onDisplayRemoved(int displayId) {
336         }
337 
338         @Override public void onDisplayChanged(int displayId) {
339             if (displayId == Display.DEFAULT_DISPLAY) {
340                 final boolean displayOn = isDisplayOn();
341                 synchronized (UsageStatsService.this.mAppIdleLock) {
342                     mAppIdleHistory.updateDisplay(displayOn, SystemClock.elapsedRealtime());
343                 }
344             }
345         }
346     };
347 
348     private final IUidObserver mUidObserver = new IUidObserver.Stub() {
349         @Override
350         public void onUidStateChanged(int uid, int procState, long procStateSeq) {
351             final int newCounter = (procState <= ActivityManager.PROCESS_STATE_TOP) ? 0 : 1;
352             synchronized (mUidToKernelCounter) {
353                 final int oldCounter = mUidToKernelCounter.get(uid, 0);
354                 if (newCounter != oldCounter) {
355                     mUidToKernelCounter.put(uid, newCounter);
356                     try {
357                         FileUtils.stringToFile(KERNEL_COUNTER_FILE, uid + " " + newCounter);
358                     } catch (IOException e) {
359                         Slog.w(TAG, "Failed to update counter set: " + e);
360                     }
361                 }
362             }
363         }
364 
365         @Override
366         public void onUidIdle(int uid, boolean disabled) throws RemoteException {
367             // Ignored
368         }
369 
370         @Override
371         public void onUidGone(int uid, boolean disabled) throws RemoteException {
372             onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
373         }
374 
375         @Override
376         public void onUidActive(int uid) throws RemoteException {
377             // Ignored
378         }
379     };
380 
381     @Override
onStatsUpdated()382     public void onStatsUpdated() {
383         mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
384     }
385 
386     @Override
onStatsReloaded()387     public void onStatsReloaded() {
388         postOneTimeCheckIdleStates();
389     }
390 
391     @Override
onNewUpdate(int userId)392     public void onNewUpdate(int userId) {
393         initializeDefaultsForSystemApps(userId);
394     }
395 
initializeDefaultsForSystemApps(int userId)396     private void initializeDefaultsForSystemApps(int userId) {
397         Slog.d(TAG, "Initializing defaults for system apps on user " + userId);
398         final long elapsedRealtime = SystemClock.elapsedRealtime();
399         List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
400                 PackageManager.MATCH_DISABLED_COMPONENTS,
401                 userId);
402         final int packageCount = packages.size();
403         synchronized (mAppIdleLock) {
404             for (int i = 0; i < packageCount; i++) {
405                 final PackageInfo pi = packages.get(i);
406                 String packageName = pi.packageName;
407                 if (pi.applicationInfo != null && pi.applicationInfo.isSystemApp()) {
408                     mAppIdleHistory.reportUsage(packageName, userId, elapsedRealtime);
409                 }
410             }
411         }
412     }
413 
shouldObfuscateInstantAppsForCaller(int callingUid, int userId)414     private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
415         return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
416     }
417 
clearAppIdleForPackage(String packageName, int userId)418     void clearAppIdleForPackage(String packageName, int userId) {
419         synchronized (mAppIdleLock) {
420             mAppIdleHistory.clearUsage(packageName, userId);
421         }
422     }
423 
cleanUpRemovedUsersLocked()424     private void cleanUpRemovedUsersLocked() {
425         final List<UserInfo> users = mUserManager.getUsers(true);
426         if (users == null || users.size() == 0) {
427             throw new IllegalStateException("There can't be no users");
428         }
429 
430         ArraySet<String> toDelete = new ArraySet<>();
431         String[] fileNames = mUsageStatsDir.list();
432         if (fileNames == null) {
433             // No users to delete.
434             return;
435         }
436 
437         toDelete.addAll(Arrays.asList(fileNames));
438 
439         final int userCount = users.size();
440         for (int i = 0; i < userCount; i++) {
441             final UserInfo userInfo = users.get(i);
442             toDelete.remove(Integer.toString(userInfo.id));
443         }
444 
445         final int deleteCount = toDelete.size();
446         for (int i = 0; i < deleteCount; i++) {
447             deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
448         }
449     }
450 
setChargingState(boolean charging)451     void setChargingState(boolean charging) {
452         synchronized (mAppIdleLock) {
453             if (mCharging != charging) {
454                 mCharging = charging;
455                 postParoleStateChanged();
456             }
457         }
458     }
459 
460     /** Paroled here means temporary pardon from being inactive */
setAppIdleParoled(boolean paroled)461     void setAppIdleParoled(boolean paroled) {
462         synchronized (mAppIdleLock) {
463             final long now = System.currentTimeMillis();
464             if (mAppIdleTempParoled != paroled) {
465                 mAppIdleTempParoled = paroled;
466                 if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
467                 if (paroled) {
468                     postParoleEndTimeout();
469                 } else {
470                     mLastAppIdleParoledTime = now;
471                     postNextParoleTimeout(now);
472                 }
473                 postParoleStateChanged();
474             }
475         }
476     }
477 
isParoledOrCharging()478     boolean isParoledOrCharging() {
479         synchronized (mAppIdleLock) {
480             return mAppIdleTempParoled || mCharging;
481         }
482     }
483 
postNextParoleTimeout(long now)484     private void postNextParoleTimeout(long now) {
485         if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
486         mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
487         // Compute when the next parole needs to happen. We check more frequently than necessary
488         // since the message handler delays are based on elapsedRealTime and not wallclock time.
489         // The comparison is done in wallclock time.
490         long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis) - now;
491         if (timeLeft < 0) {
492             timeLeft = 0;
493         }
494         mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft);
495     }
496 
postParoleEndTimeout()497     private void postParoleEndTimeout() {
498         if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT");
499         mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT);
500         mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
501     }
502 
postParoleStateChanged()503     private void postParoleStateChanged() {
504         if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
505         mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
506         mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
507     }
508 
postCheckIdleStates(int userId)509     void postCheckIdleStates(int userId) {
510         mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
511     }
512 
513     /**
514      * We send a different message to check idle states once, otherwise we would end up
515      * scheduling a series of repeating checkIdleStates each time we fired off one.
516      */
postOneTimeCheckIdleStates()517     void postOneTimeCheckIdleStates() {
518         if (mDeviceIdleController == null) {
519             // Not booted yet; wait for it!
520             mPendingOneTimeCheckIdleStates = true;
521         } else {
522             mHandler.sendEmptyMessage(MSG_ONE_TIME_CHECK_IDLE_STATES);
523             mPendingOneTimeCheckIdleStates = false;
524         }
525     }
526 
527     /**
528      * Check all running users' or specified user's apps to see if they enter an idle state.
529      * @return Returns whether checking should continue periodically.
530      */
checkIdleStates(int checkUserId)531     boolean checkIdleStates(int checkUserId) {
532         if (!mAppIdleEnabled) {
533             return false;
534         }
535 
536         final int[] runningUserIds;
537         try {
538             runningUserIds = ActivityManager.getService().getRunningUserIds();
539             if (checkUserId != UserHandle.USER_ALL
540                     && !ArrayUtils.contains(runningUserIds, checkUserId)) {
541                 return false;
542             }
543         } catch (RemoteException re) {
544             throw re.rethrowFromSystemServer();
545         }
546 
547         final long elapsedRealtime = SystemClock.elapsedRealtime();
548         for (int i = 0; i < runningUserIds.length; i++) {
549             final int userId = runningUserIds[i];
550             if (checkUserId != UserHandle.USER_ALL && checkUserId != userId) {
551                 continue;
552             }
553             if (DEBUG) {
554                 Slog.d(TAG, "Checking idle state for user " + userId);
555             }
556             List<PackageInfo> packages = mPackageManager.getInstalledPackagesAsUser(
557                     PackageManager.MATCH_DISABLED_COMPONENTS,
558                     userId);
559             final int packageCount = packages.size();
560             for (int p = 0; p < packageCount; p++) {
561                 final PackageInfo pi = packages.get(p);
562                 final String packageName = pi.packageName;
563                 final boolean isIdle = isAppIdleFiltered(packageName,
564                         UserHandle.getAppId(pi.applicationInfo.uid),
565                         userId, elapsedRealtime);
566                 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
567                         userId, isIdle ? 1 : 0, packageName));
568                 if (isIdle) {
569                     synchronized (mAppIdleLock) {
570                         mAppIdleHistory.setIdle(packageName, userId, elapsedRealtime);
571                     }
572                 }
573             }
574         }
575         if (DEBUG) {
576             Slog.d(TAG, "checkIdleStates took "
577                     + (SystemClock.elapsedRealtime() - elapsedRealtime));
578         }
579         return true;
580     }
581 
582     /** Check if it's been a while since last parole and let idle apps do some work */
checkParoleTimeout()583     void checkParoleTimeout() {
584         boolean setParoled = false;
585         synchronized (mAppIdleLock) {
586             final long now = System.currentTimeMillis();
587             if (!mAppIdleTempParoled) {
588                 final long timeSinceLastParole = now - mLastAppIdleParoledTime;
589                 if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
590                     if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
591                     setParoled = true;
592                 } else {
593                     if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
594                     postNextParoleTimeout(now);
595                 }
596             }
597         }
598         if (setParoled) {
599             setAppIdleParoled(true);
600         }
601     }
602 
notifyBatteryStats(String packageName, int userId, boolean idle)603     private void notifyBatteryStats(String packageName, int userId, boolean idle) {
604         try {
605             final int uid = mPackageManager.getPackageUidAsUser(packageName,
606                     PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
607             if (idle) {
608                 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE,
609                         packageName, uid);
610             } else {
611                 mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE,
612                         packageName, uid);
613             }
614         } catch (NameNotFoundException | RemoteException e) {
615         }
616     }
617 
onDeviceIdleModeChanged()618     void onDeviceIdleModeChanged() {
619         final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
620         if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
621         boolean paroled = false;
622         synchronized (mAppIdleLock) {
623             final long timeSinceLastParole = System.currentTimeMillis() - mLastAppIdleParoledTime;
624             if (!deviceIdle
625                     && timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
626                 if (DEBUG) {
627                     Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
628                 }
629                 paroled = true;
630             } else if (deviceIdle) {
631                 if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
632                 paroled = false;
633             } else {
634                 return;
635             }
636         }
637         setAppIdleParoled(paroled);
638     }
639 
deleteRecursively(File f)640     private static void deleteRecursively(File f) {
641         File[] files = f.listFiles();
642         if (files != null) {
643             for (File subFile : files) {
644                 deleteRecursively(subFile);
645             }
646         }
647 
648         if (!f.delete()) {
649             Slog.e(TAG, "Failed to delete " + f);
650         }
651     }
652 
getUserDataAndInitializeIfNeededLocked(int userId, long currentTimeMillis)653     private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
654             long currentTimeMillis) {
655         UserUsageStatsService service = mUserState.get(userId);
656         if (service == null) {
657             service = new UserUsageStatsService(getContext(), userId,
658                     new File(mUsageStatsDir, Integer.toString(userId)), this);
659             service.init(currentTimeMillis);
660             mUserState.put(userId, service);
661         }
662         return service;
663     }
664 
665     /**
666      * This should be the only way to get the time from the system.
667      */
checkAndGetTimeLocked()668     private long checkAndGetTimeLocked() {
669         final long actualSystemTime = System.currentTimeMillis();
670         final long actualRealtime = SystemClock.elapsedRealtime();
671         final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
672         final long diffSystemTime = actualSystemTime - expectedSystemTime;
673         if (Math.abs(diffSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS
674                 && ENABLE_TIME_CHANGE_CORRECTION) {
675             // The time has changed.
676             Slog.i(TAG, "Time changed in UsageStats by " + (diffSystemTime / 1000) + " seconds");
677             final int userCount = mUserState.size();
678             for (int i = 0; i < userCount; i++) {
679                 final UserUsageStatsService service = mUserState.valueAt(i);
680                 service.onTimeChanged(expectedSystemTime, actualSystemTime);
681             }
682             mRealTimeSnapshot = actualRealtime;
683             mSystemTimeSnapshot = actualSystemTime;
684         }
685         return actualSystemTime;
686     }
687 
688     /**
689      * Assuming the event's timestamp is measured in milliseconds since boot,
690      * convert it to a system wall time.
691      */
convertToSystemTimeLocked(UsageEvents.Event event)692     private void convertToSystemTimeLocked(UsageEvents.Event event) {
693         event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
694     }
695 
696     /**
697      * Called by the Binder stub
698      */
shutdown()699     void shutdown() {
700         synchronized (mLock) {
701             mHandler.removeMessages(MSG_REPORT_EVENT);
702             flushToDiskLocked();
703         }
704     }
705 
706     /**
707      * Called by the Binder stub.
708      */
reportEvent(UsageEvents.Event event, int userId)709     void reportEvent(UsageEvents.Event event, int userId) {
710         synchronized (mLock) {
711             final long timeNow = checkAndGetTimeLocked();
712             final long elapsedRealtime = SystemClock.elapsedRealtime();
713             convertToSystemTimeLocked(event);
714 
715             if (event.getPackageName() != null
716                     && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
717                 event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
718             }
719 
720             final UserUsageStatsService service =
721                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
722             service.reportEvent(event);
723 
724             synchronized (mAppIdleLock) {
725                 // TODO: Ideally this should call isAppIdleFiltered() to avoid calling back
726                 // about apps that are on some kind of whitelist anyway.
727                 final boolean previouslyIdle = mAppIdleHistory.isIdle(
728                         event.mPackage, userId, elapsedRealtime);
729                 // Inform listeners if necessary
730                 if ((event.mEventType == Event.MOVE_TO_FOREGROUND
731                         || event.mEventType == Event.MOVE_TO_BACKGROUND
732                         || event.mEventType == Event.SYSTEM_INTERACTION
733                         || event.mEventType == Event.USER_INTERACTION)) {
734                     mAppIdleHistory.reportUsage(event.mPackage, userId, elapsedRealtime);
735                     if (previouslyIdle) {
736                         mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
737                                 /* idle = */ 0, event.mPackage));
738                         notifyBatteryStats(event.mPackage, userId, false);
739                     }
740                 }
741             }
742         }
743     }
744 
reportContentProviderUsage(String authority, String providerPkgName, int userId)745     void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
746         // Get sync adapters for the authority
747         String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
748                 authority, userId);
749         for (String packageName: packages) {
750             // Only force the sync adapters to active if the provider is not in the same package and
751             // the sync adapter is a system package.
752             try {
753                 PackageInfo pi = mPackageManager.getPackageInfoAsUser(
754                         packageName, PackageManager.MATCH_SYSTEM_ONLY, userId);
755                 if (pi == null || pi.applicationInfo == null) {
756                     continue;
757                 }
758                 if (!packageName.equals(providerPkgName)) {
759                     setAppIdleAsync(packageName, false, userId);
760                 }
761             } catch (NameNotFoundException e) {
762                 // Shouldn't happen
763             }
764         }
765     }
766 
767     /**
768      * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
769      * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
770      * the threshold for idle.
771      *
772      * This method is always called from the handler thread, so not much synchronization is
773      * required.
774      */
forceIdleState(String packageName, int userId, boolean idle)775     void forceIdleState(String packageName, int userId, boolean idle) {
776         final int appId = getAppId(packageName);
777         if (appId < 0) return;
778         final long elapsedRealtime = SystemClock.elapsedRealtime();
779 
780         final boolean previouslyIdle = isAppIdleFiltered(packageName, appId,
781                 userId, elapsedRealtime);
782         synchronized (mAppIdleLock) {
783             mAppIdleHistory.setIdle(packageName, userId, idle, elapsedRealtime);
784         }
785         final boolean stillIdle = isAppIdleFiltered(packageName, appId,
786                 userId, elapsedRealtime);
787         // Inform listeners if necessary
788         if (previouslyIdle != stillIdle) {
789             mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
790                     /* idle = */ stillIdle ? 1 : 0, packageName));
791             if (!stillIdle) {
792                 notifyBatteryStats(packageName, userId, idle);
793             }
794         }
795     }
796 
797     /**
798      * Called by the Binder stub.
799      */
flushToDisk()800     void flushToDisk() {
801         synchronized (mLock) {
802             flushToDiskLocked();
803         }
804     }
805 
806     /**
807      * Called by the Binder stub.
808      */
onUserRemoved(int userId)809     void onUserRemoved(int userId) {
810         synchronized (mLock) {
811             Slog.i(TAG, "Removing user " + userId + " and all data.");
812             mUserState.remove(userId);
813             synchronized (mAppIdleLock) {
814                 mAppIdleHistory.onUserRemoved(userId);
815             }
816             cleanUpRemovedUsersLocked();
817         }
818     }
819 
820     /**
821      * Called by the Binder stub.
822      */
queryUsageStats(int userId, int bucketType, long beginTime, long endTime, boolean obfuscateInstantApps)823     List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
824             boolean obfuscateInstantApps) {
825         synchronized (mLock) {
826             final long timeNow = checkAndGetTimeLocked();
827             if (!validRange(timeNow, beginTime, endTime)) {
828                 return null;
829             }
830 
831             final UserUsageStatsService service =
832                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
833             List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
834             if (list == null) {
835                 return null;
836             }
837 
838             // Mangle instant app names *using their current state (not whether they were ephemeral
839             // when the data was recorded)*.
840             if (obfuscateInstantApps) {
841                 for (int i = list.size() - 1; i >= 0; i--) {
842                     final UsageStats stats = list.get(i);
843                     if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
844                         list.set(i, stats.getObfuscatedForInstantApp());
845                     }
846                 }
847             }
848 
849             return list;
850         }
851     }
852 
853     /**
854      * Called by the Binder stub.
855      */
queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime)856     List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
857             long endTime) {
858         synchronized (mLock) {
859             final long timeNow = checkAndGetTimeLocked();
860             if (!validRange(timeNow, beginTime, endTime)) {
861                 return null;
862             }
863 
864             final UserUsageStatsService service =
865                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
866             return service.queryConfigurationStats(bucketType, beginTime, endTime);
867         }
868     }
869 
870     /**
871      * Called by the Binder stub.
872      */
queryEvents(int userId, long beginTime, long endTime, boolean shouldObfuscateInstantApps)873     UsageEvents queryEvents(int userId, long beginTime, long endTime,
874             boolean shouldObfuscateInstantApps) {
875         synchronized (mLock) {
876             final long timeNow = checkAndGetTimeLocked();
877             if (!validRange(timeNow, beginTime, endTime)) {
878                 return null;
879             }
880 
881             final UserUsageStatsService service =
882                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
883             return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
884         }
885     }
886 
isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime)887     private boolean isAppIdleUnfiltered(String packageName, int userId, long elapsedRealtime) {
888         synchronized (mAppIdleLock) {
889             return mAppIdleHistory.isIdle(packageName, userId, elapsedRealtime);
890         }
891     }
892 
addListener(AppIdleStateChangeListener listener)893     void addListener(AppIdleStateChangeListener listener) {
894         synchronized (mAppIdleLock) {
895             if (!mPackageAccessListeners.contains(listener)) {
896                 mPackageAccessListeners.add(listener);
897             }
898         }
899     }
900 
removeListener(AppIdleStateChangeListener listener)901     void removeListener(AppIdleStateChangeListener listener) {
902         synchronized (mAppIdleLock) {
903             mPackageAccessListeners.remove(listener);
904         }
905     }
906 
getAppId(String packageName)907     int getAppId(String packageName) {
908         try {
909             ApplicationInfo ai = mPackageManager.getApplicationInfo(packageName,
910                     PackageManager.MATCH_ANY_USER
911                             | PackageManager.MATCH_DISABLED_COMPONENTS);
912             return ai.uid;
913         } catch (NameNotFoundException re) {
914             return -1;
915         }
916     }
917 
isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime, boolean shouldObfuscateInstantApps)918     boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
919             boolean shouldObfuscateInstantApps) {
920         if (isParoledOrCharging()) {
921             return false;
922         }
923         if (shouldObfuscateInstantApps &&
924                 mPackageManagerInternal.isPackageEphemeral(userId, packageName)) {
925             return false;
926         }
927         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
928     }
929 
930     /**
931      * Checks if an app has been idle for a while and filters out apps that are excluded.
932      * It returns false if the current system state allows all apps to be considered active.
933      * This happens if the device is plugged in or temporarily allowed to make exceptions.
934      * Called by interface impls.
935      */
isAppIdleFiltered(String packageName, int appId, int userId, long elapsedRealtime)936     private boolean isAppIdleFiltered(String packageName, int appId, int userId,
937             long elapsedRealtime) {
938         if (packageName == null) return false;
939         // If not enabled at all, of course nobody is ever idle.
940         if (!mAppIdleEnabled) {
941             return false;
942         }
943         if (appId < Process.FIRST_APPLICATION_UID) {
944             // System uids never go idle.
945             return false;
946         }
947         if (packageName.equals("android")) {
948             // Nor does the framework (which should be redundant with the above, but for MR1 we will
949             // retain this for safety).
950             return false;
951         }
952         if (mSystemServicesReady) {
953             try {
954                 // We allow all whitelisted apps, including those that don't want to be whitelisted
955                 // for idle mode, because app idle (aka app standby) is really not as big an issue
956                 // for controlling who participates vs. doze mode.
957                 if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
958                     return false;
959                 }
960             } catch (RemoteException re) {
961                 throw re.rethrowFromSystemServer();
962             }
963 
964             if (isActiveDeviceAdmin(packageName, userId)) {
965                 return false;
966             }
967 
968             if (isActiveNetworkScorer(packageName)) {
969                 return false;
970             }
971 
972             if (mAppWidgetManager != null
973                     && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
974                 return false;
975             }
976 
977             if (isDeviceProvisioningPackage(packageName)) {
978                 return false;
979             }
980         }
981 
982         if (!isAppIdleUnfiltered(packageName, userId, elapsedRealtime)) {
983             return false;
984         }
985 
986         // Check this last, as it is the most expensive check
987         // TODO: Optimize this by fetching the carrier privileged apps ahead of time
988         if (isCarrierApp(packageName)) {
989             return false;
990         }
991 
992         return true;
993     }
994 
getIdleUidsForUser(int userId)995     int[] getIdleUidsForUser(int userId) {
996         if (!mAppIdleEnabled) {
997             return new int[0];
998         }
999 
1000         final long elapsedRealtime = SystemClock.elapsedRealtime();
1001 
1002         List<ApplicationInfo> apps;
1003         try {
1004             ParceledListSlice<ApplicationInfo> slice = AppGlobals.getPackageManager()
1005                     .getInstalledApplications(/* flags= */ 0, userId);
1006             if (slice == null) {
1007                 return new int[0];
1008             }
1009             apps = slice.getList();
1010         } catch (RemoteException e) {
1011             throw e.rethrowFromSystemServer();
1012         }
1013 
1014         // State of each uid.  Key is the uid.  Value lower 16 bits is the number of apps
1015         // associated with that uid, upper 16 bits is the number of those apps that is idle.
1016         SparseIntArray uidStates = new SparseIntArray();
1017 
1018         // Now resolve all app state.  Iterating over all apps, keeping track of how many
1019         // we find for each uid and how many of those are idle.
1020         for (int i = apps.size() - 1; i >= 0; i--) {
1021             ApplicationInfo ai = apps.get(i);
1022 
1023             // Check whether this app is idle.
1024             boolean idle = isAppIdleFiltered(ai.packageName, UserHandle.getAppId(ai.uid),
1025                     userId, elapsedRealtime);
1026 
1027             int index = uidStates.indexOfKey(ai.uid);
1028             if (index < 0) {
1029                 uidStates.put(ai.uid, 1 + (idle ? 1<<16 : 0));
1030             } else {
1031                 int value = uidStates.valueAt(index);
1032                 uidStates.setValueAt(index, value + 1 + (idle ? 1<<16 : 0));
1033             }
1034         }
1035         if (DEBUG) {
1036             Slog.d(TAG, "getIdleUids took " + (SystemClock.elapsedRealtime() - elapsedRealtime));
1037         }
1038         int numIdle = 0;
1039         for (int i = uidStates.size() - 1; i >= 0; i--) {
1040             int value = uidStates.valueAt(i);
1041             if ((value&0x7fff) == (value>>16)) {
1042                 numIdle++;
1043             }
1044         }
1045 
1046         int[] res = new int[numIdle];
1047         numIdle = 0;
1048         for (int i = uidStates.size() - 1; i >= 0; i--) {
1049             int value = uidStates.valueAt(i);
1050             if ((value&0x7fff) == (value>>16)) {
1051                 res[numIdle] = uidStates.keyAt(i);
1052                 numIdle++;
1053             }
1054         }
1055 
1056         return res;
1057     }
1058 
setAppIdleAsync(String packageName, boolean idle, int userId)1059     void setAppIdleAsync(String packageName, boolean idle, int userId) {
1060         if (packageName == null) return;
1061 
1062         mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
1063                 .sendToTarget();
1064     }
1065 
isActiveDeviceAdmin(String packageName, int userId)1066     private boolean isActiveDeviceAdmin(String packageName, int userId) {
1067         DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
1068         if (dpm == null) return false;
1069         return dpm.packageHasActiveAdmins(packageName, userId);
1070     }
1071 
1072     /**
1073      * Returns {@code true} if the supplied package is the device provisioning app. Otherwise,
1074      * returns {@code false}.
1075      */
isDeviceProvisioningPackage(String packageName)1076     private boolean isDeviceProvisioningPackage(String packageName) {
1077         String deviceProvisioningPackage = getContext().getResources().getString(
1078                 com.android.internal.R.string.config_deviceProvisioningPackage);
1079         return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
1080     }
1081 
isCarrierApp(String packageName)1082     private boolean isCarrierApp(String packageName) {
1083         synchronized (mAppIdleLock) {
1084             if (!mHaveCarrierPrivilegedApps) {
1085                 fetchCarrierPrivilegedAppsLA();
1086             }
1087             if (mCarrierPrivilegedApps != null) {
1088                 return mCarrierPrivilegedApps.contains(packageName);
1089             }
1090             return false;
1091         }
1092     }
1093 
clearCarrierPrivilegedApps()1094     void clearCarrierPrivilegedApps() {
1095         if (DEBUG) {
1096             Slog.i(TAG, "Clearing carrier privileged apps list");
1097         }
1098         synchronized (mAppIdleLock) {
1099             mHaveCarrierPrivilegedApps = false;
1100             mCarrierPrivilegedApps = null; // Need to be refetched.
1101         }
1102     }
1103 
1104     @GuardedBy("mAppIdleLock")
fetchCarrierPrivilegedAppsLA()1105     private void fetchCarrierPrivilegedAppsLA() {
1106         TelephonyManager telephonyManager =
1107                 getContext().getSystemService(TelephonyManager.class);
1108         mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
1109         mHaveCarrierPrivilegedApps = true;
1110         if (DEBUG) {
1111             Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
1112         }
1113     }
1114 
isActiveNetworkScorer(String packageName)1115     private boolean isActiveNetworkScorer(String packageName) {
1116         NetworkScoreManager nsm = (NetworkScoreManager) getContext().getSystemService(
1117                 Context.NETWORK_SCORE_SERVICE);
1118         return packageName != null && packageName.equals(nsm.getActiveScorerPackage());
1119     }
1120 
informListeners(String packageName, int userId, boolean isIdle)1121     void informListeners(String packageName, int userId, boolean isIdle) {
1122         for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
1123             listener.onAppIdleStateChanged(packageName, userId, isIdle);
1124         }
1125     }
1126 
informParoleStateChanged()1127     void informParoleStateChanged() {
1128         final boolean paroled = isParoledOrCharging();
1129         for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
1130             listener.onParoleStateChanged(paroled);
1131         }
1132     }
1133 
validRange(long currentTime, long beginTime, long endTime)1134     private static boolean validRange(long currentTime, long beginTime, long endTime) {
1135         return beginTime <= currentTime && beginTime < endTime;
1136     }
1137 
flushToDiskLocked()1138     private void flushToDiskLocked() {
1139         final int userCount = mUserState.size();
1140         for (int i = 0; i < userCount; i++) {
1141             UserUsageStatsService service = mUserState.valueAt(i);
1142             service.persistActiveStats();
1143             synchronized (mAppIdleLock) {
1144                 mAppIdleHistory.writeAppIdleTimes(mUserState.keyAt(i));
1145             }
1146         }
1147         // Persist elapsed and screen on time. If this fails for whatever reason, the apps will be
1148         // considered not-idle, which is the safest outcome in such an event.
1149         synchronized (mAppIdleLock) {
1150             mAppIdleHistory.writeAppIdleDurations();
1151         }
1152         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
1153     }
1154 
1155     /**
1156      * Called by the Binder stub.
1157      */
dump(String[] args, PrintWriter pw)1158     void dump(String[] args, PrintWriter pw) {
1159         synchronized (mLock) {
1160             IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
1161             ArraySet<String> argSet = new ArraySet<>();
1162             argSet.addAll(Arrays.asList(args));
1163 
1164             final int userCount = mUserState.size();
1165             for (int i = 0; i < userCount; i++) {
1166                 idpw.printPair("user", mUserState.keyAt(i));
1167                 idpw.println();
1168                 idpw.increaseIndent();
1169                 if (argSet.contains("--checkin")) {
1170                     mUserState.valueAt(i).checkin(idpw);
1171                 } else {
1172                     mUserState.valueAt(i).dump(idpw);
1173                     idpw.println();
1174                     if (args.length > 0) {
1175                         if ("history".equals(args[0])) {
1176                             synchronized (mAppIdleLock) {
1177                                 mAppIdleHistory.dumpHistory(idpw, mUserState.keyAt(i));
1178                             }
1179                         } else if ("flush".equals(args[0])) {
1180                             UsageStatsService.this.flushToDiskLocked();
1181                             pw.println("Flushed stats to disk");
1182                         }
1183                     }
1184                 }
1185                 synchronized (mAppIdleLock) {
1186                     mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
1187                 }
1188                 idpw.decreaseIndent();
1189             }
1190 
1191             pw.println();
1192             synchronized (mAppIdleLock) {
1193                 pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
1194                         + "): " + mCarrierPrivilegedApps);
1195             }
1196 
1197             pw.println();
1198             pw.println("Settings:");
1199 
1200             pw.print("  mAppIdleDurationMillis=");
1201             TimeUtils.formatDuration(mAppIdleScreenThresholdMillis, pw);
1202             pw.println();
1203 
1204             pw.print("  mAppIdleWallclockThresholdMillis=");
1205             TimeUtils.formatDuration(mAppIdleWallclockThresholdMillis, pw);
1206             pw.println();
1207 
1208             pw.print("  mCheckIdleIntervalMillis=");
1209             TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw);
1210             pw.println();
1211 
1212             pw.print("  mAppIdleParoleIntervalMillis=");
1213             TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw);
1214             pw.println();
1215 
1216             pw.print("  mAppIdleParoleDurationMillis=");
1217             TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
1218             pw.println();
1219 
1220             pw.println();
1221             pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
1222             pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
1223             pw.print(" mCharging="); pw.print(mCharging);
1224             pw.print(" mLastAppIdleParoledTime=");
1225             TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
1226             pw.println();
1227         }
1228     }
1229 
1230     class H extends Handler {
H(Looper looper)1231         public H(Looper looper) {
1232             super(looper);
1233         }
1234 
1235         @Override
handleMessage(Message msg)1236         public void handleMessage(Message msg) {
1237             switch (msg.what) {
1238                 case MSG_REPORT_EVENT:
1239                     reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
1240                     break;
1241 
1242                 case MSG_FLUSH_TO_DISK:
1243                     flushToDisk();
1244                     break;
1245 
1246                 case MSG_REMOVE_USER:
1247                     onUserRemoved(msg.arg1);
1248                     break;
1249 
1250                 case MSG_INFORM_LISTENERS:
1251                     informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
1252                     break;
1253 
1254                 case MSG_FORCE_IDLE_STATE:
1255                     forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
1256                     break;
1257 
1258                 case MSG_CHECK_IDLE_STATES:
1259                     if (checkIdleStates(msg.arg1)) {
1260                         mHandler.sendMessageDelayed(mHandler.obtainMessage(
1261                                 MSG_CHECK_IDLE_STATES, msg.arg1, 0),
1262                                 mCheckIdleIntervalMillis);
1263                     }
1264                     break;
1265 
1266                 case MSG_ONE_TIME_CHECK_IDLE_STATES:
1267                     mHandler.removeMessages(MSG_ONE_TIME_CHECK_IDLE_STATES);
1268                     checkIdleStates(UserHandle.USER_ALL);
1269                     break;
1270 
1271                 case MSG_CHECK_PAROLE_TIMEOUT:
1272                     checkParoleTimeout();
1273                     break;
1274 
1275                 case MSG_PAROLE_END_TIMEOUT:
1276                     if (DEBUG) Slog.d(TAG, "Ending parole");
1277                     setAppIdleParoled(false);
1278                     break;
1279 
1280                 case MSG_REPORT_CONTENT_PROVIDER_USAGE:
1281                     SomeArgs args = (SomeArgs) msg.obj;
1282                     reportContentProviderUsage((String) args.arg1, // authority name
1283                             (String) args.arg2, // package name
1284                             (int) args.arg3); // userId
1285                     args.recycle();
1286                     break;
1287 
1288                 case MSG_PAROLE_STATE_CHANGED:
1289                     if (DEBUG) Slog.d(TAG, "Parole state: " + mAppIdleTempParoled
1290                             + ", Charging state:" + mCharging);
1291                     informParoleStateChanged();
1292                     break;
1293 
1294                 default:
1295                     super.handleMessage(msg);
1296                     break;
1297             }
1298         }
1299     }
1300 
1301     /**
1302      * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}.
1303      */
1304     private class SettingsObserver extends ContentObserver {
1305         /**
1306          * This flag has been used to disable app idle on older builds with bug b/26355386.
1307          */
1308         @Deprecated
1309         private static final String KEY_IDLE_DURATION_OLD = "idle_duration";
1310 
1311         private static final String KEY_IDLE_DURATION = "idle_duration2";
1312         private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold";
1313         private static final String KEY_PAROLE_INTERVAL = "parole_interval";
1314         private static final String KEY_PAROLE_DURATION = "parole_duration";
1315 
1316         private final KeyValueListParser mParser = new KeyValueListParser(',');
1317 
SettingsObserver(Handler handler)1318         SettingsObserver(Handler handler) {
1319             super(handler);
1320         }
1321 
registerObserver()1322         void registerObserver() {
1323             getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor(
1324                     Settings.Global.APP_IDLE_CONSTANTS), false, this);
1325         }
1326 
1327         @Override
onChange(boolean selfChange)1328         public void onChange(boolean selfChange) {
1329             updateSettings();
1330             postOneTimeCheckIdleStates();
1331         }
1332 
updateSettings()1333         void updateSettings() {
1334             synchronized (mAppIdleLock) {
1335                 // Look at global settings for this.
1336                 // TODO: Maybe apply different thresholds for different users.
1337                 try {
1338                     mParser.setString(Settings.Global.getString(getContext().getContentResolver(),
1339                             Settings.Global.APP_IDLE_CONSTANTS));
1340                 } catch (IllegalArgumentException e) {
1341                     Slog.e(TAG, "Bad value for app idle settings: " + e.getMessage());
1342                     // fallthrough, mParser is empty and all defaults will be returned.
1343                 }
1344 
1345                 // Default: 12 hours of screen-on time sans dream-time
1346                 mAppIdleScreenThresholdMillis = mParser.getLong(KEY_IDLE_DURATION,
1347                        COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE);
1348 
1349                 mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD,
1350                         COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days
1351 
1352                 mCheckIdleIntervalMillis = Math.min(mAppIdleScreenThresholdMillis / 4,
1353                         COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours
1354 
1355                 // Default: 24 hours between paroles
1356                 mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL,
1357                         COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
1358 
1359                 mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION,
1360                         COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
1361                 mAppIdleHistory.setThresholds(mAppIdleWallclockThresholdMillis,
1362                         mAppIdleScreenThresholdMillis);
1363             }
1364         }
1365     }
1366 
1367     private final class BinderService extends IUsageStatsManager.Stub {
1368 
hasPermission(String callingPackage)1369         private boolean hasPermission(String callingPackage) {
1370             final int callingUid = Binder.getCallingUid();
1371             if (callingUid == Process.SYSTEM_UID) {
1372                 return true;
1373             }
1374             final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
1375                     callingUid, callingPackage);
1376             if (mode == AppOpsManager.MODE_DEFAULT) {
1377                 // The default behavior here is to check if PackageManager has given the app
1378                 // permission.
1379                 return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
1380                         == PackageManager.PERMISSION_GRANTED;
1381             }
1382             return mode == AppOpsManager.MODE_ALLOWED;
1383         }
1384 
1385         @Override
queryUsageStats(int bucketType, long beginTime, long endTime, String callingPackage)1386         public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
1387                 long endTime, String callingPackage) {
1388             if (!hasPermission(callingPackage)) {
1389                 return null;
1390             }
1391 
1392             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1393                     Binder.getCallingUid(), UserHandle.getCallingUserId());
1394 
1395             final int userId = UserHandle.getCallingUserId();
1396             final long token = Binder.clearCallingIdentity();
1397             try {
1398                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
1399                         userId, bucketType, beginTime, endTime, obfuscateInstantApps);
1400                 if (results != null) {
1401                     return new ParceledListSlice<>(results);
1402                 }
1403             } finally {
1404                 Binder.restoreCallingIdentity(token);
1405             }
1406             return null;
1407         }
1408 
1409         @Override
queryConfigurationStats(int bucketType, long beginTime, long endTime, String callingPackage)1410         public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
1411                 long beginTime, long endTime, String callingPackage) throws RemoteException {
1412             if (!hasPermission(callingPackage)) {
1413                 return null;
1414             }
1415 
1416             final int userId = UserHandle.getCallingUserId();
1417             final long token = Binder.clearCallingIdentity();
1418             try {
1419                 final List<ConfigurationStats> results =
1420                         UsageStatsService.this.queryConfigurationStats(userId, bucketType,
1421                                 beginTime, endTime);
1422                 if (results != null) {
1423                     return new ParceledListSlice<>(results);
1424                 }
1425             } finally {
1426                 Binder.restoreCallingIdentity(token);
1427             }
1428             return null;
1429         }
1430 
1431         @Override
queryEvents(long beginTime, long endTime, String callingPackage)1432         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
1433             if (!hasPermission(callingPackage)) {
1434                 return null;
1435             }
1436 
1437             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1438                     Binder.getCallingUid(), UserHandle.getCallingUserId());
1439 
1440             final int userId = UserHandle.getCallingUserId();
1441             final long token = Binder.clearCallingIdentity();
1442             try {
1443                 return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
1444                         obfuscateInstantApps);
1445             } finally {
1446                 Binder.restoreCallingIdentity(token);
1447             }
1448         }
1449 
1450         @Override
isAppInactive(String packageName, int userId)1451         public boolean isAppInactive(String packageName, int userId) {
1452             try {
1453                 userId = ActivityManager.getService().handleIncomingUser(Binder.getCallingPid(),
1454                         Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
1455             } catch (RemoteException re) {
1456                 throw re.rethrowFromSystemServer();
1457             }
1458             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
1459                     Binder.getCallingUid(), userId);
1460             final long token = Binder.clearCallingIdentity();
1461             try {
1462                 return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,
1463                         SystemClock.elapsedRealtime(), obfuscateInstantApps);
1464             } finally {
1465                 Binder.restoreCallingIdentity(token);
1466             }
1467         }
1468 
1469         @Override
setAppInactive(String packageName, boolean idle, int userId)1470         public void setAppInactive(String packageName, boolean idle, int userId) {
1471             final int callingUid = Binder.getCallingUid();
1472             try {
1473                 userId = ActivityManager.getService().handleIncomingUser(
1474                         Binder.getCallingPid(), callingUid, userId, false, true,
1475                         "setAppInactive", null);
1476             } catch (RemoteException re) {
1477                 throw re.rethrowFromSystemServer();
1478             }
1479             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1480                     "No permission to change app idle state");
1481             final long token = Binder.clearCallingIdentity();
1482             try {
1483                 final int appId = getAppId(packageName);
1484                 if (appId < 0) return;
1485                 UsageStatsService.this.setAppIdleAsync(packageName, idle, userId);
1486             } finally {
1487                 Binder.restoreCallingIdentity(token);
1488             }
1489         }
1490 
1491         @Override
whitelistAppTemporarily(String packageName, long duration, int userId)1492         public void whitelistAppTemporarily(String packageName, long duration, int userId)
1493                 throws RemoteException {
1494             StringBuilder reason = new StringBuilder(32);
1495             reason.append("from:");
1496             UserHandle.formatUid(reason, Binder.getCallingUid());
1497             mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
1498                     reason.toString());
1499         }
1500 
1501         @Override
onCarrierPrivilegedAppsChanged()1502         public void onCarrierPrivilegedAppsChanged() {
1503             if (DEBUG) {
1504                 Slog.i(TAG, "Carrier privileged apps changed");
1505             }
1506             getContext().enforceCallingOrSelfPermission(
1507                     android.Manifest.permission.BIND_CARRIER_SERVICES,
1508                     "onCarrierPrivilegedAppsChanged can only be called by privileged apps.");
1509             UsageStatsService.this.clearCarrierPrivilegedApps();
1510         }
1511 
1512         @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1513         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1514             if (!DumpUtils.checkDumpAndUsageStatsPermission(getContext(), TAG, pw)) return;
1515             UsageStatsService.this.dump(args, pw);
1516         }
1517 
1518         @Override
reportChooserSelection(String packageName, int userId, String contentType, String[] annotations, String action)1519         public void reportChooserSelection(String packageName, int userId, String contentType,
1520                                            String[] annotations, String action) {
1521             if (packageName == null) {
1522                 Slog.w(TAG, "Event report user selecting a null package");
1523                 return;
1524             }
1525 
1526             UsageEvents.Event event = new UsageEvents.Event();
1527             event.mPackage = packageName;
1528 
1529             // This will later be converted to system time.
1530             event.mTimeStamp = SystemClock.elapsedRealtime();
1531 
1532             event.mEventType = Event.CHOOSER_ACTION;
1533 
1534             event.mAction = action;
1535 
1536             event.mContentType = contentType;
1537 
1538             event.mContentAnnotations = annotations;
1539 
1540             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1541         }
1542     }
1543 
1544     /**
1545      * This local service implementation is primarily used by ActivityManagerService.
1546      * ActivityManagerService will call these methods holding the 'am' lock, which means we
1547      * shouldn't be doing any IO work or other long running tasks in these methods.
1548      */
1549     private final class LocalService extends UsageStatsManagerInternal {
1550 
1551         @Override
reportEvent(ComponentName component, int userId, int eventType)1552         public void reportEvent(ComponentName component, int userId, int eventType) {
1553             if (component == null) {
1554                 Slog.w(TAG, "Event reported without a component name");
1555                 return;
1556             }
1557 
1558             UsageEvents.Event event = new UsageEvents.Event();
1559             event.mPackage = component.getPackageName();
1560             event.mClass = component.getClassName();
1561 
1562             // This will later be converted to system time.
1563             event.mTimeStamp = SystemClock.elapsedRealtime();
1564 
1565             event.mEventType = eventType;
1566             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1567         }
1568 
1569         @Override
reportEvent(String packageName, int userId, int eventType)1570         public void reportEvent(String packageName, int userId, int eventType) {
1571             if (packageName == null) {
1572                 Slog.w(TAG, "Event reported without a package name");
1573                 return;
1574             }
1575 
1576             UsageEvents.Event event = new UsageEvents.Event();
1577             event.mPackage = packageName;
1578 
1579             // This will later be converted to system time.
1580             event.mTimeStamp = SystemClock.elapsedRealtime();
1581 
1582             event.mEventType = eventType;
1583             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1584         }
1585 
1586         @Override
reportConfigurationChange(Configuration config, int userId)1587         public void reportConfigurationChange(Configuration config, int userId) {
1588             if (config == null) {
1589                 Slog.w(TAG, "Configuration event reported with a null config");
1590                 return;
1591             }
1592 
1593             UsageEvents.Event event = new UsageEvents.Event();
1594             event.mPackage = "android";
1595 
1596             // This will later be converted to system time.
1597             event.mTimeStamp = SystemClock.elapsedRealtime();
1598 
1599             event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
1600             event.mConfiguration = new Configuration(config);
1601             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1602         }
1603 
1604         @Override
reportShortcutUsage(String packageName, String shortcutId, int userId)1605         public void reportShortcutUsage(String packageName, String shortcutId, int userId) {
1606             if (packageName == null || shortcutId == null) {
1607                 Slog.w(TAG, "Event reported without a package name or a shortcut ID");
1608                 return;
1609             }
1610 
1611             UsageEvents.Event event = new UsageEvents.Event();
1612             event.mPackage = packageName.intern();
1613             event.mShortcutId = shortcutId.intern();
1614 
1615             // This will later be converted to system time.
1616             event.mTimeStamp = SystemClock.elapsedRealtime();
1617 
1618             event.mEventType = Event.SHORTCUT_INVOCATION;
1619             mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1620         }
1621 
1622         @Override
reportContentProviderUsage(String name, String packageName, int userId)1623         public void reportContentProviderUsage(String name, String packageName, int userId) {
1624             SomeArgs args = SomeArgs.obtain();
1625             args.arg1 = name;
1626             args.arg2 = packageName;
1627             args.arg3 = userId;
1628             mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args)
1629                     .sendToTarget();
1630         }
1631 
1632         @Override
isAppIdle(String packageName, int uidForAppId, int userId)1633         public boolean isAppIdle(String packageName, int uidForAppId, int userId) {
1634             return UsageStatsService.this.isAppIdleFiltered(packageName, uidForAppId, userId,
1635                     SystemClock.elapsedRealtime());
1636         }
1637 
1638         @Override
getIdleUidsForUser(int userId)1639         public int[] getIdleUidsForUser(int userId) {
1640             return UsageStatsService.this.getIdleUidsForUser(userId);
1641         }
1642 
1643         @Override
isAppIdleParoleOn()1644         public boolean isAppIdleParoleOn() {
1645             return isParoledOrCharging();
1646         }
1647 
1648         @Override
prepareShutdown()1649         public void prepareShutdown() {
1650             // This method *WILL* do IO work, but we must block until it is finished or else
1651             // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1652             // we are shutting down.
1653             shutdown();
1654         }
1655 
1656         @Override
addAppIdleStateChangeListener(AppIdleStateChangeListener listener)1657         public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1658             UsageStatsService.this.addListener(listener);
1659             listener.onParoleStateChanged(isAppIdleParoleOn());
1660         }
1661 
1662         @Override
removeAppIdleStateChangeListener( AppIdleStateChangeListener listener)1663         public void removeAppIdleStateChangeListener(
1664                 AppIdleStateChangeListener listener) {
1665             UsageStatsService.this.removeListener(listener);
1666         }
1667 
1668         @Override
getBackupPayload(int user, String key)1669         public byte[] getBackupPayload(int user, String key) {
1670             // Check to ensure that only user 0's data is b/r for now
1671             synchronized (UsageStatsService.this.mLock) {
1672                 if (user == UserHandle.USER_SYSTEM) {
1673                     final UserUsageStatsService userStats =
1674                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1675                     return userStats.getBackupPayload(key);
1676                 } else {
1677                     return null;
1678                 }
1679             }
1680         }
1681 
1682         @Override
applyRestoredPayload(int user, String key, byte[] payload)1683         public void applyRestoredPayload(int user, String key, byte[] payload) {
1684             synchronized (UsageStatsService.this.mLock) {
1685                 if (user == UserHandle.USER_SYSTEM) {
1686                     final UserUsageStatsService userStats =
1687                             getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked());
1688                     userStats.applyRestoredPayload(key, payload);
1689                 }
1690             }
1691         }
1692 
1693         @Override
queryUsageStatsForUser( int userId, int intervalType, long beginTime, long endTime, boolean obfuscateInstantApps)1694         public List<UsageStats> queryUsageStatsForUser(
1695                 int userId, int intervalType, long beginTime, long endTime,
1696                 boolean obfuscateInstantApps) {
1697             return UsageStatsService.this.queryUsageStats(
1698                     userId, intervalType, beginTime, endTime, obfuscateInstantApps);
1699         }
1700     }
1701 }
1702