Loading services/core/java/com/android/server/wm/AppWindowToken.java +51 −1 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED; import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW; import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL; import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import android.annotation.CallSuper; import android.app.Activity; Loading Loading @@ -264,6 +265,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree */ private boolean mWillCloseOrEnterPip; /** Layer used to constrain the animation to a token's stack bounds. */ SurfaceControl mAnimationBoundsLayer; /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */ boolean mNeedsAnimationBoundsLayer; AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, Loading Loading @@ -1720,6 +1727,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation; } /** * Creates a layer to apply crop to an animation. */ private SurfaceControl createAnimationBoundsLayer(Transaction t) { if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer"); final SurfaceControl.Builder builder = makeAnimationLeash() .setParent(getAnimationLeashParent()) .setName(getSurfaceControl() + " - animation-bounds") .setSize(getSurfaceWidth(), getSurfaceHeight()); final SurfaceControl boundsLayer = builder.build(); t.show(boundsLayer); return boundsLayer; } boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { Loading Loading @@ -1753,12 +1774,15 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree adapter = mService.mAppTransition.getRemoteAnimationController() .createAnimationAdapter(this, mTmpPoint, mTmpRect); } else { final int appStackClipMode = mService.mAppTransition.getAppStackClipMode(); mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM); final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); if (a != null) { adapter = new LocalAnimationAdapter( new WindowAnimationSpec(a, mTmpPoint, mTmpRect, mService.mAppTransition.canSkipFirstFrame(), mService.mAppTransition.getAppStackClipMode(), appStackClipMode, true /* isAppAnimation */), mService.mSurfaceAnimationRunner); if (a.getZAdjustment() == Animation.ZORDER_TOP) { Loading Loading @@ -1858,6 +1882,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree @Override public void onAnimationLeashDestroyed(Transaction t) { super.onAnimationLeashDestroyed(t); if (mAnimationBoundsLayer != null) { t.destroy(mAnimationBoundsLayer); mAnimationBoundsLayer = null; } if (mAnimatingAppWindowTokenRegistry != null) { mAnimatingAppWindowTokenRegistry.notifyFinished(this); } Loading Loading @@ -1908,6 +1937,26 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mAnimatingAppWindowTokenRegistry != null) { mAnimatingAppWindowTokenRegistry.notifyStarting(this); } // If the animation needs to be cropped then an animation bounds layer is created as a child // of the pinned stack or animation layer. The leash is then reparented to this new layer. if (mNeedsAnimationBoundsLayer) { final TaskStack stack = getStack(); if (stack == null) { return; } mAnimationBoundsLayer = createAnimationBoundsLayer(t); // Set clip rect to stack bounds. mTmpRect.setEmpty(); stack.getBounds(mTmpRect); // Crop to stack bounds. t.setWindowCrop(mAnimationBoundsLayer, mTmpRect); // Reparent leash to animation bounds layer. t.reparent(leash, mAnimationBoundsLayer.getHandle()); } } /** Loading @@ -1927,6 +1976,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mTransit = TRANSIT_UNSET; mTransitFlags = 0; mNeedsZBoost = false; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "AppWindowToken"); Loading services/core/java/com/android/server/wm/WindowAnimationSpec.java +1 −7 Original line number Diff line number Diff line Loading @@ -99,13 +99,7 @@ public class WindowAnimationSpec implements AnimationSpec { tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y); t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats); t.setAlpha(leash, tmp.transformation.getAlpha()); if (mStackClipMode == STACK_CLIP_NONE) { t.setWindowCrop(leash, tmp.transformation.getClipRect()); } else if (mStackClipMode == STACK_CLIP_AFTER_ANIM) { mTmpRect.set(mStackBounds); // Offset stack bounds to stack position so the final crop is in screen space. mTmpRect.offsetTo(mPosition.x, mPosition.y); t.setFinalCrop(leash, mTmpRect); if (mStackClipMode == STACK_CLIP_NONE || mStackClipMode == STACK_CLIP_AFTER_ANIM) { t.setWindowCrop(leash, tmp.transformation.getClipRect()); } else { mTmpRect.set(mStackBounds); Loading services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java 0 → 100644 +118 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.SurfaceControl.Transaction; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.SurfaceControl; import com.android.server.wm.WindowTestUtils.TestAppWindowToken; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * Animation related tests for the {@link AppWindowToken} class. * * Build/Install/Run: * atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenAnimationTests */ @SmallTest @RunWith(AndroidJUnit4.class) public class AppWindowTokenAnimationTests extends WindowTestsBase { private TestAppWindowToken mToken; @Mock private Transaction mTransaction; @Mock private AnimationAdapter mSpec; @Override public void setUp() throws Exception { super.setUp(); MockitoAnnotations.initMocks(this); mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); mToken.setPendingTransaction(mTransaction); } @Test public void clipAfterAnim_boundsLayerIsCreated() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); verify(mTransaction).reparent(eq(mToken.getSurfaceControl()), eq(mToken.mSurfaceAnimator.mLeash.getHandle())); verify(mTransaction).reparent(eq(mToken.mSurfaceAnimator.mLeash), eq(mToken.mAnimationBoundsLayer.getHandle())); } @Test public void clipAfterAnim_boundsLayerIsDestroyed() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash; final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( SurfaceAnimator.OnAnimationFinishedCallback.class); verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); callbackCaptor.getValue().onAnimationFinished(mSpec); verify(mTransaction).destroy(eq(leash)); verify(mTransaction).destroy(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @Test public void clipAfterAnimCancelled_boundsLayerIsDestroyed() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash; final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; mToken.mSurfaceAnimator.cancelAnimation(); verify(mTransaction).destroy(eq(leash)); verify(mTransaction).destroy(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @Test public void clipNoneAnim_boundsLayerIsNotCreated() throws Exception { mToken.mNeedsAnimationBoundsLayer = false; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); verify(mTransaction).reparent(eq(mToken.getSurfaceControl()), eq(mToken.mSurfaceAnimator.mLeash.getHandle())); assertThat(mToken.mAnimationBoundsLayer).isNull(); } } services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java +0 −5 Original line number Diff line number Diff line Loading @@ -70,8 +70,6 @@ public class WindowAnimationSpecTest { true /* isAppAnimation */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); verify(mTransaction).setFinalCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(mStackBounds))); } @Test Loading @@ -83,9 +81,6 @@ public class WindowAnimationSpecTest { true /* isAppAnimation */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); verify(mTransaction).setFinalCrop(eq(mSurfaceControl), argThat(rect -> rect.left == 20 && rect.top == 40 && rect.right == 30 && rect.bottom == 50)); } @Test Loading services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +14 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.os.Binder; import android.os.IBinder; import android.view.IApplicationToken; import android.view.IWindow; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.WindowManager; import static android.app.AppOpsManager.OP_NONE; Loading Loading @@ -113,6 +115,7 @@ public class WindowTestUtils { /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */ public static class TestAppWindowToken extends AppWindowToken { boolean mOnTop = false; private Transaction mPendingTransactionOverride; private TestAppWindowToken(DisplayContent dc) { super(dc.mService, new IApplicationToken.Stub() { Loading Loading @@ -158,6 +161,17 @@ public class WindowTestUtils { boolean isOnTop() { return mOnTop; } void setPendingTransaction(Transaction transaction) { mPendingTransactionOverride = transaction; } @Override public Transaction getPendingTransaction() { return mPendingTransactionOverride == null ? super.getPendingTransaction() : mPendingTransactionOverride; } } static TestWindowToken createTestWindowToken(int type, DisplayContent dc) { Loading Loading
services/core/java/com/android/server/wm/AppWindowToken.java +51 −1 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED; import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW; import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL; import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import android.annotation.CallSuper; import android.app.Activity; Loading Loading @@ -264,6 +265,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree */ private boolean mWillCloseOrEnterPip; /** Layer used to constrain the animation to a token's stack bounds. */ SurfaceControl mAnimationBoundsLayer; /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */ boolean mNeedsAnimationBoundsLayer; AppWindowToken(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, Loading Loading @@ -1720,6 +1727,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation; } /** * Creates a layer to apply crop to an animation. */ private SurfaceControl createAnimationBoundsLayer(Transaction t) { if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) Slog.i(TAG, "Creating animation bounds layer"); final SurfaceControl.Builder builder = makeAnimationLeash() .setParent(getAnimationLeashParent()) .setName(getSurfaceControl() + " - animation-bounds") .setSize(getSurfaceWidth(), getSurfaceHeight()); final SurfaceControl boundsLayer = builder.build(); t.show(boundsLayer); return boundsLayer; } boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction) { Loading Loading @@ -1753,12 +1774,15 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree adapter = mService.mAppTransition.getRemoteAnimationController() .createAnimationAdapter(this, mTmpPoint, mTmpRect); } else { final int appStackClipMode = mService.mAppTransition.getAppStackClipMode(); mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM); final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); if (a != null) { adapter = new LocalAnimationAdapter( new WindowAnimationSpec(a, mTmpPoint, mTmpRect, mService.mAppTransition.canSkipFirstFrame(), mService.mAppTransition.getAppStackClipMode(), appStackClipMode, true /* isAppAnimation */), mService.mSurfaceAnimationRunner); if (a.getZAdjustment() == Animation.ZORDER_TOP) { Loading Loading @@ -1858,6 +1882,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree @Override public void onAnimationLeashDestroyed(Transaction t) { super.onAnimationLeashDestroyed(t); if (mAnimationBoundsLayer != null) { t.destroy(mAnimationBoundsLayer); mAnimationBoundsLayer = null; } if (mAnimatingAppWindowTokenRegistry != null) { mAnimatingAppWindowTokenRegistry.notifyFinished(this); } Loading Loading @@ -1908,6 +1937,26 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (mAnimatingAppWindowTokenRegistry != null) { mAnimatingAppWindowTokenRegistry.notifyStarting(this); } // If the animation needs to be cropped then an animation bounds layer is created as a child // of the pinned stack or animation layer. The leash is then reparented to this new layer. if (mNeedsAnimationBoundsLayer) { final TaskStack stack = getStack(); if (stack == null) { return; } mAnimationBoundsLayer = createAnimationBoundsLayer(t); // Set clip rect to stack bounds. mTmpRect.setEmpty(); stack.getBounds(mTmpRect); // Crop to stack bounds. t.setWindowCrop(mAnimationBoundsLayer, mTmpRect); // Reparent leash to animation bounds layer. t.reparent(leash, mAnimationBoundsLayer.getHandle()); } } /** Loading @@ -1927,6 +1976,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mTransit = TRANSIT_UNSET; mTransitFlags = 0; mNeedsZBoost = false; mNeedsAnimationBoundsLayer = false; setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "AppWindowToken"); Loading
services/core/java/com/android/server/wm/WindowAnimationSpec.java +1 −7 Original line number Diff line number Diff line Loading @@ -99,13 +99,7 @@ public class WindowAnimationSpec implements AnimationSpec { tmp.transformation.getMatrix().postTranslate(mPosition.x, mPosition.y); t.setMatrix(leash, tmp.transformation.getMatrix(), tmp.floats); t.setAlpha(leash, tmp.transformation.getAlpha()); if (mStackClipMode == STACK_CLIP_NONE) { t.setWindowCrop(leash, tmp.transformation.getClipRect()); } else if (mStackClipMode == STACK_CLIP_AFTER_ANIM) { mTmpRect.set(mStackBounds); // Offset stack bounds to stack position so the final crop is in screen space. mTmpRect.offsetTo(mPosition.x, mPosition.y); t.setFinalCrop(leash, mTmpRect); if (mStackClipMode == STACK_CLIP_NONE || mStackClipMode == STACK_CLIP_AFTER_ANIM) { t.setWindowCrop(leash, tmp.transformation.getClipRect()); } else { mTmpRect.set(mStackBounds); Loading
services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java 0 → 100644 +118 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.SurfaceControl.Transaction; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.SurfaceControl; import com.android.server.wm.WindowTestUtils.TestAppWindowToken; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** * Animation related tests for the {@link AppWindowToken} class. * * Build/Install/Run: * atest FrameworksServicesTests:com.android.server.wm.AppWindowTokenAnimationTests */ @SmallTest @RunWith(AndroidJUnit4.class) public class AppWindowTokenAnimationTests extends WindowTestsBase { private TestAppWindowToken mToken; @Mock private Transaction mTransaction; @Mock private AnimationAdapter mSpec; @Override public void setUp() throws Exception { super.setUp(); MockitoAnnotations.initMocks(this); mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); mToken.setPendingTransaction(mTransaction); } @Test public void clipAfterAnim_boundsLayerIsCreated() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); verify(mTransaction).reparent(eq(mToken.getSurfaceControl()), eq(mToken.mSurfaceAnimator.mLeash.getHandle())); verify(mTransaction).reparent(eq(mToken.mSurfaceAnimator.mLeash), eq(mToken.mAnimationBoundsLayer.getHandle())); } @Test public void clipAfterAnim_boundsLayerIsDestroyed() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash; final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( SurfaceAnimator.OnAnimationFinishedCallback.class); verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); callbackCaptor.getValue().onAnimationFinished(mSpec); verify(mTransaction).destroy(eq(leash)); verify(mTransaction).destroy(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @Test public void clipAfterAnimCancelled_boundsLayerIsDestroyed() throws Exception { mToken.mNeedsAnimationBoundsLayer = true; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); final SurfaceControl leash = mToken.mSurfaceAnimator.mLeash; final SurfaceControl animationBoundsLayer = mToken.mAnimationBoundsLayer; mToken.mSurfaceAnimator.cancelAnimation(); verify(mTransaction).destroy(eq(leash)); verify(mTransaction).destroy(eq(animationBoundsLayer)); assertThat(mToken.mNeedsAnimationBoundsLayer).isFalse(); } @Test public void clipNoneAnim_boundsLayerIsNotCreated() throws Exception { mToken.mNeedsAnimationBoundsLayer = false; mToken.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); verify(mTransaction).reparent(eq(mToken.getSurfaceControl()), eq(mToken.mSurfaceAnimator.mLeash.getHandle())); assertThat(mToken.mAnimationBoundsLayer).isNull(); } }
services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java +0 −5 Original line number Diff line number Diff line Loading @@ -70,8 +70,6 @@ public class WindowAnimationSpecTest { true /* isAppAnimation */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); verify(mTransaction).setFinalCrop(eq(mSurfaceControl), argThat(rect -> rect.equals(mStackBounds))); } @Test Loading @@ -83,9 +81,6 @@ public class WindowAnimationSpecTest { true /* isAppAnimation */); windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0); verify(mTransaction).setWindowCrop(eq(mSurfaceControl), argThat(Rect::isEmpty)); verify(mTransaction).setFinalCrop(eq(mSurfaceControl), argThat(rect -> rect.left == 20 && rect.top == 40 && rect.right == 30 && rect.bottom == 50)); } @Test Loading
services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +14 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.os.Binder; import android.os.IBinder; import android.view.IApplicationToken; import android.view.IWindow; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.WindowManager; import static android.app.AppOpsManager.OP_NONE; Loading Loading @@ -113,6 +115,7 @@ public class WindowTestUtils { /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */ public static class TestAppWindowToken extends AppWindowToken { boolean mOnTop = false; private Transaction mPendingTransactionOverride; private TestAppWindowToken(DisplayContent dc) { super(dc.mService, new IApplicationToken.Stub() { Loading Loading @@ -158,6 +161,17 @@ public class WindowTestUtils { boolean isOnTop() { return mOnTop; } void setPendingTransaction(Transaction transaction) { mPendingTransactionOverride = transaction; } @Override public Transaction getPendingTransaction() { return mPendingTransactionOverride == null ? super.getPendingTransaction() : mPendingTransactionOverride; } } static TestWindowToken createTestWindowToken(int type, DisplayContent dc) { Loading