Merge "Make inline qsb part of grid attrs" into tm-dev
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user