Merge "Make inline qsb part of grid attrs" into tm-dev

This commit is contained in:
Thales Lima
2022-03-31 08:30:10 +00:00
committed by Android (Google) Code Review
9 changed files with 480 additions and 242 deletions
+12
View File
@@ -342,6 +342,18 @@
<attr name="horizontalMarginTwoPanelLandscape" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginTwoPanelPortrait" format="float"/>
<!-- By default all are false -->
<attr name="inlineQsb" format="integer" >
<!-- Enable on landscape only -->
<flag name="portrait" value="1" />
<!-- Enable on portrait only -->
<flag name="landscape" value="2" />
<!-- Enable on two panel portrait only -->
<flag name="twoPanelPortrait" value="4" />
<!-- Enable on two panel landscape only -->
<flag name="twoPanelLandscape" value="8" />
</attr>
</declare-styleable>
<declare-styleable name="CellLayout">
+18 -14
View File
@@ -16,6 +16,10 @@
package com.android.launcher3;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_DEFAULT;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_LANDSCAPE;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
import static com.android.launcher3.ResourceUtils.pxFromDp;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
@@ -58,7 +62,6 @@ public class DeviceProfile {
// Device properties
public final boolean isTablet;
public final boolean isLargeTablet;
public final boolean isPhone;
public final boolean transposeLayoutWithOrientation;
public final boolean isTwoPanels;
@@ -253,7 +256,6 @@ public class DeviceProfile {
// Determine device posture.
mInfo = info;
isTablet = info.isTablet(windowBounds);
isLargeTablet = info.isLargeTablet(windowBounds);
isPhone = !isTablet;
isTwoPanels = isTablet && useTwoPanels;
isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS;
@@ -278,15 +280,15 @@ public class DeviceProfile {
if (isTwoPanels) {
if (isLandscape) {
mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
mTypeIndex = INDEX_TWO_PANEL_LANDSCAPE;
} else {
mTypeIndex = InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
mTypeIndex = INDEX_TWO_PANEL_PORTRAIT;
}
} else {
if (isLandscape) {
mTypeIndex = InvariantDeviceProfile.INDEX_LANDSCAPE;
mTypeIndex = INDEX_LANDSCAPE;
} else {
mTypeIndex = InvariantDeviceProfile.INDEX_DEFAULT;
mTypeIndex = INDEX_DEFAULT;
}
}
@@ -348,9 +350,12 @@ public class DeviceProfile {
workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
// Whether QSB might be inline in appropriate orientation (landscape).
boolean canQsbInline = isLargeTablet && hotseatQsbHeight > 0;
isQsbInline = canQsbInline && isLandscape;
// Whether QSB might be inline in appropriate orientation (e.g. landscape).
boolean canQsbInline = (isTwoPanels ? inv.inlineQsb[INDEX_TWO_PANEL_PORTRAIT]
|| inv.inlineQsb[INDEX_TWO_PANEL_LANDSCAPE]
: inv.inlineQsb[INDEX_DEFAULT] || inv.inlineQsb[INDEX_LANDSCAPE])
&& hotseatQsbHeight > 0;
isQsbInline = inv.inlineQsb[mTypeIndex] && canQsbInline;
// We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
// might be inline in either orientations, to keep hotseat size consistent across rotation.
@@ -388,7 +393,7 @@ public class DeviceProfile {
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
updateHotseatIconSize(
pxFromDp(inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics));
pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -819,11 +824,11 @@ public class DeviceProfile {
private void updateFolderCellSize(float scale, Resources res) {
float invIconSizeDp = isVerticalBarLayout()
? inv.iconSize[InvariantDeviceProfile.INDEX_LANDSCAPE]
: inv.iconSize[InvariantDeviceProfile.INDEX_DEFAULT];
? inv.iconSize[INDEX_LANDSCAPE]
: inv.iconSize[INDEX_DEFAULT];
folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
folderChildTextSizePx =
pxFromSp(inv.iconTextSize[InvariantDeviceProfile.INDEX_DEFAULT], mMetrics, scale);
pxFromSp(inv.iconTextSize[INDEX_DEFAULT], mMetrics, scale);
folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale);
int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
@@ -1174,7 +1179,6 @@ public class DeviceProfile {
writer.println(prefix + "\t1 dp = " + mMetrics.density + " px");
writer.println(prefix + "\tisTablet:" + isTablet);
writer.println(prefix + "\tisLargeTablet:" + isLargeTablet);
writer.println(prefix + "\tisPhone:" + isPhone);
writer.println(prefix + "\ttransposeLayoutWithOrientation:"
+ transposeLayoutWithOrientation);
@@ -167,6 +167,7 @@ public class InvariantDeviceProfile {
public String dbFile;
public int defaultLayoutId;
int demoModeLayoutId;
boolean[] inlineQsb = new boolean[COUNT_SIZES];
/**
* An immutable list of supported profiles.
@@ -250,6 +251,8 @@ public class InvariantDeviceProfile {
COUNT_SIZES);
System.arraycopy(defaultDisplayOption.borderSpaces, 0, result.borderSpaces, 0,
COUNT_SIZES);
System.arraycopy(defaultDisplayOption.inlineQsb, 0, result.inlineQsb, 0,
COUNT_SIZES);
initGrid(context, myInfo, result, deviceType);
}
@@ -371,6 +374,8 @@ public class InvariantDeviceProfile {
devicePaddings = new DevicePaddings(context, devicePaddingId);
}
inlineQsb = displayOption.inlineQsb;
// If the partner customization apk contains any grid overrides, apply them
// Supported overrides: numRows, numColumns, iconSize
applyPartnerDeviceProfileOverrides(context, metrics);
@@ -783,12 +788,18 @@ public class InvariantDeviceProfile {
@VisibleForTesting
static final class DisplayOption {
private static final int INLINE_QSB_FOR_PORTRAIT = 1 << 0;
private static final int INLINE_QSB_FOR_LANDSCAPE = 1 << 1;
private static final int INLINE_QSB_FOR_TWO_PANEL_PORTRAIT = 1 << 2;
private static final int INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE = 1 << 3;
private static final int DONT_INLINE_QSB = 0;
public final GridOption grid;
private final float minWidthDps;
private final float minHeightDps;
private final boolean canBeDefault;
private final boolean[] inlineQsb = new boolean[COUNT_SIZES];
private final PointF[] minCellSize = new PointF[COUNT_SIZES];
@@ -815,6 +826,19 @@ public class InvariantDeviceProfile {
canBeDefault = a.getBoolean(R.styleable.ProfileDisplayOption_canBeDefault, false);
int inlineForRotation = a.getInt(R.styleable.ProfileDisplayOption_inlineQsb,
DONT_INLINE_QSB);
inlineQsb[INDEX_DEFAULT] =
(inlineForRotation & INLINE_QSB_FOR_PORTRAIT) == INLINE_QSB_FOR_PORTRAIT;
inlineQsb[INDEX_LANDSCAPE] =
(inlineForRotation & INLINE_QSB_FOR_LANDSCAPE) == INLINE_QSB_FOR_LANDSCAPE;
inlineQsb[INDEX_TWO_PANEL_PORTRAIT] =
(inlineForRotation & INLINE_QSB_FOR_TWO_PANEL_PORTRAIT)
== INLINE_QSB_FOR_TWO_PANEL_PORTRAIT;
inlineQsb[INDEX_TWO_PANEL_LANDSCAPE] =
(inlineForRotation & INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE)
== INLINE_QSB_FOR_TWO_PANEL_LANDSCAPE;
float x;
float y;
@@ -1029,6 +1053,7 @@ public class InvariantDeviceProfile {
allAppsIconSizes[i] = 0;
allAppsIconTextSizes[i] = 0;
allAppsBorderSpaces[i] = new PointF();
inlineQsb[i] = false;
}
}
@@ -1071,6 +1096,7 @@ public class InvariantDeviceProfile {
allAppsIconTextSizes[i] += p.allAppsIconTextSizes[i];
allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
allAppsBorderSpaces[i].y += p.allAppsBorderSpaces[i].y;
inlineQsb[i] |= p.inlineQsb[i];
}
folderBorderSpace += p.folderBorderSpace;
@@ -26,7 +26,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_LARGE_TABLET_WIDTH;
import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
import android.annotation.SuppressLint;
@@ -348,13 +347,6 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
return smallestSizeDp(bounds) >= MIN_TABLET_WIDTH;
}
/**
* Returns {@code true} if the bounds represent a large tablet.
*/
public boolean isLargeTablet(WindowBounds bounds) {
return smallestSizeDp(bounds) >= MIN_LARGE_TABLET_WIDTH;
}
/**
* Returns smallest size in dp for given bounds.
*/
@@ -58,7 +58,6 @@ import com.android.launcher3.util.WindowBounds;
public class WindowManagerProxy implements ResourceBasedOverride {
public static final int MIN_TABLET_WIDTH = 600;
public static final int MIN_LARGE_TABLET_WIDTH = 720;
public static final MainThreadInitializedObject<WindowManagerProxy> INSTANCE =
forOverride(WindowManagerProxy.class, R.string.window_manager_proxy_class);
@@ -0,0 +1,133 @@
/*
* Copyright (C) 2022 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.launcher3
import android.content.Context
import android.graphics.PointF
import androidx.test.core.app.ApplicationProvider
import com.android.launcher3.util.DisplayController.Info
import com.android.launcher3.util.WindowBounds
import org.junit.Before
import org.mockito.ArgumentMatchers.any
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when` as whenever
abstract class DeviceProfileBaseTest {
protected var context: Context? = null
protected var inv: InvariantDeviceProfile? = null
protected var info: Info = mock(Info::class.java)
protected var windowBounds: WindowBounds? = null
protected var isMultiWindowMode: Boolean = false
protected var transposeLayoutWithOrientation: Boolean = false
protected var useTwoPanels: Boolean = false
protected var isGestureMode: Boolean = true
@Before
fun setUp() {
context = ApplicationProvider.getApplicationContext()
// make sure to reset values
useTwoPanels = false
isGestureMode = true
}
protected fun newDP(): DeviceProfile = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
protected fun initializeVarsForPhone(isLandscape: Boolean = false) {
val (x, y) = if (isLandscape)
Pair(3120, 1440)
else
Pair(1440, 3120)
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(false)
inv = newScalableInvariantDeviceProfile()
}
protected fun initializeVarsForTablet(isLandscape: Boolean = false) {
val (x, y) = if (isLandscape)
Pair(2560, 1600)
else
Pair(1600, 2560)
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(true)
inv = newScalableInvariantDeviceProfile()
}
/**
* A very generic grid, just to make qsb tests work. For real calculations, make sure to use
* values that better represent a real grid.
*/
protected fun newScalableInvariantDeviceProfile(): InvariantDeviceProfile =
InvariantDeviceProfile().apply {
isScalable = true
numColumns = 5
numRows = 5
numShownHotseatIcons = 5
numDatabaseHotseatIcons = 6
numShrunkenHotseatIcons = 4
horizontalMargin = FloatArray(4) { 22f }
borderSpaces = listOf(
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f)
).toTypedArray()
allAppsBorderSpaces = listOf(
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f)
).toTypedArray()
hotseatBorderSpaces = FloatArray(4) { 16f }
iconSize = FloatArray(4) { 56f }
allAppsIconSize = FloatArray(4) { 56f }
iconTextSize = FloatArray(4) { 14f }
allAppsIconTextSize = FloatArray(4) { 14f }
minCellSize = listOf(
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f)
).toTypedArray()
allAppsCellSize = listOf(
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f)
).toTypedArray()
inlineQsb = booleanArrayOf(
false,
false,
false,
false
)
}
}
@@ -1,219 +0,0 @@
/*
* Copyright (C) 2022 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.launcher3
import android.content.Context
import android.graphics.PointF
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.util.DisplayController.Info
import com.android.launcher3.util.WindowBounds
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.*
@SmallTest
@RunWith(AndroidJUnit4::class)
class DeviceProfileTest {
private var context: Context? = null
private var inv: InvariantDeviceProfile? = null
private var info: Info = mock(Info::class.java)
private var windowBounds: WindowBounds? = null
private var isMultiWindowMode: Boolean = false
private var transposeLayoutWithOrientation: Boolean = false
private var useTwoPanels: Boolean = false
private var isGestureMode: Boolean = true
@Before
fun setUp() {
context = ApplicationProvider.getApplicationContext()
// make sure to reset values
useTwoPanels = false
}
@Test
fun qsbWidth_is_match_parent_for_phones() {
initializeVarsForPhone()
val dp = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_is_match_parent_for_tablet_portrait() {
initializeVarsForLargeTablet()
val dp = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_has_size_for_large_tablet_landscape() {
initializeVarsForLargeTablet(true)
val dp = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
assertThat(dp.qsbWidth).isGreaterThan(0)
} else {
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
}
/**
* This test is to make sure that two panels don't inline the QSB as tablets do
*/
@Test
fun qsbWidth_is_match_parent_for_small_two_panel_landscape() {
initializeVarsForSmallTablet(true)
useTwoPanels = true
val dp = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
private fun initializeVarsForPhone(isLandscape: Boolean = false) {
val (x, y) = if (isLandscape)
Pair(3120, 1440)
else
Pair(1440, 3120)
windowBounds = WindowBounds(x, y, x, y - 100, 0)
`when`(info.isTablet(any())).thenReturn(false)
`when`(info.isLargeTablet(any())).thenReturn(false)
scalableInvariantDeviceProfile()
}
private fun initializeVarsForSmallTablet(isLandscape: Boolean = false) {
val (x, y) = if (isLandscape)
Pair(2560, 1600)
else
Pair(1600, 2560)
windowBounds = WindowBounds(x, y, x, y - 100, 0)
`when`(info.isTablet(any())).thenReturn(true)
`when`(info.isLargeTablet(any())).thenReturn(false)
scalableInvariantDeviceProfile()
}
private fun initializeVarsForLargeTablet(isLandscape: Boolean = false) {
val (x, y) = if (isLandscape)
Pair(2560, 1600)
else
Pair(1600, 2560)
windowBounds = WindowBounds(x, y, x, y - 100, 0)
`when`(info.isTablet(any())).thenReturn(true)
`when`(info.isLargeTablet(any())).thenReturn(true)
scalableInvariantDeviceProfile()
}
/**
* A very generic grid, just to make qsb tests work. For real calculations, make sure to use
* values that better represent a real grid.
*/
private fun scalableInvariantDeviceProfile() {
inv = InvariantDeviceProfile().apply {
isScalable = true
numColumns = 5
numRows = 5
horizontalMargin = FloatArray(4) { 22f }
borderSpaces = listOf(
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f)
).toTypedArray()
allAppsBorderSpaces = listOf(
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f),
PointF(16f, 16f)
).toTypedArray()
hotseatBorderSpaces = FloatArray(4) { 16f }
iconSize = FloatArray(4) { 56f }
allAppsIconSize = FloatArray(4) { 56f }
iconTextSize = FloatArray(4) { 14f }
allAppsIconTextSize = FloatArray(4) { 14f }
minCellSize = listOf(
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f)
).toTypedArray()
allAppsCellSize = listOf(
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f),
PointF(64f, 83f)
).toTypedArray()
}
}
}
@@ -0,0 +1,186 @@
/*
* Copyright (C) 2022 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.launcher3
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY
import com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE
import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mockito.`when` as whenever
/**
* Test for [DeviceProfile]
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
class HotseatSizeTest : DeviceProfileBaseTest() {
@Test
fun hotseat_size_is_normal_for_handhelds() {
initializeVarsForPhone()
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_PHONE
}
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(5)
}
@Test
fun hotseat_size_is_max_for_foldables() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_MULTI_DISPLAY
}
useTwoPanels = true
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(6)
}
@Test
fun hotseat_size_is_shrunk_if_needed() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_MULTI_DISPLAY
inlineQsb = booleanArrayOf(
false,
false,
false,
true // two panels landscape
)
}
useTwoPanels = true
isGestureMode = false
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
assertThat(dp.numShownHotseatIcons).isEqualTo(4)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(6)
}
}
/**
* For consistency, the hotseat should shrink if any orientation on the device type has an
* inline qsb
*/
@Test
fun hotseat_size_is_shrunk_even_in_portrait() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_MULTI_DISPLAY
inlineQsb = booleanArrayOf(
false,
false,
false,
true // two panels landscape
)
}
useTwoPanels = true
isGestureMode = false
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(4)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(6)
}
}
@Test
fun hotseat_size_is_default_when_folded() {
initializeVarsForPhone()
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_MULTI_DISPLAY
}
useTwoPanels = true
val dp = newDP()
assertThat(dp.numShownHotseatIcons).isEqualTo(5)
}
@Test
fun hotseat_size_is_shrunk_if_needed_on_tablet() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_TABLET
inlineQsb = booleanArrayOf(
false,
true, // landscape
false,
false
)
}
isGestureMode = false
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
assertThat(dp.numShownHotseatIcons).isEqualTo(4)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(5)
}
}
/**
* For consistency, the hotseat should shrink if any orientation on the device type has an
* inline qsb
*/
@Test
fun hotseat_size_is_shrunk_even_in_portrait_on_tablet() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
deviceType = TYPE_TABLET
inlineQsb = booleanArrayOf(
false,
true, // landscape
false,
false
)
}
isGestureMode = false
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(4)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.numShownHotseatIcons).isEqualTo(5)
}
}
}
@@ -0,0 +1,105 @@
/*
* Copyright (C) 2022 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.launcher3
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
/**
* Test for [DeviceProfile]
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
class InlineQsbTest : DeviceProfileBaseTest() {
@Test
fun qsbWidth_is_match_parent_for_phones() {
initializeVarsForPhone()
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_is_match_parent_for_tablet_portrait() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
false,
true, // landscape
false,
false
)
}
val dp = DeviceProfile(
context,
inv,
info,
windowBounds,
isMultiWindowMode,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode
)
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_has_size_for_tablet_landscape() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
false,
true, // landscape
false,
false
)
}
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
assertThat(dp.qsbWidth).isGreaterThan(0)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
}
/**
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
*/
@Test
fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
initializeVarsForTablet(isLandscape = true)
useTwoPanels = true
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
}