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

Commit f8826f09 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Add CPU power brackets to PowerProfile"

parents 54c2cd9e ec82dbfd
Loading
Loading
Loading
Loading
+153 −6
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;

/**
 * Reports power consumption values for various device activities. Reads values from an XML file.
@@ -315,6 +316,8 @@ public class PowerProfile {

    private static final Object sLock = new Object();

    private int mCpuPowerBracketCount;

    @VisibleForTesting
    @UnsupportedAppUsage
    public PowerProfile(Context context) {
@@ -346,7 +349,6 @@ public class PowerProfile {
            sModemPowerProfile.clear();
            initLocked(context, xmlId);
        }

    }

    @GuardedBy("sLock")
@@ -450,6 +452,9 @@ public class PowerProfile {
    private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster";
    private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster";
    private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster";
    private static final String CPU_POWER_BRACKETS_PREFIX = "cpu.power_brackets.cluster";

    private static final int DEFAULT_CPU_POWER_BRACKET_NUMBER = 3;

    private void initCpuClusters() {
        if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
@@ -471,13 +476,104 @@ public class PowerProfile {
            mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0,
                    CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus);
        }

        initCpuPowerBrackets(DEFAULT_CPU_POWER_BRACKET_NUMBER);
    }

    /**
     * Parses or computes CPU power brackets: groups of states with similar power requirements.
     */
    @VisibleForTesting
    public void initCpuPowerBrackets(int defaultCpuPowerBracketNumber) {
        boolean anyBracketsSpecified = false;
        boolean allBracketsSpecified = true;
        for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
            final int steps = getNumSpeedStepsInCpuCluster(cluster);
            mCpuClusters[cluster].powerBrackets = new int[steps];
            if (sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + cluster) != null) {
                anyBracketsSpecified = true;
            } else {
                allBracketsSpecified = false;
            }
        }

        if (anyBracketsSpecified && !allBracketsSpecified) {
            throw new RuntimeException(
                    "Power brackets should be specified for all clusters or no clusters");
        }

        mCpuPowerBracketCount = 0;
        if (allBracketsSpecified) {
            for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                final Double[] data = sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + cluster);
                if (data.length != mCpuClusters[cluster].powerBrackets.length) {
                    throw new RuntimeException(
                            "Wrong number of items in " + CPU_POWER_BRACKETS_PREFIX + cluster);
                }

                for (int i = 0; i < data.length; i++) {
                    final int bracket = (int) Math.round(data[i]);
                    mCpuClusters[cluster].powerBrackets[i] = bracket;
                    if (bracket > mCpuPowerBracketCount) {
                        mCpuPowerBracketCount = bracket;
                    }
                }
            }
            mCpuPowerBracketCount++;
        } else {
            double minPower = Double.MAX_VALUE;
            double maxPower = Double.MIN_VALUE;
            int stateCount = 0;
            for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                final int steps = getNumSpeedStepsInCpuCluster(cluster);
                for (int step = 0; step < steps; step++) {
                    final double power = getAveragePowerForCpuCore(cluster, step);
                    if (power < minPower) {
                        minPower = power;
                    }
                    if (power > maxPower) {
                        maxPower = power;
                    }
                }
                stateCount += steps;
            }

            if (stateCount <= defaultCpuPowerBracketNumber) {
                mCpuPowerBracketCount = stateCount;
                int bracket = 0;
                for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                    final int steps = getNumSpeedStepsInCpuCluster(cluster);
                    for (int step = 0; step < steps; step++) {
                        mCpuClusters[cluster].powerBrackets[step] = bracket++;
                    }
                }
            } else {
                mCpuPowerBracketCount = defaultCpuPowerBracketNumber;
                final double minLogPower = Math.log(minPower);
                final double logBracket = (Math.log(maxPower) - minLogPower)
                        / defaultCpuPowerBracketNumber;

                for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                    final int steps = getNumSpeedStepsInCpuCluster(cluster);
                    for (int step = 0; step < steps; step++) {
                        final double power = getAveragePowerForCpuCore(cluster, step);
                        int bracket = (int) ((Math.log(power) - minLogPower) / logBracket);
                        if (bracket >= defaultCpuPowerBracketNumber) {
                            bracket = defaultCpuPowerBracketNumber - 1;
                        }
                        mCpuClusters[cluster].powerBrackets[step] = bracket;
                    }
                }
            }
        }
    }

    public static class CpuClusterKey {
        private final String freqKey;
        private final String clusterPowerKey;
        private final String corePowerKey;
        private final int numCpus;
    private static class CpuClusterKey {
        public final String freqKey;
        public final String clusterPowerKey;
        public final String corePowerKey;
        public final int numCpus;
        public int[] powerBrackets;

        private CpuClusterKey(String freqKey, String clusterPowerKey,
                String corePowerKey, int numCpus) {
@@ -525,6 +621,57 @@ public class PowerProfile {
        return 0;
    }

    /**
     * Returns the number of CPU power brackets: groups of states with similar power requirements.
     */
    public int getCpuPowerBracketCount() {
        return mCpuPowerBracketCount;
    }

    /**
     * Description of a CPU power bracket: which cluster/frequency combinations are included.
     */
    public String getCpuPowerBracketDescription(int powerBracket) {
        StringBuilder sb = new StringBuilder();
        for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
            int[] brackets = mCpuClusters[cluster].powerBrackets;
            for (int step = 0; step < brackets.length; step++) {
                if (brackets[step] == powerBracket) {
                    if (sb.length() != 0) {
                        sb.append(", ");
                    }
                    if (mCpuClusters.length > 1) {
                        sb.append(cluster).append('/');
                    }
                    Double[] freqs = sPowerArrayMap.get(mCpuClusters[cluster].freqKey);
                    if (freqs != null && step < freqs.length) {
                        // Frequency in MHz
                        sb.append(freqs[step].intValue() / 1000);
                    }
                    sb.append('(');
                    sb.append(String.format(Locale.US, "%.1f",
                            getAveragePowerForCpuCore(cluster, step)));
                    sb.append(')');
                }
            }
        }
        return sb.toString();
    }

    /**
     * Returns the CPU power bracket corresponding to the specified cluster and frequency step
     */
    public int getPowerBracketForCpuCore(int cluster, int step) {
        if (cluster >= 0
                && cluster < mCpuClusters.length
                && step >= 0
                && step < mCpuClusters[cluster].powerBrackets.length) {
            return mCpuClusters[cluster].powerBrackets[step];
        }
        return 0;
    }


    private int mNumDisplays;

    private void initDisplays() {
+51 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2022 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.
  -->

<device name="Android">

    <array name="cpu.clusters.cores">
        <value>1</value>
        <value>2</value>
    </array>

    <array name="cpu.core_speeds.cluster0">
        <value>300000</value>
    </array>

    <array name="cpu.core_speeds.cluster1">
        <value>300000</value>
        <value>1000000</value>
    </array>

    <array name="cpu.core_power.cluster0">
        <value>10</value>
    </array>

    <array name="cpu.core_power.cluster1">
        <value>25</value>
        <value>35</value>
    </array>

    <array name="cpu.power_brackets.cluster0">
        <value>1</value>
    </array>

    <array name="cpu.power_brackets.cluster1">
        <value>1</value>
        <value>0</value>
    </array>
</device>
+72 −3
Original line number Diff line number Diff line
@@ -21,6 +21,11 @@ import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;

import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import android.annotation.XmlRes;
import android.content.Context;
import android.content.res.Resources;
@@ -28,15 +33,16 @@ import android.content.res.XmlResourceParser;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.frameworks.coretests.R;
import com.android.internal.power.ModemPowerProfile;
import com.android.internal.util.XmlUtils;

import junit.framework.TestCase;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

/*
 * Keep this file in sync with frameworks/base/core/res/res/xml/power_profile_test.xml and
@@ -46,7 +52,8 @@ import org.junit.Test;
 *     atest com.android.internal.os.PowerProfileTest
 */
@SmallTest
public class PowerProfileTest extends TestCase {
@RunWith(AndroidJUnit4.class)
public class PowerProfileTest {

    static final String TAG_TEST_MODEM = "test-modem";
    static final String ATTR_NAME = "name";
@@ -516,4 +523,66 @@ public class PowerProfileTest extends TestCase {
        fail("Unanable to find element " + element + " with name " + elementName);
        return null;
    }

    private void assertEquals(int expected, int actual) {
        Assert.assertEquals(expected, actual);
    }

    private void assertEquals(double expected, double actual) {
        Assert.assertEquals(expected, actual, 0.1);
    }


    @Test
    public void powerBrackets_specifiedInPowerProfile() {
        mProfile.forceInitForTesting(mContext, R.xml.power_profile_test_power_brackets);
        mProfile.initCpuPowerBrackets(8);

        int cpuPowerBracketCount = mProfile.getCpuPowerBracketCount();
        assertThat(cpuPowerBracketCount).isEqualTo(2);
        assertThat(new int[]{
                mProfile.getPowerBracketForCpuCore(0, 0),
                mProfile.getPowerBracketForCpuCore(1, 0),
                mProfile.getPowerBracketForCpuCore(1, 1),
        }).isEqualTo(new int[]{1, 1, 0});
    }

    @Test
    public void powerBrackets_automatic() {
        mProfile.forceInitForTesting(mContext, R.xml.power_profile_test);

        assertThat(mProfile.getCpuPowerBracketCount()).isEqualTo(3);
        assertThat(mProfile.getCpuPowerBracketDescription(0))
                .isEqualTo("0/300(10.0)");
        assertThat(mProfile.getCpuPowerBracketDescription(1))
                .isEqualTo("0/1000(20.0), 0/2000(30.0), 1/300(25.0)");
        assertThat(mProfile.getCpuPowerBracketDescription(2))
                .isEqualTo("1/1000(35.0), 1/2500(50.0), 1/3000(60.0)");
        assertThat(new int[]{
                mProfile.getPowerBracketForCpuCore(0, 0),
                mProfile.getPowerBracketForCpuCore(0, 1),
                mProfile.getPowerBracketForCpuCore(0, 2),
                mProfile.getPowerBracketForCpuCore(1, 0),
                mProfile.getPowerBracketForCpuCore(1, 1),
                mProfile.getPowerBracketForCpuCore(1, 2),
                mProfile.getPowerBracketForCpuCore(1, 3),
        }).isEqualTo(new int[]{0, 1, 1, 1, 2, 2, 2});
    }

    @Test
    public void powerBrackets_moreBracketsThanStates() {
        mProfile.forceInitForTesting(mContext, R.xml.power_profile_test);
        mProfile.initCpuPowerBrackets(8);

        assertThat(mProfile.getCpuPowerBracketCount()).isEqualTo(7);
        assertThat(new int[]{
                mProfile.getPowerBracketForCpuCore(0, 0),
                mProfile.getPowerBracketForCpuCore(0, 1),
                mProfile.getPowerBracketForCpuCore(0, 2),
                mProfile.getPowerBracketForCpuCore(1, 0),
                mProfile.getPowerBracketForCpuCore(1, 1),
                mProfile.getPowerBracketForCpuCore(1, 2),
                mProfile.getPowerBracketForCpuCore(1, 3),
        }).isEqualTo(new int[]{0, 1, 2, 3, 4, 5, 6});
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -14965,6 +14965,18 @@ public class BatteryStatsImpl extends BatteryStats {
        }
    }
    @GuardedBy("this")
    private void dumpCpuPowerBracketsLocked(PrintWriter pw) {
        pw.println("CPU power brackets; cluster/freq in MHz(avg current in mA):");
        final int bracketCount = mPowerProfile.getCpuPowerBracketCount();
        for (int bracket = 0; bracket < bracketCount; bracket++) {
            pw.print("    ");
            pw.print(bracket);
            pw.print(": ");
            pw.println(mPowerProfile.getCpuPowerBracketDescription(bracket));
        }
    }
    /**
     * Dump measured charge stats
     */
@@ -16296,6 +16308,9 @@ public class BatteryStatsImpl extends BatteryStats {
        pw.println();
        dumpConstantsLocked(pw);
        pw.println();
        dumpCpuPowerBracketsLocked(pw);
        pw.println();
        dumpMeasuredEnergyStatsLocked(pw);
    }