blob: 101c321ab2c4338e781e6ae6a11dd88625bf4045 [file] [log] [blame]
Adam Lesinskie08af192015-03-25 16:42:59 -07001/*
2 * Copyright (C) 2015 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 */
16package com.android.internal.os;
17
18import android.os.BatteryStats;
19import android.util.ArrayMap;
20import android.util.Log;
21
22public class CpuPowerCalculator extends PowerCalculator {
23 private static final String TAG = "CpuPowerCalculator";
24 private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
Sudheer Shankaaf857412017-07-21 00:14:24 -070025 private static final long MICROSEC_IN_HR = (long) 60 * 60 * 1000 * 1000;
Adam Lesinski6832f392015-09-05 18:05:40 -070026 private final PowerProfile mProfile;
27
28 public CpuPowerCalculator(PowerProfile profile) {
29 mProfile = profile;
30 }
Adam Lesinskie08af192015-03-25 16:42:59 -070031
Adam Lesinskie08af192015-03-25 16:42:59 -070032 @Override
33 public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
Mike Ma3d422c32017-10-25 11:08:57 -070034 long rawUptimeUs, int statsType) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070035 app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
Adam Lesinski6832f392015-09-05 18:05:40 -070036 final int numClusters = mProfile.getNumCpuClusters();
Adam Lesinski6832f392015-09-05 18:05:40 -070037
Sudheer Shankaaf857412017-07-21 00:14:24 -070038 double cpuPowerMaUs = 0;
Adam Lesinski6832f392015-09-05 18:05:40 -070039 for (int cluster = 0; cluster < numClusters; cluster++) {
40 final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
41 for (int speed = 0; speed < speedsForCluster; speed++) {
Sudheer Shankaaf857412017-07-21 00:14:24 -070042 final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
43 final double cpuSpeedStepPower = timeUs *
Mike Ma3d422c32017-10-25 11:08:57 -070044 mProfile.getAveragePowerForCpuCore(cluster, speed);
Sudheer Shanka2fc52d42017-06-16 17:29:19 -070045 if (DEBUG) {
Adam Lesinski6832f392015-09-05 18:05:40 -070046 Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
Sudheer Shankaaf857412017-07-21 00:14:24 -070047 + speed + " timeUs=" + timeUs + " power="
48 + BatteryStatsHelper.makemAh(cpuSpeedStepPower / MICROSEC_IN_HR));
Adam Lesinski6832f392015-09-05 18:05:40 -070049 }
Sudheer Shankaaf857412017-07-21 00:14:24 -070050 cpuPowerMaUs += cpuSpeedStepPower;
Adam Lesinski6832f392015-09-05 18:05:40 -070051 }
52 }
Mike Ma2ab01442018-02-13 14:22:47 -080053 cpuPowerMaUs += u.getCpuActiveTime() * 1000 * mProfile.getAveragePower(
Mike Ma3d422c32017-10-25 11:08:57 -070054 PowerProfile.POWER_CPU_ACTIVE);
55 long[] cpuClusterTimes = u.getCpuClusterTimes();
56 if (cpuClusterTimes != null) {
57 if (cpuClusterTimes.length == numClusters) {
58 for (int i = 0; i < numClusters; i++) {
Mike Ma2ab01442018-02-13 14:22:47 -080059 double power =
60 cpuClusterTimes[i] * 1000 * mProfile.getAveragePowerForCpuCluster(i);
Mike Ma3d422c32017-10-25 11:08:57 -070061 cpuPowerMaUs += power;
62 if (DEBUG) {
63 Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + i + " clusterTimeUs="
64 + cpuClusterTimes[i] + " power="
65 + BatteryStatsHelper.makemAh(power / MICROSEC_IN_HR));
66 }
67 }
68 } else {
69 Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
70 + numClusters + " actual # " + cpuClusterTimes.length);
71 }
72 }
Sudheer Shankaaf857412017-07-21 00:14:24 -070073 app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
Adam Lesinski6832f392015-09-05 18:05:40 -070074
Adam Lesinskiab7672d2015-08-21 14:26:10 -070075 if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
76 Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
77 + BatteryStatsHelper.makemAh(app.cpuPowerMah));
Adam Lesinski06af1fa2015-05-05 17:35:35 -070078 }
79
Adam Lesinskie08af192015-03-25 16:42:59 -070080 // Keep track of the package with highest drain.
81 double highestDrain = 0;
82
Adam Lesinski06af1fa2015-05-05 17:35:35 -070083 app.cpuFgTimeMs = 0;
Adam Lesinskie08af192015-03-25 16:42:59 -070084 final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
85 final int processStatsCount = processStats.size();
86 for (int i = 0; i < processStatsCount; i++) {
87 final BatteryStats.Uid.Proc ps = processStats.valueAt(i);
88 final String processName = processStats.keyAt(i);
Adam Lesinskie08af192015-03-25 16:42:59 -070089 app.cpuFgTimeMs += ps.getForegroundTime(statsType);
Adam Lesinskie08af192015-03-25 16:42:59 -070090
Adam Lesinski06af1fa2015-05-05 17:35:35 -070091 final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType)
92 + ps.getForegroundTime(statsType);
Adam Lesinskie08af192015-03-25 16:42:59 -070093
94 // Each App can have multiple packages and with multiple running processes.
95 // Keep track of the package who's process has the highest drain.
96 if (app.packageWithHighestDrain == null ||
97 app.packageWithHighestDrain.startsWith("*")) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070098 highestDrain = costValue;
Adam Lesinskie08af192015-03-25 16:42:59 -070099 app.packageWithHighestDrain = processName;
Adam Lesinski06af1fa2015-05-05 17:35:35 -0700100 } else if (highestDrain < costValue && !processName.startsWith("*")) {
101 highestDrain = costValue;
Adam Lesinskie08af192015-03-25 16:42:59 -0700102 app.packageWithHighestDrain = processName;
103 }
104 }
105
106 // Ensure that the CPU times make sense.
107 if (app.cpuFgTimeMs > app.cpuTimeMs) {
108 if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) {
109 Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
110 }
111
112 // Statistics may not have been gathered yet.
113 app.cpuTimeMs = app.cpuFgTimeMs;
114 }
Adam Lesinskie08af192015-03-25 16:42:59 -0700115 }
116}