Loading core/java/com/android/internal/jank/InteractionJankMonitor.java +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.FrameTracker.FrameMetricsWrapper; import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper; import com.android.internal.jank.FrameTracker.ViewRootWrapper; import com.android.internal.util.PerfettoTrigger; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading core/java/com/android/internal/util/LatencyTracker.java +77 −17 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ package com.android.internal.util; import android.annotation.IntDef; import android.content.Context; import android.os.Build; import android.os.SystemClock; Loading @@ -23,9 +24,12 @@ import android.util.EventLog; import android.util.Log; import android.util.SparseLongArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.EventLogTags; import com.android.internal.os.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.ThreadLocalRandom; /** Loading Loading @@ -91,6 +95,34 @@ public class LatencyTracker { */ public static final int ACTION_START_RECENTS_ANIMATION = 8; private static final int[] ACTIONS_ALL = { ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, ACTION_FINGERPRINT_WAKE_AND_UNLOCK, ACTION_CHECK_CREDENTIAL, ACTION_CHECK_CREDENTIAL_UNLOCKED, ACTION_TURN_ON_SCREEN, ACTION_ROTATE_SCREEN, ACTION_FACE_WAKE_AND_UNLOCK, ACTION_START_RECENTS_ANIMATION }; /** @hide */ @IntDef({ ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, ACTION_FINGERPRINT_WAKE_AND_UNLOCK, ACTION_CHECK_CREDENTIAL, ACTION_CHECK_CREDENTIAL_UNLOCKED, ACTION_TURN_ON_SCREEN, ACTION_ROTATE_SCREEN, ACTION_FACE_WAKE_AND_UNLOCK, ACTION_START_RECENTS_ANIMATION }) @Retention(RetentionPolicy.SOURCE) public @interface Action { } private static final int[] STATSD_ACTION = new int[]{ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS, Loading @@ -105,9 +137,14 @@ public class LatencyTracker { private static LatencyTracker sLatencyTracker; private final Object mLock = new Object(); private final SparseLongArray mStartRtc = new SparseLongArray(); private volatile int mSamplingInterval; private volatile boolean mEnabled; @GuardedBy("mLock") private final int[] mTraceThresholdPerAction = new int[ACTIONS_ALL.length]; @GuardedBy("mLock") private int mSamplingInterval; @GuardedBy("mLock") private boolean mEnabled; public static LatencyTracker getInstance(Context context) { if (sLatencyTracker == null) { Loading @@ -132,20 +169,26 @@ public class LatencyTracker { } private void updateProperties(DeviceConfig.Properties properties) { synchronized (mLock) { mSamplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL); mEnabled = properties.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); for (int action : ACTIONS_ALL) { mTraceThresholdPerAction[action] = properties.getInt(getTraceTriggerNameForAction(action), -1); } } } /** * A helper method to translate action type to name. * * @param action the action type defined in AtomsProto.java * @param atomsProtoAction the action type defined in AtomsProto.java * @return the name of the action */ public static String getNameOfAction(int action) { public static String getNameOfAction(int atomsProtoAction) { // Defined in AtomsProto.java switch (action) { switch (atomsProtoAction) { case 0: return "UNKNOWN"; case 1: Loading @@ -171,24 +214,30 @@ public class LatencyTracker { } } private static String getTraceNameOfAction(int action) { private static String getTraceNameOfAction(@Action int action) { return "L<" + getNameOfAction(STATSD_ACTION[action]) + ">"; } private static String getTraceTriggerNameForAction(@Action int action) { return "latency-tracker-" + getNameOfAction(STATSD_ACTION[action]); } public static boolean isEnabled(Context ctx) { return getInstance(ctx).isEnabled(); } public boolean isEnabled() { synchronized (mLock) { return 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) { public void onActionStart(@Action int action) { if (!isEnabled()) { return; } Loading @@ -201,7 +250,7 @@ public class LatencyTracker { * * @param action The action to end. One of the ACTION_* values. */ public void onActionEnd(int action) { public void onActionEnd(@Action int action) { if (!isEnabled()) { return; } Loading @@ -221,8 +270,18 @@ public class LatencyTracker { * @param action The action to end. One of the ACTION_* values. * @param duration The duration of the action in ms. */ public void logAction(int action, int duration) { boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; public void logAction(@Action int action, int duration) { boolean shouldSample; int traceThreshold; synchronized (mLock) { shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; traceThreshold = mTraceThresholdPerAction[action]; } if (traceThreshold > 0 && duration >= traceThreshold) { PerfettoTrigger.trigger(getTraceTriggerNameForAction(action)); } logActionDeprecated(action, duration, shouldSample); } Loading @@ -233,7 +292,8 @@ public class LatencyTracker { * @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) { public static void logActionDeprecated( @Action int action, int duration, boolean writeToStatsLog) { Log.i(TAG, getNameOfAction(STATSD_ACTION[action]) + " latency=" + duration); EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration); Loading core/java/com/android/internal/jank/PerfettoTrigger.java→core/java/com/android/internal/util/PerfettoTrigger.java +44 −0 Original line number Diff line number Diff line Loading @@ -14,23 +14,18 @@ * limitations under the License. */ //TODO (165884885): Make PerfettoTrigger more generic and move it to another package. package com.android.internal.jank; package com.android.internal.util; import android.annotation.NonNull; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * A trigger implementation with perfetto backend. * @hide */ public class PerfettoTrigger { private static final String TAG = PerfettoTrigger.class.getSimpleName(); private static final boolean DEBUG = false; private static final String TAG = "PerfettoTrigger"; private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto"; /** Loading @@ -40,34 +35,10 @@ public class PerfettoTrigger { public static void trigger(String triggerName) { try { ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, triggerName); if (DEBUG) { StringBuilder sb = new StringBuilder(); for (String arg : pb.command()) { sb.append(arg).append(" "); } Log.d(TAG, "Triggering " + sb.toString()); } Log.v(TAG, "Triggering " + String.join(" ", pb.command())); Process process = pb.start(); if (DEBUG) { readConsoleOutput(process); } } catch (IOException | InterruptedException e) { } catch (IOException e) { Log.w(TAG, "Failed to trigger " + triggerName, e); } } private static void readConsoleOutput(@NonNull Process process) throws IOException, InterruptedException { process.waitFor(); try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { StringBuilder errLine = new StringBuilder(); String line; while ((line = errReader.readLine()) != null) { errLine.append(line).append("\n"); } errLine.append(", code=").append(process.exitValue()); Log.d(TAG, "err message=" + errLine.toString()); } } } Loading
core/java/com/android/internal/jank/InteractionJankMonitor.java +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.jank.FrameTracker.FrameMetricsWrapper; import com.android.internal.jank.FrameTracker.ThreadedRendererWrapper; import com.android.internal.jank.FrameTracker.ViewRootWrapper; import com.android.internal.util.PerfettoTrigger; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading
core/java/com/android/internal/util/LatencyTracker.java +77 −17 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ package com.android.internal.util; import android.annotation.IntDef; import android.content.Context; import android.os.Build; import android.os.SystemClock; Loading @@ -23,9 +24,12 @@ import android.util.EventLog; import android.util.Log; import android.util.SparseLongArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.EventLogTags; import com.android.internal.os.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.concurrent.ThreadLocalRandom; /** Loading Loading @@ -91,6 +95,34 @@ public class LatencyTracker { */ public static final int ACTION_START_RECENTS_ANIMATION = 8; private static final int[] ACTIONS_ALL = { ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, ACTION_FINGERPRINT_WAKE_AND_UNLOCK, ACTION_CHECK_CREDENTIAL, ACTION_CHECK_CREDENTIAL_UNLOCKED, ACTION_TURN_ON_SCREEN, ACTION_ROTATE_SCREEN, ACTION_FACE_WAKE_AND_UNLOCK, ACTION_START_RECENTS_ANIMATION }; /** @hide */ @IntDef({ ACTION_EXPAND_PANEL, ACTION_TOGGLE_RECENTS, ACTION_FINGERPRINT_WAKE_AND_UNLOCK, ACTION_CHECK_CREDENTIAL, ACTION_CHECK_CREDENTIAL_UNLOCKED, ACTION_TURN_ON_SCREEN, ACTION_ROTATE_SCREEN, ACTION_FACE_WAKE_AND_UNLOCK, ACTION_START_RECENTS_ANIMATION }) @Retention(RetentionPolicy.SOURCE) public @interface Action { } private static final int[] STATSD_ACTION = new int[]{ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS, Loading @@ -105,9 +137,14 @@ public class LatencyTracker { private static LatencyTracker sLatencyTracker; private final Object mLock = new Object(); private final SparseLongArray mStartRtc = new SparseLongArray(); private volatile int mSamplingInterval; private volatile boolean mEnabled; @GuardedBy("mLock") private final int[] mTraceThresholdPerAction = new int[ACTIONS_ALL.length]; @GuardedBy("mLock") private int mSamplingInterval; @GuardedBy("mLock") private boolean mEnabled; public static LatencyTracker getInstance(Context context) { if (sLatencyTracker == null) { Loading @@ -132,20 +169,26 @@ public class LatencyTracker { } private void updateProperties(DeviceConfig.Properties properties) { synchronized (mLock) { mSamplingInterval = properties.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, DEFAULT_SAMPLING_INTERVAL); mEnabled = properties.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); for (int action : ACTIONS_ALL) { mTraceThresholdPerAction[action] = properties.getInt(getTraceTriggerNameForAction(action), -1); } } } /** * A helper method to translate action type to name. * * @param action the action type defined in AtomsProto.java * @param atomsProtoAction the action type defined in AtomsProto.java * @return the name of the action */ public static String getNameOfAction(int action) { public static String getNameOfAction(int atomsProtoAction) { // Defined in AtomsProto.java switch (action) { switch (atomsProtoAction) { case 0: return "UNKNOWN"; case 1: Loading @@ -171,24 +214,30 @@ public class LatencyTracker { } } private static String getTraceNameOfAction(int action) { private static String getTraceNameOfAction(@Action int action) { return "L<" + getNameOfAction(STATSD_ACTION[action]) + ">"; } private static String getTraceTriggerNameForAction(@Action int action) { return "latency-tracker-" + getNameOfAction(STATSD_ACTION[action]); } public static boolean isEnabled(Context ctx) { return getInstance(ctx).isEnabled(); } public boolean isEnabled() { synchronized (mLock) { return 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) { public void onActionStart(@Action int action) { if (!isEnabled()) { return; } Loading @@ -201,7 +250,7 @@ public class LatencyTracker { * * @param action The action to end. One of the ACTION_* values. */ public void onActionEnd(int action) { public void onActionEnd(@Action int action) { if (!isEnabled()) { return; } Loading @@ -221,8 +270,18 @@ public class LatencyTracker { * @param action The action to end. One of the ACTION_* values. * @param duration The duration of the action in ms. */ public void logAction(int action, int duration) { boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; public void logAction(@Action int action, int duration) { boolean shouldSample; int traceThreshold; synchronized (mLock) { shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; traceThreshold = mTraceThresholdPerAction[action]; } if (traceThreshold > 0 && duration >= traceThreshold) { PerfettoTrigger.trigger(getTraceTriggerNameForAction(action)); } logActionDeprecated(action, duration, shouldSample); } Loading @@ -233,7 +292,8 @@ public class LatencyTracker { * @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) { public static void logActionDeprecated( @Action int action, int duration, boolean writeToStatsLog) { Log.i(TAG, getNameOfAction(STATSD_ACTION[action]) + " latency=" + duration); EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration); Loading
core/java/com/android/internal/jank/PerfettoTrigger.java→core/java/com/android/internal/util/PerfettoTrigger.java +44 −0 Original line number Diff line number Diff line Loading @@ -14,23 +14,18 @@ * limitations under the License. */ //TODO (165884885): Make PerfettoTrigger more generic and move it to another package. package com.android.internal.jank; package com.android.internal.util; import android.annotation.NonNull; import android.util.Log; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; /** * A trigger implementation with perfetto backend. * @hide */ public class PerfettoTrigger { private static final String TAG = PerfettoTrigger.class.getSimpleName(); private static final boolean DEBUG = false; private static final String TAG = "PerfettoTrigger"; private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto"; /** Loading @@ -40,34 +35,10 @@ public class PerfettoTrigger { public static void trigger(String triggerName) { try { ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, triggerName); if (DEBUG) { StringBuilder sb = new StringBuilder(); for (String arg : pb.command()) { sb.append(arg).append(" "); } Log.d(TAG, "Triggering " + sb.toString()); } Log.v(TAG, "Triggering " + String.join(" ", pb.command())); Process process = pb.start(); if (DEBUG) { readConsoleOutput(process); } } catch (IOException | InterruptedException e) { } catch (IOException e) { Log.w(TAG, "Failed to trigger " + triggerName, e); } } private static void readConsoleOutput(@NonNull Process process) throws IOException, InterruptedException { process.waitFor(); try (BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) { StringBuilder errLine = new StringBuilder(); String line; while ((line = errReader.readLine()) != null) { errLine.append(line).append("\n"); } errLine.append(", code=").append(process.exitValue()); Log.d(TAG, "err message=" + errLine.toString()); } } }