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 
17 package com.android.internal.os;
18 
19 import android.os.BatteryStats;
20 import android.os.Parcel;
21 import android.util.Log;
22 
23 import androidx.test.filters.SmallTest;
24 
25 import junit.framework.Assert;
26 import junit.framework.TestCase;
27 
28 import org.mockito.Mockito;
29 
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 
33 /**
34  * Provides test cases for android.os.BatteryStats.
35  */
36 public class BatteryStatsTimeBaseTest extends TestCase {
37     private static final String TAG = "BatteryStatsTimeBaseTest";
38 
39     static class TestTimeBase extends BatteryStatsImpl.TimeBase {
40 
populate(long uptime, long realtime, boolean running, long pastUptime, long uptimeStart, long pastRealtime, long realtimeStart, long unpluggedUptime, long unpluggedRealtime)41         public void populate(long uptime, long realtime, boolean running, long pastUptime,
42                 long uptimeStart, long pastRealtime, long realtimeStart,
43                 long unpluggedUptime, long unpluggedRealtime) {
44             mUptime = uptime;
45             mRealtime = realtime;
46             mRunning = running;
47             mPastUptime = pastUptime;
48             mUptimeStart = uptimeStart;
49             mPastRealtime = pastRealtime;
50             mRealtimeStart = realtimeStart;
51             mUnpluggedUptime = unpluggedUptime;
52             mUnpluggedRealtime = unpluggedRealtime;
53         }
54 
verify(long uptime, long realtime, boolean running, long pastUptime, long uptimeStart, long pastRealtime, long realtimeStart, long unpluggedUptime, long unpluggedRealtime)55         public void verify(long uptime, long realtime, boolean running, long pastUptime,
56                 long uptimeStart, long pastRealtime, long realtimeStart,
57                 long unpluggedUptime, long unpluggedRealtime) {
58             Assert.assertEquals(uptime, mUptime);
59             Assert.assertEquals(realtime, mRealtime);
60             Assert.assertEquals(running, mRunning);
61             Assert.assertEquals(pastUptime, mPastUptime);
62             Assert.assertEquals(uptimeStart, mUptimeStart);
63             Assert.assertEquals(pastRealtime, mPastRealtime);
64             Assert.assertEquals(realtimeStart, mRealtimeStart);
65             Assert.assertEquals(unpluggedUptime, mUnpluggedUptime);
66             Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtime);
67         }
68     }
69 
70     /**
71      * Test the observers and the setRunning call.
72      */
73     @SmallTest
testRunning()74     public void testRunning() throws Exception {
75         TestTimeBase tb = new TestTimeBase();
76 
77         // Toggle running once, to accumulate past uptime and past realtime
78         // so the test values aren't 0.
79         tb.setRunning(true, 100, 10000);
80         tb.setRunning(false, 200, 11000);
81         Assert.assertEquals(100, tb.getUptimeStart());
82         Assert.assertEquals(10000, tb.getRealtimeStart());
83 
84         // Create some observers
85         BatteryStatsImpl.TimeBaseObs observer1 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
86         BatteryStatsImpl.TimeBaseObs observer2 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
87         BatteryStatsImpl.TimeBaseObs observer3 = Mockito.mock(BatteryStatsImpl.TimeBaseObs.class);
88 
89         // Add them
90         tb.add(observer1);
91         tb.add(observer2);
92         tb.add(observer3);
93         Assert.assertTrue(tb.hasObserver(observer1));
94         Assert.assertTrue(tb.hasObserver(observer2));
95         Assert.assertTrue(tb.hasObserver(observer3));
96 
97         // Remove one
98         tb.remove(observer3);
99         Assert.assertTrue(tb.hasObserver(observer1));
100         Assert.assertTrue(tb.hasObserver(observer2));
101         Assert.assertFalse(tb.hasObserver(observer3));
102 
103         // Start running, make sure we get a started call on the two active observers
104         // and not the third.
105         tb.setRunning(true, 250, 14000);
106 
107         Assert.assertTrue(tb.isRunning());
108 
109         if (false) {
110             Log.d(TAG, "mUptimeStart=" + tb.getUptimeStart()
111                     + " mRealtimeStart=" + tb.getRealtimeStart()
112                     + " mUptime=" + tb.getUptime(250)
113                     + " mRealtime=" + tb.getRealtime(14000)
114                     + " isRunning=" + tb.isRunning());
115         }
116 
117         Assert.assertEquals(250, tb.getUptimeStart());
118         Assert.assertEquals(14000, tb.getRealtimeStart());
119         Assert.assertEquals(100, tb.getUptime(250));
120         Assert.assertEquals(1000, tb.getRealtime(14000));
121 
122         Mockito.verify(observer1).onTimeStarted(14000, 100, 1000);
123         Mockito.verify(observer1, Mockito.never()).onTimeStopped(-1, -1, -1);
124         Mockito.verifyNoMoreInteractions(observer1);
125         Mockito.verify(observer2).onTimeStarted(14000, 100, 1000);
126         Mockito.verify(observer2, Mockito.never()).onTimeStopped(-1, -1, -1);
127         Mockito.verifyNoMoreInteractions(observer2);
128 
129         Mockito.reset(observer1);
130         Mockito.reset(observer2);
131         Mockito.reset(observer3);
132 
133         // Advance the "timer" and make sure the getters account for the current time passed in
134         Assert.assertEquals(400, tb.getUptime(550));
135         Assert.assertEquals(1555, tb.getRealtime(14555));
136 
137         // Stop running, make sure we get a stopped call on the two active observers
138         // and not the third.
139         tb.setRunning(false, 402, 14002);
140 
141         Assert.assertFalse(tb.isRunning());
142 
143         if (false) {
144             Log.d(TAG, "mUptimeStart=" + tb.getUptimeStart()
145                     + " mRealtimeStart=" + tb.getRealtimeStart()
146                     + " mUptime=" + tb.getUptime(250)
147                     + " mRealtime=" + tb.getRealtime(14000)
148                     + " isRunning=" + tb.isRunning());
149         }
150 
151         Assert.assertEquals(252, tb.getUptime(402));
152         Assert.assertEquals(1002, tb.getRealtime(14002));
153 
154         Mockito.verify(observer1).onTimeStopped(14002, 252, 1002);
155         Mockito.verify(observer1, Mockito.never()).onTimeStopped(-1, -1, -1);
156         Mockito.verifyNoMoreInteractions(observer1);
157         Mockito.verify(observer2).onTimeStopped(14002, 252, 1002);
158         Mockito.verify(observer2, Mockito.never()).onTimeStopped(-1, -1, -1);
159         Mockito.verifyNoMoreInteractions(observer2);
160 
161         // Advance the "timer" and make sure the getters account for the current time passed in
162         // is the same as the time when running went to false.
163         Assert.assertEquals(252, tb.getUptime(600));
164         Assert.assertEquals(1002, tb.getRealtime(17000));
165     }
166 
167     /**
168      * Test that reset while running updates the plugged and unplugged times
169      */
170     @SmallTest
testResetWhileRunning()171     public void testResetWhileRunning() throws Exception {
172         TestTimeBase tb = new TestTimeBase();
173         tb.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
174 
175         tb.reset(666, 6666);
176 
177         // Not sure if this is a bug: reset while running does not
178         // reset mPastUptime, but while it is running it does.
179         tb.verify(100, 200, true, 300, 666, 500, 6666, 300, 500);
180     }
181 
182     /**
183      * Test that reset while running updates the plugged and unplugged times
184      */
185     @SmallTest
testResetWhileNotRunning()186     public void testResetWhileNotRunning() throws Exception {
187         TestTimeBase tb = new TestTimeBase();
188         tb.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
189 
190         tb.reset(666, 6666);
191 
192         tb.verify(100, 200, false, 0, 400, 0, 600, 700, 800);
193     }
194 
195     /**
196      * Test init
197      */
198     @SmallTest
testInit()199     public void testInit() throws Exception {
200         TestTimeBase tb = new TestTimeBase();
201         tb.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
202 
203         tb.init(666, 6666);
204 
205         tb.verify(0, 0, false, 0, 666, 0, 6666, 0, 0);
206     }
207 
208     /**
209      * Test writeToParcel and readFromParcel
210      */
211     @SmallTest
testParcellingWhileRunning()212     public void testParcellingWhileRunning() throws Exception {
213         TestTimeBase tb1 = new TestTimeBase();
214 
215         tb1.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
216 
217         Parcel parcel = Parcel.obtain();
218         tb1.writeToParcel(parcel, 666, 6666);
219 
220         parcel.setDataPosition(0);
221 
222         TestTimeBase tb2 = new TestTimeBase();
223         tb2.readFromParcel(parcel);
224 
225         // Running is not preserved across parceling
226         tb2.verify(100, 200, false, 300+666-400, 400, 500+6666-600, 600, 700, 800);
227     }
228 
229     /**
230      * Test writeToParcel and readFromParcel
231      */
232     @SmallTest
testParcellingWhileNotRunning()233     public void testParcellingWhileNotRunning() throws Exception {
234         TestTimeBase tb1 = new TestTimeBase();
235 
236         tb1.populate(100, 200, false, 300, 400, 500, 600, 700, 800);
237 
238         Parcel parcel = Parcel.obtain();
239         tb1.writeToParcel(parcel, 666, 6666);
240 
241         parcel.setDataPosition(0);
242 
243         TestTimeBase tb2 = new TestTimeBase();
244         tb2.readFromParcel(parcel);
245 
246         tb2.verify(100, 200, false, 300, 400, 500, 600, 700, 800);
247     }
248 
249     /**
250      * Test writeSummaryToParcel and readSummaryFromParcel
251      */
252     @SmallTest
testSummary()253     public void testSummary() throws Exception {
254         TestTimeBase tb1 = new TestTimeBase();
255 
256         tb1.populate(100, 200, true, 300, 400, 500, 600, 700, 800);
257 
258         Parcel parcel = Parcel.obtain();
259         tb1.writeSummaryToParcel(parcel, 666, 6666);
260 
261         parcel.setDataPosition(0);
262 
263         TestTimeBase tb2 = new TestTimeBase();
264 
265         // readSummaryFromParcel doesn't affect the other fields.
266         // Not sure if this is deliberate
267         tb2.populate(1, 2, true, 3, 4, 5, 6, 7, 8);
268 
269         tb2.readSummaryFromParcel(parcel);
270 
271         tb2.verify(666, 6766, true, 3, 4, 5, 6, 7, 8);
272     }
273 
274     /**
275      * Test computeUptime
276      */
277     @SmallTest
testComputeUptime()278     public void testComputeUptime() throws Exception {
279         TestTimeBase tb = new TestTimeBase();
280 
281         tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
282 
283         Assert.assertEquals(100+300+666-400,
284                 tb.computeUptime(666, BatteryStats.STATS_SINCE_CHARGED));
285     }
286 
287     /**
288      * Test computeUptime
289      */
290     @SmallTest
testComputeRealtime()291     public void testComputeRealtime() throws Exception {
292         TestTimeBase tb = new TestTimeBase();
293 
294         tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
295 
296         Assert.assertEquals(200+500+6666-600,
297                 tb.computeRealtime(6666, BatteryStats.STATS_SINCE_CHARGED));
298     }
299 
300     /**
301      * Test dump
302      */
303     @SmallTest
testDump()304     public void testDump() throws Exception {
305         TestTimeBase tb = new TestTimeBase();
306 
307         tb.populate(100, 200, true, 300, 400, 500, 600, 50, 60);
308 
309         StringWriter sw = new StringWriter();
310         PrintWriter pw = new PrintWriter(sw);
311 
312         tb.dump(pw, "+++++ ");
313 
314         pw.close();
315 
316         // note the spaces at the ends of the lines which come from formatTimeMs.
317         final String CORRECT = "+++++ mRunning=true\n"
318                 + "+++++ mUptime=0ms \n"
319                 + "+++++ mRealtime=0ms \n"
320                 + "+++++ mPastUptime=0ms mUptimeStart=0ms mUnpluggedUptime=0ms \n"
321                 + "+++++ mPastRealtime=0ms mRealtimeStart=0ms mUnpluggedRealtime=0ms \n";
322 
323         Assert.assertEquals(CORRECT, sw.toString());
324     }
325 
326 }
327 
328