Status Update
Comments
di...@gmail.com <di...@gmail.com> #2
Branch: androidx-main
commit a330c0d3bcdd41326f37968a60e6084ad4a2e32c
Author: Chet Haase <chet@google.com>
Date: Wed Jul 05 07:26:46 2023
Convert APIs using PointF to use Float instead
PointF is a convenient mechanism for passing around x.y values
representing 2D points. But there are downsides, including:
- Converting to PointF: You may not have the data in PointF form
to begin with, so using an API which takes PointF requires converting
the data to that form (including allocating a PointF object every time)
- Mutability: Point structures can be mutated internally, causing
unpredictability in what that mutation means. Should the library
react to those changes? Ignore them? Do defensive copies (requiring
even more allocations)? Using primitive types like Float make the
behavior more obvious (by making the data inherently immutable).
- Allocations: Whenever we use object types, there are necessarily
allocations on the Java heap for them. This puts pressure on the GC
at both allocation and collection time. Given the amount of points
being passed around (especially at morph creation time, when curves
are being split and created), this causes a lot of PointF objects to
be allocated (even temporarily). Using Float avoids that problem.
Also fixed bug with unclosed paths causing discontinuity at the
start/end point.
Bug: 276466399
Bug: 290254314
Test: integration and unit tests pass
Relnote: PointF parameters changed to Float pairs
Change-Id: Id4705d27c7be31b26ade8186b99fffe2e2f8450e
M graphics/graphics-shapes/api/current.txt
M graphics/graphics-shapes/api/restricted_current.txt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicShapeTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonMeasureTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/ShapesTest.kt
M graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Cubic.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CubicShape.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FeatureMapping.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FloatMapping.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Morph.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/PolygonMeasure.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Shapes.kt
M graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Utils.kt
M graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt
M graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt
M graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/MaterialShapes.kt
ma...@google.com <ma...@google.com> #3
sg...@google.com <sg...@google.com> #4
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.graphics:graphics-shapes:1.0.0-alpha04
di...@gmail.com <di...@gmail.com> #5
On my end, I discovered it was caused by division by zero and just set the bar to indeterminate in that case.
mo...@gmail.com <mo...@gmail.com> #6
I also experience this crash in our released app, I can reproduce this with both Material2 and Material3 with latest stable and alpha-versions, but only with enabled Talkback-service.
Since this crash only happens with enabled Talkback-service and the app works fine otherwise, I consider this to be a bug in the interaction between Talkback and the participating Material-compose frameworks.
build.gradle:
implementation "androidx.compose.material:material:1.8.0-alpha08"
implementation "androidx.compose.material3:material3:1.4.0-alpha06"
Minimal reproducible examples:
@Preview
@Composable
private fun MinimalReproducibleExampleM2Preview() {
androidx.compose.material.LinearProgressIndicator(
modifier =
Modifier
.fillMaxWidth()
.height(12.dp),
progress = 0f / 0f,
)
}
@Preview
@Composable
private fun MinimalReproducibleExampleM3Preview() {
androidx.compose.material3.LinearProgressIndicator(
modifier =
Modifier
.fillMaxWidth()
.height(12.dp),
progress = { 0f / 0f },
)
}
Crash in Material2:
FATAL EXCEPTION: main (Ask Gemini)
Process: de.billiger.android, PID: 416
java.lang.IllegalArgumentException: current must not be NaN
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:662)
at androidx.compose.foundation.ProgressSemanticsKt$progressSemantics$1.invoke(ProgressSemantics.kt:53)
at androidx.compose.foundation.ProgressSemanticsKt$progressSemantics$1.invoke(ProgressSemantics.kt:51)
at androidx.compose.ui.semantics.CoreSemanticsModifierNode.applySemantics(SemanticsModifier.kt:59)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:442)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:433)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2496)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:460)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:244)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeSemanticsReads$ui_release(OwnerSnapshotObserver.kt:121)
at androidx.compose.ui.node.LayoutNode.getCollapsedSemantics$ui_release(LayoutNode.kt:433)
at androidx.compose.ui.semantics.SemanticsNodeKt.SemanticsNode(SemanticsNode.kt:49)
at androidx.compose.ui.semantics.SemanticsNode.fillOneLayerOfSemanticsWrappers(SemanticsNode.kt:278)
at androidx.compose.ui.semantics.SemanticsNode.unmergedChildren$ui_release(SemanticsNode.kt:257)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release(SemanticsNode.kt:338)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release$default(SemanticsNode.kt:322)
at androidx.compose.ui.semantics.SemanticsNode.getReplacedChildren$ui_release(SemanticsNode.kt:305)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap$findAllSemanticNodesRecursive(SemanticsUtils.android.kt:195)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap(SemanticsUtils.android.kt:230)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.getCurrentSemanticsNodes(AndroidComposeViewAccessibilityDelegateCompat.android.kt:311)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.createEvent(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1577)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1519)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView$default(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1509)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendSubtreeChangeAccessibilityEvents(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2377)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.boundsUpdatesEventLoop$ui_release(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2251)
at androidx.compose.ui.platform.AndroidComposeView.boundsUpdatesAccessibilityEventLoop(AndroidComposeView.android.kt:1639)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$1$1.invokeSuspend(Wrapper.android.kt:148)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309) (Ask Gemini)
at android.view.Choreographer.doCallbacks(Choreographer.java:923)
at android.view.Choreographer.doFrame(Choreographer.java:847)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@93d2fd8, androidx.compose.runtime.BroadcastFrameClock@cb15f31, StandaloneCoroutine{Cancelling}@36ca616, AndroidUiDispatcher@ae19b97]
Crash in Material3:
FATAL EXCEPTION: main (Ask Gemini)
Process: de.billiger.android, PID: 4219
java.lang.IllegalArgumentException: current must not be NaN
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:662)
at androidx.compose.ui.semantics.ProgressBarRangeInfo.<init>(SemanticsProperties.kt:655)
at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$3$1.invoke(ProgressIndicator.kt:156)
at androidx.compose.material3.ProgressIndicatorKt$LinearProgressIndicator$3$1.invoke(ProgressIndicator.kt:155)
at androidx.compose.ui.semantics.CoreSemanticsModifierNode.applySemantics(SemanticsModifier.kt:59)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:442)
at androidx.compose.ui.node.LayoutNode$collapsedSemantics$1.invoke(LayoutNode.kt:433)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2496)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:460)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:244)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeSemanticsReads$ui_release(OwnerSnapshotObserver.kt:121)
at androidx.compose.ui.node.LayoutNode.getCollapsedSemantics$ui_release(LayoutNode.kt:433)
at androidx.compose.ui.semantics.SemanticsNodeKt.SemanticsNode(SemanticsNode.kt:49)
at androidx.compose.ui.semantics.SemanticsNode.fillOneLayerOfSemanticsWrappers(SemanticsNode.kt:278)
at androidx.compose.ui.semantics.SemanticsNode.unmergedChildren$ui_release(SemanticsNode.kt:257)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release(SemanticsNode.kt:338)
at androidx.compose.ui.semantics.SemanticsNode.getChildren$ui_release$default(SemanticsNode.kt:322)
at androidx.compose.ui.semantics.SemanticsNode.getReplacedChildren$ui_release(SemanticsNode.kt:305)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap$findAllSemanticNodesRecursive(SemanticsUtils.android.kt:195)
at androidx.compose.ui.platform.SemanticsUtils_androidKt.getAllUncoveredSemanticsNodesToIntObjectMap(SemanticsUtils.android.kt:230)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.getCurrentSemanticsNodes(AndroidComposeViewAccessibilityDelegateCompat.android.kt:311)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.createEvent(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1577)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1519)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendEventForVirtualView$default(AndroidComposeViewAccessibilityDelegateCompat.android.kt:1509)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.sendSubtreeChangeAccessibilityEvents(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2377)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.boundsUpdatesEventLoop$ui_release(AndroidComposeViewAccessibilityDelegateCompat.android.kt:2251)
at androidx.compose.ui.platform.AndroidComposeView.boundsUpdatesAccessibilityEventLoop(AndroidComposeView.android.kt:1639)
at androidx.compose.ui.platform.WrappedComposition$setContent$1$1$1$1.invokeSuspend(Wrapper.android.kt:148)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:68) (Ask Gemini)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1299)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
at android.view.Choreographer.doCallbacks(Choreographer.java:923)
at android.view.Choreographer.doFrame(Choreographer.java:847)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8762)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@f9ecebb, androidx.compose.runtime.BroadcastFrameClock@93d2fd8, StandaloneCoroutine{Cancelling}@cb15f31, AndroidUiDispatcher@36ca616]
sg...@google.com <sg...@google.com>
ap...@google.com <ap...@google.com> #7
Project: platform/frameworks/support
Branch: androidx-main
Author: Shalom Gibly <
Link:
Prevent a crash when Float.NaN is a progress value
Expand for full commit details
Prevent a crash when Float.NaN is a progress value
- Check for a NaN value and return zero if a progress lambda is
producing it and passing it into a `ProgressBarRangeInfo`. The range
info will throw an exception if a NaN is passed in.
- Applied the check at the progress indicators (M3 & M2), and at the
loading indicator.
- The remaining implementation does not cras on NaN, but the UI usually
does not render anything.
- Also, switched to use `fastCoerceIn` instead of `coerceIn`.
Test: Added
Fixes: 352364576
Relnote: "Fixed a crash at the progress and loading indicators in case a
Float.NaN is passed in as a progress."
Change-Id: I4fa969a1d46358a6f1db8b28cb0a375a809102c2
Files:
- M
compose/material/material/src/commonMain/kotlin/androidx/compose/material/ProgressIndicator.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/LoadingIndicatorTest.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/ProgressIndicatorTest.kt
- M
compose/material3/material3/src/androidInstrumentedTest/kotlin/androidx/compose/material3/WavyProgressIndicatorTest.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/LoadingIndicator.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/ProgressIndicator.kt
- M
compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/WavyProgressIndicator.kt
Hash: bf90726d0c7fadd916c5c8bf38b18f6a9a5d7a6b
Date: Wed Jan 22 16:28:41 2025
ar...@gmail.com <ar...@gmail.com> #8
pr...@google.com <pr...@google.com> #9
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.compose.material3:material3:1.4.0-alpha08
androidx.compose.material3:material3-android:1.4.0-alpha08
androidx.compose.material3:material3-jvmstubs:1.4.0-alpha08
androidx.compose.material3:material3-linuxx64stubs:1.4.0-alpha08
Description
Jetpack Compose version: androidx.compose:compose-bom:2024.06.00
Material Library Version (M2, M3 or Both?): M3
Material Compose component used: androidx.compose.material3:material3
Android Studio Build: 2024.1.1
Kotlin version: 1.9.24
Passing NaN to LinearProgressIndicator will cause the following crash; seems that coercedProgress() does not handle NaNs.