1 /* 2 * Copyright (C) 2024 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.processor; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.hardware.SensorManager; 22 import android.os.BatteryConsumer; 23 import android.os.BatteryUsageStats; 24 import android.util.IndentingPrintWriter; 25 import android.util.Slog; 26 import android.util.SparseBooleanArray; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.internal.os.BatteryStatsHistory; 30 import com.android.internal.os.CpuScalingPolicies; 31 import com.android.internal.os.PowerProfile; 32 import com.android.server.power.stats.PowerAttributor; 33 import com.android.server.power.stats.PowerStatsSpan; 34 import com.android.server.power.stats.PowerStatsStore; 35 36 import java.util.List; 37 import java.util.function.DoubleSupplier; 38 39 public class MultiStatePowerAttributor implements PowerAttributor { 40 private static final String TAG = "MultiStatePowerAttributor"; 41 42 private final PowerStatsStore mPowerStatsStore; 43 private final PowerStatsExporter mPowerStatsExporter; 44 private final PowerStatsAggregator mPowerStatsAggregator; 45 private final SparseBooleanArray mPowerStatsExporterEnabled = new SparseBooleanArray(); 46 MultiStatePowerAttributor(Context context, PowerStatsStore powerStatsStore, @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies, @NonNull DoubleSupplier batteryCapacitySupplier)47 public MultiStatePowerAttributor(Context context, PowerStatsStore powerStatsStore, 48 @NonNull PowerProfile powerProfile, @NonNull CpuScalingPolicies cpuScalingPolicies, 49 @NonNull DoubleSupplier batteryCapacitySupplier) { 50 this(powerStatsStore, new PowerStatsAggregator( 51 createAggregatedPowerStatsConfig(context, powerProfile, cpuScalingPolicies, 52 batteryCapacitySupplier))); 53 } 54 55 @VisibleForTesting MultiStatePowerAttributor(PowerStatsStore powerStatsStore, PowerStatsAggregator powerStatsAggregator)56 MultiStatePowerAttributor(PowerStatsStore powerStatsStore, 57 PowerStatsAggregator powerStatsAggregator) { 58 mPowerStatsStore = powerStatsStore; 59 mPowerStatsAggregator = powerStatsAggregator; 60 mPowerStatsStore.addSectionReader( 61 new AggregatedPowerStatsSection.Reader(mPowerStatsAggregator.getConfig())); 62 mPowerStatsExporter = new PowerStatsExporter(mPowerStatsStore, mPowerStatsAggregator); 63 setPowerComponentSupported(BatteryConsumer.POWER_COMPONENT_BASE, true); 64 } 65 createAggregatedPowerStatsConfig(Context context, PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies, DoubleSupplier batteryCapacitySupplier)66 private static AggregatedPowerStatsConfig createAggregatedPowerStatsConfig(Context context, 67 PowerProfile powerProfile, CpuScalingPolicies cpuScalingPolicies, 68 DoubleSupplier batteryCapacitySupplier) { 69 AggregatedPowerStatsConfig config = new AggregatedPowerStatsConfig(); 70 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BASE) 71 .trackDeviceStates( 72 AggregatedPowerStatsConfig.STATE_POWER, 73 AggregatedPowerStatsConfig.STATE_SCREEN) 74 .trackUidStates( 75 AggregatedPowerStatsConfig.STATE_POWER, 76 AggregatedPowerStatsConfig.STATE_SCREEN, 77 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 78 .setProcessorSupplier(() -> new BasePowerStatsProcessor(batteryCapacitySupplier)); 79 80 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WAKELOCK) 81 .trackDeviceStates( 82 AggregatedPowerStatsConfig.STATE_POWER, 83 AggregatedPowerStatsConfig.STATE_SCREEN) 84 .trackUidStates( 85 AggregatedPowerStatsConfig.STATE_POWER, 86 AggregatedPowerStatsConfig.STATE_SCREEN, 87 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 88 .setProcessorSupplier( 89 () -> new WakelockPowerStatsProcessor(powerProfile)); 90 91 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CPU, 92 BatteryConsumer.POWER_COMPONENT_WAKELOCK) 93 .setProcessorSupplier( 94 () -> new CpuPowerStatsProcessor(powerProfile, cpuScalingPolicies)); 95 96 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SCREEN) 97 .trackDeviceStates( 98 AggregatedPowerStatsConfig.STATE_POWER, 99 AggregatedPowerStatsConfig.STATE_SCREEN) 100 .trackUidStates( 101 AggregatedPowerStatsConfig.STATE_POWER, 102 AggregatedPowerStatsConfig.STATE_SCREEN) 103 .setProcessorSupplier( 104 () -> new ScreenPowerStatsProcessor(powerProfile)); 105 106 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, 107 BatteryConsumer.POWER_COMPONENT_SCREEN) 108 .setProcessorSupplier(AmbientDisplayPowerStatsProcessor::new); 109 110 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO) 111 .trackDeviceStates( 112 AggregatedPowerStatsConfig.STATE_POWER, 113 AggregatedPowerStatsConfig.STATE_SCREEN) 114 .trackUidStates( 115 AggregatedPowerStatsConfig.STATE_POWER, 116 AggregatedPowerStatsConfig.STATE_SCREEN, 117 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 118 .setProcessorSupplier( 119 () -> new MobileRadioPowerStatsProcessor(powerProfile)); 120 121 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE, 122 BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO) 123 .setProcessorSupplier(PhoneCallPowerStatsProcessor::new); 124 125 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI) 126 .trackDeviceStates( 127 AggregatedPowerStatsConfig.STATE_POWER, 128 AggregatedPowerStatsConfig.STATE_SCREEN) 129 .trackUidStates( 130 AggregatedPowerStatsConfig.STATE_POWER, 131 AggregatedPowerStatsConfig.STATE_SCREEN, 132 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 133 .setProcessorSupplier( 134 () -> new WifiPowerStatsProcessor(powerProfile)); 135 136 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_BLUETOOTH) 137 .trackDeviceStates( 138 AggregatedPowerStatsConfig.STATE_POWER, 139 AggregatedPowerStatsConfig.STATE_SCREEN) 140 .trackUidStates( 141 AggregatedPowerStatsConfig.STATE_POWER, 142 AggregatedPowerStatsConfig.STATE_SCREEN, 143 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 144 .setProcessorSupplier( 145 () -> new BluetoothPowerStatsProcessor(powerProfile)); 146 147 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_AUDIO) 148 .trackDeviceStates( 149 AggregatedPowerStatsConfig.STATE_POWER, 150 AggregatedPowerStatsConfig.STATE_SCREEN) 151 .trackUidStates( 152 AggregatedPowerStatsConfig.STATE_POWER, 153 AggregatedPowerStatsConfig.STATE_SCREEN, 154 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 155 .setProcessorSupplier( 156 () -> new AudioPowerStatsProcessor(powerProfile)); 157 158 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_VIDEO) 159 .trackDeviceStates( 160 AggregatedPowerStatsConfig.STATE_POWER, 161 AggregatedPowerStatsConfig.STATE_SCREEN) 162 .trackUidStates( 163 AggregatedPowerStatsConfig.STATE_POWER, 164 AggregatedPowerStatsConfig.STATE_SCREEN, 165 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 166 .setProcessorSupplier( 167 () -> new VideoPowerStatsProcessor(powerProfile)); 168 169 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT) 170 .trackDeviceStates( 171 AggregatedPowerStatsConfig.STATE_POWER, 172 AggregatedPowerStatsConfig.STATE_SCREEN) 173 .trackUidStates( 174 AggregatedPowerStatsConfig.STATE_POWER, 175 AggregatedPowerStatsConfig.STATE_SCREEN, 176 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 177 .setProcessorSupplier( 178 () -> new FlashlightPowerStatsProcessor(powerProfile)); 179 180 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_CAMERA) 181 .trackDeviceStates( 182 AggregatedPowerStatsConfig.STATE_POWER, 183 AggregatedPowerStatsConfig.STATE_SCREEN) 184 .trackUidStates( 185 AggregatedPowerStatsConfig.STATE_POWER, 186 AggregatedPowerStatsConfig.STATE_SCREEN, 187 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 188 .setProcessorSupplier( 189 () -> new CameraPowerStatsProcessor(powerProfile)); 190 191 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_GNSS) 192 .trackDeviceStates( 193 AggregatedPowerStatsConfig.STATE_POWER, 194 AggregatedPowerStatsConfig.STATE_SCREEN) 195 .trackUidStates( 196 AggregatedPowerStatsConfig.STATE_POWER, 197 AggregatedPowerStatsConfig.STATE_SCREEN, 198 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 199 .setProcessorSupplier( 200 () -> new GnssPowerStatsProcessor(powerProfile)); 201 202 config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_SENSORS) 203 .trackDeviceStates( 204 AggregatedPowerStatsConfig.STATE_POWER, 205 AggregatedPowerStatsConfig.STATE_SCREEN) 206 .trackUidStates( 207 AggregatedPowerStatsConfig.STATE_POWER, 208 AggregatedPowerStatsConfig.STATE_SCREEN, 209 AggregatedPowerStatsConfig.STATE_PROCESS_STATE) 210 .setProcessorSupplier(() -> new SensorPowerStatsProcessor( 211 () -> context.getSystemService(SensorManager.class))); 212 213 config.trackCustomPowerComponents(CustomEnergyConsumerPowerStatsProcessor::new) 214 .trackDeviceStates( 215 AggregatedPowerStatsConfig.STATE_POWER, 216 AggregatedPowerStatsConfig.STATE_SCREEN) 217 .trackUidStates( 218 AggregatedPowerStatsConfig.STATE_POWER, 219 AggregatedPowerStatsConfig.STATE_SCREEN, 220 AggregatedPowerStatsConfig.STATE_PROCESS_STATE); 221 return config; 222 } 223 224 /** 225 * Marks the specified power component as supported by this PowerAttributor 226 */ setPowerComponentSupported(@atteryConsumer.PowerComponentId int powerComponentId, boolean enabled)227 public void setPowerComponentSupported(@BatteryConsumer.PowerComponentId int powerComponentId, 228 boolean enabled) { 229 mPowerStatsExporterEnabled.put(powerComponentId, enabled); 230 mPowerStatsExporter.setPowerComponentEnabled(powerComponentId, enabled); 231 } 232 233 @Override isPowerComponentSupported( @atteryConsumer.PowerComponentId int powerComponentId)234 public boolean isPowerComponentSupported( 235 @BatteryConsumer.PowerComponentId int powerComponentId) { 236 return mPowerStatsExporterEnabled.get(powerComponentId); 237 } 238 239 @Override estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder, BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime)240 public void estimatePowerConsumption(BatteryUsageStats.Builder batteryUsageStatsBuilder, 241 BatteryStatsHistory batteryHistory, long monotonicStartTime, long monotonicEndTime) { 242 mPowerStatsExporter.exportAggregatedPowerStats(batteryUsageStatsBuilder, batteryHistory, 243 monotonicStartTime, monotonicEndTime); 244 } 245 246 @Override dumpEstimatedPowerConsumption(IndentingPrintWriter ipw, BatteryStatsHistory batteryStatsHistory, long startTime, long endTime)247 public void dumpEstimatedPowerConsumption(IndentingPrintWriter ipw, 248 BatteryStatsHistory batteryStatsHistory, 249 long startTime, long endTime) { 250 mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTime, 251 stats -> { 252 // Create a PowerStatsSpan for consistency of the textual output 253 PowerStatsSpan span = createPowerStatsSpan(stats); 254 if (span != null) { 255 span.dump(ipw); 256 } 257 }); 258 } 259 260 @Override storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory, long startTime, long endTimeMs)261 public long storeEstimatedPowerConsumption(BatteryStatsHistory batteryStatsHistory, 262 long startTime, long endTimeMs) { 263 long[] lastSavedMonotonicTime = new long[1]; 264 mPowerStatsAggregator.aggregatePowerStats(batteryStatsHistory, startTime, endTimeMs, 265 stats -> { 266 storeAggregatedPowerStats(stats); 267 lastSavedMonotonicTime[0] = stats.getStartTime() + stats.getDuration(); 268 }); 269 return lastSavedMonotonicTime[0]; 270 } 271 272 @VisibleForTesting storeAggregatedPowerStats(AggregatedPowerStats stats)273 void storeAggregatedPowerStats(AggregatedPowerStats stats) { 274 PowerStatsSpan span = createPowerStatsSpan(stats); 275 if (span == null) { 276 return; 277 } 278 mPowerStatsStore.storePowerStatsSpan(span); 279 } 280 createPowerStatsSpan(AggregatedPowerStats stats)281 private static PowerStatsSpan createPowerStatsSpan(AggregatedPowerStats stats) { 282 List<AggregatedPowerStats.ClockUpdate> clockUpdates = stats.getClockUpdates(); 283 if (clockUpdates.isEmpty()) { 284 Slog.w(TAG, "No clock updates in aggregated power stats " + stats); 285 return null; 286 } 287 288 long monotonicTime = clockUpdates.get(0).monotonicTime; 289 long durationSum = 0; 290 PowerStatsSpan span = new PowerStatsSpan(monotonicTime); 291 for (int i = 0; i < clockUpdates.size(); i++) { 292 AggregatedPowerStats.ClockUpdate clockUpdate = clockUpdates.get(i); 293 long duration; 294 if (i == clockUpdates.size() - 1) { 295 duration = stats.getDuration() - durationSum; 296 } else { 297 duration = clockUpdate.monotonicTime - monotonicTime; 298 } 299 span.addTimeFrame(clockUpdate.monotonicTime, clockUpdate.currentTime, duration); 300 monotonicTime = clockUpdate.monotonicTime; 301 durationSum += duration; 302 } 303 304 span.addSection(new AggregatedPowerStatsSection(stats)); 305 return span; 306 } 307 308 @Override getLastSavedEstimatesPowerConsumptionTimestamp()309 public long getLastSavedEstimatesPowerConsumptionTimestamp() { 310 long timestamp = -1; 311 for (PowerStatsSpan.Metadata metadata : mPowerStatsStore.getTableOfContents()) { 312 if (metadata.getSections().contains(AggregatedPowerStatsSection.TYPE)) { 313 for (PowerStatsSpan.TimeFrame timeFrame : metadata.getTimeFrames()) { 314 long endMonotonicTime = timeFrame.startMonotonicTime + timeFrame.duration; 315 if (endMonotonicTime > timestamp) { 316 timestamp = endMonotonicTime; 317 } 318 } 319 } 320 } 321 return timestamp; 322 } 323 } 324