1/*
2 * Copyright (C) 2015 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
17package com.android.benchmark.app;
18
19import android.annotation.TargetApi;
20import android.os.AsyncTask;
21import android.os.Bundle;
22import android.support.annotation.Nullable;
23import android.support.v4.app.ListFragment;
24import android.util.Log;
25import android.view.FrameMetrics;
26import android.widget.SimpleAdapter;
27
28import com.android.benchmark.R;
29import com.android.benchmark.registry.BenchmarkGroup;
30import com.android.benchmark.registry.BenchmarkRegistry;
31import com.android.benchmark.results.GlobalResultsStore;
32import com.android.benchmark.results.UiBenchmarkResult;
33
34import org.apache.commons.math.stat.descriptive.SummaryStatistics;
35
36import java.io.FileWriter;
37import java.io.IOException;
38import java.net.URI;
39import java.text.DecimalFormat;
40import java.util.ArrayList;
41import java.util.HashMap;
42import java.util.Map;
43
44@TargetApi(24)
45public class UiResultsFragment extends ListFragment {
46    private static final String TAG = "UiResultsFragment";
47    private static final int NUM_FIELDS = 20;
48
49    private ArrayList<UiBenchmarkResult> mResults = new ArrayList<>();
50
51    private AsyncTask<Void, Void, ArrayList<Map<String, String>>> mLoadScoresTask =
52            new AsyncTask<Void, Void, ArrayList<Map<String, String>>>() {
53        @Override
54        protected ArrayList<Map<String, String>> doInBackground(Void... voids) {
55            String[] data;
56            if (mResults.size() == 0 || mResults.get(0) == null) {
57                data = new String[] {
58                        "No metrics reported", ""
59                };
60            } else {
61                data = new String[NUM_FIELDS * (1 + mResults.size()) + 2];
62                SummaryStatistics stats = new SummaryStatistics();
63                int totalFrameCount = 0;
64                double totalAvgFrameDuration = 0;
65                double total99FrameDuration = 0;
66                double total95FrameDuration = 0;
67                double total90FrameDuration = 0;
68                double totalLongestFrame = 0;
69                double totalShortestFrame = 0;
70
71                for (int i = 0; i < mResults.size(); i++) {
72                    int start = (i * NUM_FIELDS) + + NUM_FIELDS;
73                    data[(start++)] = "Iteration";
74                    data[(start++)] = "" + i;
75                    data[(start++)] = "Total Frames";
76                    int currentFrameCount = mResults.get(i).getTotalFrameCount();
77                    totalFrameCount += currentFrameCount;
78                    data[(start++)] = Integer.toString(currentFrameCount);
79                    data[(start++)] = "Average frame duration:";
80                    double currentAvgFrameDuration = mResults.get(i).getAverage(FrameMetrics.TOTAL_DURATION);
81                    totalAvgFrameDuration += currentAvgFrameDuration;
82                    data[(start++)] = String.format("%.2f", currentAvgFrameDuration);
83                    data[(start++)] = "Frame duration 99th:";
84                    double current99FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 99);
85                    total99FrameDuration += current99FrameDuration;
86                    data[(start++)] = String.format("%.2f", current99FrameDuration);
87                    data[(start++)] = "Frame duration 95th:";
88                    double current95FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 95);
89                    total95FrameDuration += current95FrameDuration;
90                    data[(start++)] = String.format("%.2f", current95FrameDuration);
91                    data[(start++)] = "Frame duration 90th:";
92                    double current90FrameDuration = mResults.get(i).getPercentile(FrameMetrics.TOTAL_DURATION, 90);
93                    total90FrameDuration += current90FrameDuration;
94                    data[(start++)] = String.format("%.2f", current90FrameDuration);
95                    data[(start++)] = "Longest frame:";
96                    double longestFrame = mResults.get(i).getMaximum(FrameMetrics.TOTAL_DURATION);
97                    if (totalLongestFrame == 0 || longestFrame > totalLongestFrame) {
98                        totalLongestFrame = longestFrame;
99                    }
100                    data[(start++)] = String.format("%.2f", longestFrame);
101                    data[(start++)] = "Shortest frame:";
102                    double shortestFrame = mResults.get(i).getMinimum(FrameMetrics.TOTAL_DURATION);
103                    if (totalShortestFrame == 0 || totalShortestFrame > shortestFrame) {
104                        totalShortestFrame = shortestFrame;
105                    }
106                    data[(start++)] = String.format("%.2f", shortestFrame);
107                    data[(start++)] = "Score:";
108                    double score = mResults.get(i).getScore();
109                    stats.addValue(score);
110                    data[(start++)] = String.format("%.2f", score);
111                    data[(start++)] = "==============";
112                    data[(start++)] = "============================";
113                };
114
115                int start = 0;
116                data[0] = "Overall: ";
117                data[1] = "";
118                data[(start++)] = "Total Frames";
119                data[(start++)] = Integer.toString(totalFrameCount);
120                data[(start++)] = "Average frame duration:";
121                data[(start++)] = String.format("%.2f", totalAvgFrameDuration / mResults.size());
122                data[(start++)] = "Frame duration 99th:";
123                data[(start++)] = String.format("%.2f", total99FrameDuration / mResults.size());
124                data[(start++)] = "Frame duration 95th:";
125                data[(start++)] = String.format("%.2f", total95FrameDuration / mResults.size());
126                data[(start++)] = "Frame duration 90th:";
127                data[(start++)] = String.format("%.2f", total90FrameDuration / mResults.size());
128                data[(start++)] = "Longest frame:";
129                data[(start++)] = String.format("%.2f", totalLongestFrame);
130                data[(start++)] = "Shortest frame:";
131                data[(start++)] = String.format("%.2f", totalShortestFrame);
132                data[(start++)] = "Score:";
133                data[(start++)] = String.format("%.2f", stats.getGeometricMean());
134                data[(start++)] = "==============";
135                data[(start++)] = "============================";
136            }
137
138            ArrayList<Map<String, String>> dataMap = new ArrayList<>();
139            for (int i = 0; i < data.length - 1; i += 2) {
140                HashMap<String, String> map = new HashMap<>();
141                map.put("name", data[i]);
142                map.put("value", data[i + 1]);
143                dataMap.add(map);
144            }
145
146            return dataMap;
147        }
148
149        @Override
150        protected void onPostExecute(ArrayList<Map<String, String>> dataMap) {
151            setListAdapter(new SimpleAdapter(getActivity(), dataMap, R.layout.results_list_item,
152                    new String[] {"name", "value"}, new int[] { R.id.result_name, R.id.result_value }));
153            setListShown(true);
154        }
155    };
156
157    @Override
158    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
159        super.onActivityCreated(savedInstanceState);
160        setListShown(false);
161        mLoadScoresTask.execute();
162    }
163
164    public void setRunInfo(String name, int runId) {
165        mResults = GlobalResultsStore.getInstance(getActivity()).loadTestResults(name, runId);
166    }
167}
168