| Index: base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
|
| diff --git a/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3f9060c19a9ca708c1f4a7929b9bf25756378017
|
| --- /dev/null
|
| +++ b/base/android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java
|
| @@ -0,0 +1,109 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.base;
|
| +
|
| +import android.util.Log;
|
| +import android.view.Choreographer;
|
| +import android.view.Choreographer.FrameCallback;
|
| +
|
| +/**
|
| + * Record Android animation frame rate and save it to UMA histogram. This is mainly for monitoring
|
| + * any jankiness of short Chrome Android animations. It is limited to few seconds of recording.
|
| + */
|
| +public class AnimationFrameTimeHistogram {
|
| + private static final String TAG = "AnimationFrameTimeHistogram";
|
| + private static final int MAX_FRAME_TIME_NUM = 600; // 10 sec on 60 fps.
|
| +
|
| + private final String mHistogramName;
|
| + private Recorder mRecorder;
|
| +
|
| + /**
|
| + * @param histogramName The histogram name that the recorded frame times will be saved.
|
| + * This must be also defined in histograms.xml
|
| + */
|
| + public AnimationFrameTimeHistogram(String histogramName) {
|
| + mHistogramName = histogramName;
|
| + }
|
| +
|
| + /**
|
| + * Start recording frame times. The recording can fail if it exceeds a few seconds.
|
| + */
|
| + public void startRecording() {
|
| + mRecorder = new Recorder();
|
| + mRecorder.startRecording();
|
| + }
|
| +
|
| + /**
|
| + * End recording and save it to histogram. It won't save histogram if the recording wasn't
|
| + * successful.
|
| + */
|
| + public void endRecording() {
|
| + if (mRecorder.endRecording()) {
|
| + nativeSaveHistogram(mHistogramName,
|
| + mRecorder.getFrameTimesNs(), mRecorder.getFrameTimesCount());
|
| + }
|
| + mRecorder = null;
|
| + }
|
| +
|
| + /**
|
| + * Record Android animation frame rate and return the result.
|
| + */
|
| + private static class Recorder implements FrameCallback {
|
| + private final Choreographer mChoreographer = Choreographer.getInstance();
|
| + private final long[] mFrameTimesNs = new long[MAX_FRAME_TIME_NUM];
|
| + private boolean mIsRecording;
|
| + private long mPrevFrameTimeNs;
|
| + private int mFrameTimesCount;
|
| +
|
| + private void startRecording() {
|
| + mIsRecording = true;
|
| + mFrameTimesCount = -1;
|
| + mChoreographer.postFrameCallback(this);
|
| + }
|
| +
|
| + /**
|
| + * @return Whether the recording was successful. If successful, the result is available via
|
| + * getFrameTimesNs and getFrameTimesCount.
|
| + */
|
| + private boolean endRecording() {
|
| + boolean succeeded = mIsRecording;
|
| + mIsRecording = false;
|
| + return succeeded;
|
| + }
|
| +
|
| + private long[] getFrameTimesNs() {
|
| + return mFrameTimesNs;
|
| + }
|
| +
|
| + private int getFrameTimesCount() {
|
| + return mFrameTimesCount;
|
| + }
|
| +
|
| + @Override
|
| + public void doFrame(long frameTimeNs) {
|
| + if (!mIsRecording) {
|
| + return;
|
| + }
|
| +
|
| + if (mFrameTimesCount == mFrameTimesNs.length) {
|
| + mIsRecording = false;
|
| + Log.w(TAG, "Animation frame time recording reached the maximum number. It's either"
|
| + + "the animation took too long or recording end is not called.");
|
| + return;
|
| + }
|
| +
|
| + long timeDiffNs = frameTimeNs - mPrevFrameTimeNs;
|
| + mPrevFrameTimeNs = frameTimeNs;
|
| + if (mFrameTimesCount > -1) {
|
| + mFrameTimesNs[mFrameTimesCount] = timeDiffNs;
|
| + }
|
| +
|
| + ++mFrameTimesCount;
|
| + mChoreographer.postFrameCallback(this);
|
| + }
|
| + }
|
| +
|
| + private native void nativeSaveHistogram(String histogramName, long[] frameTimesNs, int count);
|
| +}
|
|
|