Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ffff74ab authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Report app standby state to batterystats" into mnc-dev

parents 7ae22652 6776849d
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -1177,8 +1177,13 @@ public abstract class BatteryStats implements Parcelable {
        public static final int EVENT_ALARM = 0x000e;
        // Record that we have decided we need to collect new stats data.
        public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
        // Event for a package becoming inactive due to being unused for a period of time.
        public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
        // Event for a package becoming active due to an interaction.
        public static final int EVENT_PACKAGE_ACTIVE = 0x0011;

        // Number of event types.
        public static final int EVENT_COUNT = 0x0010;
        public static final int EVENT_COUNT = 0x0012;
        // Mask to extract out only the type part of the event.
        public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);

@@ -1835,12 +1840,12 @@ public abstract class BatteryStats implements Parcelable {

    public static final String[] HISTORY_EVENT_NAMES = new String[] {
            "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
            "motion", "active", "pkginst", "pkgunin", "alarm", "stats"
            "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
    };

    public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
            "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
            "Esm", "Eac", "Epi", "Epu", "Eal", "Est"
            "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
    };

    /**
+33 −16
Original line number Diff line number Diff line
@@ -27,34 +27,27 @@ import com.android.internal.util.IndentingPrintWriter;
 */
public class AppIdleHistory {

    private SparseArray<ArrayMap<String,byte[]>> idleHistory = new SparseArray<>();
    private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>();
    private long lastPeriod = 0;
    private static final long ONE_MINUTE = 60 * 1000;
    private static final int HISTORY_SIZE = 100;
    private static final int FLAG_LAST_STATE = 2;
    private static final int FLAG_PARTIAL_ACTIVE = 1;
    private static final long PERIOD_DURATION = UsageStatsService.DEBUG ? ONE_MINUTE
    private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE
            : 60 * ONE_MINUTE;

    public void addEntry(String packageName, int userId, boolean idle, long timeNow) {
        ArrayMap<String, byte[]> userHistory = idleHistory.get(userId);
        if (userHistory == null) {
            userHistory = new ArrayMap<>();
            idleHistory.put(userId, userHistory);
        }
        byte[] packageHistory = userHistory.get(packageName);
        if (packageHistory == null) {
            packageHistory = new byte[HISTORY_SIZE];
            userHistory.put(packageName, packageHistory);
        }
        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
        byte[] packageHistory = getPackageHistory(userHistory, packageName);

        long thisPeriod = timeNow / PERIOD_DURATION;
        // Has the period switched over? Slide all users' package histories
        if (lastPeriod != 0 && lastPeriod < thisPeriod
                && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) {
            int diff = (int) (thisPeriod - lastPeriod);
            final int NUSERS = idleHistory.size();
            final int NUSERS = mIdleHistory.size();
            for (int u = 0; u < NUSERS; u++) {
                userHistory = idleHistory.valueAt(u);
                userHistory = mIdleHistory.valueAt(u);
                for (byte[] history : userHistory.values()) {
                    // Shift left
                    System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff);
@@ -74,12 +67,36 @@ public class AppIdleHistory {
        }
    }

    private ArrayMap<String, byte[]> getUserHistory(int userId) {
        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
        if (userHistory == null) {
            userHistory = new ArrayMap<>();
            mIdleHistory.put(userId, userHistory);
        }
        return userHistory;
    }

    private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) {
        byte[] packageHistory = userHistory.get(packageName);
        if (packageHistory == null) {
            packageHistory = new byte[HISTORY_SIZE];
            userHistory.put(packageName, packageHistory);
        }
        return packageHistory;
    }

    public void removeUser(int userId) {
        idleHistory.remove(userId);
        mIdleHistory.remove(userId);
    }

    public boolean isIdle(int userId, String packageName) {
        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
        byte[] packageHistory = getPackageHistory(userHistory, packageName);
        return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0;
    }

    public void dump(IndentingPrintWriter idpw, int userId) {
        ArrayMap<String, byte[]> userHistory = idleHistory.get(userId);
        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
        if (userHistory == null) return;
        final int P = userHistory.size();
        for (int p = 0; p < P; p++) {
+73 −30
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.database.ContentObserver;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
@@ -65,6 +66,7 @@ import android.util.SparseArray;
import android.view.Display;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.DeviceIdleController;
@@ -91,7 +93,7 @@ public class UsageStatsService extends SystemService implements
    static final String TAG = "UsageStatsService";

    static final boolean DEBUG = false;
    private static final boolean COMPRESS_TIME = false;
    static final boolean COMPRESS_TIME = false;

    private static final long TEN_SECONDS = 10 * 1000;
    private static final long ONE_MINUTE = 60 * 1000;
@@ -128,6 +130,7 @@ public class UsageStatsService extends SystemService implements
    IDeviceIdleController mDeviceIdleController;
    private DisplayManager mDisplayManager;
    private PowerManager mPowerManager;
    private IBatteryStats mBatteryStats;

    private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
    private File mUsageStatsDir;
@@ -200,6 +203,8 @@ public class UsageStatsService extends SystemService implements
            mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
            mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
                    ServiceManager.getService(DeviceIdleController.SERVICE_NAME));
            mBatteryStats = IBatteryStats.Stub.asInterface(
                    ServiceManager.getService(BatteryStats.SERVICE_NAME));
            mDisplayManager = (DisplayManager) getContext().getSystemService(
                    Context.DISPLAY_SERVICE);
            mPowerManager = getContext().getSystemService(PowerManager.class);
@@ -228,7 +233,7 @@ public class UsageStatsService extends SystemService implements
                }
            } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
                if (userId >=0) {
                    postCheckIdleStates();
                    postCheckIdleStates(userId);
                }
            }
        }
@@ -307,7 +312,7 @@ public class UsageStatsService extends SystemService implements
                    mLastAppIdleParoledTime = checkAndGetTimeLocked();
                    postNextParoleTimeout();
                }
                postCheckIdleStates();
                postCheckIdleStates(UserHandle.USER_ALL);
            }
        }
    }
@@ -332,22 +337,25 @@ public class UsageStatsService extends SystemService implements
        mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION);
    }

    void postCheckIdleStates() {
        mHandler.removeMessages(MSG_CHECK_IDLE_STATES);
        mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES);
    void postCheckIdleStates(int userId) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
    }

    /** Check all running users' apps to see if they enter an idle state. */
    void checkIdleStates() {
        final int[] runningUsers;
    /** Check all running users' or specified user's apps to see if they enter an idle state. */
    void checkIdleStates(int checkUserId) {
        final int[] userIds;
        try {
            runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
            if (checkUserId == UserHandle.USER_ALL) {
                userIds = ActivityManagerNative.getDefault().getRunningUserIds();
            } else {
                userIds = new int[] { checkUserId };
            }
        } catch (RemoteException re) {
            return;
        }

        for (int i = 0; i < runningUsers.length; i++) {
            final int userId = runningUsers[i];
        for (int i = 0; i < userIds.length; i++) {
            final int userId = userIds[i];
            List<PackageInfo> packages =
                    getContext().getPackageManager().getInstalledPackages(
                            PackageManager.GET_DISABLED_COMPONENTS
@@ -355,17 +363,22 @@ public class UsageStatsService extends SystemService implements
                            userId);
            synchronized (mLock) {
                final long timeNow = checkAndGetTimeLocked();
                final long screenOnTime = getScreenOnTimeLocked(timeNow);
                UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
                        timeNow);
                final int packageCount = packages.size();
                for (int p = 0; p < packageCount; p++) {
                    final String packageName = packages.get(p).packageName;
                    final boolean isIdle = isAppIdleFiltered(packageName, userId, timeNow);
                    final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow,
                            screenOnTime);
                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
                            userId, isIdle ? 1 : 0, packageName));
                    mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
                }
            }
        }
        mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis);
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
                mCheckIdleIntervalMillis);
    }

    /** Check if it's been a while since last parole and let idle apps do some work */
@@ -386,6 +399,20 @@ public class UsageStatsService extends SystemService implements
        }
    }

    private void notifyBatteryStats(String packageName, int userId, boolean idle) {
        try {
            int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId);
            if (idle) {
                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE,
                        packageName, uid);
            } else {
                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE,
                        packageName, uid);
            }
        } catch (RemoteException re) {
        }
    }

    void updateDisplayLocked() {
        boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
                == Display.STATE_ON;
@@ -545,7 +572,7 @@ public class UsageStatsService extends SystemService implements
            final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
            final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
                    lastUsedTime, screenOnTime, timeNow);
            service.reportEvent(event, getScreenOnTimeLocked(timeNow));
            service.reportEvent(event, screenOnTime);
            // Inform listeners if necessary
            if ((event.mEventType == Event.MOVE_TO_FOREGROUND
                    || event.mEventType == Event.MOVE_TO_BACKGROUND
@@ -555,6 +582,7 @@ public class UsageStatsService extends SystemService implements
                    // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
                    mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                            /* idle = */ 0, event.mPackage));
                    notifyBatteryStats(event.mPackage, userId, false);
                    mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow);
                }
            }
@@ -586,6 +614,9 @@ public class UsageStatsService extends SystemService implements
                // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
                mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                        /* idle = */ idle ? 1 : 0, packageName));
                if (!idle) {
                    notifyBatteryStats(packageName, userId, idle);
                }
                mAppIdleHistory.addEntry(packageName, userId, idle, timeNow);
            }
        }
@@ -660,19 +691,20 @@ public class UsageStatsService extends SystemService implements
        }
    }

    private boolean isAppIdleUnfiltered(String packageName, int userId, long timeNow) {
    private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService,
            long timeNow, long screenOnTime) {
        synchronized (mLock) {
            final long screenOnTime = getScreenOnTimeLocked(timeNow);
            final UserUsageStatsService service =
                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
            long beginIdleTime = service.getBeginIdleTime(packageName);
            long lastUsedTime = service.getSystemLastUsedTime(packageName);
            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow);
            long beginIdleTime = userService.getBeginIdleTime(packageName);
            long lastUsedTime = userService.getSystemLastUsedTime(packageName);
            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime,
                    timeNow);
        }
    }

    /**
     * @param timestamp when the app was last used in device usage timebase
     * @param beginIdleTime when the app was last used in device usage timebase
     * @param lastUsedTime wallclock time of when the app was last used
     * @param screenOnTime screen-on timebase time
     * @param currentTime current time in device usage timebase
     * @return whether it's been used far enough in the past to be considered inactive
     */
@@ -696,18 +728,29 @@ public class UsageStatsService extends SystemService implements
        }
    }

    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
        final UserUsageStatsService userService;
        final long screenOnTime;
        synchronized (mLock) {
            if (timeNow == -1) {
                timeNow = checkAndGetTimeLocked();
            }
            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
            screenOnTime = getScreenOnTimeLocked(timeNow);
        }
        return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime);
    }

    /**
     * Checks if an app has been idle for a while and filters out apps that are excluded.
     * It returns false if the current system state allows all apps to be considered active.
     * This happens if the device is plugged in or temporarily allowed to make exceptions.
     * Called by interface impls.
     */
    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
    private boolean isAppIdleFiltered(String packageName, int userId,
            UserUsageStatsService userService, long timeNow, long screenOnTime) {
        if (packageName == null) return false;
        synchronized (mLock) {
            if (timeNow == -1) {
                timeNow = checkAndGetTimeLocked();
            }
            // Temporary exemption, probably due to device charging or occasional allowance to
            // be allowed to sync, etc.
            if (mAppIdleParoled) {
@@ -735,7 +778,7 @@ public class UsageStatsService extends SystemService implements
            return false;
        }

        return isAppIdleUnfiltered(packageName, userId, timeNow);
        return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
    }

    void setAppIdle(String packageName, boolean idle, int userId) {
@@ -844,7 +887,7 @@ public class UsageStatsService extends SystemService implements
                    break;

                case MSG_CHECK_IDLE_STATES:
                    checkIdleStates();
                    checkIdleStates(msg.arg1);
                    break;

                case MSG_CHECK_PAROLE_TIMEOUT:
@@ -884,7 +927,7 @@ public class UsageStatsService extends SystemService implements
                    UserHandle.USER_OWNER);
            mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL,
                    mAppIdleDurationMillis / 4);
            postCheckIdleStates();
            postCheckIdleStates(UserHandle.USER_ALL);
        }
    }