1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.power.stats; 18 19 import android.os.BatteryConsumer; 20 import android.os.BatteryStats; 21 import android.os.BatteryUsageStats; 22 import android.os.BatteryUsageStatsQuery; 23 import android.os.Process; 24 import android.os.UidBatteryConsumer; 25 import android.util.Log; 26 import android.util.SparseArray; 27 28 import com.android.internal.os.CpuScalingPolicies; 29 import com.android.internal.os.PowerProfile; 30 31 /** 32 * Estimates the amount of power consumed by the System Server handling requests from 33 * a given app. 34 */ 35 public class SystemServicePowerCalculator extends PowerCalculator { 36 private static final boolean DEBUG = false; 37 private static final String TAG = "SystemServicePowerCalc"; 38 39 // Power estimators per CPU cluster, per CPU frequency. The array is flattened according 40 // to this layout: 41 // {cluster1-speed1, cluster1-speed2, ..., cluster2-speed1, cluster2-speed2, ...} 42 private final UsageBasedPowerEstimator[] mPowerEstimators; 43 private final CpuPowerCalculator mCpuPowerCalculator; 44 SystemServicePowerCalculator(CpuScalingPolicies cpuScalingPolicies, PowerProfile powerProfile)45 public SystemServicePowerCalculator(CpuScalingPolicies cpuScalingPolicies, 46 PowerProfile powerProfile) { 47 mCpuPowerCalculator = new CpuPowerCalculator(cpuScalingPolicies, powerProfile); 48 mPowerEstimators = new UsageBasedPowerEstimator[cpuScalingPolicies.getScalingStepCount()]; 49 int index = 0; 50 int[] policies = cpuScalingPolicies.getPolicies(); 51 for (int policy : policies) { 52 final int numSpeeds = cpuScalingPolicies.getFrequencies(policy).length; 53 for (int speed = 0; speed < numSpeeds; speed++) { 54 mPowerEstimators[index++] = new UsageBasedPowerEstimator( 55 powerProfile.getAveragePowerForCpuScalingStep(policy, speed)); 56 } 57 } 58 } 59 60 @Override isPowerComponentSupported(@atteryConsumer.PowerComponent int powerComponent)61 public boolean isPowerComponentSupported(@BatteryConsumer.PowerComponent int powerComponent) { 62 return powerComponent == BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES; 63 } 64 65 @Override calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query)66 public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, 67 long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) { 68 final BatteryStats.Uid systemUid = batteryStats.getUidStats().get(Process.SYSTEM_UID); 69 if (systemUid == null) { 70 return; 71 } 72 73 final long consumptionUC = systemUid.getCpuEnergyConsumptionUC(); 74 final int powerModel = getPowerModel(consumptionUC, query); 75 76 double systemServicePowerMah; 77 if (powerModel == BatteryConsumer.POWER_MODEL_ENERGY_CONSUMPTION) { 78 systemServicePowerMah = calculatePowerUsingEnergyConsumption(batteryStats, 79 systemUid, consumptionUC); 80 } else { 81 systemServicePowerMah = calculatePowerUsingPowerProfile(batteryStats); 82 } 83 84 final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders = 85 builder.getUidBatteryConsumerBuilders(); 86 final UidBatteryConsumer.Builder systemServerConsumer = uidBatteryConsumerBuilders.get( 87 Process.SYSTEM_UID); 88 89 if (systemServerConsumer != null) { 90 systemServicePowerMah = Math.min(systemServicePowerMah, 91 systemServerConsumer.getTotalPower()); 92 93 // The system server power needs to be adjusted because part of it got 94 // distributed to applications 95 systemServerConsumer.setConsumedPower( 96 BatteryConsumer.POWER_COMPONENT_REATTRIBUTED_TO_OTHER_CONSUMERS, 97 -systemServicePowerMah, powerModel); 98 } 99 100 for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) { 101 final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i); 102 if (app != systemServerConsumer) { 103 final BatteryStats.Uid uid = app.getBatteryStatsUid(); 104 app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES, 105 systemServicePowerMah * uid.getProportionalSystemServiceUsage(), 106 powerModel); 107 } 108 } 109 110 builder.getAggregateBatteryConsumerBuilder( 111 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE) 112 .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES, 113 systemServicePowerMah); 114 builder.getAggregateBatteryConsumerBuilder( 115 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_ALL_APPS) 116 .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES, 117 systemServicePowerMah); 118 } 119 calculatePowerUsingEnergyConsumption(BatteryStats batteryStats, BatteryStats.Uid systemUid, long consumptionUC)120 private double calculatePowerUsingEnergyConsumption(BatteryStats batteryStats, 121 BatteryStats.Uid systemUid, long consumptionUC) { 122 // Use the PowerProfile based model to estimate the ratio between the power consumed 123 // while handling incoming binder calls and the entire System UID power consumption. 124 // Apply that ratio to the _EnergyConsumer_ system UID power consumption to get a more 125 // accurate estimate of the power consumed by incoming binder calls. 126 final double systemServiceModeledPowerMah = calculatePowerUsingPowerProfile(batteryStats); 127 final double systemUidModeledPowerMah = mCpuPowerCalculator.calculateUidModeledPowerMah( 128 systemUid, BatteryStats.STATS_SINCE_CHARGED); 129 130 if (systemUidModeledPowerMah > 0) { 131 return uCtoMah(consumptionUC) * systemServiceModeledPowerMah / systemUidModeledPowerMah; 132 } else { 133 return 0; 134 } 135 } 136 calculatePowerUsingPowerProfile(BatteryStats batteryStats)137 private double calculatePowerUsingPowerProfile(BatteryStats batteryStats) { 138 final long[] systemServiceTimeAtCpuSpeeds = batteryStats.getSystemServiceTimeAtCpuSpeeds(); 139 if (systemServiceTimeAtCpuSpeeds == null) { 140 return 0; 141 } 142 143 // TODO(179210707): additionally account for CPU active and per cluster battery use 144 145 double powerMah = 0; 146 final int size = Math.min(mPowerEstimators.length, systemServiceTimeAtCpuSpeeds.length); 147 for (int i = 0; i < size; i++) { 148 powerMah += mPowerEstimators[i].calculatePower(systemServiceTimeAtCpuSpeeds[i] / 1000); 149 } 150 151 if (DEBUG) { 152 Log.d(TAG, "System service power:" + powerMah); 153 } 154 return powerMah; 155 } 156 } 157