| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.dumpsys.cts; |
| |
| import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.util.concurrent.TimeUnit; |
| |
| /** |
| * Test to check the format of the dumps of the gfxinfo. |
| */ |
| public class GfxInfoDumpsysTest extends BaseDumpsysTest { |
| private static final String TEST_APK = "CtsFramestatsTestApp.apk"; |
| private static final String TEST_PKG = "com.android.cts.framestatstestapp"; |
| |
| /** |
| * Tests the output of "dumpsys gfxinfo framestats". |
| * |
| * @throws Exception |
| */ |
| public void testGfxinfoFramestats() throws Exception { |
| final String MARKER = "---PROFILEDATA---"; |
| |
| try { |
| // cleanup test apps that might be installed from previous partial test run |
| getDevice().uninstallPackage(TEST_PKG); |
| |
| // install the test app |
| CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild); |
| File testAppFile = buildHelper.getTestFile(TEST_APK); |
| String installResult = getDevice().installPackage(testAppFile, false); |
| assertNull( |
| String.format("failed to install atrace test app. Reason: %s", installResult), |
| installResult); |
| |
| getDevice().executeShellCommand("am start -W " + TEST_PKG); |
| |
| String frameinfo = mDevice.executeShellCommand("dumpsys gfxinfo " + |
| TEST_PKG + " framestats"); |
| assertNotNull(frameinfo); |
| assertTrue(frameinfo.length() > 0); |
| int profileStart = frameinfo.indexOf(MARKER); |
| int profileEnd = frameinfo.indexOf(MARKER, profileStart + 1); |
| assertTrue(profileStart >= 0); |
| assertTrue(profileEnd > profileStart); |
| String profileData = frameinfo.substring(profileStart + MARKER.length(), profileEnd); |
| assertTrue(profileData.length() > 0); |
| validateProfileData(profileData); |
| } finally { |
| getDevice().uninstallPackage(TEST_PKG); |
| } |
| } |
| |
| private void validateProfileData(String profileData) throws IOException { |
| final int TIMESTAMP_COUNT = 22; |
| boolean foundAtLeastOneRow = false; |
| try (BufferedReader reader = new BufferedReader( |
| new StringReader(profileData))) { |
| String line; |
| // First line needs to be the headers |
| while ((line = reader.readLine()) != null && line.isEmpty()) {} |
| |
| assertNotNull(line); |
| assertTrue("First line was not the expected header: " + line, |
| line.startsWith("Flags,FrameTimelineVsyncId,IntendedVsync,Vsync" |
| + ",InputEventId,HandleInputStart,AnimationStart,PerformTraversalsStart" |
| + ",DrawStart,FrameDeadline,FrameInterval,FrameStartTime" |
| + ",SyncQueued,SyncStart,IssueDrawCommandsStart,SwapBuffers" |
| + ",FrameCompleted,DequeueBufferDuration,QueueBufferDuration" |
| + ",GpuCompleted,SwapBuffersCompleted,DisplayPresentTime")); |
| |
| long[] numparts = new long[TIMESTAMP_COUNT]; |
| while ((line = reader.readLine()) != null && !line.isEmpty()) { |
| |
| String[] parts = line.split(","); |
| assertTrue(parts.length >= TIMESTAMP_COUNT); |
| for (int i = 0; i < TIMESTAMP_COUNT; i++) { |
| numparts[i] = assertInteger(parts[i]); |
| } |
| |
| final long flags = numparts[0]; |
| // Flags = 1 just means the first frame of the window |
| if (flags != 0 && flags != 1) { |
| continue; |
| } |
| |
| final long timestampIntendedVsync = numparts[2]; |
| final long timestampVsync = numparts[3]; |
| // skip InputEventId, since it's a randomly assigned id |
| final long timestampHandleInputStart = numparts[5]; |
| final long timestampAnimationStart = numparts[6]; |
| final long timestampPerformTraversalsStart = numparts[7]; |
| final long timestampDrawStart = numparts[8]; |
| // skip FrameDeadline, FrameInterval,FrameStartTime |
| final long timestampSyncQueued = numparts[12]; |
| final long timestampSyncStart = numparts[13]; |
| final long timestampIssueDrawCommandsStart = numparts[14]; |
| final long timestampSwapBuffers = numparts[15]; |
| final long timestampFrameCompleted = numparts[16]; |
| |
| // assert time is flowing forwards. we need to check each entry explicitly |
| // as some entries do not represent a flow of events. |
| assertTrue("VSYNC happened before INTENDED_VSYNC", |
| timestampVsync >= timestampIntendedVsync); |
| assertTrue("HandleInputStart happened before VSYNC", |
| timestampHandleInputStart >= timestampVsync); |
| assertTrue("AnimationStart happened before HandleInputStart", |
| timestampAnimationStart >= timestampHandleInputStart); |
| assertTrue("PerformTraversalsStart happened before AnimationStart", |
| timestampPerformTraversalsStart >= timestampAnimationStart); |
| assertTrue("DrawStart happened before PerformTraversalsStart", |
| timestampDrawStart >= timestampPerformTraversalsStart); |
| assertTrue("SyncQueued happened before DrawStart", |
| timestampSyncQueued >= timestampDrawStart); |
| assertTrue("SyncStart happened before SyncQueued", |
| timestampSyncStart >= timestampSyncQueued); |
| assertTrue("IssueDrawCommandsStart happened before SyncStart", |
| timestampIssueDrawCommandsStart >= timestampSyncStart); |
| assertTrue("SwapBuffers happened before IssueDrawCommandsStart", |
| timestampSwapBuffers >= timestampIssueDrawCommandsStart); |
| assertTrue("FrameCompleted happened before SwapBuffers", |
| timestampFrameCompleted >= timestampSwapBuffers); |
| |
| // total duration is from IntendedVsync to FrameCompleted |
| long totalDuration = timestampFrameCompleted - timestampIntendedVsync; |
| assertTrue("Frame did not take a positive amount of time to process", |
| totalDuration > 0); |
| assertTrue("Bogus frame duration, exceeds 100 seconds", |
| totalDuration < TimeUnit.SECONDS.toNanos(100)); |
| foundAtLeastOneRow = true; |
| } |
| } |
| assertTrue(foundAtLeastOneRow); |
| } |
| } |