Crop based on real-time insets

This crops above taskbar unless app is immersive

Bug: 336511494
Test: Enable pinned taskbar, launch app, note correct bounds
Flag: com.android.wm.shell.enable_dynamic_insets_for_app_launch

Change-Id: Ie8124ae18176d167986f9861876d426ec2c6097f
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index aae8a56..24faa39 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -66,6 +66,7 @@
 import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary;
 import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
 import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
+import static com.android.wm.shell.Flags.enableDynamicInsetsForAppLaunch;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -279,6 +280,8 @@
     private final Interpolator mOpeningXInterpolator;
     private final Interpolator mOpeningInterpolator;
 
+    private final SystemUiProxy mSystemUiProxy;
+
     public QuickstepTransitionManager(Context context) {
         mLauncher = Launcher.cast(Launcher.getLauncher(context));
         mDragLayer = mLauncher.getDragLayer();
@@ -293,6 +296,7 @@
         mMaxShadowRadius = res.getDimensionPixelSize(R.dimen.max_shadow_radius);
 
         mLauncher.addOnDeviceProfileChangeListener(this);
+        mSystemUiProxy = SystemUiProxy.INSTANCE.get(mLauncher);
 
         if (ENABLE_SHELL_STARTING_SURFACE) {
             mTaskStartParams = new LinkedHashMap<>(MAX_NUM_TASKS) {
@@ -302,8 +306,7 @@
                 }
             };
 
-            SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
-                    mStartingWindowListener);
+            mSystemUiProxy.setStartingWindowListener(mStartingWindowListener);
         }
 
         mOpeningXInterpolator = AnimationUtils.loadInterpolator(context, R.interpolator.app_open_x);
@@ -504,12 +507,6 @@
                         4 - rotationChange);
             }
         }
-        if (mDeviceProfile.isTaskbarPresentInApps
-                && !target.willShowImeOnTarget
-                && !isTransientTaskbar(mLauncher)) {
-            // Animate to above the taskbar.
-            bounds.bottom -= target.contentInsets.bottom;
-        }
         return bounds;
     }
 
@@ -676,6 +673,13 @@
         };
     }
 
+    private boolean shouldCropToInset(RemoteAnimationTarget target) {
+        return enableDynamicInsetsForAppLaunch()
+                && mDeviceProfile.isTaskbarPresentInApps
+                && target != null && !target.willShowImeOnTarget
+                && !isTransientTaskbar(mLauncher);
+    }
+
     /**
      * @return Animator that controls the window of the opening targets from app icons.
      */
@@ -684,8 +688,19 @@
             RemoteAnimationTarget[] wallpaperTargets,
             RemoteAnimationTarget[] nonAppTargets,
             boolean launcherClosing) {
+        RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets,
+                wallpaperTargets, nonAppTargets, MODE_OPENING);
         int rotationChange = getRotationChange(appTargets);
         Rect windowTargetBounds = getWindowTargetBounds(appTargets, rotationChange);
+        final int[] bottomInsetPos = new int[]{
+                mSystemUiProxy.getHomeVisibilityState().getNavbarInsetPosition()};
+        final RemoteAnimationTarget target = openingTargets.getFirstAppTarget();
+        final boolean cropToInset = shouldCropToInset(target);
+        if (cropToInset) {
+            // Animate to above the taskbar.
+            windowTargetBounds.bottom = Math.min(bottomInsetPos[0],
+                    windowTargetBounds.bottom);
+        }
         boolean appTargetsAreTranslucent = areAllTargetsTranslucent(appTargets);
 
         RectF launcherIconBounds = new RectF();
@@ -698,8 +713,6 @@
         Rect crop = new Rect();
         Matrix matrix = new Matrix();
 
-        RemoteAnimationTargets openingTargets = new RemoteAnimationTargets(appTargets,
-                wallpaperTargets, nonAppTargets, MODE_OPENING);
         SurfaceTransactionApplier surfaceApplier =
                 new SurfaceTransactionApplier(floatingView);
         openingTargets.addReleaseCheck(surfaceApplier);
@@ -805,6 +818,39 @@
 
             @Override
             public void onUpdate(float percent, boolean initOnly) {
+                if (cropToInset && bottomInsetPos[0] != mSystemUiProxy.getHomeVisibilityState()
+                        .getNavbarInsetPosition()) {
+                    final RemoteAnimationTarget target = openingTargets.getFirstAppTarget();
+                    bottomInsetPos[0] = mSystemUiProxy.getHomeVisibilityState()
+                            .getNavbarInsetPosition();
+                    final Rect bounds = target != null
+                            ? target.screenSpaceBounds : windowTargetBounds;
+                    // Animate to above the taskbar.
+                    int bottomLevel = Math.min(bottomInsetPos[0], bounds.bottom);
+                    windowTargetBounds.bottom = bottomLevel;
+                    final int endHeight = bottomLevel - bounds.top;
+
+                    AnimOpenProperties prop = new AnimOpenProperties(mLauncher.getResources(),
+                            mDeviceProfile, windowTargetBounds, launcherIconBounds, v,
+                            dragLayerBounds[0], dragLayerBounds[1], hasSplashScreen,
+                            floatingView.isDifferentFromAppIcon());
+                    mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd,
+                            mOpeningInterpolator);
+                    mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd,
+                            mOpeningInterpolator);
+                    mDy = new FloatProp(0, prop.dY, mOpeningInterpolator);
+                    mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale,
+                            prop.finalAppIconScale, mOpeningInterpolator);
+                    float interpolatedPercent = mOpeningInterpolator.getInterpolation(percent);
+                    mCropRectHeight.value = Utilities.mapRange(interpolatedPercent,
+                            prop.cropHeightStart, prop.cropHeightEnd);
+                    mCropRectCenterY.value = Utilities.mapRange(interpolatedPercent,
+                            prop.cropCenterYStart, prop.cropCenterYEnd);
+                    mDy.value = Utilities.mapRange(interpolatedPercent, 0, prop.dY);
+                    mIconScaleToFitScreen.value = Utilities.mapRange(interpolatedPercent,
+                            prop.initialAppIconScale, prop.finalAppIconScale);
+                }
+
                 // Calculate the size of the scaled icon.
                 float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value;
                 float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value;
diff --git a/quickstep/src/com/android/quickstep/HomeVisibilityState.kt b/quickstep/src/com/android/quickstep/HomeVisibilityState.kt
index 1345e0b..020b9e2 100644
--- a/quickstep/src/com/android/quickstep/HomeVisibilityState.kt
+++ b/quickstep/src/com/android/quickstep/HomeVisibilityState.kt
@@ -18,6 +18,9 @@
 
 import android.os.RemoteException
 import android.util.Log
+import android.view.InsetsState
+import android.view.WindowInsets
+
 import com.android.launcher3.Utilities
 import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.util.Executors
@@ -30,6 +33,8 @@
     var isHomeVisible = true
         private set
 
+    @Volatile var navbarInsetPosition = 0
+
     private var listeners = mutableSetOf<VisibilityChangeListener>()
 
     fun addListener(l: VisibilityChangeListener) = listeners.add(l)
@@ -50,6 +55,11 @@
                             },
                         )
                     }
+                    override fun onDisplayInsetsChanged(insetsState: InsetsState) {
+                        val bottomInset = insetsState.calculateInsets(insetsState.displayFrame,
+                                WindowInsets.Type.navigationBars(), false).bottom
+                        navbarInsetPosition = insetsState.displayFrame.bottom - bottomInset
+                    }
                 }
             )
         } catch (e: RemoteException) {