Loading services/core/java/com/android/server/wm/ActivityRecord.java +0 −114 Original line number Diff line number Diff line Loading @@ -46,9 +46,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.admin.DevicePolicyResources.Drawables.Source.PROFILE_SWITCH_ANIMATION; import static android.app.admin.DevicePolicyResources.Drawables.Style.OUTLINE; import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON; import static android.content.Context.CONTEXT_RESTRICTED; import static android.content.Intent.ACTION_MAIN; import static android.content.Intent.CATEGORY_HOME; Loading Loading @@ -189,7 +186,6 @@ import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED; import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED; import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW; import static com.android.server.wm.ActivityRecordProto.STATE; import static com.android.server.wm.ActivityRecordProto.THUMBNAIL; import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT; import static com.android.server.wm.ActivityRecordProto.VISIBLE; import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED; Loading Loading @@ -265,7 +261,6 @@ import android.app.PictureInPictureParams; import android.app.ResultInfo; import android.app.WaitResult; import android.app.WindowConfiguration; import android.app.admin.DevicePolicyManager; import android.app.assist.ActivityId; import android.app.compat.CompatChanges; import android.app.servertransaction.ActivityConfigurationChangeItem; Loading Loading @@ -300,7 +295,6 @@ import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.gui.DropInputMode; import android.hardware.HardwareBuffer; import android.net.Uri; Loading Loading @@ -340,7 +334,6 @@ import android.view.WindowInsets.Type; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.TransitionOldType; import android.view.animation.Animation; import android.window.ActivityWindowInfo; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; Loading Loading @@ -4699,8 +4692,6 @@ final class ActivityRecord extends WindowToken { return true; } // TODO: Transfer thumbnail return false; } Loading Loading @@ -7595,9 +7586,6 @@ final class ActivityRecord extends WindowToken { mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getPendingTransaction()); } } if (mThumbnail != null) { mThumbnail.setShowing(getPendingTransaction(), show); } mLastSurfaceShowing = show; super.prepareSurfaces(); } Loading @@ -7609,84 +7597,6 @@ final class ActivityRecord extends WindowToken { return mLastSurfaceShowing; } void attachThumbnailAnimation() { if (!isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { return; } final HardwareBuffer thumbnailHeader = getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task); if (thumbnailHeader == null) { ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task); return; } clearThumbnail(); final Transaction transaction = getAnimatingContainer().getPendingTransaction(); mThumbnail = new WindowContainerThumbnail(transaction, getAnimatingContainer(), thumbnailHeader); mThumbnail.startAnimation(transaction, loadThumbnailAnimation(thumbnailHeader)); } /** * Attaches a surface with a thumbnail for the * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation. */ void attachCrossProfileAppsThumbnailAnimation() { if (!isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { return; } clearThumbnail(); final WindowState win = findMainWindow(); if (win == null) { return; } final Rect frame = win.getRelativeFrame(); final Context context = mAtmService.getUiContext(); final Drawable thumbnailDrawable; if (task.mUserId == mWmService.mCurrentUserId) { thumbnailDrawable = context.getDrawable(R.drawable.ic_account_circle); } else { final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); thumbnailDrawable = dpm.getResources().getDrawable( WORK_PROFILE_ICON, OUTLINE, PROFILE_SWITCH_ANIMATION, () -> context.getDrawable(R.drawable.ic_corp_badge)); } final HardwareBuffer thumbnail = getDisplayContent().mAppTransition .createCrossProfileAppsThumbnail(thumbnailDrawable, frame); if (thumbnail == null) { return; } final Transaction transaction = getPendingTransaction(); mThumbnail = new WindowContainerThumbnail(transaction, getTask(), thumbnail); final Animation animation = getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked( frame); mThumbnail.startAnimation(transaction, animation, new Point(frame.left, frame.top)); } private Animation loadThumbnailAnimation(HardwareBuffer thumbnailHeader) { final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); // If this is a multi-window scenario, we use the windows frame as // destination of the thumbnail header animation. If this is a full screen // window scenario, we use the whole display as the target. WindowState win = findMainWindow(); Rect insets; Rect appRect; if (win != null) { insets = win.getInsetsStateWithVisibilityOverride().calculateInsets( win.getFrame(), Type.systemBars(), false /* ignoreVisibility */).toRect(); appRect = new Rect(win.getFrame()); appRect.inset(insets); } else { insets = null; appRect = new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight); } final Configuration displayConfig = mDisplayContent.getConfiguration(); return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked( appRect, insets, thumbnailHeader, task, displayConfig.orientation); } @Override public void onAnimationLeashLost(Transaction t) { super.onAnimationLeashLost(t); Loading @@ -7713,7 +7623,6 @@ final class ActivityRecord extends WindowToken { setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "ActivityRecord"); clearThumbnail(); setClientVisible(isVisible() || mVisibleRequested); getDisplayContent().computeImeTargetIfNeeded(this); Loading @@ -7723,12 +7632,6 @@ final class ActivityRecord extends WindowToken { this, reportedVisible, okToDisplay(), okToAnimate(), isStartingWindowDisplayed()); // clean up thumbnail window if (mThumbnail != null) { mThumbnail.destroy(); mThumbnail = null; } // WindowState.onExitAnimationDone might modify the children list, so make a copy and then // traverse the copy. final ArrayList<WindowState> children = new ArrayList<>(mChildren); Loading Loading @@ -7767,20 +7670,6 @@ final class ActivityRecord extends WindowToken { } } @Override void cancelAnimation() { super.cancelAnimation(); clearThumbnail(); } private void clearThumbnail() { if (mThumbnail == null) { return; } mThumbnail.destroy(); mThumbnail = null; } public @TransitionOldType int getTransit() { return mTransit; } Loading Loading @@ -9726,9 +9615,6 @@ final class ActivityRecord extends WindowToken { proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart()); proto.write(IS_ANIMATING, isAnimating(TRANSITION | PARENTS | CHILDREN, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION)); if (mThumbnail != null){ mThumbnail.dumpDebug(proto, THUMBNAIL); } proto.write(FILLS_PARENT, fillsParent()); proto.write(APP_STOPPED, mAppStopped); proto.write(TRANSLUCENT, !occludesParent()); Loading services/core/java/com/android/server/wm/WindowContainer.java +0 −1 Original line number Diff line number Diff line Loading @@ -302,7 +302,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * This gets used during some open/close transitions as well as during a change transition * where it represents the starting-state snapshot. */ WindowContainerThumbnail mThumbnail; final Point mTmpPoint = new Point(); protected final Rect mTmpRect = new Rect(); final Rect mTmpPrevBounds = new Rect(); Loading services/core/java/com/android/server/wm/WindowContainerThumbnail.javadeleted 100644 → 0 +0 −218 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.view.SurfaceControl.METADATA_OWNER_UID; import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT; import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR; import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Point; import android.hardware.HardwareBuffer; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import android.view.SurfaceControl.Builder; import android.view.SurfaceControl.Transaction; import android.view.animation.Animation; import com.android.internal.protolog.ProtoLog; import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.AnimationType; /** * Represents a surface that is displayed over a subclass of {@link WindowContainer} */ class WindowContainerThumbnail implements Animatable { private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainerThumbnail" : TAG_WM; private final WindowContainer mWindowContainer; private SurfaceControl mSurfaceControl; private final SurfaceAnimator mSurfaceAnimator; private final int mWidth; private final int mHeight; /** * @param t Transaction to create the thumbnail in. * @param container The sub-class of {@link WindowContainer} to associate this thumbnail with. * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with. */ WindowContainerThumbnail(Transaction t, WindowContainer container, HardwareBuffer thumbnailHeader) { this(t, container, thumbnailHeader, null /* animator */); } WindowContainerThumbnail(Transaction t, WindowContainer container, HardwareBuffer thumbnailHeader, SurfaceAnimator animator) { mWindowContainer = container; if (animator != null) { mSurfaceAnimator = animator; } else { // We can't use a delegating constructor since we need to // reference this::onAnimationFinished mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished /* animationFinishedCallback */, container.mWmService); } mWidth = thumbnailHeader.getWidth(); mHeight = thumbnailHeader.getHeight(); // Create a new surface for the thumbnail // TODO: This should be attached as a child to the app token, once the thumbnail animations // use relative coordinates. Once we start animating task we can also consider attaching // this to the task. mSurfaceControl = mWindowContainer.makeChildSurface(mWindowContainer.getTopChild()) .setName("thumbnail anim: " + mWindowContainer.toString()) .setBLASTLayer() .setFormat(PixelFormat.TRANSLUCENT) .setMetadata(METADATA_WINDOW_TYPE, mWindowContainer.getWindowingMode()) .setMetadata(METADATA_OWNER_UID, WindowManagerService.MY_UID) .setCallsite("WindowContainerThumbnail") .build(); ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl); GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(thumbnailHeader); t.setBuffer(mSurfaceControl, graphicBuffer); t.setColorSpace(mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB)); t.show(mSurfaceControl); // We parent the thumbnail to the container, and just place it on top of anything else in // the container. t.setLayer(mSurfaceControl, Integer.MAX_VALUE); } void startAnimation(Transaction t, Animation anim) { startAnimation(t, anim, null /* position */); } void startAnimation(Transaction t, Animation anim, Point position) { anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked()); mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter( new WindowAnimationSpec(anim, position, mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(), mWindowContainer.getDisplayContent().getWindowCornerRadius()), mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); } private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { } void setShowing(Transaction pendingTransaction, boolean show) { // TODO: Not needed anymore once thumbnail is attached to the app. if (show) { pendingTransaction.show(mSurfaceControl); } else { pendingTransaction.hide(mSurfaceControl); } } void destroy() { mSurfaceAnimator.cancelAnimation(); getPendingTransaction().remove(mSurfaceControl); mSurfaceControl = null; } /** * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link * com.android.server.wm.WindowContainerThumbnailProto}. * * @param proto Stream to write the WindowContainerThumbnailProto object to. * @param fieldId Field Id of the WindowContainerThumbnailProto as defined in the parent * message. * @hide */ void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(WIDTH, mWidth); proto.write(HEIGHT, mHeight); if (mSurfaceAnimator.isAnimating()) { mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR); } proto.end(token); } @Override public Transaction getSyncTransaction() { return mWindowContainer.getSyncTransaction(); } @Override public Transaction getPendingTransaction() { return mWindowContainer.getPendingTransaction(); } @Override public void commitPendingTransaction() { mWindowContainer.commitPendingTransaction(); } @Override public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { t.setLayer(leash, Integer.MAX_VALUE); } @Override public void onAnimationLeashLost(Transaction t) { // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail // became visible. t.hide(mSurfaceControl); } @Override public Builder makeAnimationLeash() { return mWindowContainer.makeChildSurface(mWindowContainer.getTopChild()); } @Override public SurfaceControl getSurfaceControl() { return mSurfaceControl; } @Override public SurfaceControl getAnimationLeashParent() { return mWindowContainer.getAnimationLeashParent(); } @Override public SurfaceControl getParentSurfaceControl() { return mWindowContainer.getParentSurfaceControl(); } @Override public int getSurfaceWidth() { return mWidth; } @Override public int getSurfaceHeight() { return mHeight; } } services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.javadeleted 100644 → 0 +0 −65 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import android.hardware.HardwareBuffer; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.testutils.StubTransaction; import org.junit.Test; import org.junit.runner.RunWith; /** * Test class for {@link TaskSnapshotSurface}. * * Build/Install/Run: * atest WmTests:WindowContainerThumbnailTest * */ @SmallTest @Presubmit @RunWith(WindowTestRunner.class) public class WindowContainerThumbnailTest extends WindowTestsBase { private WindowContainerThumbnail buildThumbnail() { final HardwareBuffer buffer = HardwareBuffer.create(1, 1, HardwareBuffer.RGBA_8888, 1, HardwareBuffer.USAGE_CPU_READ_RARELY); final ActivityRecord mockAr = mock(ActivityRecord.class); when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction()); when(mockAr.makeChildSurface(any())).thenReturn(new MockSurfaceControlBuilder()); when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder()); return new WindowContainerThumbnail(new StubTransaction(), mockAr, buffer, mock(SurfaceAnimator.class)); } @Test public void testDestroy_nullsSurface() { final WindowContainerThumbnail t = buildThumbnail(); assertNotNull(t.getSurfaceControl()); t.destroy(); assertNull(t.getSurfaceControl()); } } Loading
services/core/java/com/android/server/wm/ActivityRecord.java +0 −114 Original line number Diff line number Diff line Loading @@ -46,9 +46,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.admin.DevicePolicyResources.Drawables.Source.PROFILE_SWITCH_ANIMATION; import static android.app.admin.DevicePolicyResources.Drawables.Style.OUTLINE; import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON; import static android.content.Context.CONTEXT_RESTRICTED; import static android.content.Intent.ACTION_MAIN; import static android.content.Intent.CATEGORY_HOME; Loading Loading @@ -189,7 +186,6 @@ import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED; import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED; import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW; import static com.android.server.wm.ActivityRecordProto.STATE; import static com.android.server.wm.ActivityRecordProto.THUMBNAIL; import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT; import static com.android.server.wm.ActivityRecordProto.VISIBLE; import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED; Loading Loading @@ -265,7 +261,6 @@ import android.app.PictureInPictureParams; import android.app.ResultInfo; import android.app.WaitResult; import android.app.WindowConfiguration; import android.app.admin.DevicePolicyManager; import android.app.assist.ActivityId; import android.app.compat.CompatChanges; import android.app.servertransaction.ActivityConfigurationChangeItem; Loading Loading @@ -300,7 +295,6 @@ import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.gui.DropInputMode; import android.hardware.HardwareBuffer; import android.net.Uri; Loading Loading @@ -340,7 +334,6 @@ import android.view.WindowInsets.Type; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.TransitionOldType; import android.view.animation.Animation; import android.window.ActivityWindowInfo; import android.window.ITaskFragmentOrganizer; import android.window.RemoteTransition; Loading Loading @@ -4699,8 +4692,6 @@ final class ActivityRecord extends WindowToken { return true; } // TODO: Transfer thumbnail return false; } Loading Loading @@ -7595,9 +7586,6 @@ final class ActivityRecord extends WindowToken { mActivityRecordInputSink.applyChangesToSurfaceIfChanged(getPendingTransaction()); } } if (mThumbnail != null) { mThumbnail.setShowing(getPendingTransaction(), show); } mLastSurfaceShowing = show; super.prepareSurfaces(); } Loading @@ -7609,84 +7597,6 @@ final class ActivityRecord extends WindowToken { return mLastSurfaceShowing; } void attachThumbnailAnimation() { if (!isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { return; } final HardwareBuffer thumbnailHeader = getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task); if (thumbnailHeader == null) { ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task); return; } clearThumbnail(); final Transaction transaction = getAnimatingContainer().getPendingTransaction(); mThumbnail = new WindowContainerThumbnail(transaction, getAnimatingContainer(), thumbnailHeader); mThumbnail.startAnimation(transaction, loadThumbnailAnimation(thumbnailHeader)); } /** * Attaches a surface with a thumbnail for the * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation. */ void attachCrossProfileAppsThumbnailAnimation() { if (!isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION)) { return; } clearThumbnail(); final WindowState win = findMainWindow(); if (win == null) { return; } final Rect frame = win.getRelativeFrame(); final Context context = mAtmService.getUiContext(); final Drawable thumbnailDrawable; if (task.mUserId == mWmService.mCurrentUserId) { thumbnailDrawable = context.getDrawable(R.drawable.ic_account_circle); } else { final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); thumbnailDrawable = dpm.getResources().getDrawable( WORK_PROFILE_ICON, OUTLINE, PROFILE_SWITCH_ANIMATION, () -> context.getDrawable(R.drawable.ic_corp_badge)); } final HardwareBuffer thumbnail = getDisplayContent().mAppTransition .createCrossProfileAppsThumbnail(thumbnailDrawable, frame); if (thumbnail == null) { return; } final Transaction transaction = getPendingTransaction(); mThumbnail = new WindowContainerThumbnail(transaction, getTask(), thumbnail); final Animation animation = getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked( frame); mThumbnail.startAnimation(transaction, animation, new Point(frame.left, frame.top)); } private Animation loadThumbnailAnimation(HardwareBuffer thumbnailHeader) { final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); // If this is a multi-window scenario, we use the windows frame as // destination of the thumbnail header animation. If this is a full screen // window scenario, we use the whole display as the target. WindowState win = findMainWindow(); Rect insets; Rect appRect; if (win != null) { insets = win.getInsetsStateWithVisibilityOverride().calculateInsets( win.getFrame(), Type.systemBars(), false /* ignoreVisibility */).toRect(); appRect = new Rect(win.getFrame()); appRect.inset(insets); } else { insets = null; appRect = new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight); } final Configuration displayConfig = mDisplayContent.getConfiguration(); return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked( appRect, insets, thumbnailHeader, task, displayConfig.orientation); } @Override public void onAnimationLeashLost(Transaction t) { super.onAnimationLeashLost(t); Loading @@ -7713,7 +7623,6 @@ final class ActivityRecord extends WindowToken { setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER, "ActivityRecord"); clearThumbnail(); setClientVisible(isVisible() || mVisibleRequested); getDisplayContent().computeImeTargetIfNeeded(this); Loading @@ -7723,12 +7632,6 @@ final class ActivityRecord extends WindowToken { this, reportedVisible, okToDisplay(), okToAnimate(), isStartingWindowDisplayed()); // clean up thumbnail window if (mThumbnail != null) { mThumbnail.destroy(); mThumbnail = null; } // WindowState.onExitAnimationDone might modify the children list, so make a copy and then // traverse the copy. final ArrayList<WindowState> children = new ArrayList<>(mChildren); Loading Loading @@ -7767,20 +7670,6 @@ final class ActivityRecord extends WindowToken { } } @Override void cancelAnimation() { super.cancelAnimation(); clearThumbnail(); } private void clearThumbnail() { if (mThumbnail == null) { return; } mThumbnail.destroy(); mThumbnail = null; } public @TransitionOldType int getTransit() { return mTransit; } Loading Loading @@ -9726,9 +9615,6 @@ final class ActivityRecord extends WindowToken { proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart()); proto.write(IS_ANIMATING, isAnimating(TRANSITION | PARENTS | CHILDREN, ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_WINDOW_ANIMATION)); if (mThumbnail != null){ mThumbnail.dumpDebug(proto, THUMBNAIL); } proto.write(FILLS_PARENT, fillsParent()); proto.write(APP_STOPPED, mAppStopped); proto.write(TRANSLUCENT, !occludesParent()); Loading
services/core/java/com/android/server/wm/WindowContainer.java +0 −1 Original line number Diff line number Diff line Loading @@ -302,7 +302,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * This gets used during some open/close transitions as well as during a change transition * where it represents the starting-state snapshot. */ WindowContainerThumbnail mThumbnail; final Point mTmpPoint = new Point(); protected final Rect mTmpRect = new Rect(); final Rect mTmpPrevBounds = new Rect(); Loading
services/core/java/com/android/server/wm/WindowContainerThumbnail.javadeleted 100644 → 0 +0 −218 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.view.SurfaceControl.METADATA_OWNER_UID; import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_TRANSACTIONS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT; import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR; import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION; import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; import android.graphics.PixelFormat; import android.graphics.Point; import android.hardware.HardwareBuffer; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl; import android.view.SurfaceControl.Builder; import android.view.SurfaceControl.Transaction; import android.view.animation.Animation; import com.android.internal.protolog.ProtoLog; import com.android.server.wm.SurfaceAnimator.Animatable; import com.android.server.wm.SurfaceAnimator.AnimationType; /** * Represents a surface that is displayed over a subclass of {@link WindowContainer} */ class WindowContainerThumbnail implements Animatable { private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainerThumbnail" : TAG_WM; private final WindowContainer mWindowContainer; private SurfaceControl mSurfaceControl; private final SurfaceAnimator mSurfaceAnimator; private final int mWidth; private final int mHeight; /** * @param t Transaction to create the thumbnail in. * @param container The sub-class of {@link WindowContainer} to associate this thumbnail with. * @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with. */ WindowContainerThumbnail(Transaction t, WindowContainer container, HardwareBuffer thumbnailHeader) { this(t, container, thumbnailHeader, null /* animator */); } WindowContainerThumbnail(Transaction t, WindowContainer container, HardwareBuffer thumbnailHeader, SurfaceAnimator animator) { mWindowContainer = container; if (animator != null) { mSurfaceAnimator = animator; } else { // We can't use a delegating constructor since we need to // reference this::onAnimationFinished mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished /* animationFinishedCallback */, container.mWmService); } mWidth = thumbnailHeader.getWidth(); mHeight = thumbnailHeader.getHeight(); // Create a new surface for the thumbnail // TODO: This should be attached as a child to the app token, once the thumbnail animations // use relative coordinates. Once we start animating task we can also consider attaching // this to the task. mSurfaceControl = mWindowContainer.makeChildSurface(mWindowContainer.getTopChild()) .setName("thumbnail anim: " + mWindowContainer.toString()) .setBLASTLayer() .setFormat(PixelFormat.TRANSLUCENT) .setMetadata(METADATA_WINDOW_TYPE, mWindowContainer.getWindowingMode()) .setMetadata(METADATA_OWNER_UID, WindowManagerService.MY_UID) .setCallsite("WindowContainerThumbnail") .build(); ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl); GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(thumbnailHeader); t.setBuffer(mSurfaceControl, graphicBuffer); t.setColorSpace(mSurfaceControl, ColorSpace.get(ColorSpace.Named.SRGB)); t.show(mSurfaceControl); // We parent the thumbnail to the container, and just place it on top of anything else in // the container. t.setLayer(mSurfaceControl, Integer.MAX_VALUE); } void startAnimation(Transaction t, Animation anim) { startAnimation(t, anim, null /* position */); } void startAnimation(Transaction t, Animation anim, Point position) { anim.restrictDuration(MAX_ANIMATION_DURATION); anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked()); mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter( new WindowAnimationSpec(anim, position, mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(), mWindowContainer.getDisplayContent().getWindowCornerRadius()), mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */, ANIMATION_TYPE_APP_TRANSITION); } private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { } void setShowing(Transaction pendingTransaction, boolean show) { // TODO: Not needed anymore once thumbnail is attached to the app. if (show) { pendingTransaction.show(mSurfaceControl); } else { pendingTransaction.hide(mSurfaceControl); } } void destroy() { mSurfaceAnimator.cancelAnimation(); getPendingTransaction().remove(mSurfaceControl); mSurfaceControl = null; } /** * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link * com.android.server.wm.WindowContainerThumbnailProto}. * * @param proto Stream to write the WindowContainerThumbnailProto object to. * @param fieldId Field Id of the WindowContainerThumbnailProto as defined in the parent * message. * @hide */ void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(WIDTH, mWidth); proto.write(HEIGHT, mHeight); if (mSurfaceAnimator.isAnimating()) { mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR); } proto.end(token); } @Override public Transaction getSyncTransaction() { return mWindowContainer.getSyncTransaction(); } @Override public Transaction getPendingTransaction() { return mWindowContainer.getPendingTransaction(); } @Override public void commitPendingTransaction() { mWindowContainer.commitPendingTransaction(); } @Override public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { t.setLayer(leash, Integer.MAX_VALUE); } @Override public void onAnimationLeashLost(Transaction t) { // TODO: Once attached to app token, we don't need to hide it immediately if thumbnail // became visible. t.hide(mSurfaceControl); } @Override public Builder makeAnimationLeash() { return mWindowContainer.makeChildSurface(mWindowContainer.getTopChild()); } @Override public SurfaceControl getSurfaceControl() { return mSurfaceControl; } @Override public SurfaceControl getAnimationLeashParent() { return mWindowContainer.getAnimationLeashParent(); } @Override public SurfaceControl getParentSurfaceControl() { return mWindowContainer.getParentSurfaceControl(); } @Override public int getSurfaceWidth() { return mWidth; } @Override public int getSurfaceHeight() { return mHeight; } }
services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.javadeleted 100644 → 0 +0 −65 Original line number Diff line number Diff line /* * Copyright (C) 2019 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 com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import android.hardware.HardwareBuffer; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.testutils.StubTransaction; import org.junit.Test; import org.junit.runner.RunWith; /** * Test class for {@link TaskSnapshotSurface}. * * Build/Install/Run: * atest WmTests:WindowContainerThumbnailTest * */ @SmallTest @Presubmit @RunWith(WindowTestRunner.class) public class WindowContainerThumbnailTest extends WindowTestsBase { private WindowContainerThumbnail buildThumbnail() { final HardwareBuffer buffer = HardwareBuffer.create(1, 1, HardwareBuffer.RGBA_8888, 1, HardwareBuffer.USAGE_CPU_READ_RARELY); final ActivityRecord mockAr = mock(ActivityRecord.class); when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction()); when(mockAr.makeChildSurface(any())).thenReturn(new MockSurfaceControlBuilder()); when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder()); return new WindowContainerThumbnail(new StubTransaction(), mockAr, buffer, mock(SurfaceAnimator.class)); } @Test public void testDestroy_nullsSurface() { final WindowContainerThumbnail t = buildThumbnail(); assertNotNull(t.getSurfaceControl()); t.destroy(); assertNull(t.getSurfaceControl()); } }