Added animations to dim layers
Added animations to dim layers when dims are set for
WindowState surfaces since they're controlled by the system.
Test: Dims for dialogs now animate.
Test: DimmerTests
Fixes: 71841698
Fixes: 69553362
Fixes: 71614627
Fixes: 72333587
Change-Id: I34f6f3d7885d5c9c0075a941e40d68bc5618a016
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 9fe16ae..b435605 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -17,34 +17,115 @@
package com.android.server.wm;
import android.util.ArrayMap;
-import android.util.Slog;
import android.view.SurfaceControl;
import android.graphics.Rect;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
* black layers of varying opacity at various Z-levels which create the effect of a Dim.
*/
class Dimmer {
private static final String TAG = "WindowManager";
+ private static final int DEFAULT_DIM_ANIM_DURATION = 200;
- private class DimState {
- SurfaceControl mSurfaceControl;
+ private class DimAnimatable implements SurfaceAnimator.Animatable {
+ private final SurfaceControl mDimLayer;
+
+ private DimAnimatable(SurfaceControl dimLayer) {
+ mDimLayer = dimLayer;
+ }
+
+ @Override
+ public SurfaceControl.Transaction getPendingTransaction() {
+ return mHost.getPendingTransaction();
+ }
+
+ @Override
+ public void commitPendingTransaction() {
+ mHost.commitPendingTransaction();
+ }
+
+ @Override
+ public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
+ }
+
+ @Override
+ public void onAnimationLeashDestroyed(SurfaceControl.Transaction t) {
+ }
+
+ @Override
+ public void destroyAfterPendingTransaction(SurfaceControl surface) {
+ mHost.destroyAfterPendingTransaction(surface);
+ }
+
+ @Override
+ public SurfaceControl.Builder makeAnimationLeash() {
+ return mHost.makeAnimationLeash();
+ }
+
+ @Override
+ public SurfaceControl getAnimationLeashParent() {
+ return mHost.getSurfaceControl();
+ }
+
+ @Override
+ public SurfaceControl getSurfaceControl() {
+ return mDimLayer;
+ }
+
+ @Override
+ public SurfaceControl getParentSurfaceControl() {
+ return mHost.getSurfaceControl();
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ // This will determine the size of the leash created. This should be the size of the
+ // host and not the dim layer since the dim layer may get bigger during animation. If
+ // that occurs, the leash size cannot change so we need to ensure the leash is big
+ // enough that the dim layer can grow.
+ // This works because the mHost will be a Task which has the display bounds.
+ return mHost.getSurfaceWidth();
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ // See getSurfaceWidth() above for explanation.
+ return mHost.getSurfaceHeight();
+ }
+ }
+
+ @VisibleForTesting
+ class DimState {
+ /**
+ * The layer where property changes should be invoked on.
+ */
+ SurfaceControl mDimLayer;
boolean mDimming;
+ boolean isVisible;
+ SurfaceAnimator mSurfaceAnimator;
/**
- * Used for Dims not assosciated with a WindowContainer. See {@link Dimmer#dimAbove} for
+ * Used for Dims not associated with a WindowContainer. See {@link Dimmer#dimAbove} for
* details on Dim lifecycle.
*/
boolean mDontReset;
- DimState(SurfaceControl ctl) {
- mSurfaceControl = ctl;
+ DimState(SurfaceControl dimLayer) {
+ mDimLayer = dimLayer;
mDimming = true;
+ mSurfaceAnimator = new SurfaceAnimator(new DimAnimatable(dimLayer), () -> {
+ if (!mDimming) {
+ mDimLayer.destroy();
+ }
+ }, mHost.mService.mAnimator::addAfterPrepareSurfacesRunnable, mHost.mService);
}
- };
+ }
- private ArrayMap<WindowContainer, DimState> mDimLayerUsers = new ArrayMap<>();
+ @VisibleForTesting
+ ArrayMap<WindowContainer, DimState> mDimLayerUsers = new ArrayMap<>();
/**
* The {@link WindowContainer} that our Dim's are bounded to. We may be dimming on behalf of the
@@ -56,19 +137,18 @@
mHost = host;
}
- SurfaceControl makeDimLayer() {
- final SurfaceControl control = mHost.makeChildSurface(null)
+ private SurfaceControl makeDimLayer() {
+ return mHost.makeChildSurface(null)
.setParent(mHost.getSurfaceControl())
.setColorLayer(true)
.setName("Dim Layer for - " + mHost.getName())
.build();
- return control;
}
/**
* Retreive the DimState for a given child of the host.
*/
- DimState getDimState(WindowContainer container) {
+ private DimState getDimState(WindowContainer container) {
DimState state = mDimLayerUsers.get(container);
if (state == null) {
final SurfaceControl ctl = makeDimLayer();
@@ -88,14 +168,12 @@
private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
float alpha) {
final DimState d = getDimState(container);
- t.show(d.mSurfaceControl);
if (container != null) {
- t.setRelativeLayer(d.mSurfaceControl,
- container.getSurfaceControl(), relativeLayer);
+ t.setRelativeLayer(d.mDimLayer, container.getSurfaceControl(), relativeLayer);
} else {
- t.setLayer(d.mSurfaceControl, Integer.MAX_VALUE);
+ t.setLayer(d.mDimLayer, Integer.MAX_VALUE);
}
- t.setAlpha(d.mSurfaceControl, alpha);
+ t.setAlpha(d.mDimLayer, alpha);
d.mDimming = true;
}
@@ -107,16 +185,18 @@
*/
void stopDim(SurfaceControl.Transaction t) {
DimState d = getDimState(null);
- t.hide(d.mSurfaceControl);
+ t.hide(d.mDimLayer);
+ d.isVisible = false;
d.mDontReset = false;
}
+
/**
* Place a Dim above the entire host container. The caller is responsible for calling stopDim to
* remove this effect. If the Dim can be assosciated with a particular child of the host
* consider using the other variant of dimAbove which ties the Dim lifetime to the child
* lifetime more explicitly.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, float alpha) {
@@ -128,9 +208,9 @@
* for each call to {@link WindowContainer#prepareSurfaces} the Dim state will be reset
* and the child should call dimAbove again to request the Dim to continue.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param container The container which to dim above. Should be a child of our host.
- * @param alpha The alpha at which to Dim.
+ * @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
dim(t, container, 1, alpha);
@@ -139,9 +219,9 @@
/**
* Like {@link #dimAbove} but places the dim below the given container.
*
- * @param t A transaction in which to apply the Dim.
+ * @param t A transaction in which to apply the Dim.
* @param container The container which to dim below. Should be a child of our host.
- * @param alpha The alpha at which to Dim.
+ * @param alpha The alpha at which to Dim.
*/
void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
@@ -159,7 +239,7 @@
void resetDimStates() {
for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
final DimState state = mDimLayerUsers.valueAt(i);
- if (state.mDontReset == false) {
+ if (!state.mDontReset) {
state.mDimming = false;
}
}
@@ -169,7 +249,7 @@
* Call after invoking {@link WindowContainer#prepareSurfaces} on children as
* described in {@link #resetDimStates}.
*
- * @param t A transaction in which to update the dims.
+ * @param t A transaction in which to update the dims.
* @param bounds The bounds at which to dim.
* @return true if any Dims were updated.
*/
@@ -177,19 +257,80 @@
boolean didSomething = false;
for (int i = mDimLayerUsers.size() - 1; i >= 0; i--) {
DimState state = mDimLayerUsers.valueAt(i);
+ WindowContainer container = mDimLayerUsers.keyAt(i);
+
// TODO: We want to animate the addition and removal of Dim's instead of immediately
// acting. When we do this we need to take care to account for the "Replacing Windows"
// case (and seamless dim transfer).
- if (state.mDimming == false) {
+ if (!state.mDimming) {
mDimLayerUsers.removeAt(i);
- state.mSurfaceControl.destroy();
+ startDimExit(container, state.mSurfaceAnimator, t);
} else {
didSomething = true;
// TODO: Once we use geometry from hierarchy this falls away.
- t.setSize(state.mSurfaceControl, bounds.width(), bounds.height());
- t.setPosition(state.mSurfaceControl, bounds.left, bounds.top);
+ t.setSize(state.mDimLayer, bounds.width(), bounds.height());
+ t.setPosition(state.mDimLayer, bounds.left, bounds.top);
+ if (!state.isVisible) {
+ state.isVisible = true;
+ t.show(state.mDimLayer);
+ startDimEnter(container, state.mSurfaceAnimator, t);
+ }
}
}
return didSomething;
}
+
+ private void startDimEnter(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t) {
+ startAnim(container, animator, t, 0 /* startAlpha */, 1 /* endAlpha */);
+ }
+
+ private void startDimExit(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t) {
+ startAnim(container, animator, t, 1 /* startAlpha */, 0 /* endAlpha */);
+ }
+
+ private void startAnim(WindowContainer container, SurfaceAnimator animator,
+ SurfaceControl.Transaction t, float startAlpha, float endAlpha) {
+ animator.startAnimation(t, new LocalAnimationAdapter(
+ new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
+ mHost.mService.mSurfaceAnimationRunner), false /* hidden */);
+ }
+
+ private long getDimDuration(WindowContainer container) {
+ // If there's no container, then there isn't an animation occurring while dimming. Set the
+ // duration to 0 so it immediately dims to the set alpha.
+ if (container == null) {
+ return 0;
+ }
+
+ // Otherwise use the same duration as the animation on the WindowContainer
+ AnimationAdapter animationAdapter = container.mSurfaceAnimator.getAnimation();
+ return animationAdapter == null ? DEFAULT_DIM_ANIM_DURATION
+ : animationAdapter.getDurationHint();
+ }
+
+ private static class AlphaAnimationSpec implements LocalAnimationAdapter.AnimationSpec {
+ private final long mDuration;
+ private final float mFromAlpha;
+ private final float mToAlpha;
+
+ AlphaAnimationSpec(float fromAlpha, float toAlpha, long duration) {
+ mFromAlpha = fromAlpha;
+ mToAlpha = toAlpha;
+ mDuration = duration;
+ }
+
+ @Override
+ public long getDuration() {
+ return mDuration;
+ }
+
+ @Override
+ public void apply(SurfaceControl.Transaction t, SurfaceControl sc, long currentPlayTime) {
+ float alpha = ((float) currentPlayTime / getDuration()) * (mToAlpha - mFromAlpha)
+ + mFromAlpha;
+ t.setAlpha(sc, alpha);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 3f49f0c..7674b5e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3599,6 +3599,8 @@
}
private final class AboveAppWindowContainers extends NonAppWindowContainers {
+ private final Dimmer mDimmer = new Dimmer(this);
+ private final Rect mTmpDimBoundsRect = new Rect();
AboveAppWindowContainers(String name, WindowManagerService service) {
super(name, service);
}
@@ -3630,6 +3632,22 @@
imeContainer.assignRelativeLayer(t, getSurfaceControl(), Integer.MAX_VALUE);
}
}
+
+ @Override
+ Dimmer getDimmer() {
+ return mDimmer;
+ }
+
+ @Override
+ void prepareSurfaces() {
+ mDimmer.resetDimStates();
+ super.prepareSurfaces();
+ getBounds(mTmpDimBoundsRect);
+
+ if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
+ scheduleAnimation();
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0628436..7d970d9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -462,8 +462,8 @@
} else {
mStack.getBounds(mTmpRect);
mTmpRect.intersect(getBounds());
+ out.set(mTmpRect);
}
- out.set(mTmpRect);
} else {
out.set(getBounds());
}
@@ -640,6 +640,7 @@
mPreserveNonFloatingState = false;
}
+ @Override
Dimmer getDimmer() {
return mDimmer;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index bc0f9ad..cf54b67 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1722,6 +1722,7 @@
|| activityType == ACTIVITY_TYPE_ASSISTANT;
}
+ @Override
Dimmer getDimmer() {
return mDimmer;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1f9255a..d58f02c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1219,4 +1219,11 @@
outPos.offset(-parentBounds.left, -parentBounds.top);
}
}
+
+ Dimmer getDimmer() {
+ if (mParent == null) {
+ return null;
+ }
+ return mParent.getDimmer();
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4fb2390..066e4e6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -907,9 +907,16 @@
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
+ return main(context, im, haveInputMethods, showBootMsgs, onlyCore, policy,
+ new SurfaceAnimationRunner());
+ }
+
+ public static WindowManagerService main(final Context context, final InputManagerService im,
+ final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
+ WindowManagerPolicy policy, SurfaceAnimationRunner surfaceAnimationRunner) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
- onlyCore, policy), 0);
+ onlyCore, policy, surfaceAnimationRunner), 0);
return sInstance;
}
@@ -932,7 +939,7 @@
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore,
- WindowManagerPolicy policy) {
+ WindowManagerPolicy policy, SurfaceAnimationRunner surfaceAnimationRunner) {
installLock(this, INDEX_WINDOW);
mContext = context;
mHaveInputMethods = haveInputMethods;
@@ -1059,7 +1066,7 @@
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
mHoldingScreenWakeLock.setReferenceCounted(false);
- mSurfaceAnimationRunner = new SurfaceAnimationRunner();
+ mSurfaceAnimationRunner = surfaceAnimationRunner;
mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 477dd2b..55c982c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2138,18 +2138,6 @@
mInputWindowHandle.inputChannel = null;
}
- private Dimmer getDimmer() {
- Task task = getTask();
- if (task != null) {
- return task.getDimmer();
- }
- TaskStack taskStack = getStack();
- if (taskStack != null) {
- return taskStack.getDimmer();
- }
- return null;
- }
-
/** Returns true if the replacement window was removed. */
boolean removeReplacedWindowIfNeeded(WindowState replacement) {
if (mWillReplaceWindow && mReplacementWindow == replacement && replacement.hasDrawnLw()) {
@@ -4516,11 +4504,11 @@
private void applyDims(Dimmer dimmer) {
if (!mAnimatingExit && mAppDied) {
mIsDimming = true;
- getDimmer().dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
+ dimmer.dimAbove(getPendingTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
} else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
- && !mAnimatingExit && isVisible()) {
+ && !mAnimatingExit && isVisible() && !mWinAnimator.mLastHidden) {
mIsDimming = true;
- getDimmer().dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
+ dimmer.dimBelow(getPendingTransaction(), this, mAttrs.dimAmount);
}
}
@@ -4531,7 +4519,6 @@
if (dimmer != null) {
applyDims(dimmer);
}
-
updateSurfacePosition(mPendingTransaction);
mWinAnimator.prepareSurfaceLocked(true);
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
index 70906df..396fef4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
@@ -16,11 +16,14 @@
package com.android.server.wm;
-import java.util.HashMap;
-
-import org.junit.Test;
-import org.junit.Before;
-import org.junit.runner.RunWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -28,22 +31,25 @@
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.eq;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.stubbing.Answer;
/**
* Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.wm.DimmerTests;
+ * atest FrameworksServicesTests:com.android.server.wm.DimmerTests;
*/
@Presubmit
+@Ignore("b/72450130")
@RunWith(AndroidJUnit4.class)
public class DimmerTests extends WindowTestsBase {
+
+ public DimmerTests() {
+ super(spy(new SurfaceAnimationRunner()));
+ }
+
private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
final SurfaceControl mControl = mock(SurfaceControl.class);
final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
@@ -65,12 +71,14 @@
private class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
final SurfaceSession mSession = new SurfaceSession();
- SurfaceControl mBuiltSurface = null;
- final SurfaceControl mHostControl = mock(SurfaceControl.class);
final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
MockSurfaceBuildingContainer() {
super(sWm);
+ mSurfaceControl = sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1)
+ .build();
}
class MockSurfaceBuilder extends SurfaceControl.Builder {
@@ -80,12 +88,19 @@
@Override
public SurfaceControl build() {
- SurfaceControl sc = mock(SurfaceControl.class);
- mBuiltSurface = sc;
- return sc;
+ return spy(sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1)
+ .build());
}
}
+ @Override
+ SurfaceControl.Builder makeSurface() {
+ return sWm.makeSurfaceBuilder(mSession)
+ .setName("test surface")
+ .setSize(1, 1);
+ }
@Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
@@ -93,11 +108,6 @@
}
@Override
- public SurfaceControl getSurfaceControl() {
- return mHostControl;
- }
-
- @Override
public SurfaceControl.Transaction getPendingTransaction() {
return mHostTransaction;
}
@@ -114,29 +124,37 @@
mTransaction = mock(SurfaceControl.Transaction.class);
mDimmer = new Dimmer(mHost);
+
+ doAnswer((Answer<Void>) invocation -> {
+ Runnable runnable = invocation.getArgument(3);
+ runnable.run();
+ return null;
+ }).when(sWm.mSurfaceAnimationRunner).startAnimation(any(), any(), any(), any());
}
@Test
public void testDimAboveNoChildCreatesSurface() throws Exception {
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setLayer(mHost.mBuiltSurface, Integer.MAX_VALUE);
+ SurfaceControl dimLayer = getDimLayer(null);
+
+ assertNotNull("Dimmer should have created a surface", dimLayer);
+
+ verify(mTransaction).setAlpha(dimLayer, alpha);
+ verify(mTransaction).setLayer(dimLayer, Integer.MAX_VALUE);
}
@Test
public void testDimAboveNoChildRedundantlyUpdatesAlphaOnExistingSurface() throws Exception {
float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, alpha);
- final SurfaceControl firstSurface = mHost.mBuiltSurface;
+ final SurfaceControl firstSurface = getDimLayer(null);
alpha = 0.9f;
mDimmer.dimAbove(mTransaction, alpha);
- assertEquals(firstSurface, mHost.mBuiltSurface);
+ assertEquals(firstSurface, getDimLayer(null));
verify(mTransaction).setAlpha(firstSurface, 0.9f);
}
@@ -148,16 +166,20 @@
int height = 300;
Rect bounds = new Rect(0, 0, width, height);
mDimmer.updateDims(mTransaction, bounds);
- verify(mTransaction).setSize(mHost.mBuiltSurface, width, height);
+
+ verify(mTransaction).setSize(getDimLayer(null), width, height);
+ verify(mTransaction).show(getDimLayer(null));
}
@Test
public void testDimAboveNoChildNotReset() throws Exception {
mDimmer.dimAbove(mTransaction, 0.8f);
+ SurfaceControl dimLayer = getDimLayer(null);
mDimmer.resetDimStates();
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface, never()).destroy();
+ verify(mTransaction).show(getDimLayer(null));
+ verify(dimLayer, never()).destroy();
}
@Test
@@ -167,11 +189,12 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+ SurfaceControl mDimLayer = getDimLayer(child);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, 1);
+ assertNotNull("Dimmer should have created a surface", mDimLayer);
+
+ verify(mTransaction).setAlpha(mDimLayer, alpha);
+ verify(mTransaction).setRelativeLayer(mDimLayer, child.mControl, 1);
}
@Test
@@ -181,11 +204,12 @@
final float alpha = 0.8f;
mDimmer.dimBelow(mTransaction, child, alpha);
- assertNotNull("Dimmer should have created a surface", mHost.mBuiltSurface);
+ SurfaceControl mDimLayer = getDimLayer(child);
- verify(mTransaction).setAlpha(mHost.mBuiltSurface, alpha);
- verify(mTransaction).show(mHost.mBuiltSurface);
- verify(mTransaction).setRelativeLayer(mHost.mBuiltSurface, child.mControl, -1);
+ assertNotNull("Dimmer should have created a surface", mDimLayer);
+
+ verify(mTransaction).setAlpha(mDimLayer, alpha);
+ verify(mTransaction).setRelativeLayer(mDimLayer, child.mControl, -1);
}
@Test
@@ -195,9 +219,11 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
+ SurfaceControl dimLayer = getDimLayer(child);
mDimmer.resetDimStates();
+
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface).destroy();
+ verify(dimLayer).destroy();
}
@Test
@@ -207,10 +233,16 @@
final float alpha = 0.8f;
mDimmer.dimAbove(mTransaction, child, alpha);
+ SurfaceControl dimLayer = getDimLayer(child);
mDimmer.resetDimStates();
mDimmer.dimAbove(mTransaction, child, alpha);
mDimmer.updateDims(mTransaction, new Rect());
- verify(mHost.mBuiltSurface, never()).destroy();
+ verify(mTransaction).show(dimLayer);
+ verify(dimLayer, never()).destroy();
+ }
+
+ private SurfaceControl getDimLayer(WindowContainer windowContainer) {
+ return mDimmer.mDimLayerUsers.get(windowContainer).mDimLayer;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 35ca493..81fd889 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
import android.os.PowerSaveState;
import android.util.proto.ProtoOutputStream;
@@ -68,6 +69,11 @@
private Runnable mRunnableWhenAddingSplashScreen;
static synchronized WindowManagerService getWindowManagerService(Context context) {
+ return getWindowManagerService(context, new SurfaceAnimationRunner());
+ }
+
+ static synchronized WindowManagerService getWindowManagerService(Context context,
+ SurfaceAnimationRunner surfaceAnimationRunner) {
if (sWm == null) {
// We only want to do this once for the test process as we don't want WM to try to
// register a bunch of local services again.
@@ -105,7 +111,7 @@
}
sWm = WindowManagerService.main(context, ims, true, false,
- false, new TestWindowManagerPolicy());
+ false, new TestWindowManagerPolicy(), surfaceAnimationRunner);
}
return sWm;
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 69b1378..7918901 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -84,6 +84,16 @@
WindowState mChildAppWindowBelow;
HashSet<WindowState> mCommonWindows;
+ private final SurfaceAnimationRunner mSurfaceAnimationRunner;
+
+ public WindowTestsBase() {
+ this(new SurfaceAnimationRunner());
+ }
+
+ public WindowTestsBase(SurfaceAnimationRunner surfaceAnimationRunner) {
+ mSurfaceAnimationRunner = surfaceAnimationRunner;
+ }
+
@Before
public void setUp() throws Exception {
if (!sOneTimeSetupDone) {
@@ -98,7 +108,7 @@
final Context context = InstrumentationRegistry.getTargetContext();
AttributeCache.init(context);
- sWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ sWm = TestWindowManagerPolicy.getWindowManagerService(context, mSurfaceAnimationRunner);
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);