Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 package com.android.internal.os;
     17 
     18 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
     19 
     20 import android.app.ActivityManager;
     21 import android.os.BatteryStats;
     22 import android.os.WorkSource;
     23 import android.support.test.filters.SmallTest;
     24 import android.util.ArrayMap;
     25 
     26 import junit.framework.TestCase;
     27 
     28 /**
     29  * Test BatteryStatsImpl onBatteryBackgroundTimeBase TimeBase.
     30  */
     31 public class BatteryStatsBackgroundStatsTest extends TestCase {
     32 
     33     private static final int UID = 10500;
     34 
     35     /** Test that BatteryStatsImpl.Uid.mOnBatteryBackgroundTimeBase works correctly. */
     36     @SmallTest
     37     public void testBgTimeBase() throws Exception {
     38         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
     39         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
     40         long cur = 0; // realtime in us
     41 
     42         BatteryStatsImpl.TimeBase bgtb = bi.getOnBatteryBackgroundTimeBase(UID);
     43 
     44         // Off-battery, non-existent
     45         clocks.realtime = clocks.uptime = 10;
     46         cur = clocks.realtime * 1000;
     47         bi.updateTimeBasesLocked(false, false, cur, cur); // off battery
     48         assertFalse(bgtb.isRunning());
     49         assertEquals(0, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     50 
     51         // Off-battery, foreground
     52         clocks.realtime = clocks.uptime = 100;
     53         cur = clocks.realtime * 1000;
     54         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
     55         assertFalse(bgtb.isRunning());
     56         assertEquals(0, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     57 
     58         // Off-battery, background
     59         clocks.realtime = clocks.uptime = 201;
     60         cur = clocks.realtime * 1000;
     61         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
     62         assertFalse(bgtb.isRunning());
     63         assertEquals(0, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     64 
     65         // On-battery, background
     66         clocks.realtime = clocks.uptime = 303;
     67         cur = clocks.realtime * 1000;
     68         bi.updateTimeBasesLocked(true, false, cur, cur); // on battery
     69         // still in ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
     70         assertTrue(bgtb.isRunning());
     71         assertEquals(0, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     72 
     73         // On-battery, background - but change screen state
     74         clocks.realtime = clocks.uptime = 409;
     75         cur = clocks.realtime * 1000;
     76         bi.updateTimeBasesLocked(true, true, cur, cur); // on battery (again)
     77         assertTrue(bgtb.isRunning());
     78         assertEquals(106_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     79 
     80         // On-battery, background - but a different background state
     81         clocks.realtime = clocks.uptime = 417;
     82         cur = clocks.realtime * 1000;
     83         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_RECEIVER); // background too
     84         assertTrue(bgtb.isRunning());
     85         assertEquals(114_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     86 
     87         // Off-battery, foreground
     88         clocks.realtime = clocks.uptime = 530;
     89         cur = clocks.realtime * 1000;
     90         bi.updateTimeBasesLocked(false, false, cur, cur); // off battery
     91         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
     92         assertFalse(bgtb.isRunning());
     93         assertEquals(227_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     94 
     95         // Off-battery, non-existent
     96         clocks.realtime = clocks.uptime = 690;
     97         cur = clocks.realtime * 1000;
     98         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_NONEXISTENT);
     99         assertFalse(bgtb.isRunning());
    100         assertEquals(227_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
    101     }
    102 
    103     /** Test that BatteryStatsImpl.Uid.mOnBatteryScreenOffBackgroundTimeBase works correctly. */
    104     @SmallTest
    105     public void testScreenOffBgTimeBase() throws Exception {
    106         final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
    107         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
    108         long cur = 0; // realtime in us
    109 
    110         BatteryStatsImpl.TimeBase bgtb = bi.getOnBatteryScreenOffBackgroundTimeBase(UID);
    111 
    112         // battery=off, screen=off, background=off
    113         cur = (clocks.realtime = clocks.uptime = 100) * 1000;
    114         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    115         bi.updateTimeBasesLocked(false, false, cur, cur);
    116         assertFalse(bgtb.isRunning());
    117 
    118         // battery=on, screen=off, background=off
    119         cur = (clocks.realtime = clocks.uptime = 200) * 1000;
    120         bi.updateTimeBasesLocked(true, false, cur, cur);
    121         assertFalse(bgtb.isRunning());
    122 
    123         // battery=on, screen=on, background=off
    124         cur = (clocks.realtime = clocks.uptime = 300) * 1000;
    125         bi.updateTimeBasesLocked(true, true, cur, cur);
    126         assertFalse(bgtb.isRunning());
    127 
    128         // battery=on, screen=on, background=on
    129         // Only during this period should the timebase progress
    130         cur = (clocks.realtime = clocks.uptime = 400) * 1000;
    131         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
    132         assertTrue(bgtb.isRunning());
    133 
    134         // battery=on, screen=off, background=on
    135         cur = (clocks.realtime = clocks.uptime = 550) * 1000;
    136         bi.updateTimeBasesLocked(true, false, cur, cur);
    137         assertFalse(bgtb.isRunning());
    138 
    139         // battery=off, screen=off, background=on
    140         cur = (clocks.realtime = clocks.uptime = 660) * 1000;
    141         bi.updateTimeBasesLocked(false, false, cur, cur);
    142         assertFalse(bgtb.isRunning());
    143 
    144         // battery=off, screen=off, background=off
    145         cur = (clocks.realtime = clocks.uptime = 770) * 1000;
    146         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    147         assertFalse(bgtb.isRunning());
    148 
    149         assertEquals(150_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
    150     }
    151 
    152     @SmallTest
    153     public void testWifiScan() throws Exception {
    154         final MockClocks clocks = new MockClocks();
    155         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
    156         long curr = 0; // realtime in us
    157 
    158         // On battery
    159         curr = 1000 * (clocks.realtime = clocks.uptime = 100);
    160         bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
    161         // App in foreground
    162         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    163 
    164         // Start timer
    165         curr = 1000 * (clocks.realtime = clocks.uptime = 202);
    166         bi.noteWifiScanStartedLocked(UID);
    167 
    168         // Move to background
    169         curr = 1000 * (clocks.realtime = clocks.uptime = 254);
    170         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
    171 
    172         // Off battery
    173         curr = 1000 * (clocks.realtime = clocks.uptime = 305);
    174         bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
    175 
    176         // Stop timer
    177         curr = 1000 * (clocks.realtime = clocks.uptime = 409);
    178         bi.noteWifiScanStoppedLocked(UID);
    179 
    180         // Test
    181         curr = 1000 * (clocks.realtime = clocks.uptime = 657);
    182         long time = bi.getUidStats().get(UID).getWifiScanTime(curr, STATS_SINCE_CHARGED);
    183         int count = bi.getUidStats().get(UID).getWifiScanCount(STATS_SINCE_CHARGED);
    184         int bgCount = bi.getUidStats().get(UID).getWifiScanBackgroundCount(STATS_SINCE_CHARGED);
    185         long actualTime = bi.getUidStats().get(UID).getWifiScanActualTime(curr);
    186         long bgTime = bi.getUidStats().get(UID).getWifiScanBackgroundTime(curr);
    187         assertEquals((305 - 202) * 1000, time);
    188         assertEquals(1, count);
    189         assertEquals(0, bgCount);
    190         assertEquals((305 - 202) * 1000, actualTime);
    191         assertEquals((305 - 254) * 1000, bgTime);
    192     }
    193 
    194     @SmallTest
    195     public void testAppBluetoothScan() throws Exception {
    196         final MockClocks clocks = new MockClocks();
    197         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
    198         WorkSource ws = new WorkSource(UID); // needed for bluetooth
    199         long curr = 0; // realtime in us
    200 
    201         // On battery
    202         curr = 1000 * (clocks.realtime = clocks.uptime = 100);
    203         bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
    204 
    205         // App in foreground
    206         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    207 
    208         // Start timer (optimized)
    209         curr = 1000 * (clocks.realtime = clocks.uptime = 202);
    210         bi.noteBluetoothScanStartedFromSourceLocked(ws, false);
    211 
    212         // Move to background
    213         curr = 1000 * (clocks.realtime = clocks.uptime = 254);
    214         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
    215 
    216         // Off battery
    217         curr = 1000 * (clocks.realtime = clocks.uptime = 305);
    218         bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
    219 
    220         // Stop timer
    221         curr = 1000 * (clocks.realtime = clocks.uptime = 409);
    222         bi.noteBluetoothScanStoppedFromSourceLocked(ws);
    223 
    224         // Start timer (unoptimized)
    225         curr = 1000 * (clocks.realtime = clocks.uptime = 1000);
    226         bi.noteBluetoothScanStartedFromSourceLocked(ws, true);
    227 
    228         // On battery
    229         curr = 1000 * (clocks.realtime = clocks.uptime = 2001);
    230         bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
    231 
    232         // Move to foreground
    233         curr = 1000 * (clocks.realtime = clocks.uptime = 3004);
    234         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
    235 
    236         // Stop timer
    237         curr = 1000 * (clocks.realtime = clocks.uptime = 4008);
    238         bi.noteBluetoothScanStoppedFromSourceLocked(ws);
    239 
    240         // Test
    241         curr = 1000 * (clocks.realtime = clocks.uptime = 5000);
    242         BatteryStats.Timer timer = bi.getUidStats().get(UID).getBluetoothScanTimer();
    243         BatteryStats.Timer bgTimer = bi.getUidStats().get(UID).getBluetoothScanBackgroundTimer();
    244         BatteryStats.Timer badTimer = bi.getUidStats().get(UID).getBluetoothUnoptimizedScanTimer();
    245         BatteryStats.Timer badBgTimer = bi.getUidStats().get(UID)
    246                 .getBluetoothUnoptimizedScanBackgroundTimer();
    247 
    248         long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
    249         int count = timer.getCountLocked(STATS_SINCE_CHARGED);
    250         int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
    251         long actualTime = timer.getTotalDurationMsLocked(clocks.realtime) * 1000;
    252         long bgTime = bgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
    253         long badTime = badTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
    254         long badBgTime = badBgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
    255         assertEquals((305 - 202 + 4008 - 2001) * 1000, time);
    256         assertEquals(1, count); // second scan starts off-battery
    257         assertEquals(0, bgCount); // first scan starts in fg, second starts off-battery
    258         assertEquals((305 - 202 + 4008 - 2001) * 1000, actualTime);
    259         assertEquals((305 - 254 + 3004 - 2001) * 1000, bgTime);
    260         assertEquals((4008 - 2001) * 1000, badTime);
    261         assertEquals((3004 - 2001) * 1000, badBgTime);
    262     }
    263 
    264     @SmallTest
    265     public void testJob() throws Exception {
    266         final MockClocks clocks = new MockClocks();
    267         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
    268         final String jobName = "job_name";
    269         long curr = 0; // realtime in us
    270 
    271         // On battery
    272         curr = 1000 * (clocks.realtime = clocks.uptime = 100);
    273         bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
    274         // App in foreground
    275         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    276 
    277         // Start timer
    278         curr = 1000 * (clocks.realtime = clocks.uptime = 151);
    279         bi.noteJobStartLocked(jobName, UID);
    280 
    281         // Stop timer
    282         curr = 1000 * (clocks.realtime = clocks.uptime = 161);
    283         bi.noteJobFinishLocked(jobName, UID);
    284 
    285         // Move to background
    286         curr = 1000 * (clocks.realtime = clocks.uptime = 202);
    287         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
    288 
    289         // Start timer
    290         curr = 1000 * (clocks.realtime = clocks.uptime = 254);
    291         bi.noteJobStartLocked(jobName, UID);
    292 
    293         // Off battery
    294         curr = 1000 * (clocks.realtime = clocks.uptime = 305);
    295         bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
    296 
    297         // Stop timer
    298         curr = 1000 * (clocks.realtime = clocks.uptime = 409);
    299         bi.noteJobFinishLocked(jobName, UID);
    300 
    301         // Test
    302         curr = 1000 * (clocks.realtime = clocks.uptime = 657);
    303         final ArrayMap<String, ? extends BatteryStats.Timer> jobs =
    304                 bi.getUidStats().get(UID).getJobStats();
    305         assertEquals(1, jobs.size());
    306         BatteryStats.Timer timer = jobs.valueAt(0);
    307         BatteryStats.Timer bgTimer = timer.getSubTimer();
    308         long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
    309         int count = timer.getCountLocked(STATS_SINCE_CHARGED);
    310         int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
    311         long bgTime = bgTimer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
    312         assertEquals((161 - 151 + 305 - 254) * 1000, time);
    313         assertEquals(2, count);
    314         assertEquals(1, bgCount);
    315         assertEquals((305 - 254) * 1000, bgTime);
    316 
    317         // Test that a second job is separate.
    318         curr = 1000 * (clocks.realtime = clocks.uptime = 3000);
    319         final String jobName2 = "second_job";
    320         bi.noteJobStartLocked(jobName2, UID);
    321         assertEquals(2, bi.getUidStats().get(UID).getJobStats().size());
    322         bi.noteJobFinishLocked(jobName2, UID);
    323     }
    324 
    325     @SmallTest
    326     public void testSyncs() throws Exception {
    327         final MockClocks clocks = new MockClocks();
    328         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
    329         final String syncName = "sync_name";
    330         long curr = 0; // realtime in us
    331 
    332         // On battery
    333         curr = 1000 * (clocks.realtime = clocks.uptime = 100);
    334         bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
    335         // App in foreground
    336         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
    337 
    338         // Start timer
    339         curr = 1000 * (clocks.realtime = clocks.uptime = 151);
    340         bi.noteSyncStartLocked(syncName, UID);
    341 
    342         // Stop timer
    343         curr = 1000 * (clocks.realtime = clocks.uptime = 161);
    344         bi.noteSyncFinishLocked(syncName, UID);
    345 
    346         // Move to background
    347         curr = 1000 * (clocks.realtime = clocks.uptime = 202);
    348         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
    349 
    350         // Start timer
    351         curr = 1000 * (clocks.realtime = clocks.uptime = 254);
    352         bi.noteSyncStartLocked(syncName, UID);
    353 
    354         // Off battery
    355         curr = 1000 * (clocks.realtime = clocks.uptime = 305);
    356         bi.updateTimeBasesLocked(false, false, curr, curr); // off battery
    357 
    358         // Stop timer
    359         curr = 1000 * (clocks.realtime = clocks.uptime = 409);
    360         bi.noteSyncFinishLocked(syncName, UID);
    361 
    362         // Test
    363         curr = 1000 * (clocks.realtime = clocks.uptime = 657);
    364         final ArrayMap<String, ? extends BatteryStats.Timer> syncs =
    365                 bi.getUidStats().get(UID).getSyncStats();
    366         assertEquals(1, syncs.size());
    367         BatteryStats.Timer timer = syncs.valueAt(0);
    368         BatteryStats.Timer bgTimer = timer.getSubTimer();
    369         long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
    370         int count = timer.getCountLocked(STATS_SINCE_CHARGED);
    371         int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
    372         long bgTime = bgTimer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
    373         assertEquals((161 - 151 + 305 - 254) * 1000, time);
    374         assertEquals(2, count);
    375         assertEquals(1, bgCount);
    376         assertEquals((305 - 254) * 1000, bgTime);
    377 
    378         // Test that a second sync is separate.
    379         curr = 1000 * (clocks.realtime = clocks.uptime = 3000);
    380         final String syncName2 = "second_sync";
    381         bi.noteSyncStartLocked(syncName2, UID);
    382         assertEquals(2, bi.getUidStats().get(UID).getSyncStats().size());
    383         bi.noteSyncFinishLocked(syncName2, UID);
    384     }
    385 }
    386