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.ArrayMap;
20e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskiimport android.util.Log;
21e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
22e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinskipublic class WakelockPowerCalculator extends PowerCalculator {
23e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private static final String TAG = "WakelockPowerCalculator";
24e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
25e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private final double mPowerWakelock;
26e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    private long mTotalAppWakelockTimeMs = 0;
27e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
28e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    public WakelockPowerCalculator(PowerProfile profile) {
29e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_AWAKE);
30e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
31e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
32e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    @Override
33f7808b7cf073175eb34a95760ef01e3dd61dd3eeAdam Lesinski    public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
34f7808b7cf073175eb34a95760ef01e3dd61dd3eeAdam Lesinski                             long rawUptimeUs, int statsType) {
35e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        long wakeLockTimeUs = 0;
36e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats =
37e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                u.getWakelockStats();
38e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        final int wakelockStatsCount = wakelockStats.size();
39e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        for (int i = 0; i < wakelockStatsCount; i++) {
40e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            final BatteryStats.Uid.Wakelock wakelock = wakelockStats.valueAt(i);
41e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
42e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            // Only care about partial wake locks since full wake locks
43e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            // are canceled when the user turns the screen off.
44e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
45e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            if (timer != null) {
46e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                wakeLockTimeUs += timer.getTotalTimeLocked(rawRealtimeUs, statsType);
47e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            }
48e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        }
49e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        app.wakeLockTimeMs = wakeLockTimeUs / 1000; // convert to millis
50e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        mTotalAppWakelockTimeMs += app.wakeLockTimeMs;
51e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
52e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        // Add cost of holding a wake lock.
53e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        app.wakeLockPowerMah = (app.wakeLockTimeMs * mPowerWakelock) / (1000*60*60);
54e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        if (DEBUG && app.wakeLockPowerMah != 0) {
55e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            Log.d(TAG, "UID " + u.getUid() + ": wake " + app.wakeLockTimeMs
56e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                    + " power=" + BatteryStatsHelper.makemAh(app.wakeLockPowerMah));
57e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        }
58e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
59e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
60e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    @Override
61e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    public void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
62e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                                   long rawUptimeUs, int statsType) {
63e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        long wakeTimeMillis = stats.getBatteryUptime(rawUptimeUs) / 1000;
64e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        wakeTimeMillis -= mTotalAppWakelockTimeMs
65e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                + (stats.getScreenOnTime(rawRealtimeUs, statsType) / 1000);
66e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        if (wakeTimeMillis > 0) {
67e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            final double power = (wakeTimeMillis * mPowerWakelock) / (1000*60*60);
68e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            if (DEBUG) {
69e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                Log.d(TAG, "OS wakeLockTime " + wakeTimeMillis + " power "
70e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski                        + BatteryStatsHelper.makemAh(power));
71e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            }
72e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            app.wakeLockTimeMs += wakeTimeMillis;
73e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski            app.wakeLockPowerMah += power;
74e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        }
75e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
76e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski
77e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    @Override
78e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    public void reset() {
79e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski        mTotalAppWakelockTimeMs = 0;
80e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski    }
81e08af19fcc7b13d526f3dfd24d58300947cf1146Adam Lesinski}
82