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;
19e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskiimport android.util.Log;
20e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
21e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskipublic class BluetoothPowerCalculator extends PowerCalculator {
22e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
23e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private static final String TAG = "BluetoothPowerCalculator";
248576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski    private final double mIdleMa;
258576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski    private final double mRxMa;
268576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski    private final double mTxMa;
279f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski    private double mAppTotalPowerMah = 0;
289f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski    private long mAppTotalTimeMs = 0;
298576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski
308576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski    public BluetoothPowerCalculator(PowerProfile profile) {
318576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski        mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
328576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski        mRxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX);
338576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski        mTxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX);
348576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski    }
35e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
36e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    @Override
37e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
38e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                             long rawUptimeUs, int statsType) {
399f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
409f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
419f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        if (counter == null) {
429f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski            return;
439f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        }
449f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
459f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
469f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
479f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
489f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
499f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
509f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski                / (double)(1000*60*60);
519f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
529f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        if (powerMah == 0) {
539f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
549f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski                    / (1000*60*60);
559f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        }
569f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
579f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.bluetoothPowerMah = powerMah;
589f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.bluetoothRunningTimeMs = totalTimeMs;
599f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
609f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
619f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
629f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        mAppTotalPowerMah += powerMah;
639f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        mAppTotalTimeMs += totalTimeMs;
64e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
65e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
66e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    @Override
67e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
68e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                                   long rawUptimeUs, int statsType) {
6921f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski        final BatteryStats.ControllerActivityCounter counter =
7021f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski                stats.getBluetoothControllerActivity();
7121f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski
7221f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
7321f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
7421f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
75e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
7621f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
7721f76aa77075be5e057c36040d7d6e695c669b72Adam Lesinski                 / (double)(1000*60*60);
788576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski
798576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski        if (powerMah == 0) {
808576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski            // Some devices do not report the power, so calculate it.
818576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
828576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski                    / (1000*60*60);
838576cf941dc20b64d60b6b7f5d0879b823628393Adam Lesinski        }
84e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
859f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        // Subtract what the apps used, but clamp to 0.
869f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
879f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
88e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        if (DEBUG && powerMah != 0) {
89e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
90e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                    + " power=" + BatteryStatsHelper.makemAh(powerMah));
91e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        }
92e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
939f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.bluetoothPowerMah = powerMah;
949f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
959f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski    }
969f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski
979f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski    @Override
989f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski    public void reset() {
999f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        mAppTotalPowerMah = 0;
1009f55cc71b9b0a27604d448b5c54e3c377b7a067fAdam Lesinski        mAppTotalTimeMs = 0;
101e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
102e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski}
103