• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  */
16 package com.android.internal.os;
17 
18 import android.os.BatteryStats;
19 import android.util.ArrayMap;
20 import android.util.Log;
21 
22 public class CpuPowerCalculator extends PowerCalculator {
23     private static final String TAG = "CpuPowerCalculator";
24     private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
25     private final PowerProfile mProfile;
26 
CpuPowerCalculator(PowerProfile profile)27     public CpuPowerCalculator(PowerProfile profile) {
28         mProfile = profile;
29     }
30 
31     @Override
calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType)32     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
33                              long rawUptimeUs, int statsType) {
34 
35         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
36 
37         // Aggregate total time spent on each cluster.
38         long totalTime = 0;
39         final int numClusters = mProfile.getNumCpuClusters();
40         for (int cluster = 0; cluster < numClusters; cluster++) {
41             final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
42             for (int speed = 0; speed < speedsForCluster; speed++) {
43                 totalTime += u.getTimeAtCpuSpeed(cluster, speed, statsType);
44             }
45         }
46         totalTime = Math.max(totalTime, 1);
47 
48         double cpuPowerMaMs = 0;
49         for (int cluster = 0; cluster < numClusters; cluster++) {
50             final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
51             for (int speed = 0; speed < speedsForCluster; speed++) {
52                 final double ratio = (double) u.getTimeAtCpuSpeed(cluster, speed, statsType) /
53                         totalTime;
54                 final double cpuSpeedStepPower = ratio * app.cpuTimeMs *
55                         mProfile.getAveragePowerForCpu(cluster, speed);
56                 if (DEBUG && ratio != 0) {
57                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
58                             + speed + " ratio=" + BatteryStatsHelper.makemAh(ratio) + " power="
59                             + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
60                 }
61                 cpuPowerMaMs += cpuSpeedStepPower;
62             }
63         }
64         app.cpuPowerMah = cpuPowerMaMs / (60 * 60 * 1000);
65 
66         if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
67             Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
68                     + BatteryStatsHelper.makemAh(app.cpuPowerMah));
69         }
70 
71         // Keep track of the package with highest drain.
72         double highestDrain = 0;
73 
74         app.cpuFgTimeMs = 0;
75         final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
76         final int processStatsCount = processStats.size();
77         for (int i = 0; i < processStatsCount; i++) {
78             final BatteryStats.Uid.Proc ps = processStats.valueAt(i);
79             final String processName = processStats.keyAt(i);
80             app.cpuFgTimeMs += ps.getForegroundTime(statsType);
81 
82             final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType)
83                     + ps.getForegroundTime(statsType);
84 
85             // Each App can have multiple packages and with multiple running processes.
86             // Keep track of the package who's process has the highest drain.
87             if (app.packageWithHighestDrain == null ||
88                     app.packageWithHighestDrain.startsWith("*")) {
89                 highestDrain = costValue;
90                 app.packageWithHighestDrain = processName;
91             } else if (highestDrain < costValue && !processName.startsWith("*")) {
92                 highestDrain = costValue;
93                 app.packageWithHighestDrain = processName;
94             }
95         }
96 
97         // Ensure that the CPU times make sense.
98         if (app.cpuFgTimeMs > app.cpuTimeMs) {
99             if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) {
100                 Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
101             }
102 
103             // Statistics may not have been gathered yet.
104             app.cpuTimeMs = app.cpuFgTimeMs;
105         }
106     }
107 }
108