diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/BaseKeyEventsTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/BaseKeyEventsTestCase.kt index 37722e020696a..3c2fd67d02035 100644 --- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/BaseKeyEventsTestCase.kt +++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/BaseKeyEventsTestCase.kt @@ -42,6 +42,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import androidx.test.filters.MediumTest +import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.testutils.PollingCheck import androidx.testutils.withActivity @@ -51,7 +52,6 @@ import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotNull -import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -144,14 +144,11 @@ abstract class BaseKeyEventsTestCase(private val activityC } } + @SdkSuppress(maxSdkVersion = 35) // b/460511639 @Test @LargeTest @Throws(InterruptedException::class) fun testBackCollapsesActionView() { - assumeFalse( - "Test fails on cuttlefish b/460511639", - Build.MODEL.contains("Cuttlefish", ignoreCase = true), - ) with(ActivityScenario.launch(activityClass)) { // Click on the Search menu item onView(withId(R.id.action_search)).perform(click()) @@ -208,11 +205,8 @@ abstract class BaseKeyEventsTestCase(private val activityC @Test @MediumTest + @SdkSuppress(maxSdkVersion = 35) // b/460511639 fun testBackPressWithEmptyMenuHandledByActivity() { - assumeFalse( - "Test fails on cuttlefish b/460511639", - Build.MODEL.contains("Cuttlefish", ignoreCase = true), - ) with(ActivityScenario.launch(activityClass)) { // Pressing the menu key with an empty menu does nothing. val scenario = (this as? ActivityScenario)!! diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/KeyEventsTestCaseWithWindowDecor.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/KeyEventsTestCaseWithWindowDecor.kt index b71cec6ec0a7c..a02303b7542c3 100644 --- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/KeyEventsTestCaseWithWindowDecor.kt +++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/KeyEventsTestCaseWithWindowDecor.kt @@ -16,7 +16,6 @@ package androidx.appcompat.app import android.content.Context -import android.os.Build import android.view.KeyEvent import android.view.View import android.view.ViewGroup @@ -27,23 +26,20 @@ import androidx.test.espresso.Espresso.onView import androidx.test.espresso.action.ViewActions.pressKey import androidx.test.espresso.matcher.ViewMatchers.isRoot import androidx.test.filters.LargeTest +import androidx.test.filters.SdkSuppress import androidx.testutils.PollingCheck import androidx.testutils.withActivity import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue -import org.junit.Assume.assumeFalse import org.junit.Test class KeyEventsTestCaseWithWindowDecor : BaseKeyEventsTestCase(WindowDecorAppCompatActivity::class.java) { + @SdkSuppress(maxSdkVersion = 35) // b/460511639 @Test @LargeTest @Throws(Throwable::class) fun testUnhandledKeys() { - assumeFalse( - "Test fails on cuttlefish b/460511639", - Build.MODEL.contains("Cuttlefish", ignoreCase = true), - ) with(ActivityScenario.launch(WindowDecorAppCompatActivity::class.java)) { val listener = MockUnhandledKeyListener() val mockView1: View = withActivity { HandlerView(this) } diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/ArcSpline.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/ArcSpline.kt index 5f77d0171189d..9cc7b15e15325 100644 --- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/ArcSpline.kt +++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/ArcSpline.kt @@ -387,6 +387,10 @@ private const val HalfPi = (PI * 0.5).toFloat() private val OurPercentCache: FloatArray = FloatArray(91) -internal expect inline fun toRadians(value: Double): Double +@Suppress("NOTHING_TO_INLINE") +internal inline fun toRadians(value: Double): Double { + // No Kotlin multiplatform function out of a box, but it's a trivial calculation + return value * (PI / 180.0) +} internal expect inline fun binarySearch(array: FloatArray, position: Float): Int diff --git a/compose/animation/animation-core/src/jvmAndAndroidMain/kotlin/androidx/compose/animation/core/ArcSpline.jvmAndAndroid.kt b/compose/animation/animation-core/src/jvmAndAndroidMain/kotlin/androidx/compose/animation/core/ArcSpline.jvmAndAndroid.kt index 5ade8f9e4eac4..728488d72e810 100644 --- a/compose/animation/animation-core/src/jvmAndAndroidMain/kotlin/androidx/compose/animation/core/ArcSpline.jvmAndAndroid.kt +++ b/compose/animation/animation-core/src/jvmAndAndroidMain/kotlin/androidx/compose/animation/core/ArcSpline.jvmAndAndroid.kt @@ -16,11 +16,6 @@ package androidx.compose.animation.core -@Suppress("NOTHING_TO_INLINE") -internal actual inline fun toRadians(value: Double): Double { - return Math.toRadians(value) -} - @Suppress("NOTHING_TO_INLINE") internal actual inline fun binarySearch(array: FloatArray, position: Float): Int { return array.binarySearch(position) diff --git a/compose/animation/animation-core/src/linuxx64StubsMain/kotlin/androidx/compose/animation/core/ArcSpline.linuxx64Stubs.kt b/compose/animation/animation-core/src/linuxx64StubsMain/kotlin/androidx/compose/animation/core/ArcSpline.linuxx64Stubs.kt index d8d41dd9de498..9bd4c8e27e781 100644 --- a/compose/animation/animation-core/src/linuxx64StubsMain/kotlin/androidx/compose/animation/core/ArcSpline.linuxx64Stubs.kt +++ b/compose/animation/animation-core/src/linuxx64StubsMain/kotlin/androidx/compose/animation/core/ArcSpline.linuxx64Stubs.kt @@ -16,9 +16,6 @@ package androidx.compose.animation.core -@Suppress("NOTHING_TO_INLINE") -internal actual inline fun toRadians(value: Double): Double = implementedInJetBrainsFork() - @Suppress("NOTHING_TO_INLINE") internal actual inline fun binarySearch(array: FloatArray, position: Float): Int = implementedInJetBrainsFork() diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt index ecfcd2e395dd3..2ec9ce764e817 100644 --- a/compose/foundation/foundation-layout/api/current.txt +++ b/compose/foundation/foundation-layout/api/current.txt @@ -204,6 +204,9 @@ package androidx.compose.foundation.layout { property @Deprecated public abstract androidx.compose.ui.unit.Dp maxWidthInLine; } + @SuppressCompatibility @kotlin.RequiresOptIn(message="This foundation layout API is experimental and is likely to change or be removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGridApi { + } + @SuppressCompatibility @kotlin.RequiresOptIn(message="The API of this layout is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalLayoutApi { } @@ -275,6 +278,110 @@ package androidx.compose.foundation.layout { method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static androidx.compose.ui.Modifier! fillMaxRowHeight$default(androidx.compose.foundation.layout.FlowRowScope!, androidx.compose.ui.Modifier!, float, int, Object!); } + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.jvm.JvmInline public final value class Fr { + ctor @KotlinOnly public Fr(float value); + method @BytecodeOnly public static androidx.compose.foundation.layout.Fr! box-impl(float); + method @BytecodeOnly public static float constructor-impl(float); + method @InaccessibleFromKotlin public float getValue(); + method @BytecodeOnly public float unbox-impl(); + property public float value; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.foundation.layout.LayoutScopeMarker public interface GridConfigurationScope extends androidx.compose.ui.unit.Density { + method @KotlinOnly public void column(androidx.compose.foundation.layout.Fr weight); + method @KotlinOnly public void column(androidx.compose.foundation.layout.GridTrackSize size); + method @KotlinOnly public void column(androidx.compose.ui.unit.Dp size); + method public void column(float percentage); + method @BytecodeOnly public void column-0680j_4(float); + method @BytecodeOnly public void column-118E5d0(long); + method @BytecodeOnly public void column-XZblgos(float); + method @KotlinOnly public void columnGap(androidx.compose.ui.unit.Dp gap); + method @BytecodeOnly public void columnGap-0680j_4(float); + method @KotlinOnly public void gap(androidx.compose.ui.unit.Dp all); + method @KotlinOnly public void gap(androidx.compose.ui.unit.Dp row, androidx.compose.ui.unit.Dp column); + method @BytecodeOnly public void gap-0680j_4(float); + method @BytecodeOnly public void gap-YgX7TsA(float, float); + method @BytecodeOnly public int getFlow-ITJdzs4(); + method @BytecodeOnly public default float getFr-9P9H2UQ(double); + method @BytecodeOnly public default float getFr-9P9H2UQ(float); + method @BytecodeOnly public default float getFr-9P9H2UQ(int); + method @KotlinOnly public void row(androidx.compose.foundation.layout.Fr weight); + method @KotlinOnly public void row(androidx.compose.foundation.layout.GridTrackSize size); + method @KotlinOnly public void row(androidx.compose.ui.unit.Dp size); + method public void row(float percentage); + method @BytecodeOnly public void row-0680j_4(float); + method @BytecodeOnly public void row-118E5d0(long); + method @BytecodeOnly public void row-XZblgos(float); + method @KotlinOnly public void rowGap(androidx.compose.ui.unit.Dp gap); + method @BytecodeOnly public void rowGap-0680j_4(float); + method @BytecodeOnly public void setFlow-4t4_IgM(int); + property public abstract androidx.compose.foundation.layout.GridFlow flow; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr int.fr; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr float.fr; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr double.fr; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.jvm.JvmInline public final value class GridFlow { + method @BytecodeOnly public static androidx.compose.foundation.layout.GridFlow! box-impl(int); + method @BytecodeOnly public int unbox-impl(); + field public static final androidx.compose.foundation.layout.GridFlow.Companion Companion; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridFlow.Companion { + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public int getColumn-ITJdzs4(); + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public int getRow-ITJdzs4(); + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public inline androidx.compose.foundation.layout.GridFlow Column; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public inline androidx.compose.foundation.layout.GridFlow Row; + } + + @SuppressCompatibility public final class GridKt { + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Composable public static void Grid(kotlin.jvm.functions.Function1, androidx.compose.ui.Modifier?, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); + method @KotlinOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Composable public static inline void Grid(kotlin.jvm.functions.Function1 config, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1 content); + method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static void columns(androidx.compose.foundation.layout.GridConfigurationScope, androidx.compose.foundation.layout.GridTrackSpec... specs); + method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static void rows(androidx.compose.foundation.layout.GridConfigurationScope, androidx.compose.foundation.layout.GridTrackSpec... specs); + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Immutable @kotlin.jvm.JvmDefaultWithCompatibility public interface GridScope { + method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, optional int row, optional int column, optional int rowSpan, optional int columnSpan, optional androidx.compose.ui.Alignment alignment); + method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, kotlin.ranges.IntRange rows, kotlin.ranges.IntRange columns, optional androidx.compose.ui.Alignment alignment); + method @BytecodeOnly @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier! gridItem$default(androidx.compose.foundation.layout.GridScope!, androidx.compose.ui.Modifier!, int, int, int, int, androidx.compose.ui.Alignment!, int, Object!); + method @BytecodeOnly @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier! gridItem$default(androidx.compose.foundation.layout.GridScope!, androidx.compose.ui.Modifier!, kotlin.ranges.IntRange!, kotlin.ranges.IntRange!, androidx.compose.ui.Alignment!, int, Object!); + field public static final androidx.compose.foundation.layout.GridScope.Companion Companion; + field @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final int GridIndexUnspecified = 0; // 0x0 + field @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final int MaxGridIndex = 1000; // 0x3e8 + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridScope.Companion { + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static int GridIndexUnspecified; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static int MaxGridIndex; + field public static final int GridIndexUnspecified = 0; // 0x0 + field public static final int MaxGridIndex = 1000; // 0x3e8 + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class GridTrackSize implements androidx.compose.foundation.layout.GridTrackSpec { + method @BytecodeOnly public static androidx.compose.foundation.layout.GridTrackSize! box-impl(long); + method @BytecodeOnly public long unbox-impl(); + field public static final androidx.compose.foundation.layout.GridTrackSize.Companion Companion; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridTrackSize.Companion { + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Fixed(androidx.compose.ui.unit.Dp size); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Fixed-psSkOvk(float); + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Flex(@FloatRange(from=0.0) androidx.compose.foundation.layout.Fr weight); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Flex-KGB9zo8(@FloatRange(from=0.0) float); + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Percentage(@FloatRange(from=0.0) float value); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Percentage-9Tp3RV8(@FloatRange(from=0.0) float); + method @BytecodeOnly public long getAuto-eyNpfc4(); + method @BytecodeOnly public long getMaxContent-eyNpfc4(); + method @BytecodeOnly public long getMinContent-eyNpfc4(); + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Auto; + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize MaxContent; + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize MinContent; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public sealed exhaustive interface GridTrackSpec { + } + public final class IntrinsicKt { method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier height(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.IntrinsicSize intrinsicSize); method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier requiredHeight(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.IntrinsicSize intrinsicSize); diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt index e9d0231946d28..e72e674f85b17 100644 --- a/compose/foundation/foundation-layout/api/restricted_current.txt +++ b/compose/foundation/foundation-layout/api/restricted_current.txt @@ -223,6 +223,9 @@ package androidx.compose.foundation.layout { property @Deprecated public abstract androidx.compose.ui.unit.Dp maxWidthInLine; } + @SuppressCompatibility @kotlin.RequiresOptIn(message="This foundation layout API is experimental and is likely to change or be removed in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalGridApi { + } + @SuppressCompatibility @kotlin.RequiresOptIn(message="The API of this layout is experimental and is likely to change in the future.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) public @interface ExperimentalLayoutApi { } @@ -298,6 +301,123 @@ package androidx.compose.foundation.layout { method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalLayoutApi public static androidx.compose.ui.Modifier! fillMaxRowHeight$default(androidx.compose.foundation.layout.FlowRowScope!, androidx.compose.ui.Modifier!, float, int, Object!); } + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.jvm.JvmInline public final value class Fr { + ctor @KotlinOnly public Fr(float value); + method @BytecodeOnly public static androidx.compose.foundation.layout.Fr! box-impl(float); + method @BytecodeOnly public static float constructor-impl(float); + method @InaccessibleFromKotlin public float getValue(); + method @BytecodeOnly public float unbox-impl(); + property public float value; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.foundation.layout.LayoutScopeMarker public interface GridConfigurationScope extends androidx.compose.ui.unit.Density { + method @KotlinOnly public void column(androidx.compose.foundation.layout.Fr weight); + method @KotlinOnly public void column(androidx.compose.foundation.layout.GridTrackSize size); + method @KotlinOnly public void column(androidx.compose.ui.unit.Dp size); + method public void column(float percentage); + method @BytecodeOnly public void column-0680j_4(float); + method @BytecodeOnly public void column-118E5d0(long); + method @BytecodeOnly public void column-XZblgos(float); + method @KotlinOnly public void columnGap(androidx.compose.ui.unit.Dp gap); + method @BytecodeOnly public void columnGap-0680j_4(float); + method @KotlinOnly public void gap(androidx.compose.ui.unit.Dp all); + method @KotlinOnly public void gap(androidx.compose.ui.unit.Dp row, androidx.compose.ui.unit.Dp column); + method @BytecodeOnly public void gap-0680j_4(float); + method @BytecodeOnly public void gap-YgX7TsA(float, float); + method @BytecodeOnly public int getFlow-ITJdzs4(); + method @BytecodeOnly public default float getFr-9P9H2UQ(double); + method @BytecodeOnly public default float getFr-9P9H2UQ(float); + method @BytecodeOnly public default float getFr-9P9H2UQ(int); + method @KotlinOnly public void row(androidx.compose.foundation.layout.Fr weight); + method @KotlinOnly public void row(androidx.compose.foundation.layout.GridTrackSize size); + method @KotlinOnly public void row(androidx.compose.ui.unit.Dp size); + method public void row(float percentage); + method @BytecodeOnly public void row-0680j_4(float); + method @BytecodeOnly public void row-118E5d0(long); + method @BytecodeOnly public void row-XZblgos(float); + method @KotlinOnly public void rowGap(androidx.compose.ui.unit.Dp gap); + method @BytecodeOnly public void rowGap-0680j_4(float); + method @BytecodeOnly public void setFlow-4t4_IgM(int); + property public abstract androidx.compose.foundation.layout.GridFlow flow; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr int.fr; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr float.fr; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Stable public default androidx.compose.foundation.layout.Fr double.fr; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.jvm.JvmInline public final value class GridFlow { + ctor @KotlinOnly @kotlin.PublishedApi internal GridFlow(int bits); + method @BytecodeOnly public static androidx.compose.foundation.layout.GridFlow! box-impl(int); + method @BytecodeOnly @kotlin.PublishedApi internal static int constructor-impl(int); + method @BytecodeOnly public int unbox-impl(); + field public static final androidx.compose.foundation.layout.GridFlow.Companion Companion; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridFlow.Companion { + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public int getColumn-ITJdzs4(); + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public int getRow-ITJdzs4(); + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public inline androidx.compose.foundation.layout.GridFlow Column; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public inline androidx.compose.foundation.layout.GridFlow Row; + } + + @SuppressCompatibility public final class GridKt { + method @BytecodeOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Composable public static void Grid(kotlin.jvm.functions.Function1, androidx.compose.ui.Modifier?, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); + method @KotlinOnly @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Composable public static inline void Grid(kotlin.jvm.functions.Function1 config, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function1 content); + method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static void columns(androidx.compose.foundation.layout.GridConfigurationScope, androidx.compose.foundation.layout.GridTrackSpec... specs); + method @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static void rows(androidx.compose.foundation.layout.GridConfigurationScope, androidx.compose.foundation.layout.GridTrackSpec... specs); + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.PublishedApi internal final class GridMeasurePolicy implements androidx.compose.ui.layout.MeasurePolicy { + ctor public GridMeasurePolicy(androidx.compose.runtime.State> configState); + method @KotlinOnly public androidx.compose.ui.layout.MeasureResult measure(androidx.compose.ui.layout.MeasureScope, java.util.List measurables, androidx.compose.ui.unit.Constraints constraints); + method @BytecodeOnly public androidx.compose.ui.layout.MeasureResult measure-3p2s80s(androidx.compose.ui.layout.MeasureScope, java.util.List, long); + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.foundation.layout.LayoutScopeMarker @androidx.compose.runtime.Immutable @kotlin.jvm.JvmDefaultWithCompatibility public interface GridScope { + method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, optional int row, optional int column, optional int rowSpan, optional int columnSpan, optional androidx.compose.ui.Alignment alignment); + method @androidx.compose.runtime.Stable public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, kotlin.ranges.IntRange rows, kotlin.ranges.IntRange columns, optional androidx.compose.ui.Alignment alignment); + method @BytecodeOnly @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier! gridItem$default(androidx.compose.foundation.layout.GridScope!, androidx.compose.ui.Modifier!, int, int, int, int, androidx.compose.ui.Alignment!, int, Object!); + method @BytecodeOnly @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier! gridItem$default(androidx.compose.foundation.layout.GridScope!, androidx.compose.ui.Modifier!, kotlin.ranges.IntRange!, kotlin.ranges.IntRange!, androidx.compose.ui.Alignment!, int, Object!); + field public static final androidx.compose.foundation.layout.GridScope.Companion Companion; + field @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final int GridIndexUnspecified = 0; // 0x0 + field @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final int MaxGridIndex = 1000; // 0x3e8 + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridScope.Companion { + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static int GridIndexUnspecified; + property @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static int MaxGridIndex; + field public static final int GridIndexUnspecified = 0; // 0x0 + field public static final int MaxGridIndex = 1000; // 0x3e8 + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @kotlin.PublishedApi internal final class GridScopeInstance implements androidx.compose.foundation.layout.GridScope { + method public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, int row, int column, int rowSpan, int columnSpan, androidx.compose.ui.Alignment alignment); + method public androidx.compose.ui.Modifier gridItem(androidx.compose.ui.Modifier, kotlin.ranges.IntRange rows, kotlin.ranges.IntRange columns, androidx.compose.ui.Alignment alignment); + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi @androidx.compose.runtime.Immutable @kotlin.jvm.JvmInline public final value class GridTrackSize implements androidx.compose.foundation.layout.GridTrackSpec { + method @BytecodeOnly public static androidx.compose.foundation.layout.GridTrackSize! box-impl(long); + method @BytecodeOnly public long unbox-impl(); + field public static final androidx.compose.foundation.layout.GridTrackSize.Companion Companion; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public static final class GridTrackSize.Companion { + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Fixed(androidx.compose.ui.unit.Dp size); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Fixed-psSkOvk(float); + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Flex(@FloatRange(from=0.0) androidx.compose.foundation.layout.Fr weight); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Flex-KGB9zo8(@FloatRange(from=0.0) float); + method @KotlinOnly @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Percentage(@FloatRange(from=0.0) float value); + method @BytecodeOnly @androidx.compose.runtime.Stable public long Percentage-9Tp3RV8(@FloatRange(from=0.0) float); + method @BytecodeOnly public long getAuto-eyNpfc4(); + method @BytecodeOnly public long getMaxContent-eyNpfc4(); + method @BytecodeOnly public long getMinContent-eyNpfc4(); + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize Auto; + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize MaxContent; + property @androidx.compose.runtime.Stable public androidx.compose.foundation.layout.GridTrackSize MinContent; + } + + @SuppressCompatibility @androidx.compose.foundation.layout.ExperimentalGridApi public sealed exhaustive interface GridTrackSpec { + } + public final class IntrinsicKt { method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier height(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.IntrinsicSize intrinsicSize); method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier requiredHeight(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.IntrinsicSize intrinsicSize); diff --git a/compose/foundation/foundation-layout/bcv/native/current.txt b/compose/foundation/foundation-layout/bcv/native/current.txt index c4aa43818895d..b804a99535070 100644 --- a/compose/foundation/foundation-layout/bcv/native/current.txt +++ b/compose/foundation/foundation-layout/bcv/native/current.txt @@ -6,6 +6,10 @@ // - Show declarations: true // Library unique name: +open annotation class androidx.compose.foundation.layout/ExperimentalGridApi : kotlin/Annotation { // androidx.compose.foundation.layout/ExperimentalGridApi|null[0] + constructor () // androidx.compose.foundation.layout/ExperimentalGridApi.|(){}[0] +} + open annotation class androidx.compose.foundation.layout/ExperimentalLayoutApi : kotlin/Annotation { // androidx.compose.foundation.layout/ExperimentalLayoutApi|null[0] constructor () // androidx.compose.foundation.layout/ExperimentalLayoutApi.|(){}[0] } @@ -54,6 +58,44 @@ abstract interface androidx.compose.foundation.layout/FlowColumnScope : androidx abstract interface androidx.compose.foundation.layout/FlowRowScope : androidx.compose.foundation.layout/RowScope // androidx.compose.foundation.layout/FlowRowScope|null[0] +abstract interface androidx.compose.foundation.layout/GridConfigurationScope : androidx.compose.ui.unit/Density { // androidx.compose.foundation.layout/GridConfigurationScope|null[0] + open val fr // androidx.compose.foundation.layout/GridConfigurationScope.fr|@kotlin.Double{}fr[0] + open fun (kotlin/Double).(): androidx.compose.foundation.layout/Fr // androidx.compose.foundation.layout/GridConfigurationScope.fr.|@kotlin.Double(){}[0] + open val fr // androidx.compose.foundation.layout/GridConfigurationScope.fr|@kotlin.Float{}fr[0] + open fun (kotlin/Float).(): androidx.compose.foundation.layout/Fr // androidx.compose.foundation.layout/GridConfigurationScope.fr.|@kotlin.Float(){}[0] + open val fr // androidx.compose.foundation.layout/GridConfigurationScope.fr|@kotlin.Int{}fr[0] + open fun (kotlin/Int).(): androidx.compose.foundation.layout/Fr // androidx.compose.foundation.layout/GridConfigurationScope.fr.|@kotlin.Int(){}[0] + + abstract var flow // androidx.compose.foundation.layout/GridConfigurationScope.flow|{}flow[0] + abstract fun (): androidx.compose.foundation.layout/GridFlow // androidx.compose.foundation.layout/GridConfigurationScope.flow.|(){}[0] + abstract fun (androidx.compose.foundation.layout/GridFlow) // androidx.compose.foundation.layout/GridConfigurationScope.flow.|(androidx.compose.foundation.layout.GridFlow){}[0] + + abstract fun column(androidx.compose.foundation.layout/Fr) // androidx.compose.foundation.layout/GridConfigurationScope.column|column(androidx.compose.foundation.layout.Fr){}[0] + abstract fun column(androidx.compose.foundation.layout/GridTrackSize) // androidx.compose.foundation.layout/GridConfigurationScope.column|column(androidx.compose.foundation.layout.GridTrackSize){}[0] + abstract fun column(androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.column|column(androidx.compose.ui.unit.Dp){}[0] + abstract fun column(kotlin/Float) // androidx.compose.foundation.layout/GridConfigurationScope.column|column(kotlin.Float){}[0] + abstract fun columnGap(androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.columnGap|columnGap(androidx.compose.ui.unit.Dp){}[0] + abstract fun gap(androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.gap|gap(androidx.compose.ui.unit.Dp){}[0] + abstract fun gap(androidx.compose.ui.unit/Dp, androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.gap|gap(androidx.compose.ui.unit.Dp;androidx.compose.ui.unit.Dp){}[0] + abstract fun row(androidx.compose.foundation.layout/Fr) // androidx.compose.foundation.layout/GridConfigurationScope.row|row(androidx.compose.foundation.layout.Fr){}[0] + abstract fun row(androidx.compose.foundation.layout/GridTrackSize) // androidx.compose.foundation.layout/GridConfigurationScope.row|row(androidx.compose.foundation.layout.GridTrackSize){}[0] + abstract fun row(androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.row|row(androidx.compose.ui.unit.Dp){}[0] + abstract fun row(kotlin/Float) // androidx.compose.foundation.layout/GridConfigurationScope.row|row(kotlin.Float){}[0] + abstract fun rowGap(androidx.compose.ui.unit/Dp) // androidx.compose.foundation.layout/GridConfigurationScope.rowGap|rowGap(androidx.compose.ui.unit.Dp){}[0] +} + +abstract interface androidx.compose.foundation.layout/GridScope { // androidx.compose.foundation.layout/GridScope|null[0] + abstract fun (androidx.compose.ui/Modifier).gridItem(kotlin.ranges/IntRange, kotlin.ranges/IntRange, androidx.compose.ui/Alignment = ...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/GridScope.gridItem|gridItem@androidx.compose.ui.Modifier(kotlin.ranges.IntRange;kotlin.ranges.IntRange;androidx.compose.ui.Alignment){}[0] + abstract fun (androidx.compose.ui/Modifier).gridItem(kotlin/Int = ..., kotlin/Int = ..., kotlin/Int = ..., kotlin/Int = ..., androidx.compose.ui/Alignment = ...): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/GridScope.gridItem|gridItem@androidx.compose.ui.Modifier(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;androidx.compose.ui.Alignment){}[0] + + final object Companion { // androidx.compose.foundation.layout/GridScope.Companion|null[0] + final const val GridIndexUnspecified // androidx.compose.foundation.layout/GridScope.Companion.GridIndexUnspecified|{}GridIndexUnspecified[0] + final fun (): kotlin/Int // androidx.compose.foundation.layout/GridScope.Companion.GridIndexUnspecified.|(){}[0] + final const val MaxGridIndex // androidx.compose.foundation.layout/GridScope.Companion.MaxGridIndex|{}MaxGridIndex[0] + final fun (): kotlin/Int // androidx.compose.foundation.layout/GridScope.Companion.MaxGridIndex.|(){}[0] + } +} + abstract interface androidx.compose.foundation.layout/PaddingValues { // androidx.compose.foundation.layout/PaddingValues|null[0] abstract fun calculateBottomPadding(): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/PaddingValues.calculateBottomPadding|calculateBottomPadding(){}[0] abstract fun calculateLeftPadding(androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/PaddingValues.calculateLeftPadding|calculateLeftPadding(androidx.compose.ui.unit.LayoutDirection){}[0] @@ -95,6 +137,59 @@ abstract interface androidx.compose.foundation.layout/WindowInsets { // androidx final object Companion // androidx.compose.foundation.layout/WindowInsets.Companion|null[0] } +sealed interface androidx.compose.foundation.layout/GridTrackSpec // androidx.compose.foundation.layout/GridTrackSpec|null[0] + +final class androidx.compose.foundation.layout/GridMeasurePolicy : androidx.compose.ui.layout/MeasurePolicy { // androidx.compose.foundation.layout/GridMeasurePolicy|null[0] + constructor (androidx.compose.runtime/State>) // androidx.compose.foundation.layout/GridMeasurePolicy.|(androidx.compose.runtime.State>){}[0] + + final fun (androidx.compose.ui.layout/MeasureScope).measure(kotlin.collections/List, androidx.compose.ui.unit/Constraints): androidx.compose.ui.layout/MeasureResult // androidx.compose.foundation.layout/GridMeasurePolicy.measure|measure@androidx.compose.ui.layout.MeasureScope(kotlin.collections.List;androidx.compose.ui.unit.Constraints){}[0] +} + +final value class androidx.compose.foundation.layout/Fr { // androidx.compose.foundation.layout/Fr|null[0] + constructor (kotlin/Float) // androidx.compose.foundation.layout/Fr.|(kotlin.Float){}[0] + + final val value // androidx.compose.foundation.layout/Fr.value|{}value[0] + final fun (): kotlin/Float // androidx.compose.foundation.layout/Fr.value.|(){}[0] + + final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.layout/Fr.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // androidx.compose.foundation.layout/Fr.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // androidx.compose.foundation.layout/Fr.toString|toString(){}[0] +} + +final value class androidx.compose.foundation.layout/GridFlow { // androidx.compose.foundation.layout/GridFlow|null[0] + constructor (kotlin/Int) // androidx.compose.foundation.layout/GridFlow.|(kotlin.Int){}[0] + + final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.layout/GridFlow.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // androidx.compose.foundation.layout/GridFlow.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // androidx.compose.foundation.layout/GridFlow.toString|toString(){}[0] + + final object Companion { // androidx.compose.foundation.layout/GridFlow.Companion|null[0] + final val Column // androidx.compose.foundation.layout/GridFlow.Companion.Column|{}Column[0] + final inline fun (): androidx.compose.foundation.layout/GridFlow // androidx.compose.foundation.layout/GridFlow.Companion.Column.|(){}[0] + final val Row // androidx.compose.foundation.layout/GridFlow.Companion.Row|{}Row[0] + final inline fun (): androidx.compose.foundation.layout/GridFlow // androidx.compose.foundation.layout/GridFlow.Companion.Row.|(){}[0] + } +} + +final value class androidx.compose.foundation.layout/GridTrackSize : androidx.compose.foundation.layout/GridTrackSpec { // androidx.compose.foundation.layout/GridTrackSize|null[0] + final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.layout/GridTrackSize.equals|equals(kotlin.Any?){}[0] + final fun hashCode(): kotlin/Int // androidx.compose.foundation.layout/GridTrackSize.hashCode|hashCode(){}[0] + final fun toString(): kotlin/String // androidx.compose.foundation.layout/GridTrackSize.toString|toString(){}[0] + + final object Companion { // androidx.compose.foundation.layout/GridTrackSize.Companion|null[0] + final val Auto // androidx.compose.foundation.layout/GridTrackSize.Companion.Auto|{}Auto[0] + final fun (): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.Auto.|(){}[0] + final val MaxContent // androidx.compose.foundation.layout/GridTrackSize.Companion.MaxContent|{}MaxContent[0] + final fun (): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.MaxContent.|(){}[0] + final val MinContent // androidx.compose.foundation.layout/GridTrackSize.Companion.MinContent|{}MinContent[0] + final fun (): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.MinContent.|(){}[0] + + final fun Fixed(androidx.compose.ui.unit/Dp): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.Fixed|Fixed(androidx.compose.ui.unit.Dp){}[0] + final fun Flex(androidx.compose.foundation.layout/Fr): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.Flex|Flex(androidx.compose.foundation.layout.Fr){}[0] + final fun Percentage(kotlin/Float): androidx.compose.foundation.layout/GridTrackSize // androidx.compose.foundation.layout/GridTrackSize.Companion.Percentage|Percentage(kotlin.Float){}[0] + } +} + final value class androidx.compose.foundation.layout/WindowInsetsSides { // androidx.compose.foundation.layout/WindowInsetsSides|null[0] final fun equals(kotlin/Any?): kotlin/Boolean // androidx.compose.foundation.layout/WindowInsetsSides.equals|equals(kotlin.Any?){}[0] final fun hashCode(): kotlin/Int // androidx.compose.foundation.layout/WindowInsetsSides.hashCode|hashCode(){}[0] @@ -197,6 +292,11 @@ final object androidx.compose.foundation.layout/ColumnScopeInstance : androidx.c final fun (androidx.compose.ui/Modifier).weight(kotlin/Float, kotlin/Boolean): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/ColumnScopeInstance.weight|weight@androidx.compose.ui.Modifier(kotlin.Float;kotlin.Boolean){}[0] } +final object androidx.compose.foundation.layout/GridScopeInstance : androidx.compose.foundation.layout/GridScope { // androidx.compose.foundation.layout/GridScopeInstance|null[0] + final fun (androidx.compose.ui/Modifier).gridItem(kotlin.ranges/IntRange, kotlin.ranges/IntRange, androidx.compose.ui/Alignment): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/GridScopeInstance.gridItem|gridItem@androidx.compose.ui.Modifier(kotlin.ranges.IntRange;kotlin.ranges.IntRange;androidx.compose.ui.Alignment){}[0] + final fun (androidx.compose.ui/Modifier).gridItem(kotlin/Int, kotlin/Int, kotlin/Int, kotlin/Int, androidx.compose.ui/Alignment): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/GridScopeInstance.gridItem|gridItem@androidx.compose.ui.Modifier(kotlin.Int;kotlin.Int;kotlin.Int;kotlin.Int;androidx.compose.ui.Alignment){}[0] +} + final object androidx.compose.foundation.layout/RowScopeInstance : androidx.compose.foundation.layout/RowScope { // androidx.compose.foundation.layout/RowScopeInstance|null[0] final fun (androidx.compose.ui/Modifier).align(androidx.compose.ui/Alignment.Vertical): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/RowScopeInstance.align|align@androidx.compose.ui.Modifier(androidx.compose.ui.Alignment.Vertical){}[0] final fun (androidx.compose.ui/Modifier).alignBy(androidx.compose.ui.layout/HorizontalAlignmentLine): androidx.compose.ui/Modifier // androidx.compose.foundation.layout/RowScopeInstance.alignBy|alignBy@androidx.compose.ui.Modifier(androidx.compose.ui.layout.HorizontalAlignmentLine){}[0] @@ -252,6 +352,8 @@ final val androidx.compose.foundation.layout/tappableElement // androidx.compose final val androidx.compose.foundation.layout/waterfall // androidx.compose.foundation.layout/waterfall|@androidx.compose.foundation.layout.WindowInsets.Companion{}waterfall[0] final fun (androidx.compose.foundation.layout/WindowInsets.Companion).(androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.foundation.layout/WindowInsets // androidx.compose.foundation.layout/waterfall.|@androidx.compose.foundation.layout.WindowInsets.Companion(androidx.compose.runtime.Composer?;kotlin.Int){}[0] +final fun (androidx.compose.foundation.layout/GridConfigurationScope).androidx.compose.foundation.layout/columns(kotlin/Array...) // androidx.compose.foundation.layout/columns|columns@androidx.compose.foundation.layout.GridConfigurationScope(kotlin.Array...){}[0] +final fun (androidx.compose.foundation.layout/GridConfigurationScope).androidx.compose.foundation.layout/rows(kotlin/Array...) // androidx.compose.foundation.layout/rows|rows@androidx.compose.foundation.layout.GridConfigurationScope(kotlin.Array...){}[0] final fun (androidx.compose.foundation.layout/PaddingValues).androidx.compose.foundation.layout/calculateEndPadding(androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/calculateEndPadding|calculateEndPadding@androidx.compose.foundation.layout.PaddingValues(androidx.compose.ui.unit.LayoutDirection){}[0] final fun (androidx.compose.foundation.layout/PaddingValues).androidx.compose.foundation.layout/calculateStartPadding(androidx.compose.ui.unit/LayoutDirection): androidx.compose.ui.unit/Dp // androidx.compose.foundation.layout/calculateStartPadding|calculateStartPadding@androidx.compose.foundation.layout.PaddingValues(androidx.compose.ui.unit.LayoutDirection){}[0] final fun (androidx.compose.foundation.layout/PaddingValues).androidx.compose.foundation.layout/minus(androidx.compose.foundation.layout/PaddingValues): androidx.compose.foundation.layout/PaddingValues // androidx.compose.foundation.layout/minus|minus@androidx.compose.foundation.layout.PaddingValues(androidx.compose.foundation.layout.PaddingValues){}[0] @@ -360,4 +462,5 @@ final fun androidx.compose.foundation.layout/rowMeasurePolicy(androidx.compose.f final fun androidx.compose.foundation.layout/rowMeasurementHelper(androidx.compose.foundation.layout/Arrangement.Horizontal, androidx.compose.foundation.layout/Arrangement.Vertical, kotlin/Int, androidx.compose.runtime/Composer?, kotlin/Int): androidx.compose.ui.layout/MeasurePolicy // androidx.compose.foundation.layout/rowMeasurementHelper|rowMeasurementHelper(androidx.compose.foundation.layout.Arrangement.Horizontal;androidx.compose.foundation.layout.Arrangement.Vertical;kotlin.Int;androidx.compose.runtime.Composer?;kotlin.Int){}[0] final inline fun androidx.compose.foundation.layout/Box(androidx.compose.ui/Modifier?, androidx.compose.ui/Alignment?, kotlin/Boolean, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.foundation.layout/Box|Box(androidx.compose.ui.Modifier?;androidx.compose.ui.Alignment?;kotlin.Boolean;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] final inline fun androidx.compose.foundation.layout/Column(androidx.compose.ui/Modifier?, androidx.compose.foundation.layout/Arrangement.Vertical?, androidx.compose.ui/Alignment.Horizontal?, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.foundation.layout/Column|Column(androidx.compose.ui.Modifier?;androidx.compose.foundation.layout.Arrangement.Vertical?;androidx.compose.ui.Alignment.Horizontal?;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] +final inline fun androidx.compose.foundation.layout/Grid(noinline kotlin/Function1, androidx.compose.ui/Modifier?, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.foundation.layout/Grid|Grid(kotlin.Function1;androidx.compose.ui.Modifier?;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] final inline fun androidx.compose.foundation.layout/Row(androidx.compose.ui/Modifier?, androidx.compose.foundation.layout/Arrangement.Horizontal?, androidx.compose.ui/Alignment.Vertical?, kotlin/Function3, androidx.compose.runtime/Composer?, kotlin/Int, kotlin/Int) // androidx.compose.foundation.layout/Row|Row(androidx.compose.ui.Modifier?;androidx.compose.foundation.layout.Arrangement.Horizontal?;androidx.compose.ui.Alignment.Vertical?;kotlin.Function3;androidx.compose.runtime.Composer?;kotlin.Int;kotlin.Int){}[0] diff --git a/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/GridDemo.kt b/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/GridDemo.kt new file mode 100644 index 0000000000000..114ac0f029c54 --- /dev/null +++ b/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/GridDemo.kt @@ -0,0 +1,413 @@ +/* + * Copyright 2026 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. + */ + +@file:OptIn(ExperimentalGridApi::class) + +package androidx.compose.foundation.layout.demos + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalGridApi +import androidx.compose.foundation.layout.Grid +import androidx.compose.foundation.layout.GridFlow +import androidx.compose.foundation.layout.GridScope +import androidx.compose.foundation.layout.GridTrackSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.columns +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +@Composable +fun GridDemo() { + Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) { + MixedSizingDemo() + Spacer(Modifier.height(32.dp)) + FlexibleSizingDemo() + Spacer(Modifier.height(32.dp)) + ContentBasedSizingDemo() + Spacer(Modifier.height(32.dp)) + NegativeIndicesDemo() + Spacer(Modifier.height(32.dp)) + GapsAndContentDemo() + Spacer(Modifier.height(32.dp)) + AlignmentDemo() + Spacer(Modifier.height(32.dp)) + AutoPlacementDemo() + Spacer(Modifier.height(32.dp)) + InfiniteConstraintsDemo() + Spacer(Modifier.height(32.dp)) + MinContentSafetyDemo() + } +} + +@Composable +private fun AutoPlacementDemo() { + DemoHeader("Auto Placement & Flow") + + Text( + "1. Flow = Row (Fixed Cols, Implicit Rows)", + fontSize = 12.sp, + fontStyle = FontStyle.Italic, + modifier = Modifier.padding(bottom = 4.dp), + ) + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(80.dp)) } // 3 Explicit Columns + gap(4.dp) + flow = GridFlow.Row // Default + }, + modifier = Modifier.demoContainer(borderColor = Color.Blue), + ) { + // 1. Simple auto items + repeat(3) { index -> + GridDemoItem(text = "${index + 1}", color = Color.Cyan, measureSize = false) + } + + // 2. Auto item with Span (Takes 2 spots) + GridDemoItem(text = "Span 2", columnSpan = 2, color = Color.Magenta, measureSize = false) + + // 3. More auto items (Wrapping to next row) + repeat(2) { index -> + GridDemoItem(text = "${index + 5}", color = Color.Cyan, measureSize = false) + } + } + + Spacer(Modifier.height(24.dp)) + + Text( + "2. Flow = Column (Fixed Rows, Implicit Cols)", + fontSize = 12.sp, + fontStyle = FontStyle.Italic, + modifier = Modifier.padding(bottom = 4.dp), + ) + // Scrollable container to allow implicit columns to grow horizontally + Box(Modifier.fillMaxWidth().horizontalScroll(rememberScrollState())) { + Grid( + config = { + flow = GridFlow.Column + repeat(3) { row(50.dp) } // 3 Explicit Rows + gap(4.dp) + }, + modifier = Modifier.border(1.dp, Color.Magenta.copy(alpha = 0.5f)).padding(8.dp), + ) { + repeat(10) { index -> + GridDemoItem( + text = "${index + 1}", + color = if (index % 2 == 0) Color.Yellow else Color.Green, + measureSize = false, + // Explicit size helps visualization in 'Auto' implicit tracks + modifier = Modifier.size(60.dp, 40.dp), + ) + } + } + } +} + +@Composable +private fun MixedSizingDemo() { + DemoHeader("Mixed Sizing: Fixed vs Fraction vs Flex") + Grid( + config = { + columns( + GridTrackSize.Fixed(100.dp), + GridTrackSize.Percentage(0.3f), + GridTrackSize.Flex(1.fr), + ) + row(100.dp) + }, + modifier = Modifier.demoContainer(), + ) { + GridDemoItem(text = "Fixed\n100dp", color = Color.Red, row = 1, column = 1) + GridDemoItem(text = "Fraction\n30% of Total", color = Color.Blue, row = 1, column = 2) + GridDemoItem(text = "Flex\nRest of Space", color = Color.Green, row = 1, column = 3) + } +} + +@Composable +private fun FlexibleSizingDemo() { + DemoHeader("Flexible (Fr) Sizing") + Grid( + config = { + column(80.dp) + column(1.fr) + column(2.fr) + row(1.fr) + row(60.dp) + }, + modifier = Modifier.height(200.dp).demoContainer(borderColor = Color.Magenta), + ) { + val rowLabels = listOf("Flex 1.fr", "60dp") + val colLabels = listOf("Fixed 80dp", "Flex 1.fr", "Flex 2.fr") + + rowLabels.forEachIndexed { rowIndex, rowLabel -> + colLabels.forEachIndexed { colIndex, colLabel -> + GridDemoItem( + text = "H: $rowLabel\nW: $colLabel", + row = rowIndex + 1, + column = colIndex + 1, + ) + } + } + } +} + +@Composable +fun NegativeIndicesDemo() { + DemoHeader("Negative Indices") + Grid( + config = { + repeat(3) { column(60.dp) } + repeat(3) { row(60.dp) } + gap(4.dp) + }, + modifier = Modifier.border(1.dp, Color.Gray), + ) { + GridDemoItem(text = "TL", row = 1, column = 1, color = Color.Red) + GridDemoItem("TR", row = 1, column = -1, color = Color.Blue) + GridDemoItem("BL", row = -1, column = 1, color = Color.Green) + GridDemoItem("BR", row = -1, column = -1, color = Color.Yellow) + GridDemoItem("Center", row = 2, column = 2, color = Color.Gray) + } +} + +@Composable +private fun ContentBasedSizingDemo() { + DemoHeader("Intrinsic Sizing (Min vs Max Content)") + Grid( + config = { + column(GridTrackSize.MinContent) + column(GridTrackSize.MaxContent) + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Auto) + row(GridTrackSize.Auto) + gap(8.dp) + }, + modifier = Modifier.demoContainer(borderColor = Color.Black), + ) { + GridDemoItem(text = "Min Content\nWraps", row = 1, column = 1, color = Color.Red) + GridDemoItem(text = "Max Content Expands", row = 1, column = 2, color = Color.Blue) + GridDemoItem(text = "Flex Fills\nRemainder", row = 1, column = 3, color = Color.Green) + GridDemoItem(text = "Auto\nContent", row = 1, column = 4, color = Color.Yellow) + } +} + +@Composable +private fun GapsAndContentDemo() { + DemoHeader("Gaps & Content Sizing") + Grid( + config = { + column(GridTrackSize.Fixed(100.dp)) + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Fixed(200.dp)) + row(GridTrackSize.Fixed(60.dp)) + row(GridTrackSize.Fixed(100.dp)) + gap(row = 12.dp, column = 6.dp) + }, + modifier = Modifier.demoContainer(borderColor = Color.Cyan), + ) { + repeat(6) { + val row = (it / 3) + 1 + val col = (it % 3) + 1 + GridDemoItem(text = "Item ${it + 1}", measureSize = false, row = row, column = col) + } + } +} + +@Composable +private fun AlignmentDemo() { + DemoHeader("Cell Content Alignment") + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(100.dp)) } + repeat(3) { row(GridTrackSize.Fixed(100.dp)) } + gap(4.dp) + }, + modifier = Modifier.demoContainer(borderColor = Color.Red), + ) { + val alignments = + listOf( + Alignment.TopStart to "TopStart", + Alignment.TopCenter to "TopCenter", + Alignment.TopEnd to "TopEnd", + Alignment.CenterStart to "CenterStart", + Alignment.Center to "Center", + Alignment.CenterEnd to "CenterEnd", + Alignment.BottomStart to "BottomStart", + Alignment.BottomCenter to "BottomCenter", + Alignment.BottomEnd to "BottomEnd", + ) + + alignments.forEachIndexed { index, (alignment, name) -> + val row = (index / 3) + 1 + val col = (index % 3) + 1 + + Box( + Modifier.gridItem(row, col) + .fillMaxSize() + .background(Color.LightGray.copy(alpha = 0.2f)) + .border(1.dp, Color.DarkGray.copy(alpha = 0.1f)) + ) + + Box( + Modifier.gridItem(row, col, alignment = alignment) + .size(60.dp, 40.dp) + .background(Color.Yellow.copy(alpha = 0.7f)) + .border(1.dp, Color.Red), + contentAlignment = Alignment.Center, + ) { + Text(name, fontSize = 10.sp) + } + } + } +} + +@Composable +private fun InfiniteConstraintsDemo() { + DemoHeader("Infinite Constraints") + Text( + "Percentage tracks fall back to Auto sizing when placed in an infinite container.", + fontSize = 12.sp, + fontStyle = FontStyle.Italic, + modifier = Modifier.padding(bottom = 4.dp), + ) + + Row( + Modifier.fillMaxWidth() + .border(1.dp, Color.Gray) + .padding(8.dp) + .horizontalScroll(rememberScrollState()) + ) { + Grid( + config = { + column(GridTrackSize.Percentage(0.5f)) + row(GridTrackSize.Auto) + gap(4.dp) + }, + modifier = Modifier.border(1.dp, Color.Blue), + ) { + GridDemoItem( + text = "I am 150dp wide\n(Percentage -> Auto)", + modifier = Modifier.width(150.dp), + color = Color.Cyan, + ) + } + } +} + +@Composable +private fun MinContentSafetyDemo() { + DemoHeader("Min-Content Flex") + Text( + "Flex tracks implement minmax(min-content, 1fr).", + fontSize = 12.sp, + fontStyle = FontStyle.Italic, + modifier = Modifier.padding(bottom = 4.dp), + ) + Box(Modifier.width(50.dp).border(2.dp, Color.Red).padding(2.dp)) { + Grid( + config = { + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Auto) + }, + modifier = Modifier.border(1.dp, Color.Green), + ) { + GridDemoItem( + text = "Min 120dp", + modifier = Modifier.width(120.dp), + color = Color.Magenta, + ) + } + } +} + +@Composable +private fun DemoHeader(text: String) = + Text( + text, + fontSize = 16.sp, + fontWeight = FontWeight.Medium, + modifier = Modifier.padding(bottom = 8.dp), + ) + +@Composable +private fun GridScope.GridDemoItem( + text: String, + modifier: Modifier = Modifier, + row: Int? = null, + column: Int? = null, + rowSpan: Int = 1, + columnSpan: Int = 1, + color: Color = Color.Green, + measureSize: Boolean = true, +) { + var size by remember { mutableStateOf(IntSize.Zero) } + val density = LocalDensity.current + var finalModifier = modifier.fillMaxSize() + + if (row != null && column != null) { + finalModifier = finalModifier.gridItem(row, column, rowSpan, columnSpan) + } else if (rowSpan > 1 || columnSpan > 1) { + finalModifier = finalModifier.gridItem(rowSpan = rowSpan, columnSpan = columnSpan) + } + + Box( + finalModifier + .onSizeChanged { size = it } + .background(color.copy(alpha = 0.1f)) + .border(1.dp, color.copy(alpha = 0.5f)) + .padding(2.dp), + contentAlignment = Alignment.Center, + ) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text(text = text, fontSize = 10.sp, textAlign = TextAlign.Center) + if (measureSize) { + val w = with(density) { size.width.toDp().value.toInt() } + val h = with(density) { size.height.toDp().value.toInt() } + Text(text = "$w x $h", fontSize = 9.sp, fontWeight = FontWeight.Bold) + } + } + } +} + +private fun Modifier.demoContainer(borderColor: Color = Color.Black) = + this.fillMaxWidth().border(1.dp, borderColor.copy(alpha = 0.5f)).padding(8.dp) diff --git a/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/LayoutDemos.kt b/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/LayoutDemos.kt index 18ed55e40f433..c348dfe2d5e9c 100644 --- a/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/LayoutDemos.kt +++ b/compose/foundation/foundation-layout/integration-tests/layout-demos/src/main/java/androidx/compose/foundation/layout/demos/LayoutDemos.kt @@ -29,5 +29,6 @@ val LayoutDemos = ComposableDemo("Contextual Flow Row") { ContextualFlowRowDemo() }, ComposableDemo("Contextual FlowColumn") { ContextualFlowColumnDemo() }, ComposableDemo("Rtl support") { RtlDemo() }, + ComposableDemo("Grid") { GridDemo() }, ), ) diff --git a/compose/foundation/foundation-layout/src/androidDeviceTest/kotlin/androidx/compose/foundation/layout/GridTest.kt b/compose/foundation/foundation-layout/src/androidDeviceTest/kotlin/androidx/compose/foundation/layout/GridTest.kt new file mode 100644 index 0000000000000..1b6ef306f4c1d --- /dev/null +++ b/compose/foundation/foundation-layout/src/androidDeviceTest/kotlin/androidx/compose/foundation/layout/GridTest.kt @@ -0,0 +1,2304 @@ +/* + * Copyright 2026 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. + */ + +@file:OptIn(ExperimentalGridApi::class) + +package androidx.compose.foundation.layout + +import androidx.compose.foundation.horizontalScroll +import androidx.compose.foundation.rememberScrollState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.layout.IntrinsicMeasurable +import androidx.compose.ui.layout.IntrinsicMeasureScope +import androidx.compose.ui.layout.Layout +import androidx.compose.ui.layout.Measurable +import androidx.compose.ui.layout.MeasurePolicy +import androidx.compose.ui.layout.MeasureResult +import androidx.compose.ui.layout.MeasureScope +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.node.Ref +import androidx.compose.ui.platform.isDebugInspectorInfoEnabled +import androidx.compose.ui.unit.Constraints +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import kotlin.math.roundToInt +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class GridTest : LayoutTest() { + + @Before + fun before() { + isDebugInspectorInfoEnabled = true + } + + @After + fun after() { + isDebugInspectorInfoEnabled = false + } + + @Test + fun testGrid_itemModifierChange_triggersRelayout() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + var targetRow by mutableStateOf(1) + + // Latch for initial layout (Row 1) + val initialLatch = CountDownLatch(1) + // Latch for update layout (Row 2) + val updateLatch = CountDownLatch(1) + + val childPosition = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + Box( + Modifier.gridItem(row = targetRow, column = 1) + .size(sizeDp) + .onGloballyPositioned { coordinates -> + childPosition.value = coordinates.localToRoot(Offset.Zero) + if (initialLatch.count > 0) { + initialLatch.countDown() + } else { + updateLatch.countDown() + } + } + ) + } + } + + // 1. Verify Initial Position (Row 1 -> Index 0 -> 0px) + assertTrue( + "Timed out waiting for initial layout", + initialLatch.await(1, TimeUnit.SECONDS), + ) + assertEquals(Offset(0f, 0f), childPosition.value) + + // 2. Update State + targetRow = 2 + + // 3. Verify Updated Position (Row 2 -> Index 1 -> 50px) + assertTrue( + "Timed out waiting for layout update", + updateLatch.await(1, TimeUnit.SECONDS), + ) + assertEquals(Offset(0f, size.toFloat()), childPosition.value) + } + + @Test + fun testGrid_configStateChange_updatesLayout() = + with(density) { + var trackSize by mutableStateOf(50.dp) + + // Use separate latches for the initial pass and the update pass. + val initialLayoutLatch = CountDownLatch(1) + val updateLayoutLatch = CountDownLatch(1) + + val childSize = Ref() + + show { + Grid( + config = { + // Reading 'trackSize' here registers a dependency. + // When 'trackSize' changes, this lambda re-executes, triggering + // the MeasurePolicy to re-measure. + column(GridTrackSize.Fixed(trackSize)) + row(GridTrackSize.Fixed(trackSize)) + } + ) { + Box( + Modifier.gridItem(1, 1).fillMaxSize().onGloballyPositioned { coordinates -> + childSize.value = coordinates.size + + // If the first latch is still open, this is the initial layout. + // Otherwise, we are in the update phase. + if (initialLayoutLatch.count > 0) { + initialLayoutLatch.countDown() + } else { + updateLayoutLatch.countDown() + } + } + ) + } + } + + // Verify Initial State (50.dp) + // Wait for the FIRST layout pass to complete + assertTrue( + "Timed out waiting for initial layout", + initialLayoutLatch.await(1, TimeUnit.SECONDS), + ) + assertEquals( + "Initial size incorrect", + IntSize(50.dp.roundToPx(), 50.dp.roundToPx()), + childSize.value, + ) + + // Change State + trackSize = 100.dp + + // Verify Update (100.dp) + // Wait for the SECOND layout pass (recomposition) to complete + assertTrue( + "Timed out waiting for layout update", + updateLayoutLatch.await(1, TimeUnit.SECONDS), + ) + assertEquals( + "Grid did not update track size after config state changed", + IntSize(100.dp.roundToPx(), 100.dp.roundToPx()), + childSize.value, + ) + } + + @Test + fun testGrid_fixedTracks_sizeCorrectly() = + with(density) { + val size1 = 50 + val size2 = 100 + val size1Dp = size1.toDp() + val size2Dp = size2.toDp() + + val positionedLatch = CountDownLatch(2) + val childSize = Array(2) { Ref() } + val childPosition = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size1Dp)) + column(GridTrackSize.Fixed(size2Dp)) + row(GridTrackSize.Fixed(size1Dp)) + } + ) { + // R1, C1 + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(childSize[0], childPosition[0], positionedLatch) + ) + // R1, C2 + Box( + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(childSize[1], childPosition[1], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + // Check Item 1 (50x50) at (0,0) + assertEquals(IntSize(size1, size1), childSize[0].value) + assertEquals(Offset(0f, 0f), childPosition[0].value) + + // Check Item 2 (100x50) at (50,0) + assertEquals(IntSize(size2, size1), childSize[1].value) + assertEquals(Offset(size1.toFloat(), 0f), childPosition[1].value) + } + + @Test + fun testGrid_fractionTracks() = + with(density) { + val totalSize = 200 + val totalSizeDp = totalSize.toDp() + + // Col 1: 25% = 50px + // Col 2: 75% = 150px + val expectedCol1 = (totalSize * 0.25f).roundToInt() + val expectedCol2 = (totalSize * 0.75f).roundToInt() + + val positionedLatch = CountDownLatch(2) + val childSize = Array(2) { Ref() } + val childPosition = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Percentage(0.25f)) + column(GridTrackSize.Percentage(0.75f)) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = Modifier.size(totalSizeDp, 50.dp), + ) { + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(childSize[0], childPosition[0], positionedLatch) + ) + Box( + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(childSize[1], childPosition[1], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals(IntSize(expectedCol1, 50.dp.roundToPx()), childSize[0].value) + assertEquals(Offset(0f, 0f), childPosition[0].value) + + assertEquals(IntSize(expectedCol2, 50.dp.roundToPx()), childSize[1].value) + assertEquals(Offset(expectedCol1.toFloat(), 0f), childPosition[1].value) + } + + @Test + fun testGrid_percentageRows_resolvesAgainstHeight() = + with(density) { + // Scenario: + // Fixed Height Container (200px). + // Row 1: 25% (50px) + // Row 2: 75% (150px) + + val totalHeight = 200 + val expectedRow1 = (totalHeight * 0.25f).roundToInt() + val expectedRow2 = (totalHeight * 0.75f).roundToInt() + + val latch = CountDownLatch(2) + val sizes = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Fixed(50.dp)) + row(GridTrackSize.Percentage(0.25f)) + row(GridTrackSize.Percentage(0.75f)) + }, + modifier = Modifier.height(totalHeight.toDp()), + ) { + // Item in Row 1 + Box( + Modifier.gridItem(1, 1).fillMaxSize().saveLayoutInfo(sizes[0], Ref(), latch) + ) + // Item in Row 2 + Box( + Modifier.gridItem(2, 1).fillMaxSize().saveLayoutInfo(sizes[1], Ref(), latch) + ) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(expectedRow1, sizes[0].value?.height) + assertEquals(expectedRow2, sizes[1].value?.height) + } + + @Test + fun testGrid_flexTracks() = + with(density) { + val totalWidth = 300 + val fixedWidth = 100 + + // Remaining space = 200 + // Flex 1: 1fr = 200 * (1/4) = 50 + // Flex 2: 3fr = 200 * (3/4) = 150 + + val positionedLatch = CountDownLatch(3) + val childSize = Array(3) { Ref() } + val childPosition = Array(3) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Fixed(fixedWidth.toDp())) + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Flex(3.fr)) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = Modifier.width(totalWidth.toDp()), + ) { + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(childSize[0], childPosition[0], positionedLatch) + ) + Box( + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(childSize[1], childPosition[1], positionedLatch) + ) + Box( + Modifier.gridItem(1, 3) + .fillMaxSize() + .saveLayoutInfo(childSize[2], childPosition[2], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + // Fixed Col + assertEquals(IntSize(fixedWidth, 50.dp.roundToPx()), childSize[0].value) + assertEquals(Offset(0f, 0f), childPosition[0].value) + + // Flex 1 (50px) + assertEquals(IntSize(50, 50.dp.roundToPx()), childSize[1].value) + assertEquals(Offset(fixedWidth.toFloat(), 0f), childPosition[1].value) + + // Flex 3 (150px) + assertEquals(IntSize(150, 50.dp.roundToPx()), childSize[2].value) + assertEquals(Offset((fixedWidth + 50).toFloat(), 0f), childPosition[2].value) + } + + @Test + fun testGrid_flexRespectsMinContent() = + with(density) { + val minContentSize = 100 + val totalSize = 150 // Only 50px left for flex + val latch = CountDownLatch(2) + val sizes = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.MinContent) + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = Modifier.width(totalSize.toDp()), + ) { + // Item 1 (MinContent): Needs 100px + IntrinsicItem( + minWidth = minContentSize, + minIntrinsicWidth = minContentSize, + maxIntrinsicWidth = minContentSize, + modifier = Modifier.gridItem(1, 1).saveLayoutInfo(sizes[0], Ref(), latch), + ) + // Item 2 (Flex): Gets remaining 50px + Box( + Modifier.gridItem(1, 2).fillMaxSize().saveLayoutInfo(sizes[1], Ref(), latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(minContentSize, sizes[0].value?.width) + assertEquals(totalSize - minContentSize, sizes[1].value?.width) + } + + @Test + fun testGrid_flexTrack_minContent_lowerBound() = + with(density) { + val containerWidth = 50 + val itemMinSize = 100 + val latch = CountDownLatch(1) + val childSize = Ref() + + show { + // Container is 50px wide, but item needs 100px. + // Flex track should expand to 100px (min-content), ignoring the 50px constraint. + Box(Modifier.width(containerWidth.toDp())) { + Grid( + config = { + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Fixed(50.dp)) + } + ) { + IntrinsicItem( + minWidth = itemMinSize, + minIntrinsicWidth = itemMinSize, + maxIntrinsicWidth = itemMinSize, + modifier = + Modifier.gridItem(1, 1) + .fillMaxHeight() + .saveLayoutInfo(childSize, Ref(), latch), + ) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Flex track should not shrink below min-content size", + itemMinSize, + childSize.value?.width, + ) + } + + @Test + fun testGrid_flexTracks_distributeSpace_afterMinContent() = + with(density) { + // Scenario: + // Container = 200px + // Track 1 (1fr): Has large content (150px) + // Track 2 (1fr): Has small content (10px) + // + // Calculation: + // 1. Base Sizes (Pass 1): + // Track 1 = 150px + // Track 2 = 10px + // Used = 160px + // + // 2. Remaining Space (Pass 2): + // 200px - 160px = 40px + // + // 3. Distribution (Equal weight 1fr): + // Track 1 adds 20px -> Final 170px + // Track 2 adds 20px -> Final 30px + + val containerWidth = 200 + val item1MinSize = 150 + val item2MinSize = 10 + val latch = CountDownLatch(2) + val size1 = Ref() + val size2 = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = Modifier.width(containerWidth.toDp()), + ) { + // Item 1: Large Min Content + IntrinsicItem( + minWidth = item1MinSize, + minIntrinsicWidth = item1MinSize, + maxIntrinsicWidth = item1MinSize, + modifier = + Modifier.gridItem(1, 1) + .fillMaxWidth() // <--- ADD THIS + .saveLayoutInfo(size1, Ref(), latch), + ) + + // Item 2: Small Min Content + IntrinsicItem( + minWidth = item2MinSize, + minIntrinsicWidth = item2MinSize, + maxIntrinsicWidth = item2MinSize, + modifier = + Modifier.gridItem(1, 2) + .fillMaxWidth() // <--- ADD THIS + .saveLayoutInfo(size2, Ref(), latch), + ) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals("Track 1 should be Base(150) + Share(20)", 170, size1.value?.width) + assertEquals("Track 2 should be Base(10) + Share(20)", 30, size2.value?.width) + } + + @Test + fun testGrid_mixedTrackTypes_resolutionOrder() = + with(density) { + val fixedSize = 50 + val contentSize = 30 + val totalSize = 200 // 50 (Fixed) + 30 (Auto) + Flex = 200 -> Flex = 120 + + val latch = CountDownLatch(3) + val sizes = Array(3) { Ref() } + val positions = Array(3) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Fixed(fixedSize.toDp())) // Col 1: Fixed + column(GridTrackSize.Auto) // Col 2: Auto (Content based) + column(GridTrackSize.Flex(1.fr)) // Col 3: Flex (Remaining) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = Modifier.width(totalSize.toDp()), + ) { + // Col 1: Fixed item + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(sizes[0], positions[0], latch) + ) + + // Col 2: Auto item (determines track width) + Box( + Modifier.gridItem(1, 2) + .width(contentSize.toDp()) + .fillMaxHeight() + .saveLayoutInfo(sizes[1], positions[1], latch) + ) + + // Col 3: Flex item + Box( + Modifier.gridItem(1, 3) + .fillMaxSize() + .saveLayoutInfo(sizes[2], positions[2], latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Col 1: 50 + assertEquals(fixedSize, sizes[0].value?.width) + // Col 2: 30 (sized by content) + assertEquals(contentSize, sizes[1].value?.width) + // Col 3: 200 - 50 - 30 = 120 + assertEquals(120, sizes[2].value?.width) + } + + @Test + fun testGrid_gaps() = + with(density) { + val size = 50 + val gap = 10 + val gapDp = gap.toDp() + val sizeDp = size.toDp() + + val positionedLatch = CountDownLatch(2) + val childPosition = Array(2) { Ref() } + // Use explicit dummy refs instead of passing null to avoid overload ambiguity + val dummySize = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Fixed(sizeDp)) + column(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + gap(gapDp) + } + ) { + // Item 1: (0, 0) + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(dummySize[0], childPosition[0], positionedLatch) + ) + // Item 2: (50 + 10, 0) = (60, 0) + Box( + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(dummySize[1], childPosition[1], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), childPosition[0].value) + assertEquals(Offset((size + gap).toFloat(), 0f), childPosition[1].value) + } + + @Test + fun testGrid_flexWithGaps() = + with(density) { + val size = 50 + val gap = 10 + // Available space for tracks: 50 - 10 = 40. + // 1.fr + 1.fr = 2 parts. 40 / 2 = 20 per track. + val expectedColWidth = (size - gap) / 2 + + val positionedLatch = CountDownLatch(2) + val childSize = Array(2) { Ref() } + val childPosition = Array(2) { Ref() } + + show { + Grid( + config = { + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Fixed(size.toDp())) + gap(gap.toDp()) + }, + modifier = Modifier.requiredSize(size.toDp()), + ) { + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(childSize[0], childPosition[0], positionedLatch) + ) + Box( + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(childSize[1], childPosition[1], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + assertEquals(IntSize(expectedColWidth, size), childSize[0].value) + assertEquals(IntSize(expectedColWidth, size), childSize[1].value) + assertEquals(Offset(0f, 0f), childPosition[0].value) + assertEquals(Offset((expectedColWidth + gap).toFloat(), 0f), childPosition[1].value) + } + + @Test + fun testGrid_spanningWithGaps() { + val size = 50 + val gap = 10 + // Spanning 2 columns: size + gap + size = 50 + 10 + 50 = 110 + val expectedWidth = size * 2 + gap + + val positionedLatch = CountDownLatch(1) + val childSize = Ref() + val dummyPos = Ref() + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(size.toDp())) } + row(GridTrackSize.Fixed(size.toDp())) + gap(gap.toDp()) + } + ) { + Box( + Modifier.gridItem(row = 1, column = 1, columnSpan = 2) + .fillMaxSize() + .saveLayoutInfo(childSize, dummyPos, positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + assertEquals(IntSize(expectedWidth, size), childSize.value) + } + + @Test + fun testGrid_implicitTracks_respectGaps() = + with(density) { + val size = 50 + val gap = 10 + val latch = CountDownLatch(2) + val pos = Array(2) { Ref() } + + // Create a dummy ref instead of passing null + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size.toDp())) // 1 Explicit Col + row(GridTrackSize.Fixed(size.toDp())) + gap(gap.toDp()) + } + ) { + // Item 1: Col 1 + Box( + Modifier.gridItem(1, 1) + .size(size.toDp()) + .saveLayoutInfo(dummy, pos[0], latch) + ) + // Item 2: Col 2 (Implicit). Should be at 50 + 10 = 60. + Box( + Modifier.gridItem(1, 2) + .size(size.toDp()) + .saveLayoutInfo(dummy, pos[1], latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset((size + gap).toFloat(), 0f), pos[1].value) + } + + @Test + fun testGrid_gapPrecedence_specificOverridesGeneric() = + with(density) { + // Scenario: + // gap(10) sets both. + // rowGap(20) overrides row gap. + // columnGap(5) overrides column gap. + // Result: RowGap = 20, ColumnGap = 5. + + val size = 50 + val baseGap = 10 + val rowGapOverride = 20 + val colGapOverride = 5 + + val sizeDp = size.toDp() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + repeat(2) { column(GridTrackSize.Fixed(sizeDp)) } + repeat(2) { row(GridTrackSize.Fixed(sizeDp)) } + + gap(baseGap.toDp()) // Sets both to 10 + rowGap(rowGapOverride.toDp()) // Overrides row to 20 + columnGap(colGapOverride.toDp()) // Overrides col to 5 + } + ) { + // (0,0) + Box(Modifier.gridItem(1, 1).size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // (0,1) -> X should be Size + ColGap(5) + Box(Modifier.gridItem(1, 2).size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + // (1,0) -> Y should be Size + RowGap(20) + Box(Modifier.gridItem(2, 1).size(sizeDp).saveLayoutInfo(dummy, pos[2], latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset((size + colGapOverride).toFloat(), 0f), pos[1].value) + assertEquals(Offset(0f, (size + rowGapOverride).toFloat()), pos[2].value) + } + + @Test + fun testGrid_alignment() = + with(density) { + val cellSize = 100 + val itemSize = 40 + // Center: (100 - 40) / 2 = 30 + val expectedOffset = 30f + val cellSizeDp = cellSize.toDp() + val itemSizeDp = itemSize.toDp() + + val positionedLatch = CountDownLatch(1) + val childPosition = Ref() + val dummySize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(cellSizeDp)) + row(GridTrackSize.Fixed(cellSizeDp)) + } + ) { + // Item smaller than cell, aligned center + Box( + Modifier.gridItem(1, 1, alignment = Alignment.Center) + .size(itemSizeDp) + .saveLayoutInfo(dummySize, childPosition, positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(expectedOffset, expectedOffset), childPosition.value) + } + + @Test + fun testGrid_alignment_spanning() = + with(density) { + val colSize = 50 + val rowSize = 60 + val gap = 10 + val itemSize = 40 + + // Calculate total area dimensions including the gap + val spannedWidth = (colSize * 2) + gap + val spannedHeight = (rowSize * 2) + gap + + // Alignment.BottomEnd calculation: + // x = ContainerWidth - ItemWidth + // y = ContainerHeight - ItemHeight + val expectedX = (spannedWidth - itemSize).toFloat() + val expectedY = (spannedHeight - itemSize).toFloat() + + val positionedLatch = CountDownLatch(1) + val childPosition = Ref() + val dummySize = Ref() + + show { + Grid( + config = { + repeat(2) { column(GridTrackSize.Fixed(colSize.toDp())) } + repeat(2) { row(GridTrackSize.Fixed(rowSize.toDp())) } + gap(gap.toDp()) + } + ) { + Box( + Modifier.gridItem( + 1, + 1, + rowSpan = 2, + columnSpan = 2, + alignment = Alignment.BottomEnd, + ) + .size(itemSize.toDp()) + .saveLayoutInfo(dummySize, childPosition, positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + assertEquals(Offset(expectedX, expectedY), childPosition.value) + } + + @Test + fun testGrid_alignment_rtl() = + with(density) { + val cellSize = 100 + val itemSize = 40 + val cellSizeDp = cellSize.toDp() + val itemSizeDp = itemSize.toDp() + + val positionedLatch = CountDownLatch(2) + val startAlignedPos = Ref() + val absLeftAlignedPos = Ref() + + show { + // Force RTL layout direction + androidx.compose.runtime.CompositionLocalProvider( + androidx.compose.ui.platform.LocalLayoutDirection provides + androidx.compose.ui.unit.LayoutDirection.Rtl + ) { + Grid( + config = { + column(GridTrackSize.Fixed(cellSizeDp)) + row(GridTrackSize.Fixed(cellSizeDp)) + } + ) { + // 1. Alignment.TopStart (Relative 2D Alignment) + // In RTL, "Start" is visually on the RIGHT. + // Cell Width 100. Item 40. + // Expect visual position: 100 - 40 = 60px from visual Left. + Box( + Modifier.gridItem(1, 1, alignment = Alignment.TopStart) + .size(itemSizeDp) + .saveLayoutInfo(Ref(), startAlignedPos, positionedLatch) + ) + + // 2. AbsoluteAlignment.TopLeft (Absolute 2D Alignment) + // "Left" is always visually Left, regardless of layout direction. + // Expect visual position: 0px from visual Left. + Box( + // Use TopLeft (2D) instead of Left (1D) to satisfy the Alignment + // type requirement + Modifier.gridItem( + 1, + 1, + alignment = androidx.compose.ui.AbsoluteAlignment.TopLeft, + ) + .size(itemSizeDp) + .saveLayoutInfo(Ref(), absLeftAlignedPos, positionedLatch) + ) + } + } + } + + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + // 1. Start (Right side of container) + assertEquals( + "Alignment.TopStart in RTL should be visually on the Right (60px from left)", + Offset(60f, 0f), + startAlignedPos.value, + ) + + // 2. Absolute Left (Left side of container) + assertEquals( + "AbsoluteAlignment.TopLeft in RTL should visually remain on the Left (0px)", + Offset(0f, 0f), + absLeftAlignedPos.value, + ) + } + + @Test + fun testGrid_contentBasedSizing() { + val childSize = Ref() + val latch = CountDownLatch(1) + val dummyPosition = Ref() + + show { + Grid( + config = { + // Col 1: MinContent (should match min intrinsic width) + column(GridTrackSize.MinContent) + // Col 2: MaxContent (should match max intrinsic width) + column(GridTrackSize.MaxContent) + row(GridTrackSize.Fixed(50.dp)) + } + ) { + // Item 1: Min=50, Max=100 + IntrinsicItem( + minWidth = 50, + minIntrinsicWidth = 50, + maxIntrinsicWidth = 100, + modifier = Modifier.gridItem(1, 1).fillMaxSize(), + ) + + // Item 2: Min=50, Max=100 + IntrinsicItem( + minWidth = 50, + minIntrinsicWidth = 50, + maxIntrinsicWidth = 100, + modifier = + Modifier.gridItem(1, 2) + .fillMaxSize() + .saveLayoutInfo(childSize, dummyPosition, latch), + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Col 1 should be 50 (min) + // Col 2 should be 100 (max) + // Item 2 in Col 2 should have width 100 + assertEquals(100, childSize.value?.width) + } + + @Test + fun testGrid_implicitTracks_shrinkToFitContent() = + with(density) { + // Scenario: + // Item placed in Col 10. + // Cols 1-9 should be implicit Auto. + // If they have no content, they should have width 0. + // Col 10 should have width 50. + // Total Grid Width should be 50 (0+0...+50). + + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(1) + val pos = Ref() + val dummy = Ref() + + show { + Grid( + config = { + // No explicit columns + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + // Place far away at Column 5. + // Columns 1, 2, 3, 4 are Implicit Auto and Empty -> Size 0. + Box( + Modifier.gridItem(column = 5).size(sizeDp).saveLayoutInfo(dummy, pos, latch) + ) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Position should be 0 because previous columns collapsed. + // Note: If gaps were added, they would add up (4 * gap). + assertEquals(Offset(0f, 0f), pos.value) + } + + @Test + fun testGrid_rowSpan_expandsRowsToFitContent() = + with(density) { + // Scenario: + // 2 Columns (Fixed 50) + // 2 Rows (Auto) + // Item 1 (Col 1, Row 1): Small (10px height) + // Item 2 (Col 1, Row 2): Small (10px height) + // Item 3 (Col 2, Row 1, Span 2): Tall (100px height) + // + // Expected Behavior: + // Without spanning logic: Rows would be 10px each (total 20px). Item 3 would overflow. + // With spanning logic: Item 3 needs 100px. + // Deficit = 100 - (10 + 10) = 80px. + // Distribute 80px / 2 rows = +40px each. + // Final Row Heights: 10 + 40 = 50px each. + // Total Grid Height: 100px. + + val colWidth = 50.dp + val smallItemHeight = 10.dp + val tallItemHeight = 100.dp + val expectedTotalHeight = 100.dp.roundToPx() + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(colWidth)) + column(GridTrackSize.Fixed(colWidth)) + row(GridTrackSize.Auto) + row(GridTrackSize.Auto) + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + // Col 1, Row 1 + Box(Modifier.gridItem(1, 1).size(colWidth, smallItemHeight)) + // Col 1, Row 2 + Box(Modifier.gridItem(2, 1).size(colWidth, smallItemHeight)) + + // Col 2, Row 1, Span 2 (The driver of expansion) + Box( + Modifier.gridItem(row = 1, column = 2, rowSpan = 2) + .size(colWidth, tallItemHeight) + ) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Grid height should expand to accommodate the tall row-spanning item", + expectedTotalHeight, + gridSize.value?.height, + ) + } + + @Test + fun testGrid_rowSpan_expandsFlexRows() = + with(density) { + // Scenario: + // Container Height = 100px (Fixed constraint) + // 2 Rows (Flex 1fr) + // Item 1 (Row 1): Empty + // Item 2 (Row 2): Empty + // Item 3 (Span 2): Tall (200px) + // + // Expected Behavior: + // Flex logic initially splits 100px -> 50px each. + // Spanning logic sees Item 3 needs 200px. + // Deficit = 200 - 100 = 100px. + // Rows should grow to 100px each. + // Total Height = 200px (Grid expands beyond parent constraint if content demands it). + + val containerHeight = 100.dp + val tallItemHeight = 200.dp + val expectedTotalHeight = 200.dp.roundToPx() + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Wrap in a box with fixed height to simulate constraints, + // but allow Grid to be larger (unbounded internal checks) + Box( + Modifier.height(containerHeight) + .wrapContentHeight(align = Alignment.Top, unbounded = true) + ) { + Grid( + config = { + column(GridTrackSize.Fixed(50.dp)) + row(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Flex(1.fr)) + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + // Spanning item forcing expansion + Box( + Modifier.gridItem(row = 1, column = 1, rowSpan = 2) + .size(50.dp, tallItemHeight) + ) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Flex rows should expand beyond 1fr share if spanning item requires it", + expectedTotalHeight, + gridSize.value?.height, + ) + } + + @Test + fun testGrid_autoPlacement_rowFlow() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(sizeDp)) + column(GridTrackSize.Fixed(sizeDp)) + // Rows are implicit/auto + flow = GridFlow.Row + } + ) { + // We use Modifier.size because implicit Auto tracks need content size to expand + // Item 1 -> (0,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // Item 2 -> (50,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + // Item 3 -> Wraps to next row -> (0, 50) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[2], latch)) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(size.toFloat(), 0f), pos[1].value) + assertEquals(Offset(0f, size.toFloat()), pos[2].value) + } + + @Test + fun testGrid_autoPlacement_columnFlow() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + flow = GridFlow.Column + row(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + // Cols are implicit/auto + } + ) { + // Item 1 -> (0,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // Item 2 -> (0,50) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + // Item 3 -> Wraps to next col -> (50,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[2], latch)) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, size.toFloat()), pos[1].value) + assertEquals(Offset(size.toFloat(), 0f), pos[2].value) + } + + @Test + fun testGrid_autoPlacement_wrapping_respectsGaps() = + with(density) { + val size = 50 + val gap = 10 + val sizeDp = size.toDp() + val gapDp = gap.toDp() + val latch = CountDownLatch(2) + val pos = Array(2) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(sizeDp)) // Only 1 column + row(GridTrackSize.Fixed(sizeDp)) + gap(gapDp) + flow = GridFlow.Row + } + ) { + // Item 1: (0,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // Item 2: Wraps to (0,1). Should include vertical gap. + // Y Position = Row 1 Height (50) + Gap (10) = 60 + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, (size + gap).toFloat()), pos[1].value) + } + + @Test + fun testGrid_columnFlow_wrapsCorrectly() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + flow = GridFlow.Column + // 2 Explicit Rows + row(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + // Item 1 -> (0,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // Item 2 -> (0,50) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + // Item 3 -> Wraps to Next Column -> (50,0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[2], latch)) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, size.toFloat()), pos[1].value) + assertEquals(Offset(size.toFloat(), 0f), pos[2].value) + } + + @Test + fun testGrid_columnFlow_createsImplicitColumns() = + with(density) { + val itemSize = 50 + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + Grid( + config = { + // 2 Explicit Rows. Flow = Column. + row(GridTrackSize.Fixed(itemSize.toDp())) + row(GridTrackSize.Fixed(itemSize.toDp())) + flow = GridFlow.Column + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + // 4 items. + // Items 1, 2 fill Col 1 (Rows 1, 2) + // Items 3, 4 should create implicit Col 2 (Rows 1, 2) + repeat(4) { Box(Modifier.size(itemSize.toDp())) } + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Expected: 2 Rows (Explicit) x 2 Columns (1 Explicit + 1 Implicit) + // Implicit columns default to Auto -> itemSize (50) + assertEquals(IntSize(itemSize * 2, itemSize * 2), gridSize.value) + } + + @Test + fun testGrid_columnFlow_implicitRows() = + with(density) { + // Scenario: + // Flow = Column. + // Explicitly define 1 Column (so we know the width). + // Do NOT define any Rows. + // Item 1: (0,0) + // Item 2: Should stack below at (1,0) -> Creating Implicit Row 2 + // Item 3: Should stack below at (2,0) -> Creating Implicit Row 3 + + val size = 50.dp + val sizePx = size.roundToPx().toFloat() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + flow = GridFlow.Column + // Define column width so layout isn't 0 width + column(GridTrackSize.Fixed(size)) + // Do NOT define rows. + // This allows the column to grow infinitely downwards. + } + ) { + // (0,0) + Box(Modifier.size(size).saveLayoutInfo(dummy, pos[0], latch)) + // (1, 0) -> Implicit Row 2 + Box(Modifier.size(size).saveLayoutInfo(dummy, pos[1], latch)) + // (2, 0) -> Implicit Row 3 + Box(Modifier.size(size).saveLayoutInfo(dummy, pos[2], latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // All X should be 0 (Column 0) + // Y should increment by sizePx + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, sizePx), pos[1].value) + assertEquals(Offset(0f, sizePx * 2), pos[2].value) + } + + @Test + fun testGrid_mixedPlacement_skipsOccupiedCells() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(sizeDp)) } + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + // 1. Explicit Item at (0, 1) (Middle Column) + Box(Modifier.gridItem(1, 2).size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + + // 2. Auto Item 1 -> Should go to (0, 0) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + + // 3. Auto Item 2 -> Should skip (0, 1) and go to (0, 2) + Box(Modifier.size(sizeDp).saveLayoutInfo(dummy, pos[2], latch)) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Explicit + assertEquals(Offset(size.toFloat(), 0f), pos[0].value) + // Auto 1 + assertEquals(Offset(0f, 0f), pos[1].value) + // Auto 2 + assertEquals(Offset((size * 2).toFloat(), 0f), pos[2].value) + } + + @Test + fun testGrid_explicitPlacement_allowsOverlaps() = + with(density) { + // Scenario: + // Two items explicitly placed in (1, 1). + // They should occupy the same space. The grid should not throw or shift them. + + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(2) + val pos = Array(2) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(sizeDp)) + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + // Item 1 + Box(Modifier.gridItem(1, 1).size(sizeDp).saveLayoutInfo(dummy, pos[0], latch)) + // Item 2 (Same Cell) + Box(Modifier.gridItem(1, 1).size(sizeDp).saveLayoutInfo(dummy, pos[1], latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, 0f), pos[1].value) + } + + @Test + fun testGrid_explicitPlacement_doesNotMoveAutoCursor() = + with(density) { + // Scenario: + // 3 Columns. + // Item 1: Auto (0,0). Cursor moves to (0,1). + // Item 2: Explicit far away (0, 2). Cursor should REMAIN at (0,1). + // Item 3: Auto. Should fill the gap at (0,1), NOT start after Item 2. + + val size = 50.dp + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(size)) } + row(GridTrackSize.Fixed(size)) + } + ) { + // 1. Auto -> (0,0) + Box(Modifier.size(size).saveLayoutInfo(dummy, pos[0], latch)) + // 2. Explicit -> (0,2). Should NOT move cursor. + Box(Modifier.gridItem(1, 3).size(size).saveLayoutInfo(dummy, pos[1], latch)) + // 3. Auto -> Should fill (0,1) + Box(Modifier.size(size).saveLayoutInfo(dummy, pos[2], latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Calculate pixel size of a single track first + val sizePx = size.roundToPx().toFloat() + + // Auto 1 (0,0) + assertEquals(Offset(0f, 0f), pos[0].value) + // Explicit (Col 3 -> Index 2) + assertEquals(Offset(sizePx * 2, 0f), pos[1].value) + // Auto 2 (Col 2 -> Index 1) + assertEquals(Offset(sizePx, 0f), pos[2].value) + } + + @Test + fun testGrid_fixedRow_autoCol_skipsOccupied() = + with(density) { + // Scenario: + // 3 Columns. + // Item 1: Explicitly placed at (0, 0). + // Item 2: Fixed Row 0. Should skip (0,0) and go to (0,1). + // Item 3: Fixed Row 0. Should skip (0,0) and (0,1) and go to (0,2). + + val size = 50.dp + val latch = CountDownLatch(3) + val pos = Array(3) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(size)) } + row(GridTrackSize.Fixed(size)) + } + ) { + // 1. Occupy (0,0) explicitly + Box(Modifier.gridItem(1, 1).size(size).saveLayoutInfo(dummy, pos[0], latch)) + // 2. Request Row 1 (Auto Col). Should find Col 2. + Box(Modifier.gridItem(row = 1).size(size).saveLayoutInfo(dummy, pos[1], latch)) + // 3. Request Row 1 (Auto Col). Should find Col 3. + Box(Modifier.gridItem(row = 1).size(size).saveLayoutInfo(dummy, pos[2], latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Calculate pixel size of a single track first + val sizePx = size.roundToPx().toFloat() + + // (0,0) + assertEquals(Offset(0f, 0f), pos[0].value) + // (50, 0) + assertEquals(Offset(sizePx, 0f), pos[1].value) + // (100, 0) -> Sum of two tracks + assertEquals(Offset(sizePx * 2, 0f), pos[2].value) + } + + @Test + fun testGrid_fixedCol_autoRow_skipsOccupied() = + with(density) { + // Scenario: + // 1 Column, 3 Rows. + // Item 1: Explicitly placed at (0, 0). + // Item 2: Fixed Col 0. Should skip (0,0) and go to (1,0). + + val size = 50.dp + val latch = CountDownLatch(2) + val pos = Array(2) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size)) + repeat(3) { row(GridTrackSize.Fixed(size)) } + } + ) { + // 1. Occupy (0,0) explicitly + Box(Modifier.gridItem(1, 1).size(size).saveLayoutInfo(dummy, pos[0], latch)) + // 2. Request Col 1 (Auto Row). Should skip Row 1 and land in Row 2. + Box( + Modifier.gridItem(column = 1) + .size(size) + .saveLayoutInfo(dummy, pos[1], latch) + ) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Calculate pixel size of a single track first + val sizePx = size.roundToPx().toFloat() + + assertEquals(Offset(0f, 0f), pos[0].value) + assertEquals(Offset(0f, sizePx), pos[1].value) + } + + @Test + fun testGrid_mixedFlow_fixedRowInColumnFlow() = + with(density) { + // Scenario: + // Flow = Column. + // Item 1: Fixed Row 1. + // Since flow is column, the logic must look for the *first available column* in that + // fixed row. + + val size = 50.dp + val latch = CountDownLatch(1) + val pos = Ref() + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size)) + column(GridTrackSize.Fixed(size)) + row(GridTrackSize.Fixed(size)) + row(GridTrackSize.Fixed(size)) + flow = GridFlow.Column + } + ) { + // Occupy (1,0) - (Row 2, Col 1) + Box(Modifier.gridItem(2, 1).size(size)) + + // Request Row 2. + // Since (2,1) is occupied, it should find (2,2). + Box(Modifier.gridItem(row = 2).size(size).saveLayoutInfo(dummy, pos, latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Calculate pixel size of a single track first + val sizePx = size.roundToPx().toFloat() + + // Should be at Row 2 (Index 1), Col 2 (Index 1) -> (50, 50) + assertEquals(Offset(sizePx, sizePx), pos.value) + } + + @Test + fun testGrid_negativeIndices_placeCorrectly() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + + val positionedLatch = CountDownLatch(4) + val childPosition = Array(4) { Ref() } + val dummySize = Array(4) { Ref() } + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(sizeDp)) } + repeat(3) { row(GridTrackSize.Fixed(sizeDp)) } + } + ) { + // 1. Top-Left (1, 1) -> (0, 0) + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(dummySize[0], childPosition[0], positionedLatch) + ) + // 2. Top-Right (1, -1) -> (100, 0) (Last Column) + Box( + Modifier.gridItem(1, -1) + .fillMaxSize() + .saveLayoutInfo(dummySize[1], childPosition[1], positionedLatch) + ) + // 3. Bottom-Left (-1, 1) -> (0, 100) (Last Row) + Box( + Modifier.gridItem(-1, 1) + .fillMaxSize() + .saveLayoutInfo(dummySize[2], childPosition[2], positionedLatch) + ) + // 4. Bottom-Right (-1, -1) -> (100, 100) (Last Row, Last Column) + Box( + Modifier.gridItem(-1, -1) + .fillMaxSize() + .saveLayoutInfo(dummySize[3], childPosition[3], positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + // 1. (0, 0) + assertEquals(Offset(0f, 0f), childPosition[0].value) + // 2. (100, 0) -> Col index 2 * 50 + assertEquals(Offset((size * 2).toFloat(), 0f), childPosition[1].value) + // 3. (0, 100) -> Row index 2 * 50 + assertEquals(Offset(0f, (size * 2).toFloat()), childPosition[2].value) + // 4. (100, 100) + assertEquals(Offset((size * 2).toFloat(), (size * 2).toFloat()), childPosition[3].value) + } + + @Test + fun testGrid_negativeIndex_refersToExplicitBounds() = + with(density) { + val size = 50 + val latch = CountDownLatch(1) + val pos = Ref() + + // Create a dummy ref instead of passing null + val dummy = Ref() + + show { + Grid( + config = { + repeat(2) { + column(GridTrackSize.Fixed(size.toDp())) + } // Explicit Cols: 0, 1 + row(GridTrackSize.Fixed(size.toDp())) + } + ) { + // Create an implicit 3rd column (Index 2) + Box(Modifier.gridItem(1, 3).size(size.toDp())) + + // Place item at column = -1. + // Should map to Explicit Col 1 (the 2nd column), NOT the implicit 3rd column. + Box( + Modifier.gridItem(column = -1) + .size(size.toDp()) + .saveLayoutInfo(dummy, pos, latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Expect pos at 2nd column (Index 1) -> 50px + assertEquals(Offset(size.toFloat(), 0f), pos.value) + } + + @Test + fun testGrid_invalidNegativeIndices_fallbackToAuto() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(2) + val pos1 = Ref() + val pos2 = Ref() + val dummy = Ref() + + show { + Grid( + config = { + // 2x2 Grid + repeat(2) { column(GridTrackSize.Fixed(sizeDp)) } + repeat(2) { row(GridTrackSize.Fixed(sizeDp)) } + } + ) { + // Case 1: Valid Negative (-1 -> Index 1) + Box( + Modifier.gridItem(row = -1, column = -1) + .size(sizeDp) + .saveLayoutInfo(dummy, pos1, latch) + ) + + // Case 2: Invalid Negative (-5 -> Index -3 -> Invalid) + // Should be treated as "Unspecified" and auto-placed. + // Since (1,1) is empty (Item 1 is at 1,1 0-based), it should go to (0,0). + Box( + Modifier.gridItem(row = -5, column = -5) + .size(sizeDp) + .saveLayoutInfo(dummy, pos2, latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Item 1 (Valid -1,-1): Bottom-Right (50, 50) + assertEquals(Offset(size.toFloat(), size.toFloat()), pos1.value) + + // Item 2 (Invalid -5,-5): Auto-placed to first available slot (0,0) + assertEquals(Offset(0f, 0f), pos2.value) + } + + @Test + fun testGrid_spanning() { + val colSize = 50 + val rowSize = 50 + + val positionedLatch = CountDownLatch(1) + val childSize = Ref() + val childPosition = Ref() + + show { + Grid( + config = { + repeat(3) { column(GridTrackSize.Fixed(colSize.toDp())) } + repeat(3) { row(GridTrackSize.Fixed(rowSize.toDp())) } + } + ) { + // Item at R2, C2 spanning 2 rows and 2 columns + // Should be at (50, 50) with size (100, 100) + Box( + Modifier.gridItem(row = 2, column = 2, rowSpan = 2, columnSpan = 2) + .fillMaxSize() + .saveLayoutInfo(childSize, childPosition, positionedLatch) + ) + } + } + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals(IntSize(colSize * 2, rowSize * 2), childSize.value) + assertEquals(Offset(colSize.toFloat(), rowSize.toFloat()), childPosition.value) + } + + @Test + fun testGrid_spanEntireGrid() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(1) + val itemSize = Ref() + + show { + Grid( + config = { + repeat(4) { column(GridTrackSize.Fixed(sizeDp)) } + row(GridTrackSize.Fixed(sizeDp)) + } + ) { + // Spans all 4 columns + Box( + Modifier.gridItem(1, 1, columnSpan = 4) + .fillMaxSize() + .saveLayoutInfo(itemSize, Ref(), latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals(size * 4, itemSize.value?.width) + } + + @Test + fun testGrid_spanning_intoImplicitTracks() = + with(density) { + val size = 50 + val latch = CountDownLatch(1) + val itemSize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size.toDp())) // 1 Explicit Column + row(GridTrackSize.Fixed(size.toDp())) + } + ) { + // Place at Col 1, Span 2. + // Should cover Explicit Col 1 + Implicit Col 2. + // Implicit Col 2 should size to Auto. Since this item spans, + // and Auto tracks ignore spanning items for intrinsic sizing (as per your + // design), + // the implicit track might collapse to 0 OR resize if logic allows. + // *Correction*: Your logic adds `Auto` tracks. If no other item is in Col 2, + // it will be size 0. + // Let's add a non-spanning item in Col 2 to give it size. + + // Item A: Spans Col 1 and Col 2 + Box( + Modifier.gridItem(1, 1, columnSpan = 2) + .fillMaxSize() + .saveLayoutInfo(itemSize, Ref(), latch) + ) + + // Item B: Sits in Implicit Col 2 to force it to have size + Box(Modifier.gridItem(1, 2).size(size.toDp())) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Width = Col 1 (50) + Col 2 (50 from Item B) = 100 + assertEquals(size * 2, itemSize.value?.width) + } + + @Test + fun testGrid_itemSpanLargerThanExplicitGrid_doesNotLoop() = + with(density) { + val size = 50 + val sizeDp = size.toDp() + val latch = CountDownLatch(1) + val pos = Ref() + val dummy = Ref() + + show { + Grid( + config = { + // 2 Explicit Columns + column(GridTrackSize.Fixed(sizeDp)) + column(GridTrackSize.Fixed(sizeDp)) + flow = GridFlow.Row + } + ) { + // Item spans 3 columns (Exceeds explicit count of 2) + // Should be placed at (0,0) and create implicit tracks + Box( + Modifier.gridItem(columnSpan = 3) + .size(sizeDp) + .saveLayoutInfo(dummy, pos, latch) + ) + } + } + assertTrue("Timed out - likely infinite loop", latch.await(1, TimeUnit.SECONDS)) + + assertEquals(Offset(0f, 0f), pos.value) + } + + @Test + fun testGrid_respectsMinConstraints_expandsToFill() = + with(density) { + val smallTrackSize = 50.dp + val largeParentSize = 100.dp + val expectedSize = 100.dp.roundToPx() + + val positionedLatch = CountDownLatch(1) + val gridSize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(smallTrackSize)) + row(GridTrackSize.Fixed(smallTrackSize)) + }, + // Force the Grid to be larger than its content + modifier = + Modifier.size(largeParentSize).onGloballyPositioned { coordinates -> + gridSize.value = coordinates.size + positionedLatch.countDown() + }, + ) { /* empty */ + } + } + + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Grid should expand to satisfy min constraints", + IntSize(expectedSize, expectedSize), + gridSize.value, + ) + } + + @Test + fun testGrid_respectsMaxConstraints_coercesSize() = + with(density) { + val largeTrackSize = 200.dp + val smallParentSize = 100.dp + val expectedSize = 100.dp.roundToPx() + + val positionedLatch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Wrap in Box with propagateMinConstraints=false to test pure max constraints + Box(Modifier.size(smallParentSize)) { + Grid( + config = { + column(GridTrackSize.Fixed(largeTrackSize)) + row(GridTrackSize.Fixed(largeTrackSize)) + }, + modifier = + Modifier.onGloballyPositioned { coordinates -> + gridSize.value = coordinates.size + positionedLatch.countDown() + }, + ) { /* empty */ + } + } + } + + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Grid should respect max constraints even if tracks are larger", + IntSize(expectedSize, expectedSize), + gridSize.value, + ) + } + + @Test + fun testGrid_respectsConstraints_whenContentOverflows() = + with(density) { + val parentSize = 100 + val contentSize = 200 // Larger than parent + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Parent container restricts size to 100x100 + Box(Modifier.size(parentSize.toDp())) { + Grid( + config = { + // Grid wants to be 200x200 + column(GridTrackSize.Fixed(contentSize.toDp())) + row(GridTrackSize.Fixed(contentSize.toDp())) + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + Box(Modifier.gridItem(1, 1).fillMaxSize()) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Assert that Grid reported the PARENT'S size (clamped), not the content size + assertEquals( + "Grid should be clamped to parent max width/height", + IntSize(parentSize, parentSize), + gridSize.value, + ) + } + + @Test + fun testGrid_respectsConstraints_whenContentUnderflows() = + with(density) { + val minSize = 200 + val contentSize = 50 // Smaller than parent min + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Parent enforces minimum size of 200x200 (e.g. fillMaxSize) + Box(Modifier.requiredSize(minSize.toDp())) { + Grid( + config = { + column(GridTrackSize.Fixed(contentSize.toDp())) + row(GridTrackSize.Fixed(contentSize.toDp())) + }, + modifier = + Modifier.fillMaxSize() // Request to fill parent + .onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + Box(Modifier.gridItem(1, 1).fillMaxSize()) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Assert that Grid expanded to meet the minimum constraints + assertEquals( + "Grid should expand to meet min constraints", + IntSize(minSize, minSize), + gridSize.value, + ) + } + + @Test + fun testGrid_percentageTrack_inIndefiniteContainer_fallbacksToAuto() = + with(density) { + val positionedLatch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Wrap in a Row to provide infinite width constraint + Row { + Grid( + config = { + // 50% of Infinity cannot be calculated. + // Fallback to Auto (MaxContent) and fit the item. + column(GridTrackSize.Percentage(0.5f)) + row(GridTrackSize.Fixed(50.dp)) + }, + modifier = + Modifier.onGloballyPositioned { coordinates -> + gridSize.value = coordinates.size + positionedLatch.countDown() + }, + ) { + // The item is 10.dp wide. The track should expand to fit this. + Box(Modifier.gridItem(1, 1).size(10.dp)) + } + } + } + + assertTrue(positionedLatch.await(1, TimeUnit.SECONDS)) + + // Width should be 10.dp (Size of the content), NOT 0. + // Height should be 50.dp (Fixed) + assertEquals(IntSize(10.dp.roundToPx(), 50.dp.roundToPx()), gridSize.value) + } + + @Test + fun testGrid_flexColumn_inInfiniteConstraints_withGap_doesNotExpand() = + with(density) { + // Scenario: Grid is inside a Row + horizontalScroll (Infinite Width). + // It has a Flex column and a GAP. + // + // Bug Trigger: + // 1. Available Width = Infinity. + // 2. Gap = 10px. + // 3. Calculation: availableTrackSpace = Infinity - 10 = 2,147,483,637. + // 4. Check: (availableTrackSpace == Infinity) is FALSE. + // 5. Result: Logic thinks it has 2 billion pixels of space to distribute. + // 6. Flex track expands to ~2 billion pixels. + + val gap = 10.dp + val itemSize = 50.dp + val expectedWidth = itemSize.roundToPx() // Should shrink to fit content + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + // Parent provides Infinite Width constraint + Row(Modifier.horizontalScroll(rememberScrollState())) { + Grid( + config = { + column(GridTrackSize.Flex(1.fr)) // Should behave like MinContent/Auto + column( + GridTrackSize.Fixed(0.dp) + ) // Dummy column to ensure gap is applied + row(GridTrackSize.Fixed(50.dp)) + columnGap(gap) + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + // Item in Flex column + Box(Modifier.gridItem(1, 1).size(itemSize)) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + assertEquals( + "Flex column in infinite constraints should fallback to min-content size", + expectedWidth + gap.roundToPx(), // 50 (Item) + 10 (Gap) + 0 (Col 2) + gridSize.value?.width, + ) + } + + @Test + fun testGrid_zeroSizeTrack_layoutCorrectly() = + with(density) { + val size = 50 + val latch = CountDownLatch(2) + val pos = Array(2) { Ref() } + val dummy = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(size.toDp())) + column(GridTrackSize.Fixed(0.dp)) // Zero width column + column(GridTrackSize.Fixed(size.toDp())) + row(GridTrackSize.Fixed(size.toDp())) + } + ) { + // Item 1: Col 1 + Box( + Modifier.gridItem(1, 1) + .size(size.toDp()) + .saveLayoutInfo(dummy, pos[0], latch) + ) + // Item 2: Col 3 (Skipping Col 2 which is 0 width) + Box( + Modifier.gridItem(1, 3) + .size(size.toDp()) + .saveLayoutInfo(dummy, pos[1], latch) + ) + } + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + + // Item 1 at 0 + assertEquals(Offset(0f, 0f), pos[0].value) + // Item 2 at 50 + 0 = 50 + assertEquals(Offset(size.toFloat(), 0f), pos[1].value) + } + + @Test + fun testGrid_zeroSizeChildren() { + val trackSize = 50 + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(trackSize.toDp())) + row(GridTrackSize.Fixed(trackSize.toDp())) + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + // Place a zero-sized item. + // It should still occupy the logical cell (1,1), but draw nothing. + // The Grid should still size itself to the Fixed tracks (50x50). + Box(Modifier.gridItem(1, 1).size(0.dp)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + assertEquals(IntSize(trackSize, trackSize), gridSize.value) + } + + @Test + fun testGrid_itemFillsCell_whenRequested() { + val trackSize = 100 + val latch = CountDownLatch(1) + val childSize = Ref() + + show { + Grid( + config = { + column(GridTrackSize.Fixed(trackSize.toDp())) + row(GridTrackSize.Fixed(trackSize.toDp())) + } + ) { + // Item has no intrinsic size, but requests fillMaxSize(). + // It should fill the definition of the track (100x100). + Box(Modifier.gridItem(1, 1).fillMaxSize().saveLayoutInfo(childSize, Ref(), latch)) + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + assertEquals(IntSize(trackSize, trackSize), childSize.value) + } + + @Test + fun testGrid_nestedGrid() = + with(density) { + val outerSize = 100 + val outerSizeDp = outerSize.toDp() + + // Inner grid will be placed in a 100x100 cell. + // It will have 2 columns of 50 each. + val latch = CountDownLatch(1) + val innerItemSize = Ref() + + show { + // Outer Grid + Grid( + config = { + column(GridTrackSize.Fixed(outerSizeDp)) + row(GridTrackSize.Fixed(outerSizeDp)) + } + ) { + // Inner Grid placed at (1,1) of Outer Grid + Grid( + modifier = Modifier.gridItem(1, 1).fillMaxSize(), + config = { + column(GridTrackSize.Flex(1.fr)) + column(GridTrackSize.Flex(1.fr)) + row(GridTrackSize.Flex(1.fr)) + }, + ) { + // Item inside Inner Grid (Col 1) + Box( + Modifier.gridItem(1, 1) + .fillMaxSize() + .saveLayoutInfo(innerItemSize, Ref(), latch) + ) + // Item inside Inner Grid (Col 2) just to fill space + Box(Modifier.gridItem(1, 2).fillMaxSize()) + } + } + } + + assertTrue(latch.await(1, TimeUnit.SECONDS)) + assertEquals(IntSize(50, 100), innerItemSize.value) + } + + @Test + fun testGrid_stressTest_manyItems() = + with(density) { + val itemSize = 10 + val itemSizeDp = itemSize.toDp() + val itemCount = 100 + val cols = 10 + + // 100 items / 10 cols = 10 rows. + // Total Height = 10 rows * 10px = 100px. + val expectedHeight = 100 + + val latch = CountDownLatch(1) + val gridSize = Ref() + + show { + Grid( + config = { + // 10 Fixed columns + repeat(cols) { column(GridTrackSize.Fixed(itemSizeDp)) } + // Implicit rows + flow = GridFlow.Row + }, + modifier = + Modifier.onGloballyPositioned { + gridSize.value = it.size + latch.countDown() + }, + ) { + repeat(itemCount) { Box(Modifier.size(itemSizeDp)) } + } + } + + assertTrue(latch.await(3, TimeUnit.SECONDS)) + + assertEquals(10 * itemSize, gridSize.value?.width) + assertEquals(expectedHeight, gridSize.value?.height) + } + + @Test(expected = IllegalArgumentException::class) + fun testGrid_invalidIndices_throws() { + show { + Grid( + config = { + column(GridTrackSize.Fixed(10.dp)) + row(GridTrackSize.Fixed(10.dp)) + } + ) { + Box(Modifier.gridItem(100000, 1)) // Out of bounds + } + } + } + + @Composable + private fun IntrinsicItem( + minWidth: Int, + minIntrinsicWidth: Int, + maxIntrinsicWidth: Int, + modifier: Modifier = Modifier, + ) { + Layout( + modifier, + measurePolicy = + object : MeasurePolicy { + override fun MeasureScope.measure( + measurables: List, + constraints: Constraints, + ): MeasureResult { + return layout( + constraints.minWidth.coerceAtLeast(minWidth), + constraints.minHeight, + ) {} + } + + override fun IntrinsicMeasureScope.minIntrinsicWidth( + measurables: List, + height: Int, + ) = minIntrinsicWidth + + override fun IntrinsicMeasureScope.maxIntrinsicWidth( + measurables: List, + height: Int, + ) = maxIntrinsicWidth + }, + ) + } +} diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ExperimentalGridApi.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ExperimentalGridApi.kt new file mode 100644 index 0000000000000..3e9e85b50c624 --- /dev/null +++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/ExperimentalGridApi.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2026 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 androidx.compose.foundation.layout + +@RequiresOptIn( + "This foundation layout API is experimental and is likely to change or be removed in the future." +) +@Retention(AnnotationRetention.BINARY) +annotation class ExperimentalGridApi diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Grid.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Grid.kt new file mode 100644 index 0000000000000..6803cf2809d90 --- /dev/null +++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Grid.kt @@ -0,0 +1,1823 @@ +/* + * Copyright 2026 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. + */ + +@file:OptIn(ExperimentalGridApi::class) + +package androidx.compose.foundation.layout + +import androidx.annotation.FloatRange +import androidx.collection.LongList +import androidx.collection.MutableIntSet +import androidx.collection.MutableObjectList +import androidx.collection.mutableLongListOf +import androidx.compose.foundation.layout.GridScope.Companion.GridIndexUnspecified +import androidx.compose.foundation.layout.GridScope.Companion.MaxGridIndex +import androidx.compose.foundation.layout.internal.JvmDefaultWithCompatibility +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.State +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.Layout +import androidx.compose.ui.layout.Measurable +import androidx.compose.ui.layout.MeasurePolicy +import androidx.compose.ui.layout.MeasureResult +import androidx.compose.ui.layout.MeasureScope +import androidx.compose.ui.layout.Placeable +import androidx.compose.ui.node.ModifierNodeElement +import androidx.compose.ui.node.ParentDataModifierNode +import androidx.compose.ui.platform.InspectorInfo +import androidx.compose.ui.unit.Constraints +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.constrainHeight +import androidx.compose.ui.unit.constrainWidth +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach +import kotlin.jvm.JvmInline +import kotlin.math.max +import kotlin.math.roundToInt + +/** + * A 2D layout composable that arranges children into a grid of rows and columns. + * + * The [Grid] allows defining explicit tracks (columns and rows) with various sizing capabilities, + * including fixed sizes (`dp`), flexible fractions (`fr`), percentages, and content-based sizing + * (`Auto`). + * + * **Key Features:** + * * **Explicit vs. Implicit:** You define the main structure via [config] (explicit tracks). If + * items are placed outside these defined bounds, or if auto-placement creates new rows/columns, + * the grid automatically extends using implicit sizing (defaults to `Auto`). + * * **Flexible Sizing:** Use [Fr] units (e.g., `1.fr`, `2.fr`) to distribute available space + * proportionally among tracks. + * * **Auto-placement:** Items without a specific [GridScope.gridItem] modifier flow automatically + * into the next available cell based on the configured [GridFlow]. . + * + * @param config A block that defines the columns, rows, and gaps of the grid. This block runs + * during the measure pass, enabling efficient updates based on state. + * @param modifier The modifier to be applied to the layout. + * @param content The content of the grid. Direct children can use [GridScope.gridItem] to configure + * their position and span. + * @see GridScope.gridItem + * @see GridConfigurationScope + */ +@Composable +@ExperimentalGridApi +inline fun Grid( + noinline config: GridConfigurationScope.() -> Unit, + modifier: Modifier = Modifier, + content: @Composable GridScope.() -> Unit, +) { + // Capture the latest config lambda in a State object. + // This ensures we always have access to the latest lambda without recreating the policy. + val currentConfig = rememberUpdatedState(config) + + // Create a stable MeasurePolicy instance. + // We use 'remember' without keys so the policy instance itself never changes. + // The policy reads 'currentConfig.value' inside measure(), triggering invalidation + // when the config changes. + val measurePolicy = remember { GridMeasurePolicy(currentConfig) } + + Layout( + content = { GridScopeInstance.content() }, + modifier = modifier, + measurePolicy = measurePolicy, + ) +} + +/** Scope for the children of [Grid]. */ +@LayoutScopeMarker +@Immutable +@JvmDefaultWithCompatibility +@ExperimentalGridApi +interface GridScope { + /** + * Configures the position, span, and alignment of an element within a [Grid] layout. + * + * Apply this modifier to direct children of a [Grid] composable. + * + * **Default Behavior:** If this modifier is not applied to a child, the child will be + * automatically placed in the next available cell (spanning 1 row and 1 column) according to + * the configured [GridFlow]. + * + * **Indexing:** Grid row and column indices are **1-based**. + * * **Positive** values count from the start (1 is the first row/column). + * * **Negative** values count from the end (-1 is the last explicitly defined row/column). + * + * **Auto-placement:** If [row] or [column] are left to their default value + * ([GridIndexUnspecified]), the [Grid] layout will automatically place the item based on the + * configured [GridFlow]. + * + * @param row The specific 1-based row index to place the item in. Positive values count from + * the start (1 is the first row). Negative values count from the end (-1 is the last row). + * Must be within the range [-[MaxGridIndex], [MaxGridIndex]]. Defaults to + * [GridIndexUnspecified] for auto-placement. + * @param column The specific 1-based column index to place the item in. Positive values count + * from the start (1 is the first column). Negative values count from the end (-1 is the last + * column). Must be within the range [-[MaxGridIndex], [MaxGridIndex]]. Defaults to + * [GridIndexUnspecified] for auto-placement. + * @param rowSpan The number of rows this item should occupy. Must be greater than 0. Defaults + * to 1. + * @param columnSpan The number of columns this item should occupy. Must be greater than 0. + * Defaults to 1. + * @param alignment Specifies how the content should be aligned within the grid cell(s) it + * occupies. Defaults to [Alignment.TopStart]. + * @throws IllegalArgumentException if [row] or [column] (when specified) are outside the valid + * range, or if [rowSpan] or [columnSpan] are less than 1. + * @see GridIndexUnspecified + * @see MaxGridIndex + */ + @Stable + fun Modifier.gridItem( + row: Int = GridIndexUnspecified, + column: Int = GridIndexUnspecified, + rowSpan: Int = 1, + columnSpan: Int = 1, + alignment: Alignment = Alignment.TopStart, + ): Modifier + + /** + * Configures the position, span, and alignment of an element within a [Grid] layout using + * ranges. + * + * This convenience overload converts [IntRange] inputs into row/column indices and spans. + * + * **Equivalence:** + * - `rows = 4..5` maps to `row = 4`, `rowSpan = 2`. + * - `columns = 1..1` maps to `column = 1`, `columnSpan = 1`. + * + * Example: `Modifier.gridItem(rows = 2..3, columns = 1..2)` is functionally equivalent to + * `Modifier.gridItem(row = 2, rowSpan = 2, column = 1, columnSpan = 2)`. + * + * @param rows The range of rows to occupy (e.g., `1..2`). The start determines the row index, + * and the size of the range determines the span. + * @param columns The range of columns to occupy (e.g., `1..3`). The start determines the column + * index, and the size of the range determines the span. + * @param alignment Specifies how the content should be aligned within the grid cell(s). + * Defaults to [Alignment.TopStart]. + * @see Modifier.gridItem + */ + @Stable + fun Modifier.gridItem( + rows: IntRange, + columns: IntRange, + alignment: Alignment = Alignment.TopStart, + ): Modifier + + companion object { + /** + * The maximum allowed index for a row or column (inclusive). + * + * This hard limit prevents performance degradation, layout timeouts, or memory issues + * potentially caused by accidental loop overflows or unreasonably large sparse grid + * definitions. + */ + @ExperimentalGridApi const val MaxGridIndex: Int = 1000 + + /** + * Sentinel value indicating that a grid position (row or column) is not manually specified + * and should be determined automatically by the layout flow. + */ + @ExperimentalGridApi const val GridIndexUnspecified: Int = 0 + } +} + +/** Internal implementation of [GridScope]. Stateless object to avoid allocations. */ +@PublishedApi +@ExperimentalGridApi +internal object GridScopeInstance : GridScope { + + override fun Modifier.gridItem( + row: Int, + column: Int, + rowSpan: Int, + columnSpan: Int, + alignment: Alignment, + ): Modifier { + if (row != GridIndexUnspecified) { + require(row in -MaxGridIndex..MaxGridIndex) { + "row must be between -$MaxGridIndex and $MaxGridIndex" + } + } + if (column != GridIndexUnspecified) { + require(column in -MaxGridIndex..MaxGridIndex) { + "column must be between -$MaxGridIndex and $MaxGridIndex" + } + } + require(rowSpan > 0) { "rowSpan must be > 0" } + require(columnSpan > 0) { "columnSpan must be > 0" } + return this.then(GridItemElement(row, column, rowSpan, columnSpan, alignment)) + } + + override fun Modifier.gridItem( + rows: IntRange, + columns: IntRange, + alignment: Alignment, + ): Modifier { + require(!rows.isEmpty()) { "Row range ($rows) cannot be empty" } + require(!columns.isEmpty()) { "Column range ($columns) cannot be empty" } + + val row = rows.first + val rowSpan = rows.last - rows.first + 1 + val column = columns.first + val columnSpan = columns.last - columns.first + 1 + return this.gridItem(row, column, rowSpan, columnSpan, alignment) + } +} + +/** + * Scope for configuring the structure of a [Grid]. + * + * This interface is implemented by the configuration block in [Grid]. It allows defining columns, + * rows, and gaps. + */ +@LayoutScopeMarker +@ExperimentalGridApi +interface GridConfigurationScope : Density { + + /** + * The direction in which items that do not specify a position are placed. Defaults to + * [GridFlow.Row]. + */ + var flow: GridFlow + + /** Defines a fixed-width column. Maps to [GridTrackSize.Fixed]. */ + fun column(size: Dp) + + /** Defines a flexible column. Maps to [GridTrackSize.Flex]. */ + fun column(weight: Fr) + + /** Defines a percentage-based column. Maps to [GridTrackSize.Percentage]. */ + fun column(percentage: Float) + + /** Defines a new column track with the specified [size]. */ + fun column(size: GridTrackSize) + + /** Defines a fixed-width row. Maps to [GridTrackSize.Fixed]. */ + fun row(size: Dp) + + /** Defines a flexible row. Maps to [GridTrackSize.Flex]. */ + fun row(weight: Fr) + + /** Defines a percentage-based row. Maps to [GridTrackSize.Percentage]. */ + fun row(percentage: Float) + + /** Defines a new row track with the specified [size]. */ + fun row(size: GridTrackSize) + + /** + * Sets both the row and column gaps (gutters) to [all]. + * + * **Precedence:** If this is called multiple times, or mixed with [columnGap] or [rowGap], the + * **last call** takes precedence. + * + * @throws IllegalArgumentException if [all] is negative. + */ + fun gap(all: Dp) + + /** + * Sets independent gaps for rows and columns. + * + * **Precedence:** If this is called multiple times, or mixed with [columnGap] or [rowGap], the + * **last call** takes precedence. + * + * @throws IllegalArgumentException if [row] or [column] is negative. + */ + fun gap(row: Dp, column: Dp) + + /** + * Sets the gap (gutter) size between columns. + * + * **Precedence:** If this is called multiple times, the **last call** takes precedence. This + * call will overwrite the column component of any previous [gap] call. + * + * @throws IllegalArgumentException if [gap] is negative. + */ + fun columnGap(gap: Dp) + + /** + * Sets the gap (gutter) size between rows. + * + * **Precedence:** If this is called multiple times, the **last call** takes precedence. This + * call will overwrite the row component of any previous [gap] call. + * + * @throws IllegalArgumentException if [gap] is negative. + */ + fun rowGap(gap: Dp) + + /** Creates an [Fr] unit from an [Int]. */ + @Stable + @ExperimentalGridApi + val Int.fr: Fr + get() = Fr(this.toFloat()) + + /** Creates an [Fr] unit from a [Float]. */ + @Stable + @ExperimentalGridApi + val Float.fr: Fr + get() = Fr(this) + + /** Creates an [Fr] unit from a [Double]. */ + @Stable + @ExperimentalGridApi + val Double.fr: Fr + get() = Fr(this.toFloat()) +} + +/** Adds multiple columns with the specified [specs]. */ +@ExperimentalGridApi +fun GridConfigurationScope.columns(vararg specs: GridTrackSpec) { + for (spec in specs) { + if (spec is GridTrackSize) { + column(spec) + } + } +} + +/** Adds multiple rows with the specified [specs]. */ +@ExperimentalGridApi +fun GridConfigurationScope.rows(vararg specs: GridTrackSpec) { + for (spec in specs) { + if (spec is GridTrackSize) { + row(spec) + } + } +} + +/** Defines the direction in which auto-placed items flow within the grid. */ +@JvmInline +@ExperimentalGridApi +value class GridFlow @PublishedApi internal constructor(private val bits: Int) { + + companion object { + /** Items are placed filling the first row, then moving to the next row. */ + @ExperimentalGridApi + inline val Row + get() = GridFlow(0) + + /** Items are placed filling the first column, then moving to the next column. */ + @ExperimentalGridApi + inline val Column + get() = GridFlow(1) + } + + override fun toString(): String = + when (this) { + Row -> "Row" + Column -> "Column" + else -> "GridFlow($bits)" + } +} + +/** + * Represents a flexible unit used for sizing [Grid] tracks. + * + * One [Fr] unit represents a fraction of the *remaining* space in the grid container after + * [GridTrackSize.Fixed] and [GridTrackSize.Percentage] tracks have been allocated. + */ +@JvmInline +@ExperimentalGridApi +value class Fr(val value: Float) { + override fun toString(): String = "$value.fr" +} + +/** + * Marker interface to enable vararg usage with [GridTrackSize]. + * + * This allows the configuration DSL to accept [GridTrackSize] items in a vararg (e.g., + * `columns(Fixed(10.dp), Flex(1.fr))`), bypassing the Kotlin limitation on value class varargs. + */ +@ExperimentalGridApi sealed interface GridTrackSpec + +/** + * Defines the size of a track (a row or a column) in a [Grid]. + * + * Use the companion functions (e.g., [Fixed], [Flex]) to create instances. + */ +@Immutable +@JvmInline +@ExperimentalGridApi +value class GridTrackSize internal constructor(internal val encodedValue: Long) : GridTrackSpec { + + internal val type: Int + get() = (encodedValue ushr 32).toInt() + + internal val value: Float + get() = Float.fromBits(encodedValue.toInt()) + + override fun toString(): String = + when (type) { + TypeFixed -> "Fixed(${value}dp)" + TypePercentage -> "Percentage($value)" + TypeFlex -> "Flex(${value}fr)" + TypeMinContent -> "MinContent" + TypeMaxContent -> "MaxContent" + TypeAuto -> "Auto" + else -> "Unknown" + } + + companion object { + internal const val TypeFixed = 1 + internal const val TypePercentage = 2 + internal const val TypeFlex = 3 + internal const val TypeMinContent = 4 + internal const val TypeMaxContent = 5 + internal const val TypeAuto = 6 + + /** + * A track with a fixed [Dp] size. + * + * @param size The size of the track. + * @throws IllegalArgumentException if [size] is negative or [Dp.Unspecified]. + */ + @Stable + fun Fixed(size: Dp): GridTrackSize { + require(size != Dp.Unspecified && size.value >= 0f) { + "Fixed size must be non-negative and specified (was $size)" + } + return pack(TypeFixed, size.value) + } + + /** + * A track sized as a percentage of the **total** available size of the grid container. + * **Note:** In this implementation, percentages are calculated based on the **remaining + * available space after gaps**. This differs from the W3C CSS Grid spec, where percentages + * are based on the container size regardless of gaps. This behavior prevents unexpected + * overflows when mixing gaps and percentages (e.g., `50%` + `50%` + `gap` will fit + * perfectly here, but would overflow in CSS). + * + * @param value The percentage of the container size. + * @throws IllegalArgumentException if [value] is negative. + */ + @Stable + fun Percentage(@FloatRange(from = 0.0) value: Float): GridTrackSize { + require(value >= 0f) { "Percentage cannot be negative" } + return pack(TypePercentage, value) + } + + /** + * A flexible track that takes a share of the **remaining** space after Fixed and Percentage + * tracks are allocated. + * + * @param weight The flexible weight. Space is distributed proportional to this weight + * divided by the total flex weight. Must be non-negative. + * @throws IllegalArgumentException if [weight] is negative. + */ + @Stable + fun Flex(@FloatRange(from = 0.0) weight: Fr): GridTrackSize { + require(weight.value >= 0f) { "Flex weight must be positive" } + return pack(TypeFlex, weight.value) + } + + /** A track that sizes itself to fit the minimum intrinsic size of its contents. */ + @Stable val MinContent = pack(TypeMinContent, 0f) + + /** A track that sizes itself to fit the maximum intrinsic size of its contents. */ + @Stable val MaxContent = pack(TypeMaxContent, 0f) + + /** + * A track that behaves automatically, typically similar to [MinContent] or [Flex] depending + * on context. + */ + @Stable val Auto = pack(TypeAuto, 0f) + + private fun pack(type: Int, value: Float): GridTrackSize { + // Pack Type (High 32) and Float bits (Low 32) into one Long. + // Mask 0xFFFFFFFFL prevents sign extension when casting int to long. + val raw = (type.toLong() shl 32) or (value.toRawBits().toLong() and 0xFFFFFFFFL) + return GridTrackSize(raw) + } + } +} + +/** + * The modifier element that creates and updates [GridItemNode]. + * + * @property row The 1-based row index, or [GridScope.GridIndexUnspecified] for auto-placement. + * @property column The 1-based column index, or [GridScope.GridIndexUnspecified] for + * auto-placement. + * @property rowSpan The number of rows the item should occupy. + * @property columnSpan The number of columns the item should occupy. + * @property alignment The alignment of the content within the grid cell. + * @see GridItemNode + */ +private class GridItemElement( + val row: Int, + val column: Int, + val rowSpan: Int, + val columnSpan: Int, + val alignment: Alignment, +) : ModifierNodeElement() { + override fun create(): GridItemNode = GridItemNode(row, column, rowSpan, columnSpan, alignment) + + override fun update(node: GridItemNode) { + node.row = row + node.column = column + node.rowSpan = rowSpan + node.columnSpan = columnSpan + node.alignment = alignment + } + + override fun InspectorInfo.inspectableProperties() { + name = "gridItem" + properties["row"] = row + properties["column"] = column + properties["rowSpan"] = rowSpan + properties["columnSpan"] = columnSpan + properties["alignment"] = alignment + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is GridItemElement) return false + + if (row != other.row) return false + if (column != other.column) return false + if (rowSpan != other.rowSpan) return false + if (columnSpan != other.columnSpan) return false + if (alignment != other.alignment) return false + + return true + } + + override fun hashCode(): Int { + var result = row + result = 31 * result + column + result = 31 * result + rowSpan + result = 31 * result + columnSpan + result = 31 * result + alignment.hashCode() + return result + } +} + +/** + * The modifier node that provides parent data to the [Grid] layout. + * + * This class implements [ParentDataModifierNode], allowing the parent [Grid] layout to inspect the + * configuration (row, column, spans) of this specific child during the measurement phase via the + * [modifyParentData] method. + * + * @property row The 1-based row index, or [GridScope.GridIndexUnspecified] for auto-placement. + * @property column The 1-based column index, or [GridScope.GridIndexUnspecified] for + * auto-placement. + * @property rowSpan The number of rows the item should occupy. + * @property columnSpan The number of columns the item should occupy. + * @property alignment The alignment of the content within the grid cell. + * @throws IllegalArgumentException if [rows] or [columns] ranges are empty, or if the derived + * row/column indices or spans do not meet the requirements of the primary [gridItem] function. + * @see GridScope.gridItem for the public API and input validation. + */ +private class GridItemNode( + var row: Int, + var column: Int, + var rowSpan: Int, + var columnSpan: Int, + var alignment: Alignment, +) : Modifier.Node(), ParentDataModifierNode { + override fun Density.modifyParentData(parentData: Any?) = this@GridItemNode +} + +/** A stable MeasurePolicy that reads configuration from a State. */ +@PublishedApi +@ExperimentalGridApi +internal class GridMeasurePolicy( + private val configState: State Unit> +) : MeasurePolicy { + override fun MeasureScope.measure( + measurables: List, + constraints: Constraints, + ): MeasureResult { + // 1. Run Configuration DSL + val gridConfig = GridConfigurationScopeImpl(this).apply(configState.value) + + // 2. Resolve Grid Item Indices (Resolve explicit and Auto placement) + // This calculates the concrete index (row, col) for every item and determines total grid + // size. + val resolvedGridItemsResult = + resolveGridItemIndices( + measurables = measurables, + columnSpecs = gridConfig.columnSpecs, + rowSpecs = gridConfig.rowSpecs, + flow = gridConfig.flow, + ) + + // 3. Resolve Track Sizes + val trackSizes = + calculateGridTrackSizes( + density = this, + gridItems = resolvedGridItemsResult.gridItems, + columnSpecs = gridConfig.columnSpecs, + rowSpecs = gridConfig.rowSpecs, + totalColCount = resolvedGridItemsResult.gridSize.width, + totalRowCount = resolvedGridItemsResult.gridSize.height, + columnGap = gridConfig.columnGap, + rowGap = gridConfig.rowGap, + constraints = constraints, + ) + + // 4. Measure Children + // Measures content constraints based on track sizes and mutates GridItem with result. + measureItems( + gridItems = resolvedGridItemsResult.gridItems, + trackSizes = trackSizes, + layoutDirection = layoutDirection, + ) + + // 5. Layout + // Coerce the final size within constraints. + // If content is larger, it will overflow (report Max). + // If content is smaller than Min, it will expand (report Min). + val layoutWidth = constraints.constrainWidth(trackSizes.totalWidth) + val layoutHeight = constraints.constrainHeight(trackSizes.totalHeight) + return layout(layoutWidth, layoutHeight) { + val columnOffsets = + calculateTrackOffsets(trackSizes.columnWidths, trackSizes.columnGapPx) + val rowOffsets = calculateTrackOffsets(trackSizes.rowHeights, trackSizes.rowGapPx) + resolvedGridItemsResult.gridItems.forEach { gridItem -> + val placeable = gridItem.placeable + // Only place if measurement succeeded (guard against edge cases) + if (placeable != null) { + val x = columnOffsets[gridItem.column] + gridItem.offsetX + val y = rowOffsets[gridItem.row] + gridItem.offsetY + placeable.place(x, y) + } + } + } + } +} + +private class GridConfigurationScopeImpl(density: Density) : + GridConfigurationScope, Density by density { + val columnSpecs = mutableLongListOf() + val rowSpecs = mutableLongListOf() + var columnGap: Dp = 0.dp + var rowGap: Dp = 0.dp + + override var flow: GridFlow = GridFlow.Row + + override fun column(size: Dp) { + column(GridTrackSize.Fixed(size)) + } + + override fun column(weight: Fr) { + column(GridTrackSize.Flex(weight)) + } + + override fun column(percentage: Float) { + column(GridTrackSize.Percentage(percentage)) + } + + override fun column(size: GridTrackSize) { + columnSpecs.add(size.encodedValue) + } + + override fun row(size: Dp) { + row(GridTrackSize.Fixed(size)) + } + + override fun row(weight: Fr) { + row(GridTrackSize.Flex(weight)) + } + + override fun row(percentage: Float) { + row(GridTrackSize.Percentage(percentage)) + } + + override fun row(size: GridTrackSize) { + rowSpecs.add(size.encodedValue) + } + + override fun gap(all: Dp) { + require(all.value >= 0f) { "Gap must be non-negative" } + columnGap = all + rowGap = all + } + + override fun gap(row: Dp, column: Dp) { + require(row.value >= 0f) { "Row gap must be non-negative" } + require(column.value >= 0f) { "Column gap must be non-negative" } + rowGap = row + columnGap = column + } + + override fun columnGap(gap: Dp) { + require(gap.value >= 0f) { "Column gap must be non-negative" } + columnGap = gap + } + + override fun rowGap(gap: Dp) { + require(gap.value >= 0f) { "Row gap must be non-negative" } + rowGap = gap + } +} + +/** + * A mutable state object representing a single child in the Grid throughout the layout lifecycle. + * + * This object is created once during the [resolveGridItemIndices] phase (containing only placement + * info) and is reused and mutated during the [measureItems] phase to store the resulting + * [Placeable] and calculation offsets. This significantly reduces object allocation per layout + * pass. + */ +private class GridItem( + val measurable: Measurable, + var row: Int, + var column: Int, + var rowSpan: Int, + var columnSpan: Int, + val alignment: Alignment, + var placeable: Placeable? = null, + var offsetX: Int = 0, + var offsetY: Int = 0, +) + +/** + * The output of the [resolveGridItemIndices] algorithm. + * + * This container holds the complete layout plan required for subsequent measurement phases. It + * encapsulates both the individual item positions and the aggregate dimensions of the grid. + * + * The [gridSize] is critical because it reveals the extent of the "Implicit Grid" — tracks that + * were not explicitly defined by the user but were created automatically to accommodate auto-placed + * items or items with out-of-bounds indices. + * + * @property gridItems The list of all items with their resolved (row, column) coordinates. + * @property gridSize The total number of rows and columns required to house all items. (width = + * total columns, height = total rows). + */ +private class ResolvedGridItemIndicesResult( + val gridItems: MutableObjectList, + val gridSize: IntSize, +) + +/** + * The "Master Blueprint" holding the calculated pixel dimensions for the entire grid. + * + * This class acts as a lookup table during the measurement phase. Instead of recalculating sizes + * for every item, we compute the track sizes once and pass this object around. + * + * @property columnWidths Array containing the exact width in pixels for each column index. + * @property rowHeights Array containing the exact height in pixels for each row index. + * @property totalWidth The sum of all column widths plus gaps. + * @property totalHeight The sum of all row heights plus gaps. + * @property columnGapPx The spacing between columns. + * @property rowGapPx The spacing between rows. + */ +private class GridTrackSizes( + val columnWidths: IntArray, + val rowHeights: IntArray, + val totalWidth: Int, + val totalHeight: Int, + val columnGapPx: Int, + val rowGapPx: Int, +) + +/** + * Executes the "Sparse Packing" auto-placement algorithm to resolve every item's position. + * + * This function is the "Engine" of the auto-placement logic. It transforms a list of raw + * measurables (with potentially unspecified `row`/`column` values) into a concrete plan where every + * item has a specific (row, column) coordinate. + * + * **Algorithm Overview:** + * 1. **Explicit Placement:** Items with both `row` and `column` manually specified are placed + * first. They anchor the grid and do not move. + * 2. **Auto-Placement Cursor:** A "cursor" (current row/column pointer) tracks the next available + * position. + * 3. **Filling Gaps:** The algorithm iterates through the remaining items. For each item: + * - It advances the cursor to the first slot that can accommodate the item's span without + * overlapping existing items. + * - It respects the [flow] direction (Row-major vs Column-major). + * - It creates "Implicit Tracks" (expanding the grid bounds) if an item is placed outside the + * currently defined area. + * + * @param measurables The raw list of children to place. + * @param columnSpecs The explicit column definitions (used to determine wrapping points). + * @param rowSpecs The explicit row definitions (used to determine wrapping points). + * @param flow The direction ([GridFlow.Row] or [GridFlow.Column]) to fill the grid. + * @return A [ResolvedGridItemIndicesResult] containing the final positions and the *total* grid + * dimensions (Explicit + Implicit). + */ +private fun resolveGridItemIndices( + measurables: List, + columnSpecs: LongList, + rowSpecs: LongList, + flow: GridFlow, +): ResolvedGridItemIndicesResult { + val gridItems = MutableObjectList(measurables.size) + + // Key = (row shl 16) | (column & 0xFFFF) + // Supports up to 65,535 rows/cols (well within MaxGridIndex). + val occupiedCells = MutableIntSet() + + val explicitColCount = columnSpecs.size + val explicitRowCount = rowSpecs.size + + // Track the effective size of the grid (starts at explicit size, expands if items are placed + // outside) + var maxRow = explicitRowCount + var maxCol = explicitColCount + + // Pack into Int (Row in high 16 bits, Col in low 16 bits) + // Supports up to 65,535 rows/cols. + fun packCoordinate(row: Int, column: Int): Int = (row shl 16) or (column and 0xFFFF) + + // Checks if the target area (defined by start position and span) overlaps with any existing + // item. + fun isAreaOccupied(startRow: Int, startCol: Int, rowSpan: Int, colSpan: Int): Boolean { + // Fast-path: Check boundary limits first + if (startRow + rowSpan > MaxGridIndex || startCol + colSpan > MaxGridIndex) return true + for (r in startRow until startRow + rowSpan) { + for (c in startCol until startCol + colSpan) { + if (occupiedCells.contains(packCoordinate(r, c))) return true + } + } + return false + } + + // Marks the cells in the area as occupied. + fun markAreaOccupied(startRow: Int, startCol: Int, rowSpan: Int, colSpan: Int) { + for (r in startRow until startRow + rowSpan) { + for (c in startCol until startCol + colSpan) { + occupiedCells.add(packCoordinate(r, c)) + } + } + } + + // The "Cursor" tracks the position of the last auto-placed item. + // Subsequent auto-placed items attempt to start searching from here to avoid re-scanning the + // whole grid. + var autoPlacementCursorRow = 0 + var autoPlacementCursorCol = 0 + + measurables.fastForEach { measurable -> + val data = measurable.parentData as? GridItemNode + val rowSpan = data?.rowSpan ?: 1 + val colSpan = data?.columnSpan ?: 1 + + // Convert 1-based user indices to 0-based internal indices. + // Returns null if the user index was unspecified (Auto). + val requestedRow = + resolveToZeroBasedIndex(data?.row ?: GridIndexUnspecified, explicitRowCount) + val requestedCol = + resolveToZeroBasedIndex(data?.column ?: GridIndexUnspecified, explicitColCount) + + var finalRow = -1 + var finalCol = -1 + + // 1. Fully Explicit (Row & Column fixed) + // We simply place it there. Overlaps are allowed for explicit placement. + if (requestedRow != -1 && requestedCol != -1) { + finalRow = requestedRow + finalCol = requestedCol + } + // 2. Fixed Row (Search for Column) + else if (requestedRow != -1) { + // Search for the first available column in the specified row. + finalRow = requestedRow + var candidateCol = 0 + + // If flowing by Row, and we are on the cursor's row, start searching from cursor + if (flow == GridFlow.Row && requestedRow == autoPlacementCursorRow) { + candidateCol = autoPlacementCursorCol + } + while (candidateCol < MaxGridIndex) { + if (!isAreaOccupied(requestedRow, candidateCol, rowSpan, colSpan)) { + finalCol = candidateCol + break + } + candidateCol++ + } + } + // 3. Fixed Column (Search for Row) + else if (requestedCol != -1) { + // Search for the first available row in the specified column. + finalCol = requestedCol + var candidateRow = 0 + // If flowing by Column, and we are on the cursor's col, start searching from cursor + if (flow == GridFlow.Column && requestedCol == autoPlacementCursorCol) { + candidateRow = autoPlacementCursorRow + } + while (candidateRow < MaxGridIndex) { + if (!isAreaOccupied(candidateRow, requestedCol, rowSpan, colSpan)) { + finalRow = candidateRow + break + } + candidateRow++ + } + } + // 4. Fully Auto (Search for Slot) + else { + // Start searching from the current cursor position. + var candidateRow = autoPlacementCursorRow + var candidateCol = autoPlacementCursorCol + + while (candidateRow < MaxGridIndex && candidateCol < MaxGridIndex) { + // Wrapping Logic + // If the item doesn't fit in the current track (explicit bounds), wrap to next. + if (flow == GridFlow.Row) { + // If we have explicit columns and exceed them... + if (explicitColCount > 0 && candidateCol + colSpan > explicitColCount) { + // If we are NOT at start, wrap. + // If we ARE at start (0) and still don't fit, we must overflow (create + // implicit track). + if (candidateCol > 0) { + candidateCol = 0 + candidateRow++ + continue // Re-evaluate wrapping at new position + } + } + } else { // GridFlow.Column + if (explicitRowCount > 0 && candidateRow + rowSpan > explicitRowCount) { + if (candidateRow > 0) { + candidateRow = 0 + candidateCol++ + continue + } + } + } + + if (!isAreaOccupied(candidateRow, candidateCol, rowSpan, colSpan)) { + finalRow = candidateRow + finalCol = candidateCol + break + } + + // Increment + if (flow == GridFlow.Row) { + candidateCol++ + // If we drift too far right without wrapping (infinite grid), force wrap safety + if (candidateCol > MaxGridIndex) { + candidateCol = 0 + candidateRow++ + } + } else { + candidateRow++ + if (candidateRow > MaxGridIndex) { + candidateRow = 0 + candidateCol++ + } + } + } + } + + // If auto-placement failed to find a spot (e.g. MaxGridIndex reached), + // we default to 0,0 to avoid crashing, though visual overlap will occur. + val placementRow = max(0, finalRow) + val placementCol = max(0, finalCol) + + markAreaOccupied(placementRow, placementCol, rowSpan, colSpan) + + // Populate the mutable GridItem + gridItems.add( + GridItem( + measurable = measurable, + row = placementRow, + column = placementCol, + rowSpan = rowSpan, + columnSpan = colSpan, + alignment = data?.alignment ?: Alignment.TopStart, + ) + ) + + // Expand total grid bounds if necessary + maxRow = max(maxRow, placementRow + rowSpan) + maxCol = max(maxCol, placementCol + colSpan) + + // Update Cursor (Only for non-explicit placements) + // Only update cursor if the item was NOT fully explicit. + // Explicit items are "out of flow" and shouldn't drag the cursor with them. + if (requestedRow == -1 || requestedCol == -1) { + if (flow == GridFlow.Row) { + autoPlacementCursorRow = placementRow + autoPlacementCursorCol = placementCol + colSpan + } else { + autoPlacementCursorRow = placementRow + rowSpan + autoPlacementCursorCol = placementCol + } + } + } + + return ResolvedGridItemIndicesResult(gridItems, IntSize(maxCol, maxRow)) +} + +/** + * Resolves a 1-based user index (positive or negative) to a 0-based concrete index. + * + * @param index The user-provided index (e.g., 1, -1, or [GridIndexUnspecified]). + * @param maxCount The number of explicit tracks defined (used for negative index resolution). + * @return The 0-based index, or -1 if the index was unspecified or invalid (e.g. negative index out + * of bounds). + */ +private fun resolveToZeroBasedIndex(index: Int, maxCount: Int): Int { + if (index == GridIndexUnspecified) return -1 + + // Positive Index (e.g., 5): Maps to 4. + // Always valid (allows creating implicit tracks if > maxCount). + if (index > 0) return index - 1 + + // Negative Index (e.g., -1): Maps to maxCount - 1. + // Must check if it points to a valid explicit track [0..maxCount-1]. + // If it points before 0 (e.g. -5 in a 2-row grid), it is invalid. + val resolved = maxCount + index + return if (resolved >= 0) resolved else -1 +} + +/** + * Resolves the abstract [GridTrackSize] specifications for all rows and columns into concrete pixel + * dimensions. This function is the core of the size calculation logic for the [Grid]. + * + * **Calculation Order:** The calculation is performed in two main phases: + * 1. **Column Widths:** Column widths are calculated first. This is crucial because the height of + * many UI elements (like text) depends on the available width. + * 2. **Row Heights:** Row heights are calculated second, utilizing the resolved column widths to + * accurately measure items, especially those with content that wraps. + * + * **Track Type Resolution:** Within each phase, different [GridTrackSize] types are resolved as + * follows: + * - [GridTrackSize.Fixed]: Converted directly to pixels using the [density]. + * - [GridTrackSize.Percentage]: Calculated based on the available space for tracks (after + * subtracting gaps). Falls back to content-based size (MaxContent) if the available space on that + * axis is infinite (e.g., in a scrollable container). + * - [GridTrackSize.MinContent], [GridTrackSize.MaxContent], [GridTrackSize.Auto]: Determined by + * measuring the intrinsic sizes of the items within the track. `Auto` typically behaves like + * `MaxContent`. + * - [GridTrackSize.Flex]: Initially sized to their minimum content size. After all other types and + * spanning items are accounted for, any remaining space is distributed proportionally among flex + * tracks. + * + * **Implicit Tracks:** Tracks not explicitly defined in [columnSpecs] or [rowSpecs] (i.e., indices + * beyond the spec list sizes) are treated as `GridTrackSize.Auto`. + * + * **Spanning Items:** The function accounts for items spanning multiple tracks, potentially + * increasing the sizes of growable tracks ([Auto], [MinContent], [MaxContent], [Flex]) to + * accommodate them. + * + * @param density The current screen density, used for converting Dp to pixels. + * @param gridItems The list of all grid items, including their placement and spans. + * @param columnSpecs The explicit configurations for columns. + * @param rowSpecs The explicit configurations for rows. + * @param totalColCount The total number of columns in the grid (explicit + implicit). + * @param totalRowCount The total number of rows in the grid (explicit + implicit). + * @param constraints The layout constraints from the parent composable. + * @param columnGap The spacing in Dp between columns. + * @param rowGap The spacing in Dp between rows. + * @return A [GridTrackSizes] object containing the calculated pixel sizes for each column and row, + * the total grid dimensions, and the gap sizes in pixels. + */ +private fun calculateGridTrackSizes( + density: Density, + gridItems: MutableObjectList, + columnSpecs: LongList, + rowSpecs: LongList, + totalColCount: Int, // Total (Implicit + Explicit) + totalRowCount: Int, // Total (Implicit + Explicit) + constraints: Constraints, + columnGap: Dp, + rowGap: Dp, +): GridTrackSizes { + val colGapPx = with(density) { columnGap.roundToPx() } + val rowGapPx = with(density) { rowGap.roundToPx() } + + // Group items by track index to avoid O(Tracks * Items) loop + // Array of lists, where index corresponds to the column index + val itemsByColumn = arrayOfNulls>(totalColCount) + // Array of lists, where index corresponds to the row index + val itemsByRow = arrayOfNulls>(totalRowCount) + + gridItems.forEach { item -> + // Populate Column Lookup + if (item.column < totalColCount) { + val list = + itemsByColumn[item.column] + ?: MutableObjectList().also { itemsByColumn[item.column] = it } + list.add(item) + } + // Populate Row Lookup + if (item.row < totalRowCount) { + val list = + itemsByRow[item.row] + ?: MutableObjectList().also { itemsByRow[item.row] = it } + list.add(item) + } + } + + // --- Phase 1: Calculate Column Widths --- + // Use totalColCount for array size + val columnWidths = IntArray(totalColCount) + // If constraints are infinite (e.g. horizontal scroll), we pass Infinity. + // This triggers the fallback logic in calculateAxisSize (Percentage -> Auto). + val availableWidth = + if (constraints.hasFixedWidth) constraints.maxWidth else Constraints.Infinity + + val totalTrackWidth = + calculateColumnWidths( + density = density, + explicitSpecs = columnSpecs, + totalCount = totalColCount, + availableSpace = availableWidth, + outSizes = columnWidths, + itemsByColumn = itemsByColumn, + constraints = constraints, + gridItems = gridItems, + columnGap = colGapPx, + ) + + // --- Phase 2: Calculate Row Heights --- + val rowHeights = IntArray(totalRowCount) + val availableHeight = + if (constraints.hasFixedHeight) constraints.maxHeight else Constraints.Infinity + + val totalTrackHeight = + calculateRowHeights( + density = density, + explicitSpecs = rowSpecs, + totalCount = totalRowCount, + availableSpace = availableHeight, + outSizes = rowHeights, + itemsByRow = itemsByRow, + constraints = constraints, + columnWidths = columnWidths, + gridItems = gridItems, + rowGap = rowGapPx, + ) + + val totalColumnGap = max(0, columnSpecs.size - 1) * colGapPx + val totalRowGap = max(0, rowSpecs.size - 1) * rowGapPx + + return GridTrackSizes( + columnWidths = columnWidths, + rowHeights = rowHeights, + columnGapPx = colGapPx, + rowGapPx = rowGapPx, + totalWidth = totalTrackWidth + totalColumnGap, + totalHeight = totalTrackHeight + totalRowGap, + ) +} + +/** + * Calculates the specific pixel width of every column in the grid. + * + * This function implements the horizontal axis sizing logic. It resolves column widths based on + * explicit configuration, available space, and content intrinsic sizes. + * + * **Algorithm Overview:** + * 1. **Pass 1 (Base Sizes):** Calculates the initial width of each column based on its + * [GridTrackSize]. + * * **Implicit Tracks:** Indices beyond `explicitSpecs` default to [GridTrackSize.Auto]. + * * **Fixed:** Resolves directly to pixels. + * * **Percentage:** Resolves against total available width. Falls back to `Auto` (MaxContent) if + * width is infinite (e.g., inside a container made horizontally scrollable with the + * `horizontalScroll` modifier). + * * **Flex:** Starts at `min-content` size to prevent collapse if content exists. + * * **Auto/Content-based:** Measured using the intrinsic width of items in that column. + * 2. **Pass 1.5 (Spanning Items):** Increases column widths if an item spanning multiple columns + * requires more width than the sum of those columns. + * 3. **Pass 2 (Flex Distribution):** Distributes any remaining horizontal space among + * [GridTrackSize.Flex] columns according to their weight. + * + * @param density Used for Dp-to-Px conversion. + * @param explicitSpecs The user-defined column configurations. + * @param totalCount The total number of columns (explicit + implicit). + * @param availableSpace The maximum width available (or [Constraints.Infinity]). + * @param outSizes Output array where calculated widths are stored. **Mutated in-place**. + * @param itemsByColumn Optimization lookup: List of items starting in each column index. + * @param constraints Parent constraints (used for fallback behavior and cross-axis limits). + * @param gridItems All items in the grid (used for spanning logic). + * @param columnGap The spacing between columns. + * @return The total used width in pixels (sum of all column widths). + */ +private fun calculateColumnWidths( + density: Density, + explicitSpecs: LongList, + totalCount: Int, + availableSpace: Int, + outSizes: IntArray, + itemsByColumn: Array?>, + constraints: Constraints, + gridItems: MutableObjectList, + columnGap: Int, +): Int { + if (totalCount == 0) return 0 + + var totalFlex = 0f + // Calculate total space consumed by gaps. + // e.g., 3 columns have 2 gaps. (N-1) * gap. + val totalGapSpace = (columnGap * (totalCount - 1)).coerceAtLeast(0) + + // Calculate space available for actual tracks (Total - Gaps). + // If availableSpace is Infinity, availableTrackSpace value becomes Constraints.Infinity + val availableTrackSpace = + if (availableSpace == Constraints.Infinity) { + Constraints.Infinity + } else { + (availableSpace - totalGapSpace).coerceAtLeast(0) + } + + // Height constraint used when measuring intrinsic width. + // Usually Infinity (standard intrinsic measurement), unless parent enforces strict height. + val crossAxisAvailable = + if (constraints.hasBoundedHeight) constraints.maxHeight else Constraints.Infinity + + // --- Pass 1: Base Sizes (Single-Span Items) --- + // Iterate through every column index (both explicit and implicit). + for (index in 0 until totalCount) { + // If index exceeds explicit specs, treat it as an Implicit Auto track. + val specRaw = + if (index < explicitSpecs.size) explicitSpecs[index] + else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + val size = + when (spec.type) { + GridTrackSize.TypeFixed -> with(density) { spec.value.dp.roundToPx() } + + GridTrackSize.TypePercentage -> { + if (availableTrackSpace != Constraints.Infinity) { + (spec.value * availableTrackSpace).roundToInt() + } else { + // If the Grid is in a horizontally scrolling container + // (infinite width), we cannot calculate a percentage of "Infinity". + // We default to 'Auto' (MaxIntrinsic) so the content remains visible. + calculateMaxIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + } + } + + GridTrackSize.TypeFlex -> { + totalFlex += spec.value + // Flex tracks start at their 'min-content' size. + // This implements `minmax(min-content, fr)`. + // It ensures that even if there is no remaining space to distribute, + // the column is at least wide enough to show its content. + calculateMinIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + } + + GridTrackSize.TypeMinContent -> + calculateMinIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + GridTrackSize.TypeMaxContent -> + calculateMaxIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + // Auto typically behaves like MaxContent in most contexts (fit the content + // comfortably). + GridTrackSize.TypeAuto -> + calculateMaxIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + // Measure the max intrinsic width of all items in this column. + else -> calculateMaxIntrinsicWidth(itemsByColumn[index], crossAxisAvailable) + } + outSizes[index] = size + } + + // --- Pass 1.5: Spanning Items --- + // If an item spans 2 columns, and those 2 columns (base sizes) sum to 100px, but the item + // is 150px wide, we must grow the columns by 50px. + distributeSpanningSpace( + explicitSpecs = explicitSpecs, + sizes = outSizes, + gridItems = gridItems, + isRowAxis = false, + constraints = constraints, + crossAxisSizes = null, // Not needed for column width calculation + gap = columnGap, + ) + + var usedSpace = 0 + for (size in outSizes) { + usedSpace += size + } + + // --- Pass 2: Flex Distribution --- + // If we have finite width and unused space, distribute it to Flex columns. + val remainingSpace = + if (availableTrackSpace == Constraints.Infinity) 0 + else max(0, availableTrackSpace - usedSpace) + + var totalAddedFromFlex = 0 + if (totalFlex > 0 && remainingSpace > 0) { + var distributed = 0 + var accumulatedFlex = 0f + + for (index in 0 until totalCount) { + val specRaw = + if (index < explicitSpecs.size) explicitSpecs[index] + else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + if (spec.type == GridTrackSize.TypeFlex) { + accumulatedFlex += spec.value + // Distribute space proportionally based on weight. + // Uses an accumulation algorithm to avoid rounding errors summing to > + // remainingSpace. + val targetSpace = (accumulatedFlex / totalFlex * remainingSpace).roundToInt() + val share = max(0, targetSpace - distributed) + + outSizes[index] += share + distributed += share + totalAddedFromFlex = distributed + } + } + } + + return usedSpace + totalAddedFromFlex +} + +/** + * Calculates the specific pixel height of every row in the grid. + * + * This function implements the vertical axis sizing logic. Unlike columns (which are usually fixed + * or determined by parent width), row heights often depend on the *width* of the content within + * them. Therefore, this function **must** be called after [calculateColumnWidths]. + * + * **Algorithm Overview:** + * 1. **Pass 1 (Base Sizes):** Calculates the initial height of each row based on its + * [GridTrackSize]. + * * **Implicit Tracks:** Indices beyond `explicitSpecs` default to [GridTrackSize.Auto]. + * * **Auto/Content-based:** Measured using the pre-calculated `columnWidths`. This ensures text + * wraps correctly within its specific cell width. + * * **Percentage:** Resolves against total height. Falls back to `Auto` if height is infinite + * (e.g., inside a ScrollView). + * * **Flex:** Starts at `min-content` size to prevent collapse if content exists. + * 2. **Pass 1.5 (Spanning Items):** Increases row heights if an item spanning multiple rows is + * taller than the sum of those rows. + * 3. **Pass 2 (Flex Distribution):** Distributes any remaining vertical space among + * [GridTrackSize.Flex] rows according to their weight. + * + * @param density Used for Dp-to-Px conversion. + * @param explicitSpecs The user-defined row configurations. + * @param totalCount The total number of rows (explicit + implicit). + * @param availableSpace The maximum height available (or [Constraints.Infinity]). + * @param outSizes Output array where calculated heights are stored. **Mutated in-place**. + * @param itemsByRow Optimization lookup: List of items starting in each row index. + * @param constraints Parent constraints (used for max height limits). + * @param columnWidths The resolved widths of columns. **Critical** for measuring text height. + * @param gridItems All items in the grid (used for spanning logic). + * @param rowGap The spacing between rows. + * @return The total used height in pixels (sum of all row heights). + */ +private fun calculateRowHeights( + density: Density, + explicitSpecs: LongList, + totalCount: Int, + availableSpace: Int, + outSizes: IntArray, + itemsByRow: Array?>, + constraints: Constraints, + columnWidths: IntArray, + gridItems: MutableObjectList, + rowGap: Int, +): Int { + if (totalCount == 0) return 0 + + var totalFlex = 0f + // Calculate total space consumed by gaps. + // e.g., 3 columns have 2 gaps. (N-1) * gap. + val totalGapSpace = (rowGap * (totalCount - 1)).coerceAtLeast(0) + + // Calculate space available for actual tracks (Total - Gaps). + // If availableSpace is Infinity, availableTrackSpace value becomes Constraints.Infinity + val availableTrackSpace = + if (availableSpace == Constraints.Infinity) { + Constraints.Infinity + } else { + (availableSpace - totalGapSpace).coerceAtLeast(0) + } + + // --- Pass 1: Base Sizes (Single-Span Items) --- + // We iterate through every row index (both explicit and implicit). + for (index in 0 until totalCount) { + // If index exceeds explicit specs, treat it as an Implicit Auto track. + val specRaw = + if (index < explicitSpecs.size) explicitSpecs[index] + else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + val size = + when (spec.type) { + GridTrackSize.TypeFixed -> with(density) { spec.value.dp.roundToPx() } + + GridTrackSize.TypePercentage -> { + if (availableTrackSpace != Constraints.Infinity) { + (spec.value * availableTrackSpace).roundToInt() + } else { + // If the Grid is in a vertically scrolling container + // (infinite height), we cannot calculate a percentage of "Infinity". + // We default to 'Auto' (MaxIntrinsic) so the content remains visible. + calculateMaxIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + } + } + + GridTrackSize.TypeFlex -> { + totalFlex += spec.value + // Flex tracks start at their 'min-content' size. + // This implements `minmax(min-content, fr)`. + // It ensures that even if there is no remaining space to distribute, + // the row is at least tall enough to show its content. + calculateMinIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + } + + GridTrackSize.TypeMinContent -> + calculateMinIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + GridTrackSize.TypeMaxContent -> + calculateMaxIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + // Auto typically behaves like MaxContent in most contexts (fit the content + // comfortably). + GridTrackSize.TypeAuto -> + calculateMaxIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + else -> + calculateMaxIntrinsicHeight( + items = itemsByRow[index], + columnWidths = columnWidths, + fallbackWidth = constraints.maxWidth, + ) + } + outSizes[index] = size + } + + // --- Pass 1.5: Spanning Items --- + // If an item spans 2 rows, and those 2 rows (base sizes) sum to 100px, but the item + // is 150px tall, we must grow the rows by 50px. + distributeSpanningSpace( + explicitSpecs = explicitSpecs, + sizes = outSizes, + gridItems = gridItems, + isRowAxis = true, + constraints = constraints, + crossAxisSizes = columnWidths, + gap = rowGap, + ) + + var usedSpace = 0 + for (size in outSizes) { + usedSpace += size + } + + // --- Pass 2: Flex Distribution --- + // + // If we have finite height and unused space, distribute it to Flex rows. + val remainingSpace = + if (availableTrackSpace == Constraints.Infinity) 0 + else max(0, availableTrackSpace - usedSpace) + + var totalAddedFromFlex = 0 + if (totalFlex > 0 && remainingSpace > 0) { + var distributed = 0 + var accumulatedFlex = 0f + + for (index in 0 until totalCount) { + val specRaw = + if (index < explicitSpecs.size) explicitSpecs[index] + else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + if (spec.type == GridTrackSize.TypeFlex) { + accumulatedFlex += spec.value + // Distribute space proportionally based on weight. + // Uses an accumulation algorithm to avoid rounding errors summing to > + // remainingSpace. + val targetSpace = (accumulatedFlex / totalFlex * remainingSpace).roundToInt() + val share = max(0, targetSpace - distributed) + + outSizes[index] += share + distributed += share + totalAddedFromFlex = distributed + } + } + } + + return usedSpace + totalAddedFromFlex +} + +private fun calculateMaxIntrinsicWidth( + items: MutableObjectList?, + heightConstraint: Int, +): Int { + if (items == null) return 0 + var maxSize = 0 + items.forEach { item -> + if (item.columnSpan == 1) { + val size = item.measurable.maxIntrinsicWidth(heightConstraint) + if (size > maxSize) maxSize = size + } + } + return maxSize +} + +private fun calculateMinIntrinsicWidth( + items: MutableObjectList?, + heightConstraint: Int, +): Int { + if (items == null) return 0 + var maxSize = 0 + items.forEach { item -> + if (item.columnSpan == 1) { + val size = item.measurable.minIntrinsicWidth(heightConstraint) + if (size > maxSize) maxSize = size + } + } + return maxSize +} + +private fun calculateMaxIntrinsicHeight( + items: MutableObjectList?, + columnWidths: IntArray, + fallbackWidth: Int, +): Int { + if (items == null) return 0 + var maxSize = 0 + items.forEach { item -> + if (item.rowSpan == 1) { + val colIndex = item.column + val width = if (colIndex < columnWidths.size) columnWidths[colIndex] else fallbackWidth + val size = item.measurable.maxIntrinsicHeight(width) + if (size > maxSize) maxSize = size + } + } + return maxSize +} + +private fun calculateMinIntrinsicHeight( + items: MutableObjectList?, + columnWidths: IntArray, + fallbackWidth: Int, +): Int { + if (items == null) return 0 + var maxSize = 0 + items.forEach { item -> + if (item.rowSpan == 1) { + val colIndex = item.column + val width = if (colIndex < columnWidths.size) columnWidths[colIndex] else fallbackWidth + val size = item.measurable.minIntrinsicHeight(width) + if (size > maxSize) maxSize = size + } + } + return maxSize +} + +/** + * Increases the size of "growable" tracks (Auto, Flex, MinContent, MaxContent) to accommodate items + * that span across multiple tracks. + * + * This represents **Pass 1.5** of the grid sizing algorithm. It runs after base track sizes + * (Pass 1) are calculated but before flexible space (Pass 2) is distributed. + * + * **The Problem:** An item spanning 2 columns might have a minimum intrinsic width of 200px. If the + * base size of those 2 columns (plus the gap) only equals 150px, the item will be clipped or + * overlap. + * + * **The Solution (Deficit Distribution):** + * 1. Calculate the **Deficit**: `RequiredSize - (SumOfTracks + SumOfGaps)`. + * 2. Distribute this deficit evenly among the tracks involved in the span, *excluding* rigid tracks + * ([GridTrackSize.Fixed] and [GridTrackSize.Percentage]). + * + * @param explicitSpecs The user-defined track specifications. Used to determine if a track is rigid + * (Fixed/Percentage) or growable (Intrinsic). + * @param sizes The current calculated pixel sizes of the tracks. + * @param gridItems The list of all items to check for spanning requirements. + * @param isRowAxis `true` if calculating Row Heights, `false` if calculating Column Widths. + * @param constraints The parent layout constraints. + * @param crossAxisSizes The calculated sizes of the *opposite* axis (e.g., Column Widths when + * calculating Row Heights). This is crucial for correctly measuring the intrinsic height of items + * that wrap text based on specific column widths. + * @param gap The spacing between tracks. + */ +private fun distributeSpanningSpace( + explicitSpecs: LongList, + sizes: IntArray, + gridItems: MutableObjectList, + isRowAxis: Boolean, + constraints: Constraints, + crossAxisSizes: IntArray?, + gap: Int, +) { + gridItems.forEach { item -> + val trackIndex = if (isRowAxis) item.row else item.column + val span = if (isRowAxis) item.rowSpan else item.columnSpan + + // Single-span items were already handled during Base Size calculation (Pass 1). + if (span <= 1) return@forEach + + val endIndex = (trackIndex + span).coerceAtMost(sizes.size) + + // --- Step 1: Analyze current space & identifying growable tracks --- + // We sum the current size of all tracks this item spans to see if they are already big + // enough. + var currentSpannedSize = 0 + var tracksToGrowCount = 0 + + for (i in trackIndex until endIndex) { + currentSpannedSize += sizes[i] + + // Implicit tracks (indices >= specs.size) default to Auto. + val specRaw = + if (i < explicitSpecs.size) explicitSpecs[i] else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + // Fixed and Percentage tracks are considered "Rigid". They respect the user's explicit + // definition and do not expand to fit content from spanning items. + // Only Intrinsic tracks (Auto, Flex, Min/MaxContent) absorb the deficit. + if (spec.type != GridTrackSize.TypeFixed && spec.type != GridTrackSize.TypePercentage) { + tracksToGrowCount++ + } + } + + // --- Step 2: Calculate the Item's Required Size (Intrinsic Measurement) --- + // This differs based on the axis. + val requiredSize = + if (isRowAxis) { + // Case: Calculating Row Heights. + // To get the correct intrinsic height (e.g., for wrapping text), we need to know + // the exact width the item occupies. This is the sum of the columns it spans. + var itemWidth = 0 + if (crossAxisSizes != null) { + val colStart = item.column + val colEnd = (colStart + item.columnSpan).coerceAtMost(crossAxisSizes.size) + for (i in colStart until colEnd) { + itemWidth += crossAxisSizes[i] + } + // Add the gaps that are included in the span. + val spannedGaps = max(0, item.columnSpan - 1) * gap + itemWidth += spannedGaps + } else { + // If we don't know column widths, constrain only by parent max. + itemWidth = constraints.maxWidth + } + item.measurable.maxIntrinsicHeight(itemWidth) + } else { + // Case: Calculating Column Widths. + // Intrinsic width is typically calculated against infinite height (maxContent), + // or the parent's bounded height if specified. + val heightConstraint = + if (constraints.hasBoundedHeight) constraints.maxHeight + else Constraints.Infinity + item.measurable.maxIntrinsicWidth(heightConstraint) + } + + // --- Step 3: Distribute Deficit --- + val deficit = requiredSize - currentSpannedSize + + // If the item needs more space than currently available, and we have eligible tracks to + // grow, we distribute the missing pixels evenly. + if (deficit > 0 && tracksToGrowCount > 0) { + val share = deficit / tracksToGrowCount + var remainder = deficit % tracksToGrowCount + + for (i in trackIndex until endIndex) { + val specRaw = + if (i < explicitSpecs.size) explicitSpecs[i] + else GridTrackSize.Auto.encodedValue + val spec = GridTrackSize(specRaw) + + // Only add space to the "growable" tracks identified in Step 1. + if ( + spec.type != GridTrackSize.TypeFixed && + spec.type != GridTrackSize.TypePercentage + ) { + // Add the base share + 1 pixel if we still have remainder to distribute. + // This ensures (share * count) + remainder == total deficit. + val add = share + if (remainder > 0) 1 else 0 + sizes[i] += add + if (remainder > 0) remainder-- + } + } + } + } +} + +/** + * Measures the content of every grid item based on its resolved position and span. + * + * This function converts abstract grid coordinates (row/column indices) into concrete pixel + * constraints. It determines the exact width and height of the cell(s) an item spans and measures + * the child content against those bounds. + * + * This method calculates the span size in O(1) time using the pre-computed offset arrays: `Size = + * (End_Offset + End_Size) - Start_Offset` + * + * This function mutates the provided [gridItems] list, updating each item with its measured + * [Placeable] and calculated (x, y) offsets. + * + * @param gridItems The list of all grid items. + * @param trackSizes The calculated pixel sizes for every row and column track. + * @param layoutDirection The current layout direction. + */ +private fun measureItems( + gridItems: MutableObjectList, + trackSizes: GridTrackSizes, + layoutDirection: LayoutDirection, +) { + val rowCount = trackSizes.rowHeights.size + val colCount = trackSizes.columnWidths.size + + gridItems.forEach { item -> + val row = item.row + val col = item.column + + if (row < rowCount && col < colCount) { + var width = 0 + val colLimit = (col + item.columnSpan).coerceAtMost(colCount) + for (i in col until colLimit) { + width += trackSizes.columnWidths[i] + } + // Add gaps for spanned columns + val colSpanActual = colLimit - col + if (colSpanActual > 1) { + width += (colSpanActual - 1) * trackSizes.columnGapPx + } + + var height = 0 + val rowLimit = (row + item.rowSpan).coerceAtMost(rowCount) + for (i in row until rowLimit) { + height += trackSizes.rowHeights[i] + } + // Add gaps for spanned rows + val rowSpanActual = rowLimit - row + if (rowSpanActual > 1) { + height += (rowSpanActual - 1) * trackSizes.rowGapPx + } + + // Use loose constraints to allow alignment to work. + // If strict fixed constraints are used, child size == cell size, so alignment is + // ignored. + val constraints = Constraints(maxWidth = width, maxHeight = height) + val placeable = item.measurable.measure(constraints) + + // Calculate Alignment Offset + val containerSize = IntSize(width, height) + val contentSize = IntSize(placeable.width, placeable.height) + val alignmentOffset = + item.alignment.align( + size = contentSize, + space = containerSize, + layoutDirection = layoutDirection, + ) + + item.placeable = placeable + // Alignment.align already accounts for RTL (Start = right side) relative to 0,0. + item.offsetX = alignmentOffset.x + item.offsetY = alignmentOffset.y + } + } +} + +/** + * Computes the cumulative starting position (offset) for each track. + * + * This function converts a list of track sizes (e.g., column widths or row heights) into absolute + * coordinates by accumulating the size of previous tracks and the specified [gapPx] between them. + * + * Example logic: + * - Offset[0] = 0 + * - Offset[1] = Size[0] + Gap + * - Offset[2] = Size[0] + Gap + Size[1] + Gap + * + * @param sizes An array containing the size of each individual track. + * @param gapPx The spacing in pixels to insert between consecutive tracks. + * @return An [IntArray] of the same length as [sizes], where index `i` contains the starting + * coordinate of that track. + */ +private fun calculateTrackOffsets(sizes: IntArray, gapPx: Int): IntArray { + val offsets = IntArray(sizes.size) + var current = 0 + for (i in sizes.indices) { + offsets[i] = current + current += sizes[i] + gapPx + } + return offsets +} diff --git a/compose/material/material/src/androidDeviceTest/kotlin/androidx/compose/material/ExposedDropdownMenuTest.kt b/compose/material/material/src/androidDeviceTest/kotlin/androidx/compose/material/ExposedDropdownMenuTest.kt index 63817a0ce3d96..faf25c2a54af4 100644 --- a/compose/material/material/src/androidDeviceTest/kotlin/androidx/compose/material/ExposedDropdownMenuTest.kt +++ b/compose/material/material/src/androidDeviceTest/kotlin/androidx/compose/material/ExposedDropdownMenuTest.kt @@ -57,6 +57,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.MediumTest +import androidx.test.filters.SdkSuppress import androidx.test.platform.app.InstrumentationRegistry import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice @@ -109,6 +110,7 @@ class ExposedDropdownMenuTest { rule.onNodeWithTag(MenuItemTag).assertDoesNotExist() } + @SdkSuppress(maxSdkVersion = 35) // b/454429920 @Test fun expandedBehaviour_dismissesOnBackPress() { rule.setMaterialContent { diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt index bb96e91e775ac..bc3a017cb8cd7 100644 --- a/compose/material3/material3/api/current.txt +++ b/compose/material3/material3/api/current.txt @@ -3074,6 +3074,8 @@ package androidx.compose.material3 { method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void SearchBar-nbWgWpA(androidx.compose.material3.SearchBarState, kotlin.jvm.functions.Function2, androidx.compose.ui.Modifier?, androidx.compose.ui.graphics.Shape?, androidx.compose.material3.SearchBarColors?, float, float, androidx.compose.runtime.Composer?, int, int); method @KotlinOnly @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopSearchBar(androidx.compose.material3.SearchBarState state, kotlin.jvm.functions.Function0 inputField, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SearchBarColors colors, optional androidx.compose.ui.unit.Dp tonalElevation, optional androidx.compose.ui.unit.Dp shadowElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.SearchBarScrollBehavior? scrollBehavior); method @BytecodeOnly @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopSearchBar-qKj4JfE(androidx.compose.material3.SearchBarState, kotlin.jvm.functions.Function2, androidx.compose.ui.Modifier?, androidx.compose.ui.graphics.Shape?, androidx.compose.material3.SearchBarColors?, float, float, androidx.compose.foundation.layout.WindowInsets?, androidx.compose.material3.SearchBarScrollBehavior?, androidx.compose.runtime.Composer?, int, int); + method @KotlinOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberContainedSearchBarState(optional androidx.compose.material3.SearchBarValue initialValue, optional androidx.compose.animation.core.AnimationSpec animationSpecForExpand, optional androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, optional androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, optional androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); + method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberContainedSearchBarState(androidx.compose.material3.SearchBarValue?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.runtime.Composer?, int, int); method @KotlinOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberSearchBarState(optional androidx.compose.material3.SearchBarValue initialValue, optional androidx.compose.animation.core.AnimationSpec animationSpecForExpand, optional androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberSearchBarState(androidx.compose.material3.SearchBarValue?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.runtime.Composer?, int, int); } @@ -3095,6 +3097,7 @@ package androidx.compose.material3 { @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class SearchBarState { ctor public SearchBarState(androidx.compose.material3.SearchBarValue initialValue, androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); + ctor public SearchBarState(androidx.compose.material3.SearchBarValue initialValue, androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); method public suspend Object? animateToCollapsed(kotlin.coroutines.Continuation); method public suspend Object? animateToExpanded(kotlin.coroutines.Continuation); method @InaccessibleFromKotlin public androidx.compose.ui.layout.LayoutCoordinates? getCollapsedCoords(); @@ -3114,6 +3117,7 @@ package androidx.compose.material3 { @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static final class SearchBarState.Companion { method public androidx.compose.runtime.saveable.Saver Saver(androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); + method public androidx.compose.runtime.saveable.Saver Saver(androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); } @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public enum SearchBarValue { diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt index bb96e91e775ac..bc3a017cb8cd7 100644 --- a/compose/material3/material3/api/restricted_current.txt +++ b/compose/material3/material3/api/restricted_current.txt @@ -3074,6 +3074,8 @@ package androidx.compose.material3 { method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void SearchBar-nbWgWpA(androidx.compose.material3.SearchBarState, kotlin.jvm.functions.Function2, androidx.compose.ui.Modifier?, androidx.compose.ui.graphics.Shape?, androidx.compose.material3.SearchBarColors?, float, float, androidx.compose.runtime.Composer?, int, int); method @KotlinOnly @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopSearchBar(androidx.compose.material3.SearchBarState state, kotlin.jvm.functions.Function0 inputField, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.SearchBarColors colors, optional androidx.compose.ui.unit.Dp tonalElevation, optional androidx.compose.ui.unit.Dp shadowElevation, optional androidx.compose.foundation.layout.WindowInsets windowInsets, optional androidx.compose.material3.SearchBarScrollBehavior? scrollBehavior); method @BytecodeOnly @Deprecated @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void TopSearchBar-qKj4JfE(androidx.compose.material3.SearchBarState, kotlin.jvm.functions.Function2, androidx.compose.ui.Modifier?, androidx.compose.ui.graphics.Shape?, androidx.compose.material3.SearchBarColors?, float, float, androidx.compose.foundation.layout.WindowInsets?, androidx.compose.material3.SearchBarScrollBehavior?, androidx.compose.runtime.Composer?, int, int); + method @KotlinOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberContainedSearchBarState(optional androidx.compose.material3.SearchBarValue initialValue, optional androidx.compose.animation.core.AnimationSpec animationSpecForExpand, optional androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, optional androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, optional androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); + method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberContainedSearchBarState(androidx.compose.material3.SearchBarValue?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.runtime.Composer?, int, int); method @KotlinOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberSearchBarState(optional androidx.compose.material3.SearchBarValue initialValue, optional androidx.compose.animation.core.AnimationSpec animationSpecForExpand, optional androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); method @BytecodeOnly @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.SearchBarState rememberSearchBarState(androidx.compose.material3.SearchBarValue?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.animation.core.AnimationSpec?, androidx.compose.runtime.Composer?, int, int); } @@ -3095,6 +3097,7 @@ package androidx.compose.material3 { @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class SearchBarState { ctor public SearchBarState(androidx.compose.material3.SearchBarValue initialValue, androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); + ctor public SearchBarState(androidx.compose.material3.SearchBarValue initialValue, androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); method public suspend Object? animateToCollapsed(kotlin.coroutines.Continuation); method public suspend Object? animateToExpanded(kotlin.coroutines.Continuation); method @InaccessibleFromKotlin public androidx.compose.ui.layout.LayoutCoordinates? getCollapsedCoords(); @@ -3114,6 +3117,7 @@ package androidx.compose.material3 { @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static final class SearchBarState.Companion { method public androidx.compose.runtime.saveable.Saver Saver(androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse); + method public androidx.compose.runtime.saveable.Saver Saver(androidx.compose.animation.core.AnimationSpec animationSpecForExpand, androidx.compose.animation.core.AnimationSpec animationSpecForCollapse, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeIn, androidx.compose.animation.core.AnimationSpec animationSpecForContentFadeOut); } @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public enum SearchBarValue { diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt index 9455a24ddd5e5..de4ad35e8429b 100644 --- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt +++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/SearchBarSamples.kt @@ -19,6 +19,10 @@ package androidx.compose.material3.samples import androidx.annotation.Sampled +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.tween +import androidx.compose.animation.slideIn +import androidx.compose.animation.slideOut import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -46,6 +50,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults +import androidx.compose.material3.MaterialTheme.motionScheme import androidx.compose.material3.PlainTooltip import androidx.compose.material3.Scaffold import androidx.compose.material3.SearchBar @@ -56,6 +61,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TooltipAnchorPosition import androidx.compose.material3.TooltipBox import androidx.compose.material3.TooltipDefaults +import androidx.compose.material3.rememberContainedSearchBarState import androidx.compose.material3.rememberSearchBarState import androidx.compose.material3.rememberTooltipState import androidx.compose.runtime.Composable @@ -65,6 +71,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch @@ -107,7 +114,7 @@ fun SimpleSearchBarSample() { @Composable fun FullScreenSearchBarScaffoldSample() { val textFieldState = rememberTextFieldState() - val searchBarState = rememberSearchBarState() + val searchBarState = rememberContainedSearchBarState() val scope = rememberCoroutineScope() val scrollBehavior = SearchBarDefaults.enterAlwaysSearchBarScrollBehavior() val appBarWithSearchColors = @@ -137,8 +144,8 @@ fun FullScreenSearchBarScaffoldSample() { state = searchBarState, colors = appBarWithSearchColors, inputField = inputField, - navigationIcon = { SampleNavigationIcon() }, - actions = { SampleActions() }, + navigationIcon = { SampleNavigationIcon(searchBarState, isAnimated = true) }, + actions = { SampleActions(searchBarState, isAnimated = true) }, ) ExpandedFullScreenContainedSearchBar( state = searchBarState, @@ -199,8 +206,8 @@ fun DockedSearchBarScaffoldSample() { state = searchBarState, colors = appBarWithSearchColors, inputField = inputField, - navigationIcon = { SampleNavigationIcon() }, - actions = { SampleActions() }, + navigationIcon = { SampleNavigationIcon(searchBarState) }, + actions = { SampleActions(searchBarState) }, ) ExpandedDockedSearchBarWithGap(state = searchBarState, inputField = inputField) { SampleSearchResults( @@ -273,28 +280,58 @@ private fun SampleTrailingIcon() = } } +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable -private fun SampleNavigationIcon() = - TooltipBox( - positionProvider = - TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), - tooltip = { PlainTooltip { Text("Menu") } }, - state = rememberTooltipState(), +private fun SampleNavigationIcon(state: SearchBarState, isAnimated: Boolean = false) = + AnimatedVisibility( + visible = !isAnimated || state.targetValue == SearchBarValue.Collapsed, + enter = + slideIn( + animationSpec = motionScheme.fastSpatialSpec(), + initialOffset = { IntOffset(-it.width, 0) }, + ), + exit = + slideOut( + animationSpec = tween(durationMillis = 150, delayMillis = 0), + targetOffset = { IntOffset(-it.width, 0) }, + ), ) { - IconButton(onClick = { /* doSomething() */ }) { - Icon(imageVector = Icons.Default.Menu, contentDescription = "Menu") + TooltipBox( + positionProvider = + TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), + tooltip = { PlainTooltip { Text("Menu") } }, + state = rememberTooltipState(), + ) { + IconButton(onClick = { /* doSomething() */ }) { + Icon(imageVector = Icons.Default.Menu, contentDescription = "Menu") + } } } +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable -private fun SampleActions() = - TooltipBox( - positionProvider = - TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), - tooltip = { PlainTooltip { Text("Account") } }, - state = rememberTooltipState(), +private fun SampleActions(state: SearchBarState, isAnimated: Boolean = false) = + AnimatedVisibility( + visible = !isAnimated || state.targetValue == SearchBarValue.Collapsed, + enter = + slideIn( + animationSpec = motionScheme.fastSpatialSpec(), + initialOffset = { IntOffset(it.width, 0) }, + ), + exit = + slideOut( + animationSpec = tween(durationMillis = 150, delayMillis = 0), + targetOffset = { IntOffset(it.width, 0) }, + ), ) { - IconButton(onClick = { /* doSomething() */ }) { - Icon(imageVector = Icons.Default.AccountCircle, contentDescription = "Account") + TooltipBox( + positionProvider = + TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above), + tooltip = { PlainTooltip { Text("Account") } }, + state = rememberTooltipState(), + ) { + IconButton(onClick = { /* doSomething() */ }) { + Icon(imageVector = Icons.Default.AccountCircle, contentDescription = "Account") + } } } diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt index afb1565d35e76..a887023d18dad 100644 --- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt +++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SearchBar.kt @@ -32,6 +32,7 @@ import androidx.compose.animation.core.FiniteAnimationSpec import androidx.compose.animation.core.VectorConverter import androidx.compose.animation.core.animateDecay import androidx.compose.animation.core.animateTo +import androidx.compose.animation.core.snap import androidx.compose.animation.core.tween import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn @@ -137,6 +138,7 @@ import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.structuralEqualityPolicy import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.focus.FocusDirection @@ -455,7 +457,11 @@ fun AppBarWithSearch( ) } } - Box(modifier = Modifier.weight(1f)) { + val isVisible = + !state.expandsToFullScreen || + state.currentValue == SearchBarValue.Collapsed || + state.targetValue == SearchBarValue.Expanded // prevent flickering + Box(modifier = Modifier.weight(1f).alpha(if (isVisible) 1f else 0f)) { SearchBar( state = state, inputField = inputField, @@ -536,6 +542,7 @@ fun ExpandedFullScreenContainedSearchBar( properties: DialogProperties = DialogProperties(), content: @Composable ColumnScope.() -> Unit, ) { + state.expandsToFullScreen = true ExpandedFullScreenSearchBarImpl(state = state, properties = properties) { focusRequester, predictiveBackState -> @@ -557,6 +564,7 @@ fun ExpandedFullScreenContainedSearchBar( tonalElevation = tonalElevation, shadowElevation = shadowElevation, windowInsets = windowInsets(), + isContained = true, content = content, ) } @@ -603,6 +611,7 @@ fun ExpandedFullScreenSearchBar( properties: DialogProperties = DialogProperties(), content: @Composable ColumnScope.() -> Unit, ) { + state.expandsToFullScreen = true ExpandedFullScreenSearchBarImpl(state = state, properties = properties) { focusRequester, predictiveBackState -> @@ -624,6 +633,7 @@ fun ExpandedFullScreenSearchBar( tonalElevation = tonalElevation, shadowElevation = shadowElevation, windowInsets = windowInsets(), + isContained = false, content = { HorizontalDivider(color = colors.dividerColor) content() @@ -1064,9 +1074,12 @@ enum class SearchBarValue { @Stable class SearchBarState private constructor( - private val animatable: Animatable, + internal val animatable: Animatable, + private val contentAnimatable: Animatable, private val animationSpecForExpand: AnimationSpec, private val animationSpecForCollapse: AnimationSpec, + private val animationSpecForContentFadeIn: AnimationSpec, + private val animationSpecForContentFadeOut: AnimationSpec, ) { /** * Construct a [SearchBarState]. @@ -1082,10 +1095,44 @@ private constructor( ) : this( animatable = Animatable(if (initialValue == SearchBarValue.Expanded) Expanded else Collapsed), + contentAnimatable = + Animatable(if (initialValue == SearchBarValue.Expanded) Expanded else Collapsed), + animationSpecForExpand = animationSpecForExpand, + animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = snap(), + animationSpecForContentFadeOut = snap(), + ) + + /** + * Construct a [SearchBarState]. + * + * @param initialValue the initial value of whether the search bar is collapsed or expanded. + * @param animationSpecForExpand the animation spec used when the search bar expands. + * @param animationSpecForCollapse the animation spec used when the search bar collapses. + * @param animationSpecForContentFadeIn the animation spec used for the content when the search + * bar expands. + * @param animationSpecForContentFadeOut the animation spec used for the content when the search + * bar collapses. + */ + constructor( + initialValue: SearchBarValue, + animationSpecForExpand: AnimationSpec, + animationSpecForCollapse: AnimationSpec, + animationSpecForContentFadeIn: AnimationSpec, + animationSpecForContentFadeOut: AnimationSpec, + ) : this( + animatable = + Animatable(if (initialValue == SearchBarValue.Expanded) Expanded else Collapsed), + contentAnimatable = + Animatable(if (initialValue == SearchBarValue.Expanded) Expanded else Collapsed), animationSpecForExpand = animationSpecForExpand, animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = animationSpecForContentFadeIn, + animationSpecForContentFadeOut = animationSpecForContentFadeOut, ) + internal var expandsToFullScreen by mutableStateOf(false) + /** * The layout coordinates, if available, of the search bar when it is collapsed. Used to * coordinate the expansion animation. @@ -1100,6 +1147,10 @@ private constructor( val progress: Float get() = animatable.value.coerceIn(0f, 1f) + @get:FloatRange(from = 0.0, to = 1.0) + internal val contentProgress: Float + get() = contentAnimatable.value.coerceIn(0f, 1f) + /** Whether the state is currently animating */ val isAnimating: Boolean get() = animatable.isRunning @@ -1129,10 +1180,18 @@ private constructor( /** Animate the search bar to its expanded state. */ suspend fun animateToExpanded() { animatable.animateTo(targetValue = Expanded, animationSpec = animationSpecForExpand) + contentAnimatable.animateTo( + targetValue = Expanded, + animationSpec = animationSpecForContentFadeIn, + ) } /** Animate the search bar to its collapsed state. */ suspend fun animateToCollapsed() { + contentAnimatable.animateTo( + targetValue = Collapsed, + animationSpec = animationSpecForContentFadeOut, + ) animatable.animateTo(targetValue = Collapsed, animationSpec = animationSpecForCollapse) } @@ -1154,12 +1213,36 @@ private constructor( animationSpecForCollapse: AnimationSpec, ): Saver = listSaver( - save = { listOf(it.progress) }, + save = { listOf(it.progress, it.contentProgress) }, restore = { SearchBarState( animatable = Animatable(it[0], Float.VectorConverter), + contentAnimatable = Animatable(it[1], Float.VectorConverter), animationSpecForExpand = animationSpecForExpand, animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = snap(), + animationSpecForContentFadeOut = snap(), + ) + }, + ) + + /** The default [Saver] implementation for [SearchBarState]. */ + fun Saver( + animationSpecForExpand: AnimationSpec, + animationSpecForCollapse: AnimationSpec, + animationSpecForContentFadeIn: AnimationSpec, + animationSpecForContentFadeOut: AnimationSpec, + ): Saver = + listSaver( + save = { listOf(it.progress, it.contentProgress) }, + restore = { + SearchBarState( + animatable = Animatable(it[0], Float.VectorConverter), + contentAnimatable = Animatable(it[1], Float.VectorConverter), + animationSpecForExpand = animationSpecForExpand, + animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = animationSpecForContentFadeIn, + animationSpecForContentFadeOut = animationSpecForContentFadeOut, ) }, ) @@ -1198,6 +1281,52 @@ fun rememberSearchBarState( } } +/** + * Create and remember a [SearchBarState] to use in conjunction with + * [ExpandedFullScreenContainedSearchBar]. + * + * @param initialValue the initial value of whether the search bar is collapsed or expanded. + * @param animationSpecForExpand the animation spec used when the search bar expands. + * @param animationSpecForCollapse the animation spec used when the search bar collapses. + * @param animationSpecForContentFadeIn the animation spec used for the content when the search bar + * expands. + * @param animationSpecForContentFadeOut the animation spec used for the content when the search bar + * collapses. + */ +@ExperimentalMaterial3Api +@Composable +fun rememberContainedSearchBarState( + initialValue: SearchBarValue = SearchBarValue.Collapsed, + animationSpecForExpand: AnimationSpec = MotionSchemeKeyTokens.FastSpatial.value(), + animationSpecForCollapse: AnimationSpec = MotionSchemeKeyTokens.FastSpatial.value(), + animationSpecForContentFadeIn: AnimationSpec = MotionSchemeKeyTokens.SlowEffects.value(), + animationSpecForContentFadeOut: AnimationSpec = + MotionSchemeKeyTokens.DefaultEffects.value(), +): SearchBarState { + return rememberSaveable( + initialValue, + animationSpecForExpand, + animationSpecForCollapse, + animationSpecForContentFadeIn, + animationSpecForContentFadeOut, + saver = + Saver( + animationSpecForExpand = animationSpecForExpand, + animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = animationSpecForContentFadeIn, + animationSpecForContentFadeOut = animationSpecForContentFadeOut, + ), + ) { + SearchBarState( + initialValue = initialValue, + animationSpecForExpand = animationSpecForExpand, + animationSpecForCollapse = animationSpecForCollapse, + animationSpecForContentFadeIn = animationSpecForContentFadeIn, + animationSpecForContentFadeOut = animationSpecForContentFadeOut, + ) + } +} + /** * A [SearchBarScrollBehavior] defines how a search bar should behave when the content beneath it is * scrolled. @@ -1615,7 +1744,7 @@ object SearchBarDefaults { @Composable fun containedColors(state: SearchBarState): SearchBarColors { val containerColor = - if (state.targetValue == SearchBarValue.Expanded) { + if (state.currentValue == SearchBarValue.Expanded) { fullScreenContainedSearchBarColor } else { collapsedContainedSearchBarColor @@ -3147,6 +3276,7 @@ private fun FullScreenSearchBarLayout( tonalElevation: Dp, shadowElevation: Dp, windowInsets: WindowInsets, + isContained: Boolean, content: @Composable ColumnScope.() -> Unit, ) { val backEvent by remember { derivedStateOf { predictiveBackState.value } } @@ -3252,8 +3382,15 @@ private fun FullScreenSearchBarLayout( .coerceAtLeast(collapsedHeight) val endWidth = lerp(constraints.maxWidth, predictiveBackEndWidth, predictiveBackProgress) val endHeight = lerp(constraints.maxHeight, predictiveBackEndHeight, predictiveBackProgress) - val width = constraints.constrainWidth(lerp(collapsedWidth, endWidth, state.progress)) - val height = constraints.constrainHeight(lerp(collapsedHeight, endHeight, state.progress)) + val width: Int + val height: Int + if (isContained) { + width = endWidth + height = endHeight + } else { + width = constraints.constrainWidth(lerp(collapsedWidth, endWidth, state.progress)) + height = constraints.constrainHeight(lerp(collapsedHeight, endHeight, state.progress)) + } val surfaceMeasurable = measurables.fastFirst { it.layoutId == LayoutIdSurface } val surfacePlaceable = surfaceMeasurable.measure(Constraints.fixed(width, height)) @@ -3262,21 +3399,29 @@ private fun FullScreenSearchBarLayout( inputFieldPadding.calculateStartPadding(this@Layout.layoutDirection).roundToPx() val endPadding = inputFieldPadding.calculateEndPadding(this@Layout.layoutDirection).roundToPx() - val animatedStartPadding = lerp(0, startPadding, state.progress) - val animatedEndPadding = lerp(0, endPadding, state.progress) - val paddedInputFieldWidth = width - animatedStartPadding - animatedEndPadding + val paddedInputFieldWidth = + lerp(collapsedWidth, width - startPadding - endPadding, state.animatable.value) val inputFieldMeasurable = measurables.fastFirst { it.layoutId == LayoutIdInputField } val inputFieldPlaceable = inputFieldMeasurable.measure(Constraints.fixed(paddedInputFieldWidth, collapsedHeight)) - val topPadding = unconsumedInsets.getTop(this@Layout) + SearchBarVerticalPadding.roundToPx() - val bottomPadding = SearchBarVerticalPadding.roundToPx() + val topPadding = + unconsumedInsets.getTop(this@Layout) + + if (isContained) { + AppBarWithSearchVerticalPadding.roundToPx() + } else { + SearchBarVerticalPadding.roundToPx() + } val animatedTopPadding = lerp(0, topPadding, min(state.progress, 1 - predictiveBackProgress)) - val animatedBottomPadding = lerp(0, bottomPadding, state.progress) + val bottomPadding = + if (isContained) { + SearchBarVerticalPadding.roundToPx() + } else { + lerp(0, SearchBarVerticalPadding.roundToPx(), state.progress) + } - val paddedInputFieldHeight = - inputFieldPlaceable.height + animatedTopPadding + animatedBottomPadding + val paddedInputFieldHeight = inputFieldPlaceable.height + animatedTopPadding + bottomPadding val contentMeasurable = measurables.fastFirst { it.layoutId == LayoutIdSearchContent } val contentPlaceable = contentMeasurable.measure( @@ -3315,26 +3460,52 @@ private fun FullScreenSearchBarLayout( .coerceAtMost(state.collapsedBounds.top) } - val endOffsetX = + val predictiveBackOffsetX = lerp(0, lastInProgressValue.value?.endOffsetX() ?: 0, predictiveBackProgress) - val endOffsetY = + val offsetX = + if (isContained) { + predictiveBackOffsetX + } else { + lerp(state.collapsedBounds.left, predictiveBackOffsetX, state.progress) + } + val currentCenterX = + lerp( + state.collapsedBounds.center.x.toFloat(), + offsetX + width / 2f, + state.animatable.value, + ) + val offsetY = lerp(0, lastInProgressValue.value?.endOffsetY() ?: 0, predictiveBackProgress) - val offsetX = lerp(state.collapsedBounds.left, endOffsetX, state.progress) - val offsetY = lerp(state.collapsedBounds.top, endOffsetY, state.progress) + val animatedOffsetY = lerp(state.collapsedBounds.top, offsetY, state.progress) - surfacePlaceable.place(x = offsetX, y = offsetY) + surfacePlaceable.placeWithLayer( + x = offsetX, + y = if (isContained) offsetY else animatedOffsetY, + layerBlock = { + if (isContained) { + alpha = state.progress + } + }, + ) inputFieldPlaceable.place( - x = offsetX + animatedStartPadding, - y = offsetY + animatedTopPadding, + x = (currentCenterX - inputFieldPlaceable.width / 2f).roundToInt(), + y = animatedOffsetY + animatedTopPadding, ) contentPlaceable.placeWithLayer( x = offsetX, y = - offsetY + + animatedOffsetY + animatedTopPadding + inputFieldPlaceable.height + - animatedBottomPadding, - layerBlock = { alpha = state.progress }, + bottomPadding, + layerBlock = { + alpha = + if (isContained) { + state.contentProgress + } else { + state.progress + } + }, ) } } diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt index 5a6ab1692f189..40e21e032e19c 100644 --- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt +++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt @@ -1122,10 +1122,7 @@ private fun TimeInputImpl(modifier: Modifier, colors: TimePickerColors, state: T userOverride.value = true } - Row( - modifier = modifier.padding(bottom = TimeInputBottomPadding), - verticalAlignment = Alignment.Top, - ) { + Row(modifier = modifier, verticalAlignment = Alignment.Top) { val textStyle = TimeInputTokens.TimeFieldLabelTextFont.value.copy( textAlign = TextAlign.Center, @@ -2033,7 +2030,7 @@ private fun SupportingText( else TimeInputTokens.TimeFieldSupportingTextColor.value Text( - modifier = modifier.offset(y = SupportLabelTop).clearAndSetSemantics {}, + modifier = modifier.padding(top = SupportLabelTop).clearAndSetSemantics {}, text = text, color = color, minLines = 2, @@ -2285,7 +2282,6 @@ private val ClockFaceBottomMargin = 24.dp private val DisplaySeparatorWidth = 24.dp private val SupportLabelTop = 7.dp -private val TimeInputBottomPadding = 8.dp private val MaxDistance = 74.dp private val MinimumInteractiveSize = 48.dp private val Minutes = intListOf(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55) diff --git a/datastore/datastore-core/src/androidMain/baselineProfiles/baseline-prof.txt b/datastore/datastore-core/src/androidMain/baselineProfiles/baseline-prof.txt new file mode 100644 index 0000000000000..caa17e9c58c12 --- /dev/null +++ b/datastore/datastore-core/src/androidMain/baselineProfiles/baseline-prof.txt @@ -0,0 +1,437 @@ +# TODO(b/469127532): Remove this merged baseline profile once AGP adds support for multiple +# baseline profile files per baselineProfiles directory. + +HSPLandroidx/datastore/core/Api26Impl;->()V +HSPLandroidx/datastore/core/Api26Impl;->()V +HSPLandroidx/datastore/core/Api26Impl;->move(Ljava/io/File;Ljava/io/File;)Z +HSPLandroidx/datastore/core/AtomicInt;->(I)V +HSPLandroidx/datastore/core/AtomicInt;->decrementAndGet()I +HSPLandroidx/datastore/core/AtomicInt;->get()I +HSPLandroidx/datastore/core/AtomicInt;->getAndIncrement()I +HSPLandroidx/datastore/core/AtomicInt;->incrementAndGet()I +HSPLandroidx/datastore/core/Data;->(Ljava/lang/Object;II)V +HSPLandroidx/datastore/core/Data;->checkHashCode()V +HSPLandroidx/datastore/core/Data;->getValue()Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1;->(Ljava/util/List;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1;->invoke(Landroidx/datastore/core/InitializerApi;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$1;->(Landroidx/datastore/core/DataMigrationInitializer$Companion;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2;->(Ljava/util/List;Ljava/util/List;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2;->invoke(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion;->()V +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion;->access$runMigrations(Landroidx/datastore/core/DataMigrationInitializer$Companion;Ljava/util/List;Landroidx/datastore/core/InitializerApi;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion;->getInitializer(Ljava/util/List;)Lkotlin/jvm/functions/Function2; +HSPLandroidx/datastore/core/DataMigrationInitializer$Companion;->runMigrations(Ljava/util/List;Landroidx/datastore/core/InitializerApi;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataMigrationInitializer;->()V +HSPLandroidx/datastore/core/DataStoreFactory;->()V +HSPLandroidx/datastore/core/DataStoreFactory;->()V +HSPLandroidx/datastore/core/DataStoreFactory;->create(Landroidx/datastore/core/Storage;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Ljava/util/List;Lkotlinx/coroutines/CoroutineScope;)Landroidx/datastore/core/DataStore; +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda0;->(Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda1;->(Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda1;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda2;->(Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda3;->()V +HSPLandroidx/datastore/core/DataStoreImpl$Companion;->()V +HSPLandroidx/datastore/core/DataStoreImpl$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$1;->(Landroidx/datastore/core/DataStoreImpl$InitDataStore;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1$updateData$1;->(Landroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1;->(Lkotlinx/coroutines/sync/Mutex;Lkotlin/jvm/internal/Ref$BooleanRef;Lkotlin/jvm/internal/Ref$ObjectRef;Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1;->updateData(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1;->(Landroidx/datastore/core/DataStoreImpl;Landroidx/datastore/core/DataStoreImpl$InitDataStore;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore;->(Landroidx/datastore/core/DataStoreImpl;Ljava/util/List;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore;->access$getInitTasks$p(Landroidx/datastore/core/DataStoreImpl$InitDataStore;)Ljava/util/List; +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore;->access$setInitTasks$p(Landroidx/datastore/core/DataStoreImpl$InitDataStore;Ljava/util/List;)V +HSPLandroidx/datastore/core/DataStoreImpl$InitDataStore;->doRun(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$2;->(Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$2;->invoke(Landroidx/datastore/core/State;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$3;->(Landroidx/datastore/core/State;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$3;->invoke(Landroidx/datastore/core/State;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$5;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2$1;->(Landroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2;->(Lkotlinx/coroutines/flow/FlowCollector;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1;->(Lkotlinx/coroutines/flow/Flow;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$data$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$data$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$data$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->(Landroidx/datastore/core/DataStoreImpl;Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$incrementCollector$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$incrementCollector$2$1$1;->(Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/DataStoreImpl$incrementCollector$2$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$incrementCollector$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$incrementCollector$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$readAndInitOrPropagateAndThrowFailure$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$readAndInitOrPropagateAndThrowFailure$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$readDataAndUpdateCache$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$readDataOrHandleCorruption$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$readState$2;->(Landroidx/datastore/core/DataStoreImpl;ZLkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$readState$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$readState$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->(Lkotlin/jvm/functions/Function2;Landroidx/datastore/core/Data;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$updateData$2;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$updateData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$updateData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$updateData$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$updateData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeActor$3;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$writeActor$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invoke(Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeData$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$writeData$2;->(Lkotlin/jvm/internal/Ref$IntRef;Landroidx/datastore/core/DataStoreImpl;Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/DataStoreImpl$writeData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/DataStoreImpl$writeData$2;->invoke(Landroidx/datastore/core/WriteScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl$writeData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->$r8$lambda$2NKMTsGrD22twvtEszaZakafv3g(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/DataStoreImpl;->$r8$lambda$iRq06cf8rCKc8bSbBlIMwgbMVK4(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/DataStoreImpl;->()V +HSPLandroidx/datastore/core/DataStoreImpl;->(Landroidx/datastore/core/Storage;Ljava/util/List;Landroidx/datastore/core/CorruptionHandler;Lkotlinx/coroutines/CoroutineScope;)V +HSPLandroidx/datastore/core/DataStoreImpl;->access$getCoordinator(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/DataStoreImpl;->access$getInMemoryCache$p(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/DataStoreInMemoryCache; +HSPLandroidx/datastore/core/DataStoreImpl;->access$getReadAndInit$p(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/DataStoreImpl$InitDataStore; +HSPLandroidx/datastore/core/DataStoreImpl;->access$getWriteActor$p(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/SimpleActor; +HSPLandroidx/datastore/core/DataStoreImpl;->access$handleUpdate(Landroidx/datastore/core/DataStoreImpl;Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$incrementCollector(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$readAndInitOrPropagateAndThrowFailure(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$readDataAndUpdateCache(Landroidx/datastore/core/DataStoreImpl;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$readDataOrHandleCorruption(Landroidx/datastore/core/DataStoreImpl;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$readState(Landroidx/datastore/core/DataStoreImpl;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->access$transformAndWrite(Landroidx/datastore/core/DataStoreImpl;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->coordinator_delegate$lambda$0(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/DataStoreImpl;->getCoordinator()Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/DataStoreImpl;->getData()Lkotlinx/coroutines/flow/Flow; +HSPLandroidx/datastore/core/DataStoreImpl;->getStorageConnection$datastore_core()Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/DataStoreImpl;->handleUpdate(Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->incrementCollector(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->readAndInitOrPropagateAndThrowFailure(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->readDataAndUpdateCache(ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->readDataFromFileOrDefault(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->readDataOrHandleCorruption(ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->readState(ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->storageConnectionDelegate$lambda$0(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/DataStoreImpl;->transformAndWrite(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->updateData(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreImpl;->writeData$datastore_core(Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/DataStoreInMemoryCache;->()V +HSPLandroidx/datastore/core/DataStoreInMemoryCache;->getCurrentState()Landroidx/datastore/core/State; +HSPLandroidx/datastore/core/DataStoreInMemoryCache;->getFlow()Lkotlinx/coroutines/flow/Flow; +HSPLandroidx/datastore/core/DataStoreInMemoryCache;->tryUpdate(Landroidx/datastore/core/State;)Landroidx/datastore/core/State; +HSPLandroidx/datastore/core/FileMoves_androidKt;->atomicMoveTo(Ljava/io/File;Ljava/io/File;)Z +HSPLandroidx/datastore/core/FileReadScope$readData$2;->(Landroidx/datastore/core/FileReadScope;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/FileReadScope$readData$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/FileReadScope$readData$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileReadScope$readData$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileReadScope$readData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileReadScope;->(Ljava/io/File;Landroidx/datastore/core/Serializer;)V +HSPLandroidx/datastore/core/FileReadScope;->checkNotClosed()V +HSPLandroidx/datastore/core/FileReadScope;->close()V +HSPLandroidx/datastore/core/FileReadScope;->getFile()Ljava/io/File; +HSPLandroidx/datastore/core/FileReadScope;->getSerializer()Landroidx/datastore/core/Serializer; +HSPLandroidx/datastore/core/FileReadScope;->readData$suspendImpl(Landroidx/datastore/core/FileReadScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileReadScope;->readData(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileStorage$$ExternalSyntheticLambda0;->(Ljava/io/File;)V +HSPLandroidx/datastore/core/FileStorage$$ExternalSyntheticLambda1;->()V +HSPLandroidx/datastore/core/FileStorage$$ExternalSyntheticLambda1;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileStorage$Companion;->()V +HSPLandroidx/datastore/core/FileStorage$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/FileStorage;->$r8$lambda$i_CTkxVTKhfAC0UyaWMuAs7ImrQ(Ljava/io/File;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/FileStorage;->()V +HSPLandroidx/datastore/core/FileStorage;->(Landroidx/datastore/core/Serializer;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/FileStorage;->(Landroidx/datastore/core/Serializer;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/FileStorage;->_init_$lambda$0(Ljava/io/File;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/FileStorage;->createConnection()Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/FileStorageConnection$readScope$1;->(Landroidx/datastore/core/FileStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/FileStorageConnection$writeScope$1;->(Landroidx/datastore/core/FileStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/FileStorageConnection;->(Ljava/io/File;Landroidx/datastore/core/Serializer;Landroidx/datastore/core/InterProcessCoordinator;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/FileStorageConnection;->checkNotClosed()V +HSPLandroidx/datastore/core/FileStorageConnection;->createParentDirectories(Ljava/io/File;)V +HSPLandroidx/datastore/core/FileStorageConnection;->getCoordinator()Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/FileStorageConnection;->readScope(Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileStorageKt$runFileDiagnosticsIfNotCorruption$1;->(Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/FileStorageKt;->access$runFileDiagnosticsIfNotCorruption(Ljava/io/File;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileStorageKt;->runFileDiagnosticsIfNotCorruption(Ljava/io/File;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileWriteScope$writeData$2;->(Landroidx/datastore/core/FileWriteScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/FileWriteScope$writeData$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/FileWriteScope$writeData$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileWriteScope$writeData$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileWriteScope$writeData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/FileWriteScope;->(Ljava/io/File;Landroidx/datastore/core/Serializer;)V +HSPLandroidx/datastore/core/FileWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/InterProcessCoordinatorKt;->createSingleProcessCoordinator(Ljava/lang/String;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/InterProcessCoordinator_jvmKt;->createSingleProcessCoordinator(Ljava/io/File;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/Message$Update;->(Lkotlin/jvm/functions/Function2;Lkotlinx/coroutines/CompletableDeferred;Landroidx/datastore/core/State;Lkotlin/coroutines/CoroutineContext;)V +HSPLandroidx/datastore/core/Message$Update;->getAck()Lkotlinx/coroutines/CompletableDeferred; +HSPLandroidx/datastore/core/Message$Update;->getCallerContext()Lkotlin/coroutines/CoroutineContext; +HSPLandroidx/datastore/core/Message$Update;->getTransform()Lkotlin/jvm/functions/Function2; +HSPLandroidx/datastore/core/Message;->()V +HSPLandroidx/datastore/core/Message;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/NoValueDataState;->(I)V +HSPLandroidx/datastore/core/RunOnce$runIfNeeded$1;->(Landroidx/datastore/core/RunOnce;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/RunOnce$runIfNeeded$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/RunOnce;->()V +HSPLandroidx/datastore/core/RunOnce;->awaitComplete(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/RunOnce;->runIfNeeded(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SimpleActor$$ExternalSyntheticLambda0;->(Lkotlin/jvm/functions/Function1;Landroidx/datastore/core/SimpleActor;Lkotlin/jvm/functions/Function2;)V +HSPLandroidx/datastore/core/SimpleActor$offer$2;->(Landroidx/datastore/core/SimpleActor;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/SimpleActor$offer$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/SimpleActor$offer$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SimpleActor;->(Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)V +HSPLandroidx/datastore/core/SimpleActor;->access$getConsumeMessage$p(Landroidx/datastore/core/SimpleActor;)Lkotlin/jvm/functions/Function2; +HSPLandroidx/datastore/core/SimpleActor;->access$getMessageQueue$p(Landroidx/datastore/core/SimpleActor;)Lkotlinx/coroutines/channels/Channel; +HSPLandroidx/datastore/core/SimpleActor;->access$getRemainingMessages$p(Landroidx/datastore/core/SimpleActor;)Landroidx/datastore/core/AtomicInt; +HSPLandroidx/datastore/core/SimpleActor;->access$getScope$p(Landroidx/datastore/core/SimpleActor;)Lkotlinx/coroutines/CoroutineScope; +HSPLandroidx/datastore/core/SimpleActor;->offer(Ljava/lang/Object;)V +HSPLandroidx/datastore/core/SingleProcessCoordinator$lock$1;->(Landroidx/datastore/core/SingleProcessCoordinator;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/SingleProcessCoordinator$lock$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1;->(Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1;->invoke(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator;->(Ljava/lang/String;)V +HSPLandroidx/datastore/core/SingleProcessCoordinator;->getUpdateNotifications()Lkotlinx/coroutines/flow/Flow; +HSPLandroidx/datastore/core/SingleProcessCoordinator;->getVersion(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator;->incrementAndGetVersion(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/SingleProcessCoordinator;->lock(Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/State;->(I)V +HSPLandroidx/datastore/core/State;->(ILkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/State;->getVersion()I +HSPLandroidx/datastore/core/StorageConnectionKt$readData$2;->(Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/StorageConnectionKt$readData$2;->invoke(Landroidx/datastore/core/ReadScope;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/StorageConnectionKt$readData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/StorageConnectionKt$readData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/StorageConnectionKt;->readData(Landroidx/datastore/core/StorageConnection;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/UnInitialized;->()V +HSPLandroidx/datastore/core/UnInitialized;->()V +HSPLandroidx/datastore/core/UncloseableOutputStream;->(Ljava/io/FileOutputStream;)V +HSPLandroidx/datastore/core/UncloseableOutputStream;->write([BII)V +HSPLandroidx/datastore/core/UpdatingDataContextElement$Companion$Key;->()V +HSPLandroidx/datastore/core/UpdatingDataContextElement$Companion$Key;->()V +HSPLandroidx/datastore/core/UpdatingDataContextElement$Companion;->()V +HSPLandroidx/datastore/core/UpdatingDataContextElement$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/UpdatingDataContextElement;->()V +HSPLandroidx/datastore/core/UpdatingDataContextElement;->(Landroidx/datastore/core/UpdatingDataContextElement;Landroidx/datastore/core/DataStoreImpl;)V +HSPLandroidx/datastore/core/UpdatingDataContextElement;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; +HSPLandroidx/datastore/core/UpdatingDataContextElement;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element; +HSPLandroidx/datastore/core/UpdatingDataContextElement;->getKey()Lkotlin/coroutines/CoroutineContext$Key; +HSPLandroidx/datastore/core/UpdatingDataContextElement;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext; +Landroidx/datastore/core/Api26Impl; +Landroidx/datastore/core/AtomicInt; +Landroidx/datastore/core/Closeable; +Landroidx/datastore/core/CorruptionException; +Landroidx/datastore/core/CorruptionHandler; +Landroidx/datastore/core/CurrentDataProviderStore; +Landroidx/datastore/core/Data; +Landroidx/datastore/core/DataMigrationInitializer$Companion$getInitializer$1; +Landroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$1; +Landroidx/datastore/core/DataMigrationInitializer$Companion$runMigrations$2; +Landroidx/datastore/core/DataMigrationInitializer$Companion; +Landroidx/datastore/core/DataMigrationInitializer; +Landroidx/datastore/core/DataStore; +Landroidx/datastore/core/DataStoreFactory; +Landroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda0; +Landroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda1; +Landroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda2; +Landroidx/datastore/core/DataStoreImpl$$ExternalSyntheticLambda3; +Landroidx/datastore/core/DataStoreImpl$Companion; +Landroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$1; +Landroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1$updateData$1; +Landroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1$api$1; +Landroidx/datastore/core/DataStoreImpl$InitDataStore$doRun$initData$1; +Landroidx/datastore/core/DataStoreImpl$InitDataStore; +Landroidx/datastore/core/DataStoreImpl$data$1$1; +Landroidx/datastore/core/DataStoreImpl$data$1$2; +Landroidx/datastore/core/DataStoreImpl$data$1$3; +Landroidx/datastore/core/DataStoreImpl$data$1$5; +Landroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2$1; +Landroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2; +Landroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1; +Landroidx/datastore/core/DataStoreImpl$data$1; +Landroidx/datastore/core/DataStoreImpl$handleUpdate$1; +Landroidx/datastore/core/DataStoreImpl$handleUpdate$2$1; +Landroidx/datastore/core/DataStoreImpl$incrementCollector$1; +Landroidx/datastore/core/DataStoreImpl$incrementCollector$2$1$1; +Landroidx/datastore/core/DataStoreImpl$incrementCollector$2$1; +Landroidx/datastore/core/DataStoreImpl$readAndInitOrPropagateAndThrowFailure$1; +Landroidx/datastore/core/DataStoreImpl$readDataAndUpdateCache$1; +Landroidx/datastore/core/DataStoreImpl$readDataOrHandleCorruption$1; +Landroidx/datastore/core/DataStoreImpl$readState$2; +Landroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1; +Landroidx/datastore/core/DataStoreImpl$transformAndWrite$2; +Landroidx/datastore/core/DataStoreImpl$updateData$2; +Landroidx/datastore/core/DataStoreImpl$writeActor$3; +Landroidx/datastore/core/DataStoreImpl$writeData$1; +Landroidx/datastore/core/DataStoreImpl$writeData$2; +Landroidx/datastore/core/DataStoreImpl; +Landroidx/datastore/core/DataStoreInMemoryCache; +Landroidx/datastore/core/FileMoves_androidKt; +Landroidx/datastore/core/FileReadScope$readData$2; +Landroidx/datastore/core/FileReadScope; +Landroidx/datastore/core/FileStorage$$ExternalSyntheticLambda0; +Landroidx/datastore/core/FileStorage$$ExternalSyntheticLambda1; +Landroidx/datastore/core/FileStorage$Companion; +Landroidx/datastore/core/FileStorage; +Landroidx/datastore/core/FileStorageConnection$readScope$1; +Landroidx/datastore/core/FileStorageConnection$writeScope$1; +Landroidx/datastore/core/FileStorageConnection; +Landroidx/datastore/core/FileStorageKt$runFileDiagnosticsIfNotCorruption$1; +Landroidx/datastore/core/FileStorageKt; +Landroidx/datastore/core/FileWriteScope$writeData$2; +Landroidx/datastore/core/FileWriteScope; +Landroidx/datastore/core/Final; +Landroidx/datastore/core/InitializerApi; +Landroidx/datastore/core/InterProcessCoordinator; +Landroidx/datastore/core/InterProcessCoordinatorKt; +Landroidx/datastore/core/InterProcessCoordinator_jvmKt; +Landroidx/datastore/core/Message$Update; +Landroidx/datastore/core/Message; +Landroidx/datastore/core/NoValueDataState; +Landroidx/datastore/core/ReadException; +Landroidx/datastore/core/ReadScope; +Landroidx/datastore/core/RunOnce$runIfNeeded$1; +Landroidx/datastore/core/RunOnce; +Landroidx/datastore/core/Serializer; +Landroidx/datastore/core/SimpleActor$$ExternalSyntheticLambda0; +Landroidx/datastore/core/SimpleActor$offer$2; +Landroidx/datastore/core/SimpleActor; +Landroidx/datastore/core/SingleProcessCoordinator$lock$1; +Landroidx/datastore/core/SingleProcessCoordinator$updateNotifications$1; +Landroidx/datastore/core/SingleProcessCoordinator; +Landroidx/datastore/core/State; +Landroidx/datastore/core/Storage; +Landroidx/datastore/core/StorageConnection; +Landroidx/datastore/core/StorageConnectionKt$readData$2; +Landroidx/datastore/core/StorageConnectionKt; +Landroidx/datastore/core/UnInitialized; +Landroidx/datastore/core/UncloseableOutputStream; +Landroidx/datastore/core/UpdatingDataContextElement$Companion$Key; +Landroidx/datastore/core/UpdatingDataContextElement$Companion; +Landroidx/datastore/core/UpdatingDataContextElement; +Landroidx/datastore/core/WriteScope; +PLandroidx/datastore/core/Api26Impl;->()V +PLandroidx/datastore/core/Api26Impl;->()V +PLandroidx/datastore/core/Api26Impl;->move(Ljava/io/File;Ljava/io/File;)Z +PLandroidx/datastore/core/AtomicInt;->decrementAndGet()I +PLandroidx/datastore/core/AtomicInt;->getAndIncrement()I +PLandroidx/datastore/core/AtomicInt;->incrementAndGet()I +PLandroidx/datastore/core/Data;->checkHashCode()V +PLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2$1;->(Landroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$data$1$invokeSuspend$$inlined$map$1$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->(Landroidx/datastore/core/DataStoreImpl;Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$handleUpdate$2$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->(Lkotlin/jvm/functions/Function2;Landroidx/datastore/core/Data;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2$newData$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$transformAndWrite$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$updateData$2;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$updateData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$updateData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$updateData$2;->invoke(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$updateData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeActor$3;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invoke(Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeActor$3;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeData$1;->(Landroidx/datastore/core/DataStoreImpl;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$writeData$2;->(Lkotlin/jvm/internal/Ref$IntRef;Landroidx/datastore/core/DataStoreImpl;Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/DataStoreImpl$writeData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/DataStoreImpl$writeData$2;->invoke(Landroidx/datastore/core/WriteScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl$writeData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->access$getWriteActor$p(Landroidx/datastore/core/DataStoreImpl;)Landroidx/datastore/core/SimpleActor; +PLandroidx/datastore/core/DataStoreImpl;->access$handleUpdate(Landroidx/datastore/core/DataStoreImpl;Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->access$transformAndWrite(Landroidx/datastore/core/DataStoreImpl;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->handleUpdate(Landroidx/datastore/core/Message$Update;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->transformAndWrite(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->updateData(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/DataStoreImpl;->writeData$datastore_core(Ljava/lang/Object;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/FileMoves_androidKt;->atomicMoveTo(Ljava/io/File;Ljava/io/File;)Z +PLandroidx/datastore/core/FileStorageConnection$writeScope$1;->(Landroidx/datastore/core/FileStorageConnection;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/FileStorageConnection;->createParentDirectories(Ljava/io/File;)V +PLandroidx/datastore/core/FileStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/FileWriteScope$writeData$2;->(Landroidx/datastore/core/FileWriteScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/FileWriteScope$writeData$2;->create(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/FileWriteScope$writeData$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/FileWriteScope$writeData$2;->invoke(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/FileWriteScope$writeData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/FileWriteScope;->(Ljava/io/File;Landroidx/datastore/core/Serializer;)V +PLandroidx/datastore/core/FileWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/Message$Update;->(Lkotlin/jvm/functions/Function2;Lkotlinx/coroutines/CompletableDeferred;Landroidx/datastore/core/State;Lkotlin/coroutines/CoroutineContext;)V +PLandroidx/datastore/core/Message$Update;->getAck()Lkotlinx/coroutines/CompletableDeferred; +PLandroidx/datastore/core/Message$Update;->getCallerContext()Lkotlin/coroutines/CoroutineContext; +PLandroidx/datastore/core/Message$Update;->getTransform()Lkotlin/jvm/functions/Function2; +PLandroidx/datastore/core/Message;->()V +PLandroidx/datastore/core/Message;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +PLandroidx/datastore/core/NoValueDataState;->(I)V +PLandroidx/datastore/core/SimpleActor$offer$2;->(Landroidx/datastore/core/SimpleActor;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/SimpleActor$offer$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/core/SimpleActor$offer$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/SimpleActor;->access$getConsumeMessage$p(Landroidx/datastore/core/SimpleActor;)Lkotlin/jvm/functions/Function2; +PLandroidx/datastore/core/SimpleActor;->access$getMessageQueue$p(Landroidx/datastore/core/SimpleActor;)Lkotlinx/coroutines/channels/Channel; +PLandroidx/datastore/core/SimpleActor;->access$getRemainingMessages$p(Landroidx/datastore/core/SimpleActor;)Landroidx/datastore/core/AtomicInt; +PLandroidx/datastore/core/SimpleActor;->access$getScope$p(Landroidx/datastore/core/SimpleActor;)Lkotlinx/coroutines/CoroutineScope; +PLandroidx/datastore/core/SimpleActor;->offer(Ljava/lang/Object;)V +PLandroidx/datastore/core/SingleProcessCoordinator$lock$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/core/SingleProcessCoordinator;->incrementAndGetVersion(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/UncloseableOutputStream;->(Ljava/io/FileOutputStream;)V +PLandroidx/datastore/core/UncloseableOutputStream;->write([BII)V +PLandroidx/datastore/core/UpdatingDataContextElement$Companion$Key;->()V +PLandroidx/datastore/core/UpdatingDataContextElement$Companion$Key;->()V +PLandroidx/datastore/core/UpdatingDataContextElement$Companion;->()V +PLandroidx/datastore/core/UpdatingDataContextElement$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +PLandroidx/datastore/core/UpdatingDataContextElement;->()V +PLandroidx/datastore/core/UpdatingDataContextElement;->(Landroidx/datastore/core/UpdatingDataContextElement;Landroidx/datastore/core/DataStoreImpl;)V +PLandroidx/datastore/core/UpdatingDataContextElement;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; +PLandroidx/datastore/core/UpdatingDataContextElement;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element; +PLandroidx/datastore/core/UpdatingDataContextElement;->getKey()Lkotlin/coroutines/CoroutineContext$Key; +PLandroidx/datastore/core/UpdatingDataContextElement;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext; diff --git a/datastore/datastore-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt b/datastore/datastore-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt new file mode 100644 index 0000000000000..76715a02fe203 --- /dev/null +++ b/datastore/datastore-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt @@ -0,0 +1,6 @@ +# TODO(b/469127532): Remove this merged baseline profile once AGP adds support for multiple +# baseline profile files per baselineProfiles directory. + +HSPLandroidx/datastore/core/handlers/NoOpCorruptionHandler;->()V +Landroidx/datastore/core/handlers/NoOpCorruptionHandler; +Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler; diff --git a/datastore/datastore-preferences-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt b/datastore/datastore-preferences-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt new file mode 100644 index 0000000000000..9a28d32c129b1 --- /dev/null +++ b/datastore/datastore-preferences-core/src/jvmAndAndroidMain/baselineProfiles/baseline-prof.txt @@ -0,0 +1,785 @@ +# TODO(b/469127532): Remove this merged baseline profile once AGP adds support for multiple +# baseline profile files per baselineProfiles directory. + +HSPLandroidx/datastore/core/okio/AtomicBoolean;->(Z)V +HSPLandroidx/datastore/core/okio/AtomicBoolean;->get()Z +HSPLandroidx/datastore/core/okio/AtomicBoolean;->set(Z)V +HSPLandroidx/datastore/core/okio/OkioReadScope$readData$1;->(Landroidx/datastore/core/okio/OkioReadScope;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioReadScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +HSPLandroidx/datastore/core/okio/OkioReadScope;->checkClose()V +HSPLandroidx/datastore/core/okio/OkioReadScope;->close()V +HSPLandroidx/datastore/core/okio/OkioReadScope;->getFileSystem()Lokio/FileSystem; +HSPLandroidx/datastore/core/okio/OkioReadScope;->getPath()Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioReadScope;->getSerializer()Landroidx/datastore/core/okio/OkioSerializer; +HSPLandroidx/datastore/core/okio/OkioReadScope;->readData$suspendImpl(Landroidx/datastore/core/okio/OkioReadScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioReadScope;->readData(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda0;->(Landroidx/datastore/core/okio/OkioStorage;)V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1;->()V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2;->(Landroidx/datastore/core/okio/OkioStorage;)V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$Companion;->()V +HSPLandroidx/datastore/core/okio/OkioStorage$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->$r8$lambda$ngX1sQHRBFS9is12Tq2RMloe3b8(Landroidx/datastore/core/okio/OkioStorage;)Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorage;->$r8$lambda$zaSHyDobNeO3yk4Wyl_gDVAF7jA(Lokio/Path;Lokio/FileSystem;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorage;->()V +HSPLandroidx/datastore/core/okio/OkioStorage;->(Lokio/FileSystem;Landroidx/datastore/core/okio/OkioSerializer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->(Lokio/FileSystem;Landroidx/datastore/core/okio/OkioSerializer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->_init_$lambda$0(Lokio/Path;Lokio/FileSystem;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorage;->canonicalPath_delegate$lambda$0(Landroidx/datastore/core/okio/OkioStorage;)Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorage;->createConnection()Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/okio/OkioStorage;->getCanonicalPath()Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorageConnection$readScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection$writeScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;Landroidx/datastore/core/InterProcessCoordinator;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->checkNotClosed()V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->getCoordinator()Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->readScope(Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorageKt;->createSingleProcessCoordinator(Lokio/Path;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioWriteScope$writeData$1;->(Landroidx/datastore/core/okio/OkioWriteScope;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioWriteScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +HSPLandroidx/datastore/core/okio/OkioWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/Synchronizer;->()V +HSPLandroidx/datastore/preferences/PreferencesMapCompat$Companion;->()V +HSPLandroidx/datastore/preferences/PreferencesMapCompat$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/preferences/PreferencesMapCompat$Companion;->readFrom(Ljava/io/InputStream;)Landroidx/datastore/preferences/PreferencesProto$PreferenceMap; +HSPLandroidx/datastore/preferences/PreferencesMapCompat;->()V +HSPLandroidx/datastore/preferences/core/Actual_jvmAndroidKt;->immutableMap(Ljava/util/Map;)Ljava/util/Map; +HSPLandroidx/datastore/preferences/core/AtomicBoolean;->(Z)V +HSPLandroidx/datastore/preferences/core/AtomicBoolean;->get()Z +HSPLandroidx/datastore/preferences/core/AtomicBoolean;->set(Z)V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->(Ljava/util/Map;Z)V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->(Ljava/util/Map;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->asMap()Ljava/util/Map; +HSPLandroidx/datastore/preferences/core/MutablePreferences;->checkNotFrozen$datastore_preferences_core()V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->equals(Ljava/lang/Object;)Z +HSPLandroidx/datastore/preferences/core/MutablePreferences;->freeze$datastore_preferences_core()V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->get(Landroidx/datastore/preferences/core/Preferences$Key;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/MutablePreferences;->hashCode()I +HSPLandroidx/datastore/preferences/core/MutablePreferences;->putAll([Landroidx/datastore/preferences/core/Preferences$Pair;)V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->set(Landroidx/datastore/preferences/core/Preferences$Key;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/core/MutablePreferences;->setUnchecked$datastore_preferences_core(Landroidx/datastore/preferences/core/Preferences$Key;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +HSPLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invoke(Landroidx/datastore/preferences/core/Preferences;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferenceDataStore;->(Landroidx/datastore/core/DataStore;)V +HSPLandroidx/datastore/preferences/core/PreferenceDataStore;->getData()Lkotlinx/coroutines/flow/Flow; +HSPLandroidx/datastore/preferences/core/PreferenceDataStore;->updateData(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory$$ExternalSyntheticLambda0;->(Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->$r8$lambda$9BrpQzy58wyiliC4ZrxXEeAelC0(Lkotlin/jvm/functions/Function0;)Ljava/io/File; +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->()V +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->()V +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->create$lambda$0(Lkotlin/jvm/functions/Function0;)Ljava/io/File; +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->create(Landroidx/datastore/core/Storage;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Ljava/util/List;Lkotlinx/coroutines/CoroutineScope;)Landroidx/datastore/core/DataStore; +HSPLandroidx/datastore/preferences/core/PreferenceDataStoreFactory;->create(Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Ljava/util/List;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function0;)Landroidx/datastore/core/DataStore; +HSPLandroidx/datastore/preferences/core/Preferences$Key;->(Ljava/lang/String;)V +HSPLandroidx/datastore/preferences/core/Preferences$Key;->equals(Ljava/lang/Object;)Z +HSPLandroidx/datastore/preferences/core/Preferences$Key;->getName()Ljava/lang/String; +HSPLandroidx/datastore/preferences/core/Preferences$Key;->hashCode()I +HSPLandroidx/datastore/preferences/core/Preferences;->()V +HSPLandroidx/datastore/preferences/core/Preferences;->toMutablePreferences()Landroidx/datastore/preferences/core/MutablePreferences; +HSPLandroidx/datastore/preferences/core/Preferences;->toPreferences()Landroidx/datastore/preferences/core/Preferences; +HSPLandroidx/datastore/preferences/core/PreferencesFactory;->createEmpty()Landroidx/datastore/preferences/core/Preferences; +HSPLandroidx/datastore/preferences/core/PreferencesFactory;->createMutable([Landroidx/datastore/preferences/core/Preferences$Pair;)Landroidx/datastore/preferences/core/MutablePreferences; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer$WhenMappings;->()V +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->()V +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->()V +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->addProtoEntryToPreferences(Ljava/lang/String;Landroidx/datastore/preferences/PreferencesProto$Value;Landroidx/datastore/preferences/core/MutablePreferences;)V +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->getDefaultValue()Landroidx/datastore/preferences/core/Preferences; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->getDefaultValue()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->getValueProto(Ljava/lang/Object;)Landroidx/datastore/preferences/PreferencesProto$Value; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->readFrom(Ljava/io/InputStream;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->writeTo(Landroidx/datastore/preferences/core/Preferences;Ljava/io/OutputStream;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferencesFileSerializer;->writeTo(Ljava/lang/Object;Ljava/io/OutputStream;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->booleanKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->doubleKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->floatKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->intKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->longKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/core/PreferencesKeys;->stringKey(Ljava/lang/String;)Landroidx/datastore/preferences/core/Preferences$Key; +HSPLandroidx/datastore/preferences/protobuf/AbstractMessageLite$Builder;->()V +HSPLandroidx/datastore/preferences/protobuf/AbstractMessageLite;->()V +HSPLandroidx/datastore/preferences/protobuf/AbstractMessageLite;->writeTo(Ljava/io/OutputStream;)V +HSPLandroidx/datastore/preferences/protobuf/Android;->()V +HSPLandroidx/datastore/preferences/protobuf/Android;->getClassForName(Ljava/lang/String;)Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/Android;->getMemoryClass()Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/Android;->isOnAndroidDevice()Z +HSPLandroidx/datastore/preferences/protobuf/ByteOutput;->()V +HSPLandroidx/datastore/preferences/protobuf/ByteString$2;->()V +HSPLandroidx/datastore/preferences/protobuf/ByteString$LeafByteString;->()V +HSPLandroidx/datastore/preferences/protobuf/ByteString$LeafByteString;->(Landroidx/datastore/preferences/protobuf/ByteString$1;)V +HSPLandroidx/datastore/preferences/protobuf/ByteString$LiteralByteString;->([B)V +HSPLandroidx/datastore/preferences/protobuf/ByteString$SystemByteArrayCopier;->()V +HSPLandroidx/datastore/preferences/protobuf/ByteString$SystemByteArrayCopier;->(Landroidx/datastore/preferences/protobuf/ByteString$1;)V +HSPLandroidx/datastore/preferences/protobuf/ByteString;->()V +HSPLandroidx/datastore/preferences/protobuf/ByteString;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder;->([BIIZ)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder;->([BIIZLandroidx/datastore/preferences/protobuf/CodedInputStream$1;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder;->getTotalBytesRead()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder;->pushLimit(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder;->recomputeBufferSizeAfterLimit()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->(Ljava/io/InputStream;I)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->(Ljava/io/InputStream;ILandroidx/datastore/preferences/protobuf/CodedInputStream$1;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->checkLastTagWas(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->isAtEnd()Z +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->popLimit(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->pushLimit(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->read(Ljava/io/InputStream;[BII)I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readBool()Z +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readDouble()D +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readFloat()F +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readInt32()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readInt64()J +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawLittleEndian32()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawLittleEndian64()J +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawVarint32()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawVarint64()J +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readString()Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readStringRequireUtf8()Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readTag()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readUInt32()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->recomputeBufferSizeAfterLimit()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->tryRefillBuffer(I)Z +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->(Landroidx/datastore/preferences/protobuf/CodedInputStream$1;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->newInstance(Ljava/io/InputStream;)Landroidx/datastore/preferences/protobuf/CodedInputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->newInstance(Ljava/io/InputStream;I)Landroidx/datastore/preferences/protobuf/CodedInputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->newInstance([B)Landroidx/datastore/preferences/protobuf/CodedInputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->newInstance([BII)Landroidx/datastore/preferences/protobuf/CodedInputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStream;->newInstance([BIIZ)Landroidx/datastore/preferences/protobuf/CodedInputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader$1;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->(Landroidx/datastore/preferences/protobuf/CodedInputStream;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->forCodedInput(Landroidx/datastore/preferences/protobuf/CodedInputStream;)Landroidx/datastore/preferences/protobuf/CodedInputStreamReader; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->getFieldNumber()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->mergeMessageFieldInternal(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Schema;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readBool()Z +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readDouble()D +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readField(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readFloat()F +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readInt32()I +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readInt64()J +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readMap(Ljava/util/Map;Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)V +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readMessage(Landroidx/datastore/preferences/protobuf/Schema;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readMessage(Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readString()Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readStringRequireUtf8()Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->requireWireType(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferInt32NoTag(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferTag(II)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferUInt32NoTag(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->(Ljava/io/OutputStream;I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->doFlush()V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->flush()V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->flushIfNotAvailable(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->write([BII)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeInt32(II)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeLazy([BII)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeMessageNoTag(Landroidx/datastore/preferences/protobuf/MessageLite;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeString(ILjava/lang/String;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeStringNoTag(Ljava/lang/String;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeTag(II)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeUInt32NoTag(I)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->()V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->(Landroidx/datastore/preferences/protobuf/CodedOutputStream$1;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->access$100()Z +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt32Size(II)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt32SizeNoTag(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeLengthDelimitedFieldSize(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeMessageSizeNoTag(Landroidx/datastore/preferences/protobuf/MessageLite;)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computePreferredBufferSize(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeStringSize(ILjava/lang/String;)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeStringSizeNoTag(Ljava/lang/String;)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeTagSize(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeUInt32SizeNoTag(I)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeUInt64SizeNoTag(J)I +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->isSerializationDeterministic()Z +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStream;->newInstance(Ljava/io/OutputStream;I)Landroidx/datastore/preferences/protobuf/CodedOutputStream; +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->fieldOrder()Landroidx/datastore/preferences/protobuf/Writer$FieldOrder; +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->forCodedOutput(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)Landroidx/datastore/preferences/protobuf/CodedOutputStreamWriter; +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeInt32(II)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeMap(ILandroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/util/Map;)V +HSPLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeString(ILjava/lang/String;)V +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryFactory;->()V +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryFactory;->createEmpty()Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite; +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryFactory;->invokeSubclassFactory(Ljava/lang/String;)Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite; +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryFactory;->reflectExtensionRegistry()Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryLite;->()V +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryLite;->(Z)V +HSPLandroidx/datastore/preferences/protobuf/ExtensionRegistryLite;->getEmptyRegistry()Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite; +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchema;->()V +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchemaLite;->()V +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchemaLite;->hasExtensions(Landroidx/datastore/preferences/protobuf/MessageLite;)Z +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchemas;->()V +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchemas;->lite()Landroidx/datastore/preferences/protobuf/ExtensionSchema; +HSPLandroidx/datastore/preferences/protobuf/ExtensionSchemas;->loadSchemaForFullRuntime()Landroidx/datastore/preferences/protobuf/ExtensionSchema; +HSPLandroidx/datastore/preferences/protobuf/FieldSet$1;->()V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->()V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->(Landroidx/datastore/preferences/protobuf/SmallSortedMap;)V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->(Z)V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->computeElementSize(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;ILjava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->computeElementSizeNoTag(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->getWireFormatForFieldType(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Z)I +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->writeElement(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;ILjava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/FieldSet;->writeElementNoTag(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/FieldType$1;->()V +HSPLandroidx/datastore/preferences/protobuf/FieldType$Collection;->()V +HSPLandroidx/datastore/preferences/protobuf/FieldType$Collection;->(Ljava/lang/String;IZ)V +HSPLandroidx/datastore/preferences/protobuf/FieldType$Collection;->values()[Landroidx/datastore/preferences/protobuf/FieldType$Collection; +HSPLandroidx/datastore/preferences/protobuf/FieldType;->()V +HSPLandroidx/datastore/preferences/protobuf/FieldType;->(Ljava/lang/String;IILandroidx/datastore/preferences/protobuf/FieldType$Collection;Landroidx/datastore/preferences/protobuf/JavaType;)V +HSPLandroidx/datastore/preferences/protobuf/FieldType;->id()I +HSPLandroidx/datastore/preferences/protobuf/FieldType;->values()[Landroidx/datastore/preferences/protobuf/FieldType; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory;->()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory;->()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory;->getInstance()Landroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory;->isSupported(Ljava/lang/Class;)Z +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory;->messageInfoFor(Ljava/lang/Class;)Landroidx/datastore/preferences/protobuf/MessageInfo; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;)V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->build()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->buildPartial()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->copyOnWrite()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->newMutableInstance()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;->()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;->(Ljava/lang/String;I)V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;->values()[Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->buildMessageInfo()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->checkMessageInitialized(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;)Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->clearMemoizedHashCode()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->clearMemoizedSerializedSize()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->computeSerializedSize(Landroidx/datastore/preferences/protobuf/Schema;)I +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->createBuilder()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->dynamicMethod(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getDefaultInstance(Ljava/lang/Class;)Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getMemoizedSerializedSize()I +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getSerializedSize()I +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getSerializedSize(Landroidx/datastore/preferences/protobuf/Schema;)I +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->isInitialized()Z +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->isInitialized(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;Z)Z +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->isMutable()Z +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->markImmutable()V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->newMessageInfo(Landroidx/datastore/preferences/protobuf/MessageLite;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->newMutableInstance()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->parseFrom(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;Ljava/io/InputStream;)Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->parsePartialFrom(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;Landroidx/datastore/preferences/protobuf/CodedInputStream;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->registerDefaultInstance(Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;)V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->setMemoizedSerializedSize(I)V +HSPLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->writeTo(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)V +HSPLandroidx/datastore/preferences/protobuf/Internal;->()V +HSPLandroidx/datastore/preferences/protobuf/Internal;->checkNotNull(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/Internal;->checkNotNull(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/JavaType;->()V +HSPLandroidx/datastore/preferences/protobuf/JavaType;->(Ljava/lang/String;ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/JavaType;->getBoxedType()Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/JavaType;->values()[Landroidx/datastore/preferences/protobuf/JavaType; +HSPLandroidx/datastore/preferences/protobuf/ListFieldSchemaLite;->()V +HSPLandroidx/datastore/preferences/protobuf/ListFieldSchemas;->()V +HSPLandroidx/datastore/preferences/protobuf/ListFieldSchemas;->lite()Landroidx/datastore/preferences/protobuf/ListFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/ListFieldSchemas;->loadSchemaForFullRuntime()Landroidx/datastore/preferences/protobuf/ListFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory$1;->()V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory$2;->()V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory$CompositeMessageInfoFactory;->([Landroidx/datastore/preferences/protobuf/MessageInfoFactory;)V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory$CompositeMessageInfoFactory;->messageInfoFor(Ljava/lang/Class;)Landroidx/datastore/preferences/protobuf/MessageInfo; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->()V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->()V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->(Landroidx/datastore/preferences/protobuf/MessageInfoFactory;)V +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->allowExtensions(Landroidx/datastore/preferences/protobuf/MessageInfo;)Z +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->createSchema(Ljava/lang/Class;)Landroidx/datastore/preferences/protobuf/Schema; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->getDefaultMessageInfoFactory()Landroidx/datastore/preferences/protobuf/MessageInfoFactory; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->getDescriptorMessageInfoFactory()Landroidx/datastore/preferences/protobuf/MessageInfoFactory; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->newSchema(Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/MessageInfo;)Landroidx/datastore/preferences/protobuf/Schema; +HSPLandroidx/datastore/preferences/protobuf/ManifestSchemaFactory;->useLiteRuntime(Ljava/lang/Class;)Z +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;->(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->computeMessageSize(ILjava/lang/Object;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->computeSerializedSize(Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/lang/Object;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->getMetadata()Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata; +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->newDefaultInstance(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)Landroidx/datastore/preferences/protobuf/MapEntryLite; +HSPLandroidx/datastore/preferences/protobuf/MapEntryLite;->writeTo(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/lang/Object;Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->emptyMapField()Landroidx/datastore/preferences/protobuf/MapFieldLite; +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->ensureMutable()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->entrySet()Ljava/util/Set; +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->isMutable()Z +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->mutableCopy()Landroidx/datastore/preferences/protobuf/MapFieldLite; +HSPLandroidx/datastore/preferences/protobuf/MapFieldLite;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->forMapData(Ljava/lang/Object;)Ljava/util/Map; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->forMapMetadata(Ljava/lang/Object;)Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->forMutableMapData(Ljava/lang/Object;)Ljava/util/Map; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->getSerializedSize(ILjava/lang/Object;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->getSerializedSizeLite(ILjava/lang/Object;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->isImmutable(Ljava/lang/Object;)Z +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->mergeFrom(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->mergeFromLite(Ljava/lang/Object;Ljava/lang/Object;)Landroidx/datastore/preferences/protobuf/MapFieldLite; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->newMapField(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->toImmutable(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemas;->()V +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemas;->lite()Landroidx/datastore/preferences/protobuf/MapFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/MapFieldSchemas;->loadSchemaForFullRuntime()Landroidx/datastore/preferences/protobuf/MapFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->()V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->([I[Ljava/lang/Object;IILandroidx/datastore/preferences/protobuf/MessageLite;Landroidx/datastore/preferences/protobuf/ProtoSyntax;Z[IIILandroidx/datastore/preferences/protobuf/NewInstanceSchema;Landroidx/datastore/preferences/protobuf/ListFieldSchema;Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Landroidx/datastore/preferences/protobuf/ExtensionSchema;Landroidx/datastore/preferences/protobuf/MapFieldSchema;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->checkMutable(Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->filterMapUnknownEnumValues(Ljava/lang/Object;ILjava/lang/Object;Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->getEnumFieldVerifier(I)Landroidx/datastore/preferences/protobuf/Internal$EnumVerifier; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->getMapFieldDefaultEntry(I)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->getSerializedSize(Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->getUnknownFieldsSerializedSize(Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->isEnforceUtf8(I)Z +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->isMutable(Ljava/lang/Object;)Z +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->isOneofPresent(Ljava/lang/Object;II)Z +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->makeImmutable(Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->mergeFrom(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Reader;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->mergeFromHelper(Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Landroidx/datastore/preferences/protobuf/ExtensionSchema;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Reader;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->mergeMap(Ljava/lang/Object;ILjava/lang/Object;Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite;Landroidx/datastore/preferences/protobuf/Reader;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->newInstance()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->newSchema(Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/MessageInfo;Landroidx/datastore/preferences/protobuf/NewInstanceSchema;Landroidx/datastore/preferences/protobuf/ListFieldSchema;Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Landroidx/datastore/preferences/protobuf/ExtensionSchema;Landroidx/datastore/preferences/protobuf/MapFieldSchema;)Landroidx/datastore/preferences/protobuf/MessageSchema; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->newSchemaForRawMessageInfo(Landroidx/datastore/preferences/protobuf/RawMessageInfo;Landroidx/datastore/preferences/protobuf/NewInstanceSchema;Landroidx/datastore/preferences/protobuf/ListFieldSchema;Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Landroidx/datastore/preferences/protobuf/ExtensionSchema;Landroidx/datastore/preferences/protobuf/MapFieldSchema;)Landroidx/datastore/preferences/protobuf/MessageSchema; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->numberAt(I)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->offset(I)J +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofIntAt(Ljava/lang/Object;J)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->positionForFieldNumber(I)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->presenceMaskAndOffsetAt(I)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->readString(Ljava/lang/Object;ILandroidx/datastore/preferences/protobuf/Reader;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->reflectField(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field; +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->setOneofPresent(Ljava/lang/Object;II)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->slowPositionForFieldNumber(II)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->type(I)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->typeAndOffsetAt(I)I +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->writeFieldsInAscendingOrder(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->writeMapHelper(Landroidx/datastore/preferences/protobuf/Writer;ILjava/lang/Object;I)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->writeString(ILjava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->writeTo(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/MessageSchema;->writeUnknownInMessageTo(Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/NewInstanceSchemaLite;->()V +HSPLandroidx/datastore/preferences/protobuf/NewInstanceSchemaLite;->newInstance(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/NewInstanceSchemas;->()V +HSPLandroidx/datastore/preferences/protobuf/NewInstanceSchemas;->lite()Landroidx/datastore/preferences/protobuf/NewInstanceSchema; +HSPLandroidx/datastore/preferences/protobuf/NewInstanceSchemas;->loadSchemaForFullRuntime()Landroidx/datastore/preferences/protobuf/NewInstanceSchema; +HSPLandroidx/datastore/preferences/protobuf/ProtoSyntax;->()V +HSPLandroidx/datastore/preferences/protobuf/ProtoSyntax;->(Ljava/lang/String;I)V +HSPLandroidx/datastore/preferences/protobuf/ProtoSyntax;->values()[Landroidx/datastore/preferences/protobuf/ProtoSyntax; +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->()V +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->()V +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->getInstance()Landroidx/datastore/preferences/protobuf/Protobuf; +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->registerSchema(Ljava/lang/Class;Landroidx/datastore/preferences/protobuf/Schema;)Landroidx/datastore/preferences/protobuf/Schema; +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->schemaFor(Ljava/lang/Class;)Landroidx/datastore/preferences/protobuf/Schema; +HSPLandroidx/datastore/preferences/protobuf/Protobuf;->schemaFor(Ljava/lang/Object;)Landroidx/datastore/preferences/protobuf/Schema; +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->(Landroidx/datastore/preferences/protobuf/MessageLite;Ljava/lang/String;[Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->getDefaultInstance()Landroidx/datastore/preferences/protobuf/MessageLite; +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->getObjects()[Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->getStringInfo()Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->getSyntax()Landroidx/datastore/preferences/protobuf/ProtoSyntax; +HSPLandroidx/datastore/preferences/protobuf/RawMessageInfo;->isMessageSetWireFormat()Z +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->()V +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->getGeneratedMessageClass()Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->getUnknownFieldSetSchema()Landroidx/datastore/preferences/protobuf/UnknownFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->getUnknownFieldSetSchemaClass()Ljava/lang/Class; +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->requireGeneratedMessage(Ljava/lang/Class;)V +HSPLandroidx/datastore/preferences/protobuf/SchemaUtil;->unknownFieldSetLiteSchema()Landroidx/datastore/preferences/protobuf/UnknownFieldSchema; +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap$1;->()V +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap$1;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->()V +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->(Landroidx/datastore/preferences/protobuf/SmallSortedMap$1;)V +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->getNumArrayEntries()I +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->getOverflowEntries()Ljava/lang/Iterable; +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->isImmutable()Z +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/SmallSortedMap;->newFieldMap()Landroidx/datastore/preferences/protobuf/SmallSortedMap; +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSchema;->()V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSchema;->()V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->()V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->(I[I[Ljava/lang/Object;Z)V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->getDefaultInstance()Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite; +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->getSerializedSize()I +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->makeImmutable()V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->writeTo(Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->()V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getFromMessage(Ljava/lang/Object;)Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite; +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getFromMessage(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getSerializedSize(Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite;)I +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getSerializedSize(Ljava/lang/Object;)I +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->makeImmutable(Ljava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->writeTo(Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->writeTo(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$1;->()V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$1;->run()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$1;->run()Lsun/misc/Unsafe; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$Android64MemoryAccessor;->(Lsun/misc/Unsafe;)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$Android64MemoryAccessor;->putByte(Ljava/lang/Object;JB)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$Android64MemoryAccessor;->supportsUnsafeByteBufferOperations()Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->(Lsun/misc/Unsafe;)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->arrayBaseOffset(Ljava/lang/Class;)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->arrayIndexScale(Ljava/lang/Class;)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->getInt(Ljava/lang/Object;J)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->objectFieldOffset(Ljava/lang/reflect/Field;)J +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->putInt(Ljava/lang/Object;JI)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor;->supportsUnsafeArrayOperations()Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->()V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->access$500(Ljava/lang/Object;JB)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->arrayBaseOffset(Ljava/lang/Class;)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->arrayIndexScale(Ljava/lang/Class;)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->bufferAddressField()Ljava/lang/reflect/Field; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->determineAndroidSupportByAddressSize(Ljava/lang/Class;)Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->field(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Field; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->fieldOffset(Ljava/lang/reflect/Field;)J +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->getInt(Ljava/lang/Object;J)I +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->getMemoryAccessor()Landroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->getObject(Ljava/lang/Object;J)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->getUnsafe()Lsun/misc/Unsafe; +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->hasUnsafeArrayOperations()Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->hasUnsafeByteBufferOperations()Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putByte([BJB)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putByteLittleEndian(Ljava/lang/Object;JB)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putInt(Ljava/lang/Object;JI)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putObject(Ljava/lang/Object;JLjava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->supportsUnsafeArrayOperations()Z +HSPLandroidx/datastore/preferences/protobuf/UnsafeUtil;->supportsUnsafeByteBufferOperations()Z +HSPLandroidx/datastore/preferences/protobuf/Utf8$DecodeUtil;->access$400(B)Z +HSPLandroidx/datastore/preferences/protobuf/Utf8$DecodeUtil;->access$500(B[CI)V +HSPLandroidx/datastore/preferences/protobuf/Utf8$DecodeUtil;->handleOneByte(B[CI)V +HSPLandroidx/datastore/preferences/protobuf/Utf8$DecodeUtil;->isOneByte(B)Z +HSPLandroidx/datastore/preferences/protobuf/Utf8$Processor;->()V +HSPLandroidx/datastore/preferences/protobuf/Utf8$SafeProcessor;->()V +HSPLandroidx/datastore/preferences/protobuf/Utf8$SafeProcessor;->decodeUtf8([BII)Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/Utf8$SafeProcessor;->encodeUtf8(Ljava/lang/String;[BII)I +HSPLandroidx/datastore/preferences/protobuf/Utf8$UnsafeProcessor;->isAvailable()Z +HSPLandroidx/datastore/preferences/protobuf/Utf8;->()V +HSPLandroidx/datastore/preferences/protobuf/Utf8;->decodeUtf8([BII)Ljava/lang/String; +HSPLandroidx/datastore/preferences/protobuf/Utf8;->encode(Ljava/lang/String;[BII)I +HSPLandroidx/datastore/preferences/protobuf/Utf8;->encodedLength(Ljava/lang/String;)I +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType$1;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;I)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType$2;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;I)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType$3;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;I)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType$4;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;I)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->()V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;I)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->(Ljava/lang/String;ILandroidx/datastore/preferences/protobuf/WireFormat$JavaType;ILandroidx/datastore/preferences/protobuf/WireFormat$1;)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->getWireType()I +HSPLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->values()[Landroidx/datastore/preferences/protobuf/WireFormat$FieldType; +HSPLandroidx/datastore/preferences/protobuf/WireFormat$JavaType;->()V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$JavaType;->(Ljava/lang/String;ILjava/lang/Object;)V +HSPLandroidx/datastore/preferences/protobuf/WireFormat$JavaType;->values()[Landroidx/datastore/preferences/protobuf/WireFormat$JavaType; +HSPLandroidx/datastore/preferences/protobuf/WireFormat;->()V +HSPLandroidx/datastore/preferences/protobuf/WireFormat;->getTagFieldNumber(I)I +HSPLandroidx/datastore/preferences/protobuf/WireFormat;->getTagWireType(I)I +HSPLandroidx/datastore/preferences/protobuf/WireFormat;->makeTag(II)I +HSPLandroidx/datastore/preferences/protobuf/Writer$FieldOrder;->()V +HSPLandroidx/datastore/preferences/protobuf/Writer$FieldOrder;->(Ljava/lang/String;I)V +Landroidx/datastore/core/okio/AtomicBoolean; +Landroidx/datastore/core/okio/OkioReadScope$readData$1; +Landroidx/datastore/core/okio/OkioReadScope; +Landroidx/datastore/core/okio/OkioSerializer; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda0; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2; +Landroidx/datastore/core/okio/OkioStorage$Companion; +Landroidx/datastore/core/okio/OkioStorage; +Landroidx/datastore/core/okio/OkioStorageConnection$readScope$1; +Landroidx/datastore/core/okio/OkioStorageConnection$writeScope$1; +Landroidx/datastore/core/okio/OkioStorageConnection; +Landroidx/datastore/core/okio/OkioStorageKt; +Landroidx/datastore/core/okio/OkioWriteScope$writeData$1; +Landroidx/datastore/core/okio/OkioWriteScope; +Landroidx/datastore/core/okio/Synchronizer; +Landroidx/datastore/preferences/PreferencesMapCompat$Companion; +Landroidx/datastore/preferences/PreferencesMapCompat; +Landroidx/datastore/preferences/core/Actual_jvmAndroidKt; +Landroidx/datastore/preferences/core/AtomicBoolean; +Landroidx/datastore/preferences/core/MutablePreferences; +Landroidx/datastore/preferences/core/PreferenceDataStore$updateData$2; +Landroidx/datastore/preferences/core/PreferenceDataStore; +Landroidx/datastore/preferences/core/PreferenceDataStoreFactory$$ExternalSyntheticLambda0; +Landroidx/datastore/preferences/core/PreferenceDataStoreFactory; +Landroidx/datastore/preferences/core/Preferences$Key; +Landroidx/datastore/preferences/core/Preferences$Pair; +Landroidx/datastore/preferences/core/Preferences; +Landroidx/datastore/preferences/core/PreferencesFactory; +Landroidx/datastore/preferences/core/PreferencesFileSerializer$WhenMappings; +Landroidx/datastore/preferences/core/PreferencesFileSerializer; +Landroidx/datastore/preferences/core/PreferencesKeys; +Landroidx/datastore/preferences/protobuf/AbstractMessageLite$Builder; +Landroidx/datastore/preferences/protobuf/AbstractMessageLite; +Landroidx/datastore/preferences/protobuf/Android; +Landroidx/datastore/preferences/protobuf/ByteOutput; +Landroidx/datastore/preferences/protobuf/ByteString$2; +Landroidx/datastore/preferences/protobuf/ByteString$ByteArrayCopier; +Landroidx/datastore/preferences/protobuf/ByteString$LeafByteString; +Landroidx/datastore/preferences/protobuf/ByteString$LiteralByteString; +Landroidx/datastore/preferences/protobuf/ByteString$SystemByteArrayCopier; +Landroidx/datastore/preferences/protobuf/ByteString; +Landroidx/datastore/preferences/protobuf/CodedInputStream$ArrayDecoder; +Landroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder$RefillCallback; +Landroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder; +Landroidx/datastore/preferences/protobuf/CodedInputStream; +Landroidx/datastore/preferences/protobuf/CodedInputStreamReader$1; +Landroidx/datastore/preferences/protobuf/CodedInputStreamReader; +Landroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder; +Landroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder; +Landroidx/datastore/preferences/protobuf/CodedOutputStream; +Landroidx/datastore/preferences/protobuf/CodedOutputStreamWriter; +Landroidx/datastore/preferences/protobuf/ExtensionRegistryFactory; +Landroidx/datastore/preferences/protobuf/ExtensionRegistryLite; +Landroidx/datastore/preferences/protobuf/ExtensionSchema; +Landroidx/datastore/preferences/protobuf/ExtensionSchemaLite; +Landroidx/datastore/preferences/protobuf/ExtensionSchemas; +Landroidx/datastore/preferences/protobuf/FieldSet$1; +Landroidx/datastore/preferences/protobuf/FieldSet; +Landroidx/datastore/preferences/protobuf/FieldType$1; +Landroidx/datastore/preferences/protobuf/FieldType$Collection; +Landroidx/datastore/preferences/protobuf/FieldType; +Landroidx/datastore/preferences/protobuf/GeneratedMessageInfoFactory; +Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder; +Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$ExtendableMessage; +Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$ExtendableMessageOrBuilder; +Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke; +Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +Landroidx/datastore/preferences/protobuf/Internal$EnumVerifier; +Landroidx/datastore/preferences/protobuf/Internal; +Landroidx/datastore/preferences/protobuf/InvalidProtocolBufferException$InvalidWireTypeException; +Landroidx/datastore/preferences/protobuf/InvalidProtocolBufferException; +Landroidx/datastore/preferences/protobuf/JavaType; +Landroidx/datastore/preferences/protobuf/LazyField; +Landroidx/datastore/preferences/protobuf/LazyFieldLite; +Landroidx/datastore/preferences/protobuf/ListFieldSchema; +Landroidx/datastore/preferences/protobuf/ListFieldSchemaLite; +Landroidx/datastore/preferences/protobuf/ListFieldSchemas; +Landroidx/datastore/preferences/protobuf/ManifestSchemaFactory$1; +Landroidx/datastore/preferences/protobuf/ManifestSchemaFactory$2; +Landroidx/datastore/preferences/protobuf/ManifestSchemaFactory$CompositeMessageInfoFactory; +Landroidx/datastore/preferences/protobuf/ManifestSchemaFactory; +Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata; +Landroidx/datastore/preferences/protobuf/MapEntryLite; +Landroidx/datastore/preferences/protobuf/MapFieldLite; +Landroidx/datastore/preferences/protobuf/MapFieldSchema; +Landroidx/datastore/preferences/protobuf/MapFieldSchemaLite; +Landroidx/datastore/preferences/protobuf/MapFieldSchemas; +Landroidx/datastore/preferences/protobuf/MessageInfo; +Landroidx/datastore/preferences/protobuf/MessageInfoFactory; +Landroidx/datastore/preferences/protobuf/MessageLite$Builder; +Landroidx/datastore/preferences/protobuf/MessageLite; +Landroidx/datastore/preferences/protobuf/MessageLiteOrBuilder; +Landroidx/datastore/preferences/protobuf/MessageSchema; +Landroidx/datastore/preferences/protobuf/NewInstanceSchema; +Landroidx/datastore/preferences/protobuf/NewInstanceSchemaLite; +Landroidx/datastore/preferences/protobuf/NewInstanceSchemas; +Landroidx/datastore/preferences/protobuf/ProtoSyntax; +Landroidx/datastore/preferences/protobuf/Protobuf; +Landroidx/datastore/preferences/protobuf/RawMessageInfo; +Landroidx/datastore/preferences/protobuf/Reader; +Landroidx/datastore/preferences/protobuf/Schema; +Landroidx/datastore/preferences/protobuf/SchemaFactory; +Landroidx/datastore/preferences/protobuf/SchemaUtil; +Landroidx/datastore/preferences/protobuf/SmallSortedMap$1; +Landroidx/datastore/preferences/protobuf/SmallSortedMap; +Landroidx/datastore/preferences/protobuf/UninitializedMessageException; +Landroidx/datastore/preferences/protobuf/UnknownFieldSchema; +Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite; +Landroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema; +Landroidx/datastore/preferences/protobuf/UnsafeUtil$1; +Landroidx/datastore/preferences/protobuf/UnsafeUtil$Android64MemoryAccessor; +Landroidx/datastore/preferences/protobuf/UnsafeUtil$MemoryAccessor; +Landroidx/datastore/preferences/protobuf/UnsafeUtil; +Landroidx/datastore/preferences/protobuf/Utf8$DecodeUtil; +Landroidx/datastore/preferences/protobuf/Utf8$Processor; +Landroidx/datastore/preferences/protobuf/Utf8$SafeProcessor; +Landroidx/datastore/preferences/protobuf/Utf8$UnpairedSurrogateException; +Landroidx/datastore/preferences/protobuf/Utf8$UnsafeProcessor; +Landroidx/datastore/preferences/protobuf/Utf8; +Landroidx/datastore/preferences/protobuf/WireFormat$FieldType$1; +Landroidx/datastore/preferences/protobuf/WireFormat$FieldType$2; +Landroidx/datastore/preferences/protobuf/WireFormat$FieldType$3; +Landroidx/datastore/preferences/protobuf/WireFormat$FieldType$4; +Landroidx/datastore/preferences/protobuf/WireFormat$FieldType; +Landroidx/datastore/preferences/protobuf/WireFormat$JavaType; +Landroidx/datastore/preferences/protobuf/WireFormat; +Landroidx/datastore/preferences/protobuf/Writer$FieldOrder; +Landroidx/datastore/preferences/protobuf/Writer; +PLandroidx/datastore/core/okio/OkioReadScope;->getFileSystem()Lokio/FileSystem; +PLandroidx/datastore/core/okio/OkioReadScope;->getPath()Lokio/Path; +PLandroidx/datastore/core/okio/OkioReadScope;->getSerializer()Landroidx/datastore/core/okio/OkioSerializer; +PLandroidx/datastore/core/okio/OkioStorageConnection$writeScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/okio/OkioStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/okio/OkioWriteScope$writeData$1;->(Landroidx/datastore/core/okio/OkioWriteScope;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/okio/OkioWriteScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +PLandroidx/datastore/core/okio/OkioWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/AtomicBoolean;->set(Z)V +PLandroidx/datastore/preferences/core/MutablePreferences;->freeze$datastore_preferences_core()V +PLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->create(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation; +PLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invoke(Landroidx/datastore/preferences/core/Preferences;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/PreferenceDataStore$updateData$2;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/PreferenceDataStore;->updateData(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/Preferences$Key;->getName()Ljava/lang/String; +PLandroidx/datastore/preferences/core/Preferences;->toMutablePreferences()Landroidx/datastore/preferences/core/MutablePreferences; +PLandroidx/datastore/preferences/core/PreferencesFileSerializer;->getValueProto(Ljava/lang/Object;)Landroidx/datastore/preferences/PreferencesProto$Value; +PLandroidx/datastore/preferences/core/PreferencesFileSerializer;->writeTo(Landroidx/datastore/preferences/core/Preferences;Ljava/io/OutputStream;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/preferences/core/PreferencesFileSerializer;->writeTo(Ljava/lang/Object;Ljava/io/OutputStream;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/preferences/protobuf/AbstractMessageLite$Builder;->()V +PLandroidx/datastore/preferences/protobuf/AbstractMessageLite;->writeTo(Ljava/io/OutputStream;)V +PLandroidx/datastore/preferences/protobuf/ByteOutput;->()V +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readDouble()D +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readFloat()F +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readInt32()I +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readInt64()J +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawLittleEndian32()I +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawLittleEndian64()J +PLandroidx/datastore/preferences/protobuf/CodedInputStream$StreamDecoder;->readRawVarint64()J +PLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readDouble()D +PLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readFloat()F +PLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readInt32()I +PLandroidx/datastore/preferences/protobuf/CodedInputStreamReader;->readInt64()J +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->buffer(B)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferFixed32NoTag(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferFixed64NoTag(J)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferInt32NoTag(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferTag(II)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferUInt32NoTag(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$AbstractBufferedEncoder;->bufferUInt64NoTag(J)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->(Ljava/io/OutputStream;I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->doFlush()V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->flush()V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->flushIfNotAvailable(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeBool(IZ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeFixed32(II)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeFixed64(IJ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeInt32(II)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeMessageNoTag(Landroidx/datastore/preferences/protobuf/MessageLite;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeString(ILjava/lang/String;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeStringNoTag(Ljava/lang/String;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeTag(II)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeUInt32NoTag(I)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream$OutputStreamEncoder;->writeUInt64(IJ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->()V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->()V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->(Landroidx/datastore/preferences/protobuf/CodedOutputStream$1;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->access$100()Z +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeBoolSize(IZ)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeBoolSizeNoTag(Z)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeDoubleSize(ID)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeDoubleSizeNoTag(D)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeFloatSize(IF)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeFloatSizeNoTag(F)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt32Size(II)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt32SizeNoTag(I)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt64Size(IJ)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeInt64SizeNoTag(J)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeLengthDelimitedFieldSize(I)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeMessageSizeNoTag(Landroidx/datastore/preferences/protobuf/MessageLite;)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computePreferredBufferSize(I)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeStringSize(ILjava/lang/String;)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeStringSizeNoTag(Ljava/lang/String;)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeTagSize(I)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeUInt32SizeNoTag(I)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->computeUInt64SizeNoTag(J)I +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->isSerializationDeterministic()Z +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->newInstance(Ljava/io/OutputStream;I)Landroidx/datastore/preferences/protobuf/CodedOutputStream; +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->writeDouble(ID)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->writeFloat(IF)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStream;->writeInt64(IJ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->fieldOrder()Landroidx/datastore/preferences/protobuf/Writer$FieldOrder; +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->forCodedOutput(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)Landroidx/datastore/preferences/protobuf/CodedOutputStreamWriter; +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeBool(IZ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeDouble(ID)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeFloat(IF)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeInt32(II)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeInt64(IJ)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeMap(ILandroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/util/Map;)V +PLandroidx/datastore/preferences/protobuf/CodedOutputStreamWriter;->writeString(ILjava/lang/String;)V +PLandroidx/datastore/preferences/protobuf/FieldSet$1;->()V +PLandroidx/datastore/preferences/protobuf/FieldSet;->()V +PLandroidx/datastore/preferences/protobuf/FieldSet;->(Landroidx/datastore/preferences/protobuf/SmallSortedMap;)V +PLandroidx/datastore/preferences/protobuf/FieldSet;->(Z)V +PLandroidx/datastore/preferences/protobuf/FieldSet;->computeElementSize(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;ILjava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/FieldSet;->computeElementSizeNoTag(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/FieldSet;->getWireFormatForFieldType(Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Z)I +PLandroidx/datastore/preferences/protobuf/FieldSet;->makeImmutable()V +PLandroidx/datastore/preferences/protobuf/FieldSet;->writeElement(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;ILjava/lang/Object;)V +PLandroidx/datastore/preferences/protobuf/FieldSet;->writeElementNoTag(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/WireFormat$FieldType;Ljava/lang/Object;)V +PLandroidx/datastore/preferences/protobuf/FieldType$1;->()V +PLandroidx/datastore/preferences/protobuf/FieldType$Collection;->()V +PLandroidx/datastore/preferences/protobuf/FieldType$Collection;->(Ljava/lang/String;IZ)V +PLandroidx/datastore/preferences/protobuf/FieldType$Collection;->values()[Landroidx/datastore/preferences/protobuf/FieldType$Collection; +PLandroidx/datastore/preferences/protobuf/FieldType;->()V +PLandroidx/datastore/preferences/protobuf/FieldType;->(Ljava/lang/String;IILandroidx/datastore/preferences/protobuf/FieldType$Collection;Landroidx/datastore/preferences/protobuf/JavaType;)V +PLandroidx/datastore/preferences/protobuf/FieldType;->id()I +PLandroidx/datastore/preferences/protobuf/FieldType;->values()[Landroidx/datastore/preferences/protobuf/FieldType; +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite;)V +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->build()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->buildPartial()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->copyOnWrite()V +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder;->newMutableInstance()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite; +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->computeSerializedSize(Landroidx/datastore/preferences/protobuf/Schema;)I +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->createBuilder()Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$Builder; +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getMemoizedSerializedSize()I +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getSerializedSize()I +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->getSerializedSize(Landroidx/datastore/preferences/protobuf/Schema;)I +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->makeImmutable()V +PLandroidx/datastore/preferences/protobuf/GeneratedMessageLite;->writeTo(Landroidx/datastore/preferences/protobuf/CodedOutputStream;)V +PLandroidx/datastore/preferences/protobuf/JavaType;->()V +PLandroidx/datastore/preferences/protobuf/JavaType;->(Ljava/lang/String;ILjava/lang/Class;Ljava/lang/Class;Ljava/lang/Object;)V +PLandroidx/datastore/preferences/protobuf/JavaType;->getBoxedType()Ljava/lang/Class; +PLandroidx/datastore/preferences/protobuf/JavaType;->values()[Landroidx/datastore/preferences/protobuf/JavaType; +PLandroidx/datastore/preferences/protobuf/MapEntryLite;->computeMessageSize(ILjava/lang/Object;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MapEntryLite;->computeSerializedSize(Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/lang/Object;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MapEntryLite;->writeTo(Landroidx/datastore/preferences/protobuf/CodedOutputStream;Landroidx/datastore/preferences/protobuf/MapEntryLite$Metadata;Ljava/lang/Object;Ljava/lang/Object;)V +PLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->forMapData(Ljava/lang/Object;)Ljava/util/Map; +PLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->getSerializedSize(ILjava/lang/Object;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MapFieldSchemaLite;->getSerializedSizeLite(ILjava/lang/Object;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MessageSchema;->getSerializedSize(Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MessageSchema;->getUnknownFieldsSerializedSize(Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofBooleanAt(Ljava/lang/Object;J)Z +PLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofDoubleAt(Ljava/lang/Object;J)D +PLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofFloatAt(Ljava/lang/Object;J)F +PLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofIntAt(Ljava/lang/Object;J)I +PLandroidx/datastore/preferences/protobuf/MessageSchema;->oneofLongAt(Ljava/lang/Object;J)J +PLandroidx/datastore/preferences/protobuf/MessageSchema;->writeFieldsInAscendingOrder(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/MessageSchema;->writeMapHelper(Landroidx/datastore/preferences/protobuf/Writer;ILjava/lang/Object;I)V +PLandroidx/datastore/preferences/protobuf/MessageSchema;->writeString(ILjava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/MessageSchema;->writeTo(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/MessageSchema;->writeUnknownInMessageTo(Landroidx/datastore/preferences/protobuf/UnknownFieldSchema;Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap$1;->()V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap$1;->makeImmutable()V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->()V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->(Landroidx/datastore/preferences/protobuf/SmallSortedMap$1;)V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->getNumArrayEntries()I +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->getOverflowEntries()Ljava/lang/Iterable; +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->isImmutable()Z +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->makeImmutable()V +PLandroidx/datastore/preferences/protobuf/SmallSortedMap;->newFieldMap()Landroidx/datastore/preferences/protobuf/SmallSortedMap; +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->getSerializedSize()I +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLite;->writeTo(Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getFromMessage(Ljava/lang/Object;)Ljava/lang/Object; +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getSerializedSize(Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite;)I +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->getSerializedSize(Ljava/lang/Object;)I +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->writeTo(Landroidx/datastore/preferences/protobuf/UnknownFieldSetLite;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/UnknownFieldSetLiteSchema;->writeTo(Ljava/lang/Object;Landroidx/datastore/preferences/protobuf/Writer;)V +PLandroidx/datastore/preferences/protobuf/UnsafeUtil$Android64MemoryAccessor;->putByte(Ljava/lang/Object;JB)V +PLandroidx/datastore/preferences/protobuf/UnsafeUtil;->access$500(Ljava/lang/Object;JB)V +PLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putByte([BJB)V +PLandroidx/datastore/preferences/protobuf/UnsafeUtil;->putByteLittleEndian(Ljava/lang/Object;JB)V +PLandroidx/datastore/preferences/protobuf/Utf8$SafeProcessor;->encodeUtf8(Ljava/lang/String;[BII)I +PLandroidx/datastore/preferences/protobuf/Utf8;->encode(Ljava/lang/String;[BII)I +PLandroidx/datastore/preferences/protobuf/Utf8;->encodedLength(Ljava/lang/String;)I +PLandroidx/datastore/preferences/protobuf/WireFormat$FieldType;->getWireType()I +PLandroidx/datastore/preferences/protobuf/WireFormat$JavaType;->values()[Landroidx/datastore/preferences/protobuf/WireFormat$JavaType; +PLandroidx/datastore/preferences/protobuf/Writer$FieldOrder;->()V +PLandroidx/datastore/preferences/protobuf/Writer$FieldOrder;->(Ljava/lang/String;I)V diff --git a/datastore/datastore-preferences/src/androidMain/baselineProfiles/baseline-prof.txt b/datastore/datastore-preferences/src/androidMain/baselineProfiles/baseline-prof.txt new file mode 100644 index 0000000000000..e114c7fbd8642 --- /dev/null +++ b/datastore/datastore-preferences/src/androidMain/baselineProfiles/baseline-prof.txt @@ -0,0 +1,109 @@ +# TODO(b/469127532): Remove this merged baseline profile once AGP adds support for multiple +# baseline profile files per baselineProfiles directory. + +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt$$ExternalSyntheticLambda0;->()V +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt$$ExternalSyntheticLambda0;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt;->$r8$lambda$M8wy2jP_OP2ZhUCev6CMnhPDA50(Landroid/content/Context;)Ljava/util/List; +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt;->preferencesDataStore$default(Ljava/lang/String;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt;->preferencesDataStore$lambda$0(Landroid/content/Context;)Ljava/util/List; +HSPLandroidx/datastore/preferences/PreferenceDataStoreDelegateKt;->preferencesDataStore(Ljava/lang/String;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;)Lkotlin/properties/ReadOnlyProperty; +HSPLandroidx/datastore/preferences/PreferenceDataStoreFile;->preferencesDataStoreFile(Landroid/content/Context;Ljava/lang/String;)Ljava/io/File; +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate$$ExternalSyntheticLambda0;->(Landroid/content/Context;Landroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;)V +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;->$r8$lambda$n_JROCQhFBE9lHuSpefRs1uNEcA(Landroid/content/Context;Landroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;)Ljava/io/File; +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;->(Ljava/lang/String;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;)V +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;->getValue$lambda$0$0(Landroid/content/Context;Landroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;)Ljava/io/File; +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;->getValue(Landroid/content/Context;Lkotlin/reflect/KProperty;)Landroidx/datastore/core/DataStore; +HSPLandroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate;->getValue(Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/PreferencesProto$1;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->(Landroidx/datastore/preferences/PreferencesProto$1;)V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->putPreferences(Ljava/lang/String;Landroidx/datastore/preferences/PreferencesProto$Value;)Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$PreferencesDefaultEntryHolder;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->access$000()Landroidx/datastore/preferences/PreferencesProto$PreferenceMap; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->access$100(Landroidx/datastore/preferences/PreferencesProto$PreferenceMap;)Ljava/util/Map; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->dynamicMethod(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->getMutablePreferencesMap()Ljava/util/Map; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->getPreferencesMap()Ljava/util/Map; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->internalGetMutablePreferences()Landroidx/datastore/preferences/protobuf/MapFieldLite; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->internalGetPreferences()Landroidx/datastore/preferences/protobuf/MapFieldLite; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->newBuilder()Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder; +HSPLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->parseFrom(Ljava/io/InputStream;)Landroidx/datastore/preferences/PreferencesProto$PreferenceMap; +HSPLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->(Landroidx/datastore/preferences/PreferencesProto$1;)V +HSPLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setInteger(I)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +HSPLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setString(Ljava/lang/String;)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +HSPLandroidx/datastore/preferences/PreferencesProto$Value$ValueCase;->$values()[Landroidx/datastore/preferences/PreferencesProto$Value$ValueCase; +HSPLandroidx/datastore/preferences/PreferencesProto$Value$ValueCase;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$Value$ValueCase;->(Ljava/lang/String;II)V +HSPLandroidx/datastore/preferences/PreferencesProto$Value$ValueCase;->forNumber(I)Landroidx/datastore/preferences/PreferencesProto$Value$ValueCase; +HSPLandroidx/datastore/preferences/PreferencesProto$Value$ValueCase;->values()[Landroidx/datastore/preferences/PreferencesProto$Value$ValueCase; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->()V +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->access$1300(Landroidx/datastore/preferences/PreferencesProto$Value;Ljava/lang/String;)V +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->access$300()Landroidx/datastore/preferences/PreferencesProto$Value; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->access$900(Landroidx/datastore/preferences/PreferencesProto$Value;I)V +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->dynamicMethod(Landroidx/datastore/preferences/protobuf/GeneratedMessageLite$MethodToInvoke;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getBoolean()Z +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getDefaultInstance()Landroidx/datastore/preferences/PreferencesProto$Value; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getDouble()D +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getFloat()F +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getInteger()I +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getLong()J +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getString()Ljava/lang/String; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->getValueCase()Landroidx/datastore/preferences/PreferencesProto$Value$ValueCase; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->newBuilder()Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->setInteger(I)V +HSPLandroidx/datastore/preferences/PreferencesProto$Value;->setString(Ljava/lang/String;)V +Landroidx/datastore/preferences/PreferenceDataStoreDelegateKt$$ExternalSyntheticLambda0; +Landroidx/datastore/preferences/PreferenceDataStoreDelegateKt; +Landroidx/datastore/preferences/PreferenceDataStoreFile; +Landroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate$$ExternalSyntheticLambda0; +Landroidx/datastore/preferences/PreferenceDataStoreSingletonDelegate; +Landroidx/datastore/preferences/PreferencesProto$1; +Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder; +Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$PreferencesDefaultEntryHolder; +Landroidx/datastore/preferences/PreferencesProto$PreferenceMap; +Landroidx/datastore/preferences/PreferencesProto$PreferenceMapOrBuilder; +Landroidx/datastore/preferences/PreferencesProto$StringSet; +Landroidx/datastore/preferences/PreferencesProto$StringSetOrBuilder; +Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +Landroidx/datastore/preferences/PreferencesProto$Value$ValueCase; +Landroidx/datastore/preferences/PreferencesProto$Value; +Landroidx/datastore/preferences/PreferencesProto$ValueOrBuilder; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->()V +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->(Landroidx/datastore/preferences/PreferencesProto$1;)V +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder;->putPreferences(Ljava/lang/String;Landroidx/datastore/preferences/PreferencesProto$Value;)Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->access$000()Landroidx/datastore/preferences/PreferencesProto$PreferenceMap; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->access$100(Landroidx/datastore/preferences/PreferencesProto$PreferenceMap;)Ljava/util/Map; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->getMutablePreferencesMap()Ljava/util/Map; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->internalGetMutablePreferences()Landroidx/datastore/preferences/protobuf/MapFieldLite; +PLandroidx/datastore/preferences/PreferencesProto$PreferenceMap;->newBuilder()Landroidx/datastore/preferences/PreferencesProto$PreferenceMap$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->()V +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->(Landroidx/datastore/preferences/PreferencesProto$1;)V +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setBoolean(Z)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setDouble(D)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setFloat(F)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setInteger(I)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setLong(J)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value$Builder;->setString(Ljava/lang/String;)Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$1100(Landroidx/datastore/preferences/PreferencesProto$Value;J)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$1300(Landroidx/datastore/preferences/PreferencesProto$Value;Ljava/lang/String;)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$1900(Landroidx/datastore/preferences/PreferencesProto$Value;D)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$300()Landroidx/datastore/preferences/PreferencesProto$Value; +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$500(Landroidx/datastore/preferences/PreferencesProto$Value;Z)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$700(Landroidx/datastore/preferences/PreferencesProto$Value;F)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->access$900(Landroidx/datastore/preferences/PreferencesProto$Value;I)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->getDouble()D +PLandroidx/datastore/preferences/PreferencesProto$Value;->getFloat()F +PLandroidx/datastore/preferences/PreferencesProto$Value;->getInteger()I +PLandroidx/datastore/preferences/PreferencesProto$Value;->getLong()J +PLandroidx/datastore/preferences/PreferencesProto$Value;->newBuilder()Landroidx/datastore/preferences/PreferencesProto$Value$Builder; +PLandroidx/datastore/preferences/PreferencesProto$Value;->setBoolean(Z)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->setDouble(D)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->setFloat(F)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->setInteger(I)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->setLong(J)V +PLandroidx/datastore/preferences/PreferencesProto$Value;->setString(Ljava/lang/String;)V diff --git a/datastore/datastore/src/androidMain/baselineProfiles/baseline-prof.txt b/datastore/datastore/src/androidMain/baselineProfiles/baseline-prof.txt new file mode 100644 index 0000000000000..c31d203347539 --- /dev/null +++ b/datastore/datastore/src/androidMain/baselineProfiles/baseline-prof.txt @@ -0,0 +1,92 @@ +# TODO(b/469127532): Remove this merged baseline profile once AGP adds support for multiple +# baseline profile files per baselineProfiles directory. + +HSPLandroidx/datastore/DataStoreDelegateKt$$ExternalSyntheticLambda0;->()V +HSPLandroidx/datastore/DataStoreDelegateKt$$ExternalSyntheticLambda0;->invoke(Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/DataStoreDelegateKt;->$r8$lambda$ltH8eG9Ry63WYy-8nryGg0pFCWg(Landroid/content/Context;)Ljava/util/List; +HSPLandroidx/datastore/DataStoreDelegateKt;->dataStore$default(Ljava/lang/String;Landroidx/datastore/core/Serializer;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; +HSPLandroidx/datastore/DataStoreDelegateKt;->dataStore$lambda$0(Landroid/content/Context;)Ljava/util/List; +HSPLandroidx/datastore/DataStoreDelegateKt;->dataStore(Ljava/lang/String;Landroidx/datastore/core/Serializer;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;)Lkotlin/properties/ReadOnlyProperty; +HSPLandroidx/datastore/DataStoreFile;->dataStoreFile(Landroid/content/Context;Ljava/lang/String;)Ljava/io/File; +HSPLandroidx/datastore/DataStoreSingletonDelegate$$ExternalSyntheticLambda0;->(Landroidx/datastore/DataStoreSingletonDelegate;Landroid/content/Context;)V +HSPLandroidx/datastore/DataStoreSingletonDelegate$$ExternalSyntheticLambda0;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/DataStoreSingletonDelegate;->$r8$lambda$jO2EpaGG7QjdydS-66DJO_jeR50(Landroidx/datastore/DataStoreSingletonDelegate;Landroid/content/Context;)Lokio/Path; +HSPLandroidx/datastore/DataStoreSingletonDelegate;->(Ljava/lang/String;Landroidx/datastore/core/okio/OkioSerializer;Landroidx/datastore/core/handlers/ReplaceFileCorruptionHandler;Lkotlin/jvm/functions/Function1;Lkotlinx/coroutines/CoroutineScope;Z)V +HSPLandroidx/datastore/DataStoreSingletonDelegate;->getValue$lambda$0$0(Landroidx/datastore/DataStoreSingletonDelegate;Landroid/content/Context;)Lokio/Path; +HSPLandroidx/datastore/DataStoreSingletonDelegate;->getValue(Landroid/content/Context;Lkotlin/reflect/KProperty;)Landroidx/datastore/core/DataStore; +HSPLandroidx/datastore/DataStoreSingletonDelegate;->getValue(Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object; +HSPLandroidx/datastore/OkioSerializerWrapper;->(Landroidx/datastore/core/Serializer;)V +HSPLandroidx/datastore/OkioSerializerWrapper;->getDefaultValue()Ljava/lang/Object; +HSPLandroidx/datastore/OkioSerializerWrapper;->readFrom(Lokio/BufferedSource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/OkioSerializerWrapper;->writeTo(Ljava/lang/Object;Lokio/BufferedSink;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/AtomicBoolean;->(Z)V +HSPLandroidx/datastore/core/okio/AtomicBoolean;->get()Z +HSPLandroidx/datastore/core/okio/AtomicBoolean;->set(Z)V +HSPLandroidx/datastore/core/okio/OkioReadScope$readData$1;->(Landroidx/datastore/core/okio/OkioReadScope;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioReadScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +HSPLandroidx/datastore/core/okio/OkioReadScope;->checkClose()V +HSPLandroidx/datastore/core/okio/OkioReadScope;->close()V +HSPLandroidx/datastore/core/okio/OkioReadScope;->getFileSystem()Lokio/FileSystem; +HSPLandroidx/datastore/core/okio/OkioReadScope;->getPath()Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioReadScope;->getSerializer()Landroidx/datastore/core/okio/OkioSerializer; +HSPLandroidx/datastore/core/okio/OkioReadScope;->readData$suspendImpl(Landroidx/datastore/core/okio/OkioReadScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioReadScope;->readData(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda0;->(Landroidx/datastore/core/okio/OkioStorage;)V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1;->()V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2;->(Landroidx/datastore/core/okio/OkioStorage;)V +HSPLandroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2;->invoke()Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorage$Companion;->()V +HSPLandroidx/datastore/core/okio/OkioStorage$Companion;->(Lkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->$r8$lambda$ngX1sQHRBFS9is12Tq2RMloe3b8(Landroidx/datastore/core/okio/OkioStorage;)Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorage;->$r8$lambda$zaSHyDobNeO3yk4Wyl_gDVAF7jA(Lokio/Path;Lokio/FileSystem;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorage;->()V +HSPLandroidx/datastore/core/okio/OkioStorage;->(Lokio/FileSystem;Landroidx/datastore/core/okio/OkioSerializer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->(Lokio/FileSystem;Landroidx/datastore/core/okio/OkioSerializer;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V +HSPLandroidx/datastore/core/okio/OkioStorage;->_init_$lambda$0(Lokio/Path;Lokio/FileSystem;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorage;->canonicalPath_delegate$lambda$0(Landroidx/datastore/core/okio/OkioStorage;)Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorage;->createConnection()Landroidx/datastore/core/StorageConnection; +HSPLandroidx/datastore/core/okio/OkioStorage;->getCanonicalPath()Lokio/Path; +HSPLandroidx/datastore/core/okio/OkioStorageConnection$readScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection$writeScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;Landroidx/datastore/core/InterProcessCoordinator;Lkotlin/jvm/functions/Function0;)V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->checkNotClosed()V +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->getCoordinator()Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->readScope(Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/OkioStorageKt;->createSingleProcessCoordinator(Lokio/Path;)Landroidx/datastore/core/InterProcessCoordinator; +HSPLandroidx/datastore/core/okio/OkioWriteScope$writeData$1;->(Landroidx/datastore/core/okio/OkioWriteScope;Lkotlin/coroutines/Continuation;)V +HSPLandroidx/datastore/core/okio/OkioWriteScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +HSPLandroidx/datastore/core/okio/OkioWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +HSPLandroidx/datastore/core/okio/Synchronizer;->()V +Landroidx/datastore/DataStoreDelegateKt$$ExternalSyntheticLambda0; +Landroidx/datastore/DataStoreDelegateKt; +Landroidx/datastore/DataStoreFile; +Landroidx/datastore/DataStoreSingletonDelegate$$ExternalSyntheticLambda0; +Landroidx/datastore/DataStoreSingletonDelegate; +Landroidx/datastore/OkioSerializerWrapper; +Landroidx/datastore/core/okio/AtomicBoolean; +Landroidx/datastore/core/okio/OkioReadScope$readData$1; +Landroidx/datastore/core/okio/OkioReadScope; +Landroidx/datastore/core/okio/OkioSerializer; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda0; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda1; +Landroidx/datastore/core/okio/OkioStorage$$ExternalSyntheticLambda2; +Landroidx/datastore/core/okio/OkioStorage$Companion; +Landroidx/datastore/core/okio/OkioStorage; +Landroidx/datastore/core/okio/OkioStorageConnection$readScope$1; +Landroidx/datastore/core/okio/OkioStorageConnection$writeScope$1; +Landroidx/datastore/core/okio/OkioStorageConnection; +Landroidx/datastore/core/okio/OkioStorageKt; +Landroidx/datastore/core/okio/OkioWriteScope$writeData$1; +Landroidx/datastore/core/okio/OkioWriteScope; +Landroidx/datastore/core/okio/Synchronizer; +PLandroidx/datastore/OkioSerializerWrapper;->writeTo(Ljava/lang/Object;Lokio/BufferedSink;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/okio/OkioReadScope;->getFileSystem()Lokio/FileSystem; +PLandroidx/datastore/core/okio/OkioReadScope;->getPath()Lokio/Path; +PLandroidx/datastore/core/okio/OkioReadScope;->getSerializer()Landroidx/datastore/core/okio/OkioSerializer; +PLandroidx/datastore/core/okio/OkioStorageConnection$writeScope$1;->(Landroidx/datastore/core/okio/OkioStorageConnection;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/okio/OkioStorageConnection;->writeScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +PLandroidx/datastore/core/okio/OkioWriteScope$writeData$1;->(Landroidx/datastore/core/okio/OkioWriteScope;Lkotlin/coroutines/Continuation;)V +PLandroidx/datastore/core/okio/OkioWriteScope;->(Lokio/FileSystem;Lokio/Path;Landroidx/datastore/core/okio/OkioSerializer;)V +PLandroidx/datastore/core/okio/OkioWriteScope;->writeData(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; diff --git a/leanback/leanback/src/androidTest/java/androidx/leanback/app/BrowseFragmentTest.java b/leanback/leanback/src/androidTest/java/androidx/leanback/app/BrowseFragmentTest.java index 10d4cfc6c6c58..45e34ff7ddfc3 100644 --- a/leanback/leanback/src/androidTest/java/androidx/leanback/app/BrowseFragmentTest.java +++ b/leanback/leanback/src/androidTest/java/androidx/leanback/app/BrowseFragmentTest.java @@ -53,6 +53,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.LargeTest; +import androidx.test.filters.SdkSuppress; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; @@ -126,9 +127,9 @@ public boolean canProceed() { }); } + @SdkSuppress(maxSdkVersion = 35) // b/460508283 @Test public void testTouchMode() throws Throwable { - assumeFalse("Test fails on cuttlefish b/460508283", Build.MODEL.contains("Cuttlefish")); Intent intent = new Intent(); intent.putExtra(BrowseFragmentTestActivity.EXTRA_ADD_TO_BACKSTACK , true); intent.putExtra(BrowseFragmentTestActivity.EXTRA_LOAD_DATA_DELAY , 0L); diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt index 9c4e9f89353cc..ae1517a40c18f 100644 --- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt +++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt @@ -115,6 +115,9 @@ abstract class SafeArgsPlugin protected constructor() : Plugin { } private fun navigationFiles(variant: Variant): Provider> { + val flavorName = variant.flavorName + val buildType = variant.buildType + val name = variant.name return variant.sources.res!!.all.map { resSources -> resSources .flatten() @@ -132,13 +135,13 @@ abstract class SafeArgsPlugin protected constructor() : Plugin { ?: entry.value.minBy { file -> when { // matches variant name exactly - file.path.substringBefore("/res/").endsWith(variant.name) -> 0 + file.path.substringBefore("/res/").endsWith(name) -> 0 // matches variant flavor - variant.flavorName?.let { + flavorName?.let { file.path.substringBefore("/res/").endsWith(it) } == true -> 1 // matches variant buildType - variant.buildType?.let { + buildType?.let { file.path.substringBefore("/res/").endsWith(it) } == true -> 2 // fall back to main diff --git a/xr/compose/compose-testing/build.gradle b/xr/compose/compose-testing/build.gradle index 8fd584b97e969..bb1ca7f9fbc3c 100644 --- a/xr/compose/compose-testing/build.gradle +++ b/xr/compose/compose-testing/build.gradle @@ -48,7 +48,7 @@ dependencies { implementation("androidx.compose.ui:ui-unit:1.7.5") implementation("androidx.compose.ui:ui-util:1.7.5") implementation("androidx.compose.ui:ui-test-junit4:1.7.5") - implementation("com.google.ar:impress:0.0.10") + implementation("com.google.ar:impress:0.0.11") compileOnly(libs.androidExtensionsXr) compileOnly(files(new File(AndroidXConfig.getPrebuiltsRoot(project), "androidx/xr/extensions/com.android.extensions.xr.host.test.jar"))) diff --git a/xr/compose/compose/api/current.txt b/xr/compose/compose/api/current.txt index 18f344f76a2db..f1088a41b721a 100644 --- a/xr/compose/compose/api/current.txt +++ b/xr/compose/compose/api/current.txt @@ -361,9 +361,9 @@ package androidx.xr.compose.subspace { } public final class SpatialRowKt { - method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialCurvedRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.unit.Dp curveRadius, kotlin.jvm.functions.Function1 content); + method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static inline void SpatialCurvedRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.unit.Dp curveRadius, kotlin.jvm.functions.Function1 content); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialCurvedRow-hGBTI10(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.xr.compose.subspace.layout.SpatialAlignment?, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal?, float, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); - method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, kotlin.jvm.functions.Function1 content); + method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static inline void SpatialRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, kotlin.jvm.functions.Function1 content); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialRow(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.xr.compose.subspace.layout.SpatialAlignment?, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal?, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); } diff --git a/xr/compose/compose/api/restricted_current.txt b/xr/compose/compose/api/restricted_current.txt index d9417cac065b4..90b9aef821098 100644 --- a/xr/compose/compose/api/restricted_current.txt +++ b/xr/compose/compose/api/restricted_current.txt @@ -316,10 +316,8 @@ package androidx.xr.compose.subspace { public final class SpatialColumnKt { method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static inline void SpatialColumn(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Vertical verticalArrangement, kotlin.jvm.functions.Function1 content); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialColumn(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.xr.compose.subspace.layout.SpatialAlignment?, androidx.xr.compose.subspace.layout.SpatialArrangement.Vertical?, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); - method @InaccessibleFromKotlin @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy getDefaultSpatialColumnMeasurePolicy(); method @KotlinOnly @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy spatialColumnMeasurePolicy(androidx.xr.compose.subspace.layout.SpatialAlignment alignment, androidx.xr.compose.subspace.layout.SpatialArrangement.Vertical verticalArrangement); method @BytecodeOnly @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy spatialColumnMeasurePolicy(androidx.xr.compose.subspace.layout.SpatialAlignment, androidx.xr.compose.subspace.layout.SpatialArrangement.Vertical, androidx.compose.runtime.Composer?, int); - property @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy DefaultSpatialColumnMeasurePolicy; } @androidx.compose.foundation.layout.LayoutScopeMarker public interface SpatialColumnScope { @@ -381,10 +379,12 @@ package androidx.xr.compose.subspace { } public final class SpatialRowKt { - method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialCurvedRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.unit.Dp curveRadius, kotlin.jvm.functions.Function1 content); + method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static inline void SpatialCurvedRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, optional androidx.compose.ui.unit.Dp curveRadius, kotlin.jvm.functions.Function1 content); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialCurvedRow-hGBTI10(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.xr.compose.subspace.layout.SpatialAlignment?, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal?, float, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); - method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, kotlin.jvm.functions.Function1 content); + method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static inline void SpatialRow(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier, optional androidx.xr.compose.subspace.layout.SpatialAlignment alignment, optional androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement, kotlin.jvm.functions.Function1 content); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialRow(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.xr.compose.subspace.layout.SpatialAlignment?, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal?, kotlin.jvm.functions.Function3, androidx.compose.runtime.Composer?, int, int); + method @KotlinOnly @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy spatialRowMeasurePolicy(androidx.compose.ui.unit.Dp curveRadius, androidx.xr.compose.subspace.layout.SpatialAlignment alignment, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal horizontalArrangement); + method @BytecodeOnly @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.xr.compose.subspace.layout.SubspaceMeasurePolicy spatialRowMeasurePolicy--orJrPs(float, androidx.xr.compose.subspace.layout.SpatialAlignment, androidx.xr.compose.subspace.layout.SpatialArrangement.Horizontal, androidx.compose.runtime.Composer?, int); } @androidx.compose.foundation.layout.LayoutScopeMarker public interface SpatialRowScope { @@ -394,6 +394,12 @@ package androidx.xr.compose.subspace { method @BytecodeOnly public static androidx.xr.compose.subspace.layout.SubspaceModifier! weight$default(androidx.xr.compose.subspace.SpatialRowScope!, androidx.xr.compose.subspace.layout.SubspaceModifier!, float, boolean, int, Object!); } + @kotlin.PublishedApi internal final class SpatialRowScopeInstance implements androidx.xr.compose.subspace.SpatialRowScope { + method public androidx.xr.compose.subspace.layout.SubspaceModifier align(androidx.xr.compose.subspace.layout.SubspaceModifier, androidx.xr.compose.subspace.layout.SpatialAlignment.Depth alignment); + method public androidx.xr.compose.subspace.layout.SubspaceModifier align(androidx.xr.compose.subspace.layout.SubspaceModifier, androidx.xr.compose.subspace.layout.SpatialAlignment.Vertical alignment); + method public androidx.xr.compose.subspace.layout.SubspaceModifier weight(androidx.xr.compose.subspace.layout.SubspaceModifier, float weight, boolean fill); + } + public final class SpatialSpacerKt { method @KotlinOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialSpacer(optional androidx.xr.compose.subspace.layout.SubspaceModifier modifier); method @BytecodeOnly @androidx.compose.runtime.Composable @androidx.xr.compose.subspace.SubspaceComposable public static void SpatialSpacer(androidx.xr.compose.subspace.layout.SubspaceModifier?, androidx.compose.runtime.Composer?, int, int); diff --git a/xr/compose/compose/build.gradle b/xr/compose/compose/build.gradle index e36cfc6be6f9d..3d79d12e19bdc 100644 --- a/xr/compose/compose/build.gradle +++ b/xr/compose/compose/build.gradle @@ -66,7 +66,7 @@ dependencies { testImplementation("androidx.compose.ui:ui-test-junit4:1.7.5") testImplementation(project(":xr:compose:compose-testing")) testImplementation(project(":xr:scenecore:scenecore-testing")) - testImplementation("com.google.ar:impress:0.0.10") + testImplementation("com.google.ar:impress:0.0.11") compileOnly(libs.androidExtensionsXr) testImplementation(files(new File(AndroidXConfig.getPrebuiltsRoot(project), "androidx/xr/extensions/com.android.extensions.xr.host.test.jar"))) diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialColumn.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialColumn.kt index 7f0b2c3b0e876..0a56635a02f61 100644 --- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialColumn.kt +++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialColumn.kt @@ -66,7 +66,6 @@ public inline fun SpatialColumn( ) } -@PublishedApi internal val DefaultSpatialColumnMeasurePolicy: SubspaceMeasurePolicy = SpatialColumnMeasurePolicy( alignment = SpatialAlignment.Center, diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialRow.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialRow.kt index f10e6cb0596f1..10db654053fb0 100644 --- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialRow.kt +++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/SpatialRow.kt @@ -24,8 +24,6 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastRoundToInt -import androidx.xr.compose.platform.LocalSession -import androidx.xr.compose.subspace.layout.CoreGroupEntity import androidx.xr.compose.subspace.layout.SpatialAlignment import androidx.xr.compose.subspace.layout.SpatialArrangement import androidx.xr.compose.subspace.layout.SubspaceLayout @@ -40,7 +38,6 @@ import androidx.xr.compose.unit.VolumeConstraints import androidx.xr.runtime.math.Pose import androidx.xr.runtime.math.Quaternion import androidx.xr.runtime.math.Vector3 -import androidx.xr.scenecore.GroupEntity import kotlin.math.cos import kotlin.math.sin @@ -55,13 +52,19 @@ import kotlin.math.sin */ @Composable @SubspaceComposable -public fun SpatialRow( +public inline fun SpatialRow( modifier: SubspaceModifier = SubspaceModifier, alignment: SpatialAlignment = SpatialAlignment.Center, horizontalArrangement: SpatialArrangement.Horizontal = SpatialArrangement.Center, - content: @Composable @SubspaceComposable SpatialRowScope.() -> Unit, + crossinline content: @Composable @SubspaceComposable SpatialRowScope.() -> Unit, ) { - SpatialRow(modifier, alignment, horizontalArrangement, Dp.Infinity, content) + SpatialCurvedRow( + modifier = modifier, + alignment = alignment, + horizontalArrangement = horizontalArrangement, + curveRadius = Dp.Infinity, + content = content, + ) } /** @@ -79,58 +82,58 @@ public fun SpatialRow( */ @Composable @SubspaceComposable -public fun SpatialCurvedRow( +public inline fun SpatialCurvedRow( modifier: SubspaceModifier = SubspaceModifier, alignment: SpatialAlignment = SpatialAlignment.Center, horizontalArrangement: SpatialArrangement.Horizontal = SpatialArrangement.Center, curveRadius: Dp = SpatialCurvedRowDefaults.curveRadius, - content: @Composable @SubspaceComposable SpatialRowScope.() -> Unit, -) { - SpatialRow(modifier, alignment, horizontalArrangement, curveRadius, content) -} - -/** - * A layout composable that arranges its children in a horizontal sequence. For arranging children - * vertically, see [SpatialColumn]. - * - * @param modifier Appearance modifiers to apply to this Composable. - * @param alignment The default alignment for child elements within the row. - * @param horizontalArrangement The horizontal arrangement of the children. - * @param curveRadius Defines the curve of the row by specifying its radius in Dp. A larger radius - * creates a gentler curve (less curvature), while a smaller positive radius results in a sharper - * curve (more curvature). Using [Dp.Infinity] or a non-positive value (zero or negative) makes - * the row straight. When curved, row items are angled to follow the curve's path. This value is - * the radial distance in the polar coordinate system. - * @param content The composable content to be laid out horizontally in the row. - */ -@Composable -@SubspaceComposable -private fun SpatialRow( - modifier: SubspaceModifier, - alignment: SpatialAlignment, - horizontalArrangement: SpatialArrangement.Horizontal, - curveRadius: Dp, - content: @Composable @SubspaceComposable SpatialRowScope.() -> Unit, + crossinline content: @Composable @SubspaceComposable SpatialRowScope.() -> Unit, ) { - val session = checkNotNull(LocalSession.current) { "session must be initialized" } - - val coreGroupEntity = remember { - CoreGroupEntity(GroupEntity.create(session, name = "SpatialRow", pose = Pose.Identity)) - } + val measurePolicy = + spatialRowMeasurePolicy( + curveRadius = if (curveRadius > 0.dp) curveRadius else Dp.Infinity, + alignment = alignment, + horizontalArrangement = horizontalArrangement, + ) SubspaceLayout( modifier = modifier, content = { SpatialRowScopeInstance.content() }, - coreEntity = coreGroupEntity, - measurePolicy = - SpatialRowMeasurePolicy( - if (curveRadius > 0.dp) curveRadius else Dp.Infinity, - alignment, - horizontalArrangement, - ), + coreEntityName = "SpatialRow", + measurePolicy = measurePolicy, ) } +internal val DefaultSpatialRowMeasurePolicy: SubspaceMeasurePolicy = + SpatialRowMeasurePolicy( + curveRadius = Dp.Infinity, + alignment = SpatialAlignment.Center, + horizontalArrangement = SpatialArrangement.Center, + ) + +@PublishedApi +@Composable +internal fun spatialRowMeasurePolicy( + curveRadius: Dp, + alignment: SpatialAlignment, + horizontalArrangement: SpatialArrangement.Horizontal, +): SubspaceMeasurePolicy = + if ( + curveRadius == Dp.Infinity && + alignment == SpatialAlignment.Center && + horizontalArrangement == SpatialArrangement.Center + ) { + DefaultSpatialRowMeasurePolicy + } else { + remember(curveRadius, alignment, horizontalArrangement) { + SpatialRowMeasurePolicy( + curveRadius = curveRadius, + alignment = alignment, + horizontalArrangement = horizontalArrangement, + ) + } + } + /** * Measure policy for [SpatialRow] and [SpatialCurvedRow] layouts. Handles the measurement and * placement of children in a horizontal sequence, optionally along a curve. @@ -379,6 +382,7 @@ public object SpatialCurvedRowDefaults { } /** Default implementation of the [SpatialRowScope] interface. */ +@PublishedApi internal object SpatialRowScopeInstance : SpatialRowScope { override fun SubspaceModifier.weight(weight: Float, fill: Boolean): SubspaceModifier { require(weight > 0.0) { "invalid weight $weight; must be greater than zero" } diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Offset.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Offset.kt index f3455b8322b7c..e0a9832656269 100644 --- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Offset.kt +++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/Offset.kt @@ -16,6 +16,7 @@ package androidx.xr.compose.subspace.layout +import androidx.annotation.RestrictTo import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.xr.compose.subspace.node.SubspaceLayoutModifierNode @@ -28,54 +29,93 @@ import androidx.xr.runtime.math.Vector3 /** * Offset the content by ([x] dp, [y] dp, [z] dp). The offsets can be positive as well as * non-positive. + * + * This modifier will automatically adjust the horizontal offset according to the layout direction: + * when the layout direction is LTR, positive [x] offsets will move the content to the right and + * when the layout direction is RTL, positive [x] offsets will move the content to the left. For a + * modifier that offsets without considering layout direction, see [absoluteOffset]. + * + * @see absoluteOffset */ public fun SubspaceModifier.offset(x: Dp = 0.dp, y: Dp = 0.dp, z: Dp = 0.dp): SubspaceModifier = - this then SubspaceOffsetElement(x = x, y = y, z = z) + this then SubspaceOffsetElement(x = x, y = y, z = z, rtlAware = true) + +/** + * Offset the content by ([x] dp, [y] dp, [z] dp) without considering layout direction. The offsets + * can be positive as well as non-positive. + * + * This modifier will not consider layout direction when calculating the position of the content: a + * positive [x] offset will always move the content to the right. For a modifier that considers the + * layout direction when applying the offset, see [offset]. + * + * @see offset + */ +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public fun SubspaceModifier.absoluteOffset( + x: Dp = 0.dp, + y: Dp = 0.dp, + z: Dp = 0.dp, +): SubspaceModifier = this then SubspaceOffsetElement(x = x, y = y, z = z, rtlAware = false) -private class SubspaceOffsetElement(public val x: Dp, public val y: Dp, public val z: Dp) : +private class SubspaceOffsetElement(val x: Dp, val y: Dp, val z: Dp, val rtlAware: Boolean) : SubspaceModifierNodeElement() { override fun create(): OffsetNode { - return OffsetNode(x, y, z) + return OffsetNode(x, y, z, rtlAware) } override fun update(node: OffsetNode) { - node.update(x, y, z) + node.update(x, y, z, rtlAware) } override fun hashCode(): Int { var result = x.hashCode() result = 31 * result + y.hashCode() result = 31 * result + z.hashCode() + result = 31 * result + rtlAware.hashCode() + return result } + /* + * TODO(b/475896820): Add unit tests for hashCode and equals for all *Element classes in + * SubspaceModifier APIs + */ override fun equals(other: Any?): Boolean { if (this === other) return true val otherElement = other as? OffsetNode ?: return false - return x == otherElement.x && y == otherElement.y && z == otherElement.z + return x == otherElement.x && + y == otherElement.y && + z == otherElement.z && + rtlAware == otherElement.rtlAware } } -private class OffsetNode(public var x: Dp, public var y: Dp, public var z: Dp) : +private class OffsetNode(var x: Dp, var y: Dp, var z: Dp, var rtlAware: Boolean) : SubspaceLayoutModifierNode, SubspaceModifier.Node() { override val shouldAutoInvalidate: Boolean = false - fun update(x: Dp, y: Dp, z: Dp) { - if (this.x != x || this.y != y || this.z != z) invalidatePlacement() + fun update(x: Dp, y: Dp, z: Dp, rtlAware: Boolean) { + if (this.x != x || this.y != y || this.z != z || this.rtlAware != rtlAware) + invalidatePlacement() this.x = x this.y = y this.z = z + this.rtlAware = rtlAware } override fun SubspaceMeasureScope.measure( measurable: SubspaceMeasurable, constraints: VolumeConstraints, ): SubspaceMeasureResult { - val placeable = measurable.measure(constraints) - return layout(placeable.measuredWidth, placeable.measuredHeight, placeable.measuredDepth) { - placeable.place( + val subspacePlaceable = measurable.measure(constraints) + return layout( + subspacePlaceable.measuredWidth, + subspacePlaceable.measuredHeight, + subspacePlaceable.measuredDepth, + ) { + val pose = Pose( Vector3( x.roundToPx().toFloat(), @@ -83,7 +123,11 @@ private class OffsetNode(public var x: Dp, public var y: Dp, public var z: Dp) : z.roundToPx().toFloat(), ) ) - ) + if (rtlAware) { + subspacePlaceable.placeRelative(pose) + } else { + subspacePlaceable.place(pose) + } } } } diff --git a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/SubspaceLayout.kt b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/SubspaceLayout.kt index ec0e8f49cb413..f6c8fdbbacb4a 100644 --- a/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/SubspaceLayout.kt +++ b/xr/compose/compose/src/main/kotlin/androidx/xr/compose/subspace/layout/SubspaceLayout.kt @@ -127,7 +127,7 @@ public inline fun SubspaceLayout( set(coreEntity, SetCoreEntity) set(modifier, SetModifier) }, - content = { content() }, + content = content, ) } } @@ -289,7 +289,7 @@ internal inline fun SubspaceLayout( set(coreGroupEntity, SetCoreEntity) set(modifier, SetModifier) }, - content = { content() }, + content = content, ) } } diff --git a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/subspace/layout/OffsetTest.kt b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/subspace/layout/OffsetTest.kt index a6648c9d0e41c..9b8f979b4d243 100644 --- a/xr/compose/compose/src/test/kotlin/androidx/xr/compose/subspace/layout/OffsetTest.kt +++ b/xr/compose/compose/src/test/kotlin/androidx/xr/compose/subspace/layout/OffsetTest.kt @@ -18,15 +18,18 @@ package androidx.xr.compose.subspace.layout import androidx.compose.material3.Button import androidx.compose.material3.Text +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.testTag import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.xr.compose.spatial.Subspace @@ -72,7 +75,43 @@ class OffsetTest { fun offset_negativeValuesArePositionedCorrectly() { composeTestRule.setContent { Subspace { - SpatialPanel(SubspaceModifier.testTag("panel").offset(-20.dp, -20.dp, -20.dp)) { + SpatialPanel( + SubspaceModifier.testTag("panel").offset((-20).dp, (-20).dp, (-20).dp) + ) { + Text(text = "Panel") + } + } + } + + composeTestRule + .onSubspaceNodeWithTag("panel") + .assertPositionInRootIsEqualTo((-20).dp, (-20).dp, (-20).dp) + } + + @Test + fun offset_rtlLayoutIsPositionedCorrectly() { + composeTestRule.setContent { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + Subspace { + SpatialPanel(SubspaceModifier.testTag("panel").offset(20.dp, 20.dp, 20.dp)) { + Text(text = "Panel") + } + } + } + } + + composeTestRule + .onSubspaceNodeWithTag("panel") + .assertPositionInRootIsEqualTo((-20).dp, 20.dp, 20.dp) + } + + @Test + fun absoluteOffset_ltrLayoutIsPositionedCorrectly() { + composeTestRule.setContent { + Subspace { + SpatialPanel( + SubspaceModifier.testTag("panel").absoluteOffset(20.dp, 20.dp, 20.dp) + ) { Text(text = "Panel") } } @@ -80,7 +119,49 @@ class OffsetTest { composeTestRule .onSubspaceNodeWithTag("panel") - .assertPositionInRootIsEqualTo(-20.dp, -20.dp, -20.dp) + .assertPositionInRootIsEqualTo(20.dp, 20.dp, 20.dp) + } + + @Test + fun absoluteOffset_rtlLayoutIsPositionedCorrectly() { + composeTestRule.setContent { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + Subspace { + SpatialPanel( + SubspaceModifier.testTag("panel").absoluteOffset(20.dp, 20.dp, 20.dp) + ) { + Text(text = "Panel") + } + } + } + } + + composeTestRule + .onSubspaceNodeWithTag("panel") + .assertPositionInRootIsEqualTo(20.dp, 20.dp, 20.dp) + } + + @Test + fun offset_and_absoluteOffset_combined_rtlLayoutIsPositionedCorrectly() { + composeTestRule.setContent { + CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) { + Subspace { + SpatialPanel( + SubspaceModifier.testTag("panel") + .offset(20.dp, 20.dp, 20.dp) + .absoluteOffset(10.dp, 10.dp, 10.dp) + ) { + Text(text = "Panel") + } + } + } + } + + // Offset with RTL moves the panel -20 dp and absoluteOffset with RTL moves the panel 10 dp. + // Final x = -20 + 10 = -10 dp + composeTestRule + .onSubspaceNodeWithTag("panel") + .assertPositionInRootIsEqualTo((-10).dp, 30.dp, 30.dp) } @Test @@ -128,7 +209,7 @@ class OffsetTest { composeTestRule .onSubspaceNodeWithTag("panel1") - .assertPositionInRootIsEqualTo(-240.dp, 10.dp, 10.dp) // x=-(1000/2/2) + 10 + .assertPositionInRootIsEqualTo((-240).dp, 10.dp, 10.dp) // x=-(1000/2/2) + 10 .assertPositionIsEqualTo(10.dp, 10.dp, 10.dp) composeTestRule @@ -143,10 +224,7 @@ class OffsetTest { Subspace { var offsetX by remember { mutableStateOf(0.dp) } SpatialPanel(SubspaceModifier.testTag("panel").offset(x = offsetX)) { - Button( - modifier = Modifier.testTag("button"), - onClick = { offsetX = offsetX + 10.dp }, - ) { + Button(modifier = Modifier.testTag("button"), onClick = { offsetX += 10.dp }) { Text(text = "Click to change offset") } } diff --git a/xr/glimmer/benchmark/src/androidTest/java/androidx/xr/glimmer/benchmark/SurfaceBenchmark.kt b/xr/glimmer/benchmark/src/androidTest/java/androidx/xr/glimmer/benchmark/SurfaceBenchmark.kt index 0193624ece736..7987ef495196c 100644 --- a/xr/glimmer/benchmark/src/androidTest/java/androidx/xr/glimmer/benchmark/SurfaceBenchmark.kt +++ b/xr/glimmer/benchmark/src/androidTest/java/androidx/xr/glimmer/benchmark/SurfaceBenchmark.kt @@ -234,11 +234,12 @@ class SurfaceBenchmark { } /** - * Measures the time to draw the first frame after emitting a [PressInteraction.Press]. This is - * benchmarked on an already-focused surface to isolate the press state change. + * Measures the time to process [PressInteraction.Press] and perform composition, measurement, + * layout, and drawing to render the first frame. This is benchmarked on an already-focused + * surface to isolate the press state change. */ @Test - fun surface_firstFrame_afterPressInteraction() { + fun surface_firstFramePressAnimation() { with(benchmarkRule) { runBenchmarkFor({ SurfaceTestCase(addSurfaceModifierEnabledByDefault = true) }) { runOnUiThread { @@ -248,9 +249,7 @@ class SurfaceBenchmark { val press = PressInteraction.Press(Offset.Zero) measureRepeatedOnUiThread { - runWithMeasurementDisabled { - runBlocking { getTestCase().emitInteraction(press) } - } + runBlocking { getTestCase().emitInteraction(press) } doFrame() @@ -273,11 +272,12 @@ class SurfaceBenchmark { } /** - * Measures the time to draw the first frame after emitting a [PressInteraction.Release]. This - * is benchmarked on an already-focused and pressed surface to isolate the release state change. + * Measures the time to process [PressInteraction.Release] and perform composition, measurement, + * layout, and draw to render the first frame. This is benchmarked on an already-focused and + * pressed surface to isolate the press state change. */ @Test - fun surface_firstFrame_afterReleaseInteraction() { + fun surface_firstFrameReleaseAnimation() { with(benchmarkRule) { runBenchmarkFor({ SurfaceTestCase(addSurfaceModifierEnabledByDefault = true) }) { runOnUiThread { @@ -288,17 +288,15 @@ class SurfaceBenchmark { val press = PressInteraction.Press(Offset.Zero) measureRepeatedOnUiThread { runWithMeasurementDisabled { - runBlocking { - // Emit interaction to start press animation. - getTestCase().emitInteraction(press) - - doFramesUntilNoChangesPending() + // Emit interaction to start press animation. + runBlocking { getTestCase().emitInteraction(press) } - // Emit interaction to trigger release animation - getTestCase().emitInteraction(PressInteraction.Release(press)) - } + doFramesUntilNoChangesPending() } + // Emit interaction to trigger release animation + runBlocking { getTestCase().emitInteraction(PressInteraction.Release(press)) } + doFrame() runWithMeasurementDisabled { diff --git a/xr/scenecore/scenecore-spatial-rendering/build.gradle b/xr/scenecore/scenecore-spatial-rendering/build.gradle index a2c2a16b69dd1..a177a5f58aa7a 100644 --- a/xr/scenecore/scenecore-spatial-rendering/build.gradle +++ b/xr/scenecore/scenecore-spatial-rendering/build.gradle @@ -36,7 +36,7 @@ dependencies { api(project(":xr:scenecore:scenecore-runtime")) implementation("androidx.annotation:annotation:1.8.1") - implementation("com.google.ar:impress:0.0.10") + implementation("com.google.ar:impress:0.0.11") testImplementation(libs.junit) testImplementation(libs.kotlinTest) diff --git a/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/GltfJniMarshallingTest.kt b/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/GltfJniMarshallingTest.kt index f6147b3034cb3..34be80b09cb6b 100644 --- a/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/GltfJniMarshallingTest.kt +++ b/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/GltfJniMarshallingTest.kt @@ -186,6 +186,30 @@ class GltfJniMarshallingTest : BaseJniMarshallingTest() { // This JNI call does not return any data, so the only assertion is on the native side. } + @Test + fun toggleGltfModelAnimation_marshalsParams_invokesOnPause() { + // Set toggle as false to pause the animation. + val expectedToggle = false + ImpressApiTestHelper.nativeSetExpectedToggleGltfModelAnimation(TEST_NODE_ID, expectedToggle) + val node = ImpressNode(TEST_NODE_ID) + + mImpressApi.toggleGltfModelAnimation(node, expectedToggle) + + // This JNI call does not return any data, so the only assertion is on the native side. + } + + @Test + fun toggleGltfModelAnimation_marshalsParams_invokesOnResume() { + // Set toggle as false to pause the animation. + val expectedToggle = true + ImpressApiTestHelper.nativeSetExpectedToggleGltfModelAnimation(TEST_NODE_ID, expectedToggle) + val node = ImpressNode(TEST_NODE_ID) + + mImpressApi.toggleGltfModelAnimation(node, expectedToggle) + + // This JNI call does not return any data, so the only assertion is on the native side. + } + @Test fun getGltfModelBoundingBox_marshalsNodeId_returnsBox() { val expectedCenter = floatArrayOf(1.0f, 2.0f, 3.0f) diff --git a/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/ImpressApiTestHelper.java b/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/ImpressApiTestHelper.java index 7d5c47f97891e..1c8240ffa0cdc 100644 --- a/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/ImpressApiTestHelper.java +++ b/xr/scenecore/scenecore-spatial-rendering/src/androidTest/java/androidx/xr/scenecore/impl/impress/ImpressApiTestHelper.java @@ -57,6 +57,8 @@ static native void nativeSetExpectedAnimateGltfModel( static native void nativeSetExpectedStopGltfModelAnimation(int nodeId); + static native void nativeSetExpectedToggleGltfModelAnimation(int nodeId, boolean toggle); + static native void nativeSetExpectedGetGltfModelLocalBounds(int nodeId); static native void nativeSetGetGltfModelLocalBoundsSuccess(float[] center, float[] halfExtents); diff --git a/xr/scenecore/scenecore-testing/build.gradle b/xr/scenecore/scenecore-testing/build.gradle index 8894e314f82b0..31b0ff6f829d0 100644 --- a/xr/scenecore/scenecore-testing/build.gradle +++ b/xr/scenecore/scenecore-testing/build.gradle @@ -37,7 +37,7 @@ dependencies { api(project(":xr:arcore:arcore-testing")) api(project(":xr:scenecore:scenecore-runtime")) - implementation("com.google.ar:impress:0.0.10") + implementation("com.google.ar:impress:0.0.11") implementation(libs.testExtTruth) implementation("androidx.annotation:annotation:1.8.1") implementation("androidx.concurrent:concurrent-futures:1.0.0")