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