diff options
-rw-r--r-- | res/values/attrs.xml | 12 | ||||
-rw-r--r-- | src/com/android/launcher3/DeviceProfile.java | 32 | ||||
-rw-r--r-- | src/com/android/launcher3/InvariantDeviceProfile.java | 26 | ||||
-rw-r--r-- | src/com/android/launcher3/util/DisplayController.java | 8 | ||||
-rw-r--r-- | src/com/android/launcher3/util/window/WindowManagerProxy.java | 1 | ||||
-rw-r--r-- | tests/src/com/android/launcher3/DeviceProfileBaseTest.kt | 133 | ||||
-rw-r--r-- | tests/src/com/android/launcher3/DeviceProfileTest.kt | 219 | ||||
-rw-r--r-- | tests/src/com/android/launcher3/HotseatSizeTest.kt | 186 | ||||
-rw-r--r-- | tests/src/com/android/launcher3/InlineQsbTest.kt | 105 |
9 files changed, 480 insertions, 242 deletions
diff --git a/res/values/attrs.xml b/res/values/attrs.xml index c96a2284e7..fcb9053418 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -316,6 +316,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"> diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 0c33bce5e0..db31350c59 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -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) @@ -812,11 +817,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); @@ -1167,7 +1172,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); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 219ed9e371..9f367ef766 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -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; @@ -1004,6 +1028,7 @@ public class InvariantDeviceProfile { allAppsIconSizes[i] = 0; allAppsIconTextSizes[i] = 0; allAppsBorderSpaces[i] = new PointF(); + inlineQsb[i] = false; } } @@ -1046,6 +1071,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; diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index 8b4ff85f90..44a0ef4436 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -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; @@ -349,13 +348,6 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { } /** - * 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. */ public float smallestSizeDp(WindowBounds bounds) { diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index ba3d9814ec..71460f3fbb 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -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); diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt new file mode 100644 index 0000000000..e598df961d --- /dev/null +++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt @@ -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 + ) + } +}
\ No newline at end of file diff --git a/tests/src/com/android/launcher3/DeviceProfileTest.kt b/tests/src/com/android/launcher3/DeviceProfileTest.kt deleted file mode 100644 index d1e91ed072..0000000000 --- a/tests/src/com/android/launcher3/DeviceProfileTest.kt +++ /dev/null @@ -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() - } - } -}
\ No newline at end of file diff --git a/tests/src/com/android/launcher3/HotseatSizeTest.kt b/tests/src/com/android/launcher3/HotseatSizeTest.kt new file mode 100644 index 0000000000..ca697d7c96 --- /dev/null +++ b/tests/src/com/android/launcher3/HotseatSizeTest.kt @@ -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) + } + } + +}
\ No newline at end of file diff --git a/tests/src/com/android/launcher3/InlineQsbTest.kt b/tests/src/com/android/launcher3/InlineQsbTest.kt new file mode 100644 index 0000000000..e00dca86e2 --- /dev/null +++ b/tests/src/com/android/launcher3/InlineQsbTest.kt @@ -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) + } + +}
\ No newline at end of file |