Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
42406de
Prevent source information stack traces downgrading to group keys
ShikaSD Dec 15, 2025
1f00727
Fix incorrect usage of rememberUpdatedState
andrewbailey Dec 19, 2025
0def1a0
Extract navigation-common hosts tests to common
terrakok Nov 14, 2025
a954958
Update NavEntryDecorator KDoc to use entry.Content()
Jan 14, 2026
e820d3f
CameraPipe FrameBuffer takes 0 capacity
Jan 12, 2026
8dd6cad
Update wear compose demo versionCode = 93 versionName = "1.93"
sravaniva Jan 15, 2026
474f3e4
Fix multiple dataStore instance in the same process.
Jan 15, 2026
1338965
Merge "Update wear compose demo versionCode = 93 versionName = "1.93"…
sravaniva Jan 15, 2026
dd0e8e5
Move AbstractMainTestClock to commonMain
eymar Dec 24, 2025
486c040
Deprecate SafeIterableMap in Arch
marcellogalhardo Jan 13, 2026
23bbcb5
Merge "CameraPipe FrameBuffer takes 0 capacity" into androidx-main
Jan 15, 2026
32e19fe
Merge "Fix multiple dataStore instance in the same process." into and…
Jan 15, 2026
946bf74
Merge "Deprecate SafeIterableMap in Arch" into androidx-main
marcellogalhardo Jan 15, 2026
9260e8e
Merge "Extract navigation-common hosts tests to common" into androidx…
Jan 15, 2026
7494c42
Update Glimmer version
memorenomunoz Jan 15, 2026
11512e2
Merge "Update Glimmer version" into androidx-main
memorenomunoz Jan 15, 2026
17d0c21
Merge "Move AbstractMainTestClock to commonMain" into androidx-main
alexvanyo Jan 15, 2026
d955aaa
Merge "Prevent source information stack traces downgrading to group k…
ShikaSD Jan 15, 2026
ad78d95
Re-map FULLSCREEN to LARGE in Widget params.
Jan 14, 2026
2b38677
Merge "Update NavEntryDecorator KDoc to use entry.Content()" into and…
Jan 15, 2026
ce3243c
Merge "Re-map FULLSCREEN to LARGE in Widget params." into androidx-main
Jan 15, 2026
b717047
Merge "Fix incorrect usage of rememberUpdatedState" into androidx-main
Jan 15, 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
40 changes: 20 additions & 20 deletions arch/core/core-common/api/restricted_current.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
// Signature format: 4.0
package androidx.arch.core.internal {

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class FastSafeIterableMap<K, V> extends androidx.arch.core.internal.SafeIterableMap<K!,V!> {
ctor public FastSafeIterableMap();
method public java.util.Map.Entry<K!,V!>? ceil(K!);
method public boolean contains(K!);
@Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class FastSafeIterableMap<K, V> extends androidx.arch.core.internal.SafeIterableMap<K!,V!> {
ctor @Deprecated public FastSafeIterableMap();
method @Deprecated public java.util.Map.Entry<K!,V!>? ceil(K!);
method @Deprecated public boolean contains(K!);
}

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SafeIterableMap<K, V> implements java.lang.Iterable<java.util.Map.Entry<K!,V!>!> {
ctor public SafeIterableMap();
method public java.util.Iterator<java.util.Map.Entry<K!,V!>!> descendingIterator();
method public java.util.Map.Entry<K!,V!>? eldest();
method protected androidx.arch.core.internal.SafeIterableMap.Entry<K!,V!>? get(K!);
method public java.util.Iterator<java.util.Map.Entry<K!,V!>!> iterator();
method public androidx.arch.core.internal.SafeIterableMap.IteratorWithAdditions iteratorWithAdditions();
method public java.util.Map.Entry<K!,V!>? newest();
method public V! putIfAbsent(K, V);
method public V! remove(K);
method public int size();
@Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SafeIterableMap<K, V> implements java.lang.Iterable<java.util.Map.Entry<K!,V!>!> {
ctor @Deprecated public SafeIterableMap();
method @Deprecated public java.util.Iterator<java.util.Map.Entry<K!,V!>!> descendingIterator();
method @Deprecated public java.util.Map.Entry<K!,V!>? eldest();
method @Deprecated protected androidx.arch.core.internal.SafeIterableMap.Entry<K!,V!>? get(K!);
method @Deprecated public java.util.Iterator<java.util.Map.Entry<K!,V!>!> iterator();
method @Deprecated public androidx.arch.core.internal.SafeIterableMap.IteratorWithAdditions iteratorWithAdditions();
method @Deprecated public java.util.Map.Entry<K!,V!>? newest();
method @Deprecated public V! putIfAbsent(K, V);
method @Deprecated public V! remove(K);
method @Deprecated public int size();
}

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SafeIterableMap.IteratorWithAdditions extends androidx.arch.core.internal.SafeIterableMap.SupportRemove<K!,V!> implements java.util.Iterator<java.util.Map.Entry<K!,V!>!> {
method public boolean hasNext();
method public java.util.Map.Entry<K!,V!>! next();
@Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public class SafeIterableMap.IteratorWithAdditions extends androidx.arch.core.internal.SafeIterableMap.SupportRemove<K!,V!> implements java.util.Iterator<java.util.Map.Entry<K!,V!>!> {
method @Deprecated public boolean hasNext();
method @Deprecated public java.util.Map.Entry<K!,V!>! next();
}

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract static class SafeIterableMap.SupportRemove<K, V> {
ctor public SafeIterableMap.SupportRemove();
@Deprecated @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public abstract static class SafeIterableMap.SupportRemove<K, V> {
ctor @Deprecated public SafeIterableMap.SupportRemove();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
*
* @param <K> Key type
* @param <V> Value type
* @deprecated These are internal legacy utilities and should not be used.
*/
@Deprecated
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public class FastSafeIterableMap<K, V> extends SafeIterableMap<K, V> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
*
* @param <K> Key type
* @param <V> Value type
* @deprecated These are internal legacy utilities and should not be used.
*/
@Deprecated
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public class SafeIterableMap<K, V> implements Iterable<Map.Entry<K, V>> {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The Android Open Source Project
* 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.
Expand All @@ -14,18 +14,17 @@
* limitations under the License.
*/

package androidx.collection;
package androidx.arch.core.internal;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import androidx.arch.core.internal.FastSafeIterableMap;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@SuppressWarnings("deprecation")
@RunWith(JUnit4.class)
public class FastSafeIterableMapTest {
@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2018 The Android Open Source Project
* 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.
Expand All @@ -14,14 +14,12 @@
* limitations under the License.
*/

package androidx.collection;
package androidx.arch.core.internal;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;

import androidx.arch.core.internal.SafeIterableMap;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
Expand All @@ -30,6 +28,7 @@
import java.util.Iterator;
import java.util.Map.Entry;

@SuppressWarnings("deprecation")
@RunWith(JUnit4.class)
public class SafeIterableMapTest {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,23 @@ internal class FrameBufferImpl(
override val frameFlow: SharedFlow<FrameReference> = _frameFlow.asSharedFlow()

init {
require(capacity > 0) { "FrameBuffer capacity must be greater than 0" }
require(capacity >= 0) { "FrameBuffer capacity must be greater than or equal to 0" }
}

private val _size = MutableStateFlow(0)
override val size: StateFlow<Int> = _size.asStateFlow()

override fun onFrameStarted(frameReference: FrameReference) {
// If capacity is 0, emit the reference and exit early.
if (capacity == 0) {
synchronized(lock) {
if (!closed) {
_frameFlow.tryEmit(frameReference)
}
}
return
}

val acquiredFrame = frameReference.tryAcquire()

val entryToAdd: BufferEntry =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,11 @@ class FrameBufferImplTest {
assertThat(frameBuffer.size.value).isEqualTo(0)
}

@Test(expected = IllegalArgumentException::class)
fun initialization_zeroCapacity_throwsException() {
createFrameBuffer(capacity = 0)
@Test
fun initialization_zeroCapacity_initializeSuccessfully() {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.capacity).isEqualTo(0)
}

@Test(expected = IllegalArgumentException::class)
Expand Down Expand Up @@ -225,13 +227,37 @@ class FrameBufferImplTest {
}
}

@Test
fun onFrameStarted_zeroCapacity_doesNotBufferFrame() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)
val frameReference = createTestFrame(1)

// Simulate onFrameStarted being called.
frameBuffer.onFrameStarted(frameReference)
advanceUntilIdle()

// Assert that the buffer size remains 0.
assertThat(frameBuffer.size.value).isEqualTo(0)
assertThat(frameBuffer.peekFirstReference()).isNull()
assertThat(frameBuffer.peekAllReferences()).isEmpty()
}

@Test
fun removeFirstReference_emptyBuffer_returnsNull() =
testScope.runTest {
assertThat(frameBuffer.removeFirstReference()).isNull()
assertThat(frameBuffer.size.value).isEqualTo(0)
}

@Test
fun removeFirstReference_zeroCapacityBuffer_returnsNull() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.removeFirstReference()).isNull()
}

@Test
fun removeFirstReference_removesCorrectFrame_updatesSize() =
testScope.runTest {
Expand Down Expand Up @@ -269,6 +295,14 @@ class FrameBufferImplTest {
assertThat(frameBuffer.size.value).isEqualTo(0)
}

@Test
fun removeLastReference_zeroCapacityBuffer_returnsNull() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.removeLastReference()).isNull()
}

@Test
fun removeLastReference_removesCorrectFrame_updatesSize() =
testScope.runTest {
Expand Down Expand Up @@ -306,6 +340,14 @@ class FrameBufferImplTest {
assertThat(frameBuffer.size.value).isEqualTo(0)
}

@Test
fun removeAllReference_zeroCapacityBuffer_doesNotThowErrors() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

frameBuffer.removeAllReferences()
}

@Test
fun removeAllReferences_returnsAllFramesInOrder_updatesSize() =
testScope.runTest {
Expand Down Expand Up @@ -338,6 +380,14 @@ class FrameBufferImplTest {
fun peekFirstReference_emptyBuffer_returnsNull() =
testScope.runTest { assertThat(frameBuffer.peekFirstReference()).isNull() }

@Test
fun peekFirstReference_zeroCapacityBuffer_returnsNull() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.peekFirstReference()).isNull()
}

@Test
fun peekFirstReference_returnsFrame_doesNotChangeSize() =
testScope.runTest {
Expand Down Expand Up @@ -366,6 +416,14 @@ class FrameBufferImplTest {
fun peekLastReference_emptyBuffer_returnsNull() =
testScope.runTest { assertThat(frameBuffer.peekLastReference()).isNull() }

@Test
fun peekLastReference_zeroCapacityBuffer_returnsNull() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.peekLastReference()).isNull()
}

@Test
fun peekLastReference_returnsFrame_doesNotChangeSize() =
testScope.runTest {
Expand Down Expand Up @@ -396,6 +454,14 @@ class FrameBufferImplTest {
fun peekAllReferences_emptyBuffer_returnsEmptyList() =
testScope.runTest { assertThat(frameBuffer.peekAllReferences()).isEmpty() }

@Test
fun peekAllReference_zeroCapacityBuffer_returnsEmptyList() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)

assertThat(frameBuffer.peekAllReferences()).isEmpty()
}

@Test
fun peekAllReferences_returnsAllFramesInOrder_doesNotChangeSize() =
testScope.runTest {
Expand Down Expand Up @@ -424,6 +490,32 @@ class FrameBufferImplTest {
assertThat(frameBuffer.peekAllReferences()).isEmpty()
}

@Test
fun onFrameAvailable_zeroCapacity_flowEmitted() =
testScope.runTest {
val frameBuffer = createFrameBuffer(capacity = 0)
val frameRef1 = createTestFrame(1)
val ready = CompletableDeferred<Unit>()
val resultsChannel = Channel<FrameReference>(Channel.UNLIMITED)

val job =
backgroundScope.launch {
frameBuffer.frameFlow
.onStart { ready.complete(Unit) }
.collect { frame -> resultsChannel.send(frame) }
}

ready.await()
frameBuffer.onFrameStarted(frameRef1)
advanceUntilIdle()

val receivedFrame = resultsChannel.receive()
assertThat(receivedFrame.frameNumber).isEqualTo(frameRef1.frameNumber)
assertThat(frameBuffer.size.value).isEqualTo(0)
assertThat(frameBuffer.peekFirstReference()).isNull()
job.cancel()
}

@Test
fun onFrameAvailable_flowEmitted() =
testScope.runTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import androidx.compose.runtime.tooling.buildTrace
import androidx.compose.runtime.tooling.findLocation
import androidx.compose.runtime.tooling.findSubcompositionContextGroup
import androidx.compose.runtime.tooling.traceForGroup
import kotlin.collections.plus
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmInline
Expand Down Expand Up @@ -254,7 +253,7 @@ internal class GapComposer(
private var childrenComposing: Int = 0
private var compositionToken: Int = 0

private var sourceMarkersEnabled =
internal var sourceMarkersEnabled =
parentContext.collectingSourceInformation || parentContext.collectingCallByInformation

private val derivedStateObserver =
Expand Down Expand Up @@ -2505,7 +2504,7 @@ internal class GapComposer(
stackTraceForGroup(groupIndex, dataIndex) + parentStackTrace()
} ?: emptyList()

return ComposeStackTrace(stackTrace)
return ComposeStackTrace(stackTrace, sourceMarkersEnabled)
}

@OptIn(ComposeToolingApi::class)
Expand All @@ -2516,7 +2515,8 @@ internal class GapComposer(
addAll(writer.buildTrace())
addAll(reader.buildTrace())
addAll(parentStackTrace())
}
},
sourceMarkersEnabled,
)
} else {
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ private fun Throwable.attachComposeStackTrace(
listOf(head.copy(groupOffset = offset)) + tail
}
}
ComposeStackTrace(trace + parentTrace)
ComposeStackTrace(trace + parentTrace, errorContext.sourceInformationEnabled)
}
}

Expand All @@ -1149,5 +1149,8 @@ private fun OperationErrorContext.withCurrentStackTrace(slots: SlotWriter): Oper
return slots.buildTrace(currentOffset, currentGroup, slots.parent(currentGroup)) +
parentTrace
}

override val sourceInformationEnabled: Boolean
get() = parent.sourceInformationEnabled
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ internal interface OperationArgContainer {

/** Error context to stitch operation execution in case an error is thrown. */
internal interface OperationErrorContext {
/** Whether the stack trace is expected to contain source information. */
val sourceInformationEnabled: Boolean

/**
* Create a stack trace from the root of the enclosing context (composition or slot table) to a
* child of the current group that is located at the slot specified by [currentOffset]. Current
Expand Down
Loading
Loading