Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit beefecc3 authored by Adrian Salido's avatar Adrian Salido
Browse files

TouchLatency: make updates time based and add fps to ball mode

Make ball updates time based instead of based on number of onDraw calls.
Also adding fps count to see how often frames are being updated, make
the color of the ball based on fps. This helps notice when there are
possible janks or change in refresh rate.

Test: gradlew build and run manual test of TouchLatency app
Change-Id: Ic2c2eb0fbd9fb31dddeee3228d6ab971a4f7f5e8
parent 39736939
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,4 +3,5 @@
/.idea
.DS_Store
/build
/gen
.iml
+3 −3
Original line number Diff line number Diff line
apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"
    compileSdkVersion 28
    buildToolsVersion '28.0.3'

    defaultConfig {
        applicationId "com.prefabulated.touchlatency"
        minSdkVersion 21
        targetSdkVersion 21
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }
+66 −35
Original line number Diff line number Diff line
@@ -19,11 +19,9 @@ package com.prefabulated.touchlatency;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.CountDownTimer;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.text.method.Touch;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Menu;
@@ -31,15 +29,17 @@ import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.os.Trace;

import java.util.ArrayList;
import java.util.Collections;
import java.math.RoundingMode;
import java.text.DecimalFormat;

class TouchLatencyView extends View implements View.OnTouchListener {
    private static final String LOG_TAG = "TouchLatency";
    private static final int BACKGROUND_COLOR = 0xFF400080;
    private static final int INNER_RADIUS = 70;
    private static final int BALL_RADIUS = 100;
    private static final int BALL_DIAMETER = 200;
    private static final int SEC_TO_NANOS = 1000000000;
    private static final float FPS_UPDATE_THRESHOLD = 20;
    private static final long BALL_VELOCITY = 420;

    public TouchLatencyView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -58,13 +58,17 @@ class TouchLatencyView extends View implements View.OnTouchListener {
        mRedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRedPaint.setColor(0xFFFF0000);
        mRedPaint.setStyle(Paint.Style.FILL);
        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setColor(0xFFFFFFFF);
        mTextPaint.setTextSize(100);
        mTextPaint.setTextAlign(Align.RIGHT);

        mTouching = false;

        mBallX = 100.0f;
        mBallY = 100.0f;
        mVelocityX = 7.0f;
        mVelocityY = 7.0f;
        mLastDrawNano = 0;
        mFps = 0;
        mLastFpsUpdate = 0;
        mFrameCount = 0;
        Trace.endSection();
    }

@@ -113,43 +117,70 @@ class TouchLatencyView extends View implements View.OnTouchListener {
        }
    }

    private Paint getBallColor() {
        if (mFps > 75)
            return mGreenPaint;
        else if (mFps > 45)
            return mYellowPaint;
        else
            return mRedPaint;
    }

    private void drawBall(Canvas canvas) {
        Trace.beginSection("TouchLatencyView drawBall");
        int width = canvas.getWidth();
        int height = canvas.getHeight();
        float fps = 0f;

        // Update position
        mBallX += mVelocityX;
        mBallY += mVelocityY;
        long t = System.nanoTime();
        long tDiff = t - mLastDrawNano;
        mLastDrawNano = t;
        mFrameCount++;

        // Clamp and change velocity if necessary
        float left = mBallX - BALL_RADIUS;
        if (left < 0) {
            left = 0;
            mVelocityX *= -1;
        if (tDiff < SEC_TO_NANOS) {
            fps = 1f * SEC_TO_NANOS / tDiff;
        }

        float top = mBallY - BALL_RADIUS;
        if (top < 0) {
            top = 0;
            mVelocityY *= -1;
        long fDiff = t - mLastFpsUpdate;
        if (Math.abs(mFps - fps) > FPS_UPDATE_THRESHOLD) {
            mFps = fps;
            mLastFpsUpdate = t;
            mFrameCount = 0;
        } else if (fDiff > SEC_TO_NANOS) {
            mFps = 1f * mFrameCount * SEC_TO_NANOS / fDiff;
            mLastFpsUpdate = t;
            mFrameCount = 0;
        }

        float right = mBallX + BALL_RADIUS;
        if (right > width) {
            right = width;
            mVelocityX *= -1;
        final long pos = t * BALL_VELOCITY / SEC_TO_NANOS;
        final long xMax = width - BALL_DIAMETER;
        final long yMax = height - BALL_DIAMETER;
        long xOffset = pos % xMax;
        long yOffset = pos % yMax;

        float left, right, top, bottom;

        if (((pos / xMax) & 1) == 0) {
            left = xMax - xOffset;
        } else {
            left = xOffset;
        }
        right = left + BALL_DIAMETER;

        float bottom = mBallY + BALL_RADIUS;
        if (bottom > height) {
            bottom = height;
            mVelocityY *= -1;
        if (((pos / yMax) & 1) == 0) {
            top = yMax - yOffset;
        } else {
            top = yOffset;
        }
        bottom = top + BALL_DIAMETER;

        // Draw the ball
        canvas.drawColor(BACKGROUND_COLOR);
        canvas.drawOval(left, top, right, bottom, mYellowPaint);
        canvas.drawOval(left, top, right, bottom, getBallColor());
        DecimalFormat df = new DecimalFormat("fps: #.##");
        df.setRoundingMode(RoundingMode.HALF_UP);
        canvas.drawText(df.format(mFps), width, 100, mTextPaint);

        invalidate();
        Trace.endSection();
    }
@@ -176,15 +207,15 @@ class TouchLatencyView extends View implements View.OnTouchListener {
        Trace.endSection();
    }

    private Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint;
    private final Paint mBluePaint, mGreenPaint, mYellowPaint, mRedPaint, mTextPaint;
    private int mMode;

    private boolean mTouching;
    private float mTouchX, mTouchY;
    private float mLastDrawnX, mLastDrawnY;

    private float mBallX, mBallY;
    private float mVelocityX, mVelocityY;
    private long mLastDrawNano, mLastFpsUpdate, mFrameCount;
    private float mFps;
}

public class TouchLatencyActivity extends Activity {
+3 −1
Original line number Diff line number Diff line
@@ -3,9 +3,10 @@
buildscript {
    repositories {
        jcenter()
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.1.0'
        classpath 'com.android.tools.build:gradle:3.2.1'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
@@ -15,5 +16,6 @@ buildscript {
allprojects {
    repositories {
        jcenter()
        google()
    }
}
+2 −2
Original line number Diff line number Diff line
#Wed Apr 10 15:27:10 PDT 2013
#Tue Nov 27 13:37:59 PST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip