Do not hidde action buttons on FixedLandscape

Also, I moved some of the boolean expressions to a method in the
rotation handler to avoid repeating code and to make the expressions
more legible.

Bug: 401483343
Flag: com.android.launcher3.one_grid_specs
Test: RecentOrientedStateTest
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:0a7bf1db572262d3263f623a1a41fe75076858e4)
Merged-In: I84c1a6e90ede827fd93ec44c3937acaf45f02413
Change-Id: I84c1a6e90ede827fd93ec44c3937acaf45f02413
This commit is contained in:
Sebastian Franco
2025-06-02 17:55:22 -05:00
committed by Android Build Coastguard Worker
parent 8150c5e116
commit 0579ceb4e4
5 changed files with 347 additions and 264 deletions

View File

@@ -1,166 +0,0 @@
/*
* Copyright (C) 2025 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.quickstep.util
import android.view.Surface
import android.view.Surface.ROTATION_0
import android.view.Surface.ROTATION_180
import android.view.Surface.ROTATION_90
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.quickstep.FallbackActivityInterface
import com.android.quickstep.orientation.RecentsPagedOrientationHandler
import com.android.quickstep.orientation.RecentsPagedOrientationHandler.Companion.PORTRAIT
import com.google.common.truth.Truth.assertWithMessage
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
/**
* Test all possible inputs to RecentsOrientedState.updateHandler. It tests all possible
* combinations of rotations and relevant methods (two methods that return boolean values) but it
* only provides the expected result when the final rotation is different from ROTATION_0 for
* simplicity. So any case not shown in resultMap you can assume results in ROTATION_0.
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
class RecentOrientedStateHandlerTests {
data class TestCase(
val recentsRotation: Int,
val displayRotation: Int,
val touchRotation: Int,
val isRotationAllowed: Boolean,
val isFixedLandscape: Boolean,
) {
override fun toString(): String {
return "TestCase(recentsRotation=${Surface.rotationToString(recentsRotation)}, " +
"displayRotation=${Surface.rotationToString(displayRotation)}, " +
"touchRotation=${Surface.rotationToString(touchRotation)}, " +
"isRotationAllowed=$isRotationAllowed, " +
"isFixedLandscape=$isFixedLandscape)"
}
}
private fun runTestCase(testCase: TestCase, expectedHandler: RecentsPagedOrientationHandler) {
val recentOrientedState =
spy(
RecentsOrientedState(
ApplicationProvider.getApplicationContext(),
FallbackActivityInterface.INSTANCE,
) {}
)
whenever(recentOrientedState.isRecentsActivityRotationAllowed).thenAnswer {
testCase.isRotationAllowed
}
whenever(recentOrientedState.isLauncherFixedLandscape).thenAnswer {
testCase.isFixedLandscape
}
recentOrientedState.update(testCase.displayRotation, testCase.touchRotation)
val rotation = recentOrientedState.orientationHandler.rotation
assertWithMessage("$testCase to ${Surface.rotationToString(rotation)},")
.that(rotation)
.isEqualTo(expectedHandler.rotation)
}
@Test
fun `test fixed landscape when device is portrait`() {
runTestCase(
TestCase(
recentsRotation = ROTATION_0,
displayRotation = -1,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
@Test
fun `test fixed landscape when device is landscape`() {
runTestCase(
TestCase(
recentsRotation = ROTATION_90,
displayRotation = -1,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
@Test
fun `test fixed landscape when device is seascape`() {
runTestCase(
TestCase(
recentsRotation = ROTATION_180,
displayRotation = -1,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
@Test
fun `test fixed landscape when device is portrait and display rotation is portrait`() {
runTestCase(
TestCase(
recentsRotation = ROTATION_0,
displayRotation = ROTATION_0,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
@Test
fun `test fixed landscape when device is landscape and display rotation is landscape `() {
runTestCase(
TestCase(
recentsRotation = ROTATION_90,
displayRotation = ROTATION_90,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
@Test
fun `test fixed landscape when device is seascape and display rotation is seascape`() {
runTestCase(
TestCase(
recentsRotation = ROTATION_180,
displayRotation = ROTATION_180,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
PORTRAIT,
)
}
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright (C) 2025 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.quickstep.util
import android.view.Surface
import android.view.Surface.ROTATION_0
import android.view.Surface.ROTATION_180
import android.view.Surface.ROTATION_90
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.quickstep.FallbackActivityInterface
import com.android.quickstep.orientation.RecentsPagedOrientationHandler
import com.android.quickstep.orientation.RecentsPagedOrientationHandler.Companion.PORTRAIT
import com.google.common.truth.Truth.assertWithMessage
import junit.framework.TestCase.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
data class HideActionsTestCase(
val recentsRotation: Int,
val touchRotation: Int,
val isRotationAllowed: Boolean,
val isFixedLandscape: Boolean,
)
data class RotationHandlerTestCase(
val displayRotation: Int,
val touchRotation: Int,
val isRotationAllowed: Boolean,
val isFixedLandscape: Boolean,
) {
override fun toString(): String {
return "TestCase(displayRotation=${Surface.rotationToString(displayRotation)}, " +
"touchRotation=${Surface.rotationToString(touchRotation)}, " +
"isRotationAllowed=$isRotationAllowed, " +
"isFixedLandscape=$isFixedLandscape)"
}
}
/**
* Test all possible inputs to RecentsOrientedState.updateHandler. It tests all possible
* combinations of rotations and relevant methods (two methods that return boolean values) but it
* only provides the expected result when the final rotation is different from ROTATION_0 for
* simplicity. So any case not shown in resultMap you can assume results in ROTATION_0.
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
class RecentOrientedStateTest {
companion object {
const val INVALID_ROTATION = -1
}
private fun createRecentOrientedState() =
spy(
RecentsOrientedState(
ApplicationProvider.getApplicationContext(),
FallbackActivityInterface.INSTANCE,
) {}
)
private fun rotationHandlerTest(
testCase: RotationHandlerTestCase,
expectedHandler: RecentsPagedOrientationHandler,
) {
val recentOrientedState = createRecentOrientedState()
whenever(recentOrientedState.isRecentsActivityRotationAllowed)
.thenReturn(testCase.isRotationAllowed)
whenever(recentOrientedState.isLauncherFixedLandscape).thenReturn(testCase.isFixedLandscape)
recentOrientedState.update(testCase.displayRotation, testCase.touchRotation)
val rotation = recentOrientedState.orientationHandler.rotation
assertWithMessage("$testCase to ${Surface.rotationToString(rotation)},")
.that(rotation)
.isEqualTo(expectedHandler.rotation)
}
private fun shouldHideActionButtonTest(
testCase: HideActionsTestCase,
hideActionButtonsExpected: Boolean,
) {
val recentOrientedState = createRecentOrientedState()
whenever(recentOrientedState.recentsActivityRotation).thenReturn(testCase.recentsRotation)
whenever(recentOrientedState.touchRotation).thenReturn(testCase.touchRotation)
whenever(recentOrientedState.isRecentsActivityRotationAllowed)
.thenReturn(testCase.isRotationAllowed)
whenever(recentOrientedState.isLauncherFixedLandscape).thenReturn(testCase.isFixedLandscape)
val res = recentOrientedState.shouldHideActionButtons()
assertWithMessage(
"Test case $testCase generated $res but should be $hideActionButtonsExpected"
)
.that(res)
.isEqualTo(hideActionButtonsExpected)
}
@Test
fun `stateId changes with flags`() {
val recentOrientedState1 = createRecentOrientedState()
val recentOrientedState2 = createRecentOrientedState()
assertEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState1.setGestureActive(true)
recentOrientedState2.setGestureActive(false)
assertNotEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState2.setGestureActive(true)
assertEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
}
@Test
fun `stateId changes with recents rotation`() {
val recentOrientedState1 = createRecentOrientedState()
val recentOrientedState2 = createRecentOrientedState()
recentOrientedState1.setRecentsRotation(ROTATION_90)
recentOrientedState2.setRecentsRotation(ROTATION_180)
assertNotEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState2.setRecentsRotation(ROTATION_90)
assertEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
}
@Test
fun `stateId changes with display rotation`() {
val recentOrientedState1 = createRecentOrientedState()
val recentOrientedState2 = createRecentOrientedState()
recentOrientedState1.update(ROTATION_0, ROTATION_90)
recentOrientedState2.update(ROTATION_0, ROTATION_180)
assertNotEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState2.update(ROTATION_90, ROTATION_90)
assertNotEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState2.update(ROTATION_90, ROTATION_0)
assertNotEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
recentOrientedState2.update(ROTATION_0, ROTATION_90)
assertEquals(recentOrientedState1.stateId, recentOrientedState2.stateId)
}
@Test
fun `rotation handler test fixed landscape when device is portrait`() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = INVALID_ROTATION,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `rotation handler test fixed landscape when device is landscape`() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = INVALID_ROTATION,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `rotation handler test fixed landscape when device is seascape`() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = INVALID_ROTATION,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `rotation handler test fixed landscape when device is portrait and display rotation is portrait`() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = ROTATION_0,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `rotation handler test fixed landscape when device is landscape and display rotation is landscape `() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = ROTATION_90,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `rotation handler test fixed landscape when device is seascape and display rotation is seascape`() {
rotationHandlerTest(
testCase =
RotationHandlerTestCase(
displayRotation = ROTATION_180,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
expectedHandler = PORTRAIT,
)
}
@Test
fun `should hide actions fixed landscape no rotation`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_0,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
hideActionButtonsExpected = false,
)
}
@Test
fun `should hide actions fixed landscape rotation 90`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_90,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = true,
),
hideActionButtonsExpected = false,
)
}
@Test
fun `should hide actions recent rotation 180`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_180,
touchRotation = ROTATION_0,
isRotationAllowed = false,
isFixedLandscape = false,
),
hideActionButtonsExpected = true,
)
}
@Test
fun `should hide actions touch rotation 180`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_0,
touchRotation = ROTATION_180,
isRotationAllowed = false,
isFixedLandscape = false,
),
hideActionButtonsExpected = true,
)
}
@Test
fun `should hide actions rotation allowed`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_90,
touchRotation = ROTATION_180,
isRotationAllowed = true,
isFixedLandscape = false,
),
hideActionButtonsExpected = false,
)
}
@Test
fun `should hide actions fixed landscape rotations and not allowed`() {
shouldHideActionButtonTest(
testCase =
HideActionsTestCase(
recentsRotation = ROTATION_180,
touchRotation = ROTATION_90,
isRotationAllowed = false,
isFixedLandscape = true,
),
hideActionButtonsExpected = false,
)
}
}

View File

@@ -1,90 +0,0 @@
/*
* 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.quickstep.util;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_90;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import android.content.Context;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.quickstep.FallbackActivityInterface;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Tests for {@link RecentsOrientedState}
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RecentsOrientedStateTest {
private RecentsOrientedState mR1, mR2;
@Before
public void setup() {
Context context = getApplicationContext();
mR1 = new RecentsOrientedState(context, FallbackActivityInterface.INSTANCE, i -> { });
mR2 = new RecentsOrientedState(context, FallbackActivityInterface.INSTANCE, i -> { });
assertEquals(mR1.getStateId(), mR2.getStateId());
}
@Test
public void stateId_changesWithFlags() {
mR1.setGestureActive(true);
mR2.setGestureActive(false);
assertNotEquals(mR1.getStateId(), mR2.getStateId());
mR2.setGestureActive(true);
assertEquals(mR1.getStateId(), mR2.getStateId());
}
@Test
public void stateId_changesWithRecentsRotation() {
mR1.setRecentsRotation(ROTATION_90);
mR2.setRecentsRotation(ROTATION_180);
assertNotEquals(mR1.getStateId(), mR2.getStateId());
mR2.setRecentsRotation(ROTATION_90);
assertEquals(mR1.getStateId(), mR2.getStateId());
}
@Test
public void stateId_changesWithDisplayRotation() {
mR1.update(ROTATION_0, ROTATION_90);
mR2.update(ROTATION_0, ROTATION_180);
assertNotEquals(mR1.getStateId(), mR2.getStateId());
mR2.update(ROTATION_90, ROTATION_90);
assertNotEquals(mR1.getStateId(), mR2.getStateId());
mR2.update(ROTATION_90, ROTATION_0);
assertNotEquals(mR1.getStateId(), mR2.getStateId());
mR2.update(ROTATION_0, ROTATION_90);
assertEquals(mR1.getStateId(), mR2.getStateId());
}
}