[Floaty] Add CUJ markers to floaty animation

Bug: 417725560
Test: Manual, i.e. verified that CUJs show up in perfetto traces and
      CUJ debug overlay
Flag: com.android.systemui.shared.enable_lpp_assist_invocation_effect
Change-Id: I9537542d6aa57714908cea263a82164dbacfcc1b
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/AppZoomOutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/AppZoomOutController.java
index 8b5b626..a22a298 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/AppZoomOutController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/AppZoomOutController.java
@@ -27,6 +27,7 @@
 import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.os.Handler;
 import android.util.Slog;
 import android.window.DisplayAreaInfo;
 import android.window.DisplayAreaOrganizer;
@@ -35,6 +36,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayChangeController;
 import com.android.wm.shell.common.DisplayController;
@@ -81,11 +83,13 @@
 
     public static AppZoomOutController create(Context context, ShellInit shellInit,
             ShellTaskOrganizer shellTaskOrganizer, DisplayController displayController,
-            DisplayLayout displayLayout, @ShellMainThread ShellExecutor mainExecutor) {
+            DisplayLayout displayLayout, @ShellMainThread ShellExecutor mainExecutor,
+            @ShellMainThread Handler mainHandler, InteractionJankMonitor interactionJankMonitor) {
         AppZoomOutDisplayAreaOrganizer appDisplayAreaOrganizer = new AppZoomOutDisplayAreaOrganizer(
                 context, displayLayout, mainExecutor);
         TopLevelZoomOutDisplayAreaOrganizer topLevelDisplayAreaOrganizer =
-                new TopLevelZoomOutDisplayAreaOrganizer(displayLayout, context, mainExecutor);
+                new TopLevelZoomOutDisplayAreaOrganizer(displayLayout, context, mainExecutor,
+                        mainHandler, interactionJankMonitor);
         return new AppZoomOutController(context, shellInit, shellTaskOrganizer, displayController,
                 appDisplayAreaOrganizer, topLevelDisplayAreaOrganizer, mainExecutor);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/TopLevelZoomOutDisplayAreaOrganizer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/TopLevelZoomOutDisplayAreaOrganizer.kt
index f379069..a239003 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/TopLevelZoomOutDisplayAreaOrganizer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/appzoomout/TopLevelZoomOutDisplayAreaOrganizer.kt
@@ -16,6 +16,7 @@
 package com.android.wm.shell.appzoomout
 
 import android.content.Context
+import android.os.Handler
 import android.util.ArrayMap
 import android.view.Choreographer
 import android.view.Display
@@ -23,6 +24,8 @@
 import android.window.DisplayAreaInfo
 import android.window.DisplayAreaOrganizer
 import android.window.WindowContainerToken
+import com.android.internal.jank.Cuj.CUJ_LPP_ASSIST_INVOCATION_EFFECT
+import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.policy.ScreenDecorationsUtils
 import com.android.wm.shell.common.DisplayLayout
 import java.util.concurrent.Executor
@@ -38,13 +41,16 @@
 class TopLevelZoomOutDisplayAreaOrganizer(
     displayLayout: DisplayLayout,
     private val context: Context,
-    mainExecutor: Executor
+    mainExecutor: Executor,
+    private val mainHandler: Handler,
+    private val interactionJankMonitor: InteractionJankMonitor,
 ) : DisplayAreaOrganizer(mainExecutor) {
 
     private val mDisplayAreaTokenMap: MutableMap<WindowContainerToken, SurfaceControl> = ArrayMap()
     private val mDisplayLayout = DisplayLayout()
     private var cornerRadius = 1f
     private var mProgress = 1f
+    private var isCujOnSuccessPath = false
 
     init {
         setDisplayLayout(displayLayout)
@@ -85,6 +91,7 @@
             return
         }
 
+        updateCuj(lastProgress = mProgress, progress = progress)
         mProgress = progress
         apply()
     }
@@ -164,6 +171,42 @@
             .setFrameTimelineVsync(Choreographer.getInstance().vsyncId)
     }
 
+    private fun updateCuj(lastProgress: Float, progress: Float) {
+        // TODO(b/418136893): Send clearer start/cancel/end signals from SysUI instead
+        if (progress == 1f) {
+            // If the animation reaches a progress of 1f, it means that assistant is being launched
+            // for sure and the animation could not have been cancelled (and can no longer be
+            // cancelled).
+            isCujOnSuccessPath = true
+        }
+        if (lastProgress == 0f && progress > 0f) {
+            // A new squeeze effect animation starts (progress starts moving away from 0f). Start
+            // the CUJ
+            mDisplayAreaTokenMap.values.firstOrNull()?.let {
+                interactionJankMonitor.begin(
+                    it,
+                    context,
+                    mainHandler,
+                    CUJ_LPP_ASSIST_INVOCATION_EFFECT
+                )
+            }
+        }
+        if (lastProgress > 0f && progress == 0f) {
+            // The progress is back at 0f, which marks the end of the animation.
+            if (isCujOnSuccessPath) {
+                // In case the isCujOnSuccessPath flag is set, assistant must have been launched
+                // and we can mark the end of the CUJ
+                interactionJankMonitor.end(CUJ_LPP_ASSIST_INVOCATION_EFFECT)
+            } else {
+                // If the isCujOnSuccessPath flag is not set, it means that the animation must have
+                // been cancelled. Mark the CUJ as cancelled.
+                interactionJankMonitor.cancel(CUJ_LPP_ASSIST_INVOCATION_EFFECT)
+            }
+            // Reset the isCujOnSuccessPath flag
+            isCujOnSuccessPath = false
+        }
+    }
+
     fun setDisplayLayout(displayLayout: DisplayLayout) {
         mDisplayLayout.set(displayLayout)
         cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 5ffd511..023ad6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -1735,9 +1735,12 @@
             ShellTaskOrganizer shellTaskOrganizer,
             DisplayController displayController,
             DisplayLayout displayLayout,
-            @ShellMainThread ShellExecutor mainExecutor) {
+            @ShellMainThread ShellExecutor mainExecutor,
+            @ShellMainThread Handler mainHandler,
+            InteractionJankMonitor interactionJankMonitor) {
         return AppZoomOutController.create(context, shellInit, shellTaskOrganizer,
-                displayController, displayLayout, mainExecutor);
+                displayController, displayLayout, mainExecutor, mainHandler,
+                interactionJankMonitor);
     }
 
     //