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

Commit dc0df828 authored by Amith Yamasani's avatar Amith Yamasani Committed by Android Git Automerger
Browse files

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

* commit 'ffff74ab':
  Report app standby state to batterystats
parents 1bb6ee4a ffff74ab
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);
        }
    }