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                    mLastAppIdleParoledTime = checkAndGetTimeLocked();
318                    postNextParoleTimeout();
319                }
320                postParoleStateChanged();
321            }
322        }
323    }
324
325    private void postNextParoleTimeout() {
326        if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
327        mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
328        // Compute when the next parole needs to happen. We check more frequently than necessary
329        // since the message handler delays are based on elapsedRealTime and not wallclock time.
330        // The comparison is done in wallclock time.
331        long timeLeft = (mLastAppIdleParoledTime + mAppIdleParoleIntervalMillis)
332                - checkAndGetTimeLocked();
333        if (timeLeft < 0) {
334            timeLeft = 0;
335        }
336        mHandler.sendEmptyMessageDelayed(MSG_CHECK_PAROLE_TIMEOUT, timeLeft / 10);
337    }
338
339    private void postParoleEndTimeout() {
340        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_END_TIMEOUT");
341        mHandler.removeMessages(MSG_PAROLE_END_TIMEOUT);
342        mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, mAppIdleParoleDurationMillis);
343    }
344
345    private void postParoleStateChanged() {
346        if (DEBUG) Slog.d(TAG, "Posting MSG_PAROLE_STATE_CHANGED");
347        mHandler.removeMessages(MSG_PAROLE_STATE_CHANGED);
348        mHandler.sendEmptyMessage(MSG_PAROLE_STATE_CHANGED);
349    }
350
351    void postCheckIdleStates(int userId) {
352        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
353    }
354
355    /** Check all running users' or specified user's apps to see if they enter an idle state. */
356    void checkIdleStates(int checkUserId) {
357        if (!mAppIdleEnabled) {
358            return;
359        }
360
361        final int[] userIds;
362        try {
363            if (checkUserId == UserHandle.USER_ALL) {
364                userIds = ActivityManagerNative.getDefault().getRunningUserIds();
365            } else {
366                userIds = new int[] { checkUserId };
367            }
368        } catch (RemoteException re) {
369            return;
370        }
371
372        for (int i = 0; i < userIds.length; i++) {
373            final int userId = userIds[i];
374            List<PackageInfo> packages =
375                    getContext().getPackageManager().getInstalledPackages(
376                            PackageManager.GET_DISABLED_COMPONENTS
377                                | PackageManager.GET_UNINSTALLED_PACKAGES,
378                            userId);
379            synchronized (mLock) {
380                final long timeNow = checkAndGetTimeLocked();
381                final long screenOnTime = getScreenOnTimeLocked(timeNow);
382                UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
383                        timeNow);
384                final int packageCount = packages.size();
385                for (int p = 0; p < packageCount; p++) {
386                    final String packageName = packages.get(p).packageName;
387                    final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow,
388                            screenOnTime);
389                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
390                            userId, isIdle ? 1 : 0, packageName));
391                    mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
392                }
393            }
394        }
395        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
396                mCheckIdleIntervalMillis);
397    }
398
399    /** Check if it's been a while since last parole and let idle apps do some work */
400    void checkParoleTimeout() {
401        synchronized (mLock) {
402            if (!mAppIdleParoled) {
403                final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
404                if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
405                    if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
406                    setAppIdleParoled(true);
407                    // Make sure it ends at some point
408                    postParoleEndTimeout();
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                postNextParoleTimeout();
496                setAppIdleParoled(true);
497            } else if (deviceIdle) {
498                if (DEBUG) Slog.i(TAG, "Device idle, back to prison");
499                setAppIdleParoled(false);
500            }
501        }
502    }
503
504    private static void deleteRecursively(File f) {
505        File[] files = f.listFiles();
506        if (files != null) {
507            for (File subFile : files) {
508                deleteRecursively(subFile);
509            }
510        }
511
512        if (!f.delete()) {
513            Slog.e(TAG, "Failed to delete " + f);
514        }
515    }
516
517    private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId,
518            long currentTimeMillis) {
519        UserUsageStatsService service = mUserState.get(userId);
520        if (service == null) {
521            service = new UserUsageStatsService(getContext(), userId,
522                    new File(mUsageStatsDir, Integer.toString(userId)), this);
523            service.init(currentTimeMillis, getScreenOnTimeLocked(currentTimeMillis));
524            mUserState.put(userId, service);
525        }
526        return service;
527    }
528
529    /**
530     * This should be the only way to get the time from the system.
531     */
532    private long checkAndGetTimeLocked() {
533        final long actualSystemTime = System.currentTimeMillis();
534        final long actualRealtime = SystemClock.elapsedRealtime();
535        final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
536        boolean resetBeginIdleTime = false;
537        if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) {
538            // The time has changed.
539
540            // Check if it's severe enough a change to reset screenOnTime
541            if (Math.abs(actualSystemTime - expectedSystemTime) > mAppIdleDurationMillis) {
542                mScreenOnSystemTimeSnapshot = actualSystemTime;
543                mScreenOnTime = 0;
544                resetBeginIdleTime = true;
545            }
546            final int userCount = mUserState.size();
547            for (int i = 0; i < userCount; i++) {
548                final UserUsageStatsService service = mUserState.valueAt(i);
549                service.onTimeChanged(expectedSystemTime, actualSystemTime, resetBeginIdleTime);
550            }
551            mRealTimeSnapshot = actualRealtime;
552            mSystemTimeSnapshot = actualSystemTime;
553        }
554        return actualSystemTime;
555    }
556
557    /**
558     * Assuming the event's timestamp is measured in milliseconds since boot,
559     * convert it to a system wall time.
560     */
561    private void convertToSystemTimeLocked(UsageEvents.Event event) {
562        event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
563    }
564
565    /**
566     * Called by the Binder stub
567     */
568    void shutdown() {
569        synchronized (mLock) {
570            mHandler.removeMessages(MSG_REPORT_EVENT);
571            flushToDiskLocked();
572        }
573    }
574
575    /**
576     * Called by the Binder stub.
577     */
578    void reportEvent(UsageEvents.Event event, int userId) {
579        synchronized (mLock) {
580            final long timeNow = checkAndGetTimeLocked();
581            final long screenOnTime = getScreenOnTimeLocked(timeNow);
582            convertToSystemTimeLocked(event);
583
584            final UserUsageStatsService service =
585                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
586            final long beginIdleTime = service.getBeginIdleTime(event.mPackage);
587            final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
588            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
589                    lastUsedTime, screenOnTime, timeNow);
590            service.reportEvent(event, screenOnTime);
591            // Inform listeners if necessary
592            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
593                    || event.mEventType == Event.MOVE_TO_BACKGROUND
594                    || event.mEventType == Event.SYSTEM_INTERACTION
595                    || event.mEventType == Event.USER_INTERACTION)) {
596                if (previouslyIdle) {
597                    // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
598                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
599                            /* idle = */ 0, event.mPackage));
600                    notifyBatteryStats(event.mPackage, userId, false);
601                    mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow);
602                }
603            }
604        }
605    }
606
607    void reportContentProviderUsage(String authority, String providerPkgName, int userId) {
608        // Get sync adapters for the authority
609        String[] packages = ContentResolver.getSyncAdapterPackagesForAuthorityAsUser(
610                authority, userId);
611        for (String packageName: packages) {
612            // Only force the sync adapters to active if the provider is not in the same package and
613            // the sync adapter is a system package.
614            try {
615                PackageInfo pi = AppGlobals.getPackageManager().getPackageInfo(
616                        packageName, 0, userId);
617                if (pi == null || pi.applicationInfo == null
618                        || !pi.applicationInfo.isSystemApp()) {
619                    continue;
620                }
621                if (!packageName.equals(providerPkgName)) {
622                    forceIdleState(packageName, userId, false);
623                }
624            } catch (RemoteException re) {
625                // Shouldn't happen
626            }
627        }
628    }
629
630    /**
631     * Forces the app's beginIdleTime and lastUsedTime to reflect idle or active. If idle,
632     * then it rolls back the beginIdleTime and lastUsedTime to a point in time that's behind
633     * the threshold for idle.
634     */
635    void forceIdleState(String packageName, int userId, boolean idle) {
636        synchronized (mLock) {
637            final long timeNow = checkAndGetTimeLocked();
638            final long screenOnTime = getScreenOnTimeLocked(timeNow);
639            final long deviceUsageTime = screenOnTime - (idle ? mAppIdleDurationMillis : 0) - 5000;
640
641            final UserUsageStatsService service =
642                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
643            final long beginIdleTime = service.getBeginIdleTime(packageName);
644            final long lastUsedTime = service.getSystemLastUsedTime(packageName);
645            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
646                    lastUsedTime, screenOnTime, timeNow);
647            service.setBeginIdleTime(packageName, deviceUsageTime);
648            service.setSystemLastUsedTime(packageName,
649                    timeNow - (idle ? mAppIdleWallclockThresholdMillis : 0) - 5000);
650            // Inform listeners if necessary
651            if (previouslyIdle != idle) {
652                // Slog.d(TAG, "Informing listeners of out-of-idle " + packageName);
653                mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
654                        /* idle = */ idle ? 1 : 0, packageName));
655                if (!idle) {
656                    notifyBatteryStats(packageName, userId, idle);
657                }
658                mAppIdleHistory.addEntry(packageName, userId, idle, timeNow);
659            }
660        }
661    }
662
663    /**
664     * Called by the Binder stub.
665     */
666    void flushToDisk() {
667        synchronized (mLock) {
668            flushToDiskLocked();
669        }
670    }
671
672    /**
673     * Called by the Binder stub.
674     */
675    void removeUser(int userId) {
676        synchronized (mLock) {
677            Slog.i(TAG, "Removing user " + userId + " and all data.");
678            mUserState.remove(userId);
679            cleanUpRemovedUsersLocked();
680        }
681    }
682
683    /**
684     * Called by the Binder stub.
685     */
686    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
687        synchronized (mLock) {
688            final long timeNow = checkAndGetTimeLocked();
689            if (!validRange(timeNow, beginTime, endTime)) {
690                return null;
691            }
692
693            final UserUsageStatsService service =
694                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
695            return service.queryUsageStats(bucketType, beginTime, endTime);
696        }
697    }
698
699    /**
700     * Called by the Binder stub.
701     */
702    List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime,
703            long endTime) {
704        synchronized (mLock) {
705            final long timeNow = checkAndGetTimeLocked();
706            if (!validRange(timeNow, beginTime, endTime)) {
707                return null;
708            }
709
710            final UserUsageStatsService service =
711                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
712            return service.queryConfigurationStats(bucketType, beginTime, endTime);
713        }
714    }
715
716    /**
717     * Called by the Binder stub.
718     */
719    UsageEvents queryEvents(int userId, long beginTime, long endTime) {
720        synchronized (mLock) {
721            final long timeNow = checkAndGetTimeLocked();
722            if (!validRange(timeNow, beginTime, endTime)) {
723                return null;
724            }
725
726            final UserUsageStatsService service =
727                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
728            return service.queryEvents(beginTime, endTime);
729        }
730    }
731
732    private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService,
733            long timeNow, long screenOnTime) {
734        synchronized (mLock) {
735            long beginIdleTime = userService.getBeginIdleTime(packageName);
736            long lastUsedTime = userService.getSystemLastUsedTime(packageName);
737            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime,
738                    timeNow);
739        }
740    }
741
742    /**
743     * @param beginIdleTime when the app was last used in device usage timebase
744     * @param lastUsedTime wallclock time of when the app was last used
745     * @param screenOnTime screen-on timebase time
746     * @param currentTime current time in device usage timebase
747     * @return whether it's been used far enough in the past to be considered inactive
748     */
749    boolean hasPassedIdleTimeoutLocked(long beginIdleTime, long lastUsedTime,
750            long screenOnTime, long currentTime) {
751        return (beginIdleTime <= screenOnTime - mAppIdleDurationMillis)
752                && (lastUsedTime <= currentTime - mAppIdleWallclockThresholdMillis);
753    }
754
755    void addListener(AppIdleStateChangeListener listener) {
756        synchronized (mLock) {
757            if (!mPackageAccessListeners.contains(listener)) {
758                mPackageAccessListeners.add(listener);
759            }
760        }
761    }
762
763    void removeListener(AppIdleStateChangeListener listener) {
764        synchronized (mLock) {
765            mPackageAccessListeners.remove(listener);
766        }
767    }
768
769    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long timeNow) {
770        if (mAppIdleParoled) {
771            return false;
772        }
773        return isAppIdleFiltered(packageName, userId, timeNow);
774    }
775
776    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
777        final UserUsageStatsService userService;
778        final long screenOnTime;
779        synchronized (mLock) {
780            if (timeNow == -1) {
781                timeNow = checkAndGetTimeLocked();
782            }
783            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
784            screenOnTime = getScreenOnTimeLocked(timeNow);
785        }
786        return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime);
787    }
788
789    /**
790     * Checks if an app has been idle for a while and filters out apps that are excluded.
791     * It returns false if the current system state allows all apps to be considered active.
792     * This happens if the device is plugged in or temporarily allowed to make exceptions.
793     * Called by interface impls.
794     */
795    private boolean isAppIdleFiltered(String packageName, int userId,
796            UserUsageStatsService userService, long timeNow, long screenOnTime) {
797        if (packageName == null) return false;
798        // If not enabled at all, of course nobody is ever idle.
799        if (!mAppIdleEnabled) {
800            return false;
801        }
802        if (packageName.equals("android")) return false;
803        try {
804            // We allow all whitelisted apps, including those that don't want to be whitelisted
805            // for idle mode, because app idle (aka app standby) is really not as big an issue
806            // for controlling who participates vs. doze mode.
807            if (mDeviceIdleController.isPowerSaveWhitelistExceptIdleApp(packageName)) {
808                return false;
809            }
810        } catch (RemoteException re) {
811        }
812        // TODO: Optimize this check
813        if (isActiveDeviceAdmin(packageName, userId)) {
814            return false;
815        }
816
817        if (isCarrierApp(packageName)) {
818            return false;
819        }
820
821        if (isActiveNetworkScorer(packageName)) {
822            return false;
823        }
824
825        if (mAppWidgetManager != null
826                && mAppWidgetManager.isBoundWidgetPackage(packageName, userId)) {
827            return false;
828        }
829
830        return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
831    }
832
833    int[] getIdleUidsForUser(int userId) {
834        if (!mAppIdleEnabled) {
835            return new int[0];
836        }
837
838        final long timeNow;
839        final UserUsageStatsService userService;
840        final long screenOnTime;
841        synchronized (mLock) {
842            timeNow = checkAndGetTimeLocked();
843            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
844            screenOnTime = getScreenOnTimeLocked(timeNow);
845        }
846
847        List<ApplicationInfo> apps;
848        try {
849            ParceledListSlice<ApplicationInfo> slice
850                    = AppGlobals.getPackageManager().getInstalledApplications(0, userId);
851            if (slice == null) {
852                return new int[0];
853            }
854            apps = slice.getList();
855        } catch (RemoteException e) {
856            return new int[0];
857        }
858
859        // State of each uid.  Key is the uid.  Value lower 16 bits is the number of apps
860        // associated with that uid, upper 16 bits is the number of those apps that is idle.
861        SparseIntArray uidStates = new SparseIntArray();
862
863        // Now resolve all app state.  Iterating over all apps, keeping track of how many
864        // we find for each uid and how many of those are idle.
865        for (int i = apps.size()-1; i >= 0; i--) {
866            ApplicationInfo ai = apps.get(i);
867
868            // Check whether this app is idle.
869            boolean idle = isAppIdleFiltered(ai.packageName, userId, userService, timeNow,
870                    screenOnTime);
871
872            int index = uidStates.indexOfKey(ai.uid);
873            if (index < 0) {
874                uidStates.put(ai.uid, 1 + (idle ? 1<<16 : 0));
875            } else {
876                int value = uidStates.valueAt(index);
877                uidStates.setValueAt(index, value + 1 + (idle ? 1<<16 : 0));
878            }
879        }
880
881        int numIdle = 0;
882        for (int i = uidStates.size() - 1; i >= 0; i--) {
883            int value = uidStates.valueAt(i);
884            if ((value&0x7fff) == (value>>16)) {
885                numIdle++;
886            }
887        }
888
889        int[] res = new int[numIdle];
890        numIdle = 0;
891        for (int i = uidStates.size() - 1; i >= 0; i--) {
892            int value = uidStates.valueAt(i);
893            if ((value&0x7fff) == (value>>16)) {
894                res[numIdle] = uidStates.keyAt(i);
895                numIdle++;
896            }
897        }
898
899        return res;
900    }
901
902    void setAppIdle(String packageName, boolean idle, int userId) {
903        if (packageName == null) return;
904
905        mHandler.obtainMessage(MSG_FORCE_IDLE_STATE, userId, idle ? 1 : 0, packageName)
906                .sendToTarget();
907    }
908
909    private boolean isActiveDeviceAdmin(String packageName, int userId) {
910        DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
911        if (dpm == null) return false;
912        List<ComponentName> components = dpm.getActiveAdminsAsUser(userId);
913        if (components == null) return false;
914        final int size = components.size();
915        for (int i = 0; i < size; i++) {
916            if (components.get(i).getPackageName().equals(packageName)) {
917                return true;
918            }
919        }
920        return false;
921    }
922
923    private boolean isCarrierApp(String packageName) {
924        TelephonyManager telephonyManager = getContext().getSystemService(TelephonyManager.class);
925        return telephonyManager.checkCarrierPrivilegesForPackageAnyPhone(packageName)
926                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
927    }
928
929    private boolean isActiveNetworkScorer(String packageName) {
930        NetworkScoreManager nsm = (NetworkScoreManager) getContext().getSystemService(
931                Context.NETWORK_SCORE_SERVICE);
932        return packageName != null && packageName.equals(nsm.getActiveScorerPackage());
933    }
934
935    void informListeners(String packageName, int userId, boolean isIdle) {
936        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
937            listener.onAppIdleStateChanged(packageName, userId, isIdle);
938        }
939    }
940
941    void informParoleStateChanged() {
942        for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
943            listener.onParoleStateChanged(mAppIdleParoled);
944        }
945    }
946
947    private static boolean validRange(long currentTime, long beginTime, long endTime) {
948        return beginTime <= currentTime && beginTime < endTime;
949    }
950
951    private void flushToDiskLocked() {
952        final int userCount = mUserState.size();
953        for (int i = 0; i < userCount; i++) {
954            UserUsageStatsService service = mUserState.valueAt(i);
955            service.persistActiveStats();
956        }
957
958        mHandler.removeMessages(MSG_FLUSH_TO_DISK);
959    }
960
961    /**
962     * Called by the Binder stub.
963     */
964    void dump(String[] args, PrintWriter pw) {
965        synchronized (mLock) {
966            final long screenOnTime = getScreenOnTimeLocked(checkAndGetTimeLocked());
967            IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
968            ArraySet<String> argSet = new ArraySet<>();
969            argSet.addAll(Arrays.asList(args));
970
971            final int userCount = mUserState.size();
972            for (int i = 0; i < userCount; i++) {
973                idpw.printPair("user", mUserState.keyAt(i));
974                idpw.println();
975                idpw.increaseIndent();
976                if (argSet.contains("--checkin")) {
977                    mUserState.valueAt(i).checkin(idpw, screenOnTime);
978                } else {
979                    mUserState.valueAt(i).dump(idpw, screenOnTime);
980                    idpw.println();
981                    if (args.length > 0 && "history".equals(args[0])) {
982                        mAppIdleHistory.dump(idpw, mUserState.keyAt(i));
983                    }
984                }
985                idpw.decreaseIndent();
986            }
987            pw.println("Screen On Timebase:" + mScreenOnTime);
988
989            pw.println();
990            pw.println("Settings:");
991
992            pw.print("  mAppIdleDurationMillis=");
993            TimeUtils.formatDuration(mAppIdleDurationMillis, pw);
994            pw.println();
995
996            pw.print("  mAppIdleWallclockThresholdMillis=");
997            TimeUtils.formatDuration(mAppIdleWallclockThresholdMillis, pw);
998            pw.println();
999
1000            pw.print("  mCheckIdleIntervalMillis=");
1001            TimeUtils.formatDuration(mCheckIdleIntervalMillis, pw);
1002            pw.println();
1003
1004            pw.print("  mAppIdleParoleIntervalMillis=");
1005            TimeUtils.formatDuration(mAppIdleParoleIntervalMillis, pw);
1006            pw.println();
1007
1008            pw.print("  mAppIdleParoleDurationMillis=");
1009            TimeUtils.formatDuration(mAppIdleParoleDurationMillis, pw);
1010            pw.println();
1011
1012            pw.println();
1013            pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
1014            pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled);
1015            pw.print(" mScreenOn="); pw.println(mScreenOn);
1016            pw.print("mLastAppIdleParoledTime=");
1017            TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
1018            pw.println();
1019            pw.print("mScreenOnTime="); TimeUtils.formatDuration(mScreenOnTime, pw);
1020            pw.println();
1021            pw.print("mScreenOnSystemTimeSnapshot=");
1022            TimeUtils.formatDuration(mScreenOnSystemTimeSnapshot, pw);
1023            pw.println();
1024        }
1025    }
1026
1027    class H extends Handler {
1028        public H(Looper looper) {
1029            super(looper);
1030        }
1031
1032        @Override
1033        public void handleMessage(Message msg) {
1034            switch (msg.what) {
1035                case MSG_REPORT_EVENT:
1036                    reportEvent((UsageEvents.Event) msg.obj, msg.arg1);
1037                    break;
1038
1039                case MSG_FLUSH_TO_DISK:
1040                    flushToDisk();
1041                    break;
1042
1043                case MSG_REMOVE_USER:
1044                    removeUser(msg.arg1);
1045                    break;
1046
1047                case MSG_INFORM_LISTENERS:
1048                    informListeners((String) msg.obj, msg.arg1, msg.arg2 == 1);
1049                    break;
1050
1051                case MSG_FORCE_IDLE_STATE:
1052                    forceIdleState((String) msg.obj, msg.arg1, msg.arg2 == 1);
1053                    break;
1054
1055                case MSG_CHECK_IDLE_STATES:
1056                    checkIdleStates(msg.arg1);
1057                    break;
1058
1059                case MSG_CHECK_PAROLE_TIMEOUT:
1060                    checkParoleTimeout();
1061                    break;
1062
1063                case MSG_PAROLE_END_TIMEOUT:
1064                    if (DEBUG) Slog.d(TAG, "Ending parole");
1065                    setAppIdleParoled(false);
1066                    break;
1067
1068                case MSG_REPORT_CONTENT_PROVIDER_USAGE:
1069                    SomeArgs args = (SomeArgs) msg.obj;
1070                    reportContentProviderUsage((String) args.arg1, // authority name
1071                            (String) args.arg2, // package name
1072                            (int) args.arg3); // userId
1073                    args.recycle();
1074                    break;
1075
1076                case MSG_PAROLE_STATE_CHANGED:
1077                    if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
1078                    informParoleStateChanged();
1079                    break;
1080
1081                default:
1082                    super.handleMessage(msg);
1083                    break;
1084            }
1085        }
1086    }
1087
1088    /**
1089     * Observe settings changes for {@link Settings.Global#APP_IDLE_CONSTANTS}.
1090     */
1091    private class SettingsObserver extends ContentObserver {
1092        private static final String KEY_IDLE_DURATION = "idle_duration";
1093        private static final String KEY_WALLCLOCK_THRESHOLD = "wallclock_threshold";
1094        private static final String KEY_PAROLE_INTERVAL = "parole_interval";
1095        private static final String KEY_PAROLE_DURATION = "parole_duration";
1096
1097        private final KeyValueListParser mParser = new KeyValueListParser(',');
1098
1099        SettingsObserver(Handler handler) {
1100            super(handler);
1101        }
1102
1103        void registerObserver() {
1104            getContext().getContentResolver().registerContentObserver(Settings.Global.getUriFor(
1105                    Settings.Global.APP_IDLE_CONSTANTS), false, this);
1106        }
1107
1108        @Override
1109        public void onChange(boolean selfChange) {
1110            updateSettings();
1111            postCheckIdleStates(UserHandle.USER_ALL);
1112        }
1113
1114        void updateSettings() {
1115            synchronized (mLock) {
1116                // Look at global settings for this.
1117                // TODO: Maybe apply different thresholds for different users.
1118                try {
1119                    mParser.setString(Settings.Global.getString(getContext().getContentResolver(),
1120                            Settings.Global.APP_IDLE_CONSTANTS));
1121                } catch (IllegalArgumentException e) {
1122                    Slog.e(TAG, "Bad value for app idle settings: " + e.getMessage());
1123                    // fallthrough, mParser is empty and all defaults will be returned.
1124                }
1125
1126                // Default: 12 hours of screen-on time sans dream-time
1127                mAppIdleDurationMillis = mParser.getLong(KEY_IDLE_DURATION,
1128                       COMPRESS_TIME ? ONE_MINUTE * 4 : 12 * 60 * ONE_MINUTE);
1129
1130                mAppIdleWallclockThresholdMillis = mParser.getLong(KEY_WALLCLOCK_THRESHOLD,
1131                        COMPRESS_TIME ? ONE_MINUTE * 8 : 2L * 24 * 60 * ONE_MINUTE); // 2 days
1132
1133                mCheckIdleIntervalMillis = Math.min(mAppIdleDurationMillis / 4,
1134                        COMPRESS_TIME ? ONE_MINUTE : 8 * 60 * ONE_MINUTE); // 8 hours
1135
1136                // Default: 24 hours between paroles
1137                mAppIdleParoleIntervalMillis = mParser.getLong(KEY_PAROLE_INTERVAL,
1138                        COMPRESS_TIME ? ONE_MINUTE * 10 : 24 * 60 * ONE_MINUTE);
1139
1140                mAppIdleParoleDurationMillis = mParser.getLong(KEY_PAROLE_DURATION,
1141                        COMPRESS_TIME ? ONE_MINUTE : 10 * ONE_MINUTE); // 10 minutes
1142            }
1143        }
1144    }
1145
1146    private final class BinderService extends IUsageStatsManager.Stub {
1147
1148        private boolean hasPermission(String callingPackage) {
1149            final int callingUid = Binder.getCallingUid();
1150            if (callingUid == Process.SYSTEM_UID) {
1151                return true;
1152            }
1153            final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
1154                    callingUid, callingPackage);
1155            if (mode == AppOpsManager.MODE_DEFAULT) {
1156                // The default behavior here is to check if PackageManager has given the app
1157                // permission.
1158                return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS)
1159                        == PackageManager.PERMISSION_GRANTED;
1160            }
1161            return mode == AppOpsManager.MODE_ALLOWED;
1162        }
1163
1164        @Override
1165        public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
1166                long endTime, String callingPackage) {
1167            if (!hasPermission(callingPackage)) {
1168                return null;
1169            }
1170
1171            final int userId = UserHandle.getCallingUserId();
1172            final long token = Binder.clearCallingIdentity();
1173            try {
1174                final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
1175                        userId, bucketType, beginTime, endTime);
1176                if (results != null) {
1177                    return new ParceledListSlice<>(results);
1178                }
1179            } finally {
1180                Binder.restoreCallingIdentity(token);
1181            }
1182            return null;
1183        }
1184
1185        @Override
1186        public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
1187                long beginTime, long endTime, String callingPackage) throws RemoteException {
1188            if (!hasPermission(callingPackage)) {
1189                return null;
1190            }
1191
1192            final int userId = UserHandle.getCallingUserId();
1193            final long token = Binder.clearCallingIdentity();
1194            try {
1195                final List<ConfigurationStats> results =
1196                        UsageStatsService.this.queryConfigurationStats(userId, bucketType,
1197                                beginTime, endTime);
1198                if (results != null) {
1199                    return new ParceledListSlice<>(results);
1200                }
1201            } finally {
1202                Binder.restoreCallingIdentity(token);
1203            }
1204            return null;
1205        }
1206
1207        @Override
1208        public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
1209            if (!hasPermission(callingPackage)) {
1210                return null;
1211            }
1212
1213            final int userId = UserHandle.getCallingUserId();
1214            final long token = Binder.clearCallingIdentity();
1215            try {
1216                return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
1217            } finally {
1218                Binder.restoreCallingIdentity(token);
1219            }
1220        }
1221
1222        @Override
1223        public boolean isAppInactive(String packageName, int userId) {
1224            try {
1225                userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
1226                        Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
1227            } catch (RemoteException re) {
1228                return false;
1229            }
1230            final long token = Binder.clearCallingIdentity();
1231            try {
1232                return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId, -1);
1233            } finally {
1234                Binder.restoreCallingIdentity(token);
1235            }
1236        }
1237
1238        @Override
1239        public void setAppInactive(String packageName, boolean idle, int userId) {
1240            final int callingUid = Binder.getCallingUid();
1241            try {
1242                userId = ActivityManagerNative.getDefault().handleIncomingUser(
1243                        Binder.getCallingPid(), callingUid, userId, false, true,
1244                        "setAppIdle", null);
1245            } catch (RemoteException re) {
1246                return;
1247            }
1248            getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
1249                    "No permission to change app idle state");
1250            final long token = Binder.clearCallingIdentity();
1251            try {
1252                PackageInfo pi = AppGlobals.getPackageManager()
1253                        .getPackageInfo(packageName, 0, userId);
1254                if (pi == null) return;
1255                UsageStatsService.this.setAppIdle(packageName, idle, userId);
1256            } catch (RemoteException re) {
1257            } finally {
1258                Binder.restoreCallingIdentity(token);
1259            }
1260        }
1261
1262        @Override
1263        public void whitelistAppTemporarily(String packageName, long duration, int userId)
1264                throws RemoteException {
1265            StringBuilder reason = new StringBuilder(32);
1266            reason.append("from:");
1267            UserHandle.formatUid(reason, Binder.getCallingUid());
1268            mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId,
1269                    reason.toString());
1270        }
1271
1272        @Override
1273        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1274            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1275                    != PackageManager.PERMISSION_GRANTED) {
1276                pw.println("Permission Denial: can't dump UsageStats from pid="
1277                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1278                        + " without permission " + android.Manifest.permission.DUMP);
1279                return;
1280            }
1281            UsageStatsService.this.dump(args, pw);
1282        }
1283    }
1284
1285    /**
1286     * This local service implementation is primarily used by ActivityManagerService.
1287     * ActivityManagerService will call these methods holding the 'am' lock, which means we
1288     * shouldn't be doing any IO work or other long running tasks in these methods.
1289     */
1290    private final class LocalService extends UsageStatsManagerInternal {
1291
1292        @Override
1293        public void reportEvent(ComponentName component, int userId, int eventType) {
1294            if (component == null) {
1295                Slog.w(TAG, "Event reported without a component name");
1296                return;
1297            }
1298
1299            UsageEvents.Event event = new UsageEvents.Event();
1300            event.mPackage = component.getPackageName();
1301            event.mClass = component.getClassName();
1302
1303            // This will later be converted to system time.
1304            event.mTimeStamp = SystemClock.elapsedRealtime();
1305
1306            event.mEventType = eventType;
1307            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1308        }
1309
1310        @Override
1311        public void reportEvent(String packageName, int userId, int eventType) {
1312            if (packageName == null) {
1313                Slog.w(TAG, "Event reported without a package name");
1314                return;
1315            }
1316
1317            UsageEvents.Event event = new UsageEvents.Event();
1318            event.mPackage = packageName;
1319
1320            // This will later be converted to system time.
1321            event.mTimeStamp = SystemClock.elapsedRealtime();
1322
1323            event.mEventType = eventType;
1324            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1325        }
1326
1327        @Override
1328        public void reportConfigurationChange(Configuration config, int userId) {
1329            if (config == null) {
1330                Slog.w(TAG, "Configuration event reported with a null config");
1331                return;
1332            }
1333
1334            UsageEvents.Event event = new UsageEvents.Event();
1335            event.mPackage = "android";
1336
1337            // This will later be converted to system time.
1338            event.mTimeStamp = SystemClock.elapsedRealtime();
1339
1340            event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE;
1341            event.mConfiguration = new Configuration(config);
1342            mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget();
1343        }
1344
1345        @Override
1346        public void reportContentProviderUsage(String name, String packageName, int userId) {
1347            SomeArgs args = SomeArgs.obtain();
1348            args.arg1 = name;
1349            args.arg2 = packageName;
1350            args.arg3 = userId;
1351            mHandler.obtainMessage(MSG_REPORT_CONTENT_PROVIDER_USAGE, args)
1352                    .sendToTarget();
1353        }
1354
1355        @Override
1356        public boolean isAppIdle(String packageName, int userId) {
1357            return UsageStatsService.this.isAppIdleFiltered(packageName, userId, -1);
1358        }
1359
1360        @Override
1361        public int[] getIdleUidsForUser(int userId) {
1362            return UsageStatsService.this.getIdleUidsForUser(userId);
1363        }
1364
1365        @Override
1366        public boolean isAppIdleParoleOn() {
1367            return mAppIdleParoled;
1368        }
1369
1370        @Override
1371        public void prepareShutdown() {
1372            // This method *WILL* do IO work, but we must block until it is finished or else
1373            // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because
1374            // we are shutting down.
1375            shutdown();
1376        }
1377
1378        @Override
1379        public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) {
1380            UsageStatsService.this.addListener(listener);
1381            listener.onParoleStateChanged(isAppIdleParoleOn());
1382        }
1383
1384        @Override
1385        public void removeAppIdleStateChangeListener(
1386                AppIdleStateChangeListener listener) {
1387            UsageStatsService.this.removeListener(listener);
1388        }
1389    }
1390}
1391