Files
lawnchair/tests/multivalentTests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt
Sunny Goyal 29f9c3d231 Merging IconShape with ThemeManager
The order of initialization for IconShape is closely tied to ThemeManager
which makes it difficult for change listeners to work. Merging these keeps
all the theming information at one place

Bug: 381897614
Test: Updated tests
Flag: EXEMPT refactor
Change-Id: Ie29efa20c3308a24be3e284c1c93ed7444b68d58
2025-02-13 22:38:01 -08:00

372 lines
13 KiB
Kotlin

/*
* 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.graphics.PointF
import android.graphics.Rect
import android.platform.test.rule.AllowedDevices
import android.platform.test.rule.DeviceProduct
import android.platform.test.rule.IgnoreLimit
import android.platform.test.rule.LimitDevicesRule
import android.util.SparseArray
import com.android.launcher3.DeviceProfile.DEFAULT_DIMENSION_PROVIDER
import com.android.launcher3.DeviceProfile.DEFAULT_PROVIDER
import com.android.launcher3.testing.shared.ResourceUtils.INVALID_RESOURCE_HANDLE
import com.android.launcher3.util.DisplayController.Info
import com.android.launcher3.util.SandboxApplication
import com.android.launcher3.util.WindowBounds
import java.io.PrintWriter
import java.io.StringWriter
import org.junit.Before
import org.junit.Rule
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
/**
* This is an abstract class for DeviceProfile tests that don't need the real Context and mock an
* InvariantDeviceProfile instead of creating one based on real values.
*
* For an implementation that creates InvariantDeviceProfile, use [AbstractDeviceProfileTest]
*/
@AllowedDevices(allowed = [DeviceProduct.CF_PHONE])
@IgnoreLimit(ignoreLimit = BuildConfig.IS_STUDIO_BUILD)
abstract class FakeInvariantDeviceProfileTest {
@get:Rule val context = SandboxApplication()
protected lateinit var inv: InvariantDeviceProfile
protected val info = mock<Info>()
protected lateinit var windowBounds: WindowBounds
private var transposeLayoutWithOrientation = false
private var useTwoPanels = false
private var isGestureMode = true
private var isTransientTaskbar = true
@Rule @JvmField val limitDevicesRule = LimitDevicesRule()
@Before
open fun setUp() {
// make sure to reset values
useTwoPanels = false
isGestureMode = true
}
protected fun newDP(): DeviceProfile =
DeviceProfile(
context,
inv,
info,
context.appComponent.wmProxy,
context.appComponent.themeManager,
windowBounds,
SparseArray(),
/*isMultiWindowMode=*/ false,
transposeLayoutWithOrientation,
useTwoPanels,
isGestureMode,
DEFAULT_PROVIDER,
DEFAULT_DIMENSION_PROVIDER,
isTransientTaskbar,
)
protected fun initializeVarsForPhone(
isGestureMode: Boolean = true,
isVerticalBar: Boolean = false,
) {
val (x, y) = if (isVerticalBar) Pair(2400, 1080) else Pair(1080, 2400)
windowBounds =
WindowBounds(
Rect(0, 0, x, y),
Rect(
if (isVerticalBar) 118 else 0,
if (isVerticalBar) 74 else 118,
if (!isGestureMode && isVerticalBar) 126 else 0,
if (isGestureMode) 63 else if (isVerticalBar) 0 else 126,
),
)
whenever(info.isTablet(any())).thenReturn(false)
whenever(info.getDensityDpi()).thenReturn(420)
whenever(info.smallestSizeDp(any())).thenReturn(411f)
this.isGestureMode = isGestureMode
this.isTransientTaskbar = false
transposeLayoutWithOrientation = true
inv =
context.appComponent.idp.apply {
numRows = 5
numColumns = 4
numSearchContainerColumns = 4
iconSize = floatArrayOf(60f, 54f, 60f, 60f)
iconTextSize = FloatArray(4) { 14f }
deviceType = InvariantDeviceProfile.TYPE_PHONE
minCellSize =
listOf(
PointF(80f, 104f),
PointF(80f, 104f),
PointF(80f, 104f),
PointF(80f, 104f),
)
.toTypedArray()
borderSpaces =
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
.toTypedArray()
numFolderRows = intArrayOf(3, 3, 3, 3)
numFolderColumns = intArrayOf(3, 3, 3, 3)
folderStyle = R.style.FolderStyleDefault
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
horizontalMargin = FloatArray(4) { 22f }
allAppsStyle = R.style.AllAppsStyleDefault
allAppsCellSize =
listOf(
PointF(80f, 104f),
PointF(80f, 104f),
PointF(80f, 104f),
PointF(80f, 104f),
)
.toTypedArray()
allAppsIconSize = floatArrayOf(60f, 60f, 60f, 60f)
allAppsIconTextSize = FloatArray(4) { 14f }
allAppsBorderSpaces =
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f))
.toTypedArray()
numShownHotseatIcons = 4
numDatabaseHotseatIcons = 4
hotseatBarBottomSpace = FloatArray(4) { 48f }
hotseatQsbSpace = FloatArray(4) { 36f }
numAllAppsColumns = 4
isScalable = true
transientTaskbarIconSize = FloatArray(4) { 44f }
startAlignTaskbar = BooleanArray(4) { false }
inlineQsb = BooleanArray(4) { false }
devicePaddingId = R.xml.paddings_handhelds
isFixedLandscape = false
workspaceSpecsId = INVALID_RESOURCE_HANDLE
allAppsSpecsId = INVALID_RESOURCE_HANDLE
folderSpecsId = INVALID_RESOURCE_HANDLE
hotseatSpecsId = INVALID_RESOURCE_HANDLE
workspaceCellSpecsId = INVALID_RESOURCE_HANDLE
allAppsCellSpecsId = INVALID_RESOURCE_HANDLE
}
}
protected fun initializeVarsForTablet(
isLandscape: Boolean = false,
isGestureMode: Boolean = true,
) {
val (x, y) = if (isLandscape) Pair(2560, 1600) else Pair(1600, 2560)
windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 104, 0, 0))
whenever(info.isTablet(any())).thenReturn(true)
whenever(info.getDensityDpi()).thenReturn(320)
whenever(info.smallestSizeDp(any())).thenReturn(800f)
this.isGestureMode = isGestureMode
this.isTransientTaskbar = true
useTwoPanels = false
inv =
context.appComponent.idp.apply {
numRows = 5
numColumns = 6
numSearchContainerColumns = 3
iconSize = FloatArray(4) { 60f }
iconTextSize = FloatArray(4) { 14f }
deviceType = InvariantDeviceProfile.TYPE_TABLET
minCellSize =
listOf(
PointF(102f, 120f),
PointF(120f, 104f),
PointF(102f, 120f),
PointF(102f, 120f),
)
.toTypedArray()
borderSpaces =
listOf(PointF(16f, 64f), PointF(64f, 16f), PointF(16f, 64f), PointF(16f, 64f))
.toTypedArray()
numFolderRows = intArrayOf(3, 3, 3, 3)
numFolderColumns = intArrayOf(3, 3, 3, 3)
folderStyle = R.style.FolderStyleDefault
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
allAppsStyle = R.style.AllAppsStyleDefault
allAppsCellSize =
listOf(
PointF(96f, 142f),
PointF(126f, 126f),
PointF(96f, 142f),
PointF(96f, 142f),
)
.toTypedArray()
allAppsIconSize = FloatArray(4) { 60f }
allAppsIconTextSize = FloatArray(4) { 14f }
allAppsBorderSpaces =
listOf(PointF(8f, 16f), PointF(16f, 16f), PointF(8f, 16f), PointF(8f, 16f))
.toTypedArray()
numShownHotseatIcons = 6
numDatabaseHotseatIcons = 6
hotseatBarBottomSpace = floatArrayOf(36f, 40f, 36f, 36f)
hotseatQsbSpace = FloatArray(4) { 32f }
numAllAppsColumns = 6
isScalable = true
devicePaddingId = R.xml.paddings_6x5
transientTaskbarIconSize = FloatArray(4) { 44f }
startAlignTaskbar = booleanArrayOf(true, false, true, true)
inlineQsb = booleanArrayOf(false, true, false, false)
devicePaddingId = R.xml.paddings_handhelds
isFixedLandscape = false
workspaceSpecsId = INVALID_RESOURCE_HANDLE
allAppsSpecsId = INVALID_RESOURCE_HANDLE
folderSpecsId = INVALID_RESOURCE_HANDLE
hotseatSpecsId = INVALID_RESOURCE_HANDLE
workspaceCellSpecsId = INVALID_RESOURCE_HANDLE
allAppsCellSpecsId = INVALID_RESOURCE_HANDLE
}
}
protected fun initializeVarsForTwoPanel(
isLandscape: Boolean = false,
isGestureMode: Boolean = true,
rows: Int = 4,
cols: Int = 4,
) {
val (x, y) = if (isLandscape) Pair(2208, 1840) else Pair(1840, 2208)
windowBounds = WindowBounds(Rect(0, 0, x, y), Rect(0, 110, 0, 0))
whenever(info.isTablet(any())).thenReturn(true)
whenever(info.getDensityDpi()).thenReturn(420)
whenever(info.smallestSizeDp(any())).thenReturn(700f)
this.isGestureMode = isGestureMode
this.isTransientTaskbar = true
useTwoPanels = true
inv =
context.appComponent.idp.apply {
numRows = rows
numColumns = cols
numSearchContainerColumns = cols
iconSize = floatArrayOf(60f, 52f, 52f, 60f)
iconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
deviceType = InvariantDeviceProfile.TYPE_MULTI_DISPLAY
minCellSize =
listOf(
PointF(80f, 104f),
PointF(80f, 104f),
PointF(68f, 116f),
PointF(80f, 102f),
)
.toTypedArray()
borderSpaces =
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 20f), PointF(20f, 20f))
.toTypedArray()
numFolderRows = intArrayOf(3, 3, 3, 3)
numFolderColumns = intArrayOf(3, 3, 3, 3)
folderStyle = R.style.FolderStyleDefault
inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split
horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
allAppsStyle = R.style.AllAppsStyleDefault
allAppsCellSize =
listOf(PointF(0f, 0f), PointF(0f, 0f), PointF(68f, 104f), PointF(80f, 104f))
.toTypedArray()
allAppsIconSize = floatArrayOf(60f, 60f, 52f, 60f)
allAppsIconTextSize = floatArrayOf(14f, 14f, 12f, 14f)
allAppsBorderSpaces =
listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 28f), PointF(20f, 16f))
.toTypedArray()
numShownHotseatIcons = 6
numDatabaseHotseatIcons = 6
hotseatBarBottomSpace = floatArrayOf(48f, 48f, 36f, 20f)
hotseatQsbSpace = floatArrayOf(36f, 36f, 36f, 28f)
numAllAppsColumns = 6
numDatabaseAllAppsColumns = 6
isScalable = true
transientTaskbarIconSize = FloatArray(4) { 44f }
startAlignTaskbar = BooleanArray(4) { true }
inlineQsb = booleanArrayOf(false, false, false, false)
devicePaddingId = R.xml.paddings_handhelds
isFixedLandscape = false
workspaceSpecsId = INVALID_RESOURCE_HANDLE
allAppsSpecsId = INVALID_RESOURCE_HANDLE
folderSpecsId = INVALID_RESOURCE_HANDLE
hotseatSpecsId = INVALID_RESOURCE_HANDLE
workspaceCellSpecsId = INVALID_RESOURCE_HANDLE
allAppsCellSpecsId = INVALID_RESOURCE_HANDLE
}
}
fun dump(dp: DeviceProfile): String {
val stringWriter = StringWriter()
val printWriter = PrintWriter(stringWriter)
dp.dump(context, "", printWriter)
printWriter.flush()
return stringWriter.toString()
}
}