blob: a34e7f50c9c9fd005f395e4acb8c6505bb84d435 [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 Ma3d422c32017-10-25 11:08:57 -070053 cpuPowerMaUs += u.getCpuActiveTime() * mProfile.getAveragePower(
54 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++) {
59 double power = cpuClusterTimes[i] * mProfile.getAveragePowerForCpuCluster(i);
60 cpuPowerMaUs += power;
61 if (DEBUG) {
62 Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + i + " clusterTimeUs="
63 + cpuClusterTimes[i] + " power="
64 + BatteryStatsHelper.makemAh(power / MICROSEC_IN_HR));
65 }
66 }
67 } else {
68 Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
69 + numClusters + " actual # " + cpuClusterTimes.length);
70 }
71 }
Sudheer Shankaaf857412017-07-21 00:14:24 -070072 app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
Adam Lesinski6832f392015-09-05 18:05:40 -070073
Adam Lesinskiab7672d2015-08-21 14:26:10 -070074 if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
75 Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
76 + BatteryStatsHelper.makemAh(app.cpuPowerMah));
Adam Lesinski06af1fa2015-05-05 17:35:35 -070077 }
78
Adam Lesinskie08af192015-03-25 16:42:59 -070079 // Keep track of the package with highest drain.
80 double highestDrain = 0;
81
Adam Lesinski06af1fa2015-05-05 17:35:35 -070082 app.cpuFgTimeMs = 0;
Adam Lesinskie08af192015-03-25 16:42:59 -070083 final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
84 final int processStatsCount = processStats.size();
85 for (int i = 0; i < processStatsCount; i++) {
86 final BatteryStats.Uid.Proc ps = processStats.valueAt(i);
87 final String processName = processStats.keyAt(i);
Adam Lesinskie08af192015-03-25 16:42:59 -070088 app.cpuFgTimeMs += ps.getForegroundTime(statsType);
Adam Lesinskie08af192015-03-25 16:42:59 -070089
Adam Lesinski06af1fa2015-05-05 17:35:35 -070090 final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType)
91 + ps.getForegroundTime(statsType);
Adam Lesinskie08af192015-03-25 16:42:59 -070092
93 // Each App can have multiple packages and with multiple running processes.
94 // Keep track of the package who's process has the highest drain.
95 if (app.packageWithHighestDrain == null ||
96 app.packageWithHighestDrain.startsWith("*")) {
Adam Lesinski06af1fa2015-05-05 17:35:35 -070097 highestDrain = costValue;
Adam Lesinskie08af192015-03-25 16:42:59 -070098 app.packageWithHighestDrain = processName;
Adam Lesinski06af1fa2015-05-05 17:35:35 -070099 } else if (highestDrain < costValue && !processName.startsWith("*")) {
100 highestDrain = costValue;
Adam Lesinskie08af192015-03-25 16:42:59 -0700101 app.packageWithHighestDrain = processName;
102 }
103 }
104
105 // Ensure that the CPU times make sense.
106 if (app.cpuFgTimeMs > app.cpuTimeMs) {
107 if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) {
108 Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
109 }
110
111 // Statistics may not have been gathered yet.
112 app.cpuTimeMs = app.cpuFgTimeMs;
113 }
Adam Lesinskie08af192015-03-25 16:42:59 -0700114 }
115}