Merge cherrypicks of ['googleplex-android-review.googlesource.com/22381002', 'googleplex-android-review.googlesource.com/23351139', 'googleplex-android-review.googlesource.com/23351578', 'googleplex-android-review.googlesource.com/23661867'] into sparse-10335664-L85300000961746380.
SPARSE_CHANGE: I7b3dcd06e7483fde745a1d56dfee7c4efc262ed7
SPARSE_CHANGE: I9fc10876c03933ac8aac05205d56ad6537df72a8
SPARSE_CHANGE: I427f0bc23f00d245c5093c75f13c9e533209362e
SPARSE_CHANGE: Ifcdac241bfe33f44f5f03f1a6db682c57f0cd388

Change-Id: I03c2d42f79c545736783501e54185a06ab5ed809
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 5985d6e..10ca899 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -36,6 +36,7 @@
 import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;
 import static android.window.ConfigurationHelper.isDifferentDisplay;
 import static android.window.ConfigurationHelper.shouldUpdateResources;
+import static android.window.ConfigurationHelper.shouldUpdateWindowMetricsBounds;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 
@@ -5987,6 +5988,11 @@
     public static boolean shouldReportChange(@Nullable Configuration currentConfig,
             @NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets,
             int handledConfigChanges) {
+        // Always report changes in window configuration bounds
+        if (shouldUpdateWindowMetricsBounds(currentConfig, newConfig)) {
+            return true;
+        }
+
         final int publicDiff = currentConfig.diffPublicOnly(newConfig);
         // Don't report the change if there's no public diff between current and new config.
         if (publicDiff == 0) {
diff --git a/core/java/android/window/ConfigurationHelper.java b/core/java/android/window/ConfigurationHelper.java
index e32adcf..269ce08 100644
--- a/core/java/android/window/ConfigurationHelper.java
+++ b/core/java/android/window/ConfigurationHelper.java
@@ -106,7 +106,7 @@
      * @see WindowManager#getCurrentWindowMetrics()
      * @see WindowManager#getMaximumWindowMetrics()
      */
-    private static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig,
+    public static boolean shouldUpdateWindowMetricsBounds(@NonNull Configuration currentConfig,
             @NonNull Configuration newConfig) {
         final Rect currentBounds = currentConfig.windowConfiguration.getBounds();
         final Rect newBounds = newConfig.windowConfiguration.getBounds();
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 984ba58..1e1fca1 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -351,10 +351,8 @@
         final Rect bounds = activity.getWindowManager().getCurrentWindowMetrics().getBounds();
         assertEquals(activityConfigPortrait.windowConfiguration.getBounds(), bounds);
 
-        // Ensure that Activity#onConfigurationChanged() not be called because the changes in
-        // WindowConfiguration shouldn't be reported, and we only apply the latest Configuration
-        // update in transaction.
-        assertEquals(numOfConfig, activity.mNumOfConfigChanges);
+        // Ensure changes in window configuration bounds are reported
+        assertEquals(numOfConfig + 1, activity.mNumOfConfigChanges);
     }
 
     @Test
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 8386131..dd2d0ec 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -381,24 +381,15 @@
             final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
             final WindowManager windowManager = Objects.requireNonNull(
                     context.getSystemService(WindowManager.class));
-            final Rect currentBounds = windowManager.getCurrentWindowMetrics().getBounds();
             final Rect maxBounds = windowManager.getMaximumWindowMetrics().getBounds();
             boolean isTaskExpanded = maxBounds.equals(taskBounds);
-            boolean isActivityExpanded = maxBounds.equals(currentBounds);
             /*
              * We need to proxy being in full screen because when a user enters PiP and exits PiP
              * the task windowingMode will report multi-window/pinned until the transition is
              * finished in WM Shell.
              * maxBounds == taskWindowBounds is a proxy check to verify the window is full screen
-             * For tasks that are letterboxed, we use currentBounds == maxBounds to filter these
-             * out.
              */
-            // TODO(b/262900133) remove currentBounds check when letterboxed apps report bounds.
-            // currently we don't want to report to letterboxed apps since they do not update the
-            // window bounds when the Activity is moved.  An inaccurate fold will be reported so
-            // we skip.
-            return isTaskExpanded && (isActivityExpanded
-                    || mTaskFragmentOrganizer.isActivityEmbedded(activityToken));
+            return isTaskExpanded;
         } else {
             // TODO(b/242674941): use task windowing mode for window context that associates with
             //  activity.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 4d40db0..f1a8c95 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -260,22 +260,20 @@
                 );
             }
 
-            public void mergeAnimation(IBinder transition, TransitionInfo info,
-                    SurfaceControl.Transaction t, IBinder mergeTarget,
-                    IRemoteTransitionFinishedCallback finishCallback) {
+            public void mergeAnimation(IBinder candidateTransition, TransitionInfo candidateInfo,
+                    SurfaceControl.Transaction candidateT, IBinder currentTransition,
+                    IRemoteTransitionFinishedCallback candidateFinishCallback) {
                 try {
-                    final IRemoteTransitionFinishedCallback origFinishCB;
+                    final IRemoteTransitionFinishedCallback currentFinishCB;
                     synchronized (mFinishCallbacks) {
-                        origFinishCB = mFinishCallbacks.remove(transition);
+                        currentFinishCB = mFinishCallbacks.remove(currentTransition);
                     }
-                    info.releaseAllSurfaces();
-                    t.close();
-                    if (origFinishCB == null) {
-                        // already finished (or not started yet), so do nothing.
+                    if (currentFinishCB == null) {
+                        Slog.e(TAG, "Called mergeAnimation, but finish callback is missing");
                         return;
                     }
                     runner.onAnimationCancelled(false /* isKeyguardOccluded */);
-                    origFinishCB.onTransitionFinished(null /* wct */, null /* t */);
+                    currentFinishCB.onTransitionFinished(null /* wct */, null /* t */);
                 } catch (RemoteException e) {
                     // nothing, we'll just let it finish on its own I guess.
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 8218976..58ed3aa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -958,14 +958,12 @@
 
                 @Override
                 public void onAnimationCancelled(boolean isKeyguardOccluded) {
-                    if (mOccludeByDreamAnimator != null) {
-                        mOccludeByDreamAnimator.cancel();
-                    }
-                    setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */);
-                    if (DEBUG) {
-                        Log.d(TAG, "Occlude by Dream animation cancelled. Occluded state is now: "
-                                + mOccluded);
-                    }
+                    mContext.getMainExecutor().execute(() -> {
+                        if (mOccludeByDreamAnimator != null) {
+                            mOccludeByDreamAnimator.cancel();
+                        }
+                    });
+                    Log.d(TAG, "Occlude by Dream animation cancelled.");
                 }
 
                 @Override
@@ -1071,10 +1069,7 @@
                         }
                     });
 
-                    setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */);
-                    Log.d(TAG, "Unocclude animation cancelled. Occluded state is now: "
-                            + mOccluded);
-
+                    Log.d(TAG, "Unocclude animation cancelled.");
                     mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
                 }
 
@@ -3441,10 +3436,7 @@
         public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
             super.onAnimationCancelled(isKeyguardOccluded);
 
-            Log.d(TAG, "Occlude animation cancelled by WM. "
-                    + "Setting occluded state to: " + isKeyguardOccluded);
-            setOccluded(isKeyguardOccluded /* occluded */, false /* animate */);
-
+            Log.d(TAG, "Occlude animation cancelled by WM.");
             mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
         }
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 74d87cd6..2426a88 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2134,10 +2134,14 @@
         }
 
         mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
+            private boolean mOccludeChangingInTransition = false;
+
             @Override
             public int onAppTransitionStartingLocked(boolean keyguardGoingAway,
                     boolean keyguardOccluding, long duration, long statusBarAnimationStartTime,
                     long statusBarAnimationDuration) {
+                mOccludeChangingInTransition = keyguardGoingAway || keyguardOccluding;
+
                 // When remote animation is enabled for KEYGUARD_GOING_AWAY transition, SysUI
                 // receives IRemoteAnimationRunner#onAnimationStart to start animation, so we don't
                 // need to call IKeyguardService#keyguardGoingAway here.
@@ -2153,6 +2157,11 @@
                         0 /* duration */);
 
                 synchronized (mLock) {
+                    if (mOccludeChangingInTransition) {
+                        mKeyguardOccludedChanged = true;
+                        mOccludeChangingInTransition = false;
+                    }
+                    applyKeyguardOcclusionChange(false);
                     mLockAfterAppTransitionFinished = false;
                 }
             }
@@ -2160,12 +2169,16 @@
             @Override
             public void onAppTransitionFinishedLocked(IBinder token) {
                 synchronized (mLock) {
+                    if (mOccludeChangingInTransition) {
+                        mKeyguardOccludedChanged = true;
+                        mOccludeChangingInTransition = false;
+                    }
+                    applyKeyguardOcclusionChange(false /* transitionStarted */);
                     if (!mLockAfterAppTransitionFinished) {
                         return;
                     }
                     mLockAfterAppTransitionFinished = false;
                 }
-
                 lockNow(null);
             }
         });
@@ -3355,7 +3368,7 @@
         if (mKeyguardOccludedChanged) {
             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
                     + mPendingKeyguardOccluded);
-            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */,
+            if (setKeyguardOccludedLw(mPendingKeyguardOccluded, true /* force */,
                     transitionStarted)) {
                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
             }
@@ -3616,6 +3629,7 @@
     private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force,
             boolean transitionStarted) {
         if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
+        mPendingKeyguardOccluded = isOccluded;
         mKeyguardOccludedChanged = false;
         if (isKeyguardOccluded() == isOccluded && !force) {
             return false;