Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,7 @@ fun configureDarwinFlags(project: Project) {
if (isIOS) addAll(iosFlags)
}

// TODO: Remove when the issue is fixed in KGP
// https://youtrack.jetbrains.com/issue/KT-74564
// it.freeCompilerArgs += flags
//
// Fixes problem when instrumented tests compilation is not properly applied to
// the framework configuration.
it.linkTaskProvider.configure {
@Suppress("DEPRECATION")
it.kotlinOptions.freeCompilerArgs += flags
}
it.freeCompilerArgs += flags
}
}
project.multiplatformExtension!!.run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ internal fun Project.originalToRedirectedDependency(
val redirecting = project.artifactRedirection() ?: return@flatMap emptyList()
redirecting.targetNames.filter { it.isNotEmpty() }.map {
val group = project.group.toString()
val name = project.name.toString()
val name = project.name
val target = it
val original = DefaultModuleIdentifier.newId(group, "$name-$target")
val redirected = DefaultModuleVersionIdentifier.newId(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ internal fun Project.configureDependencyVerification() {
.filter { !it.name.contains("test", ignoreCase = true) }
.flatMap { compilation ->
listOf(
compilation.implementationConfigurationName,
compilation.apiConfigurationName,
compilation.runtimeOnlyConfigurationName
compilation.defaultSourceSet.implementationConfigurationName,
compilation.defaultSourceSet.apiConfigurationName,
compilation.defaultSourceSet.runtimeOnlyConfigurationName
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@ enum class KotlinTarget(val apiVersion: KotlinVersion, val catalogVersion: Strin
KOTLIN_2_0(KotlinVersion.KOTLIN_2_0, "kotlin20"),
KOTLIN_2_1(KotlinVersion.KOTLIN_2_1, "kotlin21"),
KOTLIN_2_2(KotlinVersion.KOTLIN_2_2, "kotlin22"),
KOTLIN_2_3(KotlinVersion.KOTLIN_2_3, "kotlin23"),
DEFAULT(JETBRAINS_COMPILE_KOTLIN_VERSION),
LATEST(KOTLIN_2_2);
LATEST(KOTLIN_2_3);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kotlin change usually breaks our TeamCity. Did we run it? If not, let's run.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make it green, we need to update Kotlin version in compose-multiplatform too. I'll make a PR for that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still need to run CI before merge, to avoid mid-breakages.

To do this, we need to have the same branch name in 2 repos.

Copy link
Collaborator

@igordmn igordmn Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do this, we need to have the same branch name in 2 repos.

Or just merge that PR first, also works, indeed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more update in compose-multiplatform - JetBrains/compose-multiplatform#5536


constructor(
kotlinTarget: KotlinTarget
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/shared.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tasks.withType(KotlinCompile).configureEach { task ->
if (task.path == ":imports:binary-compatibility-validator:compileKotlin") {
friendPaths.from(configurations.friends.incoming.files)
}
languageVersion.set(KotlinVersion.KOTLIN_2_0)
apiVersion.set(KotlinVersion.KOTLIN_2_0)
languageVersion.set(KotlinVersion.KOTLIN_2_1)
apiVersion.set(KotlinVersion.KOTLIN_2_1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<application
android:allowBackup="false"
android:label="Animation Benchmark Target"
android:supportsRtl="true"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
<activity
android:name=".SeekableTransitionInterrupt"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<profileable
android:shell="true"
tools:targetApi="29" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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.animation.benchmark.target

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.animateColor
import androidx.compose.animation.core.SeekableTransitionState
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.rememberTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.material.Text
import androidx.compose.material3.Button
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
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.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class SeekableTransitionInterrupt : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { SeekableTransitionInterruptDemo() }
}
}

@Composable
fun SeekableTransitionInterruptDemo() {
var isToggled by remember { mutableStateOf(false) }

val seekableState = remember { SeekableTransitionState(isToggled) }
val scope = rememberCoroutineScope()

val transition = rememberTransition(seekableState, label = "DemoTransition")

val size by transition.animateDp(label = "Size") { state -> if (state) 200.dp else 100.dp }
val color by
transition.animateColor(label = "Color") { state -> if (state) Color.Red else Color.Blue }

Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box(modifier = Modifier.size(size).background(color))

Button(
onClick = {
isToggled = !isToggled

scope.launch {
seekableState.snapTo(!isToggled)

val animationJob = launch {
seekableState.animateTo(
targetState = isToggled,
animationSpec = tween(2000),
)
}

delay(500)

seekableState.seekTo(fraction = 0.3f, targetState = isToggled)

animationJob.cancel()
}
}
) {
Text("interrupt animation w/ seekTo")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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.animation.macrobenchmark

import androidx.benchmark.macro.ExperimentalMetricApi
import androidx.benchmark.macro.FrameTimingMetric
import androidx.benchmark.macro.MemoryUsageMetric
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObject2
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

/**
* This benchmark measures the cost of interrupting an animation with a seekTo for
* [SeekableTransition]. Before running this benchmark, switch the target app's active build variant
* to "benchmark" in Android Studio.
*/
@RunWith(AndroidJUnit4::class)
class SeekableTransitionInterruptMacrobenchmark {
@get:Rule val benchmarkRule = MacrobenchmarkRule()

@OptIn(ExperimentalMetricApi::class)
@Test
fun clickInterrupt() {
lateinit var button: UiObject2
benchmarkRule.measureRepeated(
packageName = "androidx.compose.animation.benchmark.target",
metrics = listOf(FrameTimingMetric(), MemoryUsageMetric(MemoryUsageMetric.Mode.Max)),
iterations = 10,
// Warm startup simulates a user interacting with an app that's already warmed up
startupMode = StartupMode.WARM,
setupBlock = {
pressHome()
startActivityAndWait()
val buttonText = "interrupt animation w/ seekTo"
button = device.findObject(By.text(buttonText))
},
) {
button.click()

device.waitForIdle()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2025 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.animation.benchmark

import androidx.benchmark.junit4.BenchmarkRule
import androidx.benchmark.junit4.measureRepeated
import androidx.compose.animation.core.SeekableTransitionState
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@LargeTest
@RunWith(AndroidJUnit4::class)
class SeekableTransitionBenchmark {

@get:Rule val benchmarkRule = BenchmarkRule()

private enum class State {
Visible,
Gone,
}

/** Measures the cost of creating a new instance of [SeekableTransitionState]. */
@Test
fun instantiation() {
benchmarkRule.measureRepeated { SeekableTransitionState(State.Visible) }
}

/** Measures the cost of using seekTo for a [SeekableTransitionState]. */
@Test
fun seekTo() {
val seekableState = SeekableTransitionState(State.Visible)
runBlocking {
seekableState.snapTo(State.Visible)
seekableState.seekTo(fraction = 0.1f, targetState = State.Gone)
}
benchmarkRule.measureRepeated {
runBlocking {
val fraction = if (seekableState.fraction > 0.4f) 0.2f else 0.5f
seekableState.seekTo(fraction)
}
}
}
}
Loading