1 /*
2  * Copyright (C) 2018 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 package android.gameperformance;
17 
18 import java.io.File;
19 import java.io.IOException;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.CountDownLatch;
24 
25 import android.annotation.NonNull;
26 import android.app.Activity;
27 import android.content.Context;
28 import android.graphics.PixelFormat;
29 import android.os.Build;
30 import android.os.Bundle;
31 import android.os.Debug;
32 import android.os.Trace;
33 import android.test.ActivityInstrumentationTestCase2;
34 import android.test.suitebuilder.annotation.SmallTest;
35 import android.util.Log;
36 
37 public class GamePerformanceTest extends
38         ActivityInstrumentationTestCase2<GamePerformanceActivity> {
39     private final static String TAG = "GamePerformanceTest";
40 
41     private final static int GRAPHIC_BUFFER_WARMUP_LOOP_CNT = 60;
42 
GamePerformanceTest()43     public GamePerformanceTest() {
44         super(GamePerformanceActivity.class);
45     }
46 
47     @SmallTest
testGraphicBufferMetrics()48     public void testGraphicBufferMetrics() throws IOException, InterruptedException {
49         Bundle status = new Bundle();
50 
51         for (int i = 0; i < 2; ++i) {
52             if (i == 0) {
53                 getActivity().attachSurfaceView();
54             } else {
55                 getActivity().attachOpenGLView();
56             }
57 
58             // Perform warm-up.
59             Thread.sleep(2000);
60 
61             // Once atrace is done, this one is triggered.
62             CountDownLatch latch = new CountDownLatch(1);
63 
64             final String passTag = i == 0 ? "surface" : "opengl";
65             final String output = (new File(getInstrumentation().getContext().getFilesDir(),
66                     "atrace_" + passTag + ".log")).getAbsolutePath();
67             Log.i(TAG, "Collecting traces to " + output);
68             new ATraceRunner(getInstrumentation(), output, 5, "gfx", new ATraceRunner.Delegate() {
69                 @Override
70                 public void onProcessed(boolean success) {
71                     latch.countDown();
72                 }
73             }).execute();
74 
75             // Reset frame times and perform invalidation loop while atrace is running.
76             getActivity().resetFrameTimes();
77             latch.await();
78 
79             // Copy results.
80             final Map<String, Double> metrics =
81                     GraphicBufferMetrics.processGraphicBufferResult(output, passTag);
82             for (Map.Entry<String, Double> metric : metrics.entrySet()) {
83                 status.putDouble(metric.getKey(), metric.getValue());
84             }
85             // Also record FPS.
86             status.putDouble(passTag + "_fps", getActivity().getFps());
87         }
88 
89         getInstrumentation().sendStatus(Activity.RESULT_OK, status);
90     }
91 
92     @SmallTest
testPerformanceMetricsWithoutExtraLoad()93     public void testPerformanceMetricsWithoutExtraLoad() throws IOException, InterruptedException {
94         final Bundle status = runPerformanceTests("no_extra_load_");
95         getInstrumentation().sendStatus(Activity.RESULT_OK, status);
96     }
97 
98     @SmallTest
testPerformanceMetricsWithExtraLoad()99     public void testPerformanceMetricsWithExtraLoad() throws IOException, InterruptedException {
100         // Start CPU ballast threads first.
101         CPULoadThread[] cpuLoadThreads = new CPULoadThread[2];
102         for (int i = 0; i < cpuLoadThreads.length; ++i) {
103             cpuLoadThreads[i] = new CPULoadThread();
104             cpuLoadThreads[i].start();
105         }
106 
107         final Bundle status = runPerformanceTests("extra_load_");
108 
109         for (int i = 0; i < cpuLoadThreads.length; ++i) {
110             cpuLoadThreads[i].issueStopRequest();
111             cpuLoadThreads[i].join();
112         }
113 
114         getInstrumentation().sendStatus(Activity.RESULT_OK, status);
115     }
116 
117     @NonNull
runPerformanceTests(@onNull String prefix)118     private Bundle runPerformanceTests(@NonNull String prefix) {
119         final Bundle status = new Bundle();
120 
121         final GamePerformanceActivity activity = getActivity();
122 
123         final List<BaseTest> tests = new ArrayList<>();
124         tests.add(new TriangleCountOpenGLTest(activity));
125         tests.add(new FillRateOpenGLTest(activity, false /* testBlend */));
126         tests.add(new FillRateOpenGLTest(activity, true /* testBlend */));
127         tests.add(new DeviceCallsOpenGLTest(activity));
128         tests.add(new ControlsTest(activity));
129 
130         for (BaseTest test : tests) {
131             final double result = test.run();
132             status.putDouble(prefix + test.getName(), result);
133         }
134 
135         return status;
136     }
137 }
138