Centralize latency measurement of recents animation

So both legacy and shell transition use the same logic to log
the latency number.

Bug: 218847872
Test: Launch any app and swipe from bottom. The logcat should
      contain "LatencyTracker: ACTION_START_RECENTS_ANIMATION".
Change-Id: I5b28ca76f4a7b3d5a22ffc13f919c59003163e6b
This commit is contained in:
Riddle Hsu
2022-06-22 20:21:03 +08:00
parent d9fa425f92
commit 99561397cc
2 changed files with 26 additions and 27 deletions

View File

@@ -144,6 +144,12 @@ class ActivityMetricsLogger {
*/
private static final long UNKNOWN_VISIBILITY_CHECK_DELAY_MS = 3000;
/**
* If the recents animation is finished before the delay since the window drawn, do not log the
* action because the duration is too small that may be just an accidentally touch.
*/
private static final long LATENCY_TRACKER_RECENTS_DELAY_MS = 300;
/**
* The flag for {@link #notifyActivityLaunching} to skip associating a new launch with an active
* transition, in the case the launch is standalone (e.g. from recents).
@@ -734,10 +740,6 @@ class ActivityMetricsLogger {
if (info.mLoggedTransitionStarting) {
done(false /* abort */, info, "notifyWindowsDrawn", timestampNs);
}
if (r.mWmService.isRecentsAnimationTarget(r)) {
r.mWmService.getRecentsAnimationController().logRecentsAnimationStartTime(
info.mSourceEventDelayMs + info.mWindowsDrawnDelayMs);
}
return infoSnapshot;
}
@@ -782,12 +784,6 @@ class ActivityMetricsLogger {
info.mReason = activityToReason.valueAt(index);
info.mLoggedTransitionStarting = true;
if (info.mIsDrawn) {
if (info.mReason == APP_TRANSITION_RECENTS_ANIM) {
final LatencyTracker latencyTracker = r.mWmService.mLatencyTracker;
final int duration = info.mSourceEventDelayMs + info.mCurrentTransitionDelayMs;
mLoggerHandler.post(() -> latencyTracker.logAction(
LatencyTracker.ACTION_START_RECENTS_ANIMATION, duration));
}
done(false /* abort */, info, "notifyTransitionStarting drawn", timestampNs);
}
}
@@ -955,6 +951,9 @@ class ActivityMetricsLogger {
launchObserverNotifyActivityLaunchFinished(info, timestampNs);
}
logAppTransitionFinished(info, isHibernating != null ? isHibernating : false);
if (info.mReason == APP_TRANSITION_RECENTS_ANIM) {
logRecentsAnimationLatency(info);
}
}
mTransitionInfoList.remove(info);
}
@@ -1110,6 +1109,22 @@ class ActivityMetricsLogger {
Log.i(TAG, sb.toString());
}
private void logRecentsAnimationLatency(TransitionInfo info) {
final int duration = info.mSourceEventDelayMs + info.mWindowsDrawnDelayMs;
final ActivityRecord r = info.mLastLaunchedActivity;
final long lastTopLossTime = r.topResumedStateLossTime;
final WindowManagerService wm = mSupervisor.mService.mWindowManager;
final Object controller = wm.getRecentsAnimationController();
mLoggerHandler.postDelayed(() -> {
if (lastTopLossTime != r.topResumedStateLossTime
|| controller != wm.getRecentsAnimationController()) {
// Skip if the animation was finished in a short time.
return;
}
wm.mLatencyTracker.logAction(LatencyTracker.ACTION_START_RECENTS_ANIMATION, duration);
}, LATENCY_TRACKER_RECENTS_DELAY_MS);
}
private static int getAppStartTransitionType(int tronType, boolean relaunched) {
if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
return FrameworkStatsLog.APP_START_OCCURRED__TYPE__COLD;

View File

@@ -71,9 +71,7 @@ import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.os.BackgroundThread;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.LatencyTracker;
import com.android.internal.util.function.pooled.PooledConsumer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
@@ -99,11 +97,6 @@ import java.util.stream.Collectors;
public class RecentsAnimationController implements DeathRecipient {
private static final String TAG = RecentsAnimationController.class.getSimpleName();
private static final long FAILSAFE_DELAY = 1000;
/**
* If the recents animation is canceled before the delay since the window drawn, do not log the
* action because the duration is too small that may be just a mistouch.
*/
private static final long LATENCY_TRACKER_LOG_DELAY_MS = 300;
// Constant for a yet-to-be-calculated {@link RemoteAnimationTarget#Mode} state
private static final int MODE_UNKNOWN = -1;
@@ -144,7 +137,7 @@ public class RecentsAnimationController implements DeathRecipient {
private boolean mPendingStart = true;
// Set when the animation has been canceled
private volatile boolean mCanceled;
private boolean mCanceled;
// Whether or not the input consumer is enabled. The input consumer must be both registered and
// enabled for it to start intercepting touch events.
@@ -785,15 +778,6 @@ public class RecentsAnimationController implements DeathRecipient {
}, false /* traverseTopToBottom */);
}
void logRecentsAnimationStartTime(int durationMs) {
BackgroundThread.getHandler().postDelayed(() -> {
if (!mCanceled) {
mService.mLatencyTracker.logAction(LatencyTracker.ACTION_START_RECENTS_ANIMATION,
durationMs);
}
}, LATENCY_TRACKER_LOG_DELAY_MS);
}
private boolean removeTaskInternal(int taskId) {
boolean result = false;
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {