1b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes/*
2b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Copyright (C) 2015 The Android Open Source Project
3b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
4b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Licensed under the Apache License, Version 2.0 (the License);
5b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * you may not use this file except in compliance with the License.
6b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * You may obtain a copy of the License at
7b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
8b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *      http://www.apache.org/licenses/LICENSE-2.0
9b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes *
10b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * Unless required by applicable law or agreed to in writing, software
11b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * distributed under the License is distributed on an AS IS BASIS,
12b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * See the License for the specific language governing permissions and
14b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes * limitations under the License.
15b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes */
16b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
17b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandespackage com.android.benchmark.app;
18b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
19b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.annotation.TargetApi;
20b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.AsyncTask;
21b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.os.Bundle;
22b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.support.annotation.Nullable;
23b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.support.v4.app.ListFragment;
24b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.util.Log;
25b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.view.FrameMetrics;
26b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport android.widget.SimpleAdapter;
27b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
28b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.R;
29b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.registry.BenchmarkGroup;
30b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.registry.BenchmarkRegistry;
31b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.results.GlobalResultsStore;
32b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport com.android.benchmark.results.UiBenchmarkResult;
33b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
34b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport org.apache.commons.math.stat.descriptive.SummaryStatistics;
35b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
36b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.io.FileWriter;
37b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.io.IOException;
38b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.net.URI;
39b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.text.DecimalFormat;
40b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.ArrayList;
41b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.HashMap;
42b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandesimport java.util.Map;
43b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
44b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes@TargetApi(24)
45b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandespublic class UiResultsFragment extends ListFragment {
46b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private static final String TAG = "UiResultsFragment";
47b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private static final int NUM_FIELDS = 20;
48b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
49b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private ArrayList<UiBenchmarkResult> mResults = new ArrayList<>();
50b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
51b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    private AsyncTask<Void, Void, ArrayList<Map<String, String>>> mLoadScoresTask =
52b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            new AsyncTask<Void, Void, ArrayList<Map<String, String>>>() {
53b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        @Override
54b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        protected ArrayList<Map<String, String>> doInBackground(Void... voids) {
55b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            String[] data;
56b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            if (mResults.size() == 0 || mResults.get(0) == null) {
57b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data = new String[] {
58b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        "No metrics reported", ""
59b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                };
60b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            } else {
61b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data = new String[NUM_FIELDS * (1 + mResults.size()) + 2];
62b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                SummaryStatistics stats = new SummaryStatistics();
63b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                int totalFrameCount = 0;
64b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double totalAvgFrameDuration = 0;
65b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double total99FrameDuration = 0;
66b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double total95FrameDuration = 0;
67b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double total90FrameDuration = 0;
68b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double totalLongestFrame = 0;
69b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                double totalShortestFrame = 0;
70b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
71b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                for (int i = 0; i < mResults.size(); i++) {
72b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    int start = (i * NUM_FIELDS) + + NUM_FIELDS;
73b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Iteration";
74b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "" + i;
75b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Total Frames";
76b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    int currentFrameCount = mResults.get(i).getTotalFrameCount();
77b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    totalFrameCount += currentFrameCount;
78b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = Integer.toString(currentFrameCount);
79b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Average frame duration:";
80b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double currentAvgFrameDuration = mResults.get(i).getAverage(FrameMetrics.TOTAL_DURATION);
81b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    totalAvgFrameDuration += currentAvgFrameDuration;
82b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", currentAvgFrameDuration);
83b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Frame duration 99th:";
84b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double current99FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 99);
85b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    total99FrameDuration += current99FrameDuration;
86b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", current99FrameDuration);
87b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Frame duration 95th:";
88b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double current95FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 95);
89b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    total95FrameDuration += current95FrameDuration;
90b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", current95FrameDuration);
91b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Frame duration 90th:";
92b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double current90FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 90);
93b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    total90FrameDuration += current90FrameDuration;
94b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", current90FrameDuration);
95b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Longest frame:";
96b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double longestFrame = mResults.get(i).getMaximum(FrameMetrics.TOTAL_DURATION);
97b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    if (totalLongestFrame == 0 || longestFrame > totalLongestFrame) {
98b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        totalLongestFrame = longestFrame;
99b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    }
100b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", longestFrame);
101b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Shortest frame:";
102b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double shortestFrame = mResults.get(i).getMinimum(FrameMetrics.TOTAL_DURATION);
103b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    if (totalShortestFrame == 0 || totalShortestFrame > shortestFrame) {
104b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                        totalShortestFrame = shortestFrame;
105b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    }
106b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", shortestFrame);
107b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "Score:";
108b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    double score = mResults.get(i).getScore();
109b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    stats.addValue(score);
110b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = String.format("%.2f", score);
111b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "==============";
112b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    data[(start++)] = "============================";
113b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                };
114b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
115b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                int start = 0;
116b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[0] = "Overall: ";
117b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[1] = "";
118b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Total Frames";
119b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = Integer.toString(totalFrameCount);
120b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Average frame duration:";
121b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", totalAvgFrameDuration / mResults.size());
122b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Frame duration 99th:";
123b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", total99FrameDuration / mResults.size());
124b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Frame duration 95th:";
125b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", total95FrameDuration / mResults.size());
126b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Frame duration 90th:";
127b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", total90FrameDuration / mResults.size());
128b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Longest frame:";
129b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", totalLongestFrame);
130b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Shortest frame:";
131b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", totalShortestFrame);
132b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "Score:";
133b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = String.format("%.2f", stats.getGeometricMean());
134b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "==============";
135b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                data[(start++)] = "============================";
136b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
137b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
138b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            ArrayList<Map<String, String>> dataMap = new ArrayList<>();
139b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            for (int i = 0; i < data.length - 1; i += 2) {
140b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                HashMap<String, String> map = new HashMap<>();
141b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                map.put("name", data[i]);
142b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                map.put("value", data[i + 1]);
143b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                dataMap.add(map);
144b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            }
145b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
146b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            return dataMap;
147b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
148b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
149b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        @Override
150b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        protected void onPostExecute(ArrayList<Map<String, String>> dataMap) {
151b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            setListAdapter(new SimpleAdapter(getActivity(), dataMap, R.layout.results_list_item,
152b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes                    new String[] {"name", "value"}, new int[] { R.id.result_name, R.id.result_value }));
153b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes            setListShown(true);
154b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        }
155b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    };
156b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
157b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    @Override
158b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
159b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        super.onActivityCreated(savedInstanceState);
160b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        setListShown(false);
161b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mLoadScoresTask.execute();
162b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
163b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes
164b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    public void setRunInfo(String name, int runId) {
165b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes        mResults = GlobalResultsStore.getInstance(getActivity()).loadTestResults(name, runId);
166b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes    }
167b5fbd41b23bf309e6b420a3df4641603d55dcb68Joel Fernandes}
168