1/*
2 * Copyright (C) 2011 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.commands.monkey;
18
19import android.app.IActivityManager;
20import android.util.Log;
21import android.view.IWindowManager;
22
23import java.io.FileWriter;
24import java.io.IOException;
25import java.io.InputStream;
26import java.io.BufferedReader;
27import java.io.InputStreamReader;
28import java.text.DecimalFormat;
29import java.util.regex.Pattern;
30import java.util.regex.Matcher;
31
32/**
33 * Events for running a special shell command to capture the frame rate.
34 * To run this test, the system property viewancestor.profile_rendering
35 * must be set to true to force the currently focused window to render at
36 * 60 Hz.
37 */
38public class MonkeyGetFrameRateEvent extends MonkeyEvent {
39
40    private String GET_FRAMERATE_CMD = "service call SurfaceFlinger 1013";
41    private String mStatus;
42    private static long mStartTime; // in millisecond
43    private static long mEndTime; // in millisecond
44    private static float mDuration; // in seconds
45    private static String mTestCaseName = null;
46    private static int mStartFrameNo;
47    private static int mEndFrameNo;
48
49    private static final String TAG = "MonkeyGetFrameRateEvent";
50    private static final String LOG_FILE = "/sdcard/avgFrameRateOut.txt";
51
52    private static final Pattern NO_OF_FRAMES_PATTERN =
53        Pattern.compile(".*\\(([a-f[A-F][0-9]].*?)\\s.*\\)");
54
55    public MonkeyGetFrameRateEvent(String status, String testCaseName) {
56        super(EVENT_TYPE_ACTIVITY);
57        mStatus = status;
58        mTestCaseName = testCaseName;
59    }
60
61    public MonkeyGetFrameRateEvent(String status) {
62        super(EVENT_TYPE_ACTIVITY);
63        mStatus = status;
64    }
65
66    //Calculate the average frame rate
67    private float getAverageFrameRate(int totalNumberOfFrame, float duration) {
68        float avgFrameRate = 0;
69        if (duration > 0) {
70            avgFrameRate = (totalNumberOfFrame / duration);
71        }
72        return avgFrameRate;
73    }
74
75    /**
76     * Calculate the frame rate and write the output to a file on the SD card.
77     */
78    private void writeAverageFrameRate() {
79        FileWriter writer = null;
80        float avgFrameRate;
81        int totalNumberOfFrame = 0;
82        try {
83            writer = new FileWriter(LOG_FILE, true); // true = append
84            totalNumberOfFrame = mEndFrameNo - mStartFrameNo;
85            avgFrameRate = getAverageFrameRate(totalNumberOfFrame, mDuration);
86            writer.write(String.format("%s:%.2f\n",mTestCaseName,avgFrameRate));
87            writer.close();
88        } catch (IOException e) {
89            Log.w(TAG, "Can't write sdcard log file", e);
90        } finally {
91            try {
92                if (writer != null) writer.close();
93            } catch (IOException e) {
94                Log.e(TAG, "IOException " + e.toString());
95            }
96        }
97    }
98
99    // Parse the output of the surfaceFlinge shell command call
100    private String getNumberOfFrames(String input){
101        String noOfFrames = null;
102        Matcher m = NO_OF_FRAMES_PATTERN.matcher(input);
103        if (m.matches()){
104            noOfFrames = m.group(1);
105        }
106        return noOfFrames;
107    }
108
109    @Override
110    public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
111        java.lang.Process p = null;
112        BufferedReader result = null;
113        try {
114            p = Runtime.getRuntime().exec(GET_FRAMERATE_CMD);
115            int status = p.waitFor();
116            if (status != 0) {
117                System.err.println(String.format("// Shell command %s status was %s",
118                        GET_FRAMERATE_CMD, status));
119            }
120            result = new BufferedReader(new InputStreamReader(p.getInputStream()));
121
122            //Only need the first line of the output
123            String output = result.readLine();
124
125            if (output != null) {
126                if (mStatus == "start") {
127                    mStartFrameNo = Integer.parseInt(getNumberOfFrames(output), 16);
128                    mStartTime = System.currentTimeMillis();
129                } else if (mStatus == "end") {
130                    mEndFrameNo = Integer.parseInt(getNumberOfFrames(output), 16);
131                    mEndTime = System.currentTimeMillis();
132                    long diff = mEndTime - mStartTime;
133                    mDuration = (float)(diff/1000.0);
134                    writeAverageFrameRate();
135                }
136            }
137        } catch (Exception e) {
138            System.err.println("// Exception from " + GET_FRAMERATE_CMD + ":");
139            System.err.println(e.toString());
140        } finally {
141            try {
142                if (result != null) {
143                    result.close();
144                }
145                if (p != null) {
146                    p.destroy();
147                }
148            } catch (IOException e) {
149                System.err.println(e.toString());
150            }
151        }
152        return MonkeyEvent.INJECT_SUCCESS;
153    }
154}