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

Commit 64ef4de9 authored by Marcin Oczeretko's avatar Marcin Oczeretko Committed by Android (Google) Code Review
Browse files

Merge "Add a flag to enable/disable/configure LatencyTracker"

parents 5cbc5a9f ad6cc0a7
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -14591,6 +14591,19 @@ public final class Settings {
         */
        public static final String MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH =
                "maximum_obscuring_opacity_for_touch";
        /**
         * LatencyTracker settings.
         *
         * The following strings are supported as keys:
         * <pre>
         *     enabled              (boolean)
         *     sampling_interval    (int)
         * </pre>
         *
         * @hide
         */
        public static final String LATENCY_TRACKER = "latency_tracker";
    }
    /**
+93 −11
Original line number Diff line number Diff line
@@ -15,14 +15,22 @@
package com.android.internal.util;

import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Build;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.EventLog;
import android.util.KeyValueListParser;
import android.util.Log;
import android.util.SparseLongArray;

import com.android.internal.logging.EventLogTags;
import com.android.internal.os.BackgroundThread;

import java.util.concurrent.ThreadLocalRandom;

/**
 * Class to track various latencies in SystemUI. It then writes the latency to statsd and also
@@ -34,6 +42,12 @@ import com.android.internal.logging.EventLogTags;
 */
public class LatencyTracker {
    private static final String TAG = "LatencyTracker";
    private static final String SETTINGS_ENABLED_KEY = "enabled";
    private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
    /** Default to being enabled on debug builds. */
    private static final boolean DEFAULT_ENABLED = Build.IS_DEBUGGABLE;
    /** Default to collecting data for 1/5 of all actions (randomly sampled). */
    private static final int DEFAULT_SAMPLING_INTERVAL = 5;

    /**
     * Time it takes until the first frame of the notification panel to be displayed while expanding
@@ -100,20 +114,59 @@ public class LatencyTracker {
    private static LatencyTracker sLatencyTracker;

    private final SparseLongArray mStartRtc = new SparseLongArray();
    private final Context mContext;
    private volatile int mSamplingInterval;
    private volatile boolean mEnabled;

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

    public LatencyTracker(Context context) {
        mContext = context;
        mEnabled = DEFAULT_ENABLED;
        mSamplingInterval = DEFAULT_SAMPLING_INTERVAL;

        // Post initialization to the background in case we're running on the main thread.
        BackgroundThread.getHandler().post(this::registerSettingsObserver);
        BackgroundThread.getHandler().post(this::readSettings);
    }

    private void registerSettingsObserver() {
        Uri settingsUri = Settings.Global.getUriFor(Settings.Global.LATENCY_TRACKER);
        mContext.getContentResolver().registerContentObserver(
                settingsUri, false, new SettingsObserver(this), UserHandle.myUserId());
    }

    private void readSettings() {
        KeyValueListParser parser = new KeyValueListParser(',');
        String settingsValue = Settings.Global.getString(mContext.getContentResolver(),
                Settings.Global.LATENCY_TRACKER);

        try {
            parser.setString(settingsValue);
            mSamplingInterval = parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY,
                    DEFAULT_SAMPLING_INTERVAL);
            mEnabled = parser.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "Incorrect settings format", e);
            mEnabled = false;
        }
    }

    public static boolean isEnabled(Context ctx) {
        return getInstance(ctx).isEnabled();
    }

    public boolean isEnabled() {
        return Build.IS_DEBUGGABLE;
        return mEnabled;
    }

    /**
@@ -154,10 +207,39 @@ public class LatencyTracker {
     * @param action          The action to end. One of the ACTION_* values.
     * @param duration        The duration of the action in ms.
     */
    public static void logAction(int action, int duration) {
    public void logAction(int action, int duration) {
        boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
        logActionDeprecated(action, duration, shouldSample);
    }

    /**
     * Logs an action that has started and ended. This needs to be called from the main thread.
     *
     * @param action          The action to end. One of the ACTION_* values.
     * @param duration        The duration of the action in ms.
     * @param writeToStatsLog Whether to write the measured latency to FrameworkStatsLog.
     */
    public static void logActionDeprecated(int action, int duration, boolean writeToStatsLog) {
        Log.i(TAG, "action=" + action + " latency=" + duration);
        EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration);

        if (writeToStatsLog) {
            FrameworkStatsLog.write(
                    FrameworkStatsLog.UI_ACTION_LATENCY_REPORTED, STATSD_ACTION[action], duration);
        }
    }

    private static class SettingsObserver extends ContentObserver {
        private final LatencyTracker mThisTracker;

        SettingsObserver(LatencyTracker thisTracker) {
            super(BackgroundThread.getHandler());
            mThisTracker = thisTracker;
        }

        @Override
        public void onChange(boolean selfChange, Uri uri, int userId) {
            mThisTracker.readSettings();
        }
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ public class SettingsBackupTest {
                    Settings.Global.KERNEL_CPU_THREAD_READER,
                    Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
                    Settings.Global.LANG_ID_UPDATE_METADATA_URL,
                    Settings.Global.LATENCY_TRACKER,
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
                    Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
+12 −1
Original line number Diff line number Diff line
@@ -28,7 +28,18 @@ public class LatencyTrackerCompat {
        return LatencyTracker.isEnabled(context);
    }

    /**
     * @see LatencyTracker
     * @deprecated Please use {@link LatencyTrackerCompat#logToggleRecents(Context, int)} instead.
     */
    @Deprecated
    public static void logToggleRecents(int duration) {
        LatencyTracker.logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, duration);
        LatencyTracker.logActionDeprecated(LatencyTracker.ACTION_TOGGLE_RECENTS, duration, false);
    }

    /** @see LatencyTracker */
    public static void logToggleRecents(Context context, int duration) {
        LatencyTracker.getInstance(context).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
                duration);
    }
}
 No newline at end of file