Merge "Set TaskFragment surface window crop" into sc-v2-dev am: b739e83401
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15933062 Change-Id: I9158d9001bad8da4b4081c02cec9a64fe07b314d
This commit is contained in:
@@ -480,7 +480,6 @@ class Task extends TaskFragment {
|
|||||||
|
|
||||||
private Dimmer mDimmer = new Dimmer(this);
|
private Dimmer mDimmer = new Dimmer(this);
|
||||||
private final Rect mTmpDimBoundsRect = new Rect();
|
private final Rect mTmpDimBoundsRect = new Rect();
|
||||||
private final Point mLastSurfaceSize = new Point();
|
|
||||||
|
|
||||||
/** @see #setCanAffectSystemUiFlags */
|
/** @see #setCanAffectSystemUiFlags */
|
||||||
private boolean mCanAffectSystemUiFlags = true;
|
private boolean mCanAffectSystemUiFlags = true;
|
||||||
|
|||||||
@@ -240,6 +240,8 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
|||||||
*/
|
*/
|
||||||
private int mTaskFragmentOrganizerPid = ActivityRecord.INVALID_PID;
|
private int mTaskFragmentOrganizerPid = ActivityRecord.INVALID_PID;
|
||||||
|
|
||||||
|
final Point mLastSurfaceSize = new Point();
|
||||||
|
|
||||||
private final Rect mTmpInsets = new Rect();
|
private final Rect mTmpInsets = new Rect();
|
||||||
private final Rect mTmpBounds = new Rect();
|
private final Rect mTmpBounds = new Rect();
|
||||||
private final Rect mTmpFullBounds = new Rect();
|
private final Rect mTmpFullBounds = new Rect();
|
||||||
@@ -1654,6 +1656,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
void onChildPositionChanged(WindowContainer child) {
|
void onChildPositionChanged(WindowContainer child) {
|
||||||
super.onChildPositionChanged(child);
|
super.onChildPositionChanged(child);
|
||||||
|
|
||||||
@@ -2049,14 +2052,58 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
|||||||
if (shouldStartChangeTransition(mTmpPrevBounds)) {
|
if (shouldStartChangeTransition(mTmpPrevBounds)) {
|
||||||
initializeChangeTransition(mTmpPrevBounds);
|
initializeChangeTransition(mTmpPrevBounds);
|
||||||
} else if (mTaskFragmentOrganizer != null) {
|
} else if (mTaskFragmentOrganizer != null) {
|
||||||
// Update the surface position here instead of in the organizer so that we can make sure
|
// Update the surface here instead of in the organizer so that we can make sure
|
||||||
// it can be synced with the surface freezer.
|
// it can be synced with the surface freezer.
|
||||||
updateSurfacePosition(getSyncTransaction());
|
final SurfaceControl.Transaction t = getSyncTransaction();
|
||||||
|
updateSurfacePosition(t);
|
||||||
|
updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTaskFragmentInfoChanged();
|
sendTaskFragmentInfoChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Updates the surface size so that the sub windows cannot be shown out of bounds. */
|
||||||
|
private void updateOrganizedTaskFragmentSurfaceSize(SurfaceControl.Transaction t,
|
||||||
|
boolean forceUpdate) {
|
||||||
|
if (mTaskFragmentOrganizer == null) {
|
||||||
|
// We only want to update for organized TaskFragment. Task will handle itself.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rect bounds = getBounds();
|
||||||
|
final int width = bounds.width();
|
||||||
|
final int height = bounds.height();
|
||||||
|
if (!forceUpdate && width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t.setWindowCrop(mSurfaceControl, width, height);
|
||||||
|
mLastSurfaceSize.set(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationLeashCreated(SurfaceControl.Transaction t, SurfaceControl leash) {
|
||||||
|
super.onAnimationLeashCreated(t, leash);
|
||||||
|
// Reset surface bounds for animation. It will be taken care by the animation leash, and
|
||||||
|
// reset again onAnimationLeashLost.
|
||||||
|
if (mTaskFragmentOrganizer != null
|
||||||
|
&& (mLastSurfaceSize.x != 0 || mLastSurfaceSize.y != 0)) {
|
||||||
|
t.setWindowCrop(mSurfaceControl, 0, 0);
|
||||||
|
mLastSurfaceSize.set(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAnimationLeashLost(SurfaceControl.Transaction t) {
|
||||||
|
super.onAnimationLeashLost(t);
|
||||||
|
// Update the surface bounds after animation.
|
||||||
|
if (mTaskFragmentOrganizer != null) {
|
||||||
|
updateOrganizedTaskFragmentSurfaceSize(t, true /* forceUpdate */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */
|
/** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */
|
||||||
private boolean shouldStartChangeTransition(Rect startBounds) {
|
private boolean shouldStartChangeTransition(Rect startBounds) {
|
||||||
if (mWmService.mDisableTransitionAnimation
|
if (mWmService.mDisableTransitionAnimation
|
||||||
@@ -2075,9 +2122,14 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
|||||||
@Override
|
@Override
|
||||||
void setSurfaceControl(SurfaceControl sc) {
|
void setSurfaceControl(SurfaceControl sc) {
|
||||||
super.setSurfaceControl(sc);
|
super.setSurfaceControl(sc);
|
||||||
// If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
|
if (mTaskFragmentOrganizer != null) {
|
||||||
// emit the callbacks now.
|
final SurfaceControl.Transaction t = getSyncTransaction();
|
||||||
sendTaskFragmentAppeared();
|
updateSurfacePosition(t);
|
||||||
|
updateOrganizedTaskFragmentSurfaceSize(t, false /* forceUpdate */);
|
||||||
|
// If the TaskFragmentOrganizer was set before we created the SurfaceControl, we need to
|
||||||
|
// emit the callbacks now.
|
||||||
|
sendTaskFragmentAppeared();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendTaskFragmentInfoChanged() {
|
void sendTaskFragmentInfoChanged() {
|
||||||
|
|||||||
@@ -3159,7 +3159,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
|
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
|
||||||
void updateSurfacePosition(Transaction t) {
|
void updateSurfacePosition(Transaction t) {
|
||||||
if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) {
|
if (mSurfaceControl == null || mSurfaceAnimator.hasLeash() || mSurfaceFreezer.hasLeash()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.doReturn;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.view.SurfaceControl;
|
||||||
|
import android.window.ITaskFragmentOrganizer;
|
||||||
|
import android.window.TaskFragmentOrganizer;
|
||||||
|
|
||||||
|
import androidx.test.filters.MediumTest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test class for {@link TaskFragment}.
|
||||||
|
*
|
||||||
|
* Build/Install/Run:
|
||||||
|
* atest WmTests:TaskFragmentTest
|
||||||
|
*/
|
||||||
|
@MediumTest
|
||||||
|
@Presubmit
|
||||||
|
@RunWith(WindowTestRunner.class)
|
||||||
|
public class TaskFragmentTest extends WindowTestsBase {
|
||||||
|
|
||||||
|
private TaskFragmentOrganizer mOrganizer;
|
||||||
|
private TaskFragment mTaskFragment;
|
||||||
|
private SurfaceControl mLeash;
|
||||||
|
@Mock
|
||||||
|
private SurfaceControl.Transaction mTransaction;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mOrganizer = new TaskFragmentOrganizer(Runnable::run);
|
||||||
|
final ITaskFragmentOrganizer iOrganizer =
|
||||||
|
ITaskFragmentOrganizer.Stub.asInterface(mOrganizer.getOrganizerToken().asBinder());
|
||||||
|
mAtm.mWindowOrganizerController.mTaskFragmentOrganizerController
|
||||||
|
.registerOrganizer(iOrganizer);
|
||||||
|
mTaskFragment = new TaskFragmentBuilder(mAtm)
|
||||||
|
.setCreateParentTask()
|
||||||
|
.setOrganizer(mOrganizer)
|
||||||
|
.build();
|
||||||
|
mLeash = mTaskFragment.getSurfaceControl();
|
||||||
|
spyOn(mTaskFragment);
|
||||||
|
doReturn(mTransaction).when(mTaskFragment).getSyncTransaction();
|
||||||
|
doReturn(mTransaction).when(mTaskFragment).getPendingTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnConfigurationChanged_updateSurface() {
|
||||||
|
final Rect bounds = new Rect(100, 100, 1100, 1100);
|
||||||
|
mTaskFragment.setBounds(bounds);
|
||||||
|
|
||||||
|
verify(mTransaction).setPosition(mLeash, 100, 100);
|
||||||
|
verify(mTransaction).setWindowCrop(mLeash, 1000, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStartChangeTransition_resetSurface() {
|
||||||
|
final Rect startBounds = new Rect(0, 0, 1000, 1000);
|
||||||
|
final Rect endBounds = new Rect(500, 500, 1000, 1000);
|
||||||
|
mTaskFragment.setBounds(startBounds);
|
||||||
|
doReturn(true).when(mTaskFragment).isVisible();
|
||||||
|
|
||||||
|
clearInvocations(mTransaction);
|
||||||
|
mTaskFragment.setBounds(endBounds);
|
||||||
|
|
||||||
|
// Surface reset when prepare transition.
|
||||||
|
verify(mTaskFragment).initializeChangeTransition(startBounds);
|
||||||
|
verify(mTransaction).setPosition(mLeash, 0, 0);
|
||||||
|
verify(mTransaction).setWindowCrop(mLeash, 0, 0);
|
||||||
|
|
||||||
|
clearInvocations(mTransaction);
|
||||||
|
mTaskFragment.mSurfaceFreezer.unfreeze(mTransaction);
|
||||||
|
|
||||||
|
// Update surface after animation.
|
||||||
|
verify(mTransaction).setPosition(mLeash, 500, 500);
|
||||||
|
verify(mTransaction).setWindowCrop(mLeash, 500, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user