Home | History | Annotate | Download | only in os
      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 static final long MICROSEC_IN_HR = (long) 60 * 60 * 1000 * 1000;
     26     private final PowerProfile mProfile;
     27 
     28     public CpuPowerCalculator(PowerProfile profile) {
     29         mProfile = profile;
     30     }
     31 
     32     @Override
     33     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
     34             long rawUptimeUs, int statsType) {
     35         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
     36         final int numClusters = mProfile.getNumCpuClusters();
     37 
     38         double cpuPowerMaUs = 0;
     39         for (int cluster = 0; cluster < numClusters; cluster++) {
     40             final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
     41             for (int speed = 0; speed < speedsForCluster; speed++) {
     42                 final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
     43                 final double cpuSpeedStepPower = timeUs *
     44                         mProfile.getAveragePowerForCpuCore(cluster, speed);
     45                 if (DEBUG) {
     46                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
     47                             + speed + " timeUs=" + timeUs + " power="
     48                             + BatteryStatsHelper.makemAh(cpuSpeedStepPower / MICROSEC_IN_HR));
     49                 }
     50                 cpuPowerMaUs += cpuSpeedStepPower;
     51             }
     52         }
     53         cpuPowerMaUs += u.getCpuActiveTime() * 1000 * 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 =
     60                             cpuClusterTimes[i] * 1000 * mProfile.getAveragePowerForCpuCluster(i);
     61                     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         }
     73         app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
     74 
     75         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));
     78         }
     79 
     80         // Keep track of the package with highest drain.
     81         double highestDrain = 0;
     82 
     83         app.cpuFgTimeMs = 0;
     84         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);
     89             app.cpuFgTimeMs += ps.getForegroundTime(statsType);
     90 
     91             final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType)
     92                     + ps.getForegroundTime(statsType);
     93 
     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("*")) {
     98                 highestDrain = costValue;
     99                 app.packageWithHighestDrain = processName;
    100             } else if (highestDrain < costValue && !processName.startsWith("*")) {
    101                 highestDrain = costValue;
    102                 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         }
    115     }
    116 }
    117