Skip to content

Commit 012c074

Browse files
committed
feat: Mechanics
1 parent 8721978 commit 012c074

File tree

142 files changed

+33586
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+33586
-0
lines changed

mechanics/Android.bp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (C) 2024 The Android Open Source Project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package {
16+
default_team: "trendy_team_motion",
17+
default_applicable_licenses: ["Android-Apache-2.0"],
18+
}
19+
20+
android_library {
21+
name: "mechanics",
22+
manifest: "AndroidManifest.xml",
23+
sdk_version: "system_current",
24+
min_sdk_version: "31",
25+
static_libs: [
26+
"androidx.compose.runtime_runtime",
27+
"androidx.compose.material3_material3",
28+
"androidx.compose.ui_ui-util",
29+
"androidx.compose.foundation_foundation-layout",
30+
],
31+
srcs: [
32+
"src/**/*.kt",
33+
],
34+
kotlincflags: ["-Xjvm-default=all"],
35+
}

mechanics/AndroidManifest.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="utf-8"?><!--
2+
Copyright (C) 2024 The Android Open Source Project
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
18+
package="com.android.mechanics">
19+
</manifest>

mechanics/TEST_MAPPING

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"presubmit": [
3+
{
4+
"name": "mechanics_tests",
5+
"options": [
6+
{"exclude-annotation": "org.junit.Ignore"},
7+
{"exclude-annotation": "androidx.test.filters.FlakyTest"}
8+
]
9+
},
10+
{
11+
"name": "SystemUIGoogleTests",
12+
"options": [
13+
{"exclude-annotation": "org.junit.Ignore"},
14+
{"exclude-annotation": "androidx.test.filters.FlakyTest"}
15+
]
16+
},
17+
{
18+
"name": "PlatformComposeSceneTransitionLayoutTests"
19+
},
20+
{
21+
"name": "PlatformComposeCoreTests"
22+
}
23+
],
24+
"presubmit-large": [
25+
{
26+
"name": "SystemUITests",
27+
"options": [
28+
{"exclude-annotation": "org.junit.Ignore"},
29+
{"exclude-annotation": "androidx.test.filters.FlakyTest"}
30+
]
31+
}
32+
],
33+
"wm-cf": [
34+
{
35+
"name": "WMShellUnitTests"
36+
}
37+
]
38+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
4+
5+
<!--
6+
Important: disable debugging for accurate performance results
7+
8+
In a com.android.library project, this flag must be disabled from this
9+
manifest, as it is not possible to override this flag from Gradle.
10+
-->
11+
<application
12+
android:debuggable="false"
13+
tools:ignore="HardcodedDebugMode"
14+
tools:replace="android:debuggable" />
15+
</manifest>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile
22+
23+
-dontobfuscate
24+
25+
-ignorewarnings
26+
27+
-keepattributes *Annotation*
28+
29+
-dontnote junit.framework.**
30+
-dontnote junit.runner.**
31+
32+
-dontwarn androidx.test.**
33+
-dontwarn org.junit.**
34+
-dontwarn org.hamcrest.**
35+
-dontwarn com.squareup.javawriter.JavaWriter
36+
37+
-keepclasseswithmembers @org.junit.runner.RunWith public class *
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright (C) 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.android.mechanics.benchmark
18+
19+
import androidx.benchmark.junit4.BenchmarkRule
20+
import androidx.benchmark.junit4.measureRepeated
21+
import androidx.compose.animation.core.Animatable
22+
import androidx.compose.runtime.mutableFloatStateOf
23+
import androidx.compose.runtime.snapshotFlow
24+
import androidx.compose.runtime.snapshots.Snapshot
25+
import androidx.compose.ui.util.fastForEach
26+
import androidx.test.ext.junit.runners.AndroidJUnit4
27+
import kotlinx.coroutines.flow.launchIn
28+
import kotlinx.coroutines.flow.onEach
29+
import kotlinx.coroutines.launch
30+
import org.junit.Rule
31+
import org.junit.Test
32+
import org.junit.runner.RunWith
33+
import platform.test.motion.compose.runMonotonicClockTest
34+
35+
/** Benchmark, which will execute on an Android device. Previous results: go/mm-microbenchmarks */
36+
@RunWith(AndroidJUnit4::class)
37+
class ComposeBaselineBenchmark {
38+
@get:Rule val benchmarkRule = BenchmarkRule()
39+
40+
// Compose specific
41+
42+
@Test
43+
fun writeState_1snapshotFlow() = runMonotonicClockTest {
44+
val composeState = mutableFloatStateOf(0f)
45+
46+
var lastRead = 0f
47+
snapshotFlow { composeState.floatValue }.onEach { lastRead = it }.launchIn(backgroundScope)
48+
49+
benchmarkRule.measureRepeated {
50+
composeState.floatValue++
51+
Snapshot.sendApplyNotifications()
52+
testScheduler.advanceTimeBy(16)
53+
}
54+
55+
check(lastRead == composeState.floatValue) {
56+
"snapshotFlow lastRead $lastRead != ${composeState.floatValue} (current composeState)"
57+
}
58+
}
59+
60+
@Test
61+
fun writeState_100snapshotFlow() = runMonotonicClockTest {
62+
val composeState = mutableFloatStateOf(0f)
63+
64+
repeat(100) { snapshotFlow { composeState.floatValue }.launchIn(backgroundScope) }
65+
66+
benchmarkRule.measureRepeated {
67+
composeState.floatValue++
68+
Snapshot.sendApplyNotifications()
69+
testScheduler.advanceTimeBy(16)
70+
}
71+
}
72+
73+
@Test
74+
fun readAnimatableValue_100animatables_keepRunning() = runMonotonicClockTest {
75+
val anim = List(100) { Animatable(0f) }
76+
77+
benchmarkRule.measureRepeated {
78+
testScheduler.advanceTimeBy(16)
79+
anim.fastForEach {
80+
it.value
81+
82+
if (!it.isRunning) {
83+
launch { it.animateTo(if (it.targetValue != 0f) 0f else 1f) }
84+
}
85+
}
86+
}
87+
88+
testScheduler.advanceTimeBy(2000)
89+
}
90+
91+
@Test
92+
fun readAnimatableValue_100animatables_restartEveryFrame() = runMonotonicClockTest {
93+
val animatables = List(100) { Animatable(0f) }
94+
95+
benchmarkRule.measureRepeated {
96+
testScheduler.advanceTimeBy(16)
97+
animatables.fastForEach { animatable ->
98+
animatable.value
99+
launch { animatable.animateTo(if (animatable.targetValue != 0f) 0f else 1f) }
100+
}
101+
}
102+
103+
testScheduler.advanceTimeBy(2000)
104+
}
105+
}

0 commit comments

Comments
 (0)