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 */
16package com.android.internal.os;
17
18import android.os.BatteryStats;
19import android.util.Log;
20
21public class BluetoothPowerCalculator extends PowerCalculator {
22    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
23    private static final String TAG = "BluetoothPowerCalculator";
24    private final double mIdleMa;
25    private final double mRxMa;
26    private final double mTxMa;
27    private double mAppTotalPowerMah = 0;
28    private long mAppTotalTimeMs = 0;
29
30    public BluetoothPowerCalculator(PowerProfile profile) {
31        mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
32        mRxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX);
33        mTxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX);
34    }
35
36    @Override
37    public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
38                             long rawUptimeUs, int statsType) {
39
40        final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
41        if (counter == null) {
42            return;
43        }
44
45        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
46        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
47        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
48        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
49        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
50                / (double)(1000*60*60);
51
52        if (powerMah == 0) {
53            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
54                    / (1000*60*60);
55        }
56
57        app.bluetoothPowerMah = powerMah;
58        app.bluetoothRunningTimeMs = totalTimeMs;
59        app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
60        app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
61
62        mAppTotalPowerMah += powerMah;
63        mAppTotalTimeMs += totalTimeMs;
64    }
65
66    @Override
67    public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
68                                   long rawUptimeUs, int statsType) {
69        final BatteryStats.ControllerActivityCounter counter =
70                stats.getBluetoothControllerActivity();
71
72        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
73        final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
74        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
75        final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
76        double powerMah = counter.getPowerCounter().getCountLocked(statsType)
77                 / (double)(1000*60*60);
78
79        if (powerMah == 0) {
80            // Some devices do not report the power, so calculate it.
81            powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
82                    / (1000*60*60);
83        }
84
85        // Subtract what the apps used, but clamp to 0.
86        powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
87
88        if (DEBUG && powerMah != 0) {
89            Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
90                    + " power=" + BatteryStatsHelper.makemAh(powerMah));
91        }
92
93        app.bluetoothPowerMah = powerMah;
94        app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
95    }
96
97    @Override
98    public void reset() {
99        mAppTotalPowerMah = 0;
100        mAppTotalTimeMs = 0;
101    }
102}
103