1 /*
2  * Copyright (C) 2014 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 android.dumpsys.cts;
18 
19 import com.android.cts.migration.MigrationHelper;
20 import com.android.tradefed.build.IBuildInfo;
21 import com.android.tradefed.device.ITestDevice;
22 import com.android.tradefed.testtype.DeviceTestCase;
23 import com.android.tradefed.testtype.IBuildReceiver;
24 
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.IOException;
28 import java.io.StringReader;
29 import java.util.HashSet;
30 import java.util.Set;
31 
32 /**
33  * Test to check the format of the dumps of various services.
34  * Currently procstats and batterystats are tested.
35  */
36 public class DumpsysHostTest extends DeviceTestCase implements IBuildReceiver {
37     private static final String TAG = "DumpsysHostTest";
38     private static final String TEST_APK = "CtsFramestatsTestApp.apk";
39     private static final String TEST_PKG = "com.android.cts.framestatstestapp";
40 
41     /**
42      * A reference to the device under test.
43      */
44     private ITestDevice mDevice;
45 
46     @Override
setUp()47     protected void setUp() throws Exception {
48         super.setUp();
49         mDevice = getDevice();
50     }
51 
52     /**
53      * Tests the output of "dumpsys procstats -c". This is a proxy for testing "dumpsys procstats
54      * --checkin", since the latter is not idempotent.
55      *
56      * @throws Exception
57      */
testProcstatsOutput()58     public void testProcstatsOutput() throws Exception {
59         String procstats = mDevice.executeShellCommand("dumpsys procstats -c");
60         assertNotNull(procstats);
61         assertTrue(procstats.length() > 0);
62 
63         Set<String> seenTags = new HashSet<>();
64         int version = -1;
65 
66         try (BufferedReader reader = new BufferedReader(
67                 new StringReader(procstats))) {
68 
69             String line;
70             while ((line = reader.readLine()) != null) {
71                 if (line.isEmpty()) {
72                     continue;
73                 }
74 
75                 // extra space to make sure last column shows up.
76                 if (line.endsWith(",")) {
77                   line = line + " ";
78                 }
79                 String[] parts = line.split(",");
80                 seenTags.add(parts[0]);
81 
82                 switch (parts[0]) {
83                     case "vers":
84                         assertEquals(2, parts.length);
85                         version = Integer.parseInt(parts[1]);
86                         break;
87                     case "period":
88                         checkPeriod(parts);
89                         break;
90                     case "pkgproc":
91                         checkPkgProc(parts, version);
92                         break;
93                     case "pkgpss":
94                         checkPkgPss(parts, version);
95                         break;
96                     case "pkgsvc-bound":
97                     case "pkgsvc-exec":
98                     case "pkgsvc-run":
99                     case "pkgsvc-start":
100                         checkPkgSvc(parts, version);
101                         break;
102                     case "pkgkills":
103                         checkPkgKills(parts, version);
104                         break;
105                     case "proc":
106                         checkProc(parts);
107                         break;
108                     case "pss":
109                         checkPss(parts);
110                         break;
111                     case "kills":
112                         checkKills(parts);
113                         break;
114                     case "total":
115                         checkTotal(parts);
116                         break;
117                     default:
118                         break;
119                 }
120             }
121         }
122 
123         // spot check a few tags
124         assertSeenTag(seenTags, "pkgproc");
125         assertSeenTag(seenTags, "proc");
126         assertSeenTag(seenTags, "pss");
127         assertSeenTag(seenTags, "total");
128     }
129 
checkPeriod(String[] parts)130     private void checkPeriod(String[] parts) {
131         assertTrue("Expected 5 or 6, found: " + parts.length,
132                 parts.length == 5 || parts.length == 6);
133         assertNotNull(parts[1]); // date
134         assertInteger(parts[2]); // start time (msec)
135         assertInteger(parts[3]); // end time (msec)
136         assertNotNull(parts[4]); // status
137         if (parts.length == 6) {
138             assertNotNull(parts[5]); // swapped-out-pss
139         }
140     }
141 
checkPkgProc(String[] parts, int version)142     private void checkPkgProc(String[] parts, int version) {
143         int statesStartIndex;
144 
145         if (version < 4) {
146             assertTrue(parts.length >= 4);
147             assertNotNull(parts[1]); // package name
148             assertInteger(parts[2]); // uid
149             assertNotNull(parts[3]); // process
150             statesStartIndex = 4;
151         } else {
152             assertTrue(parts.length >= 5);
153             assertNotNull(parts[1]); // package name
154             assertInteger(parts[2]); // uid
155             assertInteger(parts[3]); // app version
156             assertNotNull(parts[4]); // process
157             statesStartIndex = 5;
158         }
159 
160         for (int i = statesStartIndex; i < parts.length; i++) {
161             String[] subparts = parts[i].split(":");
162             assertEquals(2, subparts.length);
163             checkTag(subparts[0], true); // tag
164             assertInteger(subparts[1]); // duration (msec)
165         }
166     }
167 
checkTag(String tag, boolean hasProcess)168     private void checkTag(String tag, boolean hasProcess) {
169         assertEquals(hasProcess ? 3 : 2, tag.length());
170 
171         // screen: 0 = off, 1 = on
172         char s = tag.charAt(0);
173         if (s != '0' && s != '1') {
174             fail("malformed tag: " + tag);
175         }
176 
177         // memory: n = normal, m = moderate, l = low, c = critical
178         char m = tag.charAt(1);
179         if (m != 'n' && m != 'm' && m != 'l' && m != 'c') {
180             fail("malformed tag: " + tag);
181         }
182 
183         if (hasProcess) {
184             char p = tag.charAt(2);
185             assertTrue("malformed tag: " + tag, p >= 'a' && p <= 'z');
186         }
187     }
188 
checkPkgPss(String[] parts, int version)189     private void checkPkgPss(String[] parts, int version) {
190         int statesStartIndex;
191 
192         if (version < 4) {
193             assertTrue(parts.length >= 4);
194             assertNotNull(parts[1]); // package name
195             assertInteger(parts[2]); // uid
196             assertNotNull(parts[3]); // process
197             statesStartIndex = 4;
198         } else {
199             assertTrue(parts.length >= 5);
200             assertNotNull(parts[1]); // package name
201             assertInteger(parts[2]); // uid
202             assertInteger(parts[3]); // app version
203             assertNotNull(parts[4]); // process
204             statesStartIndex = 5;
205         }
206 
207         for (int i = statesStartIndex; i < parts.length; i++) {
208             String[] subparts = parts[i].split(":");
209             assertEquals(8, subparts.length);
210             checkTag(subparts[0], true); // tag
211             assertInteger(subparts[1]); // sample size
212             assertInteger(subparts[2]); // pss min
213             assertInteger(subparts[3]); // pss avg
214             assertInteger(subparts[4]); // pss max
215             assertInteger(subparts[5]); // uss min
216             assertInteger(subparts[6]); // uss avg
217             assertInteger(subparts[7]); // uss max
218         }
219     }
220 
checkPkgSvc(String[] parts, int version)221     private void checkPkgSvc(String[] parts, int version) {
222         int statesStartIndex;
223 
224         if (version < 4) {
225             assertTrue(parts.length >= 5);
226             assertNotNull(parts[1]); // package name
227             assertInteger(parts[2]); // uid
228             assertNotNull(parts[3]); // service name
229             assertInteger(parts[4]); // count
230             statesStartIndex = 5;
231         } else {
232             assertTrue(parts.length >= 6);
233             assertNotNull(parts[1]); // package name
234             assertInteger(parts[2]); // uid
235             assertInteger(parts[3]); // app version
236             assertNotNull(parts[4]); // service name
237             assertInteger(parts[5]); // count
238             statesStartIndex = 6;
239         }
240 
241         for (int i = statesStartIndex; i < parts.length; i++) {
242             String[] subparts = parts[i].split(":");
243             assertEquals(2, subparts.length);
244             checkTag(subparts[0], false); // tag
245             assertInteger(subparts[1]); // duration (msec)
246         }
247     }
248 
checkPkgKills(String[] parts, int version)249     private void checkPkgKills(String[] parts, int version) {
250         String pssStr;
251 
252         if (version < 4) {
253             assertEquals(8, parts.length);
254             assertNotNull(parts[1]); // package name
255             assertInteger(parts[2]); // uid
256             assertNotNull(parts[3]); // process
257             assertInteger(parts[4]); // wakes
258             assertInteger(parts[5]); // cpu
259             assertInteger(parts[6]); // cached
260             pssStr = parts[7];
261         } else {
262             assertEquals(9, parts.length);
263             assertNotNull(parts[1]); // package name
264             assertInteger(parts[2]); // uid
265             assertInteger(parts[3]); // app version
266             assertNotNull(parts[4]); // process
267             assertInteger(parts[5]); // wakes
268             assertInteger(parts[6]); // cpu
269             assertInteger(parts[7]); // cached
270             pssStr = parts[8];
271         }
272 
273         String[] subparts = pssStr.split(":");
274         assertEquals(3, subparts.length);
275         assertInteger(subparts[0]); // pss min
276         assertInteger(subparts[1]); // pss avg
277         assertInteger(subparts[2]); // pss max
278     }
279 
checkProc(String[] parts)280     private void checkProc(String[] parts) {
281         assertTrue(parts.length >= 3);
282         assertNotNull(parts[1]); // package name
283         assertInteger(parts[2]); // uid
284 
285         for (int i = 3; i < parts.length; i++) {
286             String[] subparts = parts[i].split(":");
287             assertEquals(2, subparts.length);
288             checkTag(subparts[0], true); // tag
289             assertInteger(subparts[1]); // duration (msec)
290         }
291     }
292 
checkPss(String[] parts)293     private void checkPss(String[] parts) {
294         assertTrue(parts.length >= 3);
295         assertNotNull(parts[1]); // package name
296         assertInteger(parts[2]); // uid
297 
298         for (int i = 3; i < parts.length; i++) {
299             String[] subparts = parts[i].split(":");
300             assertEquals(8, subparts.length);
301             checkTag(subparts[0], true); // tag
302             assertInteger(subparts[1]); // sample size
303             assertInteger(subparts[2]); // pss min
304             assertInteger(subparts[3]); // pss avg
305             assertInteger(subparts[4]); // pss max
306             assertInteger(subparts[5]); // uss min
307             assertInteger(subparts[6]); // uss avg
308             assertInteger(subparts[7]); // uss max
309         }
310     }
311 
checkKills(String[] parts)312     private void checkKills(String[] parts) {
313         assertEquals(7, parts.length);
314         assertNotNull(parts[1]); // package name
315         assertInteger(parts[2]); // uid
316         assertInteger(parts[3]); // wakes
317         assertInteger(parts[4]); // cpu
318         assertInteger(parts[5]); // cached
319         String pssStr = parts[6];
320 
321         String[] subparts = pssStr.split(":");
322         assertEquals(3, subparts.length);
323         assertInteger(subparts[0]); // pss min
324         assertInteger(subparts[1]); // pss avg
325         assertInteger(subparts[2]); // pss max
326     }
327 
checkTotal(String[] parts)328     private void checkTotal(String[] parts) {
329         assertTrue(parts.length >= 2);
330         for (int i = 1; i < parts.length; i++) {
331             String[] subparts = parts[i].split(":");
332             checkTag(subparts[0], false); // tag
333 
334             if (subparts[1].contains("sysmemusage")) {
335                 break; // see b/18340771
336             }
337             assertInteger(subparts[1]); // duration (msec)
338         }
339     }
340 
341     /**
342      * Tests the output of "dumpsys batterystats --checkin".
343      *
344      * @throws Exception
345      */
testBatterystatsOutput()346     public void testBatterystatsOutput() throws Exception {
347         String batterystats = mDevice.executeShellCommand("dumpsys batterystats --checkin");
348         assertNotNull(batterystats);
349         assertTrue(batterystats.length() > 0);
350 
351         Set<String> seenTags = new HashSet<>();
352         int version = -1;
353 
354         try (BufferedReader reader = new BufferedReader(
355                 new StringReader(batterystats))) {
356 
357             String line;
358             while ((line = reader.readLine()) != null) {
359                 if (line.isEmpty()) {
360                     continue;
361                 }
362 
363 
364                 // With a default limit of 0, empty strings at the end are discarded.
365                 // We still consider the empty string as a valid value in some cases.
366                 // Using any negative number for the limit will preserve a trailing empty string.
367                 // @see String#split(String, int)
368                 String[] parts = line.split(",", -1);
369                 assertInteger(parts[0]); // old version
370                 assertInteger(parts[1]); // UID
371                 switch (parts[2]) { // aggregation type
372                     case "i":
373                     case "l":
374                     case "c":
375                     case "u":
376                         break;
377                     default:
378                         fail("malformed stat: " + parts[2]);
379                 }
380                 assertNotNull(parts[3]);
381                 seenTags.add(parts[3]);
382 
383                 // Note the time fields are measured in milliseconds by default.
384                 switch (parts[3]) {
385                     case "vers":
386                         checkVersion(parts);
387                         break;
388                     case "uid":
389                         checkUid(parts);
390                         break;
391                     case "apk":
392                         checkApk(parts);
393                         break;
394                     case "pr":
395                         checkProcess(parts);
396                         break;
397                     case "sr":
398                         checkSensor(parts);
399                         break;
400                     case "vib":
401                         checkVibrator(parts);
402                         break;
403                     case "fg":
404                         checkForeground(parts);
405                         break;
406                     case "st":
407                         checkStateTime(parts);
408                         break;
409                     case "wl":
410                         checkWakelock(parts);
411                         break;
412                     case "sy":
413                         checkSync(parts);
414                         break;
415                     case "jb":
416                         checkJob(parts);
417                         break;
418                     case "kwl":
419                         checkKernelWakelock(parts);
420                         break;
421                     case "wr":
422                         checkWakeupReason(parts);
423                         break;
424                     case "nt":
425                         checkNetwork(parts);
426                         break;
427                     case "ua":
428                         checkUserActivity(parts);
429                         break;
430                     case "bt":
431                         checkBattery(parts);
432                         break;
433                     case "dc":
434                         checkBatteryDischarge(parts);
435                         break;
436                     case "lv":
437                         checkBatteryLevel(parts);
438                         break;
439                     case "wfl":
440                         checkWifi(parts);
441                         break;
442                     case "m":
443                         checkMisc(parts);
444                         break;
445                     case "gn":
446                         checkGlobalNetwork(parts);
447                         break;
448                     case "br":
449                         checkScreenBrightness(parts);
450                         break;
451                     case "sgt":
452                     case "sgc":
453                         checkSignalStrength(parts);
454                         break;
455                     case "sst":
456                         checkSignalScanningTime(parts);
457                         break;
458                     case "dct":
459                     case "dcc":
460                         checkDataConnection(parts);
461                         break;
462                     case "wst":
463                     case "wsc":
464                         checkWifiState(parts);
465                         break;
466                     case "wsst":
467                     case "wssc":
468                         checkWifiSupplState(parts);
469                         break;
470                     case "wsgt":
471                     case "wsgc":
472                         checkWifiSignalStrength(parts);
473                         break;
474                     case "bst":
475                     case "bsc":
476                         checkBluetoothState(parts);
477                         break;
478                     case "pws":
479                         checkPowerUseSummary(parts);
480                         break;
481                     case "pwi":
482                         checkPowerUseItem(parts);
483                         break;
484                     case "dsd":
485                     case "csd":
486                         checkChargeDischargeStep(parts);
487                         break;
488                     case "dtr":
489                         checkDischargeTimeRemain(parts);
490                         break;
491                     case "ctr":
492                         checkChargeTimeRemain(parts);
493                         break;
494                     case "cpu":
495                         checkUidCpuUsage(parts);
496                     default:
497                         break;
498                 }
499             }
500         }
501 
502         // spot check a few tags
503         assertSeenTag(seenTags, "vers");
504         assertSeenTag(seenTags, "bt");
505         assertSeenTag(seenTags, "dc");
506         assertSeenTag(seenTags, "m");
507     }
508 
checkVersion(String[] parts)509     private void checkVersion(String[] parts) {
510         assertEquals(8, parts.length);
511         assertInteger(parts[4]); // checkinVersion
512         assertInteger(parts[5]); // parcelVersion
513         assertNotNull(parts[6]); // startPlatformVersion
514         assertNotNull(parts[7]); // endPlatformVersion
515     }
516 
checkUid(String[] parts)517     private void checkUid(String[] parts) {
518         assertEquals(6, parts.length);
519         assertInteger(parts[4]); // uid
520         assertNotNull(parts[5]); // pkgName
521     }
522 
checkApk(String[] parts)523     private void checkApk(String[] parts) {
524         assertEquals(10, parts.length);
525         long wakeup_count = assertInteger(parts[4]); // wakeups
526         assertNotNull(parts[5]); // apk
527         assertNotNull(parts[6]); // service
528         assertInteger(parts[7]); // startTime
529         assertInteger(parts[8]); // starts
530         assertInteger(parts[9]); // launches
531 
532         // Sanity check.
533         assertTrue("wakeup count must be >= 0", wakeup_count >= 0);
534     }
535 
checkProcess(String[] parts)536     private void checkProcess(String[] parts) {
537         assertTrue(parts.length >= 9);
538         assertNotNull(parts[4]); // process
539         assertInteger(parts[5]); // userMillis
540         assertInteger(parts[6]); // systemMillis
541         assertInteger(parts[7]); // foregroundMillis
542         assertInteger(parts[8]); // starts
543     }
544 
checkSensor(String[] parts)545     private void checkSensor(String[] parts) {
546         assertEquals(7, parts.length);
547         assertInteger(parts[4]); // sensorNumber
548         assertInteger(parts[5]); // totalTime
549         assertInteger(parts[6]); // count
550     }
551 
checkVibrator(String[] parts)552     private void checkVibrator(String[] parts) {
553         assertEquals(6, parts.length);
554         assertInteger(parts[4]); // totalTime
555         assertInteger(parts[5]); // count
556     }
557 
checkForeground(String[] parts)558     private void checkForeground(String[] parts) {
559         assertEquals(6, parts.length);
560         assertInteger(parts[4]); // totalTime
561         assertInteger(parts[5]); // count
562     }
563 
checkStateTime(String[] parts)564     private void checkStateTime(String[] parts) {
565         assertEquals(7, parts.length);
566         assertInteger(parts[4]); // foreground
567         assertInteger(parts[5]); // active
568         assertInteger(parts[6]); // running
569     }
570 
checkWakelock(String[] parts)571     private void checkWakelock(String[] parts) {
572         assertEquals(14, parts.length);
573         assertNotNull(parts[4]);      // wakelock
574         assertInteger(parts[5]);      // full totalTime
575         assertEquals("f", parts[6]);  // full
576         long full_count = assertInteger(parts[7]);      // full count
577         assertInteger(parts[8]);      // partial totalTime
578         assertEquals("p", parts[9]);  // partial
579         long partial_count = assertInteger(parts[10]);     // partial count
580         assertInteger(parts[11]);     // window totalTime
581         assertEquals("w", parts[12]); // window
582         long window_count = assertInteger(parts[13]);     // window count
583 
584         // Sanity checks.
585         assertTrue("full wakelock count must be >= 0", full_count >= 0);
586         assertTrue("partial wakelock count must be >= 0", partial_count >= 0);
587         assertTrue("window wakelock count must be >= 0", window_count >= 0);
588     }
589 
checkSync(String[] parts)590     private void checkSync(String[] parts) {
591         assertEquals(7, parts.length);
592         assertNotNull(parts[4]); // sync
593         assertInteger(parts[5]); // totalTime
594         assertInteger(parts[6]); // count
595     }
596 
checkJob(String[] parts)597     private void checkJob(String[] parts) {
598         assertEquals(7, parts.length);
599         assertNotNull(parts[4]); // job
600         assertInteger(parts[5]); // totalTime
601         assertInteger(parts[6]); // count
602     }
603 
checkKernelWakelock(String[] parts)604     private void checkKernelWakelock(String[] parts) {
605         assertTrue(parts.length >= 7);
606 	assertNotNull(parts[4]); // Kernel wakelock
607 	assertInteger(parts[parts.length-2]); // totalTime
608         assertInteger(parts[parts.length-1]); // count
609     }
610 
checkWakeupReason(String[] parts)611     private void checkWakeupReason(String[] parts) {
612         assertTrue(parts.length >= 7);
613         for (int i = 4; i < parts.length-2; i++) {
614             assertNotNull(parts[i]); // part of wakeup
615         }
616         assertInteger(parts[parts.length-2]); // totalTime
617         assertInteger(parts[parts.length-1]); // count
618     }
619 
checkNetwork(String[] parts)620     private void checkNetwork(String[] parts) {
621         assertEquals(14, parts.length);
622         long mbRx = assertInteger(parts[4]);  // mobileBytesRx
623         long mbTx = assertInteger(parts[5]);  // mobileBytesTx
624         long wbRx = assertInteger(parts[6]);  // wifiBytesRx
625         long wbTx = assertInteger(parts[7]);  // wifiBytesTx
626         long mpRx = assertInteger(parts[8]);  // mobilePacketsRx
627         long mpTx = assertInteger(parts[9]);  // mobilePacketsTx
628         long wpRx = assertInteger(parts[10]); // wifiPacketsRx
629         long wpTx = assertInteger(parts[11]); // wifiPacketsTx
630         assertInteger(parts[12]); // mobileActiveTime (usec)
631         assertInteger(parts[13]); // mobileActiveCount
632 
633         // Assuming each packet contains some bytes, bytes >= packets >= 0.
634         assertTrue("mobileBytesRx must be >= mobilePacketsRx", mbRx >= mpRx);
635         assertTrue("mobilePacketsRx must be >= 0", mpRx >= 0);
636         assertTrue("mobileBytesTx must be >= mobilePacketsTx", mbTx >= mpTx);
637         assertTrue("mobilePacketsTx must be >= 0", mpTx >= 0);
638         assertTrue("wifiBytesRx must be >= wifiPacketsRx", wbRx >= wpRx);
639         assertTrue("wifiPacketsRx must be >= 0", wpRx >= 0);
640         assertTrue("wifiBytesTx must be >= wifiPacketsTx", wbTx >= wpTx);
641         assertTrue("wifiPacketsTx must be >= 0", wpTx >= 0);
642     }
643 
checkUserActivity(String[] parts)644     private void checkUserActivity(String[] parts) {
645         assertEquals(7, parts.length);
646         assertInteger(parts[4]); // other
647         assertInteger(parts[5]); // button
648         assertInteger(parts[6]); // touch
649     }
650 
checkBattery(String[] parts)651     private void checkBattery(String[] parts) {
652         assertEquals(12, parts.length);
653         if (!parts[4].equals("N/A")) {
654             assertInteger(parts[4]);  // startCount
655         }
656         long bReal = assertInteger(parts[5]);  // batteryRealtime
657         long bUp = assertInteger(parts[6]);  // batteryUptime
658         long tReal = assertInteger(parts[7]);  // totalRealtime
659         long tUp = assertInteger(parts[8]);  // totalUptime
660         assertInteger(parts[9]);  // startClockTime
661         long bOffReal = assertInteger(parts[10]); // batteryScreenOffRealtime
662         long bOffUp = assertInteger(parts[11]); // batteryScreenOffUptime
663 
664         // The device cannot be up more than there are real-world seconds.
665         assertTrue("batteryRealtime must be >= batteryUptime", bReal >= bUp);
666         assertTrue("totalRealtime must be >= totalUptime", tReal >= tUp);
667         assertTrue("batteryScreenOffRealtime must be >= batteryScreenOffUptime",
668                 bOffReal >= bOffUp);
669 
670         // total >= battery >= battery screen-off >= 0
671         assertTrue("totalRealtime must be >= batteryRealtime", tReal >= bReal);
672         assertTrue("batteryRealtime must be >= batteryScreenOffRealtime", bReal >= bOffReal);
673         assertTrue("batteryScreenOffRealtime must be >= 0", bOffReal >= 0);
674         assertTrue("totalUptime must be >= batteryUptime", tUp >= bUp);
675         assertTrue("batteryUptime must be >= batteryScreenOffUptime", bUp >= bOffUp);
676         assertTrue("batteryScreenOffUptime must be >= 0", bOffUp >= 0);
677     }
678 
checkBatteryDischarge(String[] parts)679     private void checkBatteryDischarge(String[] parts) {
680         assertEquals(8, parts.length);
681         assertInteger(parts[4]); // low
682         assertInteger(parts[5]); // high
683         assertInteger(parts[6]); // screenOn
684         assertInteger(parts[7]); // screenOff
685     }
686 
checkBatteryLevel(String[] parts)687     private void checkBatteryLevel(String[] parts) {
688         assertEquals(6, parts.length);
689         assertInteger(parts[4]); // startLevel
690         assertInteger(parts[5]); // currentLevel
691     }
692 
checkWifi(String[] parts)693     private void checkWifi(String[] parts) {
694         assertEquals(7, parts.length);
695         assertInteger(parts[4]); // fullWifiLockOnTime (usec)
696         assertInteger(parts[5]); // wifiScanTime (usec)
697         assertInteger(parts[6]); // uidWifiRunningTime (usec)
698     }
699 
checkMisc(String[] parts)700     private void checkMisc(String[] parts) {
701         assertTrue(parts.length >= 19);
702         assertInteger(parts[4]);      // screenOnTime
703         assertInteger(parts[5]);      // phoneOnTime
704         assertInteger(parts[6]);      // fullWakeLockTimeTotal
705         assertInteger(parts[7]);      // partialWakeLockTimeTotal
706         assertInteger(parts[8]);      // mobileRadioActiveTime
707         assertInteger(parts[9]);      // mobileRadioActiveAdjustedTime
708         assertInteger(parts[10]);     // interactiveTime
709         assertInteger(parts[11]);     // lowPowerModeEnabledTime
710         assertInteger(parts[12]);     // connChanges
711         assertInteger(parts[13]);     // deviceIdleModeEnabledTime
712         assertInteger(parts[14]);     // deviceIdleModeEnabledCount
713         assertInteger(parts[15]);     // deviceIdlingTime
714         assertInteger(parts[16]);     // deviceIdlingCount
715         assertInteger(parts[17]);     // mobileRadioActiveCount
716         assertInteger(parts[18]);     // mobileRadioActiveUnknownTime
717     }
718 
checkGlobalNetwork(String[] parts)719     private void checkGlobalNetwork(String[] parts) {
720         assertEquals(12, parts.length);
721         assertInteger(parts[4]);  // mobileRxTotalBytes
722         assertInteger(parts[5]);  // mobileTxTotalBytes
723         assertInteger(parts[6]);  // wifiRxTotalBytes
724         assertInteger(parts[7]);  // wifiTxTotalBytes
725         assertInteger(parts[8]);  // mobileRxTotalPackets
726         assertInteger(parts[9]);  // mobileTxTotalPackets
727         assertInteger(parts[10]); // wifiRxTotalPackets
728         assertInteger(parts[11]); // wifiTxTotalPackets
729     }
730 
checkScreenBrightness(String[] parts)731     private void checkScreenBrightness(String[] parts) {
732         assertEquals(9, parts.length);
733         assertInteger(parts[4]); // dark
734         assertInteger(parts[5]); // dim
735         assertInteger(parts[6]); // medium
736         assertInteger(parts[7]); // light
737         assertInteger(parts[8]); // bright
738     }
739 
checkSignalStrength(String[] parts)740     private void checkSignalStrength(String[] parts) {
741         assertTrue(parts.length >= 9);
742         assertInteger(parts[4]); // none
743         assertInteger(parts[5]); // poor
744         assertInteger(parts[6]); // moderate
745         assertInteger(parts[7]); // good
746         assertInteger(parts[8]); // great
747     }
748 
checkSignalScanningTime(String[] parts)749     private void checkSignalScanningTime(String[] parts) {
750         assertEquals(5, parts.length);
751         assertInteger(parts[4]); // signalScanningTime
752     }
753 
checkDataConnection(String[] parts)754     private void checkDataConnection(String[] parts) {
755         assertEquals(21, parts.length);
756         assertInteger(parts[4]);  // none
757         assertInteger(parts[5]);  // gprs
758         assertInteger(parts[6]);  // edge
759         assertInteger(parts[7]);  // umts
760         assertInteger(parts[8]);  // cdma
761         assertInteger(parts[9]);  // evdo_0
762         assertInteger(parts[10]); // evdo_A
763         assertInteger(parts[11]); // 1xrtt
764         assertInteger(parts[12]); // hsdpa
765         assertInteger(parts[13]); // hsupa
766         assertInteger(parts[14]); // hspa
767         assertInteger(parts[15]); // iden
768         assertInteger(parts[16]); // evdo_b
769         assertInteger(parts[17]); // lte
770         assertInteger(parts[18]); // ehrpd
771         assertInteger(parts[19]); // hspap
772         assertInteger(parts[20]); // other
773     }
774 
checkWifiState(String[] parts)775     private void checkWifiState(String[] parts) {
776         assertEquals(12, parts.length);
777         assertInteger(parts[4]);  // off
778         assertInteger(parts[5]);  // scanning
779         assertInteger(parts[6]);  // no_net
780         assertInteger(parts[7]);  // disconn
781         assertInteger(parts[8]);  // sta
782         assertInteger(parts[9]);  // p2p
783         assertInteger(parts[10]); // sta_p2p
784         assertInteger(parts[11]); // soft_ap
785     }
786 
checkWifiSupplState(String[] parts)787     private void checkWifiSupplState(String[] parts) {
788         assertEquals(17, parts.length);
789         assertInteger(parts[4]);  // inv
790         assertInteger(parts[5]);  // dsc
791         assertInteger(parts[6]);  // dis
792         assertInteger(parts[7]);  // inact
793         assertInteger(parts[8]);  // scan
794         assertInteger(parts[9]);  // auth
795         assertInteger(parts[10]); // ascing
796         assertInteger(parts[11]); // asced
797         assertInteger(parts[12]); // 4-way
798         assertInteger(parts[13]); // group
799         assertInteger(parts[14]); // compl
800         assertInteger(parts[15]); // dorm
801         assertInteger(parts[16]); // uninit
802     }
803 
checkWifiSignalStrength(String[] parts)804     private void checkWifiSignalStrength(String[] parts) {
805         assertEquals(9, parts.length);
806         assertInteger(parts[4]); // none
807         assertInteger(parts[5]); // poor
808         assertInteger(parts[6]); // moderate
809         assertInteger(parts[7]); // good
810         assertInteger(parts[8]); // great
811     }
812 
checkBluetoothState(String[] parts)813     private void checkBluetoothState(String[] parts) {
814         assertEquals(8, parts.length);
815         assertInteger(parts[4]); // inactive
816         assertInteger(parts[5]); // low
817         assertInteger(parts[6]); // med
818         assertInteger(parts[7]); // high
819     }
820 
checkPowerUseSummary(String[] parts)821     private void checkPowerUseSummary(String[] parts) {
822         assertEquals(8, parts.length);
823         assertDouble(parts[4]); // batteryCapacity
824         assertDouble(parts[5]); // computedPower
825         assertDouble(parts[6]); // minDrainedPower
826         assertDouble(parts[7]); // maxDrainedPower
827     }
828 
checkPowerUseItem(String[] parts)829     private void checkPowerUseItem(String[] parts) {
830         assertEquals(6, parts.length);
831         assertNotNull(parts[4]); // label
832         double mAH = assertDouble(parts[5]);  // mAh
833 
834         assertTrue("powerUseItem mAH must be >= 0", mAH >= 0);
835         // Largest current Android battery is ~5K. 100K shouldn't get made for a while.
836         assertTrue("powerUseItem mAH is expected to be <= 100000", mAH <= 100000);
837     }
838 
checkChargeDischargeStep(String[] parts)839     private void checkChargeDischargeStep(String[] parts) {
840         assertEquals(9, parts.length);
841         assertInteger(parts[4]); // duration
842         if (!parts[5].equals("?")) {
843             assertInteger(parts[5]); // level
844         }
845         assertNotNull(parts[6]); // screen
846         assertNotNull(parts[7]); // power-save
847         assertNotNull(parts[8]); // device-idle
848     }
849 
checkDischargeTimeRemain(String[] parts)850     private void checkDischargeTimeRemain(String[] parts) {
851         assertEquals(5, parts.length);
852         assertInteger(parts[4]); // batteryTimeRemaining
853     }
854 
checkChargeTimeRemain(String[] parts)855     private void checkChargeTimeRemain(String[] parts) {
856         assertEquals(5, parts.length);
857         assertInteger(parts[4]); // chargeTimeRemaining
858     }
859 
checkUidCpuUsage(String[] parts)860     private void checkUidCpuUsage(String[] parts) {
861         assertTrue(parts.length >= 6);
862         assertInteger(parts[4]); // user time
863         assertInteger(parts[5]); // system time
864     }
865 
866     /**
867      * Tests the output of "dumpsys gfxinfo framestats".
868      *
869      * @throws Exception
870      */
testGfxinfoFramestats()871     public void testGfxinfoFramestats() throws Exception {
872         final String MARKER = "---PROFILEDATA---";
873 
874         try {
875             // cleanup test apps that might be installed from previous partial test run
876             getDevice().uninstallPackage(TEST_PKG);
877 
878             // install the test app
879             File testAppFile = MigrationHelper.getTestFile(mCtsBuild, TEST_APK);
880             String installResult = getDevice().installPackage(testAppFile, false);
881             assertNull(
882                     String.format("failed to install atrace test app. Reason: %s", installResult),
883                     installResult);
884 
885             getDevice().executeShellCommand("am start -W " + TEST_PKG);
886 
887             String frameinfo = mDevice.executeShellCommand("dumpsys gfxinfo " +
888                     TEST_PKG + " framestats");
889             assertNotNull(frameinfo);
890             assertTrue(frameinfo.length() > 0);
891             int profileStart = frameinfo.indexOf(MARKER);
892             int profileEnd = frameinfo.indexOf(MARKER, profileStart + 1);
893             assertTrue(profileStart >= 0);
894             assertTrue(profileEnd > profileStart);
895             String profileData = frameinfo.substring(profileStart + MARKER.length(), profileEnd);
896             assertTrue(profileData.length() > 0);
897             validateProfileData(profileData);
898         } finally {
899             getDevice().uninstallPackage(TEST_PKG);
900         }
901     }
902 
validateProfileData(String profileData)903     private void validateProfileData(String profileData) throws IOException {
904         final int TIMESTAMP_COUNT = 14;
905         boolean foundAtLeastOneRow = false;
906         try (BufferedReader reader = new BufferedReader(
907                 new StringReader(profileData))) {
908             String line;
909             // First line needs to be the headers
910             while ((line = reader.readLine()) != null && line.isEmpty()) {}
911 
912             assertNotNull(line);
913             assertTrue("First line was not the expected header",
914                     line.startsWith("Flags,IntendedVsync,Vsync,OldestInputEvent" +
915                             ",NewestInputEvent,HandleInputStart,AnimationStart" +
916                             ",PerformTraversalsStart,DrawStart,SyncQueued,SyncStart" +
917                             ",IssueDrawCommandsStart,SwapBuffers,FrameCompleted"));
918 
919             long[] numparts = new long[TIMESTAMP_COUNT];
920             while ((line = reader.readLine()) != null && !line.isEmpty()) {
921 
922                 String[] parts = line.split(",");
923                 assertTrue(parts.length >= TIMESTAMP_COUNT);
924                 for (int i = 0; i < TIMESTAMP_COUNT; i++) {
925                     numparts[i] = assertInteger(parts[i]);
926                 }
927                 if (numparts[0] != 0) {
928                     continue;
929                 }
930                 // assert VSYNC >= INTENDED_VSYNC
931                 assertTrue(numparts[2] >= numparts[1]);
932                 // assert time is flowing forwards, skipping index 3 & 4
933                 // as those are input timestamps that may or may not be present
934                 assertTrue(numparts[5] >= numparts[2]);
935                 for (int i = 6; i < TIMESTAMP_COUNT; i++) {
936                     assertTrue("Index " + i + " did not flow forward, " +
937                             numparts[i] + " not larger than " + numparts[i - 1],
938                             numparts[i] >= numparts[i-1]);
939                 }
940                 long totalDuration = numparts[13] - numparts[1];
941                 assertTrue("Frame did not take a positive amount of time to process",
942                         totalDuration > 0);
943                 assertTrue("Bogus frame duration, exceeds 100 seconds",
944                         totalDuration < 100000000000L);
945                 foundAtLeastOneRow = true;
946             }
947         }
948         assertTrue(foundAtLeastOneRow);
949     }
950 
951     private IBuildInfo mCtsBuild;
952 
953     /**
954      * {@inheritDoc}
955      */
956     @Override
setBuild(IBuildInfo buildInfo)957     public void setBuild(IBuildInfo buildInfo) {
958         mCtsBuild = buildInfo;
959     }
960 
assertInteger(String input)961     private static long assertInteger(String input) {
962         try {
963             return Long.parseLong(input);
964         } catch (NumberFormatException e) {
965             fail("Expected an integer but found \"" + input + "\"");
966             // Won't be hit, above throws AssertException
967             return -1;
968         }
969     }
970 
assertDouble(String input)971     private static double assertDouble(String input) {
972         try {
973             return Double.parseDouble(input);
974         } catch (NumberFormatException e) {
975             fail("Expected a double but found \"" + input + "\"");
976             return -1;
977         }
978     }
979 
assertSeenTag(Set<String> seenTags, String tag)980     private static void assertSeenTag(Set<String> seenTags, String tag) {
981         assertTrue("No line starting with \"" + tag + ",\"", seenTags.contains(tag));
982     }
983 }
984