1e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski/* 2e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * Copyright (C) 2015 The Android Open Source Project 3e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * 4e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * you may not use this file except in compliance with the License. 6e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * You may obtain a copy of the License at 7e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * 8e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * 10e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * See the License for the specific language governing permissions and 14e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * limitations under the License. 15e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski */ 16e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskipackage com.android.internal.os; 17e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 18e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskiimport android.os.BatteryStats; 191739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinskiimport android.util.Log; 20e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 21e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski/** 22e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * WiFi power calculator for when BatteryStats supports energy reporting 23e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski * from the WiFi controller. 24e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski */ 25e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskipublic class WifiPowerCalculator extends PowerCalculator { 261739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski private static final boolean DEBUG = BatteryStatsHelper.DEBUG; 271739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski private static final String TAG = "WifiPowerCalculator"; 28e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski private final double mIdleCurrentMa; 29e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski private final double mTxCurrentMa; 30e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski private final double mRxCurrentMa; 31e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski private double mTotalAppPowerDrain = 0; 329f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski private long mTotalAppRunningTime = 0; 33e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 34e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski public WifiPowerCalculator(PowerProfile profile) { 35e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski mIdleCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE); 36e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski mTxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX); 37e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski mRxCurrentMa = profile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX); 38e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski } 39e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 40e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski @Override 41e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, 42e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski long rawUptimeUs, int statsType) { 4321f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final BatteryStats.ControllerActivityCounter counter = u.getWifiControllerActivity(); 4421f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski if (counter == null) { 4521f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski return; 4621f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski } 4721f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski 4821f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long idleTime = counter.getIdleTimeCounter().getCountLocked(statsType); 4921f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long txTime = counter.getTxTimeCounters()[0].getCountLocked(statsType); 5021f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType); 51e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiRunningTimeMs = idleTime + rxTime + txTime; 529f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski mTotalAppRunningTime += app.wifiRunningTimeMs; 539f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski 54e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiPowerMah = 55e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski ((idleTime * mIdleCurrentMa) + (txTime * mTxCurrentMa) + (rxTime * mRxCurrentMa)) 56e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski / (1000*60*60); 57e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski mTotalAppPowerDrain += app.wifiPowerMah; 58e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 59e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiRxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_RX_DATA, 60e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski statsType); 61e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiTxPackets = u.getNetworkActivityPackets(BatteryStats.NETWORK_WIFI_TX_DATA, 62e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski statsType); 63e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_RX_DATA, 64e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski statsType); 65e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA, 66e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski statsType); 67083e1d9e4b32dde846b763474152664d62f5b3f1Mitchell Wills 68083e1d9e4b32dde846b763474152664d62f5b3f1Mitchell Wills if (DEBUG && app.wifiPowerMah != 0) { 69083e1d9e4b32dde846b763474152664d62f5b3f1Mitchell Wills Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime + "ms tx=" + 70083e1d9e4b32dde846b763474152664d62f5b3f1Mitchell Wills txTime + "ms power=" + BatteryStatsHelper.makemAh(app.wifiPowerMah)); 71083e1d9e4b32dde846b763474152664d62f5b3f1Mitchell Wills } 72e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski } 73e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 74e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski @Override 75e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs, 76e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski long rawUptimeUs, int statsType) { 7721f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final BatteryStats.ControllerActivityCounter counter = stats.getWifiControllerActivity(); 7821f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski 7921f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType); 8021f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType); 8121f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType); 829f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski 839f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski app.wifiRunningTimeMs = Math.max(0, 849f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski (idleTimeMs + rxTimeMs + txTimeMs) - mTotalAppRunningTime); 85e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 8621f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski double powerDrainMah = counter.getPowerCounter().getCountLocked(statsType) 8721f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski / (double)(1000*60*60); 888576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski if (powerDrainMah == 0) { 89e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski // Some controllers do not report power drain, so we can calculate it here. 908576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa) 91e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski + (rxTimeMs * mRxCurrentMa)) / (1000*60*60); 92e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski } 938576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski app.wifiPowerMah = Math.max(0, powerDrainMah - mTotalAppPowerDrain); 941739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski 951739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski if (DEBUG) { 961739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski Log.d(TAG, "left over WiFi power: " + BatteryStatsHelper.makemAh(app.wifiPowerMah)); 971739076ef9cc940c54cbde3f0576f0dc228f7d68Adam Lesinski } 98e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski } 99e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski 100e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski @Override 101e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski public void reset() { 102e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski mTotalAppPowerDrain = 0; 1039f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski mTotalAppRunningTime = 0; 104e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski } 105e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski} 106