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