summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/SnapshotDrawerUtils.java106
-rw-r--r--core/java/android/window/StartingWindowInfo.java11
-rw-r--r--core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java5
-rw-r--r--services/core/java/com/android/server/wm/Task.java3
6 files changed, 71 insertions, 67 deletions
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index e5658e63f7ec..29bb32e6443f 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -52,11 +52,9 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.util.Log;
@@ -98,11 +96,6 @@ public class SnapshotDrawerUtils {
| FLAG_SECURE
| FLAG_DIM_BEHIND;
- private static final RectF sTmpSnapshotSize = new RectF();
- private static final RectF sTmpDstFrame = new RectF();
-
- private static final Matrix sSnapshotMatrix = new Matrix();
- private static final float[] sTmpFloat9 = new float[9];
private static final Paint sBackgroundPaint = new Paint();
/**
@@ -116,24 +109,27 @@ public class SnapshotDrawerUtils {
private final CharSequence mTitle;
private SystemBarBackgroundPainter mSystemBarBackgroundPainter;
- private final Rect mTaskBounds;
private final Rect mFrame = new Rect();
private final Rect mSystemBarInsets = new Rect();
+ private final int mSnapshotW;
+ private final int mSnapshotH;
private boolean mSizeMismatch;
public SnapshotSurface(SurfaceControl rootSurface, TaskSnapshot snapshot,
- CharSequence title,
- Rect taskBounds) {
+ CharSequence title) {
mRootSurface = rootSurface;
mSnapshot = snapshot;
mTitle = title;
- mTaskBounds = taskBounds;
+ final HardwareBuffer hwBuffer = snapshot.getHardwareBuffer();
+ mSnapshotW = hwBuffer.getWidth();
+ mSnapshotH = hwBuffer.getHeight();
}
/**
* Initiate system bar painter to draw the system bar background.
*/
- void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
+ @VisibleForTesting
+ public void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
int appearance, ActivityManager.TaskDescription taskDescription,
@WindowInsets.Type.InsetsType int requestedVisibleTypes) {
mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
@@ -143,14 +139,13 @@ public class SnapshotDrawerUtils {
}
/**
- * Set frame size.
+ * Set frame size that the snapshot should fill. It is the bounds of a task or activity.
*/
- void setFrames(Rect frame, Rect systemBarInsets) {
+ @VisibleForTesting
+ public void setFrames(Rect frame, Rect systemBarInsets) {
mFrame.set(frame);
mSystemBarInsets.set(systemBarInsets);
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- mSizeMismatch = (mFrame.width() != snapshot.getWidth()
- || mFrame.height() != snapshot.getHeight());
+ mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH);
mSystemBarBackgroundPainter.setInsets(systemBarInsets);
}
@@ -186,7 +181,7 @@ public class SnapshotDrawerUtils {
// We consider nearly matched dimensions as there can be rounding errors and the user
// won't notice very minute differences from scaling one dimension more than the other
- boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshot);
+ boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshotW, mSnapshotH);
// Keep a reference to it such that it doesn't get destroyed when finalized.
SurfaceControl childSurfaceControl = new SurfaceControl.Builder(session)
@@ -198,12 +193,14 @@ public class SnapshotDrawerUtils {
.build();
final Rect frame;
+ final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
+ float offsetX = letterboxInsets.left;
+ float offsetY = letterboxInsets.top;
// We can just show the surface here as it will still be hidden as the parent is
// still hidden.
mTransaction.show(childSurfaceControl);
if (aspectRatioMismatch) {
Rect crop = null;
- final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
if (letterboxInsets.left != 0 || letterboxInsets.top != 0
|| letterboxInsets.right != 0 || letterboxInsets.bottom != 0) {
// Clip off letterbox.
@@ -214,23 +211,27 @@ public class SnapshotDrawerUtils {
// if letterbox doesn't match window frame, try crop by content insets
if (aspectRatioMismatch) {
// Clip off ugly navigation bar.
- crop = calculateSnapshotCrop(mSnapshot.getContentInsets());
+ final Rect contentInsets = mSnapshot.getContentInsets();
+ crop = calculateSnapshotCrop(contentInsets);
+ offsetX = contentInsets.left;
+ offsetY = contentInsets.top;
}
frame = calculateSnapshotFrame(crop);
- mTransaction.setWindowCrop(childSurfaceControl, crop);
- mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
- sTmpSnapshotSize.set(crop);
- sTmpDstFrame.set(frame);
+ mTransaction.setCrop(childSurfaceControl, crop);
} else {
frame = null;
- sTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
- sTmpDstFrame.set(mFrame);
- sTmpDstFrame.offsetTo(0, 0);
}
- // Scale the mismatch dimensions to fill the task bounds
- sSnapshotMatrix.setRectToRect(sTmpSnapshotSize, sTmpDstFrame, Matrix.ScaleToFit.FILL);
- mTransaction.setMatrix(childSurfaceControl, sSnapshotMatrix, sTmpFloat9);
+ // Align the snapshot with content area.
+ if (offsetX != 0f || offsetY != 0f) {
+ mTransaction.setPosition(childSurfaceControl,
+ -offsetX * mFrame.width() / mSnapshot.getTaskSize().x,
+ -offsetY * mFrame.height() / mSnapshot.getTaskSize().y);
+ }
+ // Scale the mismatch dimensions to fill the target frame.
+ final float scaleX = (float) mFrame.width() / mSnapshotW;
+ final float scaleY = (float) mFrame.height() / mSnapshotH;
+ mTransaction.setScale(childSurfaceControl, scaleX, scaleY);
mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
@@ -261,17 +262,17 @@ public class SnapshotDrawerUtils {
* @param insets Content insets or Letterbox insets
* @return crop rect in snapshot coordinate space.
*/
- Rect calculateSnapshotCrop(@NonNull Rect insets) {
+ @VisibleForTesting
+ public Rect calculateSnapshotCrop(@NonNull Rect insets) {
final Rect rect = new Rect();
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
+ rect.set(0, 0, mSnapshotW, mSnapshotH);
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Let's remove all system decorations except the status bar, but only if the task is at
// the very top of the screen.
- final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
+ final boolean isTop = mFrame.top == 0;
rect.inset((int) (insets.left * scaleX),
isTop ? 0 : (int) (insets.top * scaleY),
(int) (insets.right * scaleX),
@@ -284,10 +285,10 @@ public class SnapshotDrawerUtils {
*
* @param crop rect that is in snapshot coordinate space.
*/
- Rect calculateSnapshotFrame(Rect crop) {
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ @VisibleForTesting
+ public Rect calculateSnapshotFrame(Rect crop) {
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Rescale the frame from snapshot to window coordinate space
final Rect frame = new Rect(0, 0,
@@ -303,7 +304,8 @@ public class SnapshotDrawerUtils {
/**
* Draw status bar and navigation bar background.
*/
- void drawBackgroundAndBars(Canvas c, Rect frame) {
+ @VisibleForTesting
+ public void drawBackgroundAndBars(Canvas c, Rect frame) {
final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
final boolean fillHorizontally = c.getWidth() > frame.right;
final boolean fillVertically = c.getHeight() > frame.bottom;
@@ -320,33 +322,27 @@ public class SnapshotDrawerUtils {
/**
* Ask system bar background painter to draw status bar background.
- *
*/
- void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ @VisibleForTesting
+ public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
}
/**
* Ask system bar background painter to draw navigation bar background.
- *
*/
- void drawNavigationBarBackground(Canvas c) {
+ @VisibleForTesting
+ public void drawNavigationBarBackground(Canvas c) {
mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
}
}
- /**
- * @return true if the aspect ratio match between a frame and a snapshot buffer.
- */
- public static boolean isAspectRatioMatch(Rect frame, TaskSnapshot snapshot) {
+ private static boolean isAspectRatioMatch(Rect frame, int w, int h) {
if (frame.isEmpty()) {
return false;
}
- final HardwareBuffer buffer = snapshot.getHardwareBuffer();
- return Math.abs(
- ((float) buffer.getWidth() / buffer.getHeight())
- - ((float) frame.width() / frame.height())) <= 0.01f;
+ return Math.abs(((float) w / h) - ((float) frame.width() / frame.height())) <= 0.01f;
}
private static boolean isAspectRatioMatch(Rect frame1, Rect frame2) {
@@ -378,14 +374,14 @@ public class SnapshotDrawerUtils {
*/
public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
SurfaceControl rootSurface, TaskSnapshot snapshot,
- Rect configBounds, Rect windowBounds, InsetsState topWindowInsetsState,
+ Rect windowBounds, InsetsState topWindowInsetsState,
boolean releaseAfterDraw) {
if (windowBounds.isEmpty()) {
Log.e(TAG, "Unable to draw snapshot on an empty windowBounds");
return;
}
final SnapshotSurface drawSurface = new SnapshotSurface(
- rootSurface, snapshot, lp.getTitle(), configBounds);
+ rootSurface, snapshot, lp.getTitle());
final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 260d9a82472f..72df343a2dbe 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -79,11 +80,17 @@ public final class StartingWindowInfo implements Parcelable {
/**
* The {@link TaskInfo} from this task.
- * @hide
+ * <p>Note that the configuration of this taskInfo could be from the top activity of its task.
+ * Because only activity contains persisted configuration (e.g. night mode, language). Besides,
+ * it can also be used for activity level snapshot.
*/
@NonNull
public ActivityManager.RunningTaskInfo taskInfo;
+ /** The bounds of the target task. */
+ @NonNull
+ public final Rect taskBounds = new Rect();
+
/**
* The {@link ActivityInfo} of the target activity which to create the starting window.
* It can be null if the info is the same as the top in task info.
@@ -253,6 +260,7 @@ public final class StartingWindowInfo implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(taskInfo, flags);
+ taskBounds.writeToParcel(dest, flags);
dest.writeTypedObject(targetActivityInfo, flags);
dest.writeInt(startingWindowTypeParameter);
dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
@@ -269,6 +277,7 @@ public final class StartingWindowInfo implements Parcelable {
void readFromParcel(@NonNull Parcel source) {
taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ taskBounds.readFromParcel(source);
targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
startingWindowTypeParameter = source.readInt();
topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
diff --git a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
index 036154634ae7..6c8dcd39e223 100644
--- a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
+++ b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
@@ -77,7 +77,7 @@ public class SnapshotDrawerUtilsTest {
Color.RED, Color.BLUE);
mSnapshotSurface = new SnapshotDrawerUtils.SnapshotSurface(
- new SurfaceControl(), snapshot, "Test", taskBounds);
+ new SurfaceControl(), snapshot, "Test");
mSnapshotSurface.initiateSystemBarPainter(windowFlags, 0, 0,
taskDescription, WindowInsets.Type.defaultVisible());
}
@@ -167,14 +167,16 @@ public class SnapshotDrawerUtilsTest {
@Test
public void testCalculateSnapshotCrop_taskNotOnTop() {
final Rect contentInsets = new Rect(0, 10, 0, 10);
- setupSurface(100, 100, contentInsets, 0, new Rect(0, 50, 100, 150));
+ final Rect bounds = new Rect(0, 50, 100, 150);
+ setupSurface(100, 100, contentInsets, 0, bounds);
+ mSnapshotSurface.setFrames(bounds, contentInsets);
assertEquals(new Rect(0, 10, 100, 90),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
}
@Test
public void testCalculateSnapshotCrop_navBarLeft() {
- final Rect contentInsets = new Rect(0, 10, 0, 0);
+ final Rect contentInsets = new Rect(10, 0, 0, 0);
setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
assertEquals(new Rect(10, 0, 100, 100),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index ceac40d9ba95..5fec38dc23d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -27,7 +27,6 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -100,8 +99,6 @@ public class TaskSnapshotWindow {
return null;
}
- final Point taskSize = snapshot.getTaskSize();
- final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final int orientation = snapshot.getOrientation();
final int displayId = runningTaskInfo.displayId;
@@ -150,7 +147,7 @@ public class TaskSnapshotWindow {
}
SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
- taskBounds, tmpFrames.frame, topWindowInsetsState, true /* releaseAfterDraw */);
+ info.taskBounds, topWindowInsetsState, true /* releaseAfterDraw */);
snapshotSurface.mHasDrawn = true;
snapshotSurface.reportDrawn();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
index fed2f34b5e0c..5c814dcc9b16 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
@@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.Context;
-import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.view.Display;
@@ -77,15 +76,13 @@ class WindowlessSnapshotWindowCreator {
runningTaskInfo.configuration, rootSurface);
final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
mContext, display, wlw, "WindowlessSnapshotWindowCreator");
- final Point taskSize = snapshot.getTaskSize();
- final Rect snapshotBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
final FrameLayout rootLayout = new FrameLayout(
mSplashscreenContentDrawer.createViewContextWrapper(mContext));
mViewHost.setView(rootLayout, lp);
SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
- snapshotBounds, windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
+ windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
final ActivityManager.TaskDescription taskDescription =
SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f23a440eb0ed..89b8e15b9461 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3689,6 +3689,9 @@ class Task extends TaskFragment {
info.requestedVisibleTypes = topMainWin.getRequestedVisibleTypes();
}
}
+ final Rect rotatedBounds = activity.getFixedRotationTransformDisplayBounds();
+ info.taskBounds.set(rotatedBounds != null ? rotatedBounds
+ : info.taskInfo.configuration.windowConfiguration.getBounds());
// If the developer has persist a different configuration, we need to override it to the
// starting window because persisted configuration does not effect to Task.
info.taskInfo.configuration.setTo(activity.getConfiguration());