blob: 1d92a48c25fda82467d04ac4b6fa9a608bc1ef30 [file] [log] [blame]
/*
* Copyright (C) 2020 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.wm.shell.onehanded;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT;
import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.DisplayAreaAppearedInfo;
import android.window.DisplayAreaInfo;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.ShellExecutor;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
static final int DISPLAYAREA_INFO_COUNT = 3;
static final int DISPLAY_WIDTH = 1000;
static final int DISPLAY_HEIGHT = 1000;
DisplayAreaInfo mDisplayAreaInfo;
Display mDisplay;
DisplayLayout mDisplayLayout;
OneHandedDisplayAreaOrganizer mSpiedDisplayAreaOrganizer;
OneHandedTutorialHandler mTutorialHandler;
OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator;
WindowContainerToken mToken;
SurfaceControl mLeash;
TestableLooper mTestableLooper;
@Mock
IWindowContainerToken mMockRealToken;
@Mock
OneHandedAnimationController mMockAnimationController;
@Mock
OneHandedAnimationController.OneHandedTransitionAnimator mMockAnimator;
@Mock
OneHandedSurfaceTransactionHelper mMockSurfaceTransactionHelper;
@Mock
DisplayController mMockDisplayController;
@Mock
SurfaceControl mMockLeash;
@Mock
WindowContainerTransaction mMockWindowContainerTransaction;
@Mock
OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
@Mock
ShellExecutor mMockShellMainExecutor;
@Mock
OneHandedSettingsUtil mMockSettingsUitl;
List<DisplayAreaAppearedInfo> mDisplayAreaAppearedInfoList = new ArrayList<>();
final boolean mDefaultEnabled = true;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
Binder binder = new Binder();
doReturn(binder).when(mMockRealToken).asBinder();
mToken = new WindowContainerToken(mMockRealToken);
mLeash = new SurfaceControl();
mDisplay = mContext.getDisplay();
mDisplayLayout = new DisplayLayout(mContext, mDisplay);
mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY, FEATURE_ONE_HANDED);
mDisplayAreaInfo.configuration.orientation = Configuration.ORIENTATION_PORTRAIT;
when(mMockAnimationController.getAnimator(any(), any(), anyFloat(), anyFloat(),
any())).thenReturn(
null);
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
when(mMockSurfaceTransactionHelper.translate(any(), any(), anyFloat())).thenReturn(
mMockSurfaceTransactionHelper);
when(mMockSurfaceTransactionHelper.crop(any(), any(), any())).thenReturn(
mMockSurfaceTransactionHelper);
when(mMockSurfaceTransactionHelper.round(any(), any())).thenReturn(
mMockSurfaceTransactionHelper);
when(mMockAnimator.isRunning()).thenReturn(true);
when(mMockAnimator.setDuration(anyInt())).thenReturn(mFakeAnimator);
when(mMockAnimator.addOneHandedAnimationCallback(any())).thenReturn(mFakeAnimator);
when(mMockAnimator.setTransitionDirection(anyInt())).thenReturn(mFakeAnimator);
when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH);
when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT);
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
mDefaultEnabled);
mSpiedDisplayAreaOrganizer = spy(new OneHandedDisplayAreaOrganizer(mContext,
mDisplayLayout,
mMockSettingsUitl,
mMockAnimationController,
mTutorialHandler,
mMockBackgroundOrganizer,
mMockShellMainExecutor));
for (int i = 0; i < DISPLAYAREA_INFO_COUNT; i++) {
mDisplayAreaAppearedInfoList.add(getDummyDisplayAreaInfo());
}
doReturn(mDisplayAreaAppearedInfoList).when(mSpiedDisplayAreaOrganizer).registerOrganizer(
FEATURE_ONE_HANDED);
}
private DisplayAreaAppearedInfo getDummyDisplayAreaInfo() {
return new DisplayAreaAppearedInfo(mDisplayAreaInfo, mMockLeash);
}
@Test
public void testRegisterDisplayAreaOrganizer() {
assertThat(mSpiedDisplayAreaOrganizer.registerOrganizer(FEATURE_ONE_HANDED)).isNotNull();
}
@Test
public void testOnDisplayAreaAppeared() {
mDisplayAreaAppearedInfoList.forEach(
(info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaAppeared(
info.getDisplayAreaInfo(),
info.getLeash()));
verify(mMockAnimationController, never()).getAnimator(any(), any(), anyFloat(), anyFloat(),
any());
}
@Test
public void testOnDisplayAreaVanished() {
mDisplayAreaAppearedInfoList.forEach(
(info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaAppeared(
info.getDisplayAreaInfo(),
info.getLeash()));
mDisplayAreaAppearedInfoList.forEach(
(info) -> mSpiedDisplayAreaOrganizer.onDisplayAreaVanished(
info.getDisplayAreaInfo()));
verify(mSpiedDisplayAreaOrganizer, times(DISPLAYAREA_INFO_COUNT)).onDisplayAreaVanished(
any());
}
@Test
public void testRotation_portrait_0_to_landscape_90() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 0 -> 90
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_0_to_seascape_270() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 0 -> 270
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_180_to_landscape_90() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 180 -> 90
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_180_to_seascape_270() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 180 -> 270
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_landscape_90_to_portrait_0() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 90 -> 0
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_landscape_90_to_portrait_180() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 90 -> 180
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_seascape_270_to_portrait_0() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 270 -> 0
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_seascape_270_to_portrait_180() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 270 -> 180
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_0_to_portrait_0() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 0 -> 0
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_0_to_portrait_180() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 0 -> 180
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_180_to_portrait_180() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 180 -> 180
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_180,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_portrait_180_to_portrait_0() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 180 -> 0
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_0,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_landscape_90_to_landscape_90() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 90 -> 90
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_landscape_90_to_seascape_270() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 90 -> 270
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_90);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_seascape_270_to_seascape_270() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 270 -> 270
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_270,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
}
@Test
public void testRotation_seascape_270_to_landscape_90() {
when(mMockLeash.isValid()).thenReturn(false);
// Rotate 270 -> 90
mDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_270);
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
mSpiedDisplayAreaOrganizer.onRotateDisplay(mContext, Surface.ROTATION_90,
mMockWindowContainerTransaction);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
verify(mSpiedDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
}
@Test
public void testTriggerOffset() {
final Rect testBounds = mSpiedDisplayAreaOrganizer.getLastDisplayBounds();
final int offset = 100;
testBounds.offsetTo(0, offset);
mSpiedDisplayAreaOrganizer.finishOffset(offset, TRANSITION_DIRECTION_TRIGGER);
assertThat(mSpiedDisplayAreaOrganizer.getLastDisplayBounds()).isEqualTo(testBounds);
}
@Test
public void testExitOffsetToZero() {
final Rect testBounds = mSpiedDisplayAreaOrganizer.getLastDisplayBounds();
final int offset = 100;
mSpiedDisplayAreaOrganizer.finishOffset(offset, TRANSITION_DIRECTION_TRIGGER);
mSpiedDisplayAreaOrganizer.finishOffset(0, TRANSITION_DIRECTION_EXIT);
assertThat(mSpiedDisplayAreaOrganizer.getLastDisplayBounds()).isEqualTo(testBounds);
}
@Test
public void testExit_must_resetWindowsOffset() {
mSpiedDisplayAreaOrganizer.finishOffset(0, TRANSITION_DIRECTION_EXIT);
verify(mSpiedDisplayAreaOrganizer).resetWindowsOffset();
}
@Test
public void testTrigger_not_resetWindowsOffset() {
mSpiedDisplayAreaOrganizer.finishOffset(0, TRANSITION_DIRECTION_TRIGGER);
verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset();
}
@Test
public void testDisplayArea_notReadyForTransition() {
OneHandedDisplayAreaOrganizer testSpiedDisplayAreaOrganizer = spy(
new OneHandedDisplayAreaOrganizer(mContext,
mDisplayLayout,
mMockSettingsUitl,
mMockAnimationController,
mTutorialHandler,
mMockBackgroundOrganizer,
mMockShellMainExecutor));
assertThat(testSpiedDisplayAreaOrganizer.isReady()).isFalse();
}
@Test
public void testDisplayArea_setDisplayLayout_should_updateDisplayBounds() {
mSpiedDisplayAreaOrganizer.setDisplayLayout(mDisplayLayout);
verify(mSpiedDisplayAreaOrganizer).updateDisplayBounds();
}
}