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