UsageStatsService.java revision 06bf824628c118fbd5ad6756913d7fd63a6f4ce5
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.Context;
35import android.content.Intent;
36import android.content.IntentFilter;
37import android.content.pm.PackageInfo;
38import android.content.pm.PackageManager;
39import android.content.pm.ParceledListSlice;
40import android.content.pm.UserInfo;
41import android.content.res.Configuration;
42import android.database.ContentObserver;
43import android.hardware.display.DisplayManager;
44import android.net.Uri;
45import android.os.BatteryManager;
46import android.os.Binder;
47import android.os.Environment;
48import android.os.Handler;
49import android.os.IDeviceIdleController;
50import android.os.Looper;
51import android.os.Message;
52import android.os.Process;
53import android.os.RemoteException;
54import android.os.ServiceManager;
55import android.os.SystemClock;
56import android.os.UserHandle;
57import android.os.UserManager;
58import android.provider.Settings;
59import android.util.ArraySet;
60import android.util.AtomicFile;
61import android.util.Slog;
62import android.util.SparseArray;
63import android.view.Display;
64
65import com.android.internal.os.BackgroundThread;
66import com.android.internal.util.IndentingPrintWriter;
67import com.android.server.DeviceIdleController;
68import com.android.server.SystemService;
69
70import java.io.BufferedReader;
71import java.io.File;
72import java.io.FileDescriptor;
73import java.io.FileOutputStream;
74import java.io.FileReader;
75import java.io.IOException;
76import java.io.PrintWriter;
77import java.util.ArrayList;
78import java.util.Arrays;
79import java.util.List;
80
81/**
82 * A service that collects, aggregates, and persists application usage data.
83 * This data can be queried by apps that have been granted permission by AppOps.
84 */
85public class UsageStatsService extends SystemService implements
86        UserUsageStatsService.StatsUpdatedListener {
87
88    static final String TAG = "UsageStatsService";
89
90    static final boolean DEBUG = false;
91    private static final long TEN_SECONDS = 10 * 1000;
92    private static final long TWENTY_MINUTES = 20 * 60 * 1000;
93    private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES;
94    private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
95    static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = 2L * 24 * 60 * 60 * 1000; // 1 day
96    static final long DEFAULT_CHECK_IDLE_INTERVAL = 8 * 3600 * 1000; // 8 hours
97
98    // Handler message types.
99    static final int MSG_REPORT_EVENT = 0;
100    static final int MSG_FLUSH_TO_DISK = 1;
101    static final int MSG_REMOVE_USER = 2;
102    static final int MSG_INFORM_LISTENERS = 3;
103    static final int MSG_FORCE_IDLE_STATE = 4;
104    static final int MSG_CHECK_IDLE_STATES = 5;
105
106    private final Object mLock = new Object();
107    Handler mHandler;
108    AppOpsManager mAppOps;
109    UserManager mUserManager;
110    AppWidgetManager mAppWidgetManager;
111    IDeviceIdleController mDeviceIdleController;
112    private DisplayManager mDisplayManager;
113
114    private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
115    private File mUsageStatsDir;
116    long mRealTimeSnapshot;
117    long mSystemTimeSnapshot;
118    boolean mAppIdleParoled;
119    private boolean mScreenOn;
120
121    long mAppIdleDurationMillis;
122    long mCheckIdleIntervalMillis = DEFAULT_CHECK_IDLE_INTERVAL;
123    long mScreenOnTime;
124    long mScreenOnSystemTimeSnapshot;
125
126    private ArrayList<UsageStatsManagerInternal.AppIdleStateChangeListener>
127            mPackageAccessListeners = new ArrayList<>();
128
129    public UsageStatsService(Context context) {
130        super(context);
131    }
132
133    @Override
134    public void onStart() {
135        mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
136        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
137
138        mHandler = new H(BackgroundThread.get().getLooper());
139
140        File systemDataDir = new File(Environment.getDataDirectory(), "system");
141        mUsageStatsDir = new File(systemDataDir, "usagestats");
142        mUsageStatsDir.mkdirs();
143        if (!mUsageStatsDir.exists()) {
144            throw new IllegalStateException("Usage stats directory does not exist: "
145                    + mUsageStatsDir.getAbsolutePath());
146        }
147
148        IntentFilter userActions = new IntentFilter(Intent.ACTION_USER_REMOVED);
149        userActions.addAction(Intent.ACTION_USER_STARTED);
150        getContext().registerReceiverAsUser(new UserActionsReceiver(), UserHandle.ALL, userActions,
151                null, null);
152
153        IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
154        deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
155        getContext().registerReceiver(new DeviceStateReceiver(), deviceStates);
156        synchronized (mLock) {
157            cleanUpRemovedUsersLocked();
158        }
159
160        mRealTimeSnapshot = SystemClock.elapsedRealtime();
161        mSystemTimeSnapshot = System.currentTimeMillis();
162        // Look at primary user's secure setting for this. TODO: Maybe apply different
163        // thresholds for different users.
164        mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(),
165                Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS,
166                UserHandle.USER_OWNER);
167
168        publishLocalService(UsageStatsManagerInternal.class, new LocalService());
169        publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
170    }
171
172    @Override
173    public void onBootPhase(int phase) {
174        if (phase == PHASE_SYSTEM_SERVICES_READY) {
175            // Observe changes to the threshold
176            new SettingsObserver(mHandler).registerObserver();
177            mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
178            mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
179                    ServiceManager.getService(DeviceIdleController.SERVICE_NAME));
180            mDisplayManager = (DisplayManager) getContext().getSystemService(
181                    Context.DISPLAY_SERVICE);
182            mScreenOnSystemTimeSnapshot = System.currentTimeMillis();
183            synchronized (this) {
184                mScreenOnTime = readScreenOnTimeLocked();
185            }
186            mDisplayManager.registerDisplayListener(mDisplayListener, null);
187            synchronized (this) {
188                updateDisplayLocked();
189            }
190        } else if (phase == PHASE_BOOT_COMPLETED) {
191            setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
192        }
193    }
194
195    private class UserActionsReceiver extends BroadcastReceiver {
196
197        @Override
198        public void onReceive(Context context, Intent intent) {
199            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
200            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
201                if (userId >= 0) {
202                    mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget();
203                }
204            } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
205                if (userId >=0) {
206                    postCheckIdleStates();
207                }
208            }
209        }
210    }
211
212    private class DeviceStateReceiver extends BroadcastReceiver {
213        @Override
214        public void onReceive(Context context, Intent intent) {
215            final String action = intent.getAction();
216            if (BatteryManager.ACTION_CHARGING.equals(action)
217                    || BatteryManager.ACTION_DISCHARGING.equals(action)) {
218                setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action));
219            }
220        }
221    }
222
223    private final DisplayManager.DisplayListener mDisplayListener
224            = new DisplayManager.DisplayListener() {
225
226        @Override public void onDisplayAdded(int displayId) {
227        }
228
229        @Override public void onDisplayRemoved(int displayId) {
230        }
231
232        @Override public void onDisplayChanged(int displayId) {
233            if (displayId == Display.DEFAULT_DISPLAY) {
234                synchronized (UsageStatsService.this.mLock) {
235                    updateDisplayLocked();
236                }
237            }
238        }
239    };
240
241    @Override
242    public void onStatsUpdated() {
243        mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL);
244    }
245
246    private void cleanUpRemovedUsersLocked() {
247        final List<UserInfo> users = mUserManager.getUsers(true);
248        if (users == null || users.size() == 0) {
249            throw new IllegalStateException("There can't be no users");
250        }
251
252        ArraySet<String> toDelete = new ArraySet<>();
253        String[] fileNames = mUsageStatsDir.list();
254        if (fileNames == null) {
255            // No users to delete.
256            return;
257        }
258
259        toDelete.addAll(Arrays.asList(fileNames));
260
261        final int userCount = users.size();
262        for (int i = 0; i < userCount; i++) {
263            final UserInfo userInfo = users.get(i);
264            toDelete.remove(Integer.toString(userInfo.id));
265        }
266
267        final int deleteCount = toDelete.size();
268        for (int i = 0; i < deleteCount; i++) {
269            deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i)));
270        }
271    }
272
273    void setAppIdleParoled(boolean paroled) {
274        synchronized (mLock) {
275            if (mAppIdleParoled != paroled) {
276                mAppIdleParoled = paroled;
277                postCheckIdleStates();
278            }
279        }
280    }
281
282    void postCheckIdleStates() {
283        mHandler.removeMessages(MSG_CHECK_IDLE_STATES);
284        mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES);
285    }
286
287    /** Check all running users' apps to see if they enter an idle state. */
288    void checkIdleStates() {
289        final int[] runningUsers;
290        try {
291            runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
292        } catch (RemoteException re) {
293            return;
294        }
295
296        for (int i = 0; i < runningUsers.length; i++) {
297            final int userId = runningUsers[i];
298            List<PackageInfo> packages =
299                    getContext().getPackageManager().getInstalledPackages(
300                            PackageManager.GET_DISABLED_COMPONENTS
301                                | PackageManager.GET_UNINSTALLED_PACKAGES,
302                            userId);
303            synchronized (mLock) {
304                final int packageCount = packages.size();
305                for (int p = 0; p < packageCount; p++) {
306                    final String packageName = packages.get(p).packageName;
307                    final boolean isIdle = isAppIdleFiltered(packageName, userId);
308                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
309                            userId, isIdle ? 1 : 0, packageName));
310                }
311            }
312        }
313        mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis);
314    }
315
316    void updateDisplayLocked() {
317        boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
318                != Display.STATE_OFF;
319        if (screenOn == mScreenOn) return;
320
321        mScreenOn = screenOn;
322        long now = System.currentTimeMillis();
323        if (mScreenOn) {
324            mScreenOnSystemTimeSnapshot = now;
325        } else {
326            mScreenOnTime += now - mScreenOnSystemTimeSnapshot;
327            writeScreenOnTimeLocked(mScreenOnTime);
328        }
329    }
330
331    private long getScreenOnTimeLocked(long now) {
332        if (mScreenOn) {
333            return now - mScreenOnSystemTimeSnapshot + mScreenOnTime;
334        } else {
335            return mScreenOnTime;
336        }
337    }
338
339    private File getScreenOnTimeFile() {
340        return new File(mUsageStatsDir, UserHandle.USER_OWNER + "/screen_on_time");
341    }
342
343    private long readScreenOnTimeLocked() {
344        long screenOnTime = 0;
345        File screenOnTimeFile = getScreenOnTimeFile();
346        if (screenOnTimeFile.exists()) {
347            try {
348                BufferedReader reader = new BufferedReader(new FileReader(screenOnTimeFile));
349                screenOnTime = Long.parseLong(reader.readLine());
350                reader.close();
351            } catch (IOException | NumberFormatException e) {
352            }
353        } else {
354            writeScreenOnTimeLocked(screenOnTime);
355        }
356        return screenOnTime;
357    }
358
359    private void writeScreenOnTimeLocked(long screenOnTime) {
360        AtomicFile screenOnTimeFile = new AtomicFile(getScreenOnTimeFile());
361        FileOutputStream fos = null;
362        try {
363            fos = screenOnTimeFile.startWrite();
364            fos.write(Long.toString(screenOnTime).getBytes());
365            screenOnTimeFile.finishWrite(fos);
366        } catch (IOException ioe) {
367            screenOnTimeFile.failWrite(fos);
368        }
369    }
370
371    private static void deleteRecursively(File f) {
372        File[] files = f.listFiles();
373        if (files != null) {
374            for (File subFile : files) {
375                deleteRecursively(subFile);
376            }
377        }
378
379        if (!f.delete()) {
380            Slog.e(TAG, "Failed to delete " + f);
381        }
382    }
383
384    private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
385            long currentTimeMillis) {
386        UserUsageStatsService service = mUserState.get(userId);
387        if (service == null) {
388            service = new UserUsageStatsService(getContext(), userId,
389                    new File(mUsageStatsDir, Integer.toString(userId)), this);
390            service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
391            mUserState.put(userId, service);
392        }
393        return service;
394    }
395
396    /**
397     * This should be the only way to get the time from the system.
398     */
399    private long checkAndGetTimeLocked() {
400        final long actualSystemTime = System.currentTimeMillis();
401        final long actualRealtime = SystemClock.elapsedRealtime();
402        final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
403        if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
404            // The time has changed.
405            final int userCount = mUserState.size();
406            for (int i = 0; i < userCount; i++) {
407                final UserUsageStatsService service = mUserState.valueAt(i);
408                service.onTimeChanged(expectedSystemTime, actualSystemTime);
409            }
410            mRealTimeSnapshot = actualRealtime;
411            mSystemTimeSnapshot = actualSystemTime;
412        }
413        return actualSystemTime;
414    }
415
416    /**
417     * Assuming the event's timestamp is measured in milliseconds since boot,
418     * convert it to a system wall time.
419     */
420    private void convertToSystemTimeLocked(UsageEvents.Event event) {
421        event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
422    }
423
424    /**
425     * Called by the Binder stub
426     */
427    void shutdown() {
428        synchronized (mLock) {
429            mHandler.removeMessages(MSG_REPORT_EVENT);
430            flushToDiskLocked();
431        }
432    }
433
434    /**
435     * Called by the Binder stub.
436     */
437    void reportEvent(UsageEvents.Event event, int userId) {
438        synchronized (mLock) {
439            final long timeNow = checkAndGetTimeLocked();
440            convertToSystemTimeLocked(event);
441
442            final UserUsageStatsService service =
443                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
444            final long lastUsed = service.getBeginIdleTime(event.mPackage);
445            final long screenOnTime = getScreenOnTimeLocked(timeNow);
446            final boolean previouslyIdle = hasPassedIdleTimeout(lastUsed, screenOnTime);
447            service.reportEvent(event, screenOnTime);
448            // Inform listeners if necessary
449            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
450                    || event.mEventType == Event.MOVE_TO_BACKGROUND
451                    || event.mEventType == Event.INTERACTION)) {
452                if (previouslyIdle) {
453                    // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
454                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
455                            /* idle = */ 0, event.mPackage));
456                }
457            }
458        }
459    }
460
461    /**
462     * Forces the app's beginIdleTime to reflect idle or active. If idle, then it rolls back the
463     * beginIdleTime to a point in time thats behind the threshold for idle.
464     */
465    void forceIdleState(String packageName, int userId, boolean idle) {
466        synchronized (mLock) {
467            final long timeNow = checkAndGetTimeLocked();
468            final long screenOnTime = getScreenOnTimeLocked(timeNow);
469            final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
470
471            final UserUsageStatsService service =
472                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
473            final long lastUsed = service.getBeginIdleTime(packageName);
474            final boolean previouslyIdle = hasPassedIdleTimeout(lastUsed,
475                    getScreenOnTimeLocked(timeNow));
476            service.setBeginIdleTime(packageName, deviceUsageTime);
477            // Inform listeners if necessary
478            if (previouslyIdle != idle) {
479                // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
480                mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
481                        /* idle = */ idle ? 1 : 0, packageName));
482            }
483        }
484    }
485
486    /**
487     * Called by the Binder stub.
488     */
489    void flushToDisk() {
490        synchronized (mLock) {
491            flushToDiskLocked();
492        }
493    }
494
495    /**
496     * Called by the Binder stub.
497     */
498    void removeUser(int userId) {
499        synchronized (mLock) {
500            Slog.i(TAG, "Removing user " + userId + " and all data.");
501            mUserState.remove(userId);
502            cleanUpRemovedUsersLocked();
503        }
504    }
505
506    /**
507     * Called by the Binder stub.
508     */
509    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
510        synchronized (mLock) {
511            final long timeNow = checkAndGetTimeLocked();
512            if (!validRange(timeNow, beginTime, endTime)) {
513                return null;
514            }
515
516            final UserUsageStatsService service =
517                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
518            return service.queryUsageStats(bucketType, beginTime, endTime);
519        }
520    }
521
522    /**
523     * Called by the Binder stub.
524     */
525    List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
526            long endTime) {
527        synchronized (mLock) {
528            final long timeNow = checkAndGetTimeLocked();
529            if (!validRange(timeNow, beginTime, endTime)) {
530                return null;
531            }
532
533            final UserUsageStatsService service =
534                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
535            return service.queryConfigurationStats(bucketType, beginTime, endTime);
536        }
537    }
538
539    /**
540     * Called by the Binder stub.
541     */
542    UsageEvents queryEvents(int userId, long beginTime, long endTime) {
543        synchronized (mLock) {
544            final long timeNow = checkAndGetTimeLocked();
545            if (!validRange(timeNow, beginTime, endTime)) {
546                return null;
547            }
548
549            final UserUsageStatsService service =
550                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
551            return service.queryEvents(beginTime, endTime);
552        }
553    }
554
555    private boolean isAppIdleUnfiltered(String packageName, int userId) {
556        synchronized (mLock) {
557            final long timeNow = checkAndGetTimeLocked();
558            final UserUsageStatsService service =
559                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
560            long beginIdleTime = service.getBeginIdleTime(packageName);
561            return hasPassedIdleTimeout(beginIdleTime, getScreenOnTimeLocked(timeNow));
562        }
563    }
564
565    /**
566     * @param timestamp when the app was last used in device usage timebase
567     * @param currentTime current time in device usage timebase
568     * @return whether it's been used far enough in the past to be considered inactive
569     */
570    boolean hasPassedIdleTimeout(long timestamp, long currentTime) {
571        return timestamp <= currentTime - mAppIdleDurationMillis;
572    }
573
574    void addListener(AppIdleStateChangeListener listener) {
575        synchronized (mLock) {
576            if (!mPackageAccessListeners.contains(listener)) {
577                mPackageAccessListeners.add(listener);
578            }
579        }
580    }
581
582    void removeListener(AppIdleStateChangeListener listener) {
583        synchronized (mLock) {
584            mPackageAccessListeners.remove(listener);
585        }
586    }
587
588    /**
589     * Checks if an app has been idle for a while and filters out apps that are excluded.
590     * It returns false if the current system state allows all apps to be considered active.
591     * This happens if the device is plugged in or temporarily allowed to make exceptions.
592     * Called by interface impls.
593     */
594    boolean isAppIdleFiltered(String packageName, int userId) {
595        if (packageName == null) return false;
596        synchronized (mLock) {
597            // Temporary exemption, probably due to device charging or occasional allowance to
598            // be allowed to sync, etc.
599            if (mAppIdleParoled) {
600                return false;
601            }
602        }
603        if (packageName.equals("android")) return false;
604        try {
605            if (mDeviceIdleController.isPowerSaveWhitelistApp(packageName)) {
606                return false;
607            }
608        } catch (RemoteException re) {
609        }
610        // TODO: Optimize this check
611        if (isActiveDeviceAdmin(packageName, userId)) {
612            return false;
613        }
614
615        if (mAppWidgetManager != null
616                && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
617            return false;
618        }
619
620        return isAppIdleUnfiltered(packageName, userId);
621    }
622
623    void setAppIdle(String packageName, boolean idle, int userId) {
624        if (packageName == null) return;
625
626        mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
627                .sendToTarget();
628    }
629
630    private boolean isActiveDeviceAdmin(String packageName, int userId) {
631        DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
632        if (dpm == null) return false;
633        List<ComponentName> components = dpm.getActiveAdminsAsUser(userId);
634        if (components == null) return false;
635        final int size = components.size();
636        for (int i = 0; i < size; i++) {
637            if (components.get(i).getPackageName().equals(packageName)) {
638                return true;
639            }
640        }
641        return false;
642    }
643
644    void informListeners(String packageName, int userId, boolean isIdle) {
645        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
646            listener.onAppIdleStateChanged(packageName, userId, isIdle);
647        }
648    }
649
650    private static boolean validRange(long currentTime, long beginTime, long endTime) {
651        return beginTime <= currentTime && beginTime < endTime;
652    }
653
654    private void flushToDiskLocked() {
655        final int userCount = mUserState.size();
656        for (int i = 0; i < userCount; i++) {
657            UserUsageStatsService service = mUserState.valueAt(i);
658            service.persistActiveStats();
659        }
660
661        mHandler.removeMessages(MSG_FLUSH_TO_DISK);
662    }
663
664    /**
665     * Called by the Binder stub.
666     */
667    void dump(String[] args, PrintWriter pw) {
668        synchronized (mLock) {
669            final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
670            IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
671            ArraySet<String> argSet = new ArraySet<>();
672            argSet.addAll(Arrays.asList(args));
673
674            final int userCount = mUserState.size();
675            for (int i = 0; i < userCount; i++) {
676                idpw.printPair("user", mUserState.keyAt(i));
677                idpw.println();
678                idpw.increaseIndent();
679                if (argSet.contains("--checkin")) {
680                    mUserState.valueAt(i).checkin(idpw, screenOnTime);
681                } else {
682                    mUserState.valueAt(i).dump(idpw, screenOnTime);
683                }
684                idpw.decreaseIndent();
685            }
686            pw.write("Screen On Timestamp:" + mScreenOnTime + "\n");
687        }
688    }
689
690    class H extends Handler {
691        public H(Looper looper) {
692            super(looper);
693        }
694
695        @Override
696        public void handleMessage(Message msg) {
697            switch (msg.what) {
698                case MSG_REPORT_EVENT:
699                    reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
700                    break;
701
702                case MSG_FLUSH_TO_DISK:
703                    flushToDisk();
704                    break;
705
706                case MSG_REMOVE_USER:
707                    removeUser(msg.arg1);
708                    break;
709
710                case MSG_INFORM_LISTENERS:
711                    informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
712                    break;
713
714                case MSG_FORCE_IDLE_STATE:
715                    forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
716                    break;
717
718                case MSG_CHECK_IDLE_STATES:
719                    checkIdleStates();
720                    break;
721                default:
722                    super.handleMessage(msg);
723                    break;
724            }
725        }
726    }
727
728    /**
729     * Observe settings changes for Settings.Secure.APP_IDLE_DURATION.
730     */
731    private class SettingsObserver extends ContentObserver {
732
733        SettingsObserver(Handler handler) {
734            super(handler);
735        }
736
737        void registerObserver() {
738            getContext().getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
739                    Settings.Secure.APP_IDLE_DURATION), false, this, UserHandle.USER_OWNER);
740        }
741
742        @Override
743        public void onChange(boolean selfChange, Uri uri, int userId) {
744            mAppIdleDurationMillis = Settings.Secure.getLongForUser(getContext().getContentResolver(),
745                    Settings.Secure.APP_IDLE_DURATION, DEFAULT_APP_IDLE_THRESHOLD_MILLIS,
746                    UserHandle.USER_OWNER);
747            mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL,
748                    mAppIdleDurationMillis / 4);
749            postCheckIdleStates();
750        }
751    }
752
753    private class BinderService extends IUsageStatsManager.Stub {
754
755        private boolean hasPermission(String callingPackage) {
756            final int callingUid = Binder.getCallingUid();
757            if (callingUid == Process.SYSTEM_UID) {
758                return true;
759            }
760            final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
761                    callingUid, callingPackage);
762            if (mode == AppOpsManager.MODE_DEFAULT) {
763                // The default behavior here is to check if PackageManager has given the app
764                // permission.
765                return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
766                        == PackageManager.PERMISSION_GRANTED;
767            }
768            return mode == AppOpsManager.MODE_ALLOWED;
769        }
770
771        @Override
772        public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
773                long endTime, String callingPackage) {
774            if (!hasPermission(callingPackage)) {
775                return null;
776            }
777
778            final int userId = UserHandle.getCallingUserId();
779            final long token = Binder.clearCallingIdentity();
780            try {
781                final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
782                        userId, bucketType, beginTime, endTime);
783                if (results != null) {
784                    return new ParceledListSlice<>(results);
785                }
786            } finally {
787                Binder.restoreCallingIdentity(token);
788            }
789            return null;
790        }
791
792        @Override
793        public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
794                long beginTime, long endTime, String callingPackage) throws RemoteException {
795            if (!hasPermission(callingPackage)) {
796                return null;
797            }
798
799            final int userId = UserHandle.getCallingUserId();
800            final long token = Binder.clearCallingIdentity();
801            try {
802                final List<ConfigurationStats> results =
803                        UsageStatsService.this.queryConfigurationStats(userId, bucketType,
804                                beginTime, endTime);
805                if (results != null) {
806                    return new ParceledListSlice<>(results);
807                }
808            } finally {
809                Binder.restoreCallingIdentity(token);
810            }
811            return null;
812        }
813
814        @Override
815        public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
816            if (!hasPermission(callingPackage)) {
817                return null;
818            }
819
820            final int userId = UserHandle.getCallingUserId();
821            final long token = Binder.clearCallingIdentity();
822            try {
823                return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
824            } finally {
825                Binder.restoreCallingIdentity(token);
826            }
827        }
828
829        @Override
830        public boolean isAppInactive(String packageName, int userId) {
831            try {
832                userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
833                        Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
834            } catch (RemoteException re) {
835                return false;
836            }
837            final long token = Binder.clearCallingIdentity();
838            try {
839                return UsageStatsService.this.isAppIdleFiltered(packageName, userId);
840            } finally {
841                Binder.restoreCallingIdentity(token);
842            }
843        }
844
845        @Override
846        public void setAppInactive(String packageName, boolean idle, int userId) {
847            final int callingUid = Binder.getCallingUid();
848            try {
849                userId = ActivityManagerNative.getDefault().handleIncomingUser(
850                        Binder.getCallingPid(), callingUid, userId, false, true,
851                        "setAppIdle", null);
852            } catch (RemoteException re) {
853                return;
854            }
855            getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
856                    "No permission to change app idle state");
857            final long token = Binder.clearCallingIdentity();
858            try {
859                PackageInfo pi = AppGlobals.getPackageManager()
860                        .getPackageInfo(packageName, 0, userId);
861                if (pi == null) return;
862                UsageStatsService.this.setAppIdle(packageName, idle, userId);
863            } catch (RemoteException re) {
864            } finally {
865                Binder.restoreCallingIdentity(token);
866            }
867        }
868
869        @Override
870        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
871            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
872                    != PackageManager.PERMISSION_GRANTED) {
873                pw.println("Permission Denial: can't dump UsageStats from pid="
874                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
875                        + " without permission " + android.Manifest.permission.DUMP);
876                return;
877            }
878            UsageStatsService.this.dump(args, pw);
879        }
880    }
881
882    /**
883     * This local service implementation is primarily used by ActivityManagerService.
884     * ActivityManagerService will call these methods holding the 'am' lock, which means we
885     * shouldn't be doing any IO work or other long running tasks in these methods.
886     */
887    private class LocalService extends UsageStatsManagerInternal {
888
889        @Override
890        public void reportEvent(ComponentName component, int userId, int eventType) {
891            if (component == null) {
892                Slog.w(TAG, "Event reported without a component name");
893                return;
894            }
895
896            UsageEvents.Event event = new UsageEvents.Event();
897            event.mPackage = component.getPackageName();
898            event.mClass = component.getClassName();
899
900            // This will later be converted to system time.
901            event.mTimeStamp = SystemClock.elapsedRealtime();
902
903            event.mEventType = eventType;
904            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
905        }
906
907        @Override
908        public void reportEvent(String packageName, int userId, int eventType) {
909            if (packageName == null) {
910                Slog.w(TAG, "Event reported without a package name");
911                return;
912            }
913
914            UsageEvents.Event event = new UsageEvents.Event();
915            event.mPackage = packageName;
916
917            // This will later be converted to system time.
918            event.mTimeStamp = SystemClock.elapsedRealtime();
919
920            event.mEventType = eventType;
921            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
922        }
923
924        @Override
925        public void reportConfigurationChange(Configuration config, int userId) {
926            if (config == null) {
927                Slog.w(TAG, "Configuration event reported with a null config");
928                return;
929            }
930
931            UsageEvents.Event event = new UsageEvents.Event();
932            event.mPackage = "android";
933
934            // This will later be converted to system time.
935            event.mTimeStamp = SystemClock.elapsedRealtime();
936
937            event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
938            event.mConfiguration = new Configuration(config);
939            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
940        }
941
942        @Override
943        public boolean isAppIdle(String packageName, int userId) {
944            return UsageStatsService.this.isAppIdleFiltered(packageName, userId);
945        }
946
947        @Override
948        public void prepareShutdown() {
949            // This method *WILL* do IO work, but we must block until it is finished or else
950            // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
951            // we are shutting down.
952            shutdown();
953        }
954
955        @Override
956        public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
957            UsageStatsService.this.addListener(listener);
958        }
959
960        @Override
961        public void removeAppIdleStateChangeListener(
962                AppIdleStateChangeListener listener) {
963            UsageStatsService.this.removeListener(listener);
964        }
965    }
966}
967