Merge "Fixes bug where the camera app would launch below the lock-screen" into tm-qpr-dev
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 0cf2b28..d53a98c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -403,7 +403,9 @@
private boolean shouldDispatchToLauncher(int backType) {
return backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
&& mBackToLauncherCallback != null
- && mEnableAnimations.get();
+ && mEnableAnimations.get()
+ && mBackNavigationInfo != null
+ && mBackNavigationInfo.getDepartingAnimationTarget() != null;
}
private static void dispatchOnBackStarted(IOnBackInvokedCallback callback) {
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 4cce87a..a3ba88e 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -90,11 +90,36 @@
SkRect srcRect = inSrcRect.toSkRect();
- SkRect imageSrcRect =
- SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom);
- if (imageSrcRect.isEmpty()) {
- imageSrcRect = SkRect::MakeIWH(description.width, description.height);
+ SkRect imageSrcRect = SkRect::MakeIWH(description.width, description.height);
+ SkISize imageWH = SkISize::Make(description.width, description.height);
+ if (cropRect.left < cropRect.right && cropRect.top < cropRect.bottom) {
+ imageSrcRect =
+ SkRect::MakeLTRB(cropRect.left, cropRect.top, cropRect.right, cropRect.bottom);
+ imageWH = SkISize::Make(cropRect.right - cropRect.left, cropRect.bottom - cropRect.top);
+
+ // Chroma channels of YUV420 images are subsampled we may need to shrink the crop region by
+ // a whole texel on each side. Since skia still adds its own 0.5 inset, we apply an
+ // additional 0.5 inset. See GLConsumer::computeTransformMatrix for details.
+ float shrinkAmount = 0.0f;
+ switch (description.format) {
+ // Use HAL formats since some AHB formats are only available in vndk
+ case HAL_PIXEL_FORMAT_YCBCR_420_888:
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+ shrinkAmount = 0.5f;
+ break;
+ default:
+ break;
+ }
+
+ // Shrink the crop if it has more than 1-px and differs from the buffer size.
+ if (imageWH.width() > 1 && imageWH.width() < (int32_t)description.width)
+ imageSrcRect = imageSrcRect.makeInset(shrinkAmount, 0);
+
+ if (imageWH.height() > 1 && imageWH.height() < (int32_t)description.height)
+ imageSrcRect = imageSrcRect.makeInset(0, shrinkAmount);
}
+
ALOGV("imageSrcRect = " RECT_STRING, SK_RECT_ARGS(imageSrcRect));
// Represents the "logical" width/height of the texture. That is, the dimensions of the buffer
@@ -153,7 +178,7 @@
*/
SkMatrix m;
- const SkRect imageDstRect = SkRect::MakeIWH(imageSrcRect.width(), imageSrcRect.height());
+ const SkRect imageDstRect = SkRect::Make(imageWH);
const float px = imageDstRect.centerX();
const float py = imageDstRect.centerY();
if (windowTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index db41601..a66dc77 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -427,18 +427,14 @@
mPipTransaction = null;
}
}
- // Release surface references now. This is apparently to free GPU
- // memory while doing quick operations (eg. during CTS).
- for (int i = 0; i < mLeashMap.size(); ++i) {
- if (mLeashMap.keyAt(i) == mLeashMap.valueAt(i)) continue;
- t.remove(mLeashMap.valueAt(i));
- }
try {
mFinishCB.onTransitionFinished(wct.isEmpty() ? null : wct, t);
} catch (RemoteException e) {
Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e);
t.apply();
}
+ // Only release the non-local created surface references. The animator is responsible
+ // for releasing the leashes created by local.
for (int i = 0; i < mInfo.getChanges().size(); ++i) {
mInfo.getChanges().get(i).getLeash().release();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index a146340..2214287 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -398,7 +398,14 @@
if (child instanceof ActivatableNotificationView) {
ActivatableNotificationView anv =
(ActivatableNotificationView) child;
- updateCornerRoundnessOnScroll(anv, viewStart, shelfStart);
+ // Because we show whole notifications on the lockscreen, the bottom notification is
+ // always "just about to enter the shelf" by normal scrolling rules. This is fine
+ // if the shelf is visible, but if the shelf is hidden, it causes incorrect curling.
+ // notificationClipEnd handles the discrepancy between a visible and hidden shelf,
+ // so we use that when on the keyguard (and while animating away) to reduce curling.
+ final float keyguardSafeShelfStart =
+ mAmbientState.isOnKeyguard() ? notificationClipEnd : shelfStart;
+ updateCornerRoundnessOnScroll(anv, viewStart, keyguardSafeShelfStart);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ee6b05f..d4155d1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -7733,9 +7733,6 @@
// relatively fixed.
overrideConfig.colorMode = fullConfig.colorMode;
overrideConfig.densityDpi = fullConfig.densityDpi;
- // The smallest screen width is the short side of screen bounds. Because the bounds
- // and density won't be changed, smallestScreenWidthDp is also fixed.
- overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
if (info.isFixedOrientation()) {
// lock rotation too. When in size-compat, onConfigurationChanged will watch for and
// apply runtime rotation changes.
@@ -7832,7 +7829,7 @@
// computed accordingly.
if (!matchParentBounds()) {
getTaskFragment().computeConfigResourceOverrides(resolvedConfig,
- newParentConfiguration);
+ newParentConfiguration, areBoundsLetterboxed());
}
// If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
// are already calculated in resolveFixedOrientationConfiguration.
@@ -8003,7 +8000,8 @@
}
// Since bounds has changed, the configuration needs to be computed accordingly.
- getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
+ getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
+ areBoundsLetterboxed());
}
void recomputeConfiguration() {
@@ -8219,7 +8217,7 @@
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig);
+ newParentConfig, mCompatDisplayInsets, areBoundsLetterboxed());
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -8247,7 +8245,7 @@
// Compute the configuration based on the resolved bounds. If aspect ratio doesn't
// restrict, the bounds should be the requested override bounds.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- getFixedRotationTransformDisplayInfo());
+ getFixedRotationTransformDisplayInfo(), areBoundsLetterboxed());
}
}
@@ -8311,7 +8309,7 @@
// are calculated in compat container space. The actual position on screen will be applied
// later, so the calculation is simpler that doesn't need to involve offset from parent.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- mCompatDisplayInsets);
+ mCompatDisplayInsets, areBoundsLetterboxed());
// Use current screen layout as source because the size of app is independent to parent.
resolvedConfig.screenLayout = TaskFragment.computeScreenLayoutOverride(
getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index d07cc68..9295c18 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -112,6 +112,7 @@
RemoteAnimationTarget topAppTarget = null;
int prevTaskId;
int prevUserId;
+ boolean prepareAnimation;
BackNavigationInfo.Builder infoBuilder = new BackNavigationInfo.Builder();
synchronized (wmService.mGlobalLock) {
@@ -257,7 +258,8 @@
BackNavigationInfo.typeToString(backType));
// For now, we only animate when going home.
- boolean prepareAnimation = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
+ prepareAnimation = backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
+ && requestAnimation
// Only create a new leash if no leash has been created.
// Otherwise return null for animation target to avoid conflict.
&& !removedWindowContainer.hasCommittedReparentToAnimationLeash();
@@ -292,7 +294,7 @@
}
// Special handling for back to home animation
- if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && requestAnimation
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && prepareAnimation
&& prevTask != null) {
currentTask.mBackGestureStarted = true;
// Make launcher show from behind by marking its top activity as visible and
@@ -347,7 +349,7 @@
Task finalTask = currentTask;
RemoteCallback onBackNavigationDone = new RemoteCallback(result -> onBackNavigationDone(
result, finalRemovedWindowContainer, finalBackType, finalTask,
- finalprevActivity, requestAnimation));
+ finalprevActivity, prepareAnimation));
infoBuilder.setOnBackNavigationDone(onBackNavigationDone);
}
@@ -381,14 +383,14 @@
private void onBackNavigationDone(
Bundle result, WindowContainer<?> windowContainer, int backType,
- Task task, ActivityRecord prevActivity, boolean requestAnimation) {
+ Task task, ActivityRecord prevActivity, boolean prepareAnimation) {
SurfaceControl surfaceControl = windowContainer.getSurfaceControl();
boolean triggerBack = result != null && result.getBoolean(
BackNavigationInfo.KEY_TRIGGER_BACK);
ProtoLog.d(WM_DEBUG_BACK_PREVIEW, "onBackNavigationDone backType=%s, "
+ "task=%s, prevActivity=%s", backType, task, prevActivity);
- if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && requestAnimation) {
+ if (backType == BackNavigationInfo.TYPE_RETURN_TO_HOME && prepareAnimation) {
if (triggerBack) {
if (surfaceControl != null && surfaceControl.isValid()) {
// When going back to home, hide the task surface before it is re-parented to
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index f8a9d46..21c5886 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1957,29 +1957,37 @@
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
@NonNull Configuration parentConfig) {
computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
- null /* compatInsets */);
+ null /* compatInsets */, false /* areBoundsLetterboxed */);
}
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
- @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
+ @NonNull Configuration parentConfig, boolean areBoundsLetterboxed) {
+ computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
+ null /* compatInsets */, areBoundsLetterboxed);
+ }
+
+ void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
+ @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
+ boolean areBoundsLetterboxed) {
if (overrideDisplayInfo != null) {
// Make sure the screen related configs can be computed by the provided display info.
inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
invalidateAppBoundsConfig(inOutConfig);
}
computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
- null /* compatInsets */);
+ null /* compatInsets */, areBoundsLetterboxed);
}
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
@NonNull Configuration parentConfig,
- @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
+ @Nullable ActivityRecord.CompatDisplayInsets compatInsets,
+ boolean areBoundsLetterboxed) {
if (compatInsets != null) {
// Make sure the app bounds can be computed by the compat insets.
invalidateAppBoundsConfig(inOutConfig);
}
computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
- compatInsets);
+ compatInsets, areBoundsLetterboxed);
}
/**
@@ -2006,7 +2014,8 @@
**/
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
@NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
- @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
+ @Nullable ActivityRecord.CompatDisplayInsets compatInsets,
+ boolean areBoundsLetterboxed) {
int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
windowingMode = parentConfig.windowConfiguration.getWindowingMode();
@@ -2113,6 +2122,7 @@
: overrideScreenHeightDp;
}
+ // TODO(b/238331848): Consider simplifying logic that computes smallestScreenWidthDp.
if (inOutConfig.smallestScreenWidthDp
== Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
// When entering to or exiting from Pip, the PipTaskOrganizer will set the
@@ -2128,9 +2138,10 @@
// task, because they should not be affected by insets.
inOutConfig.smallestScreenWidthDp = (int) (0.5f
+ Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
- } else if (isEmbedded()) {
- // For embedded TFs, the smallest width should be updated. Otherwise, inherit
- // from the parent task would result in applications loaded wrong resource.
+ } else if (isEmbedded() || areBoundsLetterboxed || customContainerPolicy) {
+ // For embedded TFs and activities that are letteboxed or eligible for size
+ // compat mode, the smallest width should be updated. Otherwise, inherit from
+ // the parent task would result in applications loaded wrong resource.
inOutConfig.smallestScreenWidthDp =
Math.min(inOutConfig.screenWidthDp, inOutConfig.screenHeightDp);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 91afa04..19b3384 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3760,6 +3760,15 @@
* hierarchy change implies a configuration change.
*/
private void onSyncReparent(WindowContainer oldParent, WindowContainer newParent) {
+ // Check if this is changing displays. If so, mark the old display as "ready" for
+ // transitions. This is to work around the problem where setting readiness against this
+ // container will only set the new display as ready and leave the old display as unready.
+ if (mSyncState != SYNC_STATE_NONE && oldParent != null
+ && oldParent.getDisplayContent() != null && (newParent == null
+ || oldParent.getDisplayContent() != newParent.getDisplayContent())) {
+ mTransitionController.setReady(oldParent.getDisplayContent());
+ }
+
if (newParent == null || newParent.mSyncState == SYNC_STATE_NONE) {
if (mSyncState == SYNC_STATE_NONE) {
return;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 324e244..f2640d2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1496,6 +1496,79 @@
}
@Test
+ public void testComputeConfigResourceOverrides_unresizableApp() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+
+ int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp;
+ int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp;
+
+ // App should launch in fixed orientation letterbox.
+ // Activity bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFitted();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
+
+ // Rotate display to portrait.
+ rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+ // After we rotate, the activity should go in the size-compat mode and report the same
+ // configuration values.
+ assertScaled();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+
+ // Restart activity
+ mActivity.restartProcessIfVisible();
+
+ // Now configuration should be updated
+ assertFitted();
+ assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+ assertEquals(mActivity.getConfiguration().screenWidthDp,
+ mActivity.getConfiguration().smallestScreenWidthDp);
+ }
+
+ @Test
+ public void testComputeConfigResourceOverrides_resizableFixedOrientationActivity() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app without max aspect.
+ prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_PORTRAIT, false /* isUnresizable */);
+
+ final Rect activityBounds = new Rect(mActivity.getBounds());
+
+ int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp;
+ int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp;
+
+ // App should launch in fixed orientation letterbox.
+ // Activity bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFitted();
+ assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
+ assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
+
+ // Rotate display to portrait.
+ rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+ // Now configuration should be updated
+ assertFitted();
+ assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp);
+ assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp);
+ assertEquals(mActivity.getConfiguration().screenWidthDp,
+ mActivity.getConfiguration().smallestScreenWidthDp);
+ }
+
+ @Test
public void testSplitAspectRatioForUnresizablePortraitApps() {
// Set up a display in landscape and ignoring orientation request.
int screenWidth = 1600;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 46e21f1..e2fe1b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -691,7 +691,8 @@
final ActivityRecord.CompatDisplayInsets compatInsets =
new ActivityRecord.CompatDisplayInsets(
display, activity, /* fixedOrientationBounds= */ null);
- task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatInsets);
+ task.computeConfigResourceOverrides(
+ inOutConfig, parentConfig, compatInsets, /* areBoundsLetterboxed */ true);
assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());
final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;