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

Commit e05256e2 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Add LatencyTracker to track important SystemUI latencies for testing

Add a new class that can record latencies for various actions. Add a
new system property debug.systemui.latency_tracking to enable/disable
latency as well as a broadcast to reload the property if it changes.

This will be used to write lab latency tests to track important
transitions/latencies.

Change-Id: I11f96f1c410d83f2d3dbbdf903b29e3035744fb8
parent 0a9ba66b
Loading
Loading
Loading
Loading
+110 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.systemui;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.util.Log;
import android.util.SparseLongArray;

/**
 * Class to track various latencies in SystemUI. It then outputs the latency to logcat so these
 * latencies can be captured by tests and then used for dashboards.
 */
public class LatencyTracker {

    private static final String ACTION_RELOAD_PROPERTY =
            "com.android.systemui.RELOAD_LATENCY_TRACKER_PROPERTY";

    private static final String TAG = "LatencyTracker";

    public static final int ACTION_EXPAND_PANEL = 0;
    public static final int ACTION_TOGGLE_RECENTS = 1;

    private static final String[] NAMES = new String[] {
            "expand panel",
            "toggle recents" };

    private static LatencyTracker sLatencyTracker;

    private final SparseLongArray mStartRtc = new SparseLongArray();
    private boolean mEnabled;

    public static LatencyTracker getInstance(Context context) {
        if (sLatencyTracker == null) {
            sLatencyTracker = new LatencyTracker(context);
        }
        return sLatencyTracker;
    }

    private LatencyTracker(Context context) {
        context.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                reloadProperty();
            }
        }, new IntentFilter(ACTION_RELOAD_PROPERTY));
        reloadProperty();
    }

    private void reloadProperty() {
        mEnabled = SystemProperties.getBoolean("debug.systemui.latency_tracking", false);
    }

    public static boolean isEnabled(Context ctx) {
        return Build.IS_DEBUGGABLE && getInstance(ctx).mEnabled;
    }

    /**
     * Notifies that an action is starting. This needs to be called from the main thread.
     *
     * @param action The action to start. One of the ACTION_* values.
     */
    public void onActionStart(int action) {
        if (!mEnabled) {
            return;
        }
        Trace.asyncTraceBegin(Trace.TRACE_TAG_APP, NAMES[action], 0);
        mStartRtc.put(action, SystemClock.elapsedRealtime());
    }

    /**
     * Notifies that an action has ended. This needs to be called from the main thread.
     *
     * @param action The action to end. One of the ACTION_* values.
     */
    public void onActionEnd(int action) {
        if (!mEnabled) {
            return;
        }
        long endRtc = SystemClock.elapsedRealtime();
        long startRtc = mStartRtc.get(action, -1);
        if (startRtc == -1) {
            return;
        }
        Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0);
        long duration = endRtc - startRtc;
        Log.i(TAG, "action=" + action + " latency=" + duration);
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -40,7 +40,9 @@ import android.view.WindowManager.LayoutParams;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.LatencyTracker;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
@@ -187,6 +189,11 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
                public boolean onPreDraw() {
                    mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
                    EventBus.getDefault().post(new RecentsDrawnEvent());
                    if (LatencyTracker.isEnabled(getApplicationContext())) {
                        DejankUtils.postAfterTraversal(() -> LatencyTracker.getInstance(
                                getApplicationContext()).onActionEnd(
                                LatencyTracker.ACTION_TOGGLE_RECENTS));
                    }
                    return true;
                }
            };
+17 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputDevice;
@@ -32,9 +33,11 @@ import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;

import com.android.systemui.DejankUtils;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.LatencyTracker;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.doze.DozeLog;
@@ -115,6 +118,7 @@ public abstract class PanelView extends FrameLayout {
    protected boolean mExpanding;
    private boolean mGestureWaitForTouchSlop;
    private boolean mIgnoreXTouchSlop;
    private boolean mExpandLatencyTracking;
    private Runnable mPeekRunnable = new Runnable() {
        @Override
        public void run() {
@@ -215,6 +219,14 @@ public abstract class PanelView extends FrameLayout {
        }
    }

    public void startExpandLatencyTracking() {
        if (LatencyTracker.isEnabled(mContext)) {
            LatencyTracker.getInstance(mContext).onActionStart(
                    LatencyTracker.ACTION_EXPAND_PANEL);
            mExpandLatencyTracking = true;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mInstantExpanding || mTouchDisabled
@@ -739,6 +751,11 @@ public abstract class PanelView extends FrameLayout {
    }

    public void setExpandedHeightInternal(float h) {
        if (mExpandLatencyTracking && h != 0f) {
            DejankUtils.postAfterTraversal(() -> LatencyTracker.getInstance(mContext).onActionEnd(
                    LatencyTracker.ACTION_EXPAND_PANEL));
            mExpandLatencyTracking = false;
        }
        float fhWithoutOverExpansion = getMaxPanelHeight() - getOverExpansionAmount();
        if (mHeightAnimator == null) {
            float overExpansionPixels = Math.max(0, h - fhWithoutOverExpansion);
+5 −0
Original line number Diff line number Diff line
@@ -132,6 +132,7 @@ import com.android.systemui.DemoMode;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Interpolators;
import com.android.systemui.LatencyTracker;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
@@ -1291,6 +1292,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (LatencyTracker.isEnabled(mContext)) {
                LatencyTracker.getInstance(mContext).onActionStart(
                        LatencyTracker.ACTION_TOGGLE_RECENTS);
            }
            awakenDreams();
            toggleRecentApps();
        }
+5 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.media.session.MediaSessionLegacyHelper;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Trace;
import android.util.AttributeSet;
import android.view.ActionMode;
import android.view.InputQueue;
@@ -225,6 +226,10 @@ public class StatusBarWindowView extends FrameLayout {

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN
                && mNotificationPanel.getExpandedHeight() == 0f) {
            mNotificationPanel.startExpandLatencyTracking();
        }
        mFalsingManager.onTouchEvent(ev, getWidth(), getHeight());
        if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == VISIBLE) {
            // Disallow new pointers while the brightness mirror is visible. This is so that you