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

Commit 695cf72f authored by Narayan Kamath's avatar Narayan Kamath
Browse files

Support chained attribution for alarm related WorkSources.

.. those passed down via the AlarmManager.set() variant that takes
a WorkSource. This required a minor re-arrangement of code in
the ActivityManager. We now treat WorkSources as opaque in the
AlarmManager and simply push them down to the AM (and eventually
to BatteryStats) where they are picked apart.

Test: BatteryStatsNoteTest, AlarmManagerTest
Bug: 62390666
Change-Id: I118f1a1d16aafa41b4f401f1a6a3ba4d2d5eca8f
parent 37d870bc
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
@@ -3911,10 +3912,10 @@ public class ActivityManager {
    /**
     * @hide
     */
    public static void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg,
            String tag) {
    public static void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid,
            String sourcePkg, String tag) {
        try {
            getService().noteWakeupAlarm((ps != null) ? ps.getTarget() : null,
            getService().noteWakeupAlarm((ps != null) ? ps.getTarget() : null, workSource,
                    sourceUid, sourcePkg, tag);
        } catch (RemoteException ex) {
        }
@@ -3923,19 +3924,24 @@ public class ActivityManager {
    /**
     * @hide
     */
    public static void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) {
    public static void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid,
            String tag) {
        try {
            getService().noteAlarmStart((ps != null) ? ps.getTarget() : null, sourceUid, tag);
            getService().noteAlarmStart((ps != null) ? ps.getTarget() : null, workSource,
                    sourceUid, tag);
        } catch (RemoteException ex) {
        }
    }


    /**
     * @hide
     */
    public static void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) {
    public static void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid,
            String tag) {
        try {
            getService().noteAlarmFinish((ps != null) ? ps.getTarget() : null, sourceUid, tag);
            getService().noteAlarmFinish((ps != null) ? ps.getTarget() : null, workSource,
                    sourceUid, tag);
        } catch (RemoteException ex) {
        }
    }
+3 −3
Original line number Diff line number Diff line
@@ -75,20 +75,20 @@ public abstract class ActivityManagerNative {
     */
    static public void noteWakeupAlarm(PendingIntent ps, int sourceUid, String sourcePkg,
            String tag) {
        ActivityManager.noteWakeupAlarm(ps, sourceUid, sourcePkg, tag);
        ActivityManager.noteWakeupAlarm(ps, null, sourceUid, sourcePkg, tag);
    }

    /**
     * @deprecated use ActivityManager.noteAlarmStart instead.
     */
    static public void noteAlarmStart(PendingIntent ps, int sourceUid, String tag) {
        ActivityManager.noteAlarmStart(ps, sourceUid, tag);
        ActivityManager.noteAlarmStart(ps, null, sourceUid, tag);
    }

    /**
     * @deprecated use ActivityManager.noteAlarmFinish instead.
     */
    static public void noteAlarmFinish(PendingIntent ps, int sourceUid, String tag) {
        ActivityManager.noteAlarmFinish(ps, sourceUid, tag);
        ActivityManager.noteAlarmFinish(ps, null, sourceUid, tag);
    }
}
+4 −3
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import android.os.IProgressListener;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.StrictMode;
import android.os.WorkSource;
import android.service.voice.IVoiceInteractionSession;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
@@ -198,7 +199,7 @@ interface IActivityManager {
    void enterSafeMode();
    boolean startNextMatchingActivity(in IBinder callingActivity,
            in Intent intent, in Bundle options);
    void noteWakeupAlarm(in IIntentSender sender, int sourceUid,
    void noteWakeupAlarm(in IIntentSender sender, in WorkSource workSource, int sourceUid,
            in String sourcePkg, in String tag);
    void removeContentProvider(in IBinder connection, boolean stable);
    void setRequestedOrientation(in IBinder token, int requestedOrientation);
@@ -468,8 +469,8 @@ interface IActivityManager {
    void dumpHeapFinished(in String path);
    void setVoiceKeepAwake(in IVoiceInteractionSession session, boolean keepAwake);
    void updateLockTaskPackages(int userId, in String[] packages);
    void noteAlarmStart(in IIntentSender sender, int sourceUid, in String tag);
    void noteAlarmFinish(in IIntentSender sender, int sourceUid, in String tag);
    void noteAlarmStart(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
    void noteAlarmFinish(in IIntentSender sender, in WorkSource workSource, int sourceUid, in String tag);
    int getPackageProcessState(in String packageName, in String callingPackage);
    oneway void showLockTaskEscapeMessage(in IBinder token);
    void updateDeviceOwner(in String packageName);
+70 −15
Original line number Diff line number Diff line
@@ -506,8 +506,8 @@ public class BatteryStatsImpl extends BatteryStats {
    final HistoryEventTracker mActiveEvents = new HistoryEventTracker();
    long mHistoryBaseTime;
    boolean mHaveBatteryLevel = false;
    boolean mRecordingHistory = false;
    protected boolean mHaveBatteryLevel = false;
    protected boolean mRecordingHistory = false;
    int mNumHistoryItems;
    final Parcel mHistoryBuffer = Parcel.obtain();
@@ -3975,30 +3975,85 @@ public class BatteryStatsImpl extends BatteryStats {
        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid);
    }
    public void noteAlarmStartLocked(String name, int uid) {
    public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) {
        noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid);
    }
    public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) {
        noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid);
    }
    private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource,
            int uid) {
        if (!mRecordAllHistory) {
            return;
        }
        uid = mapUid(uid);
        final long elapsedRealtime = mClocks.elapsedRealtime();
        final long uptime = mClocks.uptimeMillis();
        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_START, name, uid, 0)) {
            return;
        if (workSource != null) {
            for (int i = 0; i < workSource.size(); ++i) {
                uid = mapUid(workSource.get(i));
                if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
                    addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
                }
        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_START, name, uid);
            }
    public void noteAlarmFinishLocked(String name, int uid) {
        if (!mRecordAllHistory) {
            return;
            List<WorkChain> workChains = workSource.getWorkChains();
            if (workChains != null) {
                for (int i = 0; i < workChains.size(); ++i) {
                    uid = mapUid(workChains.get(i).getAttributionUid());
                    if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
                        addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
                    }
                }
            }
        } else {
            uid = mapUid(uid);
        final long elapsedRealtime = mClocks.elapsedRealtime();
        final long uptime = mClocks.uptimeMillis();
        if (!mActiveEvents.updateState(HistoryItem.EVENT_ALARM_FINISH, name, uid, 0)) {
            if (mActiveEvents.updateState(historyItem, name, uid, 0)) {
                addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid);
            }
        }
    }
    public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource,
            String tag) {
        if (!isOnBattery()) {
            return;
        }
        addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ALARM_FINISH, name, uid);
        if (workSource != null) {
            for (int i = 0; i < workSource.size(); ++i) {
                uid = workSource.get(i);
                final String workSourceName = workSource.getName(i);
                BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid,
                        workSourceName != null ? workSourceName : packageName);
                pkg.noteWakeupAlarmLocked(tag);
                StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
            }
            ArrayList<WorkChain> workChains = workSource.getWorkChains();
            if (workChains != null) {
                for (int i = 0; i < workChains.size(); ++i) {
                    final WorkChain wc = workChains.get(i);
                    uid = wc.getAttributionUid();
                    BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
                    pkg.noteWakeupAlarmLocked(tag);
                    // TODO(statsd): Log the full attribution chain here once it's available
                    StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
                }
            }
        } else {
            BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName);
            pkg.noteWakeupAlarmLocked(tag);
            StatsLog.write(StatsLog.WAKEUP_ALARM_OCCURRED, uid, tag);
        }
    }
    private void requestWakelockCpuUpdate() {
+186 −20
Original line number Diff line number Diff line
@@ -15,16 +15,19 @@
 */
package com.android.internal.os;

import static android.os.BatteryStats.STATS_CURRENT;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;

import android.app.ActivityManager;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.BatteryStats.HistoryItem;
import android.os.WorkSource;
import android.support.test.filters.SmallTest;
import android.view.Display;

import com.android.internal.os.BatteryStatsImpl.Uid;
import junit.framework.TestCase;

import java.util.ArrayList;
@@ -45,10 +48,13 @@ import java.util.Map;
 *      com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
 */
public class BatteryStatsNoteTest extends TestCase {

    private static final int UID = 10500;
    private static final WorkSource WS = new WorkSource(UID);

    /** Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked. */
    /**
     * Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked.
     */
    @SmallTest
    public void testNoteBluetoothScanResultLocked() throws Exception {
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
@@ -75,7 +81,9 @@ public class BatteryStatsNoteTest extends TestCase{
                        .getCountLocked(STATS_SINCE_CHARGED));
    }

    /** Test BatteryStatsImpl.Uid.noteStartWakeLocked. */
    /**
     * Test BatteryStatsImpl.Uid.noteStartWakeLocked.
     */
    @SmallTest
    public void testNoteStartWakeLocked() throws Exception {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
@@ -86,7 +94,8 @@ public class BatteryStatsNoteTest extends TestCase{

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
        bi.getUidStatsLocked(UID).noteStartWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
        bi.getUidStatsLocked(UID)
                .noteStartWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);

        clocks.realtime = clocks.uptime = 100;
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
@@ -94,7 +103,8 @@ public class BatteryStatsNoteTest extends TestCase{
        clocks.realtime = clocks.uptime = 220;
        bi.getUidStatsLocked(UID).noteStopWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);

        BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID).getAggregatedPartialWakelockTimer();
        BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID)
                .getAggregatedPartialWakelockTimer();
        long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
        long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
        assertEquals(220_000, actualTime);
@@ -102,7 +112,9 @@ public class BatteryStatsNoteTest extends TestCase{
    }


    /** Test BatteryStatsImpl.noteUidProcessStateLocked. */
    /**
     * Test BatteryStatsImpl.noteUidProcessStateLocked.
     */
    @SmallTest
    public void testNoteUidProcessStateLocked() throws Exception {
        final MockClocks clocks = new MockClocks();
@@ -145,7 +157,6 @@ public class BatteryStatsNoteTest extends TestCase{
        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP);
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);


        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
                elapsedTimeUs, STATS_SINCE_CHARGED);
        expectedRunTimeMs = stateRuntimeMap.get(
@@ -153,19 +164,16 @@ public class BatteryStatsNoteTest extends TestCase{
                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);


        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
                elapsedTimeUs, STATS_SINCE_CHARGED);
        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);


        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_FOREGROUND,
                elapsedTimeUs, STATS_SINCE_CHARGED);
        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);


        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_BACKGROUND,
                elapsedTimeUs, STATS_SINCE_CHARGED);
        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND)
@@ -174,7 +182,6 @@ public class BatteryStatsNoteTest extends TestCase{
                + stateRuntimeMap.get(ActivityManager.PROCESS_STATE_RECEIVER);
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);


        actualRunTimeUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_CACHED,
                elapsedTimeUs, STATS_SINCE_CHARGED);
        expectedRunTimeMs = stateRuntimeMap.get(ActivityManager.PROCESS_STATE_HOME)
@@ -191,7 +198,9 @@ public class BatteryStatsNoteTest extends TestCase{
        assertEquals(expectedRunTimeMs * 1000, actualRunTimeUs);
    }

    /** Test BatteryStatsImpl.updateTimeBasesLocked. */
    /**
     * Test BatteryStatsImpl.updateTimeBasesLocked.
     */
    @SmallTest
    public void testUpdateTimeBasesLocked() throws Exception {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
@@ -213,7 +222,9 @@ public class BatteryStatsNoteTest extends TestCase{
        assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
    }

    /** Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly. */
    /**
     * Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly.
     */
    @SmallTest
    public void testNoteScreenStateLocked() throws Exception {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
@@ -232,15 +243,13 @@ public class BatteryStatsNoteTest extends TestCase{
        assertEquals(bi.getScreenState(), Display.STATE_OFF);
    }

    /** Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
    /**
     * Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
     *
     * Unknown and doze should both be subset of off state
     *
     *  Timeline 0----100----200----310----400------------1000
     *  Unknown         -------
     *  On                     -------
     *  Off             -------       ----------------------
     *  Doze                                ----------------
     * Timeline 0----100----200----310----400------------1000 Unknown         ------- On ------- Off
     * -------       ---------------------- Doze ----------------
     */
    @SmallTest
    public void testNoteScreenStateTimersLocked() throws Exception {
@@ -280,4 +289,161 @@ public class BatteryStatsNoteTest extends TestCase{
        assertEquals(600_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
    }

    @SmallTest
    public void testAlarmStartAndFinishLocked() throws Exception {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setRecordAllHistoryLocked(true);
        bi.forceRecordAllHistory();

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);

        clocks.realtime = clocks.uptime = 100;
        bi.noteAlarmStartLocked("foo", null, UID);
        clocks.realtime = clocks.uptime = 5000;
        bi.noteAlarmFinishLocked("foo", null, UID);

        HistoryItem item = new HistoryItem();
        assertTrue(bi.startIteratingHistoryLocked());

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
        assertEquals("foo", item.eventTag.string);
        assertEquals(UID, item.eventTag.uid);

        // TODO(narayan): Figure out why this event is written to the history buffer. See
        // test below where it is being interspersed between multiple START events too.
        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_NONE, item.eventCode);

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
        assertTrue(item.isDeltaData());
        assertEquals("foo", item.eventTag.string);
        assertEquals(UID, item.eventTag.uid);

        assertFalse(bi.getNextHistoryLocked(item));
    }

    @SmallTest
    public void testAlarmStartAndFinishLocked_workSource() throws Exception {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setRecordAllHistoryLocked(true);
        bi.forceRecordAllHistory();

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);

        WorkSource ws = new WorkSource();
        ws.add(100);
        ws.createWorkChain().addNode(500, "tag");
        bi.noteAlarmStartLocked("foo", ws, UID);
        clocks.realtime = clocks.uptime = 5000;
        bi.noteAlarmFinishLocked("foo", ws, UID);

        HistoryItem item = new HistoryItem();
        assertTrue(bi.startIteratingHistoryLocked());

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
        assertEquals("foo", item.eventTag.string);
        assertEquals(100, item.eventTag.uid);

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_NONE, item.eventCode);

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_START, item.eventCode);
        assertEquals("foo", item.eventTag.string);
        assertEquals(500, item.eventTag.uid);

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
        assertEquals("foo", item.eventTag.string);
        assertEquals(100, item.eventTag.uid);

        assertTrue(bi.getNextHistoryLocked(item));
        assertEquals(HistoryItem.EVENT_ALARM_FINISH, item.eventCode);
        assertEquals("foo", item.eventTag.string);
        assertEquals(500, item.eventTag.uid);
    }

    @SmallTest
    public void testNoteWakupAlarmLocked() {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setRecordAllHistoryLocked(true);
        bi.forceRecordAllHistory();
        bi.mForceOnBattery = true;

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);

        bi.noteWakupAlarmLocked("com.foo.bar", UID, null, "tag");

        Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
        assertEquals(1, pkg.getWakeupAlarmStats().get("tag").getCountLocked(STATS_CURRENT));
        assertEquals(1, pkg.getWakeupAlarmStats().size());
    }

    @SmallTest
    public void testNoteWakupAlarmLocked_workSource_uid() {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setRecordAllHistoryLocked(true);
        bi.forceRecordAllHistory();
        bi.mForceOnBattery = true;

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);

        WorkSource ws = new WorkSource();
        ws.add(100);

        // When a WorkSource is present, "UID" should not be used - only the uids present in the
        // WorkSource should be reported.
        bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");
        Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
        assertEquals(0, pkg.getWakeupAlarmStats().size());
        pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
        assertEquals(1, pkg.getWakeupAlarmStats().size());

        // If the WorkSource contains a "name", it should be interpreted as a package name and
        // the packageName supplied as an argument must be ignored.
        ws = new WorkSource();
        ws.add(100, "com.foo.baz_alternate");
        bi.noteWakupAlarmLocked("com.foo.baz", UID, ws, "tag");
        pkg = bi.getPackageStatsLocked(100, "com.foo.baz");
        assertEquals(0, pkg.getWakeupAlarmStats().size());
        pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
        assertEquals(1, pkg.getWakeupAlarmStats().size());
    }

    @SmallTest
    public void testNoteWakupAlarmLocked_workSource_workChain() {
        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
        bi.setRecordAllHistoryLocked(true);
        bi.forceRecordAllHistory();
        bi.mForceOnBattery = true;

        bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);

        WorkSource ws = new WorkSource();
        ws.createWorkChain().addNode(100, "com.foo.baz_alternate");
        bi.noteWakupAlarmLocked("com.foo.bar", UID, ws, "tag");

        // For WorkChains, again we must only attribute to the uids present in the WorkSource
        // (and not to "UID"). However, unlike the older "tags" we do not change the packagename
        // supplied as an argument, given that we're logging the entire attribution chain.
        Uid.Pkg pkg = bi.getPackageStatsLocked(UID, "com.foo.bar");
        assertEquals(0, pkg.getWakeupAlarmStats().size());
        pkg = bi.getPackageStatsLocked(100, "com.foo.bar");
        assertEquals(1, pkg.getWakeupAlarmStats().size());
        pkg = bi.getPackageStatsLocked(100, "com.foo.baz_alternate");
        assertEquals(0, pkg.getWakeupAlarmStats().size());
    }
}
Loading