summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/res/values-nl/strings.xml6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java77
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java51
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java20
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java58
-rw-r--r--libs/hwui/DisplayList.h11
-rw-r--r--libs/hwui/Properties.cpp4
-rw-r--r--libs/hwui/Properties.h7
-rw-r--r--libs/hwui/RenderNode.cpp4
-rw-r--r--libs/hwui/WebViewFunctorManager.cpp38
-rw-r--r--libs/hwui/WebViewFunctorManager.h7
-rw-r--r--libs/hwui/canvas/CanvasOpBuffer.cpp4
-rw-r--r--libs/hwui/canvas/CanvasOpBuffer.h1
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp7
-rw-r--r--libs/hwui/pipeline/skia/FunctorDrawable.h4
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.cpp6
-rw-r--r--libs/hwui/pipeline/skia/SkiaDisplayList.h7
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp4
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp1
-rw-r--r--libs/hwui/renderthread/CanvasContext.h4
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp4
-rw-r--r--libs/hwui/renderthread/RenderThread.h4
30 files changed, 364 insertions, 76 deletions
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 69fc25a378cf..06aaad7d65ca 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -45,10 +45,10 @@
<string name="accessibility_action_divider_top_50" msgid="8649582798829048946">"Bovenste scherm 50%"</string>
<string name="accessibility_action_divider_top_30" msgid="3572788224908570257">"Bovenste scherm 30%"</string>
<string name="accessibility_action_divider_bottom_full" msgid="2831868345092314060">"Onderste scherm op volledig scherm"</string>
- <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bediening met één hand gebruiken"</string>
+ <string name="one_handed_tutorial_title" msgid="4583241688067426350">"Bediening met 1 hand gebruiken"</string>
<string name="one_handed_tutorial_description" msgid="3486582858591353067">"Als je wilt afsluiten, swipe je omhoog vanaf de onderkant van het scherm of tik je ergens boven de app"</string>
- <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bediening met één hand starten"</string>
- <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Bediening met één hand afsluiten"</string>
+ <string name="accessibility_action_start_one_handed" msgid="5070337354072861426">"Bediening met 1 hand starten"</string>
+ <string name="accessibility_action_stop_one_handed" msgid="1369940261782179442">"Bediening met 1 hand afsluiten"</string>
<string name="bubbles_settings_button_description" msgid="1301286017420516912">"Instellingen voor <xliff:g id="APP_NAME">%1$s</xliff:g>-bubbels"</string>
<string name="bubble_overflow_button_content_description" msgid="8160974472718594382">"Overloop"</string>
<string name="bubble_accessibility_action_add_back" msgid="1830101076853540953">"Weer toevoegen aan stack"</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index cb27ad9f58f5..f565724813eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -159,6 +159,14 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
+ private void dispatchImeControlTargetChanged(int displayId, boolean controlling) {
+ synchronized (mPositionProcessors) {
+ for (ImePositionProcessor pp : mPositionProcessors) {
+ pp.onImeControlTargetChanged(displayId, controlling);
+ }
+ }
+ }
+
private void dispatchVisibilityChanged(int displayId, boolean isShowing) {
synchronized (mPositionProcessors) {
for (ImePositionProcessor pp : mPositionProcessors) {
@@ -237,42 +245,52 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
protected void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
insetsChanged(insetsState);
+ InsetsSourceControl imeSourceControl = null;
if (activeControls != null) {
for (InsetsSourceControl activeControl : activeControls) {
if (activeControl == null) {
continue;
}
if (activeControl.getType() == InsetsState.ITYPE_IME) {
- final Point lastSurfacePosition = mImeSourceControl != null
- ? mImeSourceControl.getSurfacePosition() : null;
- final boolean positionChanged =
- !activeControl.getSurfacePosition().equals(lastSurfacePosition);
- final boolean leashChanged =
- !haveSameLeash(mImeSourceControl, activeControl);
- final InsetsSourceControl lastImeControl = mImeSourceControl;
- mImeSourceControl = activeControl;
- if (mAnimation != null) {
- if (positionChanged) {
- startAnimation(mImeShowing, true /* forceRestart */);
- }
- } else {
- if (leashChanged) {
- applyVisibilityToLeash();
- }
- if (!mImeShowing) {
- removeImeSurface();
- }
- }
- if (lastImeControl != null) {
- lastImeControl.release(SurfaceControl::release);
- }
+ imeSourceControl = activeControl;
+ }
+ }
+ }
+
+ final boolean hadImeSourceControl = mImeSourceControl != null;
+ final boolean hasImeSourceControl = imeSourceControl != null;
+ if (hadImeSourceControl != hasImeSourceControl) {
+ dispatchImeControlTargetChanged(mDisplayId, hasImeSourceControl);
+ }
+
+ if (hasImeSourceControl) {
+ final Point lastSurfacePosition = mImeSourceControl != null
+ ? mImeSourceControl.getSurfacePosition() : null;
+ final boolean positionChanged =
+ !imeSourceControl.getSurfacePosition().equals(lastSurfacePosition);
+ final boolean leashChanged =
+ !haveSameLeash(mImeSourceControl, imeSourceControl);
+ if (mAnimation != null) {
+ if (positionChanged) {
+ startAnimation(mImeShowing, true /* forceRestart */);
+ }
+ } else {
+ if (leashChanged) {
+ applyVisibilityToLeash(imeSourceControl);
}
+ if (!mImeShowing) {
+ removeImeSurface();
+ }
+ }
+ if (mImeSourceControl != null) {
+ mImeSourceControl.release(SurfaceControl::release);
}
+ mImeSourceControl = imeSourceControl;
}
}
- private void applyVisibilityToLeash() {
- SurfaceControl leash = mImeSourceControl.getLeash();
+ private void applyVisibilityToLeash(InsetsSourceControl imeSourceControl) {
+ SurfaceControl leash = imeSourceControl.getLeash();
if (leash != null) {
SurfaceControl.Transaction t = mTransactionPool.acquire();
if (mImeShowing) {
@@ -584,6 +602,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
/**
+ * Called when the IME control target changed. So that the processor can restore its
+ * adjusted layout when the IME insets is not controlling by the current controller anymore.
+ *
+ * @param controlling indicates whether the current controller is controlling IME insets.
+ */
+ default void onImeControlTargetChanged(int displayId, boolean controlling) {
+ }
+
+ /**
* Called when the IME visibility changed.
*
* @param isShowing {@code true} if the IME is shown.
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 e42f511eb391..5b158d2063ba 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
@@ -366,6 +366,7 @@ public final class SplitLayout {
private final int mDisplayId;
+ private boolean mImeShown;
private int mYOffsetForIme;
private float mDimValue1;
private float mDimValue2;
@@ -392,6 +393,7 @@ public final class SplitLayout {
if (!mInitialized || imeTargetPosition == SPLIT_POSITION_UNDEFINED) return 0;
mStartImeTop = showing ? hiddenTop : shownTop;
mEndImeTop = showing ? shownTop : hiddenTop;
+ mImeShown = showing;
// Update target dim values
mLastDim1 = mDimValue1;
@@ -414,7 +416,7 @@ public final class SplitLayout {
mSplitWindowManager.setInteractive(
!showing || imeTargetPosition == SPLIT_POSITION_UNDEFINED);
- return 0;
+ return needOffset ? IME_ANIMATION_NO_ALPHA : 0;
}
@Override
@@ -432,6 +434,17 @@ public final class SplitLayout {
mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
}
+ @Override
+ public void onImeControlTargetChanged(int displayId, boolean controlling) {
+ if (displayId != mDisplayId) return;
+ // Restore the split layout when wm-shell is not controlling IME insets anymore.
+ if (!controlling && mImeShown) {
+ reset();
+ mSplitWindowManager.setInteractive(true);
+ mSplitLayoutHandler.onBoundsChanging(SplitLayout.this);
+ }
+ }
+
private int getTargetYOffset() {
final int desireOffset = Math.abs(mEndImeTop - mStartImeTop);
// Make sure to keep at least 30% visible for the top split.
@@ -461,8 +474,10 @@ public final class SplitLayout {
}
private void reset() {
- mYOffsetForIme = 0;
- mDimValue1 = mDimValue2 = 0.0f;
+ mImeShown = false;
+ mYOffsetForIme = mLastYOffset = mTargetYOffset = 0;
+ mDimValue1 = mLastDim1 = mTargetDim1 = 0.0f;
+ mDimValue2 = mLastDim2 = mTargetDim2 = 0.0f;
}
/* Adjust bounds with IME offset. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
index 23171bb9575c..aced072c8c71 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
@@ -91,7 +91,6 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
private boolean mPaused = true;
private boolean mPausedTargetAdjusted = false;
- private boolean mAdjustedWhileHidden = false;
DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool,
ShellExecutor mainExecutor, TaskOrganizer taskOrganizer) {
@@ -123,7 +122,6 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
void reset() {
mPaused = true;
mPausedTargetAdjusted = false;
- mAdjustedWhileHidden = false;
mAnimation = null;
mAdjusted = mTargetAdjusted = false;
mImeWasShown = mTargetShown = false;
@@ -140,6 +138,19 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
? ADJUSTED_NONFOCUS_DIM : 0.f;
}
+
+ @Override
+ public void onImeControlTargetChanged(int displayId, boolean controlling) {
+ // Restore the split layout when wm-shell is not controlling IME insets anymore.
+ if (!controlling && mTargetShown) {
+ mPaused = false;
+ mTargetAdjusted = mTargetShown = false;
+ mTargetPrimaryDim = mTargetSecondaryDim = 0.f;
+ updateImeAdjustState(true /* force */);
+ startAsyncAnimation();
+ }
+ }
+
@Override
@ImeAnimationFlags
public int onImeStartPositioning(int displayId, int hiddenTop, int shownTop,
@@ -151,8 +162,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mShownTop = shownTop;
mTargetShown = imeShouldShow;
mSecondaryHasFocus = getSecondaryHasFocus(displayId);
- final boolean splitIsVisible = !getView().isHidden();
- final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
+ final boolean targetAdjusted = imeShouldShow && mSecondaryHasFocus
&& !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
&& !mSplits.mSplitScreenController.isMinimized();
if (mLastAdjustTop < 0) {
@@ -176,7 +186,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
}
mTargetAdjusted = targetAdjusted;
updateDimTargets();
- if (DEBUG) Slog.d(TAG, " ime starting. vis:" + splitIsVisible + " " + dumpState());
+ if (DEBUG) Slog.d(TAG, " ime starting. " + dumpState());
if (mAnimation != null || (mImeWasShown && imeShouldShow
&& mTargetAdjusted != mAdjusted)) {
// We need to animate adjustment independently of the IME position, so
@@ -184,13 +194,8 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
// different split's editor has gained focus while the IME is still visible.
startAsyncAnimation();
}
- if (splitIsVisible) {
- // If split is hidden, we don't want to trigger any relayouts that would cause the
- // divider to show again.
- updateImeAdjustState();
- } else {
- mAdjustedWhileHidden = true;
- }
+ updateImeAdjustState();
+
return (mTargetAdjusted || mAdjusted) ? IME_ANIMATION_NO_ALPHA : 0;
}
@@ -256,11 +261,6 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mSplits.mSplitScreenController.setAdjustedForIme(mTargetShown && !mPaused);
}
- public void updateAdjustForIme() {
- updateImeAdjustState(mAdjustedWhileHidden);
- mAdjustedWhileHidden = false;
- }
-
@Override
public void onImePositionChanged(int displayId, int imeTop,
SurfaceControl.Transaction t) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index 261ff2f8de83..80ab166d0649 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -146,10 +146,8 @@ public class LegacySplitScreenController implements DisplayController.OnDisplays
new LegacySplitDisplayLayout(mContext, displayLayout, mSplits);
sdl.rotateTo(toRotation);
mRotateSplitLayout = sdl;
- final int position = isDividerVisible()
- ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
- : mView.getCurrentPosition())
- // snap resets to middle target when not in split-mode
+ // snap resets to middle target when not minimized and rotation changed.
+ final int position = mMinimized ? mView.mSnapTargetBeforeMinimized.position
: sdl.getSnapAlgorithm().getMiddleTarget().position;
DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
final DividerSnapAlgorithm.SnapTarget target =
@@ -229,9 +227,6 @@ public class LegacySplitScreenController implements DisplayController.OnDisplays
return;
}
mView.setHidden(showing);
- if (!showing) {
- mImePositionProcessor.updateAdjustForIme();
- }
mIsKeyguardShowing = showing;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 046c32071358..a4b866aa3f5e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -19,6 +19,7 @@ package com.android.wm.shell.pip;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.PictureInPictureParams;
import android.content.Context;
import android.content.pm.ActivityInfo;
@@ -454,6 +455,56 @@ public class PipBoundsAlgorithm {
}
/**
+ * @return the normal bounds adjusted so that they fit the menu actions.
+ */
+ public Rect adjustNormalBoundsToFitMenu(@NonNull Rect normalBounds,
+ @Nullable Size minMenuSize) {
+ if (minMenuSize == null) {
+ return normalBounds;
+ }
+ if (normalBounds.width() >= minMenuSize.getWidth()
+ && normalBounds.height() >= minMenuSize.getHeight()) {
+ // The normal bounds can fit the menu as is, no need to adjust the bounds.
+ return normalBounds;
+ }
+ final Rect adjustedNormalBounds = new Rect();
+ final boolean needsWidthAdj = minMenuSize.getWidth() > normalBounds.width();
+ final boolean needsHeightAdj = minMenuSize.getHeight() > normalBounds.height();
+ final int adjWidth;
+ final int adjHeight;
+ if (needsWidthAdj && needsHeightAdj) {
+ // Both the width and the height are too small - find the edge that needs the larger
+ // adjustment and scale that edge. The other edge will scale beyond the minMenuSize
+ // when the aspect ratio is applied.
+ final float widthScaleFactor =
+ ((float) (minMenuSize.getWidth())) / ((float) (normalBounds.width()));
+ final float heightScaleFactor =
+ ((float) (minMenuSize.getHeight())) / ((float) (normalBounds.height()));
+ if (widthScaleFactor > heightScaleFactor) {
+ adjWidth = minMenuSize.getWidth();
+ adjHeight = Math.round(adjWidth / mPipBoundsState.getAspectRatio());
+ } else {
+ adjHeight = minMenuSize.getHeight();
+ adjWidth = Math.round(adjHeight * mPipBoundsState.getAspectRatio());
+ }
+ } else if (needsWidthAdj) {
+ // Width is too small - use the min menu size width instead.
+ adjWidth = minMenuSize.getWidth();
+ adjHeight = Math.round(adjWidth / mPipBoundsState.getAspectRatio());
+ } else {
+ // Height is too small - use the min menu size height instead.
+ adjHeight = minMenuSize.getHeight();
+ adjWidth = Math.round(adjHeight * mPipBoundsState.getAspectRatio());
+ }
+ adjustedNormalBounds.set(0, 0, adjWidth, adjHeight);
+ // Make sure the bounds conform to the aspect ratio and min edge size.
+ transformBoundsToAspectRatio(adjustedNormalBounds,
+ mPipBoundsState.getAspectRatio(), true /* useCurrentMinEdgeSize */,
+ true /* useCurrentSize */);
+ return adjustedNormalBounds;
+ }
+
+ /**
* Dumps internal states.
*/
public void dump(PrintWriter pw, String prefix) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 324a6e27a242..f367cd608f37 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -722,6 +722,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) {
mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
}
+
+ final PipAnimationController.PipTransitionAnimator animator =
+ mPipAnimationController.getCurrentAnimator();
+ if (animator != null) {
+ animator.removeAllUpdateListeners();
+ animator.removeAllListeners();
+ animator.cancel();
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index f0bd8a2846ed..c816f18c2fc2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -246,10 +246,20 @@ public class PipResizeGestureHandler {
}
if (ev instanceof MotionEvent) {
+ MotionEvent mv = (MotionEvent) ev;
+ int action = mv.getActionMasked();
+ final Rect pipBounds = mPipBoundsState.getBounds();
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ if (!pipBounds.contains((int) mv.getRawX(), (int) mv.getRawY())
+ && mPhonePipMenuController.isMenuVisible()) {
+ mPhonePipMenuController.hideMenu();
+ }
+ }
+
if (mEnablePinchResize && mOngoingPinchToResize) {
- onPinchResize((MotionEvent) ev);
+ onPinchResize(mv);
} else if (mEnableDragCornerResize) {
- onDragCornerResize((MotionEvent) ev);
+ onDragCornerResize(mv);
}
}
}
@@ -450,7 +460,6 @@ public class PipResizeGestureHandler {
float x = ev.getX();
float y = ev.getY() - mOhmOffset;
if (action == MotionEvent.ACTION_DOWN) {
- final Rect currentPipBounds = mPipBoundsState.getBounds();
mLastResizeBounds.setEmpty();
mAllowGesture = isInValidSysUiState() && isWithinDragResizeRegion((int) x, (int) y);
if (mAllowGesture) {
@@ -458,11 +467,6 @@ public class PipResizeGestureHandler {
mDownPoint.set(x, y);
mDownBounds.set(mPipBoundsState.getBounds());
}
- if (!currentPipBounds.contains((int) x, (int) y)
- && mPhonePipMenuController.isMenuVisible()) {
- mPhonePipMenuController.hideMenu();
- }
-
} else if (mAllowGesture) {
switch (action) {
case MotionEvent.ACTION_POINTER_DOWN:
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index b1086c575f49..0bcd1a363eb6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -726,12 +726,17 @@ public class PipTouchHandler {
}
private void animateToNormalSize(Runnable callback) {
+ // Save the current bounds as the user-resize bounds.
mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds());
- final Rect normalBounds = new Rect(mPipBoundsState.getNormalBounds());
+
+ final Size minMenuSize = mMenuController.getEstimatedMinMenuSize();
+ final Rect normalBounds = mPipBoundsState.getNormalBounds();
+ final Rect destBounds = mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds,
+ minMenuSize);
Rect restoredMovementBounds = new Rect();
- mPipBoundsAlgorithm.getMovementBounds(normalBounds,
+ mPipBoundsAlgorithm.getMovementBounds(destBounds,
mInsetBounds, restoredMovementBounds, mIsImeShowing ? mImeHeight : 0);
- mSavedSnapFraction = mMotionHelper.animateToExpandedState(normalBounds,
+ mSavedSnapFraction = mMotionHelper.animateToExpandedState(destBounds,
mPipBoundsState.getMovementBounds(), restoredMovementBounds, callback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
index 9986154b051d..4e477ca104dd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
@@ -85,7 +85,10 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener {
}
View iconView = view.getIconView();
- if (iconView == null || iconView.getBackground() == null) {
+
+ // If the icon and the background are invisible, don't animate it
+ if (iconView == null || iconView.getLayoutParams().width == 0
+ || iconView.getLayoutParams().height == 0) {
mIconFadeOutDuration = 0;
mIconStartAlpha = 0;
mAppRevealDelay = 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index df3fee043419..b09d0d89a6b9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -77,6 +77,13 @@ public class SplashscreenContentDrawer {
// For example, an icon with the foreground 108*108 opaque pixels and it's background
// also 108*108 pixels, then do not enlarge this icon if only need to show foreground icon.
private static final float ENLARGE_FOREGROUND_ICON_THRESHOLD = (72f * 72f) / (108f * 108f);
+
+ /**
+ * If the developer doesn't specify a background for the icon, we slightly scale it up.
+ *
+ * The background is either manually specified in the theme or the Adaptive Icon
+ * background is used if it's different from the window background.
+ */
private static final float NO_BACKGROUND_SCALE = 192f / 160;
private final Context mContext;
private final IconProvider mIconProvider;
@@ -228,7 +235,7 @@ public class SplashscreenContentDrawer {
attrs.mWindowBgColor = safeReturnAttrDefault((def) -> typedArray.getColor(
R.styleable.Window_windowSplashScreenBackground, def),
Color.TRANSPARENT);
- attrs.mReplaceIcon = safeReturnAttrDefault((def) -> typedArray.getDrawable(
+ attrs.mSplashScreenIcon = safeReturnAttrDefault((def) -> typedArray.getDrawable(
R.styleable.Window_windowSplashScreenAnimatedIcon), null);
attrs.mAnimationDuration = safeReturnAttrDefault((def) -> typedArray.getInt(
R.styleable.Window_windowSplashScreenAnimationDuration, def), 0);
@@ -241,7 +248,7 @@ public class SplashscreenContentDrawer {
if (DEBUG) {
Slog.d(TAG, "window attributes color: "
+ Integer.toHexString(attrs.mWindowBgColor)
- + " icon " + attrs.mReplaceIcon + " duration " + attrs.mAnimationDuration
+ + " icon " + attrs.mSplashScreenIcon + " duration " + attrs.mAnimationDuration
+ " brandImage " + attrs.mBrandingImage);
}
}
@@ -250,7 +257,7 @@ public class SplashscreenContentDrawer {
public static class SplashScreenWindowAttrs {
private int mWindowBgResId = 0;
private int mWindowBgColor = Color.TRANSPARENT;
- private Drawable mReplaceIcon = null;
+ private Drawable mSplashScreenIcon = null;
private Drawable mBrandingImage = null;
private int mIconBgColor = Color.TRANSPARENT;
private int mAnimationDuration = 0;
@@ -287,10 +294,15 @@ public class SplashscreenContentDrawer {
// empty splash screen case
animationDuration = 0;
mFinalIconSize = 0;
- } else if (mTmpAttrs.mReplaceIcon != null) {
+ } else if (mTmpAttrs.mSplashScreenIcon != null) {
// replaced icon, don't process
- iconDrawable = mTmpAttrs.mReplaceIcon;
+ iconDrawable = mTmpAttrs.mSplashScreenIcon;
animationDuration = mTmpAttrs.mAnimationDuration;
+
+ // There is no background below the icon, so scale the icon up
+ if (mTmpAttrs.mIconBgColor == Color.TRANSPARENT) {
+ mFinalIconSize *= NO_BACKGROUND_SCALE;
+ }
createIconDrawable(iconDrawable, false);
} else {
final float iconScale = (float) mIconSize / (float) mDefaultIconSize;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index dae7055ede53..211941f44c8e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -162,6 +162,7 @@ public class SplashscreenIconDrawableFactory {
@Override
public void draw(Canvas canvas) {
+ canvas.clipPath(mMaskScaleOnly);
if (mMaskScaleOnly != null) {
canvas.drawPath(mMaskScaleOnly, mPaint);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
index a0c6d1138698..90f898aa09da 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java
@@ -402,6 +402,64 @@ public class PipBoundsAlgorithmTest extends ShellTestCase {
assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
}
+ @Test
+ public void adjustNormalBoundsToFitMenu_alreadyFits() {
+ final Rect normalBounds = new Rect(0, 0, 400, 711);
+ final Size minMenuSize = new Size(396, 292);
+ mPipBoundsState.setAspectRatio(
+ ((float) normalBounds.width()) / ((float) normalBounds.height()));
+
+ final Rect bounds =
+ mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds, minMenuSize);
+
+ assertEquals(normalBounds, bounds);
+ }
+
+ @Test
+ public void adjustNormalBoundsToFitMenu_widthTooSmall() {
+ final Rect normalBounds = new Rect(0, 0, 297, 528);
+ final Size minMenuSize = new Size(396, 292);
+ mPipBoundsState.setAspectRatio(
+ ((float) normalBounds.width()) / ((float) normalBounds.height()));
+
+ final Rect bounds =
+ mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds, minMenuSize);
+
+ assertEquals(minMenuSize.getWidth(), bounds.width());
+ assertEquals(minMenuSize.getWidth() / mPipBoundsState.getAspectRatio(),
+ bounds.height(), 0.3f);
+ }
+
+ @Test
+ public void adjustNormalBoundsToFitMenu_heightTooSmall() {
+ final Rect normalBounds = new Rect(0, 0, 400, 280);
+ final Size minMenuSize = new Size(396, 292);
+ mPipBoundsState.setAspectRatio(
+ ((float) normalBounds.width()) / ((float) normalBounds.height()));
+
+ final Rect bounds =
+ mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds, minMenuSize);
+
+ assertEquals(minMenuSize.getHeight(), bounds.height());
+ assertEquals(minMenuSize.getHeight() * mPipBoundsState.getAspectRatio(),
+ bounds.width(), 0.3f);
+ }
+
+ @Test
+ public void adjustNormalBoundsToFitMenu_widthAndHeightTooSmall() {
+ final Rect normalBounds = new Rect(0, 0, 350, 280);
+ final Size minMenuSize = new Size(396, 292);
+ mPipBoundsState.setAspectRatio(
+ ((float) normalBounds.width()) / ((float) normalBounds.height()));
+
+ final Rect bounds =
+ mPipBoundsAlgorithm.adjustNormalBoundsToFitMenu(normalBounds, minMenuSize);
+
+ assertEquals(minMenuSize.getWidth(), bounds.width());
+ assertEquals(minMenuSize.getWidth() / mPipBoundsState.getAspectRatio(),
+ bounds.height(), 0.3f);
+ }
+
private void overrideDefaultAspectRatio(float aspectRatio) {
final TestableResources res = mContext.getOrCreateTestableResources();
res.addOverride(
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 894b479c11db..eb5878d95561 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -133,6 +133,12 @@ public:
}
}
+ void onRemovedFromTree() {
+ if (mImpl) {
+ mImpl->onRemovedFromTree();
+ }
+ }
+
[[nodiscard]] bool hasText() const {
return mImpl && mImpl->hasText();
}
@@ -172,6 +178,7 @@ private:
return false;
}
void syncContents(const WebViewSyncData& data) { }
+ void onRemovedFromTree() { }
void applyColorTransform(ColorTransform transform) { }
};
@@ -298,6 +305,10 @@ public:
apply([&](auto& it) { it.syncContents(data); });
}
+ void onRemovedFromTree() {
+ apply([&](auto& it) { it.onRemovedFromTree(); });
+ }
+
[[nodiscard]] bool hasText() const {
return apply([](const auto& it) -> auto { return it.hasText(); });
}
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index f0995c4f324b..b8fa55a18dac 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -84,6 +84,8 @@ float Properties::defaultSdrWhitePoint = 200.f;
bool Properties::useHintManager = true;
int Properties::targetCpuTimePercentage = 70;
+bool Properties::enableWebViewOverlays = false;
+
StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI;
bool Properties::load() {
@@ -137,6 +139,8 @@ bool Properties::load() {
targetCpuTimePercentage = base::GetIntProperty(PROPERTY_TARGET_CPU_TIME_PERCENTAGE, 70);
if (targetCpuTimePercentage <= 0 || targetCpuTimePercentage > 100) targetCpuTimePercentage = 70;
+ enableWebViewOverlays = base::GetBoolProperty(PROPERTY_WEBVIEW_OVERLAYS_ENABLED, false);
+
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index f5fd0036f7be..7df6e2c92247 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -182,6 +182,11 @@ enum DebugLevel {
*/
#define PROPERTY_REDUCE_OPS_TASK_SPLITTING "renderthread.skia.reduceopstasksplitting"
+/**
+ * Enable WebView Overlays feature.
+ */
+#define PROPERTY_WEBVIEW_OVERLAYS_ENABLED "debug.hwui.webview_overlays_enabled"
+
///////////////////////////////////////////////////////////////////////////////
// Misc
///////////////////////////////////////////////////////////////////////////////
@@ -276,6 +281,8 @@ public:
static bool useHintManager;
static int targetCpuTimePercentage;
+ static bool enableWebViewOverlays;
+
static StretchEffectBehavior getStretchEffectBehavior() {
return stretchEffectBehavior;
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 44c335f6adb3..0c422df65881 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -18,6 +18,7 @@
#include "DamageAccumulator.h"
#include "Debug.h"
+#include "Properties.h"
#include "TreeInfo.h"
#include "VectorDrawable.h"
#include "private/hwui/WebViewFunctor.h"
@@ -473,6 +474,9 @@ void RenderNode::decParentRefCount(TreeObserver& observer, TreeInfo* info) {
}
void RenderNode::onRemovedFromTree(TreeInfo* info) {
+ if (Properties::enableWebViewOverlays && mDisplayList) {
+ mDisplayList.onRemovedFromTree();
+ }
destroyHardwareResources(info);
}
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 92e20c477669..df4101109a18 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -108,6 +108,13 @@ void WebViewFunctor::sync(const WebViewSyncData& syncData) const {
mCallbacks.onSync(mFunctor, mData, syncData);
}
+void WebViewFunctor::onRemovedFromTree() {
+ ATRACE_NAME("WebViewFunctor::onRemovedFromTree");
+ if (mSurfaceControl) {
+ removeOverlays();
+ }
+}
+
void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
ATRACE_NAME("WebViewFunctor::drawGl");
if (!mHasContext) {
@@ -121,12 +128,19 @@ void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
.mergeTransaction = currentFunctor.mergeTransaction,
};
- if (!drawInfo.isLayer) {
+ if (Properties::enableWebViewOverlays && !drawInfo.isLayer) {
renderthread::CanvasContext* activeContext =
renderthread::CanvasContext::getActiveContext();
if (activeContext != nullptr) {
ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl();
- if (rootSurfaceControl) overlayParams.overlaysMode = OverlaysMode::Enabled;
+ if (rootSurfaceControl) {
+ overlayParams.overlaysMode = OverlaysMode::Enabled;
+ int32_t rgid = activeContext->getSurfaceControlGenerationId();
+ if (mParentSurfaceControlGenerationId != rgid) {
+ reparentSurfaceControl(rootSurfaceControl);
+ mParentSurfaceControlGenerationId = rgid;
+ }
+ }
}
}
@@ -178,6 +192,7 @@ void WebViewFunctor::removeOverlays() {
ScopedCurrentFunctor currentFunctor(this);
mCallbacks.removeOverlays(mFunctor, mData, currentFunctor.mergeTransaction);
if (mSurfaceControl) {
+ reparentSurfaceControl(nullptr);
auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
funcs.releaseFunc(mSurfaceControl);
mSurfaceControl = nullptr;
@@ -195,6 +210,7 @@ ASurfaceControl* WebViewFunctor::getSurfaceControl() {
LOG_ALWAYS_FATAL_IF(rootSurfaceControl == nullptr, "Null root surface control!");
auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
+ mParentSurfaceControlGenerationId = activeContext->getSurfaceControlGenerationId();
mSurfaceControl = funcs.createFunc(rootSurfaceControl, "Webview Overlay SurfaceControl");
ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
activeContext->prepareSurfaceControlForWebview();
@@ -209,15 +225,29 @@ ASurfaceControl* WebViewFunctor::getSurfaceControl() {
void WebViewFunctor::mergeTransaction(ASurfaceTransaction* transaction) {
ATRACE_NAME("WebViewFunctor::mergeTransaction");
if (transaction == nullptr) return;
+ bool done = false;
renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext();
- LOG_ALWAYS_FATAL_IF(activeContext == nullptr, "Null active canvas context!");
- bool done = activeContext->mergeTransaction(transaction, mSurfaceControl);
+ // activeContext might be null when called from mCallbacks.removeOverlays()
+ if (activeContext != nullptr) {
+ done = activeContext->mergeTransaction(transaction, mSurfaceControl);
+ }
if (!done) {
auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
funcs.transactionApplyFunc(transaction);
}
}
+void WebViewFunctor::reparentSurfaceControl(ASurfaceControl* parent) {
+ ATRACE_NAME("WebViewFunctor::reparentSurfaceControl");
+ if (mSurfaceControl == nullptr) return;
+
+ auto funcs = renderthread::RenderThread::getInstance().getASurfaceControlFunctions();
+ ASurfaceTransaction* transaction = funcs.transactionCreateFunc();
+ funcs.transactionReparentFunc(transaction, mSurfaceControl, parent);
+ mergeTransaction(transaction);
+ funcs.transactionDeleteFunc(transaction);
+}
+
WebViewFunctorManager& WebViewFunctorManager::instance() {
static WebViewFunctorManager sInstance;
return sInstance;
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index a84cda550567..f28f310993ec 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -58,6 +58,8 @@ public:
void removeOverlays() { mReference.removeOverlays(); }
+ void onRemovedFromTree() { mReference.onRemovedFromTree(); }
+
private:
friend class WebViewFunctor;
@@ -74,6 +76,7 @@ public:
void postDrawVk();
void destroyContext();
void removeOverlays();
+ void onRemovedFromTree();
ASurfaceControl* getSurfaceControl();
void mergeTransaction(ASurfaceTransaction* transaction);
@@ -85,12 +88,16 @@ public:
}
private:
+ void reparentSurfaceControl(ASurfaceControl* parent);
+
+private:
WebViewFunctorCallbacks mCallbacks;
void* const mData;
int mFunctor;
RenderMode mMode;
bool mHasContext = false;
bool mCreatedHandle = false;
+ int32_t mParentSurfaceControlGenerationId = 0;
ASurfaceControl* mSurfaceControl = nullptr;
};
diff --git a/libs/hwui/canvas/CanvasOpBuffer.cpp b/libs/hwui/canvas/CanvasOpBuffer.cpp
index 6089c572b0d5..336c5d8dab35 100644
--- a/libs/hwui/canvas/CanvasOpBuffer.cpp
+++ b/libs/hwui/canvas/CanvasOpBuffer.cpp
@@ -46,6 +46,10 @@ void CanvasOpBuffer::syncContents(const WebViewSyncData& data) {
LOG_ALWAYS_FATAL("TODO");
}
+void CanvasOpBuffer::onRemovedFromTree() {
+ LOG_ALWAYS_FATAL("TODO");
+}
+
void CanvasOpBuffer::applyColorTransform(ColorTransform transform) {
LOG_ALWAYS_FATAL("TODO");
}
diff --git a/libs/hwui/canvas/CanvasOpBuffer.h b/libs/hwui/canvas/CanvasOpBuffer.h
index af797ca8288b..529546d5c49c 100644
--- a/libs/hwui/canvas/CanvasOpBuffer.h
+++ b/libs/hwui/canvas/CanvasOpBuffer.h
@@ -100,6 +100,7 @@ public:
TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn);
void syncContents(const WebViewSyncData& data);
+ void onRemovedFromTree();
void applyColorTransform(ColorTransform transform);
[[nodiscard]] bool isEmpty() const { return !mHas.content; }
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 4d31cd90d40f..ef3a11c13469 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -933,6 +933,11 @@ static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, job
env->ReleaseStringUTFChars(skiaDiskCachePath, skiaCacheArray);
}
+static jboolean android_view_ThreadedRenderer_isWebViewOverlaysEnabled(JNIEnv* env, jobject clazz) {
+ // this value is valid only after loadSystemProperties() is called
+ return Properties::enableWebViewOverlays;
+}
+
// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -1025,6 +1030,8 @@ static const JNINativeMethod gMethods[] = {
(void*)android_view_ThreadedRenderer_setDisplayDensityDpi},
{"nInitDisplayInfo", "(IIFIJJ)V", (void*)android_view_ThreadedRenderer_initDisplayInfo},
{"preload", "()V", (void*)android_view_ThreadedRenderer_preload},
+ {"isWebViewOverlaysEnabled", "()Z",
+ (void*)android_view_ThreadedRenderer_isWebViewOverlaysEnabled},
};
static JavaVM* mJvm = nullptr;
diff --git a/libs/hwui/pipeline/skia/FunctorDrawable.h b/libs/hwui/pipeline/skia/FunctorDrawable.h
index 988a896b6267..9bbd0a92600b 100644
--- a/libs/hwui/pipeline/skia/FunctorDrawable.h
+++ b/libs/hwui/pipeline/skia/FunctorDrawable.h
@@ -44,6 +44,10 @@ public:
mWebViewHandle->sync(data);
}
+ virtual void onRemovedFromTree() {
+ mWebViewHandle->onRemovedFromTree();
+ }
+
protected:
virtual SkRect onGetBounds() override { return mBounds; }
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index 3498f715b455..fcfc4f82abed 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -47,6 +47,12 @@ void SkiaDisplayList::syncContents(const WebViewSyncData& data) {
}
}
+void SkiaDisplayList::onRemovedFromTree() {
+ for (auto& functor : mChildFunctors) {
+ functor->onRemovedFromTree();
+ }
+}
+
bool SkiaDisplayList::reuseDisplayList(RenderNode* node) {
reset();
node->attachAvailableList(this);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 90e9bc6a1a28..2a677344b7b2 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -111,6 +111,13 @@ public:
*/
void syncContents(const WebViewSyncData& data);
+ /**
+ * ONLY to be called by RenderNode::onRemovedFromTree so that we can notify any
+ * contained VectorDrawables or GLFunctors.
+ *
+ */
+ void onRemovedFromTree();
+
void applyColorTransform(ColorTransform transform) {
mDisplayList.applyColorTransform(transform);
}
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 5462623e75ff..44a6e4354608 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -59,6 +59,10 @@ void SkiaPipeline::onDestroyHardwareResources() {
}
bool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
+ if (!mRenderThread.getGrContext()) {
+ ALOGD("Trying to pin an image with an invalid GrContext");
+ return false;
+ }
for (SkImage* image : mutableImages) {
if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
mPinnedImages.emplace_back(sk_ref_sp(image));
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0c9711ba8025..81cee6103d22 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -201,6 +201,7 @@ void CanvasContext::setSurfaceControl(ASurfaceControl* surfaceControl) {
funcs.releaseFunc(mSurfaceControl);
}
mSurfaceControl = surfaceControl;
+ mSurfaceControlGenerationId++;
mExpectSurfaceStats = surfaceControl != nullptr;
if (mSurfaceControl != nullptr) {
funcs.acquireFunc(mSurfaceControl);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 3279ccb8e597..85af3e4fb0b6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -110,6 +110,7 @@ public:
GrDirectContext* getGrContext() const { return mRenderThread.getGrContext(); }
ASurfaceControl* getSurfaceControl() const { return mSurfaceControl; }
+ int32_t getSurfaceControlGenerationId() const { return mSurfaceControlGenerationId; }
// Won't take effect until next EGLSurface creation
void setSwapBehavior(SwapBehavior swapBehavior);
@@ -253,6 +254,9 @@ private:
// The SurfaceControl reference is passed from ViewRootImpl, can be set to
// NULL to remove the reference
ASurfaceControl* mSurfaceControl = nullptr;
+ // id to track surface control changes and WebViewFunctor uses it to determine
+ // whether reparenting is needed
+ int32_t mSurfaceControlGenerationId = 0;
// stopped indicates the CanvasContext will reject actual redraw operations,
// and defer repaint until it is un-stopped
bool mStopped = false;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 524407d2b9b0..f83c0a4926f9 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -98,6 +98,10 @@ ASurfaceControlFunctions::ASurfaceControlFunctions() {
LOG_ALWAYS_FATAL_IF(transactionApplyFunc == nullptr,
"Failed to find required symbol ASurfaceTransaction_apply!");
+ transactionReparentFunc = (AST_reparent)dlsym(handle_, "ASurfaceTransaction_reparent");
+ LOG_ALWAYS_FATAL_IF(transactionReparentFunc == nullptr,
+ "Failed to find required symbol transactionReparentFunc!");
+
transactionSetVisibilityFunc =
(AST_setVisibility)dlsym(handle_, "ASurfaceTransaction_setVisibility");
LOG_ALWAYS_FATAL_IF(transactionSetVisibilityFunc == nullptr,
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index c5e3746587b8..05d225b856db 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -94,6 +94,9 @@ typedef uint64_t (*ASCStats_getFrameNumber)(ASurfaceControlStats* stats);
typedef ASurfaceTransaction* (*AST_create)();
typedef void (*AST_delete)(ASurfaceTransaction* transaction);
typedef void (*AST_apply)(ASurfaceTransaction* transaction);
+typedef void (*AST_reparent)(ASurfaceTransaction* aSurfaceTransaction,
+ ASurfaceControl* aSurfaceControl,
+ ASurfaceControl* newParentASurfaceControl);
typedef void (*AST_setVisibility)(ASurfaceTransaction* transaction,
ASurfaceControl* surface_control, int8_t visibility);
typedef void (*AST_setZOrder)(ASurfaceTransaction* transaction, ASurfaceControl* surface_control,
@@ -113,6 +116,7 @@ struct ASurfaceControlFunctions {
AST_create transactionCreateFunc;
AST_delete transactionDeleteFunc;
AST_apply transactionApplyFunc;
+ AST_reparent transactionReparentFunc;
AST_setVisibility transactionSetVisibilityFunc;
AST_setZOrder transactionSetZOrderFunc;
};