summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java42
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java9
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java2
-rw-r--r--libs/hwui/jni/android_graphics_Canvas.cpp10
9 files changed, 117 insertions, 36 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index c2ad1a98d167..5b7d141591ea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -69,6 +69,7 @@ import com.android.wm.shell.common.InteractionJankMonitorUtils;
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import java.io.PrintWriter;
+import java.util.function.Consumer;
/**
* Records and handles layout of splits. Helps to calculate proper bounds when configuration or
@@ -599,7 +600,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
/** Swich both surface position with animation. */
public void splitSwitching(SurfaceControl.Transaction t, SurfaceControl leash1,
- SurfaceControl leash2, Runnable finishCallback) {
+ SurfaceControl leash2, Consumer<Rect> finishCallback) {
final boolean isLandscape = isLandscape();
final Rect insets = getDisplayInsets(mContext);
insets.set(isLandscape ? insets.left : 0, isLandscape ? 0 : insets.top,
@@ -617,18 +618,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
distBounds1.offset(-mRootBounds.left, -mRootBounds.top);
distBounds2.offset(-mRootBounds.left, -mRootBounds.top);
distDividerBounds.offset(-mRootBounds.left, -mRootBounds.top);
- // DO NOT move to insets area for smooth animation.
- distBounds1.set(distBounds1.left, distBounds1.top,
- distBounds1.right - insets.right, distBounds1.bottom - insets.bottom);
- distBounds2.set(distBounds2.left + insets.left, distBounds2.top + insets.top,
- distBounds2.right, distBounds2.bottom);
ValueAnimator animator1 = moveSurface(t, leash1, getRefBounds1(), distBounds1,
- false /* alignStart */);
+ -insets.left, -insets.top);
ValueAnimator animator2 = moveSurface(t, leash2, getRefBounds2(), distBounds2,
- true /* alignStart */);
+ insets.left, insets.top);
ValueAnimator animator3 = moveSurface(t, getDividerLeash(), getRefDividerBounds(),
- distDividerBounds, true /* alignStart */);
+ distDividerBounds, 0 /* offsetX */, 0 /* offsetY */);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2, animator3);
@@ -638,14 +634,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public void onAnimationEnd(Animator animation) {
mDividePosition = dividerPos;
updateBounds(mDividePosition);
- finishCallback.run();
+ finishCallback.accept(insets);
}
});
set.start();
}
private ValueAnimator moveSurface(SurfaceControl.Transaction t, SurfaceControl leash,
- Rect start, Rect end, boolean alignStart) {
+ Rect start, Rect end, float offsetX, float offsetY) {
Rect tempStart = new Rect(start);
Rect tempEnd = new Rect(end);
final float diffX = tempEnd.left - tempStart.left;
@@ -661,15 +657,15 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
final float distY = tempStart.top + scale * diffY;
final int width = (int) (tempStart.width() + scale * diffWidth);
final int height = (int) (tempStart.height() + scale * diffHeight);
- if (alignStart) {
+ if (offsetX == 0 && offsetY == 0) {
t.setPosition(leash, distX, distY);
t.setWindowCrop(leash, width, height);
} else {
- final int offsetX = width - tempStart.width();
- final int offsetY = height - tempStart.height();
- t.setPosition(leash, distX + offsetX, distY + offsetY);
+ final int diffOffsetX = (int) (scale * offsetX);
+ final int diffOffsetY = (int) (scale * offsetY);
+ t.setPosition(leash, distX + diffOffsetX, distY + diffOffsetY);
mTempRect.set(0, 0, width, height);
- mTempRect.offsetTo(-offsetX, -offsetY);
+ mTempRect.offsetTo(-diffOffsetX, -diffOffsetY);
t.setCrop(leash, mTempRect);
}
t.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 2b36b4c0307d..85bad174194c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -335,6 +335,7 @@ public class PipTransition extends PipTransitionController {
final ActivityManager.RunningTaskInfo taskInfo = mPipOrganizer.getTaskInfo();
if (taskInfo != null) {
startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
+ mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
new Rect(mExitDestinationBounds), Surface.ROTATION_0);
}
mExitDestinationBounds.setEmpty();
@@ -475,6 +476,20 @@ public class PipTransition extends PipTransitionController {
taskInfo);
return;
}
+
+ // When exiting PiP, the PiP leash may be an Activity of a multi-windowing Task, for which
+ // case it may not be in the screen coordinate.
+ // Reparent the pip leash to the root with max layer so that we can animate it outside of
+ // parent crop, and make sure it is not covered by other windows.
+ final SurfaceControl pipLeash = pipChange.getLeash();
+ startTransaction.reparent(pipLeash, info.getRootLeash());
+ startTransaction.setLayer(pipLeash, Integer.MAX_VALUE);
+ // Note: because of this, the bounds to animate should be translated to the root coordinate.
+ final Point offset = info.getRootOffset();
+ final Rect currentBounds = mPipBoundsState.getBounds();
+ currentBounds.offset(-offset.x, -offset.y);
+ startTransaction.setPosition(pipLeash, currentBounds.left, currentBounds.top);
+
mFinishCallback = (wct, wctCB) -> {
mPipOrganizer.onExitPipFinished(taskInfo);
finishCallback.onTransitionFinished(wct, wctCB);
@@ -496,18 +511,17 @@ public class PipTransition extends PipTransitionController {
if (displayRotationChange != null) {
// Exiting PIP to fullscreen with orientation change.
startExpandAndRotationAnimation(info, startTransaction, finishTransaction,
- displayRotationChange, taskInfo, pipChange);
+ displayRotationChange, taskInfo, pipChange, offset);
return;
}
}
// Set the initial frame as scaling the end to the start.
final Rect destinationBounds = new Rect(pipChange.getEndAbsBounds());
- final Point offset = pipChange.getEndRelOffset();
destinationBounds.offset(-offset.x, -offset.y);
- startTransaction.setWindowCrop(pipChange.getLeash(), destinationBounds);
- mSurfaceTransactionHelper.scale(startTransaction, pipChange.getLeash(),
- destinationBounds, mPipBoundsState.getBounds());
+ startTransaction.setWindowCrop(pipLeash, destinationBounds);
+ mSurfaceTransactionHelper.scale(startTransaction, pipLeash, destinationBounds,
+ currentBounds);
startTransaction.apply();
// Check if it is fixed rotation.
@@ -532,19 +546,21 @@ public class PipTransition extends PipTransitionController {
y = destinationBounds.bottom;
}
mSurfaceTransactionHelper.rotateAndScaleWithCrop(finishTransaction,
- pipChange.getLeash(), endBounds, endBounds, new Rect(), degree, x, y,
+ pipLeash, endBounds, endBounds, new Rect(), degree, x, y,
true /* isExpanding */, rotationDelta == ROTATION_270 /* clockwise */);
} else {
rotationDelta = Surface.ROTATION_0;
}
- startExpandAnimation(taskInfo, pipChange.getLeash(), destinationBounds, rotationDelta);
+ startExpandAnimation(taskInfo, pipLeash, currentBounds, currentBounds, destinationBounds,
+ rotationDelta);
}
private void startExpandAndRotationAnimation(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull TransitionInfo.Change displayRotationChange,
- @NonNull TaskInfo taskInfo, @NonNull TransitionInfo.Change pipChange) {
+ @NonNull TaskInfo taskInfo, @NonNull TransitionInfo.Change pipChange,
+ @NonNull Point offset) {
final int rotateDelta = deltaRotation(displayRotationChange.getStartRotation(),
displayRotationChange.getEndRotation());
@@ -556,7 +572,6 @@ public class PipTransition extends PipTransitionController {
final Rect startBounds = new Rect(pipChange.getStartAbsBounds());
rotateBounds(startBounds, displayRotationChange.getStartAbsBounds(), rotateDelta);
final Rect endBounds = new Rect(pipChange.getEndAbsBounds());
- final Point offset = pipChange.getEndRelOffset();
startBounds.offset(-offset.x, -offset.y);
endBounds.offset(-offset.x, -offset.y);
@@ -592,11 +607,12 @@ public class PipTransition extends PipTransitionController {
}
private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash,
- final Rect destinationBounds, final int rotationDelta) {
+ final Rect baseBounds, final Rect startBounds, final Rect endBounds,
+ final int rotationDelta) {
final PipAnimationController.PipTransitionAnimator animator =
- mPipAnimationController.getAnimator(taskInfo, leash, mPipBoundsState.getBounds(),
- mPipBoundsState.getBounds(), destinationBounds, null,
- TRANSITION_DIRECTION_LEAVE_PIP, 0 /* startingAngle */, rotationDelta);
+ mPipAnimationController.getAnimator(taskInfo, leash, baseBounds, startBounds,
+ endBounds, null /* sourceHintRect */, TRANSITION_DIRECTION_LEAVE_PIP,
+ 0 /* startingAngle */, rotationDelta);
animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(mEnterExitAnimationDuration)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 943419bb8ea2..15a11334307b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -115,6 +115,7 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
@@ -846,15 +847,44 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
void setSideStagePositionAnimated(@SplitPosition int sideStagePosition) {
if (mSideStagePosition == sideStagePosition) return;
SurfaceControl.Transaction t = mTransactionPool.acquire();
+ mTempRect1.setEmpty();
final StageTaskListener topLeftStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
+ final SurfaceControl topLeftScreenshot = ScreenshotUtils.takeScreenshot(t,
+ topLeftStage.mRootLeash, mTempRect1, Integer.MAX_VALUE - 1);
final StageTaskListener bottomRightStage =
mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
+ final SurfaceControl bottomRightScreenshot = ScreenshotUtils.takeScreenshot(t,
+ bottomRightStage.mRootLeash, mTempRect1, Integer.MAX_VALUE - 1);
mSplitLayout.splitSwitching(t, topLeftStage.mRootLeash, bottomRightStage.mRootLeash,
- () -> {
- setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition),
- null /* wct */);
- mTransactionPool.release(t);
+ insets -> {
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), wct);
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(st -> {
+ updateSurfaceBounds(mSplitLayout, st, false /* applyResizingOffset */);
+ st.setPosition(topLeftScreenshot, -insets.left, -insets.top);
+ st.setPosition(bottomRightScreenshot, insets.left, insets.top);
+
+ final ValueAnimator va = ValueAnimator.ofFloat(1, 0);
+ va.addUpdateListener(valueAnimator-> {
+ final float progress = (float) valueAnimator.getAnimatedValue();
+ t.setAlpha(topLeftScreenshot, progress);
+ t.setAlpha(bottomRightScreenshot, progress);
+ t.apply();
+ });
+ va.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(
+ @androidx.annotation.NonNull Animator animation) {
+ t.remove(topLeftScreenshot);
+ t.remove(bottomRightScreenshot);
+ t.apply();
+ mTransactionPool.release(t);
+ }
+ });
+ va.start();
+ });
});
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index af79386caf9c..928e71f8d3a6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -46,6 +46,7 @@ import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL;
import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS;
import static android.window.TransitionInfo.FLAG_FILLS_TASK;
import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
+import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -319,6 +320,17 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final int wallpaperTransit = getWallpaperTransitType(info);
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
+ if (change.hasAllFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY
+ | FLAG_IS_BEHIND_STARTING_WINDOW)) {
+ // Don't animate embedded activity if it is covered by the starting window.
+ // Non-embedded case still needs animation because the container can still animate
+ // the starting window together, e.g. CLOSE or CHANGE type.
+ continue;
+ }
+ if (change.hasFlags(TransitionInfo.FLAGS_IS_NON_APP_WINDOW)) {
+ // Wallpaper, IME, and system windows don't need any default animations.
+ continue;
+ }
final boolean isTask = change.getTaskInfo() != null;
boolean isSeamlessDisplayChange = false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 63d31cde4715..89205a6dfb01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -341,6 +341,15 @@ public class Transitions implements RemoteCallable<Transitions> {
final SurfaceControl leash = change.getLeash();
final int mode = info.getChanges().get(i).getMode();
+ if (mode == TRANSIT_TO_FRONT
+ && ((change.getStartAbsBounds().height() != change.getEndAbsBounds().height()
+ || change.getStartAbsBounds().width() != change.getEndAbsBounds().width()))) {
+ // When the window is moved to front with a different size, make sure the crop is
+ // updated to prevent it from using the old crop.
+ t.setWindowCrop(leash, change.getEndAbsBounds().width(),
+ change.getEndAbsBounds().height());
+ }
+
// Don't move anything that isn't independent within its parents
if (!TransitionInfo.isIndependent(change, info)) {
if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT || mode == TRANSIT_CHANGE) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index 73159c981b82..ad7a531b589d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -145,15 +145,19 @@ class SwitchAppByDoubleTapDivider(testSpec: FlickerTestParameter) : SplitScreenB
// robust enough to get the correct end state.
}
+ @Presubmit
@Test
fun splitScreenDividerKeepVisible() = testSpec.layerKeepVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
+ @Presubmit
@Test
fun primaryAppLayerIsVisibleAtEnd() = testSpec.layerIsVisibleAtEnd(primaryApp)
+ @Presubmit
@Test
fun secondaryAppLayerIsVisibleAtEnd() = testSpec.layerIsVisibleAtEnd(secondaryApp)
+ @Presubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
primaryApp,
@@ -161,6 +165,7 @@ class SwitchAppByDoubleTapDivider(testSpec: FlickerTestParameter) : SplitScreenB
portraitPosTop = true
)
+ @Presubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
secondaryApp,
@@ -168,9 +173,11 @@ class SwitchAppByDoubleTapDivider(testSpec: FlickerTestParameter) : SplitScreenB
portraitPosTop = false
)
+ @Presubmit
@Test
fun primaryAppWindowIsVisibleAtEnd() = testSpec.appWindowIsVisibleAtEnd(primaryApp)
+ @Presubmit
@Test
fun secondaryAppWindowIsVisibleAtEnd() = testSpec.appWindowIsVisibleAtEnd(secondaryApp)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
index 55883ab2ef70..d01f3d310fc3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java
@@ -39,6 +39,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -110,6 +111,7 @@ public class SplitScreenControllerTests extends ShellTestCase {
}
@Test
+ @UiThreadTest
public void instantiateController_registerDumpCallback() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
@@ -118,6 +120,7 @@ public class SplitScreenControllerTests extends ShellTestCase {
}
@Test
+ @UiThreadTest
public void instantiateController_registerCommandCallback() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
@@ -126,6 +129,7 @@ public class SplitScreenControllerTests extends ShellTestCase {
}
@Test
+ @UiThreadTest
public void testControllerRegistersKeyguardChangeListener() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
@@ -134,6 +138,7 @@ public class SplitScreenControllerTests extends ShellTestCase {
}
@Test
+ @UiThreadTest
public void instantiateController_addExternalInterface() {
doReturn(mMainExecutor).when(mTaskOrganizer).getExecutor();
when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(new DisplayLayout());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 835087007b30..3569860b6128 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -50,6 +50,7 @@ import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -113,6 +114,7 @@ public class StageCoordinatorTests extends ShellTestCase {
private StageCoordinator mStageCoordinator;
@Before
+ @UiThreadTest
public void setup() {
MockitoAnnotations.initMocks(this);
mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 0513447ed05e..35258a3e0774 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -20,6 +20,7 @@
#include <android/api-level.h>
#else
#define __ANDROID_API_P__ 28
+#define __ANDROID_API_U__ 34
#endif
#include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
@@ -30,8 +31,9 @@
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedStringChars.h>
-#include "FontUtils.h"
#include "Bitmap.h"
+#include "FontUtils.h"
+#include "SkAndroidFrameworkUtils.h"
#include "SkBitmap.h"
#include "SkBlendMode.h"
#include "SkClipOp.h"
@@ -42,10 +44,10 @@
#include "SkMatrix.h"
#include "SkPath.h"
#include "SkPoint.h"
+#include "SkRRect.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include "SkRegion.h"
-#include "SkRRect.h"
#include "SkScalar.h"
#include "SkVertices.h"
@@ -710,6 +712,9 @@ static void freeTextLayoutCaches(JNIEnv* env, jobject) {
static void setCompatibilityVersion(JNIEnv* env, jobject, jint apiLevel) {
Canvas::setCompatibilityVersion(apiLevel);
+ if (apiLevel < __ANDROID_API_U__) {
+ SkAndroidFrameworkUtils::UseLegacyLocalMatrixConcatenation();
+ }
}
static void punchHole(JNIEnv* env, jobject, jlong canvasPtr, jfloat left, jfloat top, jfloat right,
@@ -800,7 +805,6 @@ int register_android_graphics_Canvas(JNIEnv* env) {
ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
ret |= RegisterMethodsOrDie(env, "android/graphics/BaseRecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
return ret;
-
}
}; // namespace android