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

Commit a93542f9 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Rewrite app standby stats

Don't mix up with usage stats. Keep a separate db and history
based on elapsed time and screen on time.

Unit tests for AppIdleHistory class.

Bug: 26989006
Change-Id: If343785b46da1db67f7c1c1263854c2732a232c6
parent a37278b0
Loading
Loading
Loading
Loading
+0 −41
Original line number Diff line number Diff line
@@ -46,20 +46,6 @@ public final class UsageStats implements Parcelable {
     */
    public long mLastTimeUsed;

    /**
     * The last time the package was used via implicit, non-user initiated actions (service
     * was bound, etc).
     * {@hide}
     */
    public long mLastTimeSystemUsed;

    /**
     * Last time the package was used and the beginning of the idle countdown.
     * This uses a different timebase that is about how much the device has been in use in general.
     * {@hide}
     */
    public long mBeginIdleTime;

    /**
     * {@hide}
     */
@@ -89,8 +75,6 @@ public final class UsageStats implements Parcelable {
        mTotalTimeInForeground = stats.mTotalTimeInForeground;
        mLaunchCount = stats.mLaunchCount;
        mLastEvent = stats.mLastEvent;
        mBeginIdleTime = stats.mBeginIdleTime;
        mLastTimeSystemUsed = stats.mLastTimeSystemUsed;
    }

    public String getPackageName() {
@@ -126,25 +110,6 @@ public final class UsageStats implements Parcelable {
        return mLastTimeUsed;
    }

    /**
     * @hide
     * Get the last time this package was used by the system (not the user). This can be different
     * from {@link #getLastTimeUsed()} when the system binds to one of this package's services.
     * See {@link System#currentTimeMillis()}.
     */
    public long getLastTimeSystemUsed() {
        return mLastTimeSystemUsed;
    }

    /**
     * @hide
     * Get the last time this package was active, measured in milliseconds. This timestamp
     * uses a timebase that represents how much the device was used and not wallclock time.
     */
    public long getBeginIdleTime() {
        return mBeginIdleTime;
    }

    /**
     * Get the total time this package spent in the foreground, measured in milliseconds.
     */
@@ -172,8 +137,6 @@ public final class UsageStats implements Parcelable {
            // regards to their mEndTimeStamp.
            mLastEvent = right.mLastEvent;
            mLastTimeUsed = right.mLastTimeUsed;
            mBeginIdleTime = right.mBeginIdleTime;
            mLastTimeSystemUsed = right.mLastTimeSystemUsed;
        }
        mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
        mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
@@ -195,8 +158,6 @@ public final class UsageStats implements Parcelable {
        dest.writeLong(mTotalTimeInForeground);
        dest.writeInt(mLaunchCount);
        dest.writeInt(mLastEvent);
        dest.writeLong(mBeginIdleTime);
        dest.writeLong(mLastTimeSystemUsed);
    }

    public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
@@ -210,8 +171,6 @@ public final class UsageStats implements Parcelable {
            stats.mTotalTimeInForeground = in.readLong();
            stats.mLaunchCount = in.readInt();
            stats.mLastEvent = in.readInt();
            stats.mBeginIdleTime = in.readLong();
            stats.mLastTimeSystemUsed = in.readLong();
            return stats;
        }

+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
    services.core \
    services.devicepolicy \
    services.net \
    services.usage \
    easymocklib \
    guava \
    android-support-test \
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.usage;

import android.os.FileUtils;
import android.test.AndroidTestCase;

import java.io.File;

public class AppIdleHistoryTests extends AndroidTestCase {

    File mStorageDir;

    final static String PACKAGE_1 = "com.android.testpackage1";
    final static String PACKAGE_2 = "com.android.testpackage2";

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mStorageDir = new File(getContext().getFilesDir(), "appidle");
        mStorageDir.mkdirs();
    }

    @Override
    protected void tearDown() throws Exception {
        FileUtils.deleteContents(mStorageDir);
        super.tearDown();
    }

    public void testFilesCreation() {
        final int userId = 0;
        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 0);

        aih.updateDisplayLocked(true, /* elapsedRealtime= */ 1000);
        aih.updateDisplayLocked(false, /* elapsedRealtime= */ 2000);
        // Screen On time file should be written right away
        assertTrue(aih.getScreenOnTimeFile().exists());

        aih.writeAppIdleTimesLocked(userId);
        // stats file should be written now
        assertTrue(new File(new File(mStorageDir, "users/" + userId),
                AppIdleHistory.APP_IDLE_FILENAME).exists());
    }

    public void testScreenOnTime() {
        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
        aih.updateDisplayLocked(false, 2000);
        assertEquals(aih.getScreenOnTimeLocked(2000), 0);
        aih.updateDisplayLocked(true, 3000);
        assertEquals(aih.getScreenOnTimeLocked(4000), 1000);
        assertEquals(aih.getScreenOnTimeLocked(5000), 2000);
        aih.updateDisplayLocked(false, 6000);
        // Screen on time should not keep progressing with screen is off
        assertEquals(aih.getScreenOnTimeLocked(7000), 3000);
        assertEquals(aih.getScreenOnTimeLocked(8000), 3000);
        aih.writeElapsedTimeLocked();

        // Check if the screen on time is persisted across instantiations
        AppIdleHistory aih2 = new AppIdleHistory(mStorageDir, 0);
        assertEquals(aih2.getScreenOnTimeLocked(11000), 3000);
        aih2.updateDisplayLocked(true, 4000);
        aih2.updateDisplayLocked(false, 5000);
        assertEquals(aih2.getScreenOnTimeLocked(13000), 4000);
    }

    public void testPackageEvents() {
        AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
        aih.setThresholds(4000, 1000);
        aih.updateDisplayLocked(true, 1000);
        // App is not-idle by default
        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 1500));
        // Still not idle
        assertFalse(aih.isIdleLocked(PACKAGE_1, 0, 3000));
        // Idle now
        assertTrue(aih.isIdleLocked(PACKAGE_1, 0, 8000));
        // Not idle
        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 9000));

        // Screen off
        aih.updateDisplayLocked(false, 9100);
        // Still idle after 10 seconds because screen hasn't been on long enough
        assertFalse(aih.isIdleLocked(PACKAGE_2, 0, 20000));
        aih.updateDisplayLocked(true, 21000);
        assertTrue(aih.isIdleLocked(PACKAGE_2, 0, 23000));
    }
}
 No newline at end of file
+334 −32

File changed.

Preview size limit exceeded, changes collapsed.

+0 −18
Original line number Diff line number Diff line
@@ -48,7 +48,6 @@ class IntervalStats {
            usageStats.mPackageName = getCachedStringRef(packageName);
            usageStats.mBeginTimeStamp = beginTime;
            usageStats.mEndTimeStamp = endTime;
            usageStats.mBeginIdleTime = 0;
            packageStats.put(usageStats.mPackageName, usageStats);
        }
        return usageStats;
@@ -113,7 +112,6 @@ class IntervalStats {
        if (eventType != UsageEvents.Event.SYSTEM_INTERACTION) {
            usageStats.mLastTimeUsed = timeStamp;
        }
        usageStats.mLastTimeSystemUsed = timeStamp;
        usageStats.mEndTimeStamp = timeStamp;

        if (eventType == UsageEvents.Event.MOVE_TO_FOREGROUND) {
@@ -123,22 +121,6 @@ class IntervalStats {
        endTime = timeStamp;
    }

    /**
     * Updates the last active time for the package. The timestamp uses a timebase that
     * tracks the device usage time.
     * @param packageName
     * @param timeStamp
     */
    void updateBeginIdleTime(String packageName, long timeStamp) {
        UsageStats usageStats = getOrCreateUsageStats(packageName);
        usageStats.mBeginIdleTime = timeStamp;
    }

    void updateSystemLastUsedTime(String packageName, long lastUsedTime) {
        UsageStats usageStats = getOrCreateUsageStats(packageName);
        usageStats.mLastTimeSystemUsed = lastUsedTime;
    }

    void updateConfigurationStats(Configuration config, long timeStamp) {
        if (activeConfiguration != null) {
            ConfigurationStats activeStats = configurations.get(activeConfiguration);
Loading