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

This commit is contained in:
Marcin Oczeretko
2020-10-15 13:04:48 +00:00
committed by Android (Google) Code Review
4 changed files with 119 additions and 12 deletions

View File

@@ -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";
}
/**

View File

@@ -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
@@ -76,7 +90,7 @@ public class LatencyTracker {
*/
public static final int ACTION_FACE_WAKE_AND_UNLOCK = 7;
private static final String[] NAMES = new String[] {
private static final String[] NAMES = new String[]{
"expand panel",
"toggle recents",
"fingerprint wake-and-unlock",
@@ -84,9 +98,9 @@ public class LatencyTracker {
"check credential unlocked",
"turn on screen",
"rotate the screen",
"face wake-and-unlock" };
"face wake-and-unlock"};
private static final int[] STATSD_ACTION = new int[] {
private static final int[] STATSD_ACTION = new int[]{
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS,
FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FINGERPRINT_WAKE_AND_UNLOCK,
@@ -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;
}
/**
@@ -145,19 +198,48 @@ public class LatencyTracker {
}
mStartRtc.delete(action);
Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0);
logAction(action, (int)(endRtc - startRtc));
logAction(action, (int) (endRtc - startRtc));
}
/**
* 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 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);
FrameworkStatsLog.write(
FrameworkStatsLog.UI_ACTION_LATENCY_REPORTED, STATSD_ACTION[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();
}
}
}

View File

@@ -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,

View File

@@ -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);
}
}