From f8bfb036ba2963f8e9ac75eeb1e998c987a1ea9e Mon Sep 17 00:00:00 2001 From: Thales Lima Date: Mon, 24 Jul 2023 15:08:05 +0100 Subject: [PATCH] Create specs for hotseat Some attributes of hotseat change depending on the size of the device. In the future more attributes could be moved to the spec, e.g. hotseat icons. Fix: 292204436 Test: CalculatedHotseatSpecTest Test: HotseatSpecsTest Test: SizeSpecTest Test: DeviceProfileResponsiveDumpTest Test: DeviceProfileResponsiveAlternativeDisplaysDumpTest Flag: ENABLE_RESPONSIVE_WORKSPACE Change-Id: I6a4e05d75af819dbf1444a5ca45c2080f55dc203 --- res/values/attrs.xml | 11 +- src/com/android/launcher3/DeviceProfile.java | 19 ++- .../launcher3/InvariantDeviceProfile.java | 13 ++ .../launcher3/responsive/HotseatSpecs.kt | 122 ++++++++++++++++++ .../android/launcher3/responsive/SizeSpec.kt | 9 ++ tests/res/xml/invalid_hotseat_file_case_1.xml | 30 +++++ tests/res/xml/valid_hotseat_file.xml | 30 +++++ .../launcher3/AbstractDeviceProfileTest.kt | 9 ++ .../responsive/CalculatedFolderSpecsTest.kt | 5 - .../responsive/CalculatedHotseatSpecTest.kt | 75 +++++++++++ .../launcher3/responsive/FolderSpecsTest.kt | 9 -- .../launcher3/responsive/HotseatSpecsTest.kt | 71 ++++++++++ .../launcher3/responsive/SizeSpecTest.kt | 16 +++ 13 files changed, 402 insertions(+), 17 deletions(-) create mode 100644 src/com/android/launcher3/responsive/HotseatSpecs.kt create mode 100644 tests/res/xml/invalid_hotseat_file_case_1.xml create mode 100644 tests/res/xml/valid_hotseat_file.xml create mode 100644 tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt create mode 100644 tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4d75fb856d..05eaf88ffb 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -202,6 +202,7 @@ + @@ -210,11 +211,14 @@ Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled --> - + + + @@ -278,6 +282,11 @@ + + + + + diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 83de98ac47..ee7bebf1f5 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -56,8 +56,10 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.responsive.AllAppsSpecs; import com.android.launcher3.responsive.CalculatedAllAppsSpec; import com.android.launcher3.responsive.CalculatedFolderSpec; +import com.android.launcher3.responsive.CalculatedHotseatSpec; import com.android.launcher3.responsive.CalculatedWorkspaceSpec; import com.android.launcher3.responsive.FolderSpecs; +import com.android.launcher3.responsive.HotseatSpecs; import com.android.launcher3.responsive.WorkspaceSpecs; import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.DisplayController; @@ -121,6 +123,7 @@ public class DeviceProfile { private CalculatedAllAppsSpec mAllAppsResponsiveHeightSpec; private CalculatedFolderSpec mResponsiveFolderWidthSpec; private CalculatedFolderSpec mResponsiveFolderHeightSpec; + private CalculatedHotseatSpec mResponsiveHotseatSpec; /** * The maximum amount of left/right workspace padding as a percentage of the screen width. @@ -316,7 +319,8 @@ public class DeviceProfile { // TODO(b/241386436): shouldn't change any launcher behaviour mIsResponsiveGrid = inv.workspaceSpecsId != INVALID_RESOURCE_HANDLE && inv.allAppsSpecsId != INVALID_RESOURCE_HANDLE - && inv.folderSpecsId != INVALID_RESOURCE_HANDLE; + && inv.folderSpecsId != INVALID_RESOURCE_HANDLE + && inv.hotseatSpecsId != INVALID_RESOURCE_HANDLE; mIsScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode; // Determine device posture. @@ -495,7 +499,17 @@ public class DeviceProfile { int hotseatBarBottomSpace = pxFromDp(inv.hotseatBarBottomSpace[mTypeIndex], mMetrics); int minQsbMargin = res.getDimensionPixelSize(R.dimen.min_qsb_margin); - hotseatQsbSpace = pxFromDp(inv.hotseatQsbSpace[mTypeIndex], mMetrics); + + if (mIsResponsiveGrid) { + HotseatSpecs hotseatSpecs = + HotseatSpecs.create(new ResourceHelper(context, + isTwoPanels ? inv.hotseatSpecsTwoPanelId : inv.hotseatSpecsId)); + mResponsiveHotseatSpec = hotseatSpecs.getCalculatedHeightSpec(heightPx); + hotseatQsbSpace = mResponsiveHotseatSpec.getHotseatQsbSpace(); + } else { + hotseatQsbSpace = pxFromDp(inv.hotseatQsbSpace[mTypeIndex], mMetrics); + } + // Have a little space between the inset and the QSB if (mInsets.bottom + minQsbMargin > hotseatBarBottomSpace) { int availableSpace = hotseatQsbSpace - (mInsets.bottom - hotseatBarBottomSpace); @@ -1952,6 +1966,7 @@ public class DeviceProfile { + mAllAppsResponsiveWidthSpec.toString()); writer.println(prefix + "\tmResponsiveFolderHeightSpec:" + mResponsiveFolderHeightSpec); writer.println(prefix + "\tmResponsiveFolderWidthSpec:" + mResponsiveFolderWidthSpec); + writer.println(prefix + "\tmResponsiveHotseatSpec:" + mResponsiveHotseatSpec); } } diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index dac6120e1b..722991a8b6 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -189,6 +189,8 @@ public class InvariantDeviceProfile { public int folderSpecsId = INVALID_RESOURCE_HANDLE; @XmlRes public int folderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; + public int hotseatSpecsId = INVALID_RESOURCE_HANDLE; + public int hotseatSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; public String dbFile; public int defaultLayoutId; @@ -368,6 +370,8 @@ public class InvariantDeviceProfile { allAppsSpecsTwoPanelId = closestProfile.mAllAppsSpecsTwoPanelId; folderSpecsId = closestProfile.mFolderSpecsId; folderSpecsTwoPanelId = closestProfile.mFolderSpecsTwoPanelId; + hotseatSpecsId = closestProfile.mHotseatSpecsId; + hotseatSpecsTwoPanelId = closestProfile.mHotseatSpecsTwoPanelId; this.deviceType = deviceType; inlineNavButtonsEndSpacing = closestProfile.inlineNavButtonsEndSpacing; @@ -819,6 +823,8 @@ public class InvariantDeviceProfile { private final int mAllAppsSpecsTwoPanelId; private final int mFolderSpecsId; private final int mFolderSpecsTwoPanelId; + private final int mHotseatSpecsId; + private final int mHotseatSpecsTwoPanelId; public GridOption(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes( @@ -896,6 +902,11 @@ public class InvariantDeviceProfile { mFolderSpecsTwoPanelId = a.getResourceId( R.styleable.GridDisplayOption_folderSpecsTwoPanelId, INVALID_RESOURCE_HANDLE); + mHotseatSpecsId = a.getResourceId( + R.styleable.GridDisplayOption_hotseatSpecsId, INVALID_RESOURCE_HANDLE); + mHotseatSpecsTwoPanelId = a.getResourceId( + R.styleable.GridDisplayOption_hotseatSpecsTwoPanelId, + INVALID_RESOURCE_HANDLE); } else { mWorkspaceSpecsId = INVALID_RESOURCE_HANDLE; mWorkspaceSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; @@ -903,6 +914,8 @@ public class InvariantDeviceProfile { mAllAppsSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; mFolderSpecsId = INVALID_RESOURCE_HANDLE; mFolderSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; + mHotseatSpecsId = INVALID_RESOURCE_HANDLE; + mHotseatSpecsTwoPanelId = INVALID_RESOURCE_HANDLE; } int inlineForRotation = a.getInt(R.styleable.GridDisplayOption_inlineQsb, diff --git a/src/com/android/launcher3/responsive/HotseatSpecs.kt b/src/com/android/launcher3/responsive/HotseatSpecs.kt new file mode 100644 index 0000000000..482508d085 --- /dev/null +++ b/src/com/android/launcher3/responsive/HotseatSpecs.kt @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2023 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.responsive + +import android.content.res.TypedArray +import android.util.Log +import com.android.launcher3.R +import com.android.launcher3.util.ResourceHelper + +class HotseatSpecs(val specs: List) { + + fun getCalculatedHeightSpec(availableHeight: Int): CalculatedHotseatSpec { + val spec = specs.firstOrNull { availableHeight <= it.maxAvailableSize } + check(spec != null) { "No available height spec found within $availableHeight." } + return CalculatedHotseatSpec(availableHeight, spec) + } + + companion object { + private const val XML_HOTSEAT_SPEC = "hotseatSpec" + + @JvmStatic + fun create(resourceHelper: ResourceHelper): HotseatSpecs { + val parser = ResponsiveSpecsParser(resourceHelper) + val specs = parser.parseXML(XML_HOTSEAT_SPEC, ::HotseatSpec) + return HotseatSpecs(specs.filter { it.specType == ResponsiveSpec.SpecType.HEIGHT }) + } + } +} + +data class HotseatSpec( + val maxAvailableSize: Int, + val specType: ResponsiveSpec.SpecType, + val hotseatQsbSpace: SizeSpec +) { + + init { + check(isValid()) { "Invalid HotseatSpec found." } + } + + constructor( + attrs: TypedArray, + specs: Map + ) : this( + maxAvailableSize = + attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0), + specType = + ResponsiveSpec.SpecType.values()[ + attrs.getInt( + R.styleable.ResponsiveSpec_specType, + ResponsiveSpec.SpecType.HEIGHT.ordinal + )], + hotseatQsbSpace = specs.getOrError(SizeSpec.XmlTags.HOTSEAT_QSB_SPACE) + ) + + fun isValid(): Boolean { + if (maxAvailableSize <= 0) { + Log.e(LOG_TAG, "${this::class.simpleName}#isValid - maxAvailableSize <= 0") + return false + } + + // All specs need to be individually valid + if (!allSpecsAreValid()) { + Log.e(LOG_TAG, "${this::class.simpleName}#isValid - !allSpecsAreValid()") + return false + } + + return true + } + + private fun allSpecsAreValid(): Boolean { + return hotseatQsbSpace.isValid() && hotseatQsbSpace.onlyFixedSize() + } + + companion object { + private const val LOG_TAG = "HotseatSpec" + } +} + +class CalculatedHotseatSpec(val availableSpace: Int, val spec: HotseatSpec) { + + var hotseatQsbSpace: Int = 0 + private set + + init { + hotseatQsbSpace = spec.hotseatQsbSpace.getCalculatedValue(availableSpace) + } + + override fun hashCode(): Int { + var result = availableSpace.hashCode() + result = 31 * result + hotseatQsbSpace.hashCode() + result = 31 * result + spec.hashCode() + return result + } + + override fun equals(other: Any?): Boolean { + return other is CalculatedHotseatSpec && + availableSpace == other.availableSpace && + hotseatQsbSpace == other.hotseatQsbSpace && + spec == other.spec + } + + override fun toString(): String { + return "${this::class.simpleName}(" + + "availableSpace=$availableSpace, hotseatQsbSpace=$hotseatQsbSpace, " + + "${spec::class.simpleName}.maxAvailableSize=${spec.maxAvailableSize}" + + ")" + } +} diff --git a/src/com/android/launcher3/responsive/SizeSpec.kt b/src/com/android/launcher3/responsive/SizeSpec.kt index d3868f0c20..c868c9f7be 100644 --- a/src/com/android/launcher3/responsive/SizeSpec.kt +++ b/src/com/android/launcher3/responsive/SizeSpec.kt @@ -107,11 +107,20 @@ data class SizeSpec( return true } + fun onlyFixedSize(): Boolean { + if (ofAvailableSpace > 0 || ofRemainderSpace > 0 || matchWorkspace) { + Log.e(TAG, "SizeSpec#onlyFixedSize - only fixed size allowed for this tag") + return false + } + return true + } + object XmlTags { const val START_PADDING = "startPadding" const val END_PADDING = "endPadding" const val GUTTER = "gutter" const val CELL_SIZE = "cellSize" + const val HOTSEAT_QSB_SPACE = "hotseatQsbSpace" } companion object { diff --git a/tests/res/xml/invalid_hotseat_file_case_1.xml b/tests/res/xml/invalid_hotseat_file_case_1.xml new file mode 100644 index 0000000000..fcbc5ead8d --- /dev/null +++ b/tests/res/xml/invalid_hotseat_file_case_1.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/res/xml/valid_hotseat_file.xml b/tests/res/xml/valid_hotseat_file.xml new file mode 100644 index 0000000000..c7f52e82c2 --- /dev/null +++ b/tests/res/xml/valid_hotseat_file.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt index f0cedd30e5..89159a72c3 100644 --- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt @@ -22,6 +22,7 @@ import android.graphics.Rect import android.util.DisplayMetrics import android.view.Surface import androidx.test.core.app.ApplicationProvider +import com.android.launcher3.testing.shared.ResourceUtils import com.android.launcher3.util.DisplayController import com.android.launcher3.util.NavigationMode import com.android.launcher3.util.WindowBounds @@ -306,4 +307,12 @@ abstract class AbstractDeviceProfileTest { private fun writeToDevice(context: Context, fileName: String, content: String) { File(context.getDir("dumpTests", Context.MODE_PRIVATE), fileName).writeText(content) } + + protected fun Float.dpToPx(): Float { + return ResourceUtils.pxFromDp(this, context!!.resources.displayMetrics).toFloat() + } + + protected fun Int.dpToPx(): Int { + return ResourceUtils.pxFromDp(this.toFloat(), context!!.resources.displayMetrics) + } } diff --git a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt index 863cf76185..f2a269a607 100644 --- a/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt +++ b/tests/src/com/android/launcher3/responsive/CalculatedFolderSpecsTest.kt @@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest -import com.android.launcher3.testing.shared.ResourceUtils import com.android.launcher3.tests.R import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat @@ -118,8 +117,4 @@ class CalculatedFolderSpecsTest : AbstractDeviceProfileTest() { assertThat(cellSizePx).isEqualTo(calculatedWorkspace.cellSizePx) } } - - private fun Int.dpToPx(): Int { - return ResourceUtils.pxFromDp(this.toFloat(), context!!.resources.displayMetrics) - } } diff --git a/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt new file mode 100644 index 0000000000..0ecf7bae5a --- /dev/null +++ b/tests/src/com/android/launcher3/responsive/CalculatedHotseatSpecTest.kt @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 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.responsive + +import android.content.Context +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.AbstractDeviceProfileTest +import com.android.launcher3.tests.R as TestR +import com.android.launcher3.util.TestResourceHelper +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class CalculatedHotseatSpecTest : AbstractDeviceProfileTest() { + override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context + + /** + * This test tests: + * - (height spec) gets the correct breakpoint from the XML - skips the first breakpoint + */ + @Test + fun normalPhone_returnsSecondBreakpointSpec() { + val deviceSpec = deviceSpecs["phone"]!! + initializeVarsForPhone(deviceSpec) + + // Hotseat uses the whole device height + val availableHeight = deviceSpec.naturalSize.second + + val hotseatSpecs = + HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file)) + val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight) + + assertThat(heightSpec.availableSpace).isEqualTo(availableHeight) + assertThat(heightSpec.hotseatQsbSpace).isEqualTo(95) + } + + /** + * This test tests: + * - (height spec) gets the correct breakpoint from the XML - use the first breakpoint + */ + @Test + fun smallPhone_returnsFirstBreakpointSpec() { + val deviceSpec = deviceSpecs["phone"]!! + deviceSpec.densityDpi = 540 // larger display size + initializeVarsForPhone(deviceSpec) + + // Hotseat uses the whole device height + val availableHeight = deviceSpec.naturalSize.second + + val hotseatSpecs = + HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file)) + val heightSpec = hotseatSpecs.getCalculatedHeightSpec(availableHeight) + + assertThat(heightSpec.availableSpace).isEqualTo(availableHeight) + assertThat(heightSpec.hotseatQsbSpace).isEqualTo(81) + } +} diff --git a/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt b/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt index e21af57cd5..4b05949e35 100644 --- a/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt +++ b/tests/src/com/android/launcher3/responsive/FolderSpecsTest.kt @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.launcher3.AbstractDeviceProfileTest import com.android.launcher3.responsive.ResponsiveSpec.SpecType -import com.android.launcher3.testing.shared.ResourceUtils import com.android.launcher3.tests.R import com.android.launcher3.util.TestResourceHelper import com.google.common.truth.Truth.assertThat @@ -249,12 +248,4 @@ class FolderSpecsTest : AbstractDeviceProfileTest() { val folderSpecs = FolderSpecs.create(resourceHelper) folderSpecs.getCalculatedHeightSpec(cells, availableSpace, calculatedWorkspaceSpec) } - - private fun Float.dpToPx(): Float { - return ResourceUtils.pxFromDp(this, context!!.resources.displayMetrics).toFloat() - } - - private fun Int.dpToPx(): Int { - return ResourceUtils.pxFromDp(this.toFloat(), context!!.resources.displayMetrics) - } } diff --git a/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt b/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt new file mode 100644 index 0000000000..c764e47526 --- /dev/null +++ b/tests/src/com/android/launcher3/responsive/HotseatSpecsTest.kt @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2023 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.responsive + +import android.content.Context +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import androidx.test.platform.app.InstrumentationRegistry +import com.android.launcher3.AbstractDeviceProfileTest +import com.android.launcher3.tests.R as TestR +import com.android.launcher3.util.TestResourceHelper +import com.android.systemui.util.dpToPx +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class HotseatSpecsTest : AbstractDeviceProfileTest() { + override val runningContext: Context = InstrumentationRegistry.getInstrumentation().context + + @Before + fun setup() { + initializeVarsForPhone(deviceSpecs["phone"]!!) + } + + @Test + fun parseValidFile() { + val hotseatSpecs = + HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.valid_hotseat_file)) + assertThat(hotseatSpecs.specs.size).isEqualTo(2) + + val expectedSpecs = + listOf( + HotseatSpec( + maxAvailableSize = 847.dpToPx(), + specType = ResponsiveSpec.SpecType.HEIGHT, + hotseatQsbSpace = SizeSpec(24f.dpToPx()) + ), + HotseatSpec( + maxAvailableSize = 9999.dpToPx(), + specType = ResponsiveSpec.SpecType.HEIGHT, + hotseatQsbSpace = SizeSpec(36f.dpToPx()) + ), + ) + + assertThat(hotseatSpecs.specs.size).isEqualTo(expectedSpecs.size) + assertThat(hotseatSpecs.specs[0]).isEqualTo(expectedSpecs[0]) + assertThat(hotseatSpecs.specs[1]).isEqualTo(expectedSpecs[1]) + } + + @Test(expected = IllegalStateException::class) + fun parseInvalidFile_spaceIsNotFixedSize_throwsError() { + HotseatSpecs.create(TestResourceHelper(context!!, TestR.xml.invalid_hotseat_file_case_1)) + } +} diff --git a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt index 088cae1485..8ca07c6d96 100644 --- a/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt +++ b/tests/src/com/android/launcher3/responsive/SizeSpecTest.kt @@ -139,4 +139,20 @@ class SizeSpecTest : AbstractDeviceProfileTest() { assertThat(instance.isValid()).isEqualTo(false) } } + + @Test + fun onlyFixedSize() { + assertThat(SizeSpec(fixedSize = 16f).onlyFixedSize()).isEqualTo(true) + + val combinations = + listOf( + SizeSpec(0f, 1.1f, 0f, false), + SizeSpec(0f, 0f, 1.1f, false), + SizeSpec(0f, 0f, 0f, true) + ) + + for (instance in combinations) { + assertThat(instance.onlyFixedSize()).isEqualTo(false) + } + } }