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

Commit f6b9b302 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Change PowerProfile to allow flexible CPU scaling policies

Bug: 283012390
Test: atest FrameworksCoreTests:PowerProfileTest

Change-Id: I1e2f6552c9813ab99c7eb14fc44bce6b655de818
parent d407ac2a
Loading
Loading
Loading
Loading
+212 −45
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
@@ -294,6 +295,8 @@ public class PowerProfile {

    private static final long SUBSYSTEM_FIELDS_MASK = 0xFFFF_FFFF;

    private static final int DEFAULT_CPU_POWER_BRACKET_NUMBER = 3;

    /**
     * A map from Power Use Item to its power consumption.
     */
@@ -357,6 +360,8 @@ public class PowerProfile {
            readPowerValuesFromXml(context, xmlId);
        }
        initCpuClusters();
        initCpuScalingPolicies();
        initCpuPowerBrackets(DEFAULT_CPU_POWER_BRACKET_NUMBER);
        initDisplays();
        initModem();
    }
@@ -452,9 +457,7 @@ 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 static final String CPU_POWER_BRACKETS_PREFIX = "cpu.power_brackets.policy";

    private void initCpuClusters() {
        if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
@@ -476,8 +479,82 @@ 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);
    private SparseArray<CpuScalingPolicyPower> mCpuScalingPolicies;
    private static final String CPU_SCALING_POLICY_POWER_POLICY = "cpu.scaling_policy_power.policy";
    private static final String CPU_SCALING_STEP_POWER_POLICY = "cpu.scaling_step_power.policy";

    private void initCpuScalingPolicies() {
        int policyCount = 0;
        for (String key : sPowerItemMap.keySet()) {
            if (key.startsWith(CPU_SCALING_POLICY_POWER_POLICY)) {
                int policy =
                        Integer.parseInt(key.substring(CPU_SCALING_POLICY_POWER_POLICY.length()));
                policyCount = Math.max(policyCount, policy + 1);
            }
        }
        for (String key : sPowerArrayMap.keySet()) {
            if (key.startsWith(CPU_SCALING_STEP_POWER_POLICY)) {
                int policy =
                        Integer.parseInt(key.substring(CPU_SCALING_STEP_POWER_POLICY.length()));
                policyCount = Math.max(policyCount, policy + 1);
            }
        }

        if (policyCount > 0) {
            mCpuScalingPolicies = new SparseArray<>(policyCount);
            for (int policy = 0; policy < policyCount; policy++) {
                Double policyPower = sPowerItemMap.get(CPU_SCALING_POLICY_POWER_POLICY + policy);
                Double[] stepPower = sPowerArrayMap.get(CPU_SCALING_STEP_POWER_POLICY + policy);
                if (policyPower != null || stepPower != null) {
                    double[] primitiveStepPower;
                    if (stepPower != null) {
                        primitiveStepPower = new double[stepPower.length];
                        for (int i = 0; i < stepPower.length; i++) {
                            primitiveStepPower[i] = stepPower[i];
                        }
                    } else {
                        primitiveStepPower = new double[0];
                    }
                    mCpuScalingPolicies.put(policy, new CpuScalingPolicyPower(
                            policyPower != null ? policyPower : 0, primitiveStepPower));
                }
            }
        } else {
            // Legacy power_profile.xml
            int cpuId = 0;
            for (CpuClusterKey cpuCluster : mCpuClusters) {
                policyCount = cpuId + 1;
                cpuId += cpuCluster.numCpus;
            }

            if (policyCount > 0) {
                mCpuScalingPolicies = new SparseArray<>(policyCount);
                cpuId = 0;
                for (CpuClusterKey cpuCluster : mCpuClusters) {
                    double clusterPower = getAveragePower(cpuCluster.clusterPowerKey);
                    double[] stepPower;
                    int numSteps = getNumElements(cpuCluster.corePowerKey);
                    if (numSteps != 0) {
                        stepPower = new double[numSteps];
                        for (int step = 0; step < numSteps; step++) {
                            stepPower[step] = getAveragePower(cpuCluster.corePowerKey, step);
                        }
                    } else {
                        stepPower = new double[1];
                    }
                    mCpuScalingPolicies.put(cpuId,
                            new CpuScalingPolicyPower(clusterPower, stepPower));
                    cpuId += cpuCluster.numCpus;
                }
            } else {
                mCpuScalingPolicies = new SparseArray<>(1);
                mCpuScalingPolicies.put(0,
                        new CpuScalingPolicyPower(getAveragePower(POWER_CPU_ACTIVE),
                                new double[]{0}));
            }
        }
    }

    /**
@@ -487,33 +564,38 @@ public class PowerProfile {
    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) {
        for (int i = mCpuScalingPolicies.size() - 1; i >= 0; i--) {
            int policy = mCpuScalingPolicies.keyAt(i);
            CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
            final int steps = cpuScalingPolicyPower.stepPower.length;
            cpuScalingPolicyPower.powerBrackets = new int[steps];
            if (sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + policy) != null) {
                anyBracketsSpecified = true;
            } else {
                allBracketsSpecified = false;
            }
        }

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

        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) {
            for (int i = mCpuScalingPolicies.size() - 1; i >= 0; i--) {
                int policy = mCpuScalingPolicies.keyAt(i);
                CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
                final Double[] data = sPowerArrayMap.get(CPU_POWER_BRACKETS_PREFIX + policy);
                if (data.length != cpuScalingPolicyPower.powerBrackets.length) {
                    throw new RuntimeException(
                            "Wrong number of items in " + CPU_POWER_BRACKETS_PREFIX + cluster);
                            "Wrong number of items in " + CPU_POWER_BRACKETS_PREFIX + policy
                                    + ", expected: "
                                    + cpuScalingPolicyPower.powerBrackets.length);
                }

                for (int i = 0; i < data.length; i++) {
                    final int bracket = (int) Math.round(data[i]);
                    mCpuClusters[cluster].powerBrackets[i] = bracket;
                for (int j = 0; j < data.length; j++) {
                    final int bracket = (int) Math.round(data[j]);
                    cpuScalingPolicyPower.powerBrackets[j] = bracket;
                    if (bracket > mCpuPowerBracketCount) {
                        mCpuPowerBracketCount = bracket;
                    }
@@ -524,10 +606,12 @@ public class PowerProfile {
            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 i = mCpuScalingPolicies.size() - 1; i >= 0; i--) {
                int policy = mCpuScalingPolicies.keyAt(i);
                CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
                final int steps = cpuScalingPolicyPower.stepPower.length;
                for (int step = 0; step < steps; step++) {
                    final double power = getAveragePowerForCpuCore(cluster, step);
                    final double power = getAveragePowerForCpuScalingStep(policy, step);
                    if (power < minPower) {
                        minPower = power;
                    }
@@ -541,10 +625,11 @@ public class PowerProfile {
            if (stateCount <= defaultCpuPowerBracketNumber) {
                mCpuPowerBracketCount = stateCount;
                int bracket = 0;
                for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                    final int steps = getNumSpeedStepsInCpuCluster(cluster);
                for (int i = 0; i < mCpuScalingPolicies.size(); i++) {
                    CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
                    final int steps = cpuScalingPolicyPower.stepPower.length;
                    for (int step = 0; step < steps; step++) {
                        mCpuClusters[cluster].powerBrackets[step] = bracket++;
                        cpuScalingPolicyPower.powerBrackets[step] = bracket++;
                    }
                }
            } else {
@@ -553,27 +638,70 @@ public class PowerProfile {
                final double logBracket = (Math.log(maxPower) - minLogPower)
                        / defaultCpuPowerBracketNumber;

                for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
                    final int steps = getNumSpeedStepsInCpuCluster(cluster);
                for (int i = mCpuScalingPolicies.size() - 1; i >= 0; i--) {
                    int policy = mCpuScalingPolicies.keyAt(i);
                    CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
                    final int steps = cpuScalingPolicyPower.stepPower.length;
                    for (int step = 0; step < steps; step++) {
                        final double power = getAveragePowerForCpuCore(cluster, step);
                        final double power = getAveragePowerForCpuScalingStep(policy, step);
                        int bracket = (int) ((Math.log(power) - minLogPower) / logBracket);
                        if (bracket >= defaultCpuPowerBracketNumber) {
                            bracket = defaultCpuPowerBracketNumber - 1;
                        }
                        mCpuClusters[cluster].powerBrackets[step] = bracket;
                        cpuScalingPolicyPower.powerBrackets[step] = bracket;
                    }
                }
            }
        }
    }

    private static class CpuScalingPolicyPower {
        public final double policyPower;
        public final double[] stepPower;
        public int[] powerBrackets;

        private CpuScalingPolicyPower(double policyPower, double[] stepPower) {
            this.policyPower = policyPower;
            this.stepPower = stepPower;
        }
    }

    /**
     * Returns the average additional power in (mA) when the CPU scaling policy <code>policy</code>
     * is used.
     *
     * @param policy Policy ID as per <code>ls /sys/devices/system/cpu/cpufreq</code>. Typically,
     *               policy ID corresponds to the index of the first related CPU, e.g. for "policy6"
     *               <code>/sys/devices/system/cpu/cpufreq/policy6/related_cpus</code> will
     *               contain CPU IDs like <code>6, 7</code>
     */
    public double getAveragePowerForCpuScalingPolicy(int policy) {
        CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy);
        if (cpuScalingPolicyPower != null) {
            return cpuScalingPolicyPower.policyPower;
        }
        return 0;
    }

    /**
     * Returns the average additional power in (mA) when the CPU scaling policy <code>policy</code>
     * is used at the <code>step</code> frequency step (this is not the frequency itself, but the
     * integer index of the frequency step).
     */
    public double getAveragePowerForCpuScalingStep(int policy, int step) {
        CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy);
        if (cpuScalingPolicyPower != null
                && step >= 0 && step < cpuScalingPolicyPower.stepPower.length) {
            return cpuScalingPolicyPower.stepPower[step];
        }
        return 0;
    }

    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) {
@@ -584,11 +712,19 @@ public class PowerProfile {
        }
    }

    /**
     * @deprecated Use CpuScalingPolicy instead
     */
    @UnsupportedAppUsage
    @Deprecated
    public int getNumCpuClusters() {
        return mCpuClusters.length;
    }

    /**
     * @deprecated Use CpuScalingPolicy instead
     */
    @Deprecated
    public int getNumCoresInCpuCluster(int cluster) {
        if (cluster < 0 || cluster >= mCpuClusters.length) {
            return 0; // index out of bound
@@ -596,7 +732,11 @@ public class PowerProfile {
        return mCpuClusters[cluster].numCpus;
    }

    /**
     * @deprecated Use CpuScalingPolicy instead
     */
    @UnsupportedAppUsage
    @Deprecated
    public int getNumSpeedStepsInCpuCluster(int cluster) {
        if (cluster < 0 || cluster >= mCpuClusters.length) {
            return 0; // index out of bound
@@ -607,6 +747,10 @@ public class PowerProfile {
        return 1; // Only one speed
    }

    /**
     * @deprecated Use getAveragePowerForCpuScalingPolicy
     */
    @Deprecated
    public double getAveragePowerForCpuCluster(int cluster) {
        if (cluster >= 0 && cluster < mCpuClusters.length) {
            return getAveragePower(mCpuClusters[cluster].clusterPowerKey);
@@ -614,6 +758,10 @@ public class PowerProfile {
        return 0;
    }

    /**
     * @deprecated Use getAveragePowerForCpuScalingStep
     */
    @Deprecated
    public double getAveragePowerForCpuCore(int cluster, int step) {
        if (cluster >= 0 && cluster < mCpuClusters.length) {
            return getAveragePower(mCpuClusters[cluster].corePowerKey, step);
@@ -631,26 +779,28 @@ public class PowerProfile {
    /**
     * Description of a CPU power bracket: which cluster/frequency combinations are included.
     */
    public String getCpuPowerBracketDescription(int powerBracket) {
    public String getCpuPowerBracketDescription(CpuScalingPolicies cpuScalingPolicies,
            int powerBracket) {
        StringBuilder sb = new StringBuilder();
        for (int cluster = 0; cluster < mCpuClusters.length; cluster++) {
            int[] brackets = mCpuClusters[cluster].powerBrackets;
        for (int i = 0; i < mCpuScalingPolicies.size(); i++) {
            int policy = mCpuScalingPolicies.keyAt(i);
            CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.valueAt(i);
            int[] brackets = cpuScalingPolicyPower.powerBrackets;
            int[] freqs = cpuScalingPolicies.getFrequencies(policy);
            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('/');
                    if (mCpuScalingPolicies.size() > 1) {
                        sb.append(policy).append('/');
                    }
                    Double[] freqs = sPowerArrayMap.get(mCpuClusters[cluster].freqKey);
                    if (freqs != null && step < freqs.length) {
                        // Frequency in MHz
                        sb.append(freqs[step].intValue() / 1000);
                    if (step < freqs.length) {
                        sb.append(freqs[step] / 1000);
                    }
                    sb.append('(');
                    sb.append(String.format(Locale.US, "%.1f",
                            getAveragePowerForCpuCore(cluster, step)));
                            getAveragePowerForCpuScalingStep(policy, step)));
                    sb.append(')');
                }
            }
@@ -659,18 +809,35 @@ public class PowerProfile {
    }

    /**
     * Returns the CPU power bracket corresponding to the specified cluster and frequency step
     * Returns the CPU power bracket corresponding to the specified scaling policy 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];
    public int getCpuPowerBracketForScalingStep(int policy, int step) {
        CpuScalingPolicyPower cpuScalingPolicyPower = mCpuScalingPolicies.get(policy);
        if (cpuScalingPolicyPower != null
                && step >= 0 && step < cpuScalingPolicyPower.powerBrackets.length) {
            return cpuScalingPolicyPower.powerBrackets[step];
        }
        return 0;
    }

    /**
     * Description of a CPU power bracket: which cluster/frequency combinations are included.
     * @deprecated Use getCpuPowerBracketDescription
     */
    @Deprecated
    public String getCpuPowerBracketDescription(int powerBracket) {
        return "unsupported";
    }

    /**
     * Returns the CPU power bracket corresponding to the specified cluster and frequency step
     * @deprecated Use getCpuPowerBracketForScalingStep
     */
    @Deprecated
    public int getPowerBracketForCpuCore(int cluster, int step) {
        return 0;
    }

    private int mNumDisplays;

+10 −32
Original line number Diff line number Diff line
@@ -19,12 +19,6 @@
    <!-- This is the battery capacity in mAh -->
    <item name="battery.capacity">3000</item>

    <!-- Number of cores each CPU cluster contains -->
    <array name="cpu.clusters.cores">
        <value>4</value> <!-- Cluster 0 has 4 cores (cpu0, cpu1, cpu2, cpu3) -->
        <value>4</value> <!-- Cluster 1 has 4 cores (cpu4, cpu5, cpu5, cpu7) -->
    </array>

    <!-- Power consumption when CPU is suspended -->
    <item name="cpu.suspend">5</item>
    <!-- Additional power consumption when CPU is in a kernel idle loop -->
@@ -32,37 +26,21 @@
    <!-- Additional power consumption by CPU excluding cluster and core when  running -->
    <item name="cpu.active">2.55</item>

    <!-- Additional power consumption by CPU cluster0 itself when running excluding cores in it -->
    <item name="cpu.cluster_power.cluster0">2.11</item>
    <!-- Additional power consumption by CPU cluster1 itself when running excluding cores in it -->
    <item name="cpu.cluster_power.cluster1">2.22</item>

    <!-- Different CPU speeds as reported in
         /sys/devices/system/cpu/cpu0/cpufreq/stats/scaling_available_frequencies -->
    <array name="cpu.core_speeds.cluster0">
        <value>300000</value> <!-- 300 MHz CPU speed -->
        <value>1000000</value> <!-- 1000 MHz CPU speed -->
        <value>2000000</value> <!-- 2000 MHz CPU speed -->
    </array>
    <!-- Different CPU speeds as reported in
         /sys/devices/system/cpu/cpu4/cpufreq/stats/scaling_available_frequencies -->
    <array name="cpu.core_speeds.cluster1">
        <value>300000</value> <!-- 300 MHz CPU speed -->
        <value>1000000</value> <!-- 1000 MHz CPU speed -->
        <value>2500000</value> <!-- 2500 MHz CPU speed -->
        <value>3000000</value> <!-- 3000 MHz CPU speed -->
    </array>
    <!-- Additional power consumption of CPU policy0 itself when running on related cores -->
    <item name="cpu.scaling_policy_power.policy0">2.11</item>
    <!-- Additional power consumption of CPU policy4 itself when running on related cores -->
    <item name="cpu.scaling_policy_power.policy3">2.22</item>

    <!-- Additional power used by a CPU from cluster 0 when running at different
         speeds. Currently this measurement also includes cluster cost. -->
    <array name="cpu.core_power.cluster0">
    <!-- Additional power used by a CPU related to policy3 when running at different
     speeds. -->
    <array name="cpu.scaling_step_power.policy0">
        <value>10</value> <!-- 300 MHz CPU speed -->
        <value>20</value> <!-- 1000 MHz CPU speed -->
        <value>30</value> <!-- 1900 MHz CPU speed -->
    </array>
    <!-- Additional power used by a CPU from cluster 1 when running at different
         speeds. Currently this measurement also includes cluster cost. -->
    <array name="cpu.core_power.cluster1">
    <!-- Additional power used by a CPU related to policy3 when running at different
         speeds. -->
    <array name="cpu.scaling_step_power.policy3">
        <value>25</value> <!-- 300 MHz CPU speed -->
        <value>35</value> <!-- 1000 MHz CPU speed -->
        <value>50</value> <!-- 2500 MHz CPU speed -->
+116 −0

File added.

Preview size limit exceeded, changes collapsed.

+4 −18
Original line number Diff line number Diff line
@@ -17,34 +17,20 @@

<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">
    <array name="cpu.scaling_step_power.policy0">
        <value>10</value>
    </array>

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

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

    <array name="cpu.power_brackets.cluster1">
    <array name="cpu.power_brackets.policy4">
        <value>1</value>
        <value>0</value>
    </array>
+53 −31

File changed.

Preview size limit exceeded, changes collapsed.