1 /* 2 * Copyright (C) 2018 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 */ 16 package com.android.server.power.batterysaver; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.anyInt; 21 import static org.mockito.ArgumentMatchers.anyString; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.reset; 24 import static org.mockito.Mockito.times; 25 import static org.mockito.Mockito.verify; 26 27 import android.metrics.LogMaker; 28 import android.support.test.filters.SmallTest; 29 import android.support.test.runner.AndroidJUnit4; 30 31 import com.android.internal.logging.MetricsLogger; 32 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 33 import com.android.server.power.batterysaver.BatterySavingStats.BatterySaverState; 34 import com.android.server.power.batterysaver.BatterySavingStats.DozeState; 35 import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState; 36 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.mockito.ArgumentCaptor; 40 41 import java.io.ByteArrayOutputStream; 42 import java.io.PrintWriter; 43 44 /** 45 atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySavingStatsTest.java 46 */ 47 @SmallTest 48 @RunWith(AndroidJUnit4.class) 49 public class BatterySavingStatsTest { 50 private class BatterySavingStatsTestable extends BatterySavingStats { 51 private long mTime = 1_000_000; // Some random starting time. 52 53 private int mBatteryLevel = 1_000_000_000; 54 55 private BatterySavingStatsTestable() { 56 super(new Object(), mMetricsLogger); 57 } 58 59 @Override 60 long injectCurrentTime() { 61 return mTime; 62 } 63 64 @Override 65 int injectBatteryLevel() { 66 return mBatteryLevel; 67 } 68 69 @Override 70 int injectBatteryPercent() { 71 return mBatteryLevel / 10; 72 } 73 74 void assertDumpable() { 75 final ByteArrayOutputStream out = new ByteArrayOutputStream(); 76 dump(new PrintWriter(out), ""); // Just make sure it won't crash. 77 } 78 79 void advanceClock(int minutes) { 80 mTime += 60_000 * minutes; 81 } 82 83 void drainBattery(int value) { 84 mBatteryLevel -= value; 85 if (mBatteryLevel < 0) { 86 mBatteryLevel = 0; 87 } 88 } 89 90 String toDebugString() { 91 final StringBuilder sb = new StringBuilder(); 92 String sep = ""; 93 for (int i = 0; i < mStats.size(); i++) { 94 sb.append(sep); 95 sb.append(stateToString(mStats.keyAt(i))); 96 sb.append(":"); 97 sb.append(mStats.valueAt(i).toStringForTest()); 98 sep = "\n"; 99 } 100 return sb.toString(); 101 } 102 } 103 104 public MetricsLogger mMetricsLogger = mock(MetricsLogger.class); 105 106 private boolean sendTronEvents; 107 108 @Test 109 public void testAll_withTron() { 110 sendTronEvents = true; 111 checkAll(); 112 } 113 114 @Test 115 public void testAll_noTron() { 116 sendTronEvents = false; 117 checkAll(); 118 } 119 120 private void checkAll() { 121 final BatterySavingStatsTestable target = new BatterySavingStatsTestable(); 122 target.setSendTronLog(sendTronEvents); 123 124 target.assertDumpable(); 125 126 target.advanceClock(1); 127 target.drainBattery(200); 128 129 target.transitionState( 130 BatterySaverState.OFF, 131 InteractiveState.INTERACTIVE, 132 DozeState.NOT_DOZING); 133 134 target.advanceClock(4); 135 target.drainBattery(100); 136 137 target.transitionState( 138 BatterySaverState.OFF, 139 InteractiveState.NON_INTERACTIVE, 140 DozeState.NOT_DOZING); 141 142 target.advanceClock(2); 143 target.drainBattery(500); 144 145 target.transitionState( 146 BatterySaverState.OFF, 147 InteractiveState.INTERACTIVE, 148 DozeState.NOT_DOZING); 149 150 target.advanceClock(4); 151 target.drainBattery(100); 152 153 target.transitionState( 154 BatterySaverState.OFF, 155 InteractiveState.NON_INTERACTIVE, 156 DozeState.NOT_DOZING); 157 158 target.advanceClock(2); 159 target.drainBattery(500); 160 161 target.transitionState( 162 BatterySaverState.OFF, 163 InteractiveState.INTERACTIVE, 164 DozeState.NOT_DOZING); 165 166 target.advanceClock(3); 167 target.drainBattery(100); 168 169 target.transitionState( 170 BatterySaverState.OFF, 171 InteractiveState.NON_INTERACTIVE, 172 DozeState.LIGHT); 173 174 target.advanceClock(5); 175 target.drainBattery(100); 176 177 target.transitionState( 178 BatterySaverState.OFF, 179 InteractiveState.NON_INTERACTIVE, 180 DozeState.DEEP); 181 182 target.advanceClock(1); 183 target.drainBattery(200); 184 185 target.transitionState( 186 BatterySaverState.ON, 187 InteractiveState.INTERACTIVE, 188 DozeState.NOT_DOZING); 189 190 target.advanceClock(1); 191 target.drainBattery(300); 192 193 target.transitionState( 194 BatterySaverState.OFF, 195 InteractiveState.INTERACTIVE, 196 DozeState.NOT_DOZING); 197 198 target.advanceClock(3); 199 target.drainBattery(500); 200 201 target.transitionState( 202 BatterySaverState.ON, 203 InteractiveState.INTERACTIVE, 204 DozeState.NOT_DOZING); 205 206 target.advanceClock(3); 207 target.drainBattery(500); 208 209 target.startCharging(); 210 211 target.advanceClock(5); 212 target.drainBattery(1000); 213 214 target.transitionState( 215 BatterySaverState.ON, 216 InteractiveState.INTERACTIVE, 217 DozeState.NOT_DOZING); 218 219 target.advanceClock(5); 220 target.drainBattery(100); 221 222 target.startCharging(); 223 224 target.assertDumpable(); 225 226 assertEquals( 227 "BS=0,I=0,D=0:{4m,1000,15000.00uA/H,1500.00%}\n" + 228 "BS=1,I=0,D=0:{0m,0,0.00uA/H,0.00%}\n" + 229 "BS=0,I=1,D=0:{14m,800,3428.57uA/H,342.86%}\n" + 230 "BS=1,I=1,D=0:{9m,900,6000.00uA/H,600.00%}\n" + 231 "BS=0,I=0,D=1:{5m,100,1200.00uA/H,120.00%}\n" + 232 "BS=1,I=0,D=1:{0m,0,0.00uA/H,0.00%}\n" + 233 "BS=0,I=1,D=1:{0m,0,0.00uA/H,0.00%}\n" + 234 "BS=1,I=1,D=1:{0m,0,0.00uA/H,0.00%}\n" + 235 "BS=0,I=0,D=2:{1m,200,12000.00uA/H,1200.00%}\n" + 236 "BS=1,I=0,D=2:{0m,0,0.00uA/H,0.00%}\n" + 237 "BS=0,I=1,D=2:{0m,0,0.00uA/H,0.00%}\n" + 238 "BS=1,I=1,D=2:{0m,0,0.00uA/H,0.00%}", 239 target.toDebugString()); 240 } 241 242 private void assertLog(boolean batterySaver, boolean interactive, long deltaTimeMs, 243 int deltaBatteryLevelUa, int deltaBatteryLevelPercent) { 244 if (sendTronEvents) { 245 ArgumentCaptor<LogMaker> ac = ArgumentCaptor.forClass(LogMaker.class); 246 verify(mMetricsLogger, times(1)).write(ac.capture()); 247 248 LogMaker lm = ac.getValue(); 249 assertEquals(MetricsEvent.BATTERY_SAVER, lm.getCategory()); 250 assertEquals(batterySaver ? 1 : 0, 251 lm.getTaggedData(MetricsEvent.RESERVED_FOR_LOGBUILDER_SUBTYPE)); 252 assertEquals(interactive ? 1 : 0, lm.getTaggedData(MetricsEvent.FIELD_INTERACTIVE)); 253 assertEquals(deltaTimeMs, lm.getTaggedData(MetricsEvent.FIELD_DURATION_MILLIS)); 254 255 assertEquals(deltaBatteryLevelUa, 256 (int) lm.getTaggedData(MetricsEvent.FIELD_START_BATTERY_UA) 257 - (int) lm.getTaggedData(MetricsEvent.FIELD_END_BATTERY_UA)); 258 assertEquals(deltaBatteryLevelPercent, 259 (int) lm.getTaggedData(MetricsEvent.FIELD_START_BATTERY_PERCENT) 260 - (int) lm.getTaggedData(MetricsEvent.FIELD_END_BATTERY_PERCENT)); 261 } else { 262 verify(mMetricsLogger, times(0)).write(any(LogMaker.class)); 263 } 264 } 265 266 267 @Test 268 public void testMetricsLogger_withTron() { 269 sendTronEvents = true; 270 checkMetricsLogger(); 271 } 272 273 @Test 274 public void testMetricsLogger_noTron() { 275 sendTronEvents = false; 276 checkMetricsLogger(); 277 } 278 279 private void checkMetricsLogger() { 280 final BatterySavingStatsTestable target = new BatterySavingStatsTestable(); 281 target.setSendTronLog(sendTronEvents); 282 283 target.advanceClock(1); 284 target.drainBattery(1000); 285 286 target.transitionState( 287 BatterySaverState.OFF, 288 InteractiveState.INTERACTIVE, 289 DozeState.NOT_DOZING); 290 291 verify(mMetricsLogger, times(0)).count(anyString(), anyInt()); 292 293 target.advanceClock(1); 294 target.drainBattery(2000); 295 296 reset(mMetricsLogger); 297 target.transitionState( 298 BatterySaverState.OFF, 299 InteractiveState.NON_INTERACTIVE, 300 DozeState.NOT_DOZING); 301 302 assertLog(false, true, 60_000, 2000, 200); 303 304 target.advanceClock(1); 305 target.drainBattery(2000); 306 307 reset(mMetricsLogger); 308 target.transitionState( 309 BatterySaverState.OFF, 310 InteractiveState.NON_INTERACTIVE, 311 DozeState.DEEP); 312 313 target.advanceClock(1); 314 target.drainBattery(2000); 315 316 verify(mMetricsLogger, times(0)).count(anyString(), anyInt()); 317 318 target.transitionState( 319 BatterySaverState.OFF, 320 InteractiveState.NON_INTERACTIVE, 321 DozeState.LIGHT); 322 323 target.advanceClock(1); 324 target.drainBattery(2000); 325 326 verify(mMetricsLogger, times(0)).count(anyString(), anyInt()); 327 328 target.transitionState( 329 BatterySaverState.ON, 330 InteractiveState.INTERACTIVE, 331 DozeState.NOT_DOZING); 332 333 assertLog(false, false, 60_000 * 3, 2000 * 3, 200 * 3); 334 335 target.advanceClock(10); 336 target.drainBattery(10000); 337 338 reset(mMetricsLogger); 339 target.startCharging(); 340 341 assertLog(true, true, 60_000 * 10, 10000, 1000); 342 343 target.advanceClock(1); 344 target.drainBattery(2000); 345 346 reset(mMetricsLogger); 347 target.transitionState( 348 BatterySaverState.ON, 349 InteractiveState.NON_INTERACTIVE, 350 DozeState.NOT_DOZING); 351 352 verify(mMetricsLogger, times(0)).count(anyString(), anyInt()); 353 354 target.advanceClock(1); 355 target.drainBattery(2000); 356 357 target.startCharging(); 358 359 assertLog(true, false, 60_000, 2000, 200); 360 } 361 } 362