UsageStatsService.java revision 92617036fcc9b25378c8448c923d6346a012346b
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
17package com.android.server.usage;
18
19import android.Manifest;
20import android.app.ActivityManagerNative;
21import android.app.AppGlobals;
22import android.app.AppOpsManager;
23import android.app.admin.DevicePolicyManager;
24import android.app.usage.ConfigurationStats;
25import android.app.usage.IUsageStatsManager;
26import android.app.usage.UsageEvents;
27import android.app.usage.UsageEvents.Event;
28import android.app.usage.UsageStats;
29import android.app.usage.UsageStatsManagerInternal;
30import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
31import android.appwidget.AppWidgetManager;
32import android.content.BroadcastReceiver;
33import android.content.ComponentName;
34import android.content.ContentResolver;
35import android.content.Context;
36import android.content.Intent;
37import android.content.IntentFilter;
38import android.content.pm.PackageInfo;
39import android.content.pm.PackageManager;
40import android.content.pm.ParceledListSlice;
41import android.content.pm.UserInfo;
42import android.content.res.Configuration;
43import android.database.ContentObserver;
44import android.hardware.display.DisplayManager;
45import android.os.BatteryManager;
46import android.os.BatteryStats;
47import android.os.Binder;
48import android.os.Environment;
49import android.os.Handler;
50import android.os.IDeviceIdleController;
51import android.os.Looper;
52import android.os.Message;
53import android.os.PowerManager;
54import android.os.Process;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.os.SystemClock;
58import android.os.UserHandle;
59import android.os.UserManager;
60import android.provider.Settings;
61import android.telephony.TelephonyManager;
62import android.util.ArraySet;
63import android.util.AtomicFile;
64import android.util.KeyValueListParser;
65import android.util.Slog;
66import android.util.SparseArray;
67import android.util.TimeUtils;
68import android.view.Display;
69
70import com.android.internal.annotations.GuardedBy;
71import com.android.internal.app.IBatteryStats;
72import com.android.internal.os.BackgroundThread;
73import com.android.internal.os.SomeArgs;
74import com.android.internal.util.IndentingPrintWriter;
75import com.android.server.SystemService;
76
77import java.io.BufferedReader;
78import java.io.File;
79import java.io.FileDescriptor;
80import java.io.FileOutputStream;
81import java.io.FileReader;
82import java.io.IOException;
83import java.io.PrintWriter;
84import java.util.ArrayList;
85import java.util.Arrays;
86import java.util.List;
87
88/**
89 * A service that collects, aggregates, and persists application usage data.
90 * This data can be queried by apps that have been granted permission by AppOps.
91 */
92public class UsageStatsService extends SystemService implements
93        UserUsageStatsService.StatsUpdatedListener {
94
95    static final String TAG = "UsageStatsService";
96
97    static final boolean DEBUG = false;
98    static final boolean COMPRESS_TIME = false;
99
100    private static final long TEN_SECONDS = 10 * 1000;
101    private static final long ONE_MINUTE = 60 * 1000;
102    private static final long TWENTY_MINUTES = 20 * 60 * 1000;
103    private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
104    private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
105
106    long mAppIdleDurationMillis;
107    long mCheckIdleIntervalMillis;
108    long mAppIdleWallclockThresholdMillis;
109    long mAppIdleParoleIntervalMillis;
110    long mAppIdleParoleDurationMillis;
111
112    // Handler message types.
113    static final int MSG_REPORT_EVENT = 0;
114    static final int MSG_FLUSH_TO_DISK = 1;
115    static final int MSG_REMOVE_USER = 2;
116    static final int MSG_INFORM_LISTENERS = 3;
117    static final int MSG_FORCE_IDLE_STATE = 4;
118    static final int MSG_CHECK_IDLE_STATES = 5;
119    static final int MSG_CHECK_PAROLE_TIMEOUT = 6;
120    static final int MSG_PAROLE_END_TIMEOUT = 7;
121    static final int MSG_REPORT_CONTENT_PROVIDER_USAGE = 8;
122
123    private final Object mLock = new Object();
124    Handler mHandler;
125    AppOpsManager mAppOps;
126    UserManager mUserManager;
127    AppWidgetManager mAppWidgetManager;
128    IDeviceIdleController mDeviceIdleController;
129    private DisplayManager mDisplayManager;
130    private PowerManager mPowerManager;
131    private IBatteryStats mBatteryStats;
132
133    private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
134    private File mUsageStatsDir;
135    long mRealTimeSnapshot;
136    long mSystemTimeSnapshot;
137
138    boolean mAppIdleEnabled;
139    boolean mAppIdleParoled;
140    private boolean mScreenOn;
141    private long mLastAppIdleParoledTime;
142
143    long mScreenOnTime;
144    long mScreenOnSystemTimeSnapshot;
145
146    @GuardedBy("mLock")
147    private AppIdleHistory mAppIdleHistory = new AppIdleHistory();
148
149    private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
150            mPackageAccessListeners = new ArrayList<>();
151
152    public UsageStatsService(Context context) {
153        super(context);
154    }
155
156    @Override
157    public void onStart() {
158        mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
159        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
160
161        mHandler = new H(BackgroundThread.get().getLooper());
162
163        File systemDataDir = new File(Environment.getDataDirectory(), "system");
164        mUsageStatsDir = new File(systemDataDir, "usagestats");
165        mUsageStatsDir.mkdirs();
166        if (!mUsageStatsDir.exists()) {
167            throw new IllegalStateException("Usage stats directory does not exist: "
168                    + mUsageStatsDir.getAbsolutePath());
169        }
170
171        IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED);
172        userActions.addAction(Intent.ACTION_USER_STARTED);
173        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions,
174                null, null);
175
176        mAppIdleEnabled = getContext().getResources().getBoolean(
177                com.android.internal.R.bool.config_enableAutoPowerModes);
178        if (mAppIdleEnabled) {
179            IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
180            deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
181            deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
182            getContext().registerReceiver(new DeviceStateReceiver(), deviceStates);
183        }
184
185        synchronized (mLock) {
186            cleanUpRemovedUsersLocked();
187        }
188
189        mRealTimeSnapshot = SystemClock.elapsedRealtime();
190        mSystemTimeSnapshot = System.currentTimeMillis();
191
192        publishLocalService(UsageStatsManagerInternal.class, new LocalService());
193        publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
194    }
195
196    @Override
197    public void onBootPhase(int phase) {
198        if (phase == PHASE_SYSTEM_SERVICES_READY) {
199            // Observe changes to the threshold
200            SettingsObserver settingsObserver = new SettingsObserver(mHandler);
201            settingsObserver.registerObserver();
202            settingsObserver.updateSettings();
203
204            mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
205            mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
206                    ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
207            mBatteryStats = IBatteryStats.Stub.asInterface(
208                    ServiceManager.getService(BatteryStats.SERVICE_NAME));
209            mDisplayManager = (DisplayManager) getContext().getSystemService(
210                    Context.DISPLAY_SERVICE);
211            mPowerManager = getContext().getSystemService(PowerManager.class);
212
213            mScreenOnSystemTimeSnapshot = System.currentTimeMillis();
214            synchronized (this) {
215                mScreenOnTime = readScreenOnTimeLocked();
216            }
217            mDisplayManager.registerDisplayListener(mDisplayListener, null);
218            synchronized (this) {
219                updateDisplayLocked();
220            }
221        } else if (phase == PHASE_BOOT_COMPLETED) {
222            setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
223        }
224    }
225
226    private class UserActionsReceiver extends BroadcastReceiver {
227
228        @Override
229        public void onReceive(Context context, Intent intent) {
230            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
231            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
232                if (userId >= 0) {
233                    mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
234                }
235            } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
236                if (userId >=0) {
237                    postCheckIdleStates(userId);
238                }
239            }
240        }
241    }
242
243    private class DeviceStateReceiver extends BroadcastReceiver {
244        @Override
245        public void onReceive(Context context, Intent intent) {
246            final String action = intent.getAction();
247            if (BatteryManager.ACTION_CHARGING.equals(action)
248                    || BatteryManager.ACTION_DISCHARGING.equals(action)) {
249                setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action));
250            } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
251                onDeviceIdleModeChanged();
252            }
253        }
254    }
255
256    private final DisplayManager.DisplayListener mDisplayListener
257            = new DisplayManager.DisplayListener() {
258
259        @Override public void onDisplayAdded(int displayId) {
260        }
261
262        @Override public void onDisplayRemoved(int displayId) {
263        }
264
265        @Override public void onDisplayChanged(int displayId) {
266            if (displayId == Display.DEFAULT_DISPLAY) {
267                synchronized (UsageStatsService.this.mLock) {
268                    updateDisplayLocked();
269                }
270            }
271        }
272    };
273
274    @Override
275    public void onStatsUpdated() {
276        mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
277    }
278
279    private void cleanUpRemovedUsersLocked() {
280        final List<UserInfo> users = mUserManager.getUsers(true);
281        if (users == null || users.size() == 0) {
282            throw new IllegalStateException("There can't be no users");
283        }
284
285        ArraySet<String> toDelete = new ArraySet<>();
286        String[] fileNames = mUsageStatsDir.list();
287        if (fileNames == null) {
288            // No users to delete.
289            return;
290        }
291
292        toDelete.addAll(Arrays.asList(fileNames));
293
294        final int userCount = users.size();
295        for (int i = 0; i < userCount; i++) {
296            final UserInfo userInfo = users.get(i);
297            toDelete.remove(Integer.toString(userInfo.id));
298        }
299
300        final int deleteCount = toDelete.size();
301        for (int i = 0; i < deleteCount; i++) {
302            deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
303        }
304    }
305
306    /** Paroled here means temporary pardon from being inactive */
307    void setAppIdleParoled(boolean paroled) {
308        synchronized (mLock) {
309            if (mAppIdleParoled != paroled) {
310                mAppIdleParoled = paroled;
311                if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled);
312                if (paroled) {
313                    mLastAppIdleParoledTime = checkAndGetTimeLocked();
314                    postNextParoleTimeout();
315                }
316                postCheckIdleStates(UserHandle.USER_ALL);
317            }
318        }
319    }
320
321    private void postNextParoleTimeout() {
322        if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
323        mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
324        // Compute when the next parole needs to happen. We check more frequently than necessary
325        // since the message handler delays are based on elapsedRealTime and not wallclock time.
326        // The comparison is done in wallclock time.
327        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis)
328                - checkAndGetTimeLocked();
329        if (timeLeft < 0) {
330            timeLeft = 0;
331        }
332        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10);
333    }
334
335    private void postParoleEndTimeout() {
336        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT");
337        mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT);
338        mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
339    }
340
341    void postCheckIdleStates(int userId) {
342        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
343    }
344
345    /** Check all running users' or specified user's apps to see if they enter an idle state. */
346    void checkIdleStates(int checkUserId) {
347        if (!mAppIdleEnabled) {
348            return;
349        }
350
351        final int[] userIds;
352        try {
353            if (checkUserId == UserHandle.USER_ALL) {
354                userIds = ActivityManagerNative.getDefault().getRunningUserIds();
355            } else {
356                userIds = new int[] { checkUserId };
357            }
358        } catch (RemoteException re) {
359            return;
360        }
361
362        for (int i = 0; i < userIds.length; i++) {
363            final int userId = userIds[i];
364            List<PackageInfo> packages =
365                    getContext().getPackageManager().getInstalledPackages(
366                            PackageManager.GET_DISABLED_COMPONENTS
367                                | PackageManager.GET_UNINSTALLED_PACKAGES,
368                            userId);
369            synchronized (mLock) {
370                final long timeNow = checkAndGetTimeLocked();
371                final long screenOnTime = getScreenOnTimeLocked(timeNow);
372                UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
373                        timeNow);
374                final int packageCount = packages.size();
375                for (int p = 0; p < packageCount; p++) {
376                    final String packageName = packages.get(p).packageName;
377                    final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow,
378                            screenOnTime);
379                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
380                            userId, isIdle ? 1 : 0, packageName));
381                    mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
382                }
383            }
384        }
385        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
386                mCheckIdleIntervalMillis);
387    }
388
389    /** Check if it's been a while since last parole and let idle apps do some work */
390    void checkParoleTimeout() {
391        synchronized (mLock) {
392            if (!mAppIdleParoled) {
393                final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
394                if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
395                    if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
396                    setAppIdleParoled(true);
397                    // Make sure it ends at some point
398                    postParoleEndTimeout();
399                } else {
400                    if (DEBUG) Slog.d(TAG, "Not long enough to go to parole");
401                    postNextParoleTimeout();
402                }
403            }
404        }
405    }
406
407    private void notifyBatteryStats(String packageName, int userId, boolean idle) {
408        try {
409            int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId);
410            if (idle) {
411                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE,
412                        packageName, uid);
413            } else {
414                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE,
415                        packageName, uid);
416            }
417        } catch (RemoteException re) {
418        }
419    }
420
421    void updateDisplayLocked() {
422        boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
423                == Display.STATE_ON;
424
425        if (screenOn == mScreenOn) return;
426
427        mScreenOn = screenOn;
428        long now = System.currentTimeMillis();
429        if (mScreenOn) {
430            mScreenOnSystemTimeSnapshot = now;
431        } else {
432            mScreenOnTime += now - mScreenOnSystemTimeSnapshot;
433            writeScreenOnTimeLocked(mScreenOnTime);
434        }
435    }
436
437    private long getScreenOnTimeLocked(long now) {
438        if (mScreenOn) {
439            return now - mScreenOnSystemTimeSnapshot + mScreenOnTime;
440        } else {
441            return mScreenOnTime;
442        }
443    }
444
445    private File getScreenOnTimeFile() {
446        return new File(mUsageStatsDir, UserHandle.USER_OWNER + "/screen_on_time");
447    }
448
449    private long readScreenOnTimeLocked() {
450        long screenOnTime = 0;
451        File screenOnTimeFile = getScreenOnTimeFile();
452        if (screenOnTimeFile.exists()) {
453            try {
454                BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile));
455                screenOnTime = Long.parseLong(reader.readLine());
456                reader.close();
457            } catch (IOException | NumberFormatException e) {
458            }
459        } else {
460            writeScreenOnTimeLocked(screenOnTime);
461        }
462        return screenOnTime;
463    }
464
465    private void writeScreenOnTimeLocked(long screenOnTime) {
466        AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
467        FileOutputStream fos = null;
468        try {
469            fos = screenOnTimeFile.startWrite();
470            fos.write(Long.toString(screenOnTime).getBytes());
471            screenOnTimeFile.finishWrite(fos);
472        } catch (IOException ioe) {
473            screenOnTimeFile.failWrite(fos);
474        }
475    }
476
477    void onDeviceIdleModeChanged() {
478        final boolean deviceIdle = mPowerManager.isDeviceIdleMode();
479        if (DEBUG) Slog.i(TAG, "DeviceIdleMode changed to " + deviceIdle);
480        synchronized (mLock) {
481            final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
482            if (!deviceIdle
483                    && timeSinceLastParole >= mAppIdleParoleIntervalMillis) {
484                if (DEBUG) Slog.i(TAG, "Bringing idle apps out of inactive state due to deviceIdleMode=false");
485                postNextParoleTimeout();
486                setAppIdleParoled(true);
487            } else if (deviceIdle) {
488                if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
489                setAppIdleParoled(false);
490            }
491        }
492    }
493
494    private static void deleteRecursively(File f) {
495        File[] files = f.listFiles();
496        if (files != null) {
497            for (File subFile : files) {
498                deleteRecursively(subFile);
499            }
500        }
501
502        if (!f.delete()) {
503            Slog.e(TAG, "Failed to delete " + f);
504        }
505    }
506
507    private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
508            long currentTimeMillis) {
509        UserUsageStatsService service = mUserState.get(userId);
510        if (service == null) {
511            service = new UserUsageStatsService(getContext(), userId,
512                    new File(mUsageStatsDir, Integer.toString(userId)), this);
513            service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
514            mUserState.put(userId, service);
515        }
516        return service;
517    }
518
519    /**
520     * This should be the only way to get the time from the system.
521     */
522    private long checkAndGetTimeLocked() {
523        final long actualSystemTime = System.currentTimeMillis();
524        final long actualRealtime = SystemClock.elapsedRealtime();
525        final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
526        boolean resetBeginIdleTime = false;
527        if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
528            // The time has changed.
529
530            // Check if it's severe enough a change to reset screenOnTime
531            if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) {
532                mScreenOnSystemTimeSnapshot = actualSystemTime;
533                mScreenOnTime = 0;
534                resetBeginIdleTime = true;
535            }
536            final int userCount = mUserState.size();
537            for (int i = 0; i < userCount; i++) {
538                final UserUsageStatsService service = mUserState.valueAt(i);
539                service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime);
540            }
541            mRealTimeSnapshot = actualRealtime;
542            mSystemTimeSnapshot = actualSystemTime;
543        }
544        return actualSystemTime;
545    }
546
547    /**
548     * Assuming the event's timestamp is measured in milliseconds since boot,
549     * convert it to a system wall time.
550     */
551    private void convertToSystemTimeLocked(UsageEvents.Event event) {
552        event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
553    }
554
555    /**
556     * Called by the Binder stub
557     */
558    void shutdown() {
559        synchronized (mLock) {
560            mHandler.removeMessages(MSG_REPORT_EVENT);
561            flushToDiskLocked();
562        }
563    }
564
565    /**
566     * Called by the Binder stub.
567     */
568    void reportEvent(UsageEvents.Event event, int userId) {
569        synchronized (mLock) {
570            final long timeNow = checkAndGetTimeLocked();
571            final long screenOnTime = getScreenOnTimeLocked(timeNow);
572            convertToSystemTimeLocked(event);
573
574            final UserUsageStatsService service =
575                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
576            final long beginIdleTime = service.getBeginIdleTime(event.mPackage);
577            final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
578            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
579                    lastUsedTime, screenOnTime, timeNow);
580            service.reportEvent(event, screenOnTime);
581            // Inform listeners if necessary
582            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
583                    || event.mEventType == Event.MOVE_TO_BACKGROUND
584                    || event.mEventType == Event.SYSTEM_INTERACTION
585                    || event.mEventType == Event.USER_INTERACTION)) {
586                if (previouslyIdle) {
587                    // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
588                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
589                            /* idle = */ 0, event.mPackage));
590                    notifyBatteryStats(event.mPackage, userId, false);
591                    mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow);
592                }
593            }
594        }
595    }
596
597    void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
598        // Get sync adapters for the authority
599        String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
600                authority, userId);
601        for (String packageName: packages) {
602            // Only force the sync adapters to active if the provider is not in the same package and
603            // the sync adapter is a system package.
604            try {
605                PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo(
606                        packageName, 0, userId);
607                if (pi == null || pi.applicationInfo == null
608                        || !pi.applicationInfo.isSystemApp()) {
609                    continue;
610                }
611                if (!packageName.equals(providerPkgName)) {
612                    forceIdleState(packageName, userId, false);
613                }
614            } catch (RemoteException re) {
615                // Shouldn't happen
616            }
617        }
618    }
619
620    /**
621     * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
622     * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
623     * the threshold for idle.
624     */
625    void forceIdleState(String packageName, int userId, boolean idle) {
626        synchronized (mLock) {
627            final long timeNow = checkAndGetTimeLocked();
628            final long screenOnTime = getScreenOnTimeLocked(timeNow);
629            final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
630
631            final UserUsageStatsService service =
632                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
633            final long beginIdleTime = service.getBeginIdleTime(packageName);
634            final long lastUsedTime = service.getSystemLastUsedTime(packageName);
635            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
636                    lastUsedTime, screenOnTime, timeNow);
637            service.setBeginIdleTime(packageName, deviceUsageTime);
638            service.setSystemLastUsedTime(packageName,
639                    timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000);
640            // Inform listeners if necessary
641            if (previouslyIdle != idle) {
642                // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName);
643                mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
644                        /* idle = */ idle ? 1 : 0, packageName));
645                if (!idle) {
646                    notifyBatteryStats(packageName, userId, idle);
647                }
648                mAppIdleHistory.addEntry(packageName, userId, idle, timeNow);
649            }
650        }
651    }
652
653    /**
654     * Called by the Binder stub.
655     */
656    void flushToDisk() {
657        synchronized (mLock) {
658            flushToDiskLocked();
659        }
660    }
661
662    /**
663     * Called by the Binder stub.
664     */
665    void removeUser(int userId) {
666        synchronized (mLock) {
667            Slog.i(TAG, "Removing user " + userId + " and all data.");
668            mUserState.remove(userId);
669            cleanUpRemovedUsersLocked();
670        }
671    }
672
673    /**
674     * Called by the Binder stub.
675     */
676    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
677        synchronized (mLock) {
678            final long timeNow = checkAndGetTimeLocked();
679            if (!validRange(timeNow, beginTime, endTime)) {
680                return null;
681            }
682
683            final UserUsageStatsService service =
684                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
685            return service.queryUsageStats(bucketType, beginTime, endTime);
686        }
687    }
688
689    /**
690     * Called by the Binder stub.
691     */
692    List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
693            long endTime) {
694        synchronized (mLock) {
695            final long timeNow = checkAndGetTimeLocked();
696            if (!validRange(timeNow, beginTime, endTime)) {
697                return null;
698            }
699
700            final UserUsageStatsService service =
701                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
702            return service.queryConfigurationStats(bucketType, beginTime, endTime);
703        }
704    }
705
706    /**
707     * Called by the Binder stub.
708     */
709    UsageEvents queryEvents(int userId, long beginTime, long endTime) {
710        synchronized (mLock) {
711            final long timeNow = checkAndGetTimeLocked();
712            if (!validRange(timeNow, beginTime, endTime)) {
713                return null;
714            }
715
716            final UserUsageStatsService service =
717                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
718            return service.queryEvents(beginTime, endTime);
719        }
720    }
721
722    private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService,
723            long timeNow, long screenOnTime) {
724        synchronized (mLock) {
725            long beginIdleTime = userService.getBeginIdleTime(packageName);
726            long lastUsedTime = userService.getSystemLastUsedTime(packageName);
727            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime,
728                    timeNow);
729        }
730    }
731
732    /**
733     * @param beginIdleTime when the app was last used in device usage timebase
734     * @param lastUsedTime wallclock time of when the app was last used
735     * @param screenOnTime screen-on timebase time
736     * @param currentTime current time in device usage timebase
737     * @return whether it's been used far enough in the past to be considered inactive
738     */
739    boolean hasPassedIdleTimeoutLocked(long beginIdleTime, long lastUsedTime,
740            long screenOnTime, long currentTime) {
741        return (beginIdleTime <= screenOnTime - mAppIdleDurationMillis)
742                && (lastUsedTime <= currentTime - mAppIdleWallclockThresholdMillis);
743    }
744
745    void addListener(AppIdleStateChangeListener listener) {
746        synchronized (mLock) {
747            if (!mPackageAccessListeners.contains(listener)) {
748                mPackageAccessListeners.add(listener);
749            }
750        }
751    }
752
753    void removeListener(AppIdleStateChangeListener listener) {
754        synchronized (mLock) {
755            mPackageAccessListeners.remove(listener);
756        }
757    }
758
759    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
760        final UserUsageStatsService userService;
761        final long screenOnTime;
762        synchronized (mLock) {
763            if (timeNow == -1) {
764                timeNow = checkAndGetTimeLocked();
765            }
766            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
767            screenOnTime = getScreenOnTimeLocked(timeNow);
768        }
769        return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime);
770    }
771
772    /**
773     * Checks if an app has been idle for a while and filters out apps that are excluded.
774     * It returns false if the current system state allows all apps to be considered active.
775     * This happens if the device is plugged in or temporarily allowed to make exceptions.
776     * Called by interface impls.
777     */
778    private boolean isAppIdleFiltered(String packageName, int userId,
779            UserUsageStatsService userService, long timeNow, long screenOnTime) {
780        if (packageName == null) return false;
781        // If not enabled at all, of course nobody is ever idle.
782        if (!mAppIdleEnabled) {
783            return false;
784        }
785        synchronized (mLock) {
786            // Temporary exemption, probably due to device charging or occasional allowance to
787            // be allowed to sync, etc.
788            if (mAppIdleParoled) {
789                return false;
790            }
791        }
792        if (packageName.equals("android")) return false;
793        try {
794            if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
795                return false;
796            }
797        } catch (RemoteException re) {
798        }
799        // TODO: Optimize this check
800        if (isActiveDeviceAdmin(packageName, userId)) {
801            return false;
802        }
803
804        if (isCarrierApp(packageName)) {
805            return false;
806        }
807
808        if (mAppWidgetManager != null
809                && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
810            return false;
811        }
812
813        return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
814    }
815
816    void setAppIdle(String packageName, boolean idle, int userId) {
817        if (packageName == null) return;
818
819        mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
820                .sendToTarget();
821    }
822
823    private boolean isActiveDeviceAdmin(String packageName, int userId) {
824        DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
825        if (dpm == null) return false;
826        List<ComponentName> components = dpm.getActiveAdminsAsUser(userId);
827        if (components == null) return false;
828        final int size = components.size();
829        for (int i = 0; i < size; i++) {
830            if (components.get(i).getPackageName().equals(packageName)) {
831                return true;
832            }
833        }
834        return false;
835    }
836
837    private boolean isCarrierApp(String packageName) {
838        TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
839        return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
840                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
841    }
842
843    void informListeners(String packageName, int userId, boolean isIdle) {
844        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
845            listener.onAppIdleStateChanged(packageName, userId, isIdle);
846        }
847    }
848
849    private static boolean validRange(long currentTime, long beginTime, long endTime) {
850        return beginTime <= currentTime && beginTime < endTime;
851    }
852
853    private void flushToDiskLocked() {
854        final int userCount = mUserState.size();
855        for (int i = 0; i < userCount; i++) {
856            UserUsageStatsService service = mUserState.valueAt(i);
857            service.persistActiveStats();
858        }
859
860        mHandler.removeMessages(MSG_FLUSH_TO_DISK);
861    }
862
863    /**
864     * Called by the Binder stub.
865     */
866    void dump(String[] args, PrintWriter pw) {
867        synchronized (mLock) {
868            final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
869            IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
870            ArraySet<String> argSet = new ArraySet<>();
871            argSet.addAll(Arrays.asList(args));
872
873            final int userCount = mUserState.size();
874            for (int i = 0; i < userCount; i++) {
875                idpw.printPair("user", mUserState.keyAt(i));
876                idpw.println();
877                idpw.increaseIndent();
878                if (argSet.contains("--checkin")) {
879                    mUserState.valueAt(i).checkin(idpw, screenOnTime);
880                } else {
881                    mUserState.valueAt(i).dump(idpw, screenOnTime);
882                    idpw.println();
883                    if (args.length > 0 && "history".equals(args[0])) {
884                        mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
885                    }
886                }
887                idpw.decreaseIndent();
888            }
889            pw.println("Screen On Timebase:" + mScreenOnTime);
890
891            pw.println();
892            pw.println("Settings:");
893
894            pw.print("  mAppIdleDurationMillis=");
895            TimeUtils.formatDuration(mAppIdleDurationMillis, pw);
896            pw.println();
897
898            pw.print("  mAppIdleWallclockThresholdMillis=");
899            TimeUtils.formatDuration(mAppIdleWallclockThresholdMillis, pw);
900            pw.println();
901
902            pw.print("  mCheckIdleIntervalMillis=");
903            TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw);
904            pw.println();
905
906            pw.print("  mAppIdleParoleIntervalMillis=");
907            TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw);
908            pw.println();
909
910            pw.print("  mAppIdleParoleDurationMillis=");
911            TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
912            pw.println();
913
914            pw.println();
915            pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
916            pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled);
917            pw.print(" mScreenOn="); pw.println(mScreenOn);
918            pw.print("mLastAppIdleParoledTime=");
919            TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
920            pw.println();
921            pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw);
922            pw.println();
923            pw.print("mScreenOnSystemTimeSnapshot=");
924            TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw);
925            pw.println();
926        }
927    }
928
929    class H extends Handler {
930        public H(Looper looper) {
931            super(looper);
932        }
933
934        @Override
935        public void handleMessage(Message msg) {
936            switch (msg.what) {
937                case MSG_REPORT_EVENT:
938                    reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
939                    break;
940
941                case MSG_FLUSH_TO_DISK:
942                    flushToDisk();
943                    break;
944
945                case MSG_REMOVE_USER:
946                    removeUser(msg.arg1);
947                    break;
948
949                case MSG_INFORM_LISTENERS:
950                    informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
951                    break;
952
953                case MSG_FORCE_IDLE_STATE:
954                    forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
955                    break;
956
957                case MSG_CHECK_IDLE_STATES:
958                    checkIdleStates(msg.arg1);
959                    break;
960
961                case MSG_CHECK_PAROLE_TIMEOUT:
962                    checkParoleTimeout();
963                    break;
964
965                case MSG_PAROLE_END_TIMEOUT:
966                    if (DEBUG) Slog.d(TAG, "Ending parole");
967                    setAppIdleParoled(false);
968                    break;
969
970                case MSG_REPORT_CONTENT_PROVIDER_USAGE:
971                    SomeArgs args = (SomeArgs) msg.obj;
972                    reportContentProviderUsage((String) args.arg1, // authority name
973                            (String) args.arg2, // package name
974                            (int) args.arg3); // userId
975                    args.recycle();
976                    break;
977
978                default:
979                    super.handleMessage(msg);
980                    break;
981            }
982        }
983    }
984
985    /**
986     * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}.
987     */
988    private class SettingsObserver extends ContentObserver {
989        private static final String KEY_IDLE_DURATION = "idle_duration";
990        private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold";
991        private static final String KEY_PAROLE_INTERVAL = "parole_interval";
992        private static final String KEY_PAROLE_DURATION = "parole_duration";
993
994        private final KeyValueListParser mParser = new KeyValueListParser(',');
995
996        SettingsObserver(Handler handler) {
997            super(handler);
998        }
999
1000        void registerObserver() {
1001            getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor(
1002                    Settings.Global.APP_IDLE_CONSTANTS), false, this);
1003        }
1004
1005        @Override
1006        public void onChange(boolean selfChange) {
1007            updateSettings();
1008            postCheckIdleStates(UserHandle.USER_ALL);
1009        }
1010
1011        void updateSettings() {
1012            synchronized (mLock) {
1013                // Look at global settings for this.
1014                // TODO: Maybe apply different thresholds for different users.
1015                try {
1016                    mParser.setString(Settings.Global.getString(getContext().getContentResolver(),
1017                            Settings.Global.APP_IDLE_CONSTANTS));
1018                } catch (IllegalArgumentException e) {
1019                    Slog.e(TAG, "Bad value for app idle settings: " + e.getMessage());
1020                    // fallthrough, mParser is empty and all defaults will be returned.
1021                }
1022
1023                // Default: 12 hours of screen-on time sans dream-time
1024                mAppIdleDurationMillis = mParser.getLong(KEY_IDLE_DURATION,
1025                       COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE);
1026
1027                mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD,
1028                        COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days
1029
1030                mCheckIdleIntervalMillis = Math.min(mAppIdleDurationMillis / 4,
1031                        COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours
1032
1033                // Default: 24 hours between paroles
1034                mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL,
1035                        COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
1036
1037                mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION,
1038                        COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
1039            }
1040        }
1041    }
1042
1043    private final class BinderService extends IUsageStatsManager.Stub {
1044
1045        private boolean hasPermission(String callingPackage) {
1046            final int callingUid = Binder.getCallingUid();
1047            if (callingUid == Process.SYSTEM_UID) {
1048                return true;
1049            }
1050            final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
1051                    callingUid, callingPackage);
1052            if (mode == AppOpsManager.MODE_DEFAULT) {
1053                // The default behavior here is to check if PackageManager has given the app
1054                // permission.
1055                return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
1056                        == PackageManager.PERMISSION_GRANTED;
1057            }
1058            return mode == AppOpsManager.MODE_ALLOWED;
1059        }
1060
1061        @Override
1062        public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
1063                long endTime, String callingPackage) {
1064            if (!hasPermission(callingPackage)) {
1065                return null;
1066            }
1067
1068            final int userId = UserHandle.getCallingUserId();
1069            final long token = Binder.clearCallingIdentity();
1070            try {
1071                final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
1072                        userId, bucketType, beginTime, endTime);
1073                if (results != null) {
1074                    return new ParceledListSlice<>(results);
1075                }
1076            } finally {
1077                Binder.restoreCallingIdentity(token);
1078            }
1079            return null;
1080        }
1081
1082        @Override
1083        public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
1084                long beginTime, long endTime, String callingPackage) throws RemoteException {
1085            if (!hasPermission(callingPackage)) {
1086                return null;
1087            }
1088
1089            final int userId = UserHandle.getCallingUserId();
1090            final long token = Binder.clearCallingIdentity();
1091            try {
1092                final List<ConfigurationStats> results =
1093                        UsageStatsService.this.queryConfigurationStats(userId, bucketType,
1094                                beginTime, endTime);
1095                if (results != null) {
1096                    return new ParceledListSlice<>(results);
1097                }
1098            } finally {
1099                Binder.restoreCallingIdentity(token);
1100            }
1101            return null;
1102        }
1103
1104        @Override
1105        public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
1106            if (!hasPermission(callingPackage)) {
1107                return null;
1108            }
1109
1110            final int userId = UserHandle.getCallingUserId();
1111            final long token = Binder.clearCallingIdentity();
1112            try {
1113                return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
1114            } finally {
1115                Binder.restoreCallingIdentity(token);
1116            }
1117        }
1118
1119        @Override
1120        public boolean isAppInactive(String packageName, int userId) {
1121            try {
1122                userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
1123                        Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
1124            } catch (RemoteException re) {
1125                return false;
1126            }
1127            final long token = Binder.clearCallingIdentity();
1128            try {
1129                return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
1130            } finally {
1131                Binder.restoreCallingIdentity(token);
1132            }
1133        }
1134
1135        @Override
1136        public void setAppInactive(String packageName, boolean idle, int userId) {
1137            final int callingUid = Binder.getCallingUid();
1138            try {
1139                userId = ActivityManagerNative.getDefault().handleIncomingUser(
1140                        Binder.getCallingPid(), callingUid, userId, false, true,
1141                        "setAppIdle", null);
1142            } catch (RemoteException re) {
1143                return;
1144            }
1145            getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1146                    "No permission to change app idle state");
1147            final long token = Binder.clearCallingIdentity();
1148            try {
1149                PackageInfo pi = AppGlobals.getPackageManager()
1150                        .getPackageInfo(packageName, 0, userId);
1151                if (pi == null) return;
1152                UsageStatsService.this.setAppIdle(packageName, idle, userId);
1153            } catch (RemoteException re) {
1154            } finally {
1155                Binder.restoreCallingIdentity(token);
1156            }
1157        }
1158
1159        @Override
1160        public void whitelistAppTemporarily(String packageName, long duration, int userId)
1161                throws RemoteException {
1162            mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId);
1163        }
1164
1165        @Override
1166        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1167            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1168                    != PackageManager.PERMISSION_GRANTED) {
1169                pw.println("Permission Denial: can't dump UsageStats from pid="
1170                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1171                        + " without permission " + android.Manifest.permission.DUMP);
1172                return;
1173            }
1174            UsageStatsService.this.dump(args, pw);
1175        }
1176    }
1177
1178    /**
1179     * This local service implementation is primarily used by ActivityManagerService.
1180     * ActivityManagerService will call these methods holding the 'am' lock, which means we
1181     * shouldn't be doing any IO work or other long running tasks in these methods.
1182     */
1183    private final class LocalService extends UsageStatsManagerInternal {
1184
1185        @Override
1186        public void reportEvent(ComponentName component, int userId, int eventType) {
1187            if (component == null) {
1188                Slog.w(TAG, "Event reported without a component name");
1189                return;
1190            }
1191
1192            UsageEvents.Event event = new UsageEvents.Event();
1193            event.mPackage = component.getPackageName();
1194            event.mClass = component.getClassName();
1195
1196            // This will later be converted to system time.
1197            event.mTimeStamp = SystemClock.elapsedRealtime();
1198
1199            event.mEventType = eventType;
1200            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1201        }
1202
1203        @Override
1204        public void reportEvent(String packageName, int userId, int eventType) {
1205            if (packageName == null) {
1206                Slog.w(TAG, "Event reported without a package name");
1207                return;
1208            }
1209
1210            UsageEvents.Event event = new UsageEvents.Event();
1211            event.mPackage = packageName;
1212
1213            // This will later be converted to system time.
1214            event.mTimeStamp = SystemClock.elapsedRealtime();
1215
1216            event.mEventType = eventType;
1217            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1218        }
1219
1220        @Override
1221        public void reportConfigurationChange(Configuration config, int userId) {
1222            if (config == null) {
1223                Slog.w(TAG, "Configuration event reported with a null config");
1224                return;
1225            }
1226
1227            UsageEvents.Event event = new UsageEvents.Event();
1228            event.mPackage = "android";
1229
1230            // This will later be converted to system time.
1231            event.mTimeStamp = SystemClock.elapsedRealtime();
1232
1233            event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
1234            event.mConfiguration = new Configuration(config);
1235            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1236        }
1237
1238        @Override
1239        public void reportContentProviderUsage(String name, String packageName, int userId) {
1240            SomeArgs args = SomeArgs.obtain();
1241            args.arg1 = name;
1242            args.arg2 = packageName;
1243            args.arg3 = userId;
1244            mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args)
1245                    .sendToTarget();
1246        }
1247
1248        @Override
1249        public boolean isAppIdle(String packageName, int userId) {
1250            return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
1251        }
1252
1253        @Override
1254        public void prepareShutdown() {
1255            // This method *WILL* do IO work, but we must block until it is finished or else
1256            // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1257            // we are shutting down.
1258            shutdown();
1259        }
1260
1261        @Override
1262        public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1263            UsageStatsService.this.addListener(listener);
1264        }
1265
1266        @Override
1267        public void removeAppIdleStateChangeListener(
1268                AppIdleStateChangeListener listener) {
1269            UsageStatsService.this.removeListener(listener);
1270        }
1271    }
1272}
1273