1/*
2 * Copyright (C) 2016 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
17package com.android.internal.os;
18
19import android.os.BatteryStats;
20import android.os.Parcel;
21import android.support.test.filters.SmallTest;
22import android.util.StringBuilderPrinter;
23
24import junit.framework.Assert;
25import junit.framework.TestCase;
26
27import com.android.internal.os.BatteryStatsImpl.Clocks;
28import com.android.internal.os.BatteryStatsImpl.TimeBase;
29import com.android.internal.os.BatteryStatsImpl.Timer;
30
31/**
32 * Provides test cases for android.os.BatteryStats.
33 */
34public class BatteryStatsTimerTest extends TestCase {
35    private static final String TAG = "BatteryStatsTest";
36
37    class TestTimer extends Timer {
38        long nextComputeRunTime;
39        long lastComputeRunTimeRealtime;
40
41        int nextComputeCurrentCount;
42
43        TestTimer(Clocks clocks, int type, TimeBase timeBase, Parcel in) {
44            super(clocks, type, timeBase, in);
45        }
46
47        TestTimer(Clocks clocks, int type, TimeBase timeBase) {
48            super(clocks, type, timeBase);
49        }
50
51        protected long computeRunTimeLocked(long curBatteryRealtime) {
52            lastComputeRunTimeRealtime = curBatteryRealtime;
53            return nextComputeRunTime;
54        }
55
56        protected int computeCurrentCountLocked() {
57            return nextComputeCurrentCount;
58        }
59
60        public int getCount() {
61            return mCount;
62        }
63
64        public void setCount(int val) {
65            mCount = val;
66        }
67
68        public int getLoadedCount() {
69            return mLoadedCount;
70        }
71
72        public void setLoadedCount(int val) {
73            mLoadedCount = val;
74        }
75
76        public int getLastCount() {
77            return mLastCount;
78        }
79
80        public void setLastCount(int val) {
81            mLastCount = val;
82        }
83
84        public int getUnpluggedCount() {
85            return mUnpluggedCount;
86        }
87
88        public void setUnpluggedCount(int val) {
89            mUnpluggedCount = val;
90        }
91
92        public long getTotalTime() {
93            return mTotalTime;
94        }
95
96        public void setTotalTime(long val) {
97            mTotalTime = val;
98        }
99
100        public long getLoadedTime() {
101            return mLoadedTime;
102        }
103
104        public void setLoadedTime(long val) {
105            mLoadedTime = val;
106        }
107
108        public long getLastTime() {
109            return mLastTime;
110        }
111
112        public void setLastTime(long val) {
113            mLastTime = val;
114        }
115
116        public long getUnpluggedTime() {
117            return mUnpluggedTime;
118        }
119
120        public void setUnpluggedTime(long val) {
121            mUnpluggedTime = val;
122        }
123
124        public long getTimeBeforeMark() {
125            return mTimeBeforeMark;
126        }
127
128        public void setTimeBeforeMark(long val) {
129            mTimeBeforeMark = val;
130        }
131    }
132
133    /**
134     * Tests that the flow through TimeBase.setRunning propagates through
135     * to the timer.
136     */
137    @SmallTest
138    public void testRunning() throws Exception {
139        TimeBase timeBase = new TimeBase();
140        MockClocks clocks = new MockClocks();
141
142        TestTimer timer = new TestTimer(clocks, 0, timeBase);
143        timer.nextComputeCurrentCount = 3000;
144
145        // Test that starting the timer counts the unplugged time and counters
146        timer.nextComputeRunTime = 4;
147        timer.onTimeStarted(10, 20, 50);
148        Assert.assertEquals(50, timer.lastComputeRunTimeRealtime);
149        Assert.assertEquals(4, timer.getUnpluggedTime());
150        Assert.assertEquals(3000, timer.getUnpluggedCount());
151
152        // Test that stopping the timer updates mTotalTime and mCount
153        timer.nextComputeRunTime = 17;
154        timer.onTimeStopped(100, 130, 170);
155        Assert.assertEquals(17, timer.getTotalTime());
156        Assert.assertEquals(3000, timer.getCount());
157    }
158
159    /**
160     * Tests that the parcel can be parceled and unparceled without losing anything.
161     */
162    @SmallTest
163    public void testParceling() throws Exception {
164        TimeBase timeBase = new TimeBase();
165        MockClocks clocks = new MockClocks();
166
167        // Test write then read
168        TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
169        timer1.setCount(1);
170        timer1.setLoadedCount(3);
171        timer1.setLastCount(4);
172        timer1.setUnpluggedCount(5);
173        timer1.setTotalTime(9223372036854775807L);
174        timer1.setLoadedTime(9223372036854775806L);
175        timer1.setLastTime(9223372036854775805L);
176        timer1.setUnpluggedTime(9223372036854775804L);
177        timer1.setTimeBeforeMark(9223372036854775803L);
178        timer1.nextComputeRunTime = 201;
179        timer1.nextComputeCurrentCount = 2;
180
181        Parcel parcel = Parcel.obtain();
182        Timer.writeTimerToParcel(parcel, timer1, 77);
183
184        parcel.setDataPosition(0);
185        Assert.assertTrue("parcel null object", parcel.readInt() != 0);
186
187        TestTimer timer2 = new TestTimer(clocks, 0, timeBase, parcel);
188        Assert.assertEquals(2, timer2.getCount()); // from computeTotalCountLocked()
189        Assert.assertEquals(3, timer2.getLoadedCount());
190        Assert.assertEquals(0, timer2.getLastCount()); // NOT saved
191        Assert.assertEquals(5, timer2.getUnpluggedCount());
192        Assert.assertEquals(201, timer2.getTotalTime()); // from computeRunTimeLocked()
193        Assert.assertEquals(9223372036854775806L, timer2.getLoadedTime());
194        Assert.assertEquals(0, timer2.getLastTime()); // NOT saved
195        Assert.assertEquals(9223372036854775804L, timer2.getUnpluggedTime());
196        Assert.assertEquals(9223372036854775803L, timer2.getTimeBeforeMark());
197
198        parcel.recycle();
199    }
200
201    /**
202     * Tests that the parcel can be parceled and unparceled without losing anything.
203     */
204    @SmallTest
205    public void testParcelingNull() throws Exception {
206        // Test writing null
207        Parcel parcel = Parcel.obtain();
208        Timer.writeTimerToParcel(parcel, null, 88);
209
210        parcel.setDataPosition(0);
211        Assert.assertEquals(0, parcel.readInt());
212
213        parcel.recycle();
214    }
215
216    /**
217     * Tests that reset() clears the correct times.
218     */
219    @SmallTest
220    public void testResetNoDetach() throws Exception {
221        TimeBase timeBase = new TimeBase();
222        MockClocks clocks = new MockClocks();
223
224        TestTimer timer = new TestTimer(clocks, 0, timeBase);
225        timer.setCount(1);
226        timer.setLoadedCount(2);
227        timer.setLastCount(3);
228        timer.setUnpluggedCount(4);
229        timer.setTotalTime(9223372036854775807L);
230        timer.setLoadedTime(9223372036854775806L);
231        timer.setLastTime(9223372036854775805L);
232        timer.setUnpluggedTime(9223372036854775804L);
233        timer.setTimeBeforeMark(9223372036854775803L);
234
235        timer.reset(false);
236
237        Assert.assertEquals(0, timer.getCount());
238        Assert.assertEquals(0, timer.getLoadedCount());
239        Assert.assertEquals(0, timer.getLastCount());
240        Assert.assertEquals(4, timer.getUnpluggedCount());
241        Assert.assertEquals(0, timer.getTotalTime());
242        Assert.assertEquals(0, timer.getLoadedTime());
243        Assert.assertEquals(0, timer.getLastTime());
244        Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
245        Assert.assertEquals(0, timer.getTimeBeforeMark());
246
247        // reset(false) shouldn't remove it from the list
248        Assert.assertEquals(true, timeBase.hasObserver(timer));
249    }
250
251    /**
252     * Tests that reset() clears the correct times.
253     */
254    @SmallTest
255    public void testResetDetach() throws Exception {
256        TimeBase timeBase = new TimeBase();
257        MockClocks clocks = new MockClocks();
258
259        TestTimer timer = new TestTimer(clocks, 0, timeBase);
260        timer.setCount(1);
261        timer.setLoadedCount(2);
262        timer.setLastCount(3);
263        timer.setUnpluggedCount(4);
264        timer.setTotalTime(9223372036854775807L);
265        timer.setLoadedTime(9223372036854775806L);
266        timer.setLastTime(9223372036854775805L);
267        timer.setUnpluggedTime(9223372036854775804L);
268        timer.setTimeBeforeMark(9223372036854775803L);
269
270        timer.reset(true);
271
272        Assert.assertEquals(0, timer.getCount());
273        Assert.assertEquals(0, timer.getLoadedCount());
274        Assert.assertEquals(0, timer.getLastCount());
275        Assert.assertEquals(4, timer.getUnpluggedCount());
276        Assert.assertEquals(0, timer.getTotalTime());
277        Assert.assertEquals(0, timer.getLoadedTime());
278        Assert.assertEquals(0, timer.getLastTime());
279        Assert.assertEquals(9223372036854775804L, timer.getUnpluggedTime());
280        Assert.assertEquals(0, timer.getTimeBeforeMark());
281
282        // reset(true) should remove it from the list
283        Assert.assertEquals(false, timeBase.hasObserver(timer));
284    }
285
286    /**
287     * Tests reading and writing the summary to a parcel
288     */
289    @SmallTest
290    public void testSummaryParceling() throws Exception {
291        TimeBase timeBase = new TimeBase();
292        timeBase.setRunning(true, 10, 20);
293        timeBase.setRunning(false, 45, 60);
294        Assert.assertEquals(40, timeBase.getRealtime(200));
295        // the past uptime is 35 and the past runtime is 40
296
297        MockClocks clocks = new MockClocks();
298
299        TestTimer timer1 = new TestTimer(clocks, 0, timeBase);
300        timer1.setCount(1);
301        timer1.setLoadedCount(2);
302        timer1.setLastCount(3);
303        timer1.setUnpluggedCount(4);
304        timer1.setTotalTime(9223372036854775807L);
305        timer1.setLoadedTime(9223372036854775806L);
306        timer1.setLastTime(9223372036854775805L);
307        timer1.setUnpluggedTime(9223372036854775804L);
308        timer1.setTimeBeforeMark(9223372036854775803L);
309
310        Parcel parcel = Parcel.obtain();
311        timer1.nextComputeRunTime = 9223372036854775800L;
312        timer1.nextComputeCurrentCount = 1;
313        timer1.writeSummaryFromParcelLocked(parcel, 201);
314        Assert.assertEquals(40, timer1.lastComputeRunTimeRealtime);
315
316        TestTimer timer2 = new TestTimer(clocks, 0, timeBase);
317
318        // Make sure that all the values get touched
319        timer2.setCount(666);
320        timer2.setLoadedCount(666);
321        timer2.setLastCount(666);
322        timer2.setUnpluggedCount(666);
323        timer2.setTotalTime(666);
324        timer2.setLoadedTime(666);
325        timer2.setLastTime(666);
326        timer2.setUnpluggedTime(666);
327        timer2.setTimeBeforeMark(666);
328
329        parcel.setDataPosition(0);
330
331        parcel.setDataPosition(0);
332        timer2.readSummaryFromParcelLocked(parcel);
333
334        Assert.assertEquals(1, timer2.getCount());
335        Assert.assertEquals(1, timer2.getLoadedCount());
336        Assert.assertEquals(0, timer2.getLastCount());
337        Assert.assertEquals(1, timer2.getUnpluggedCount());
338        Assert.assertEquals(9223372036854775800L, timer2.getTotalTime());
339        Assert.assertEquals(9223372036854775800L, timer2.getLoadedTime());
340        Assert.assertEquals(0, timer2.getLastTime());
341        Assert.assertEquals(9223372036854775800L, timer2.getUnpluggedTime());
342        Assert.assertEquals(9223372036854775800L, timer2.getTimeBeforeMark());
343
344        parcel.recycle();
345    }
346
347    /**
348     * Tests getTotalTimeLocked
349     */
350    @SmallTest
351    public void testGetTotalTimeLocked() throws Exception {
352        TimeBase timeBase = new TimeBase();
353        timeBase.setRunning(true, 10, 20);
354        timeBase.setRunning(false, 45, 60);
355        Assert.assertEquals(40, timeBase.getRealtime(200));
356
357        MockClocks clocks = new MockClocks();
358
359        TestTimer timer = new TestTimer(clocks, 0, timeBase);
360        timer.setCount(1);
361        timer.setLoadedCount(2);
362        timer.setLastCount(3);
363        timer.setUnpluggedCount(4);
364        timer.setTotalTime(100);
365        timer.setLoadedTime(200);
366        timer.setLastTime(300);
367        timer.setUnpluggedTime(400);
368        timer.setTimeBeforeMark(500);
369
370        timer.nextComputeRunTime = 10000;
371
372        // Timer.getTotalTimeLocked(STATS_SINCE_CHARGED)
373        timer.lastComputeRunTimeRealtime = -1;
374        Assert.assertEquals(10000,
375                timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_CHARGED));
376        Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
377
378        // Timer.getTotalTimeLocked(STATS_CURRENT)
379        timer.lastComputeRunTimeRealtime = -1;
380        Assert.assertEquals(9800, timer.getTotalTimeLocked(66, BatteryStats.STATS_CURRENT));
381        Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
382
383        // Timer.getTotalTimeLocked(STATS_SINCE_UNPLUGGED)
384        timer.lastComputeRunTimeRealtime = -1;
385        Assert.assertEquals(9600, timer.getTotalTimeLocked(66, BatteryStats.STATS_SINCE_UNPLUGGED));
386        Assert.assertEquals(40, timer.lastComputeRunTimeRealtime);
387    }
388
389    /**
390     * Tests getCountLocked
391     */
392    @SmallTest
393    public void testGetCountLocked() throws Exception {
394        TimeBase timeBase = new TimeBase();
395        timeBase.setRunning(true, 10, 20);
396        timeBase.setRunning(false, 45, 60);
397        Assert.assertEquals(40, timeBase.getRealtime(200));
398
399        MockClocks clocks = new MockClocks();
400
401        TestTimer timer = new TestTimer(clocks, 0, timeBase);
402        timer.setCount(1);
403        timer.setLoadedCount(2);
404        timer.setLastCount(3);
405        timer.setUnpluggedCount(4);
406        timer.setTotalTime(100);
407        timer.setLoadedTime(200);
408        timer.setLastTime(300);
409        timer.setUnpluggedTime(400);
410        timer.setTimeBeforeMark(500);
411
412        // Timer.getCountLocked(STATS_SINCE_CHARGED)
413        timer.nextComputeCurrentCount = 10000;
414        Assert.assertEquals(10000, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
415
416        // Timer.getCountLocked(STATS_CURRENT)
417        timer.nextComputeCurrentCount = 10000;
418        Assert.assertEquals(9998, timer.getCountLocked(BatteryStats.STATS_CURRENT));
419
420        // Timer.getCountLocked(STATS_SINCE_UNPLUGGED)
421        timer.nextComputeCurrentCount = 10000;
422        Assert.assertEquals(9996, timer.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
423    }
424
425    /**
426     * Tests getTimeSinceMarkLocked
427     */
428    @SmallTest
429    public void testGetTimeSinceMarked() throws Exception {
430        TimeBase timeBase = new TimeBase();
431        timeBase.setRunning(true, 10, 20);
432        timeBase.setRunning(false, 45, 60);
433        Assert.assertEquals(40, timeBase.getRealtime(200));
434
435        MockClocks clocks = new MockClocks();
436
437        TestTimer timer = new TestTimer(clocks, 0, timeBase);
438        timer.setCount(1);
439        timer.setLoadedCount(2);
440        timer.setLastCount(3);
441        timer.setUnpluggedCount(4);
442        timer.setTotalTime(100);
443        timer.setLoadedTime(200);
444        timer.setLastTime(300);
445        timer.setUnpluggedTime(400);
446        timer.setTimeBeforeMark(500);
447
448        timer.nextComputeRunTime = 10000;
449        Assert.assertEquals(9500, timer.getTimeSinceMarkLocked(666));
450    }
451
452    /**
453     * Tests logState
454     */
455    @SmallTest
456    public void testLogState() throws Exception {
457        TimeBase timeBase = new TimeBase();
458        MockClocks clocks = new MockClocks();
459
460        TestTimer timer = new TestTimer(clocks, 0, timeBase);
461        timer.setTotalTime(100);
462        timer.setLoadedTime(200);
463        timer.setLastTime(300);
464        timer.setUnpluggedTime(400);
465        timer.setTimeBeforeMark(500);
466        timer.setCount(1);
467        timer.setLoadedCount(2);
468        timer.setLastCount(3);
469        timer.setUnpluggedCount(4);
470        timer.setTotalTime(9223372036854775807L);
471        timer.setLoadedTime(9223372036854775806L);
472        timer.setLastTime(9223372036854775805L);
473        timer.setUnpluggedTime(9223372036854775804L);
474        timer.setTimeBeforeMark(9223372036854775803L);
475
476        StringBuilder sb = new StringBuilder();
477        StringBuilderPrinter pw = new StringBuilderPrinter(sb);
478
479        timer.logState(pw, "  ");
480
481        Assert.assertEquals(
482                      "  mCount=1 mLoadedCount=2 mLastCount=3 mUnpluggedCount=4\n"
483                    + "  mTotalTime=9223372036854775807 mLoadedTime=9223372036854775806\n"
484                    + "  mLastTime=9223372036854775805 mUnpluggedTime=9223372036854775804\n",
485                sb.toString());
486    }
487}
488
489