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.Log;
20 
21 /**
22  * WiFi power calculator for when BatteryStats supports energy reporting
23  * from the WiFi controller.
24  */
25 public class WifiPowerCalculator extends PowerCalculator {
26     private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
27     private static final String TAG = "WifiPowerCalculator";
28     private final double mIdleCurrentMa;
29     private final double mTxCurrentMa;
30     private final double mRxCurrentMa;
31     private double mTotalAppPowerDrain = 0;
32     private long mTotalAppRunningTime = 0;
33 
WifiPowerCalculator(PowerProfile profile)34     public WifiPowerCalculator(PowerProfile profile) {
35         mIdleCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE);
36         mTxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX);
37         mRxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX);
38     }
39 
40     @Override
calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType)41     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
42                              long rawUptimeUs, int statsType) {
43         final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity();
44         if (counter == null) {
45             return;
46         }
47 
48         final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType);
49         final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType);
50         final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
51         app.wifiRunningTimeMs = idleTime + rxTime + txTime;
52         mTotalAppRunningTime += app.wifiRunningTimeMs;
53 
54         app.wifiPowerMah =
55                 ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa))
56                 / (1000*60*60);
57         mTotalAppPowerDrain += app.wifiPowerMah;
58 
59         app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA,
60                 statsType);
61         app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA,
62                 statsType);
63         app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA,
64                 statsType);
65         app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
66                 statsType);
67 
68         if (DEBUG && app.wifiPowerMah != 0) {
69             Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime + "ms tx=" +
70                     txTime + "ms power=" + BatteryStatsHelper.makemAh(app.wifiPowerMah));
71         }
72     }
73 
74     @Override
calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, long rawUptimeUs, int statsType)75     public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
76                                    long rawUptimeUs, int statsType) {
77         final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity();
78 
79         final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
80         final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
81         final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
82 
83         app.wifiRunningTimeMs = Math.max(0,
84                 (idleTimeMs + rxTimeMs + txTimeMs) - mTotalAppRunningTime);
85 
86         double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType)
87                 / (double)(1000*60*60);
88         if (powerDrainMah == 0) {
89             // Some controllers do not report power drain, so we can calculate it here.
90             powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
91                     + (rxTimeMs * mRxCurrentMa)) / (1000*60*60);
92         }
93         app.wifiPowerMah = Math.max(0, powerDrainMah - mTotalAppPowerDrain);
94 
95         if (DEBUG) {
96             Log.d(TAG, "left over WiFi power: " + BatteryStatsHelper.makemAh(app.wifiPowerMah));
97         }
98     }
99 
100     @Override
reset()101     public void reset() {
102         mTotalAppPowerDrain = 0;
103         mTotalAppRunningTime = 0;
104     }
105 }
106