1 /*
2  * Copyright (C) 2020 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.compatibility.common.tradefed.build.CompatibilityBuildHelper;
20 
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.StringReader;
25 import java.util.concurrent.TimeUnit;
26 
27 /**
28  * Test to check the format of the dumps of the gfxinfo.
29  */
30 public class GfxInfoDumpsysTest extends BaseDumpsysTest {
31     private static final String TEST_APK = "CtsFramestatsTestApp.apk";
32     private static final String TEST_PKG = "com.android.cts.framestatstestapp";
33 
34     /**
35      * Tests the output of "dumpsys gfxinfo framestats".
36      *
37      * @throws Exception
38      */
testGfxinfoFramestats()39     public void testGfxinfoFramestats() throws Exception {
40         final String MARKER = "---PROFILEDATA---";
41 
42         try {
43             // cleanup test apps that might be installed from previous partial test run
44             getDevice().uninstallPackage(TEST_PKG);
45 
46             // install the test app
47             CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
48             File testAppFile = buildHelper.getTestFile(TEST_APK);
49             String installResult = getDevice().installPackage(testAppFile, false);
50             assertNull(
51                     String.format("failed to install atrace test app. Reason: %s", installResult),
52                     installResult);
53 
54             getDevice().executeShellCommand("am start -W " + TEST_PKG);
55             // Currently "wait for launch" doesn't actually wait for the frame to be finished
56             // So do a little sleep to let things stabilize
57             Thread.sleep(500);
58 
59             String frameinfo = mDevice.executeShellCommand("dumpsys gfxinfo " +
60                     TEST_PKG + " framestats");
61             assertNotNull(frameinfo);
62             assertTrue(frameinfo.length() > 0);
63             int profileStart = frameinfo.indexOf(MARKER);
64             int profileEnd = frameinfo.indexOf(MARKER, profileStart + 1);
65             assertTrue(profileStart >= 0);
66             assertTrue(profileEnd > profileStart);
67             String profileData = frameinfo.substring(profileStart + MARKER.length(), profileEnd);
68             assertTrue(profileData.length() > 0);
69             validateProfileData(profileData);
70         } finally {
71             getDevice().uninstallPackage(TEST_PKG);
72         }
73     }
74 
validateProfileData(String profileData)75     private void validateProfileData(String profileData) throws IOException {
76         final int TIMESTAMP_COUNT = 22;
77         boolean foundAtLeastOneRow = false;
78         try (BufferedReader reader = new BufferedReader(
79                 new StringReader(profileData))) {
80             String line;
81             // First line needs to be the headers
82             while ((line = reader.readLine()) != null && line.isEmpty()) {}
83 
84             assertNotNull(line);
85             assertTrue("First line was not the expected header: " + line,
86                     line.startsWith("Flags,FrameTimelineVsyncId,IntendedVsync,Vsync"
87                             + ",InputEventId,HandleInputStart,AnimationStart,PerformTraversalsStart"
88                             + ",DrawStart,FrameDeadline,FrameInterval,FrameStartTime"
89                             + ",SyncQueued,SyncStart,IssueDrawCommandsStart,SwapBuffers"
90                             + ",FrameCompleted,DequeueBufferDuration,QueueBufferDuration"
91                             + ",GpuCompleted,SwapBuffersCompleted,DisplayPresentTime"));
92 
93             long[] numparts = new long[TIMESTAMP_COUNT];
94             while ((line = reader.readLine()) != null && !line.isEmpty()) {
95 
96                 String[] parts = line.split(",");
97                 assertTrue(parts.length >= TIMESTAMP_COUNT);
98                 for (int i = 0; i < TIMESTAMP_COUNT; i++) {
99                     numparts[i] = assertInteger(parts[i]);
100                 }
101 
102                 final long flags = numparts[0];
103                 // Flags = 1 just means the first frame of the window
104                 if (flags != 0 && flags != 1) {
105                     continue;
106                 }
107 
108                 final long timestampIntendedVsync = numparts[2];
109                 final long timestampVsync = numparts[3];
110                 // skip InputEventId, since it's a randomly assigned id
111                 final long timestampHandleInputStart = numparts[5];
112                 final long timestampAnimationStart = numparts[6];
113                 final long timestampPerformTraversalsStart = numparts[7];
114                 final long timestampDrawStart = numparts[8];
115                 // skip FrameDeadline, FrameInterval,FrameStartTime
116                 final long timestampSyncQueued = numparts[12];
117                 final long timestampSyncStart = numparts[13];
118                 final long timestampIssueDrawCommandsStart = numparts[14];
119                 final long timestampSwapBuffers = numparts[15];
120                 final long timestampFrameCompleted = numparts[16];
121 
122                 // assert time is flowing forwards. we need to check each entry explicitly
123                 // as some entries do not represent a flow of events.
124                 assertTrue("VSYNC happened before INTENDED_VSYNC",
125                         timestampVsync >= timestampIntendedVsync);
126                 assertTrue("HandleInputStart happened before VSYNC",
127                         timestampHandleInputStart >= timestampVsync);
128                 assertTrue("AnimationStart happened before HandleInputStart",
129                         timestampAnimationStart >= timestampHandleInputStart);
130                 assertTrue("PerformTraversalsStart happened before AnimationStart",
131                         timestampPerformTraversalsStart >= timestampAnimationStart);
132                 assertTrue("DrawStart happened before PerformTraversalsStart",
133                         timestampDrawStart >= timestampPerformTraversalsStart);
134                 assertTrue("SyncQueued happened before DrawStart",
135                         timestampSyncQueued >= timestampDrawStart);
136                 assertTrue("SyncStart happened before SyncQueued",
137                         timestampSyncStart >= timestampSyncQueued);
138                 assertTrue("IssueDrawCommandsStart happened before SyncStart",
139                         timestampIssueDrawCommandsStart >= timestampSyncStart);
140                 assertTrue("SwapBuffers happened before IssueDrawCommandsStart",
141                         timestampSwapBuffers >= timestampIssueDrawCommandsStart);
142                 assertTrue("FrameCompleted happened before SwapBuffers",
143                         timestampFrameCompleted >= timestampSwapBuffers);
144 
145                 // total duration is from IntendedVsync to FrameCompleted
146                 long totalDuration = timestampFrameCompleted - timestampIntendedVsync;
147                 assertTrue("Frame did not take a positive amount of time to process",
148                         totalDuration > 0);
149                 assertTrue("Bogus frame duration, exceeds 100 seconds",
150                         totalDuration < TimeUnit.SECONDS.toNanos(100));
151                 foundAtLeastOneRow = true;
152             }
153         }
154         assertTrue(foundAtLeastOneRow);
155     }
156 }
157