103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck/* 203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * Copyright (C) 2016 The Android Open Source Project 303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * 403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * Licensed under the Apache License, Version 2.0 (the "License"); 503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * you may not use this file except in compliance with the License. 603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * You may obtain a copy of the License at 703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * 803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * http://www.apache.org/licenses/LICENSE-2.0 903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * 1003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * Unless required by applicable law or agreed to in writing, software 1103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * distributed under the License is distributed on an "AS IS" BASIS, 1203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * See the License for the specific language governing permissions and 1403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck * limitations under the License. 1503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck */ 1603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 1703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckpackage com.android.test.uibench; 1803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 1903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.app.Activity; 20e692f31fd687abacc58dbf34c28527b224a9598aJohn Reckimport android.content.Context; 2103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.Canvas; 2203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.Color; 2303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.ColorFilter; 2403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.Paint; 2503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.PixelFormat; 2603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.Rect; 2703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.graphics.drawable.Drawable; 2803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.os.Bundle; 2903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.os.Handler; 3003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.os.HandlerThread; 3103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.os.Message; 32e692f31fd687abacc58dbf34c28527b224a9598aJohn Reckimport android.util.AttributeSet; 3303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.view.FrameMetrics; 3403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.view.View; 3503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.view.Window; 3603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.view.Window.OnFrameMetricsAvailableListener; 3703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.view.animation.AnimationUtils; 3803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckimport android.widget.TextView; 3903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 4003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reckpublic class RenderingJitter extends Activity { 4103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private TextView mJitterReport; 4203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private TextView mUiFrameTimeReport; 4303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private TextView mRenderThreadTimeReport; 4403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private TextView mTotalFrameTimeReport; 4503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private TextView mMostlyTotalFrameTimeReport; 46e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private PointGraphView mGraph; 4703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 4803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private static Handler sMetricsHandler; 4903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck static { 5003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck HandlerThread thread = new HandlerThread("frameMetricsListener"); 5103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck thread.start(); 5203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck sMetricsHandler = new Handler(thread.getLooper()); 5303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 5403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 5503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private Handler mUpdateHandler = new Handler() { 5603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 5703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public void handleMessage(Message msg) { 5803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck switch (msg.what) { 5903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck case R.id.jitter_mma: 6003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mJitterReport.setText((CharSequence) msg.obj); 6103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck break; 6203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck case R.id.totalish_mma: 6303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mMostlyTotalFrameTimeReport.setText((CharSequence) msg.obj); 6403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck break; 6503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck case R.id.ui_frametime_mma: 6603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUiFrameTimeReport.setText((CharSequence) msg.obj); 6703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck break; 6803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck case R.id.rt_frametime_mma: 6903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mRenderThreadTimeReport.setText((CharSequence) msg.obj); 7003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck break; 7103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck case R.id.total_mma: 7203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mTotalFrameTimeReport.setText((CharSequence) msg.obj); 7303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck break; 74e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck case R.id.graph: 75e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mGraph.addJitterSample(msg.arg1, msg.arg2); 76e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck break; 7703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 7803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 7903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck }; 8003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 8103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 8203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck protected void onCreate(Bundle savedInstanceState) { 8303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck super.onCreate(savedInstanceState); 8403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck setContentView(R.layout.rendering_jitter); 8503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck View content = findViewById(android.R.id.content); 8603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck content.setBackground(new AnimatedBackgroundDrawable()); 8703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck content.setKeepScreenOn(true); 8851efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mJitterReport = findViewById(R.id.jitter_mma); 8951efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mMostlyTotalFrameTimeReport = findViewById(R.id.totalish_mma); 9051efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mUiFrameTimeReport = findViewById(R.id.ui_frametime_mma); 9151efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mRenderThreadTimeReport = findViewById(R.id.rt_frametime_mma); 9251efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mTotalFrameTimeReport = findViewById(R.id.total_mma); 9351efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette mGraph = findViewById(R.id.graph); 9403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mJitterReport.setText("abcdefghijklmnopqrstuvwxyz"); 9503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mMostlyTotalFrameTimeReport.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 9603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUiFrameTimeReport.setText("0123456789"); 9703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mRenderThreadTimeReport.setText(",.!()[]{};"); 9803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck getWindow().addOnFrameMetricsAvailableListener(mMetricsListener, sMetricsHandler); 9903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 10003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 101e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck public static final class PointGraphView extends View { 102e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private static final float[] JITTER_LINES_MS = { 103e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck .5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 5.0f 104e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck }; 105e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private static final String[] JITTER_LINES_LABELS = makeLabels(JITTER_LINES_MS); 106e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private static final int[] JITTER_LINES_COLORS = new int[] { 107e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 0xFF00E676, 0xFFFFF176, 0xFFFDD835, 0xFFFBC02D, 0xFFF9A825, 108e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 0xFFF57F17, 0xFFDD2C00 109e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck }; 110e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private Paint mPaint = new Paint(); 111e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float[] mJitterYs = new float[JITTER_LINES_MS.length]; 112e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float mLabelWidth; 113e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float mLabelHeight; 114e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float mDensity; 115e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float mGraphScale; 116e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float mGraphMaxMs; 117e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 118e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float[] mJitterPoints; 119e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float[] mJitterAvgPoints; 120e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 121e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck public PointGraphView(Context context, AttributeSet attrs) { 122e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck super(context, attrs); 123e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck setWillNotDraw(false); 124e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mDensity = context.getResources().getDisplayMetrics().density; 125e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setTextSize(dp(10)); 126e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck Rect textBounds = new Rect(); 127e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.getTextBounds("8.8", 0, 3, textBounds); 128e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mLabelWidth = textBounds.width() + dp(2); 129e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mLabelHeight = textBounds.height(); 130e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 131e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 132e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck public void addJitterSample(int jitterUs, int jitterUsAvg) { 133e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 1; i < mJitterPoints.length - 2; i += 2) { 134e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterPoints[i] = mJitterPoints[i + 2]; 135e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterAvgPoints[i] = mJitterAvgPoints[i + 2]; 136e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 137e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterPoints[mJitterPoints.length - 1] = 138e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck getHeight() - mGraphScale * (jitterUs / 1000.0f); 139e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterAvgPoints[mJitterAvgPoints.length - 1] = 140e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck getHeight() - mGraphScale * (jitterUsAvg / 1000.0f); 141e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck invalidate(); 142e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 143e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 144e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private float dp(float dp) { 145e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck return mDensity * dp; 146e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 147e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 148e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck @Override 149e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck protected void onDraw(Canvas canvas) { 150e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawColor(0x90000000); 151e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck int h = getHeight(); 152e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck int w = getWidth(); 153e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setColor(Color.WHITE); 154e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setStrokeWidth(dp(1)); 155e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawLine(mLabelWidth, 0, mLabelWidth, h, mPaint); 156e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 0; i < JITTER_LINES_LABELS.length; i++) { 157e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawText(JITTER_LINES_LABELS[i], 158e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 0, (float) Math.floor(mJitterYs[i] + mLabelHeight * .5f), mPaint); 159e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 160e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 0; i < JITTER_LINES_LABELS.length; i++) { 161e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setColor(JITTER_LINES_COLORS[i]); 162e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawLine(mLabelWidth, mJitterYs[i], w, mJitterYs[i], mPaint); 163e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 164e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setStrokeWidth(dp(2)); 165e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setColor(Color.WHITE); 166e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawPoints(mJitterPoints, mPaint); 167e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mPaint.setColor(0xFF2196F3); 168e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck canvas.drawPoints(mJitterAvgPoints, mPaint); 169e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 170e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 171e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck @Override 172e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck protected void onSizeChanged(int w, int h, int oldw, int oldh) { 173e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck super.onSizeChanged(w, h, oldw, oldh); 174e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck int graphWidth = (int) ((w - mLabelWidth - dp(1)) / mDensity); 175e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck float[] oldJitterPoints = mJitterPoints; 176e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck float[] oldJitterAvgPoints = mJitterAvgPoints; 177e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterPoints = new float[graphWidth * 2]; 178e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterAvgPoints = new float[graphWidth * 2]; 179e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 0; i < mJitterPoints.length; i += 2) { 180e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterPoints[i] = mLabelWidth + (i / 2 + 1) * mDensity; 181e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterAvgPoints[i] = mJitterPoints[i]; 182e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 183e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck if (oldJitterPoints != null) { 184e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck int newIndexShift = Math.max(mJitterPoints.length - oldJitterPoints.length, 0); 185e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck int oldIndexShift = oldJitterPoints.length - mJitterPoints.length; 186e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 1 + newIndexShift; i < mJitterPoints.length; i += 2) { 187e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterPoints[i] = oldJitterPoints[i + oldIndexShift]; 188e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterAvgPoints[i] = oldJitterAvgPoints[i + oldIndexShift]; 189e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 190e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 191e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mGraphMaxMs = JITTER_LINES_MS[JITTER_LINES_MS.length - 1] + .5f; 192e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mGraphScale = (h / mGraphMaxMs); 193e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 0; i < JITTER_LINES_MS.length; i++) { 194e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mJitterYs[i] = (float) Math.floor(h - mGraphScale * JITTER_LINES_MS[i]); 195e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 196e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 197e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 198e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck private static String[] makeLabels(float[] divisions) { 199e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck String[] ret = new String[divisions.length]; 200e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck for (int i = 0; i < divisions.length; i++) { 201e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck ret[i] = Float.toString(divisions[i]); 202e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 203e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck return ret; 204e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 205e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck } 206e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck 20703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private final OnFrameMetricsAvailableListener mMetricsListener = new OnFrameMetricsAvailableListener() { 20803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private final static double WEIGHT = 40; 20903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private long mPreviousFrameTotal; 21003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private double mJitterMma; 21103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private double mUiFrametimeMma; 21203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private double mRtFrametimeMma; 21303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private double mTotalFrametimeMma; 21403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private double mMostlyTotalFrametimeMma; 21503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private boolean mNeedsFirstValues = true; 21603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 21703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 21803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics, 21903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int dropCountSinceLastInvocation) { 22003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (frameMetrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1) { 22103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck return; 22203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 22303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 22403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck long uiDuration = frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION) 22503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck + frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION) 22603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck + frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION) 22703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck + frameMetrics.getMetric(FrameMetrics.DRAW_DURATION); 22803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck long rtDuration = frameMetrics.getMetric(FrameMetrics.SYNC_DURATION) 22903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck + frameMetrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION); 23003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck long totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION); 23103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck long jitter = Math.abs(totalDuration - mPreviousFrameTotal); 23203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mNeedsFirstValues) { 23303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mJitterMma = 0; 23403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUiFrametimeMma = uiDuration; 23503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mRtFrametimeMma = rtDuration; 23603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mTotalFrametimeMma = totalDuration; 23703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mMostlyTotalFrametimeMma = uiDuration + rtDuration; 23803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mNeedsFirstValues = false; 23903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } else { 24003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mJitterMma = add(mJitterMma, jitter); 24103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUiFrametimeMma = add(mUiFrametimeMma, uiDuration); 24203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mRtFrametimeMma = add(mRtFrametimeMma, rtDuration); 24303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mTotalFrametimeMma = add(mTotalFrametimeMma, totalDuration); 24403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mMostlyTotalFrametimeMma = add(mMostlyTotalFrametimeMma, uiDuration + rtDuration); 24503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 24603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mPreviousFrameTotal = totalDuration; 24703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUpdateHandler.obtainMessage(R.id.jitter_mma, 24803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck String.format("Jitter: %.3fms", toMs(mJitterMma))).sendToTarget(); 24903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUpdateHandler.obtainMessage(R.id.totalish_mma, 25003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck String.format("CPU-total duration: %.3fms", toMs(mMostlyTotalFrametimeMma))).sendToTarget(); 25103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUpdateHandler.obtainMessage(R.id.ui_frametime_mma, 25203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck String.format("UI duration: %.3fms", toMs(mUiFrametimeMma))).sendToTarget(); 25303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUpdateHandler.obtainMessage(R.id.rt_frametime_mma, 25403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck String.format("RT duration: %.3fms", toMs(mRtFrametimeMma))).sendToTarget(); 25503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mUpdateHandler.obtainMessage(R.id.total_mma, 25603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck String.format("Total duration: %.3fms", toMs(mTotalFrametimeMma))).sendToTarget(); 257e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck mUpdateHandler.obtainMessage(R.id.graph, (int) (jitter / 1000), 258e692f31fd687abacc58dbf34c28527b224a9598aJohn Reck (int) (mJitterMma / 1000)).sendToTarget(); 25903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 26003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 26103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck double add(double previous, double today) { 26203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck return (((WEIGHT - 1) * previous) + today) / WEIGHT; 26303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 26403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 26503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck double toMs(double val) { 26603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck return val / 1000000; 26703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 26803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck }; 26903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 27003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private static final class AnimatedBackgroundDrawable extends Drawable { 27103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private static final int FROM_COLOR = 0xFF18FFFF; 27203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private static final int TO_COLOR = 0xFF40C4FF; 27303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private static final int DURATION = 1400; 27403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 27503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private final Paint mPaint; 27603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private boolean mReverse; 27703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private long mStartTime; 27803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private int mColor; 27903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 28003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private boolean mReverseX; 28103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private boolean mReverseY; 28203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private float mX; 28303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private float mY; 28403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private float mRadius; 28503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private float mMoveStep = 10.0f; 28603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 28703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public AnimatedBackgroundDrawable() { 28803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mPaint = new Paint(); 28903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mPaint.setColor(0xFFFFFF00); 29003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mPaint.setAntiAlias(true); 29103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 29203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 29303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 29403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public void draw(Canvas canvas) { 29503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck stepColor(); 29603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck canvas.drawColor(mColor); 29703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 29803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mX += (mReverseX ? -mMoveStep : mMoveStep); 29903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mY += (mReverseY ? -mMoveStep : mMoveStep); 30003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck clampXY(); 30103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck canvas.drawCircle(mX, mY, mRadius, mPaint); 30203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 30303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck invalidateSelf(); 30403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 30503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 30603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private void clampXY() { 30703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mX <= mRadius) { 30803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mReverseX = false; 30903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mX = mRadius; 31003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 31103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mY <= mRadius) { 31203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mReverseY = false; 31303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mY = mRadius; 31403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 31503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck float maxX = getBounds().width() - mRadius; 31603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mX >= maxX) { 31703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mReverseX = true; 31803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mX = maxX; 31903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 32003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck float maxY = getBounds().height() - mRadius; 32103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mY >= maxY) { 32203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mReverseY = true; 32303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mY = maxY; 32403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 32503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 32603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 32703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 32803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck protected void onBoundsChange(Rect bounds) { 32903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck super.onBoundsChange(bounds); 33003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mMoveStep = Math.min(bounds.width(), bounds.height()) / 130.0f; 33103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mRadius = Math.min(bounds.width(), bounds.height()) / 20.0f; 33203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 33303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 33403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 33503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public void setAlpha(int alpha) { 33603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 33703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 33803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 33903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public void setColorFilter(ColorFilter colorFilter) { 34003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 34103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 34203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck @Override 34303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck public int getOpacity() { 34403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck return PixelFormat.OPAQUE; 34503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 34603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck 34703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck private void stepColor() { 34803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (mStartTime == 0) { 34903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mStartTime = AnimationUtils.currentAnimationTimeMillis(); 35003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 35103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck float frac = (AnimationUtils.currentAnimationTimeMillis() - mStartTime) 35203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck / (float) DURATION; 35303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (frac > 1.0f) frac = 1.0f; 35403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int dest = mReverse ? FROM_COLOR : TO_COLOR; 35503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int src = mReverse ? TO_COLOR : FROM_COLOR; 35603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int r = (int) (Color.red(src) + (Color.red(dest) - Color.red(src)) * frac); 35703a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int g = (int) (Color.green(src) + (Color.green(dest) - Color.green(src)) * frac); 35803a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck int b = (int) (Color.blue(src) + (Color.blue(dest) - Color.blue(src)) * frac); 35903a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mColor = Color.rgb(r, g, b); 36003a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck if (frac == 1.0f) { 36103a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mStartTime = 0; 36203a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck mReverse = !mReverse; 36303a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 36403a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 36503a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck } 36603a1edfe7f3aec23c8d459a53dadd2fe01b6eda2John Reck} 367