Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a51fd19
Recover missing widget mapping from PackageManager in GlanceWearWidge…
Sep 17, 2026
82d7f06
[Showcase] Add more CarProgressBarStyle examples
Sep 11, 2026
0b9ce36
Add RemoteButtonDefaults.buttonWithContainerPainterColors overload
yschimke Sep 7, 2026
5bbe7a2
compose: Don't leak ComputedState dependencies into observing scopes
IgorpetinDev Sep 13, 2026
41504ba
Remove usage of legacyDisableKotlinStrictApiMode in health libraries
liutikas Sep 18, 2026
d9c6da6
Fix debug update broadcast in GlanceWearWidget.triggerUpdateAll
Sep 17, 2026
b6d0469
Upgrade to build tools 37.0.0
liutikas Sep 18, 2026
b34e73b
Upgrade to KSP 2.3.12
liutikas Sep 19, 2026
39da586
Sort required properties in A2uiObjectSchema JSON serialization
Sep 20, 2026
4b391d5
Revert "Migrate trivial derived states to computed states"
garg-lucifer Sep 21, 2026
842e9d6
Restore androidx.media docs
icbaker Sep 18, 2026
384eb37
Expose RemoteState non-composable constructors
yschimke Sep 17, 2026
a87f7e0
Merge "[Showcase] Add more CarProgressBarStyle examples" into android…
Sep 21, 2026
9b35374
Merge "Restore androidx.media docs" into androidx-main
Sep 21, 2026
d20bae6
Merge "Upgrade to build tools 37.0.0" into androidx-main
Sep 21, 2026
c7006a0
Remove explicit setting of Kotlin 2.2 target
liutikas Sep 21, 2026
92d264f
Merge "Upgrade to KSP 2.3.12" into androidx-main
liutikas Sep 21, 2026
d18b0f4
Fix RcPlayerState updateTime and warn on reserved system variable IDs
yschimke Sep 18, 2026
81d538e
Support MultiClickModifier and collapse GONE components to 0x0
yschimke Sep 21, 2026
deb3f1a
Merge "Remove explicit setting of Kotlin 2.2 target" into androidx-main
Sep 21, 2026
656a184
Merge "Revert "Migrate trivial derived states to computed states"" in…
garg-lucifer Sep 21, 2026
4dfd668
Pin to more stable dependencies where possible
liutikas Sep 21, 2026
0bb6f16
Rename useSafeFallbackRendererVersion to useBaselineHostVersion
Sep 18, 2026
8afe1b8
Merge "Expose RemoteState non-composable constructors" into androidx-…
yschimke Sep 21, 2026
581a46d
Validate inline image bounds on older SDK levels
PierluigiFimiano Sep 21, 2026
f6820e2
Merge "Pin to more stable dependencies where possible" into androidx-…
Sep 21, 2026
0fc5205
Merge "Validate inline image bounds on older SDK levels" into android…
Sep 21, 2026
115eb4d
Merge "Add RemoteButtonDefaults.buttonWithContainerPainterColors over…
yschimke Sep 21, 2026
a4d2df0
Merge "Fix RcPlayerState updateTime and warn on reserved system varia…
yschimke Sep 21, 2026
bb06eb1
Merge "Support MultiClickModifier and collapse GONE components to 0x0…
yschimke Sep 21, 2026
ff8988e
Merge "Sort required properties in A2uiObjectSchema JSON serializatio…
Sep 21, 2026
3fac28c
Merge "Rename useSafeFallbackRendererVersion to useBaselineHostVersio…
Sep 21, 2026
d9c3911
Merge "Remove usage of legacyDisableKotlinStrictApiMode in health lib…
liutikas Sep 21, 2026
b7b6859
Merge "compose: Don't leak ComputedState dependencies into observing …
ShikaSD Sep 21, 2026
b0e5f9f
Merge changes I22d3f064,I09eed04c into androidx-main
Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public constructor(
put(KEY_TYPE, TYPE_OBJECT)
put(KEY_PROPERTIES, JsonObject(properties.mapValues { it.value.toJsonElement() }))
if (required.isNotEmpty()) {
put(KEY_REQUIRED, JsonArray(required.map { JsonPrimitive(it) }))
put(KEY_REQUIRED, JsonArray(required.sorted().map { JsonPrimitive(it) }))
}
if (!isAdditionalPropertiesAllowed) {
put(KEY_ADDITIONAL_PROPERTIES, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.test.assertFailsWith
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.put
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
Expand Down Expand Up @@ -75,6 +78,28 @@ class A2uiObjectSchemaTest {
assertThat(Json.parseToJsonElement(schema.toJsonSchema())).isEqualTo(expected)
}

@Test
fun toJsonSchema_withMultipleRequiredProperties_serializesRequiredInAlphabeticalOrder() {
val schema =
A2uiObjectSchema(
properties =
mapOf(
"zebra" to A2uiBooleanSchema(),
"alpha" to A2uiBooleanSchema(),
"middle" to A2uiBooleanSchema(),
),
// Pass in non-alphabetical order to ensure sorting occurs regardless of input set
// iteration order
required = linkedSetOf("zebra", "alpha", "middle"),
)

val jsonElement = Json.parseToJsonElement(schema.toJsonSchema()) as JsonObject
val requiredArray = jsonElement[REQUIRED_FIELD] as JsonArray
val requiredList = requiredArray.map { it.jsonPrimitive.content }

assertThat(requiredList).containsExactly("alpha", "middle", "zebra").inOrder()
}

@Test
fun toJsonSchema_withEmptyRequired_doesNotIncludeRequiredField() {
val schema =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.gradle.api.file.FileCollection

/** AndroidX configuration backed by Gradle properties. */
abstract class AndroidConfigImpl(private val project: Project) : AndroidConfig {
override val buildToolsVersion: String = "36.0.0"
override val buildToolsVersion: String = "37.0.0"

override val compileSdk: Int by lazy {
val sdkString = project.extraPropertyOrNull(COMPILE_SDK)?.toString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import androidx.car.app.model.Header
import androidx.car.app.model.Row
import androidx.car.app.model.RowSection
import androidx.car.app.model.SectionedItemTemplate
import androidx.car.app.model.StrokeCap
import androidx.car.app.model.Template
import androidx.car.app.sample.showcase.common.R
import androidx.core.graphics.drawable.IconCompat
Expand Down Expand Up @@ -64,6 +65,7 @@ class ProgressBarDemoScreen(carContext: CarContext) : Screen(carContext) {
.addSection(createRegularRowsSection())
.addSection(createRowConfigurationsSection())
.addSection(createColoredRowsSection())
.addSection(createStrokeCapRowsSection())
.addSection(createGridSection(GridSection.ITEM_SIZE_SMALL))
.addSection(createGridSection(GridSection.ITEM_SIZE_MEDIUM))
.addSection(createGridSection(GridSection.ITEM_SIZE_LARGE))
Expand Down Expand Up @@ -102,20 +104,89 @@ class ProgressBarDemoScreen(carContext: CarContext) : Screen(carContext) {
val colors = listOf(CarColor.RED, CarColor.GREEN, CarColor.BLUE, CarColor.YELLOW)
val colorNames = listOf("Red", "Green", "Blue", "Yellow")

val rows =
val coloredRows =
colors.zip(colorNames).map { (color, name) ->
Row.Builder()
.setTitle("$name Progress Bar Row")
.addText("Colored progress bar example")
.setImage(testImage, Row.IMAGE_TYPE_LARGE)
.setProgressBar(
CarProgressBar.Builder(0.5f)
.setStyle(CarProgressBarStyle.Builder().setColor(color).build())
.setStyle(
CarProgressBarStyle.Builder()
.setColor(color)
.setTrackColor(color)
.build()
)
.build()
)
.build()
}

// Track color examples
val trackColoredRows =
listOf(
Row.Builder()
.setTitle("Green Progress Bar Row with Blue Track")
.addText("Colored progress bar example")
.setImage(testImage, Row.IMAGE_TYPE_LARGE)
.setProgressBar(
CarProgressBar.Builder(0.5f)
.setStyle(
CarProgressBarStyle.Builder()
.setColor(CarColor.GREEN)
.setTrackColor(CarColor.BLUE)
.build()
)
.build()
)
.build(),
Row.Builder()
.setTitle("Red Progress Bar Row with Yellow Track")
.addText("Colored progress bar example")
.setImage(testImage, Row.IMAGE_TYPE_LARGE)
.setProgressBar(
CarProgressBar.Builder(0.5f)
.setStyle(
CarProgressBarStyle.Builder()
.setColor(CarColor.RED)
.setTrackColor(CarColor.YELLOW)
.build()
)
.build()
)
.build(),
)

return RowSection.Builder()
.setTitle("Colored Progress Bars")
.setItems(coloredRows + trackColoredRows)
.build()
}

private fun createStrokeCapRowsSection(): RowSection {
val strokeCaps =
listOf(
StrokeCap.DEFAULT,
StrokeCap.ROUND,
StrokeCap.SQUARE,
)
val strokeCapNames = listOf("System default", "Round", "Square")

val rows =
strokeCaps.zip(strokeCapNames).map { (strokeCap, name) ->
Row.Builder()
.setTitle("$name Stroke Cap Progress Bar Row")
.addText("Custom shaped progress bar example")
.setImage(testImage, Row.IMAGE_TYPE_LARGE)
.setProgressBar(
CarProgressBar.Builder(0.5f)
.setStyle(CarProgressBarStyle.Builder().setStrokeCap(strokeCap).build())
.build()
)
.build()
}
return RowSection.Builder().setTitle("Colored Progress Bars").setItems(rows).build()
return RowSection.Builder().setTitle("Shaped Progress Bars").setItems(rows).build()
}

private fun createGridSection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
Expand Down Expand Up @@ -1377,7 +1376,7 @@ protected constructor(
// target change.
val runFrameLoop by
remember(this) {
computedStateOf {
derivedStateOf {
this.targetState != currentState || isRunning || updateChildrenNeeded
}
}
Expand Down Expand Up @@ -2124,8 +2123,8 @@ public inline fun <S, T, V : AnimationVector> Transition<S>.animateValue(
// recomposition for both the first and second frame of the animation. As a temporary
// workaround, `derivedStateOf` is added here to avoid recomposing when the state value is the
// same.
val targetValue = targetValueByState(remember(this) { computedStateOf { targetState } }.value)
val animationSpec = transitionSpec(remember(this) { computedStateOf { segment } }.value)
val targetValue = targetValueByState(remember(this) { derivedStateOf { targetState } }.value)
val animationSpec = transitionSpec(remember(this) { derivedStateOf { segment } }.value)

return createTransitionAnimation(initialValue, targetValue, animationSpec, typeConverter, label)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import androidx.compose.animation.core.repeatable
import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
Expand Down Expand Up @@ -238,7 +238,7 @@ private class PathPropertyValues : PropertyValues<List<PathNode>>() {
if (atEnd) overallDuration.toFloat() else 0f
}
@Suppress("UnrememberedMutableState") // b/279909531
return computedStateOf { interpolate(timeState.value) }
return derivedStateOf { interpolate(timeState.value) }
}

private fun interpolate(timeMillis: Float): List<PathNode> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
Expand Down Expand Up @@ -145,7 +145,7 @@ private class SplineKeyframesPlaygroundModel(private val scope: CoroutineScope)
private val pointCount = 6
private val animatedOffset = Animatable(Offset.Zero, Offset.VectorConverter)
private val anchors = mutableStateListOf<Offset>()
private val anchorCount by computedStateOf { anchors.size }
private val anchorCount by derivedStateOf { anchors.size }

// Note that this is not the duration per keyframe, just an arbitrary number so that the total
// duration scales with number of anchors
Expand All @@ -155,7 +155,7 @@ private class SplineKeyframesPlaygroundModel(private val scope: CoroutineScope)
private val samplePoints = mutableListOf<Offset>()
private val sampleCount = 100

val totalDuration by computedStateOf { anchors.size * durationPerAnchor.floatValue }
val totalDuration by derivedStateOf { anchors.size * durationPerAnchor.floatValue }

private var isInit = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.runtime.Composable
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -825,12 +825,15 @@ internal fun <T> AnimatedEnterExitImpl(

val shouldDisposeAfterExit by
remember(childTransition, shouldDisposeBlock) {
computedStateOf {
childTransition.exitFinished &&
derivedStateOf {
if (childTransition.exitFinished) {
shouldDisposeBlock(
childTransition.currentState,
childTransition.targetState,
)
} else {
false
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions compose/foundation/foundation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ androidXMultiplatform {
androidMain.dependencies {
api("androidx.annotation:annotation:1.8.1")
api("androidx.annotation:annotation-experimental:1.4.1")
implementation("androidx.emoji2:emoji2:1.7.0-rc01")
implementation("androidx.emoji2:emoji2:1.7.0")
implementation("androidx.core:core:1.13.1")
}

Expand All @@ -73,7 +73,7 @@ androidXMultiplatform {
implementation("androidx.activity:activity-compose:1.3.1")
implementation("androidx.lifecycle:lifecycle-runtime:2.10.0")
implementation("androidx.savedstate:savedstate:1.2.1")
implementation("androidx.emoji2:emoji2-bundled:1.7.0-rc01")
implementation("androidx.emoji2:emoji2-bundled:1.7.0")

implementation(libs.testUiautomator)
implementation(libs.testRules)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.annotation.FrequentlyChangingValue
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
Expand Down Expand Up @@ -178,9 +178,9 @@ public class ScrollState(initial: Int) : ScrollableState {
override val isScrollInProgress: Boolean
get() = scrollableState.isScrollInProgress

override val canScrollForward: Boolean by computedStateOf { value < maxValue }
override val canScrollForward: Boolean by derivedStateOf { value < maxValue }

override val canScrollBackward: Boolean by computedStateOf { value > 0 }
override val canScrollBackward: Boolean by derivedStateOf { value > 0 }

@get:Suppress("GetterSetterNames")
override val lastScrolledForward: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.lazy.layout.LazyLayoutSemanticState
import androidx.compose.foundation.lazy.layout.estimatedLazyMaxScrollOffset
import androidx.compose.foundation.lazy.layout.estimatedLazyScrollOffset
import androidx.compose.runtime.computedStateOf
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.ui.semantics.CollectionInfo

Expand All @@ -31,7 +31,7 @@ internal fun LazyLayoutSemanticState(
object : LazyLayoutSemanticState {

// The total number of items in the list, derived from layout info.
private val totalItemsCount by computedStateOf { state.layoutInfo.totalItemsCount }
private val totalItemsCount by derivedStateOf { state.layoutInfo.totalItemsCount }

override val scrollOffset: Float
get() =
Expand Down
Loading
Loading