Support tracking latency of shell recents transition

Note that now the metric counts the transition delay because it is
the actual duration to start animation. While in legacy, the
event of transition start is notified immediately when calling
startRecentsActivity, so it counts the draw time as the duration.
The different duration sources are because of different concept of
the animation system, however, the duration is still consistent with
actual visual result.

Also move reportStartReasonsToLogger to the end of onTransactionReady
to align the ready timing with legacy handleAppTransitionReady, which
should be closer to where the animation is prepared.

Bug: 218847872
Test: adb shell setprop persist.debug.shell_transit 1; reboot
      Launch any app and swipe from bottom. The logcat should
      contain "LatencyTracker: ACTION_TOGGLE_RECENTS".

Change-Id: Ib731e9d7a5f412577891fd887bbeb0a142c0117c
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index a8dd856..a32d45c 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -68,6 +68,7 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_METRICS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_TIMEOUT;
 import static com.android.server.wm.EventLogTags.WM_ACTIVITY_LAUNCH_TIME;
 
@@ -102,6 +103,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.internal.util.LatencyTracker;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -742,6 +744,12 @@
             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);
             }
         }
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 2be24c8..85aaa2c 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -52,6 +52,7 @@
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
+import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_RECENTS_ANIM;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
 
@@ -594,8 +595,6 @@
 
         handleNonAppWindowsInTransition(dc, mType, mFlags);
 
-        reportStartReasonsToLogger();
-
         // The callback is only populated for custom activity-level client animations
         sendRemoteCallback(mClientAnimationStartCallback);
 
@@ -684,6 +683,8 @@
         }
         mSyncId = -1;
         mOverrideOptions = null;
+
+        reportStartReasonsToLogger();
     }
 
     /**
@@ -876,11 +877,15 @@
         for (int i = mParticipants.size() - 1; i >= 0; --i) {
             ActivityRecord r = mParticipants.valueAt(i).asActivityRecord();
             if (r == null || !r.mVisibleRequested) continue;
+            int transitionReason = APP_TRANSITION_WINDOWS_DRAWN;
             // At this point, r is "ready", but if it's not "ALL ready" then it is probably only
             // ready due to starting-window.
-            reasons.put(r, (r.mStartingData instanceof SplashScreenStartingData
-                    && !r.mLastAllReadyAtSync)
-                    ? APP_TRANSITION_SPLASH_SCREEN : APP_TRANSITION_WINDOWS_DRAWN);
+            if (r.mStartingData instanceof SplashScreenStartingData && !r.mLastAllReadyAtSync) {
+                transitionReason = APP_TRANSITION_SPLASH_SCREEN;
+            } else if (r.isActivityTypeHomeOrRecents() && isTransientLaunch(r)) {
+                transitionReason = APP_TRANSITION_RECENTS_ANIM;
+            }
+            reasons.put(r, transitionReason);
         }
         mController.mAtm.mTaskSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
                 reasons);