Merge "Add converter APIs in XProcessing" into androidx-main
diff --git a/activity/activity-compose/src/androidTest/java/androidx/activity/compose/ActivityResultRegistryTest.kt b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/ActivityResultRegistryTest.kt
index d9f957e..9da389c 100644
--- a/activity/activity-compose/src/androidTest/java/androidx/activity/compose/ActivityResultRegistryTest.kt
+++ b/activity/activity-compose/src/androidTest/java/androidx/activity/compose/ActivityResultRegistryTest.kt
@@ -208,7 +208,7 @@
composeTestRule.runOnIdle {
assertThat(counter).isEqualTo(0)
}
- launchChannel.offer(true)
+ launchChannel.trySend(true)
composeTestRule.runOnIdle {
registry.dispatchResult(code, RESULT_OK, Intent())
assertThat(counter).isEqualTo(1)
diff --git a/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt b/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
index 047b11d..1dbb51a 100644
--- a/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
+++ b/activity/activity-ktx/src/main/java/androidx/activity/PipHintTracker.kt
@@ -50,6 +50,7 @@
// Create a cold flow that will emit the most updated position of the view in the form of a
// rect as long as the view is attached to the window.
+ @Suppress("DEPRECATION")
val flow = callbackFlow<Rect> {
// Emit a new hint rect any time the view moves.
val layoutChangeListener = View.OnLayoutChangeListener { v, l, t, r, b, oldLeft, oldTop,
diff --git a/appcompat/appcompat/build.gradle b/appcompat/appcompat/build.gradle
index 70207954..ef97181 100644
--- a/appcompat/appcompat/build.gradle
+++ b/appcompat/appcompat/build.gradle
@@ -11,7 +11,7 @@
dependencies {
api("androidx.annotation:annotation:1.3.0-alpha01")
- api("androidx.core:core:1.6.0-rc01")
+ api(project(":core:core"))
implementation(project(":emoji2:emoji2"))
implementation(project(":emoji2:emoji2-views-helper"))
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRtlTestUtilsRegressionTestCase.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRtlTestUtilsRegressionTestCase.kt
index 9b03daf..77ab362 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRtlTestUtilsRegressionTestCase.kt
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeRtlTestUtilsRegressionTestCase.kt
@@ -22,6 +22,7 @@
import androidx.appcompat.app.NightModeCustomAttachBaseContextActivity.CUSTOM_LOCALE
import androidx.appcompat.testutils.NightModeActivityTestRule
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.MediumTest
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.After
@@ -83,6 +84,7 @@
restoreConfig?.invoke()
}
+ @FlakyTest(bugId = 190529688)
@Test
@Suppress("DEPRECATION")
fun testLocaleIsMaintained() {
@@ -92,6 +94,7 @@
assertEquals(TextUtils.getLayoutDirectionFromLocale(CUSTOM_LOCALE), config.layoutDirection)
}
+ @FlakyTest(bugId = 190529688)
@Test
fun testFontScaleIsMaintained() {
// Check that the custom configuration properties are maintained
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseTextViewEmojiTest.java b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseTextViewEmojiTest.java
index da6fa86..9c4be75 100644
--- a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseTextViewEmojiTest.java
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/widget/AppCompatBaseTextViewEmojiTest.java
@@ -34,6 +34,7 @@
import androidx.emoji2.text.EmojiCompat;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -78,6 +79,7 @@
EmojiCompat.reset(mEmojiCompatMock);
}
+ @FlakyTest(bugId = 190530500)
@Test
@UiThreadTest
@SdkSuppress(minSdkVersion = 19)
@@ -89,6 +91,7 @@
verify(mEmojiCompatMock, atLeastOnce()).getLoadState();
}
+ @FlakyTest(bugId = 190530500)
@Test
@UiThreadTest
@SdkSuppress(minSdkVersion = 19)
@@ -101,6 +104,7 @@
verify(mEmojiCompatMock, atLeastOnce()).getLoadState();
}
+ @FlakyTest(bugId = 190530500)
@Test
@UiThreadTest
@SdkSuppress(minSdkVersion = 19)
@@ -114,6 +118,7 @@
verifyNoMoreInteractions(mEmojiCompatMock);
}
+ @FlakyTest(bugId = 190530500)
@Test
@UiThreadTest
@SdkSuppress(minSdkVersion = 19)
@@ -130,6 +135,7 @@
verify(mEmojiCompatMock, atLeastOnce()).getLoadState();
}
+ @FlakyTest(bugId = 190530500)
@Test
@SdkSuppress(minSdkVersion = 19)
public void whenNotConfigured_andDisabled_doesNotEnable_whenConfigured() throws Throwable {
@@ -167,6 +173,7 @@
}
+ @FlakyTest(bugId = 190530500)
@Test
@SdkSuppress(minSdkVersion = 19)
public void whenNotConfigured_callingEnabled_afterConfigure_enablesEmoji() throws Throwable {
@@ -187,6 +194,7 @@
verify(mEmojiCompatMock, atLeastOnce()).getLoadState();
}
+ @FlakyTest(bugId = 190530500)
@Test
@SdkSuppress(minSdkVersion = 19)
public void getEnabled() throws Throwable {
diff --git a/appcompat/integration-tests/receive-content-testapp/build.gradle b/appcompat/integration-tests/receive-content-testapp/build.gradle
index 6e9dbe7..0bb03a7 100644
--- a/appcompat/integration-tests/receive-content-testapp/build.gradle
+++ b/appcompat/integration-tests/receive-content-testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -30,7 +28,7 @@
dependencies {
api("androidx.annotation:annotation:1.1.0")
implementation(project(":appcompat:appcompat"))
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation(libs.guavaAndroid)
implementation(project(":recyclerview:recyclerview"))
implementation(libs.material)
diff --git a/benchmark/common/src/main/java/androidx/benchmark/Outputs.kt b/benchmark/common/src/main/java/androidx/benchmark/Outputs.kt
index 2fbbcaa..bf333e1 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/Outputs.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/Outputs.kt
@@ -16,7 +16,6 @@
package androidx.benchmark
-import android.annotation.SuppressLint
import android.os.Build
import android.os.Environment
import android.util.Log
@@ -50,7 +49,6 @@
// Be explicit about the TimeZone for stable formatting
formatter.timeZone = TimeZone.getTimeZone("UTC")
- @SuppressLint("UnsafeNewApiCall", "NewApi")
@Suppress("DEPRECATION")
dirUsableByAppAndShell = when {
Build.VERSION.SDK_INT == 30 -> {
diff --git a/benchmark/common/src/main/java/androidx/benchmark/Profiler.kt b/benchmark/common/src/main/java/androidx/benchmark/Profiler.kt
index 2ed9bec..2fe9622 100644
--- a/benchmark/common/src/main/java/androidx/benchmark/Profiler.kt
+++ b/benchmark/common/src/main/java/androidx/benchmark/Profiler.kt
@@ -16,7 +16,6 @@
package androidx.benchmark
-import android.annotation.SuppressLint
import android.os.Build
import android.os.Debug
import android.util.Log
@@ -86,7 +85,6 @@
}
}
-@SuppressLint("UnsafeNewApiCall")
internal fun startRuntimeMethodTracing(traceFileName: String, sampled: Boolean) {
val path = Outputs.testOutputFile(traceFileName).absolutePath
@@ -189,4 +187,4 @@
}
override val requiresLibraryOutputDir: Boolean = false
-}
\ No newline at end of file
+}
diff --git a/benchmark/integration-tests/macrobenchmark-target/build.gradle b/benchmark/integration-tests/macrobenchmark-target/build.gradle
index a9204d8..6dae47c 100644
--- a/benchmark/integration-tests/macrobenchmark-target/build.gradle
+++ b/benchmark/integration-tests/macrobenchmark-target/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -34,7 +32,7 @@
dependencies {
implementation(libs.kotlinStdlib)
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation("androidx.arch.core:core-runtime:2.1.0")
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("androidx.recyclerview:recyclerview:1.1.0")
diff --git a/benchmark/macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt b/benchmark/macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
index fa87ce4..dee3d44 100644
--- a/benchmark/macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
+++ b/benchmark/macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt
@@ -17,7 +17,6 @@
package androidx.benchmark.macro.junit4
import android.Manifest
-import android.annotation.SuppressLint
import androidx.annotation.IntRange
import androidx.annotation.RequiresApi
import androidx.benchmark.macro.CompilationMode
@@ -89,7 +88,6 @@
}
private fun applyInternal(base: Statement, description: Description) = object : Statement() {
- @SuppressLint("UnsafeNewApiCall")
override fun evaluate() {
currentDescription = description
base.evaluate()
diff --git a/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt b/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
index d09755d..b4a72dd 100644
--- a/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
+++ b/benchmark/macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
@@ -16,7 +16,6 @@
package androidx.benchmark.macro
-import android.annotation.SuppressLint
import android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE
import android.content.pm.PackageManager
import android.os.Build
@@ -44,7 +43,6 @@
)
}
- @SuppressLint("UnsafeNewApiCall")
val errorNotProfileable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
!applicationInfo.isProfileableByShell
} else {
diff --git a/biometric/biometric-ktx/samples/build.gradle b/biometric/biometric-ktx/samples/build.gradle
index 845d9c8..4835be3c 100644
--- a/biometric/biometric-ktx/samples/build.gradle
+++ b/biometric/biometric-ktx/samples/build.gradle
@@ -16,10 +16,6 @@
import androidx.build.LibraryGroups
import androidx.build.LibraryType
-import androidx.build.LibraryVersions
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-import static androidx.build.dependencies.DependenciesKt.*
plugins {
id("AndroidXPlugin")
diff --git a/build.gradle b/build.gradle
index 12f31bc..4f878c1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,7 +16,6 @@
import androidx.build.AndroidXRootPlugin
import androidx.build.SdkHelperKt
-import static androidx.build.dependencies.DependenciesKt.*
buildscript {
SdkHelperKt.setSupportRootFolder(project, project.projectDir)
diff --git a/buildSrc-tests/build.gradle b/buildSrc-tests/build.gradle
index a491a7b..75dad66 100644
--- a/buildSrc-tests/build.gradle
+++ b/buildSrc-tests/build.gradle
@@ -17,7 +17,6 @@
// This project contains tests for code contained in buildSrc
// This project is stored outside of buildSrc/ so that waiting for these tests to complete doesn't delay the rest of the build
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.BuildServerConfigurationKt
plugins {
@@ -27,7 +26,7 @@
dependencies {
implementation(gradleApi())
- testImplementation(JUNIT)
+ testImplementation(libs.junit)
implementation(project.files(new File(BuildServerConfigurationKt.getRootOutDirectory(project), "buildSrc/build/libs/buildSrc.jar")))
}
diff --git a/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-dep/build.gradle b/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-dep/build.gradle
index 5d6b1bc..f835c39 100644
--- a/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-dep/build.gradle
+++ b/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-dep/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.Publish
diff --git a/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-main/build.gradle b/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-main/build.gradle
index 6ba36d7..56d1cc00 100644
--- a/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-main/build.gradle
+++ b/buildSrc-tests/max-dep-versions/buildSrc-tests-max-dep-versions-main/build.gradle
@@ -1,6 +1,4 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.Publish
plugins {
id("AndroidXPlugin")
diff --git a/buildSrc-tests/project-subsets/build.gradle b/buildSrc-tests/project-subsets/build.gradle
index cfeacda..3199270 100644
--- a/buildSrc-tests/project-subsets/build.gradle
+++ b/buildSrc-tests/project-subsets/build.gradle
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-import androidx.build.BuildServerConfigurationKt
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -24,7 +21,7 @@
dependencies {
implementation gradleTestKit()
- testImplementation JUNIT
+ testImplementation libs.junit
}
tasks["test"].configure { t ->
// The output of this task can potentially depend on the contents of settings.gradle
diff --git a/buildSrc-tests/src/test/kotlin/androidx/build/dependencyTracker/AffectedModuleDetectorImplTest.kt b/buildSrc-tests/src/test/kotlin/androidx/build/dependencyTracker/AffectedModuleDetectorImplTest.kt
index d8b6782..cdb91693 100644
--- a/buildSrc-tests/src/test/kotlin/androidx/build/dependencyTracker/AffectedModuleDetectorImplTest.kt
+++ b/buildSrc-tests/src/test/kotlin/androidx/build/dependencyTracker/AffectedModuleDetectorImplTest.kt
@@ -61,6 +61,7 @@
private lateinit var p10: Project
private lateinit var p11: Project
private val cobuiltTestPaths = setOf(setOf("cobuilt1", "cobuilt2"))
+ private val ignoredPaths = setOf("ignored/")
@Before
fun init() {
@@ -592,6 +593,106 @@
)
}
+ @Test
+ fun `Only ignored file`() {
+ val detector = AffectedModuleDetectorImpl(
+ rootProject = root,
+ logger = logger,
+ ignoreUnknownProjects = false,
+ cobuiltTestPaths = cobuiltTestPaths,
+ ignoredPaths = ignoredPaths,
+ injectedGitClient = MockGitClient(
+ lastMergeSha = "foo",
+ changedFiles = listOf(convertToFilePath("ignored", "example.txt"))
+ )
+ )
+ MatcherAssert.assertThat(
+ detector.buildAll,
+ CoreMatchers.`is`(
+ false
+ )
+ )
+ }
+
+ @Test
+ fun `Ignored file and changed file`() {
+ val detector = AffectedModuleDetectorImpl(
+ rootProject = root,
+ logger = logger,
+ ignoreUnknownProjects = false,
+ cobuiltTestPaths = cobuiltTestPaths,
+ ignoredPaths = ignoredPaths,
+ injectedGitClient = MockGitClient(
+ lastMergeSha = "foo",
+ changedFiles = listOf(
+ convertToFilePath("ignored", "example.txt"),
+ convertToFilePath("p1", "foo.kt")
+ )
+ )
+ )
+ MatcherAssert.assertThat(
+ detector.changedProjects,
+ CoreMatchers.`is`(
+ setOf(p1, p11)
+ )
+ )
+ MatcherAssert.assertThat(
+ detector.buildAll,
+ CoreMatchers.`is`(
+ false
+ )
+ )
+ }
+
+ @Test
+ fun `Ignored file and unknown file`() {
+ val detector = AffectedModuleDetectorImpl(
+ rootProject = root,
+ logger = logger,
+ ignoreUnknownProjects = false,
+ cobuiltTestPaths = cobuiltTestPaths,
+ ignoredPaths = ignoredPaths,
+ injectedGitClient = MockGitClient(
+ lastMergeSha = "foo",
+ changedFiles = listOf(
+ convertToFilePath("ignored", "example.txt"),
+ convertToFilePath("unknown", "foo.kt")
+ )
+ )
+ )
+ MatcherAssert.assertThat(
+ detector.buildAll,
+ CoreMatchers.`is`(
+ true
+ )
+ )
+ }
+
+ @Test
+ fun `Ignored file, unknown file, and changed file`() {
+ val detector = AffectedModuleDetectorImpl(
+ rootProject = root,
+ logger = logger,
+ ignoreUnknownProjects = false,
+ cobuiltTestPaths = cobuiltTestPaths,
+ ignoredPaths = ignoredPaths,
+ injectedGitClient = MockGitClient(
+ lastMergeSha = "foo",
+ changedFiles = listOf(
+ "ignored/eg.txt",
+ convertToFilePath("unknown", "foo.kt"),
+ convertToFilePath("p1", "bar.kt")
+ )
+ )
+ )
+ MatcherAssert.assertThat(
+ detector.buildAll,
+ CoreMatchers.`is`(
+ true
+ )
+ )
+ }
+
// For both Linux/Windows
fun convertToFilePath(vararg list: String): String {
return list.toList().joinToString(File.separator)
diff --git a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
index abf1af0..d67c165 100644
--- a/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/AndroidXPlugin.kt
@@ -50,7 +50,7 @@
import org.gradle.api.Task
import org.gradle.api.file.DuplicatesStrategy
import org.gradle.api.plugins.JavaPlugin
-import org.gradle.api.plugins.JavaPluginConvention
+import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar
@@ -63,7 +63,6 @@
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.findByType
-import org.gradle.kotlin.dsl.getPlugin
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper
@@ -167,11 +166,11 @@
task.finalizedBy(zipHtmlTask)
task.doFirst {
zipHtmlTask.configure {
- it.from(htmlReport.destination)
+ it.from(htmlReport.outputLocation)
}
}
val xmlReport = task.reports.junitXml
- if (xmlReport.isEnabled) {
+ if (xmlReport.required.get()) {
val zipXmlTask = project.tasks.register(
"zipXmlResultsOf${task.name.capitalize()}",
Zip::class.java
@@ -185,7 +184,7 @@
task.finalizedBy(zipXmlTask)
task.doFirst {
zipXmlTask.configure {
- it.from(xmlReport.destination)
+ it.from(xmlReport.outputLocation)
}
}
}
@@ -332,8 +331,8 @@
project.configureSourceJarForJava()
// Force Java 1.8 source- and target-compatibilty for all Java libraries.
- val convention = project.convention.getPlugin<JavaPluginConvention>()
- convention.apply {
+ val javaExtension = project.extensions.getByType<JavaPluginExtension>()
+ javaExtension.apply {
sourceCompatibility = VERSION_1_8
targetCompatibility = VERSION_1_8
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
index ccb626b..cdf88fa 100644
--- a/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/ErrorProneConfiguration.kt
@@ -237,7 +237,7 @@
val compileTask = compileTaskProvider.get()
it.classpath = compileTask.classpath
it.source = compileTask.source
- it.destinationDir = file(buildDir.resolve("errorProne"))
+ it.destinationDirectory.set(file(buildDir.resolve("errorProne")))
it.options.compilerArgs = compileTask.options.compilerArgs.toMutableList()
it.options.annotationProcessorPath = compileTask.options.annotationProcessorPath
it.options.bootstrapClasspath = compileTask.options.bootstrapClasspath
diff --git a/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt b/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
index ca240d4..63dd976 100644
--- a/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/Ktlint.kt
@@ -58,7 +58,7 @@
task.description = "Check Kotlin code style."
task.group = "Verification"
task.classpath = getKtlintConfiguration()
- task.main = "com.pinterest.ktlint.Main"
+ task.mainClass.set("com.pinterest.ktlint.Main")
task.args = listOf(
"--android",
"--disabled_rules",
@@ -83,7 +83,7 @@
task.description = "Fix Kotlin code style deviations."
task.group = "formatting"
task.classpath = getKtlintConfiguration()
- task.main = "com.pinterest.ktlint.Main"
+ task.mainClass.set("com.pinterest.ktlint.Main")
task.args = listOf(
"--android",
"-F",
@@ -121,7 +121,7 @@
task.description = "Check Kotlin code style."
task.group = "Verification"
task.classpath = getKtlintConfiguration()
- task.main = "com.pinterest.ktlint.Main"
+ task.mainClass.set("com.pinterest.ktlint.Main")
task.doFirst {
if (task.files.isEmpty()) {
diff --git a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
index 5d3e47a..5f58c68 100644
--- a/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
@@ -95,7 +95,7 @@
val PRINT = Version("1.1.0-beta01")
val PERCENTLAYOUT = Version("1.1.0-alpha01")
val PREFERENCE = Version("1.2.0-alpha01")
- val PROFILEINSTALLER = Version("1.0.0-alpha01")
+ val PROFILEINSTALLER = Version("1.0.0-beta01")
val RECOMMENDATION = Version("1.1.0-alpha01")
val RECYCLERVIEW = Version("1.3.0-alpha01")
val RECYCLERVIEW_SELECTION = Version("1.2.0-alpha02")
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 42ea14c..6457f22 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -22,43 +22,25 @@
const val ANDROIDX_TEST_VERSION = "1.4.0-beta01"
const val ANDROIDX_TEST_CORE = "androidx.test:core:$ANDROIDX_TEST_VERSION"
const val ANDROIDX_TEST_EXT_JUNIT = "androidx.test.ext:junit:1.1.3-beta01"
-const val ANDROIDX_TEST_EXT_KTX = "androidx.test.ext:junit-ktx:1.1.3-beta01"
-const val ANDROIDX_TEST_EXT_TRUTH = "androidx.test.ext:truth:$ANDROIDX_TEST_VERSION"
const val ANDROIDX_TEST_MONITOR = "androidx.test:monitor:$ANDROIDX_TEST_VERSION"
const val ANDROIDX_TEST_RULES = "androidx.test:rules:$ANDROIDX_TEST_VERSION"
const val ANDROIDX_TEST_RUNNER = "androidx.test:runner:$ANDROIDX_TEST_VERSION"
const val ANDROIDX_TEST_UIAUTOMATOR = "androidx.test.uiautomator:uiautomator:2.2.0"
const val AUTO_COMMON = "com.google.auto:auto-common:0.11"
-const val AUTO_SERVICE_ANNOTATIONS = "com.google.auto.service:auto-service-annotations:1.0-rc6"
-const val AUTO_SERVICE_PROCESSOR = "com.google.auto.service:auto-service:1.0-rc6"
-const val AUTO_VALUE = "com.google.auto.value:auto-value:1.6.3"
-const val AUTO_VALUE_ANNOTATIONS = "com.google.auto.value:auto-value-annotations:1.6.3"
const val CONSTRAINT_LAYOUT = "androidx.constraintlayout:constraintlayout:2.0.1@aar"
-const val CONSTRAINT_LAYOUT_CORE = "androidx.constraintlayout:constraintlayout-core:1.0.0-alpha1"
const val DAGGER = "com.google.dagger:dagger:2.35"
const val DEXMAKER_MOCKITO = "com.linkedin.dexmaker:dexmaker-mockito:2.25.0"
-const val DEXMAKER_MOCKITO_INLINE = "com.linkedin.dexmaker:dexmaker-mockito-inline:2.25.0"
-const val ESPRESSO_CONTRIB = "androidx.test.espresso:espresso-contrib:3.3.0"
const val ESPRESSO_CORE = "androidx.test.espresso:espresso-core:3.3.0"
const val ESPRESSO_INTENTS = "androidx.test.espresso:espresso-intents:3.3.0"
-const val ESPRESSO_IDLING_NET = "androidx.test.espresso.idling:idling-net:3.3.0"
-const val ESPRESSO_IDLING_RESOURCE = "androidx.test.espresso:espresso-idling-resource:3.3.0"
-const val ESPRESSO_WEB = "androidx.test.espresso:espresso-web:3.3.0"
const val GOOGLE_COMPILE_TESTING = "com.google.testing.compile:compile-testing:0.18"
const val GUAVA_VERSION = "29.0-jre"
const val GUAVA = "com.google.guava:guava:$GUAVA_VERSION"
const val GUAVA_ANDROID_VERSION = "29.0-android"
const val GUAVA_ANDROID = "com.google.guava:guava:$GUAVA_ANDROID_VERSION"
-const val GUAVA_LISTENABLE_FUTURE = "com.google.guava:listenablefuture:1.0"
-const val GRADLE_INCAP_HELPER = "net.ltgt.gradle.incap:incap:0.2"
-const val GRADLE_INCAP_HELPER_PROCESSOR = "net.ltgt.gradle.incap:incap-processor:0.2"
-const val INTELLIJ_ANNOTATIONS = "com.intellij:annotations:12.0"
const val JAVAPOET = "com.squareup:javapoet:1.13.0"
const val JSR250 = "javax.annotation:javax.annotation-api:1.2"
const val JUNIT = "junit:junit:4.12"
-const val KOTLINPOET = "com.squareup:kotlinpoet:1.8.0"
-const val KOTLIN_COMPILE_TESTING = "com.github.tschuchortdev:kotlin-compile-testing:1.4.1"
/**
* KSP is used both as a plugin and runtime dependency, hence its version is declared in the
@@ -66,22 +48,14 @@
*/
internal lateinit var kspVersion: String
val KSP_VERSION get() = kspVersion
-const val KOTLIN_GRADLE_PLUGIN = "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10"
const val KOTLIN_METADATA_JVM = "org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.3.0"
-const val LEAKCANARY = "com.squareup.leakcanary:leakcanary-android:2.2"
-const val LEAKCANARY_INSTRUMENTATION =
- "com.squareup.leakcanary:leakcanary-android-instrumentation:2.2"
const val MATERIAL = "com.google.android.material:material:1.2.1"
const val MOCKITO_CORE = "org.mockito:mockito-core:2.25.0"
const val MOCKITO_ANDROID = "org.mockito:mockito-android:2.25.0"
-const val MOCKITO_KOTLIN = "com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0"
const val MULTIDEX = "androidx.multidex:multidex:2.0.1"
-const val NULLAWAY = "com.uber.nullaway:nullaway:0.3.7"
-const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.2.9"
-const val RX_JAVA3 = "io.reactivex.rxjava3:rxjava:3.0.0"
-val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.3.1"
+val SKIKO_VERSION = System.getenv("SKIKO_VERSION") ?: "0.3.3"
val SKIKO = "org.jetbrains.skiko:skiko-jvm:$SKIKO_VERSION"
val SKIKO_LINUX_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-linux-x64:$SKIKO_VERSION"
val SKIKO_MACOS_X64 = "org.jetbrains.skiko:skiko-jvm-runtime-macos-x64:$SKIKO_VERSION"
@@ -100,14 +74,6 @@
}
}
const val TRUTH = "com.google.truth:truth:1.0.1"
-const val VIEW_BINDING = "androidx.databinding:viewbinding:4.1.2"
-const val XPP3 = "xpp3:xpp3:1.1.4c"
-const val XMLPULL = "xmlpull:xmlpull:1.1.3.1"
-
-const val SQLDELIGHT_ANDROID = "com.squareup.sqldelight:android-driver:1.3.0"
-const val SQLDELIGHT_COROUTINES_EXT = "com.squareup.sqldelight:coroutines-extensions:1.3.0"
-
-const val ROBOLECTRIC = "org.robolectric:robolectric:4.5.1"
const val PROTOBUF = "com.google.protobuf:protobuf-java:3.4.0"
const val PROTOBUF_COMPILER = "com.google.protobuf:protoc:3.10.0"
@@ -123,31 +89,18 @@
val KOTLIN_STDLIB get() = "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
val KOTLIN_STDLIB_COMMON get() = "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlinVersion"
val KOTLIN_STDLIB_JDK8 get() = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
-val KOTLIN_STDLIB_JS get() = "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion"
val KOTLIN_TEST get() = "org.jetbrains.kotlin:kotlin-test:$kotlinVersion"
val KOTLIN_TEST_COMMON get() = "org.jetbrains.kotlin:kotlin-test-common:$kotlinVersion"
-val KOTLIN_TEST_ANNOTATIONS_COMMON get() =
- "org.jetbrains.kotlin:kotlin-test-annotations-common:$kotlinVersion"
-val KOTLIN_TEST_JUNIT get() = "org.jetbrains.kotlin:kotlin-test-junit:$kotlinVersion"
-val KOTLIN_TEST_JS get() = "org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion"
val KOTLIN_REFLECT get() = "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
internal lateinit var kotlinCoroutinesVersion: String
val KOTLIN_COROUTINES_ANDROID
get() = "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
-val KOTLIN_COROUTINES_SWING
- get() = "org.jetbrains.kotlinx:kotlinx-coroutines-swing:$kotlinCoroutinesVersion"
val KOTLIN_COROUTINES_CORE
get() = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion"
-val KOTLIN_COROUTINES_GUAVA
- get() = "org.jetbrains.kotlinx:kotlinx-coroutines-guava:$kotlinCoroutinesVersion"
val KOTLIN_COROUTINES_TEST
get() = "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutinesVersion"
-val KOTLIN_COROUTINES_RX2
- get() = "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlinCoroutinesVersion"
-val KOTLIN_COROUTINES_RX3
- get() = "org.jetbrains.kotlinx:kotlinx-coroutines-rx3:$kotlinCoroutinesVersion"
internal lateinit var agpVersion: String
@@ -158,6 +111,5 @@
const val LINT_API_MIN = "com.android.tools.lint:lint-api:$lintMinVersion"
val LINT_API_LATEST get() = "com.android.tools.lint:lint-api:$lintVersion"
-val LINT_CHECKS_LATEST get() = "com.android.tools.lint:lint-checks:$lintVersion"
val LINT_CORE get() = "com.android.tools.lint:lint:$lintVersion"
val LINT_TESTS get() = "com.android.tools.lint:lint-tests:$lintVersion"
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
index b32a04c..147c312 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
@@ -217,6 +217,7 @@
private val ignoreUnknownProjects: Boolean = false,
private val cobuiltTestPaths: Set<Set<String>> = COBUILT_TEST_PATHS,
private val alwaysBuildIfExistsPaths: Set<String> = ALWAYS_BUILD_IF_EXISTS,
+ private val ignoredPaths: Set<String> = IGNORED_PATHS,
private val injectedGitClient: GitClient? = null,
private val baseCommitOverride: String? = null
) : AffectedModuleDetector(logger) {
@@ -250,6 +251,9 @@
private var unknownFiles: MutableSet<String> = mutableSetOf()
+ // Files tracked by git that are not expected to effect the build, thus require no consideration
+ private var ignoredFiles: MutableSet<String> = mutableSetOf()
+
val buildAll by lazy {
shouldBuildAll()
}
@@ -311,18 +315,29 @@
val changedProjects: MutableSet<Project> = alwaysBuild.toMutableSet()
for (filePath in changedFiles) {
- val containingProject = findContainingProject(filePath)
- if (containingProject == null) {
- unknownFiles.add(filePath)
+ if (ignoredPaths.any {
+ filePath.startsWith(it)
+ }
+ ) {
+ ignoredFiles.add(filePath)
logger?.info(
- "Couldn't find containing project for file$filePath. Adding to unknownFiles."
+ "Ignoring file: $filePath"
)
} else {
- changedProjects.add(containingProject)
- logger?.info(
- "For file $filePath containing project is $containingProject. " +
- "Adding to changedProjects."
- )
+ val containingProject = findContainingProject(filePath)
+ if (containingProject == null) {
+ unknownFiles.add(filePath)
+ logger?.info(
+ "Couldn't find containing project for file: $filePath. Adding to " +
+ "unknownFiles."
+ )
+ } else {
+ changedProjects.add(containingProject)
+ logger?.info(
+ "For file $filePath containing project is $containingProject. " +
+ "Adding to changedProjects."
+ )
+ }
}
}
@@ -350,8 +365,11 @@
*/
private fun shouldBuildAll(): Boolean {
var shouldBuildAll = false
- // Should only trigger if there are no changedFiles
- if (changedProjects.size == alwaysBuild.size && unknownFiles.isEmpty()) {
+ // Should only trigger if there are no changedFiles and no ignored files
+ if (changedProjects.size == alwaysBuild.size &&
+ unknownFiles.isEmpty() &&
+ ignoredFiles.isEmpty()
+ ) {
shouldBuildAll = true
} else if (unknownFiles.isNotEmpty() && !isGithubInfraChange()) {
shouldBuildAll = true
@@ -366,7 +384,7 @@
if (unknownFiles.isEmpty()) {
logger?.info("because no changed files were detected")
} else {
- logger?.info("because one of the unknown files affects everything in the build")
+ logger?.info("because one of the unknown files may affect everything in the build")
logger?.info(
"""
The modules detected as affected by changed files are
@@ -492,5 +510,10 @@
":emoji2:integration-tests:init-enabled-macrobenchmark-target",
),
)
+
+ private val IGNORED_PATHS = setOf(
+ "docs/",
+ "development/"
+ )
}
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt b/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
index 205bd58..2a1375c 100644
--- a/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/doclava/DoclavaTask.kt
@@ -281,7 +281,7 @@
execOperations.javaexec {
it.classpath(classpath)
- it.main = "com.google.doclava.Doclava"
+ it.mainClass.set("com.google.doclava.Doclava")
it.args = args
}
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/docs/AndroidXDocsPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/docs/AndroidXDocsPlugin.kt
index 9afdb1d..7069810 100644
--- a/buildSrc/src/main/kotlin/androidx/build/docs/AndroidXDocsPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/docs/AndroidXDocsPlugin.kt
@@ -559,7 +559,7 @@
}
}
-private const val DACKKA_DEPENDENCY = "com.google.devsite:dackka:0.0.5"
+private const val DACKKA_DEPENDENCY = "com.google.devsite:dackka:0.0.6"
private const val DOCLAVA_DEPENDENCY = "com.android:doclava:1.0.6"
// Allowlist for directories that should be processed by Dackka
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
index 0d29425..632845e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaRunner.kt
@@ -69,7 +69,7 @@
"java.base/java.util=ALL-UNNAMED"
)
it.classpath(parameters.metalavaClasspath.get())
- it.main = "com.android.tools.metalava.Driver"
+ it.mainClass.set("com.android.tools.metalava.Driver")
it.args = parameters.args.get()
}
}
diff --git a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
index cd2726e..eec8c70 100644
--- a/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
@@ -225,7 +225,7 @@
) { task ->
@Suppress("DEPRECATION") val compileTask = variant.javaCompile
task.source = project.files(apiStubsDirectory).asFileTree
- task.destinationDir = apiStubClassesDirectory
+ task.destinationDirectory.set(apiStubClassesDirectory)
task.classpath = compileTask.classpath
task.options.compilerArgs = compileTask.options.compilerArgs
diff --git a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
index 0cb6f6a..838efb9 100644
--- a/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/testConfiguration/GenerateMediaTestConfigurationTask.kt
@@ -175,7 +175,8 @@
.isServicePrevious(isServicePrevious)
.tag("androidx_unit_tests")
.tag("media_compat")
- configBuilder.isPostsubmit(!isPresubmitBuild())
+ val isPresubmit = isPresubmitBuild()
+ configBuilder.isPostsubmit(!isPresubmit)
when (affectedModuleDetectorSubset.get()) {
ProjectSubset.DEPENDENT_PROJECTS -> {
if (isConstrained) {
@@ -184,6 +185,13 @@
configBuilder.runAllTests(true)
}
}
+ ProjectSubset.NONE -> {
+ if (isPresubmit) {
+ configBuilder.runAllTests(false)
+ } else {
+ configBuilder.runAllTests(true)
+ }
+ }
else -> {
configBuilder.runAllTests(true)
}
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulator.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulator.kt
index e3f878f4..c520358 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulator.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulator.kt
@@ -29,7 +29,7 @@
import androidx.camera.camera2.pipe.Request
import androidx.camera.camera2.pipe.StreamId
import kotlinx.atomicfu.atomic
-import kotlinx.coroutines.withTimeoutOrNull
+import kotlinx.coroutines.withTimeout
/** Simulator for observing and responding to interactions with the a [CameraGraph]. */
class CameraGraphSimulator(
@@ -54,18 +54,17 @@
suspend fun simulateNextFrame(
advanceClockByNanos: Long = 33_366_666 // (2_000_000_000 / (60 / 1.001))
- ): FrameSimulator? = generateNextFrame().also {
+ ): FrameSimulator = generateNextFrame().also {
val clockNanos = frameClockNanos.addAndGet(advanceClockByNanos)
- it?.simulateStarted(clockNanos)
+ it.simulateStarted(clockNanos)
}
- private suspend fun generateNextFrame(): FrameSimulator? {
+ private suspend fun generateNextFrame(): FrameSimulator {
// This checks the pending frame queue and polls for the next request. If no request is
// available it will suspend until the next interaction with the request processor.
if (pendingFrameQueue.isEmpty()) {
val requestSequence =
- withTimeoutOrNull(timeMillis = 200) { fakeRequestProcessor.nextRequestSequence() }
- ?: return null
+ withTimeout(timeMillis = 250) { fakeRequestProcessor.nextRequestSequence() }
// Each sequence is processed as a group, and if a sequence contains multiple requests
// the list of requests is processed in order before polling the next sequence.
@@ -73,7 +72,7 @@
pendingFrameQueue.add(FrameSimulator(request, requestSequence))
}
}
- return pendingFrameQueue.removeFirstOrNull()
+ return pendingFrameQueue.removeFirst()
}
/**
diff --git a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestProcessor.kt b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestProcessor.kt
index 8b36e26..e7d0ec0 100644
--- a/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestProcessor.kt
+++ b/camera/camera-camera2-pipe-testing/src/main/java/androidx/camera/camera2/pipe/testing/FakeRequestProcessor.kt
@@ -74,35 +74,7 @@
defaultParameters: Map<*, Any?>,
requiredParameters: Map<*, Any?>,
defaultListeners: List<Request.Listener>
- ): Boolean {
- val requestSequence =
- createRequestSequence(
- repeating = false,
- listOf(request),
- defaultParameters,
- requiredParameters,
- defaultListeners
- )
-
- if (rejectRequests) {
- check(eventChannel.offer(Event(requestSequence = requestSequence, rejected = true)))
- return false
- }
-
- val signal = synchronized(lock) {
- requestSequenceQueue.add(requestSequence)
- pendingSequence?.also {
- pendingSequence = null
- }
- }
- requestSequence.invokeOnSequenceCreated()
- requestSequence.invokeOnSequenceSubmitted()
- signal?.complete(requestSequence)
-
- check(eventChannel.offer(Event(requestSequence = requestSequence, submit = true)))
-
- return true
- }
+ ): Boolean = submit(listOf(request), defaultParameters, requiredParameters, defaultListeners)
override fun submit(
requests: List<Request>,
@@ -119,7 +91,11 @@
defaultListeners
)
if (rejectRequests) {
- check(eventChannel.offer(Event(requestSequence = requestSequence, rejected = true)))
+ check(
+ eventChannel
+ .trySend(Event(requestSequence = requestSequence, rejected = true))
+ .isSuccess
+ )
return false
}
@@ -133,7 +109,11 @@
requestSequence.invokeOnSequenceSubmitted()
signal?.complete(requestSequence)
- check(eventChannel.offer(Event(requestSequence = requestSequence, submit = true)))
+ check(
+ eventChannel
+ .trySend(Event(requestSequence = requestSequence, submit = true))
+ .isSuccess
+ )
return true
}
@@ -153,7 +133,11 @@
defaultListeners
)
if (rejectRequests) {
- check(eventChannel.offer(Event(requestSequence = requestSequence, rejected = true)))
+ check(
+ eventChannel
+ .trySend(Event(requestSequence = requestSequence, rejected = true))
+ .isSuccess
+ )
return false
}
@@ -167,7 +151,11 @@
requestSequence.invokeOnSequenceSubmitted()
signal?.complete(requestSequence)
- check(eventChannel.offer(Event(requestSequence = requestSequence, startRepeating = true)))
+ check(
+ eventChannel
+ .trySend(Event(requestSequence = requestSequence, startRepeating = true))
+ .isSuccess
+ )
return true
}
@@ -180,7 +168,7 @@
for (sequence in requestSequencesToAbort) {
sequence.invokeOnSequenceAborted()
}
- check(eventChannel.offer(Event(abort = true)))
+ check(eventChannel.trySend(Event(abort = true)).isSuccess)
}
override fun stopRepeating() {
@@ -190,14 +178,14 @@
}
}
requestSequence?.invokeOnSequenceAborted()
- check(eventChannel.offer(Event(stop = true)))
+ check(eventChannel.trySend(Event(stop = true)).isSuccess)
}
override fun close() {
synchronized(lock) {
rejectRequests = true
}
- check(eventChannel.offer(Event(close = true)))
+ check(eventChannel.trySend(Event(close = true)).isSuccess)
}
/**
diff --git a/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt b/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
index bd61d50..5bdcdf0 100644
--- a/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
+++ b/camera/camera-camera2-pipe-testing/src/test/java/androidx/camera/camera2/pipe/testing/CameraGraphSimulatorTest.kt
@@ -36,7 +36,6 @@
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
-import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@@ -74,8 +73,6 @@
simulator.cameraGraph.start()
val frame = simulator.simulateNextFrame()
- assertThat(frame).isNotNull()
- frame!! // Tell kotlin that this is not null.
assertThat(frame.request).isSameInstanceAs(request)
assertThat(frame.frameNumber.value).isGreaterThan(0)
@@ -186,7 +183,7 @@
}
simulator.cameraGraph.start()
- val frame = simulator.simulateNextFrame()!!
+ val frame = simulator.simulateNextFrame()
assertThat(frame.request).isSameInstanceAs(request)
frame.simulateBufferLoss(stream.id)
@@ -196,7 +193,6 @@
assertThat(lossEvent.streamId).isEqualTo(stream.id)
}
- @Ignore // TODO(b/188446185): flaky
@Test
fun simulatorCanIssueMultipleFrames() = runBlocking {
val listener = FakeRequestListener()
@@ -210,9 +206,9 @@
}
simulator.cameraGraph.start()
- val frame1 = simulator.simulateNextFrame()!!
- val frame2 = simulator.simulateNextFrame()!!
- val frame3 = simulator.simulateNextFrame()!!
+ val frame1 = simulator.simulateNextFrame()
+ val frame2 = simulator.simulateNextFrame()
+ val frame3 = simulator.simulateNextFrame()
assertThat(frame1).isNotEqualTo(frame2)
assertThat(frame2).isNotEqualTo(frame3)
@@ -236,7 +232,7 @@
frame3.simulateComplete(resultMetadata)
}
- val startEvents = withTimeout(timeMillis = 150) {
+ val startEvents = withTimeout(timeMillis = 250) {
listener.onStartedFlow.take(3).toList()
}
assertThat(startEvents).hasSize(3)
@@ -261,7 +257,7 @@
assertThat(event2.requestMetadata.request).isSameInstanceAs(request)
assertThat(event3.requestMetadata.request).isSameInstanceAs(request)
- val completeEvents = withTimeout(timeMillis = 150) {
+ val completeEvents = withTimeout(timeMillis = 250) {
listener.onCompleteFlow.take(3).toList()
}
assertThat(completeEvents).hasSize(3)
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
index 8f9b59d..1365663 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Camera2CameraMetadata.kt
@@ -16,7 +16,6 @@
package androidx.camera.camera2.pipe.compat
-import android.annotation.SuppressLint
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.CaptureResult
@@ -125,7 +124,6 @@
}
}
- @SuppressLint("UnsafeNewApiCall")
private val _physicalCameraIds: Lazy<Set<CameraId>> =
lazy(LazyThreadSafetyMode.PUBLICATION) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
@@ -176,4 +174,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
index 7eefdc5..b5def51 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
@@ -119,7 +119,6 @@
private val threads: Threads,
private val graphConfig: CameraGraph.Config
) : CaptureSessionFactory {
- @SuppressLint("NewApi")
override fun create(
cameraDevice: CameraDeviceWrapper,
surfaces: Map<StreamId, Surface>,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
index 6d120e6..2b533ea 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
@@ -16,7 +16,6 @@
package androidx.camera.camera2.pipe.compat
-import android.annotation.SuppressLint
import android.graphics.SurfaceTexture
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.params.OutputConfiguration
@@ -118,7 +117,6 @@
}
@RequiresApi(24)
-@SuppressLint("UnsafeNewApiCall")
internal class AndroidOutputConfiguration(
private val output: OutputConfiguration,
override val surfaceSharing: Boolean,
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
index aa1cf52..209ea86e 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/VirtualCameraManager.kt
@@ -82,7 +82,7 @@
}
private fun offerChecked(request: CameraRequest) {
- check(requestQueue.offer(request)) {
+ check(requestQueue.trySend(request).isSuccess) {
"There are more than $requestQueueDepth requests buffered!"
}
}
@@ -298,7 +298,6 @@
/**
* Wait for the specified duration, or until the availability callback is invoked.
*/
- @SuppressLint("UnsafeNewApiCall")
private suspend fun awaitAvailableCameraId(
cameraId: CameraId,
timeoutMillis: Long = 200
@@ -362,7 +361,7 @@
scope,
timeout = 1000,
callback = {
- channel.offer(RequestClose(this))
+ channel.trySend(RequestClose(this)).isSuccess
}
)
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AForCaptureTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AForCaptureTest.kt
index aae32a7..b886e3c 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AForCaptureTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AForCaptureTest.kt
@@ -30,6 +30,7 @@
import androidx.camera.camera2.pipe.testing.FakeRequestProcessor
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
@@ -47,6 +48,7 @@
private val listener3A = Listener3A()
private val controller3A = Controller3A(graphProcessor, graphState3A, listener3A)
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testLock3AForCapture(): Unit = runBlocking {
initGraphProcessor()
@@ -125,6 +127,7 @@
}
}
+ @OptIn(DelicateCoroutinesApi::class)
private fun testUnlock3APostCaptureAndroidMAndAbove(): Unit = runBlocking {
initGraphProcessor()
@@ -193,6 +196,7 @@
.isEqualTo(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL)
}
+ @OptIn(DelicateCoroutinesApi::class)
private fun testUnlock3APostCaptureAndroidLAndBelow(): Unit = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ALock3ATest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ALock3ATest.kt
index 89e5ebb..f7aadd1 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ALock3ATest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ALock3ATest.kt
@@ -32,6 +32,7 @@
import androidx.camera.camera2.pipe.testing.FakeRequestProcessor
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
@@ -50,6 +51,7 @@
private val listener3A = Listener3A()
private val controller3A = Controller3A(graphProcessor, graphState3A, listener3A)
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfImmediateAeImmediate(): Unit = runBlocking {
initGraphProcessor()
@@ -130,6 +132,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfImmediateAeAfterCurrentScan(): Unit = runBlocking {
initGraphProcessor()
@@ -210,6 +213,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfImmediateAeAfterNewScan(): Unit = runBlocking {
initGraphProcessor()
@@ -295,6 +299,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfAfterCurrentScanAeImmediate(): Unit = runBlocking {
initGraphProcessor()
@@ -375,6 +380,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfAfterNewScanScanAeImmediate(): Unit = runBlocking {
initGraphProcessor()
@@ -461,6 +467,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfAfterCurrentScanAeAfterCurrentScan(): Unit = runBlocking {
initGraphProcessor()
@@ -555,6 +562,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfAfterNewScanScanAeAfterNewScan(): Unit = runBlocking {
initGraphProcessor()
@@ -644,6 +652,7 @@
)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testLock3AWithRegions(): Unit = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASetTorchTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASetTorchTest.kt
index df382c3..686e644 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASetTorchTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASetTorchTest.kt
@@ -32,6 +32,7 @@
import androidx.camera.camera2.pipe.testing.FakeRequestProcessor
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -48,6 +49,7 @@
private val listener3A = Listener3A()
private val controller3A = Controller3A(graphProcessor, graphState3A, listener3A)
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testSetTorchOn() = runBlocking {
initGraphProcessor()
@@ -80,6 +82,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testSetTorchOff() = runBlocking {
initGraphProcessor()
@@ -112,6 +115,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testSetTorchDoesNotChangeAeModeIfNotNeeded() = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASubmit3ATest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASubmit3ATest.kt
index 2a57464..ba1cee06 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASubmit3ATest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3ASubmit3ATest.kt
@@ -34,6 +34,7 @@
import androidx.camera.camera2.pipe.testing.FakeRequestProcessor
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -59,6 +60,7 @@
assertThat(result.isCompleted).isFalse()
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfModeSubmit(): Unit = runBlocking {
initGraphProcessor()
@@ -86,6 +88,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAeModeSubmit(): Unit = runBlocking {
initGraphProcessor()
@@ -114,6 +117,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAwbModeSubmit(): Unit = runBlocking {
initGraphProcessor()
@@ -142,6 +146,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfRegionsSubmit(): Unit = runBlocking {
initGraphProcessor()
@@ -170,6 +175,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAeRegionsSubmit(): Unit = runBlocking {
initGraphProcessor()
@@ -198,6 +204,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAwbRegionsSubmit(): Unit = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUnlock3ATest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUnlock3ATest.kt
index 2e145aa..d5438e7 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUnlock3ATest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUnlock3ATest.kt
@@ -30,6 +30,7 @@
import androidx.camera.camera2.pipe.testing.FakeRequestProcessor
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
@@ -48,6 +49,7 @@
private val listener3A = Listener3A()
private val controller3A = Controller3A(graphProcessor, graphState3A, listener3A)
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testUnlockAe(): Unit = runBlocking {
initGraphProcessor()
@@ -111,6 +113,7 @@
Truth.assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testUnlockAf(): Unit = runBlocking {
initGraphProcessor()
@@ -172,6 +175,7 @@
Truth.assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testUnlockAwb(): Unit = runBlocking {
initGraphProcessor()
@@ -235,6 +239,7 @@
Truth.assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testUnlockAeAf(): Unit = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUpdate3ATest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUpdate3ATest.kt
index 54d025f..c21151c 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUpdate3ATest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/graph/Controller3AUpdate3ATest.kt
@@ -35,6 +35,7 @@
import androidx.camera.camera2.pipe.testing.RobolectricCameraPipeTestRunner
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -73,6 +74,7 @@
assertThat(result.getCompletionExceptionOrNull() is CancellationException)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfModeUpdate(): Unit = runBlocking {
initGraphProcessor()
@@ -100,6 +102,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAeModeUpdate(): Unit = runBlocking {
initGraphProcessor()
@@ -128,6 +131,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAwbModeUpdate(): Unit = runBlocking {
initGraphProcessor()
@@ -156,6 +160,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAfRegionsUpdate(): Unit = runBlocking {
initGraphProcessor()
@@ -184,6 +189,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAeRegionsUpdate(): Unit = runBlocking {
initGraphProcessor()
@@ -212,6 +218,7 @@
assertThat(result3A.status).isEqualTo(Result3A.Status.OK)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testAwbRegionsUpdate(): Unit = runBlocking {
initGraphProcessor()
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
index f515300..888c893 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionTest.java
@@ -79,6 +79,7 @@
@LargeTest
@RunWith(Parameterized.class)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
+@SuppressWarnings("deprecation")
public class ExtensionTest {
@Rule
@@ -127,7 +128,7 @@
mExtensionsManager.isExtensionAvailable(mProcessCameraProvider, mBaseCameraSelector,
mExtensionMode));
- mExtensionsCameraSelector = mExtensionsManager.getExtensionCameraSelector(
+ mExtensionsCameraSelector = mExtensionsManager.getExtensionEnabledCameraSelector(
mProcessCameraProvider, mBaseCameraSelector, mExtensionMode);
mFakeLifecycleOwner = new FakeLifecycleOwner();
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
index f582f51..37ae718 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsErrorListenerTest.java
@@ -73,6 +73,7 @@
* Unit tests for {@link androidx.camera.extensions.ExtensionsErrorListener}.
* */
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.M)
+@SuppressWarnings("deprecation")
public final class ExtensionsErrorListenerTest {
@Rule
public TestRule mUseCamera = CameraUtil.grantCameraPermissionAndPreTest();
@@ -137,7 +138,7 @@
mFakeLifecycleOwner = new FakeLifecycleOwner();
mFakeLifecycleOwner.startAndResume();
- mExtensionsCameraSelector = mExtensionsManager.getExtensionCameraSelector(
+ mExtensionsCameraSelector = mExtensionsManager.getExtensionEnabledCameraSelector(
mProcessCameraProvider, mCameraSelector, mExtensionMode);
}
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
index bd03675..a3e8978 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ExtensionsManagerTest.kt
@@ -38,6 +38,7 @@
@SmallTest
@RunWith(Parameterized::class)
+@Suppress("DEPRECATION")
class ExtensionsManagerTest(
@field:ExtensionMode.Mode @param:ExtensionMode.Mode private val extensionMode: Int,
@field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
@@ -117,7 +118,7 @@
val baseCameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
assertThrows<IllegalArgumentException> {
- extensionsManager.getExtensionCameraSelector(
+ extensionsManager.getExtensionEnabledCameraSelector(
cameraProvider,
baseCameraSelector,
extensionMode
@@ -139,7 +140,7 @@
)
assertThrows<IllegalArgumentException> {
- extensionsManager.getExtensionCameraSelector(
+ extensionsManager.getExtensionEnabledCameraSelector(
cameraProvider,
baseCameraSelector,
extensionMode
@@ -160,7 +161,7 @@
)
)
- val resultCameraSelector = extensionsManager.getExtensionCameraSelector(
+ val resultCameraSelector = extensionsManager.getExtensionEnabledCameraSelector(
cameraProvider,
baseCameraSelector,
extensionMode
@@ -193,7 +194,7 @@
)
)
- val extensionCameraSelector = extensionsManager.getExtensionCameraSelector(
+ val extensionCameraSelector = extensionsManager.getExtensionEnabledCameraSelector(
cameraProvider,
baseCameraSelector,
extensionMode
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
index 6c72f4a..f0182c4 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderTest.java
@@ -80,6 +80,7 @@
import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
+@SuppressWarnings("deprecation")
public class ImageCaptureExtenderTest {
private static final String EXTENSION_AVAILABLE_CAMERA_ID = "0";
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
index 88a4788..946082b 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/ImageCaptureExtenderValidationTest.kt
@@ -43,6 +43,7 @@
@SmallTest
@RunWith(Parameterized::class)
+@Suppress("DEPRECATION")
class ImageCaptureExtenderValidationTest(
@field:Mode @param:Mode private val extensionMode: Int,
@field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
index f7c6642..cf2cd94 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderTest.java
@@ -86,6 +86,7 @@
import java.util.concurrent.TimeoutException;
@RunWith(AndroidJUnit4.class)
+@SuppressWarnings("deprecation")
public class PreviewExtenderTest {
private static final String EXTENSION_AVAILABLE_CAMERA_ID = "0";
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
index 7b7ebb7..c15563c 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/PreviewExtenderValidationTest.kt
@@ -43,6 +43,7 @@
@SmallTest
@RunWith(Parameterized::class)
+@Suppress("DEPRECATION")
class PreviewExtenderValidationTest(
@field:Mode @param:Mode private val extensionMode: Int,
@field:CameraSelector.LensFacing @param:CameraSelector.LensFacing private val lensFacing: Int
diff --git a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
index 4e98ef6..e33b291 100644
--- a/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
+++ b/camera/camera-extensions/src/androidTest/java/androidx/camera/extensions/util/ExtensionsTestUtil.java
@@ -60,6 +60,10 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+/**
+ * Extension test util functions.
+ */
+@SuppressWarnings("deprecation")
public class ExtensionsTestUtil {
@NonNull
public static Collection<Object[]> getAllEffectLensFacingCombinations() {
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoImageCaptureExtender.java
index a4eb7d6..ede1749 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoImageCaptureExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension implementation for auto effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class AutoImageCaptureExtender extends ImageCaptureExtender {
private static final String TAG = "AutoICExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoPreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoPreviewExtender.java
index 39611fb..ac6739c 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoPreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/AutoPreviewExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
import androidx.camera.core.Preview;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension Preview implementation for auto effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class AutoPreviewExtender extends PreviewExtender {
private static final String TAG = "AutoPreviewExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyImageCaptureExtender.java
index 276cee0..7e291a2 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyImageCaptureExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension implementation for beauty effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class BeautyImageCaptureExtender extends ImageCaptureExtender {
private static final String TAG = "BeautyICExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyPreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyPreviewExtender.java
index 85b20e1..ff75720 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyPreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BeautyPreviewExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
import androidx.camera.core.Preview;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension Preview implementation for beauty effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class BeautyPreviewExtender extends PreviewExtender {
private static final String TAG = "BeautyPreviewExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehImageCaptureExtender.java
index 7b6b349..05c04e7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehImageCaptureExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger;
@@ -25,7 +26,15 @@
/**
* Loads the OEM extension implementation for bokeh effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class BokehImageCaptureExtender extends ImageCaptureExtender {
private static final String TAG = "BokehImgCaptureExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehPreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehPreviewExtender.java
index a5f4600..3ee03b7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehPreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/BokehPreviewExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
import androidx.camera.core.Preview;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension Preview implementation for bokeh effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class BokehPreviewExtender extends PreviewExtender {
private static final String TAG = "BokehPreviewExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
index 58b0463..3047db7 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionCameraFilter.java
@@ -37,7 +37,7 @@
* A filter that filters camera based on extender implementation. If the implementation is
* unavailable, the camera will be considered available.
*/
-public final class ExtensionCameraFilter implements CameraFilter {
+final class ExtensionCameraFilter implements CameraFilter {
private final Id mId;
private final PreviewExtenderImpl mPreviewExtenderImpl;
private final ImageCaptureExtenderImpl mImageCaptureExtenderImpl;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
index e2b3ba4..5a80197 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionMode.java
@@ -27,10 +27,7 @@
/**
* The available modes for the extensions.
- *
- * @hide
*/
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public final class ExtensionMode {
/** Normal mode without any specific effect applied. */
public static final int NONE = 0;
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
index 279710c..06b7623 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsManager.java
@@ -49,7 +49,14 @@
public final class ExtensionsManager {
private static final String TAG = "ExtensionsManager";
- /** The effect mode options applied on the bound use cases */
+ /**
+ * The effect mode options applied on the bound use cases
+ *
+ * @deprecated Use {@link ExtensionMode} to call the new
+ * {@link #isExtensionAvailable(CameraProvider, CameraSelector, int)} and
+ * {@link #getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)} APIs.
+ */
+ @Deprecated
public enum EffectMode {
/** Normal mode without any specific effect applied. */
NORMAL,
@@ -131,7 +138,11 @@
*
* <p>This should be the first call to the extensions module. An application must wait until the
* {@link ListenableFuture} completes before making any other calls to the extensions module.
+ *
+ * @deprecated Use {@link #getInstance(Context)} to obtain an {@link ExtensionsManager}
+ * instance to access the extensions functions.
*/
+ @Deprecated
@NonNull
public static ListenableFuture<ExtensionsAvailability> init(@NonNull Context context) {
synchronized (EXTENSIONS_LOCK) {
@@ -275,7 +286,10 @@
* @param effectMode The extension function to be checked.
* @param lensFacing The lensFacing of the camera device to be checked.
* @return True if the specific extension function is supported for the camera device.
+ * @deprecated Use {@link #isExtensionAvailable(CameraProvider, CameraSelector, int)} to
+ * check whether extension function can support with the given {@link CameraSelector}.
*/
+ @Deprecated
public static boolean isExtensionAvailable(@NonNull EffectMode effectMode,
@CameraSelector.LensFacing int lensFacing) {
boolean isImageCaptureAvailable = checkImageCaptureExtensionCapability(effectMode,
@@ -298,7 +312,10 @@
* @param effectMode The extension function to be checked.
* @param lensFacing The lensFacing of the camera device to be checked.
* @return True if the specific extension function is supported for the camera device.
+ * @deprecated Use {@link #isExtensionAvailable(CameraProvider, CameraSelector, int)} to
+ * check whether extension function can support with the given {@link CameraSelector}.
*/
+ @Deprecated
public static boolean isExtensionAvailable(@NonNull Class<?> klass,
@NonNull EffectMode effectMode, @CameraSelector.LensFacing int lensFacing) {
boolean isAvailable = false;
@@ -318,10 +335,7 @@
* <p>An application must wait until the {@link ListenableFuture} completes to get an
* {@link ExtensionsManager} instance. The {@link ExtensionsManager} instance can be used to
* access the extensions related functions.
- *
- * @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
public static ListenableFuture<ExtensionsManager> getInstance(@NonNull Context context) {
return getInstance(context, VersionName.getCurrentVersion());
@@ -476,8 +490,7 @@
}
/**
- * Returns a new {@link CameraSelector} based on the one passed in for the specified extension
- * mode.
+ * Returns a modified {@link CameraSelector} that will enable the specified extension mode.
*
* <p>The returned extension {@link CameraSelector} can be used to bind use cases to a
* desired {@link LifecycleOwner} and then the specified extension mode will be enabled on
@@ -494,12 +507,9 @@
* @throws IllegalArgumentException If this device doesn't support extensions function, no
* camera can be found to support the specified extension mode, or the base
* {@link CameraSelector} has contained extension related configuration in it.
- *
- * @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
- public CameraSelector getExtensionCameraSelector(@NonNull CameraProvider cameraProvider,
+ public CameraSelector getExtensionEnabledCameraSelector(@NonNull CameraProvider cameraProvider,
@NonNull CameraSelector baseCameraSelector, @ExtensionMode.Mode int mode) {
// Directly return the input baseCameraSelector if the target extension mode is NONE.
if (mode == ExtensionMode.NONE) {
@@ -523,10 +533,7 @@
* @param cameraProvider The {@link CameraProvider} which will be used to bind use cases.
* @param baseCameraSelector The base {@link CameraSelector} to find a camera to use.
* @param mode The target extension mode to support.
- *
- * @hide
*/
- @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public boolean isExtensionAvailable(@NonNull CameraProvider cameraProvider,
@NonNull CameraSelector baseCameraSelector, @ExtensionMode.Mode int mode) {
if (mode == ExtensionMode.NONE) {
@@ -547,6 +554,7 @@
return mExtensionsAvailability;
}
+ @SuppressWarnings("deprecation")
private static boolean checkImageCaptureExtensionCapability(EffectMode effectMode,
@CameraSelector.LensFacing int lensFacing) {
ImageCapture.Builder builder = new ImageCapture.Builder();
@@ -612,6 +620,7 @@
}
}
+ @SuppressWarnings("deprecation")
private static boolean checkPreviewExtensionCapability(EffectMode effectMode,
@CameraSelector.LensFacing int lensFacing) {
Preview.Builder builder = new Preview.Builder();
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrImageCaptureExtender.java
index c3ce107..82cb6ab 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrImageCaptureExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension implementation for HDR effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class HdrImageCaptureExtender extends ImageCaptureExtender {
private static final String TAG = "HdrImageCaptureExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrPreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrPreviewExtender.java
index 3122998..43ae3b6 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrPreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/HdrPreviewExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
import androidx.camera.core.Preview;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension Preview implementation for HDR effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class HdrPreviewExtender extends PreviewExtender {
private static final String TAG = "HdrPreviewExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ImageCaptureExtender.java
index 86bfdc4..3413c32e 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ImageCaptureExtender.java
@@ -33,6 +33,7 @@
import androidx.camera.camera2.interop.Camera2CameraInfo;
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
import androidx.camera.core.CameraInfo;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraX;
import androidx.camera.core.ImageCapture;
@@ -59,7 +60,15 @@
/**
* Class for using an OEM provided extension on image capture.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public abstract class ImageCaptureExtender {
private static final String TAG = "ImageCaptureExtender";
static final Config.Option<Integer> OPTION_IMAGE_CAPTURE_EXTENDER_MODE =
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightImageCaptureExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightImageCaptureExtender.java
index 277e833..99902db 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightImageCaptureExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightImageCaptureExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.Logger;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension implementation for night effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class NightImageCaptureExtender extends ImageCaptureExtender {
private static final String TAG = "NightICExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightPreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightPreviewExtender.java
index dd38274..6f5141c 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightPreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/NightPreviewExtender.java
@@ -17,6 +17,7 @@
package androidx.camera.extensions;
import androidx.annotation.NonNull;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.Logger;
import androidx.camera.core.Preview;
@@ -25,7 +26,15 @@
/**
* Load the OEM extension Preview implementation for night effect type.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public class NightPreviewExtender extends PreviewExtender {
private static final String TAG = "NightPreviewExtender";
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/PreviewExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/PreviewExtender.java
index 80da011..c515061 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/PreviewExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/PreviewExtender.java
@@ -33,6 +33,7 @@
import androidx.camera.camera2.interop.Camera2CameraInfo;
import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
import androidx.camera.core.CameraInfo;
+import androidx.camera.core.CameraProvider;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.CameraX;
import androidx.camera.core.Logger;
@@ -57,7 +58,15 @@
/**
* Class for using an OEM provided extension on preview.
+ *
+ * @deprecated Use
+ * {@link ExtensionsManager#isExtensionAvailable(CameraProvider, CameraSelector, int)}
+ * to check whether extension function can support with the given {@link CameraSelector}. Use
+ * {@link ExtensionsManager#getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int)}
+ * to get a {@link CameraSelector} for the specific extension mode, then use it to bind the use
+ * cases to a lifecycle owner.
*/
+@Deprecated
public abstract class PreviewExtender {
private static final String TAG = "PreviewExtender";
static final Config.Option<Integer> OPTION_PREVIEW_EXTENDER_MODE = Config.Option.create(
diff --git a/camera/camera-video/build.gradle b/camera/camera-video/build.gradle
index a3e03e9..60272a1 100644
--- a/camera/camera-video/build.gradle
+++ b/camera/camera-video/build.gradle
@@ -73,6 +73,8 @@
// Use Robolectric 4.+
testOptions.unitTests.includeAndroidResources = true
+
+ kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
}
androidx {
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
index 019ce90..6c26f0c 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/encoder/AudioEncoderTest.kt
@@ -24,6 +24,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
@@ -372,6 +373,7 @@
private val started = AtomicBoolean(false)
private var job: Job? = null
+ @OptIn(DelicateCoroutinesApi::class)
fun start() {
if (started.getAndSet(true)) {
return
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/VideoCaptureLegacy.java b/camera/camera-video/src/main/java/androidx/camera/video/VideoCaptureLegacy.java
index b8a4537..7db9551 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/VideoCaptureLegacy.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/VideoCaptureLegacy.java
@@ -43,7 +43,6 @@
import static androidx.camera.video.impl.VideoCaptureLegacyConfig.OPTION_VIDEO_FRAME_RATE;
import android.Manifest;
-import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.location.Location;
@@ -1024,7 +1023,6 @@
}
}
- @SuppressLint("UnsafeNewApiCall")
@NonNull
private MediaMuxer initMediaMuxer(@NonNull OutputFileOptions outputFileOptions)
throws IOException {
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
index 1830f64..d69288a 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/AudioSource.java
@@ -21,7 +21,6 @@
import static androidx.camera.video.internal.AudioSource.InternalState.STARTED;
import android.Manifest;
-import android.annotation.SuppressLint;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.AudioTimestamp;
@@ -269,7 +268,6 @@
}
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
- @SuppressLint("UnsafeNewApiCall")
long generatePresentationTimeUs() {
long presentationTimeUs = -1;
if (Build.VERSION.SDK_INT >= 24) {
diff --git a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
index 7062c6a..720ba9b 100644
--- a/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
+++ b/camera/camera-view/src/main/java/androidx/camera/view/PreviewView.java
@@ -156,7 +156,6 @@
@SuppressWarnings("WeakerAccess")
final Preview.SurfaceProvider mSurfaceProvider = new Preview.SurfaceProvider() {
- @SuppressLint("NewApi")
@OptIn(markerClass = ExperimentalUseCaseGroup.class)
@Override
@AnyThread
diff --git a/camera/integration-tests/camerapipetestapp/build.gradle b/camera/integration-tests/camerapipetestapp/build.gradle
index 1caa678..9fab5bd 100644
--- a/camera/integration-tests/camerapipetestapp/build.gradle
+++ b/camera/integration-tests/camerapipetestapp/build.gradle
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -55,7 +53,7 @@
// Android Support Library
implementation("androidx.appcompat:appcompat:1.1.0")
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
// Camera Pipe
implementation(project(":camera:camera-camera2-pipe"))
diff --git a/camera/integration-tests/coretestapp/build.gradle b/camera/integration-tests/coretestapp/build.gradle
index 61455aa..a470a0b 100644
--- a/camera/integration-tests/coretestapp/build.gradle
+++ b/camera/integration-tests/coretestapp/build.gradle
@@ -15,11 +15,8 @@
* limitations under the License.
*/
-
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -75,7 +72,7 @@
implementation(project(":concurrent:concurrent-futures"))
// Android Support Library
- api(CONSTRAINT_LAYOUT, { transitive = true })
+ api(libs.constraintLayout)
implementation(libs.guavaAndroid)
implementation(libs.espressoIdlingResource)
// MLKit library: Barcode scanner
diff --git a/camera/integration-tests/extensionstestapp/build.gradle b/camera/integration-tests/extensionstestapp/build.gradle
index 77a4380..a379c83 100644
--- a/camera/integration-tests/extensionstestapp/build.gradle
+++ b/camera/integration-tests/extensionstestapp/build.gradle
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -42,7 +40,7 @@
implementation("androidx.concurrent:concurrent-futures:1.0.0")
// Android Support Library
- api(CONSTRAINT_LAYOUT, { transitive = true })
+ api(libs.constraintLayout)
implementation("androidx.appcompat:appcompat:1.1.0")
// Guava
diff --git a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
index 46c2472..7e10814 100644
--- a/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
+++ b/camera/integration-tests/extensionstestapp/src/main/java/androidx/camera/integration/extensions/CameraExtensionsActivity.java
@@ -182,7 +182,7 @@
mPreview = previewBuilder.build();
mPreview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
- CameraSelector cameraSelector = mExtensionsManager.getExtensionCameraSelector(
+ CameraSelector cameraSelector = mExtensionsManager.getExtensionEnabledCameraSelector(
mCameraProvider, mCurrentCameraSelector, extensionMode);
mCameraProvider.unbindAll();
diff --git a/camera/integration-tests/timingtestapp/build.gradle b/camera/integration-tests/timingtestapp/build.gradle
index 73186e7..416945d 100644
--- a/camera/integration-tests/timingtestapp/build.gradle
+++ b/camera/integration-tests/timingtestapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -47,6 +45,9 @@
buildFeatures {
viewBinding true
}
+ kotlinOptions {
+ freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
+ }
}
dependencies {
@@ -63,7 +64,7 @@
implementation("androidx.preference:preference:1.1.0")
implementation("androidx.exifinterface:exifinterface:1.0.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.2.0")
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation(libs.kotlinStdlib)
implementation(libs.kotlinCoroutinesAndroid)
diff --git a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
index f86966c..5c393cc 100644
--- a/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
+++ b/camera/integration-tests/timingtestapp/src/main/java/androidx/camera/integration/antelope/cameracontrollers/CameraXController.kt
@@ -42,6 +42,7 @@
import androidx.concurrent.futures.await
import androidx.core.util.Consumer
import androidx.lifecycle.LifecycleOwner
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -57,6 +58,7 @@
* All the needed Cmaera X use cases should be bound before starting the lifecycle. Depending on
* the test, bind either the preview case, or both the preview and image capture case.
*/
+@kotlin.OptIn(DelicateCoroutinesApi::class)
internal fun cameraXOpenCamera(
activity: MainActivity,
params: CameraParams,
@@ -194,6 +196,7 @@
/**
* End Camera X custom lifecycle, unbind use cases, and start timing the camera close.
*/
+@kotlin.OptIn(DelicateCoroutinesApi::class)
internal fun closeCameraX(activity: MainActivity, params: CameraParams, testConfig: TestConfig) {
logd("In closecameraX, camera: " + params.id + ", test: " + testConfig.currentRunningTest)
diff --git a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/car/NavigationCarAppService.java b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/car/NavigationCarAppService.java
index e555e2b..eadd1ad 100644
--- a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/car/NavigationCarAppService.java
+++ b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/car/NavigationCarAppService.java
@@ -16,7 +16,6 @@
package androidx.car.app.sample.navigation.common.car;
-import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -97,7 +96,6 @@
}
}
- @SuppressLint("UnsafeNewApiCall")
private void createNotificationChannel() {
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
diff --git a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
index 21dd896..0dbe1c4 100644
--- a/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
+++ b/car/app/app-samples/navigation/common/src/main/java/androidx/car/app/sample/navigation/common/nav/NavigationService.java
@@ -18,7 +18,6 @@
import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
-import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -420,7 +419,6 @@
stopSelf();
}
- @SuppressLint("UnsafeNewApiCall")
private void playNavigationDirection(@RawRes int resourceId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
@@ -496,7 +494,6 @@
stopNavigation();
}
- @SuppressLint("UnsafeNewApiCall")
private void createNotificationChannel() {
mNotificationManager = getSystemService(NotificationManager.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/NotificationDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/NotificationDemoScreen.java
index 3bfc510..da975f2 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/NotificationDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/misc/NotificationDemoScreen.java
@@ -215,7 +215,7 @@
// Suppressing 'ObsoleteSdkInt' as this code is shared between APKs with different min SDK
// levels
- @SuppressLint({"UnsafeNewApiCall", "ObsoleteSdkInt"})
+ @SuppressLint("ObsoleteSdkInt")
private void sendNotification(CharSequence title, CharSequence text, String channelId,
CharSequence channelName, int notificationId, int importance) {
CarNotificationManager carNotificationManager =
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationService.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationService.java
index 8d2b6da..3d1b041 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationService.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationService.java
@@ -104,7 +104,7 @@
*/
// Suppressing 'ObsoleteSdkInt' as this code is shared between APKs with different min SDK
// levels
- @SuppressLint({"UnsafeNewApiCall", "ObsoleteSdkInt"})
+ @SuppressLint({"ObsoleteSdkInt"})
private static void initNotifications(Context context) {
NotificationChannelCompat navChannel =
new NotificationChannelCompat.Builder(
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationsDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationsDemoScreen.java
index 27b7cdf..2db959c 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationsDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/navigation/NavigationNotificationsDemoScreen.java
@@ -40,7 +40,7 @@
// Suppressing 'ObsoleteSdkInt' as this code is shared between APKs with different min SDK
// levels
- @SuppressLint({"UnsafeNewApiCall", "ObsoleteSdkInt"})
+ @SuppressLint({"ObsoleteSdkInt"})
@NonNull
@Override
public Template onGetTemplate() {
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
index 9c67c3f..b5997ab 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/templates/SignInTemplateDemoScreen.java
@@ -31,7 +31,6 @@
import androidx.car.app.model.CarIcon;
import androidx.car.app.model.InputCallback;
import androidx.car.app.model.MessageTemplate;
-import androidx.car.app.model.OnInputCompletedListener;
import androidx.car.app.model.ParkedOnlyOnClickListener;
import androidx.car.app.model.Template;
import androidx.car.app.model.signin.InputSignInMethod;
@@ -200,17 +199,20 @@
}
private Template getPasswordSignInTemplate() {
- OnInputCompletedListener listener = text -> {
- // Mocked password validation
- if (!EXPECTED_PASSWORD.equals(text)) {
- mErrorMessage = "Invalid password";
- } else {
- mErrorMessage = "";
- mState = State.SIGNED_IN;
+ InputCallback callback = new InputCallback() {
+ @Override
+ public void onInputSubmitted(@NonNull String text) {
+ // Mocked password validation
+ if (!EXPECTED_PASSWORD.equals(text)) {
+ mErrorMessage = "Invalid password";
+ } else {
+ mErrorMessage = "";
+ mState = State.SIGNED_IN;
+ }
+ invalidate();
}
- invalidate();
};
- InputSignInMethod.Builder builder = new InputSignInMethod.Builder(listener)
+ InputSignInMethod.Builder builder = new InputSignInMethod.Builder(callback)
.setHint("Password")
.setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD);
if (mErrorMessage != null) {
diff --git a/car/app/app/api/current.txt b/car/app/app/api/current.txt
index 73194f8..202be75 100644
--- a/car/app/app/api/current.txt
+++ b/car/app/app/api/current.txt
@@ -246,8 +246,8 @@
package androidx.car.app.hardware.info {
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Accelerometer {
- ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getForces();
+ ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getForces();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class CarHardwareLocation {
@@ -283,8 +283,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Compass {
- ctor public Compass(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getOrientations();
+ ctor public Compass(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getOrientations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyLevel {
@@ -306,8 +306,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyProfile {
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getEvConnectorTypes();
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getFuelTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getEvConnectorTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getFuelTypes();
field public static final int EVCONNECTOR_TYPE_CHADEMO = 3; // 0x3
field public static final int EVCONNECTOR_TYPE_COMBO_1 = 4; // 0x4
field public static final int EVCONNECTOR_TYPE_COMBO_2 = 5; // 0x5
@@ -339,13 +339,13 @@
public static final class EnergyProfile.Builder {
ctor public EnergyProfile.Builder();
method public androidx.car.app.hardware.info.EnergyProfile build();
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Gyroscope {
- ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getRotations();
+ ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getRotations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Mileage {
@@ -738,14 +738,6 @@
method public void onClick();
}
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedDelegate {
- method public void sendInputCompleted(String, androidx.car.app.OnDoneCallback);
- }
-
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedListener {
- method public void onInputCompleted(String);
- }
-
@androidx.car.app.annotations.CarProtocol public interface OnItemVisibilityChangedDelegate {
method public void sendItemVisibilityChanged(int, int, androidx.car.app.OnDoneCallback);
}
@@ -957,10 +949,9 @@
method public androidx.car.app.model.CarText? getDefaultValue();
method public androidx.car.app.model.CarText? getErrorMessage();
method public androidx.car.app.model.CarText? getHint();
- method @androidx.car.app.annotations.RequiresCarApi(2) public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
+ method public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
method public int getInputType();
method public int getKeyboardType();
- method public androidx.car.app.model.OnInputCompletedDelegate getOnInputCompletedDelegate();
method public boolean isShowKeyboardByDefault();
field public static final int INPUT_TYPE_DEFAULT = 1; // 0x1
field public static final int INPUT_TYPE_PASSWORD = 2; // 0x2
@@ -971,8 +962,7 @@
}
public static final class InputSignInMethod.Builder {
- ctor public InputSignInMethod.Builder(androidx.car.app.model.OnInputCompletedListener);
- ctor @androidx.car.app.annotations.RequiresCarApi(2) public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
+ ctor public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
method public androidx.car.app.model.signin.InputSignInMethod build();
method public androidx.car.app.model.signin.InputSignInMethod.Builder setDefaultValue(String);
method public androidx.car.app.model.signin.InputSignInMethod.Builder setErrorMessage(CharSequence);
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index b5cdda3..85629b1 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -249,8 +249,8 @@
package androidx.car.app.hardware.info {
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Accelerometer {
- ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getForces();
+ ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getForces();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class CarHardwareLocation {
@@ -286,8 +286,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Compass {
- ctor public Compass(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getOrientations();
+ ctor public Compass(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getOrientations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyLevel {
@@ -309,8 +309,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyProfile {
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getEvConnectorTypes();
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getFuelTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getEvConnectorTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getFuelTypes();
field public static final int EVCONNECTOR_TYPE_CHADEMO = 3; // 0x3
field public static final int EVCONNECTOR_TYPE_COMBO_1 = 4; // 0x4
field public static final int EVCONNECTOR_TYPE_COMBO_2 = 5; // 0x5
@@ -342,13 +342,13 @@
public static final class EnergyProfile.Builder {
ctor public EnergyProfile.Builder();
method public androidx.car.app.hardware.info.EnergyProfile build();
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Gyroscope {
- ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getRotations();
+ ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getRotations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Mileage {
@@ -741,14 +741,6 @@
method public void onClick();
}
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedDelegate {
- method public void sendInputCompleted(String, androidx.car.app.OnDoneCallback);
- }
-
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedListener {
- method public void onInputCompleted(String);
- }
-
@androidx.car.app.annotations.CarProtocol public interface OnItemVisibilityChangedDelegate {
method public void sendItemVisibilityChanged(int, int, androidx.car.app.OnDoneCallback);
}
@@ -960,10 +952,9 @@
method public androidx.car.app.model.CarText? getDefaultValue();
method public androidx.car.app.model.CarText? getErrorMessage();
method public androidx.car.app.model.CarText? getHint();
- method @androidx.car.app.annotations.RequiresCarApi(2) public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
+ method public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
method public int getInputType();
method public int getKeyboardType();
- method public androidx.car.app.model.OnInputCompletedDelegate getOnInputCompletedDelegate();
method public boolean isShowKeyboardByDefault();
field public static final int INPUT_TYPE_DEFAULT = 1; // 0x1
field public static final int INPUT_TYPE_PASSWORD = 2; // 0x2
@@ -974,8 +965,7 @@
}
public static final class InputSignInMethod.Builder {
- ctor public InputSignInMethod.Builder(androidx.car.app.model.OnInputCompletedListener);
- ctor @androidx.car.app.annotations.RequiresCarApi(2) public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
+ ctor public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
method public androidx.car.app.model.signin.InputSignInMethod build();
method public androidx.car.app.model.signin.InputSignInMethod.Builder setDefaultValue(String);
method public androidx.car.app.model.signin.InputSignInMethod.Builder setErrorMessage(CharSequence);
diff --git a/car/app/app/api/restricted_current.txt b/car/app/app/api/restricted_current.txt
index 73194f8..202be75 100644
--- a/car/app/app/api/restricted_current.txt
+++ b/car/app/app/api/restricted_current.txt
@@ -246,8 +246,8 @@
package androidx.car.app.hardware.info {
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Accelerometer {
- ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getForces();
+ ctor public Accelerometer(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getForces();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class CarHardwareLocation {
@@ -283,8 +283,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Compass {
- ctor public Compass(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getOrientations();
+ ctor public Compass(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getOrientations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyLevel {
@@ -306,8 +306,8 @@
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class EnergyProfile {
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getEvConnectorTypes();
- method public androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!> getFuelTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getEvConnectorTypes();
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!> getFuelTypes();
field public static final int EVCONNECTOR_TYPE_CHADEMO = 3; // 0x3
field public static final int EVCONNECTOR_TYPE_COMBO_1 = 4; // 0x4
field public static final int EVCONNECTOR_TYPE_COMBO_2 = 5; // 0x5
@@ -339,13 +339,13 @@
public static final class EnergyProfile.Builder {
ctor public EnergyProfile.Builder();
method public androidx.car.app.hardware.info.EnergyProfile build();
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
- method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.lang.Integer![]!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setEvConnectorTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
+ method public androidx.car.app.hardware.info.EnergyProfile.Builder setFuelTypes(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Integer!>!>);
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Gyroscope {
- ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.lang.Float![]!>);
- method public androidx.car.app.hardware.common.CarValue<java.lang.Float![]!> getRotations();
+ ctor public Gyroscope(androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!>);
+ method public androidx.car.app.hardware.common.CarValue<java.util.List<java.lang.Float!>!> getRotations();
}
@androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.RequiresCarApi(3) public final class Mileage {
@@ -738,14 +738,6 @@
method public void onClick();
}
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedDelegate {
- method public void sendInputCompleted(String, androidx.car.app.OnDoneCallback);
- }
-
- @androidx.car.app.annotations.RequiresCarApi(2) public interface OnInputCompletedListener {
- method public void onInputCompleted(String);
- }
-
@androidx.car.app.annotations.CarProtocol public interface OnItemVisibilityChangedDelegate {
method public void sendItemVisibilityChanged(int, int, androidx.car.app.OnDoneCallback);
}
@@ -957,10 +949,9 @@
method public androidx.car.app.model.CarText? getDefaultValue();
method public androidx.car.app.model.CarText? getErrorMessage();
method public androidx.car.app.model.CarText? getHint();
- method @androidx.car.app.annotations.RequiresCarApi(2) public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
+ method public androidx.car.app.model.InputCallbackDelegate getInputCallbackDelegate();
method public int getInputType();
method public int getKeyboardType();
- method public androidx.car.app.model.OnInputCompletedDelegate getOnInputCompletedDelegate();
method public boolean isShowKeyboardByDefault();
field public static final int INPUT_TYPE_DEFAULT = 1; // 0x1
field public static final int INPUT_TYPE_PASSWORD = 2; // 0x2
@@ -971,8 +962,7 @@
}
public static final class InputSignInMethod.Builder {
- ctor public InputSignInMethod.Builder(androidx.car.app.model.OnInputCompletedListener);
- ctor @androidx.car.app.annotations.RequiresCarApi(2) public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
+ ctor public InputSignInMethod.Builder(androidx.car.app.model.InputCallback);
method public androidx.car.app.model.signin.InputSignInMethod build();
method public androidx.car.app.model.signin.InputSignInMethod.Builder setDefaultValue(String);
method public androidx.car.app.model.signin.InputSignInMethod.Builder setErrorMessage(CharSequence);
diff --git a/car/app/app/src/main/aidl/androidx/car/app/model/IOnInputCompletedListener.aidl b/car/app/app/src/main/aidl/androidx/car/app/model/IOnInputCompletedListener.aidl
deleted file mode 100644
index 632f921..0000000
--- a/car/app/app/src/main/aidl/androidx/car/app/model/IOnInputCompletedListener.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2021 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.car.app.model;
-
-import androidx.car.app.IOnDoneCallback;
-
-/** @hide */
-oneway interface IOnInputCompletedListener {
- void onInputCompleted(String value, IOnDoneCallback callback) = 1;
-}
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppPermission.java b/car/app/app/src/main/java/androidx/car/app/CarAppPermission.java
index b83ee11..4d5fba8 100644
--- a/car/app/app/src/main/java/androidx/car/app/CarAppPermission.java
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppPermission.java
@@ -56,25 +56,28 @@
* Permission that apps can use to get access to the navigation templates of the car app
* library.
*
- * <p>This permission can <b>ONLY</b> be requested by apps that declare themselves as a
- * navigation app.
- *
- * @see CarAppService#CATEGORY_NAVIGATION_APP
+ * <p>This permission should only be declared by apps that belong to one of the categories that
+ * allow using the navigation templates. See
+ * <a href="https://developer.android.com/training/cars/navigation#access-navigation-templates">the
+ * documentation</a> for the list of such categories. An app not in one of those categories
+ * requesting this permission may be rejected upon submission to the Play Store. See
+ * {@link CarAppService} for how to declare your app's category.
*/
public static final String NAVIGATION_TEMPLATES = "androidx.car.app.NAVIGATION_TEMPLATES";
/**
* Permission that apps can use to get access to templates that show a map such as
- * {@link androidx.car.app.model.PlaceListMapTemplate}. Templates used by navigation apps that
+ * {@link androidx.car.app.model.PlaceListMapTemplate}. Templates used by navigation apps that
* draw their own maps
* (e.g. {@link androidx.car.app.navigation.model.PlaceListNavigationTemplate}) don't require
* this permission.
*
- * <p>This permission can <b>ONLY</b> be requested by apps that declare themselves as a
- * parking or charging app.
- *
- * @see CarAppService#CATEGORY_CHARGING_APP
- * @see CarAppService#CATEGORY_PARKING_APP
+ * <p>This permission should only be declared by apps that belong to one of the categories that
+ * allow using the map templates. See
+ * <a href="https://developer.android.com/training/cars/navigation#access-map-template">the
+ * documentation</a> for the list of such categories. An app not in one of those categories
+ * requesting this permission may be rejected upon submission to the Play Store. See
+ * {@link CarAppService} for how to declare your app's category.
*/
public static final String MAP_TEMPLATES = "androidx.car.app.MAP_TEMPLATES";
diff --git a/car/app/app/src/main/java/androidx/car/app/CarAppService.java b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
index c3ac61e..572ea9c 100644
--- a/car/app/app/src/main/java/androidx/car/app/CarAppService.java
+++ b/car/app/app/src/main/java/androidx/car/app/CarAppService.java
@@ -72,6 +72,9 @@
* </service>
* }</pre>
*
+ * <p>For a list of all the supported categories see
+ * <a href="https://developer.android.com/training/cars/navigation#supported-app-categories">Supported App Categories</a>.
+ *
* <h4>Accessing Location</h4>
*
* When the app is running in the car display, the system will not consider it as being in the
diff --git a/car/app/app/src/main/java/androidx/car/app/hardware/common/CarValue.java b/car/app/app/src/main/java/androidx/car/app/hardware/common/CarValue.java
index ede436a..eca9dbc 100644
--- a/car/app/app/src/main/java/androidx/car/app/hardware/common/CarValue.java
+++ b/car/app/app/src/main/java/androidx/car/app/hardware/common/CarValue.java
@@ -26,6 +26,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
import java.util.Objects;
/**
@@ -112,11 +113,11 @@
/** @hide */
@RestrictTo(LIBRARY)
- public static final CarValue<Float[]> UNIMPLEMENTED_FLOAT_ARRAY = unimplemented();
+ public static final CarValue<List<Float>> UNIMPLEMENTED_FLOAT_LIST = unimplemented();
/** @hide */
@RestrictTo(LIBRARY)
- public static final CarValue<Integer[]> UNIMPLEMENTED_INTEGER_ARRAY = unimplemented();
+ public static final CarValue<List<Integer>> UNIMPLEMENTED_INTEGER_LIST = unimplemented();
/**
* Returns a the data value or {@code null} if the status is not successful.
diff --git a/car/app/app/src/main/java/androidx/car/app/hardware/info/Accelerometer.java b/car/app/app/src/main/java/androidx/car/app/hardware/info/Accelerometer.java
index 07294ca..08b562d 100644
--- a/car/app/app/src/main/java/androidx/car/app/hardware/info/Accelerometer.java
+++ b/car/app/app/src/main/java/androidx/car/app/hardware/info/Accelerometer.java
@@ -24,6 +24,7 @@
import androidx.car.app.annotations.RequiresCarApi;
import androidx.car.app.hardware.common.CarValue;
+import java.util.List;
import java.util.Objects;
/** Information about car specific accelerometers available from the car hardware. */
@@ -33,7 +34,7 @@
@Keep
@NonNull
- private final CarValue<Float[]> mForces;
+ private final CarValue<List<Float>> mForces;
/**
* Returns the raw accelerometer force data from the car sensor.
@@ -41,7 +42,7 @@
* <p>Follows the same format as {@link android.hardware.SensorEvent#values}.
*/
@NonNull
- public CarValue<Float[]> getForces() {
+ public CarValue<List<Float>> getForces() {
return mForces;
}
@@ -74,12 +75,12 @@
*
* @throws NullPointerException if {@code forces} is {@code null}
*/
- public Accelerometer(@NonNull CarValue<Float[]> forces) {
+ public Accelerometer(@NonNull CarValue<List<Float>> forces) {
mForces = requireNonNull(forces);
}
/** Constructs an empty instance, used by serialization code. */
private Accelerometer() {
- mForces = CarValue.UNIMPLEMENTED_FLOAT_ARRAY;
+ mForces = CarValue.UNIMPLEMENTED_FLOAT_LIST;
}
}
diff --git a/car/app/app/src/main/java/androidx/car/app/hardware/info/Compass.java b/car/app/app/src/main/java/androidx/car/app/hardware/info/Compass.java
index 4b7ea45..2142740 100644
--- a/car/app/app/src/main/java/androidx/car/app/hardware/info/Compass.java
+++ b/car/app/app/src/main/java/androidx/car/app/hardware/info/Compass.java
@@ -24,6 +24,7 @@
import androidx.car.app.annotations.RequiresCarApi;
import androidx.car.app.hardware.common.CarValue;
+import java.util.List;
import java.util.Objects;
/** Information about car specific compass available from the car hardware. */
@@ -33,7 +34,7 @@
@Keep
@NonNull
- private final CarValue<Float[]> mOrientations;
+ private final CarValue<List<Float>> mOrientations;
/**
* Returns the raw compass data from the car sensor.
@@ -41,8 +42,8 @@
* <p>Follows the same format as {@link android.hardware.SensorEvent#values}.
*/
@NonNull
- public CarValue<Float[]> getOrientations() {
- return requireNonNull(mOrientations);
+ public CarValue<List<Float>> getOrientations() {
+ return mOrientations;
}
@Override
@@ -74,12 +75,12 @@
*
* @throws NullPointerException if {@code orientations} is {@code null}
*/
- public Compass(@NonNull CarValue<Float[]> orientations) {
+ public Compass(@NonNull CarValue<List<Float>> orientations) {
mOrientations = requireNonNull(orientations);
}
/** Constructs an empty instance, used by serialization code. */
private Compass() {
- mOrientations = CarValue.UNIMPLEMENTED_FLOAT_ARRAY;
+ mOrientations = CarValue.UNIMPLEMENTED_FLOAT_LIST;
}
}
diff --git a/car/app/app/src/main/java/androidx/car/app/hardware/info/EnergyProfile.java b/car/app/app/src/main/java/androidx/car/app/hardware/info/EnergyProfile.java
index 7f7bc31..948800f 100644
--- a/car/app/app/src/main/java/androidx/car/app/hardware/info/EnergyProfile.java
+++ b/car/app/app/src/main/java/androidx/car/app/hardware/info/EnergyProfile.java
@@ -30,6 +30,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
import java.util.Objects;
/** Information about car hardware fuel profile such as fuel types and connector ports. */
@@ -168,11 +169,11 @@
@Keep
@NonNull
- private final CarValue<Integer[]> mEvConnectorTypes;
+ private final CarValue<List<Integer>> mEvConnectorTypes;
@Keep
@NonNull
- private final CarValue<Integer[]> mFuelTypes;
+ private final CarValue<List<Integer>> mFuelTypes;
/**
* Returns an array of the available EV connectors.
@@ -182,7 +183,7 @@
* is known but not in the current list {@link #EVCONNECTOR_TYPE_UNKNOWN} will be returned.
*/
@NonNull
- public CarValue<Integer[]> getEvConnectorTypes() {
+ public CarValue<List<Integer>> getEvConnectorTypes() {
return requireNonNull(mEvConnectorTypes);
}
@@ -194,7 +195,7 @@
* {@link #EVCONNECTOR_TYPE_UNKNOWN} will be returned.
*/
@NonNull
- public CarValue<Integer[]> getFuelTypes() {
+ public CarValue<List<Integer>> getFuelTypes() {
return requireNonNull(mFuelTypes);
}
@@ -230,14 +231,14 @@
/** Constructs an empty instance, used by serialization code. */
private EnergyProfile() {
- mEvConnectorTypes = CarValue.UNIMPLEMENTED_INTEGER_ARRAY;
- mFuelTypes = CarValue.UNIMPLEMENTED_INTEGER_ARRAY;
+ mEvConnectorTypes = CarValue.UNIMPLEMENTED_INTEGER_LIST;
+ mFuelTypes = CarValue.UNIMPLEMENTED_INTEGER_LIST;
}
/** A builder of {@link EnergyProfile}. */
public static final class Builder {
- CarValue<Integer[]> mEvConnectorTypes = CarValue.UNIMPLEMENTED_INTEGER_ARRAY;
- CarValue<Integer[]> mFuelTypes = CarValue.UNIMPLEMENTED_INTEGER_ARRAY;
+ CarValue<List<Integer>> mEvConnectorTypes = CarValue.UNIMPLEMENTED_INTEGER_LIST;
+ CarValue<List<Integer>> mFuelTypes = CarValue.UNIMPLEMENTED_INTEGER_LIST;
/**
* Sets the cars EV connector types.
@@ -245,7 +246,7 @@
* @throws NullPointerException if {@code evConnectorTypes} is {@code null}
*/
@NonNull
- public Builder setEvConnectorTypes(@NonNull CarValue<Integer[]> evConnectorTypes) {
+ public Builder setEvConnectorTypes(@NonNull CarValue<List<Integer>> evConnectorTypes) {
mEvConnectorTypes = requireNonNull(evConnectorTypes);
return this;
}
@@ -256,7 +257,7 @@
* @throws NullPointerException if {@code fuelTypes} is {@code null}
*/
@NonNull
- public Builder setFuelTypes(@NonNull CarValue<Integer[]> fuelTypes) {
+ public Builder setFuelTypes(@NonNull CarValue<List<Integer>> fuelTypes) {
mFuelTypes = requireNonNull(fuelTypes);
return this;
}
diff --git a/car/app/app/src/main/java/androidx/car/app/hardware/info/Gyroscope.java b/car/app/app/src/main/java/androidx/car/app/hardware/info/Gyroscope.java
index 4799961..e5a8fa5 100644
--- a/car/app/app/src/main/java/androidx/car/app/hardware/info/Gyroscope.java
+++ b/car/app/app/src/main/java/androidx/car/app/hardware/info/Gyroscope.java
@@ -24,6 +24,7 @@
import androidx.car.app.annotations.RequiresCarApi;
import androidx.car.app.hardware.common.CarValue;
+import java.util.List;
import java.util.Objects;
/** Information about car specific gyroscopes available from the car hardware. */
@@ -32,12 +33,12 @@
public final class Gyroscope {
@Keep
@NonNull
- private final CarValue<Float[]> mRotations;
+ private final CarValue<List<Float>> mRotations;
/** Returns the raw gyroscope data from the car sensor. */
@NonNull
- public CarValue<Float[]> getRotations() {
- return requireNonNull(mRotations);
+ public CarValue<List<Float>> getRotations() {
+ return mRotations;
}
@Override
@@ -69,12 +70,12 @@
*
* @throws NullPointerException if {@code rotations} is {@code null}
*/
- public Gyroscope(@NonNull CarValue<Float[]> rotations) {
+ public Gyroscope(@NonNull CarValue<List<Float>> rotations) {
mRotations = requireNonNull(rotations);
}
/** Constructs an empty instance, used by serialization code. */
private Gyroscope() {
- mRotations = CarValue.UNIMPLEMENTED_FLOAT_ARRAY;
+ mRotations = CarValue.UNIMPLEMENTED_FLOAT_LIST;
}
}
diff --git a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegate.java b/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegate.java
deleted file mode 100644
index 26253de..0000000
--- a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegate.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2021 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.car.app.model;
-
-import android.annotation.SuppressLint;
-
-import androidx.annotation.NonNull;
-import androidx.car.app.OnDoneCallback;
-import androidx.car.app.annotations.RequiresCarApi;
-
-/**
- * A host-side delegate for sending {@link OnInputCompletedListener} events to the car app.
- */
-@RequiresCarApi(2)
-public interface OnInputCompletedDelegate {
- /**
- * Notifies that user input has completed.
- *
- * @param value the text entered
- * @param callback the {@link OnDoneCallback} to trigger when the client finishes handling
- * the event
- */
- // This mirrors the AIDL class and is not supposed to support an executor as an input.
- @SuppressLint("ExecutorRegistration")
- void sendInputCompleted(@NonNull String value, @NonNull OnDoneCallback callback);
-}
diff --git a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegateImpl.java b/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegateImpl.java
deleted file mode 100644
index 3ac951db..0000000
--- a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedDelegateImpl.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2021 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.car.app.model;
-
-import static androidx.annotation.RestrictTo.Scope.LIBRARY;
-
-import static java.util.Objects.requireNonNull;
-
-import android.annotation.SuppressLint;
-import android.os.RemoteException;
-
-import androidx.annotation.Keep;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RestrictTo;
-import androidx.car.app.IOnDoneCallback;
-import androidx.car.app.OnDoneCallback;
-import androidx.car.app.utils.RemoteUtils;
-
-/**
- * Implementation class for {@link OnInputCompletedDelegate} to allow IPC for text-input-related
- * events.
- *
- * @hide
- */
-@RestrictTo(LIBRARY)
-public class OnInputCompletedDelegateImpl implements OnInputCompletedDelegate {
-
- @Keep
- @Nullable
- private final IOnInputCompletedListener mListener;
-
- @Override
- public void sendInputCompleted(@NonNull String text, @NonNull OnDoneCallback callback) {
- try {
- requireNonNull(mListener).onInputCompleted(text,
- RemoteUtils.createOnDoneCallbackStub(callback));
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
-
- /** Creates an instance of {@link OnInputCompletedDelegateImpl}. */
- // This mirrors the AIDL class and is not supposed to support an executor as an input.
- @SuppressLint("ExecutorRegistration")
- @NonNull
- public static OnInputCompletedDelegate create(@NonNull OnInputCompletedListener listener) {
- return new OnInputCompletedDelegateImpl(requireNonNull(listener));
- }
-
- private OnInputCompletedDelegateImpl(@NonNull OnInputCompletedListener listener) {
- mListener = new OnInputCompletedStub(listener);
- }
-
- /** For serialization. */
- private OnInputCompletedDelegateImpl() {
- mListener = null;
- }
-
- @Keep // We need to keep these stub for Bundler serialization logic.
- private static class OnInputCompletedStub extends IOnInputCompletedListener.Stub {
- private final OnInputCompletedListener mListener;
-
- OnInputCompletedStub(OnInputCompletedListener listener) {
- mListener = listener;
- }
-
- @Override
- public void onInputCompleted(String value, IOnDoneCallback callback) {
- RemoteUtils.dispatchCallFromHost(callback, "onInputCompleted",
- () -> {
- mListener.onInputCompleted(value);
- return null;
-
- });
- }
- }
-}
diff --git a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedListener.java b/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedListener.java
deleted file mode 100644
index 058d711..0000000
--- a/car/app/app/src/main/java/androidx/car/app/model/OnInputCompletedListener.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2021 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.car.app.model;
-
-import androidx.annotation.NonNull;
-import androidx.car.app.annotations.RequiresCarApi;
-
-/** A listener for handling text input completion event. */
-@RequiresCarApi(2)
-public interface OnInputCompletedListener {
- /**
- * Notifies when the user finished entering text in an input box.
- *
- * <p>This event is sent when the user finishes typing in the keyboard and pressed enter.
- * If the user simply stops typing and closes the keyboard, this event will not be sent.
- *
- * @param text the text that was entered, or an empty string if no text was typed.
- */
- void onInputCompleted(@NonNull String text);
-}
diff --git a/car/app/app/src/main/java/androidx/car/app/model/signin/InputSignInMethod.java b/car/app/app/src/main/java/androidx/car/app/model/signin/InputSignInMethod.java
index 7cf4e7f..a8f4b1bb 100644
--- a/car/app/app/src/main/java/androidx/car/app/model/signin/InputSignInMethod.java
+++ b/car/app/app/src/main/java/androidx/car/app/model/signin/InputSignInMethod.java
@@ -33,9 +33,6 @@
import androidx.car.app.model.InputCallback;
import androidx.car.app.model.InputCallbackDelegate;
import androidx.car.app.model.InputCallbackDelegateImpl;
-import androidx.car.app.model.OnInputCompletedDelegate;
-import androidx.car.app.model.OnInputCompletedDelegateImpl;
-import androidx.car.app.model.OnInputCompletedListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -126,9 +123,6 @@
@Keep
@KeyboardType
private final int mKeyboardType;
- @Keep
- @Nullable
- private final OnInputCompletedDelegate mOnInputCompletedDelegate;
@Nullable
private final InputCallbackDelegate mInputCallbackDelegate;
@Keep
@@ -189,21 +183,10 @@
}
/**
- * Returns the {@link OnInputCompletedDelegate} for input callbacks.
- *
- * @see Builder#Builder(OnInputCompletedListener)
- */
- @NonNull
- public OnInputCompletedDelegate getOnInputCompletedDelegate() {
- return requireNonNull(mOnInputCompletedDelegate);
- }
-
- /**
* Returns the {@link InputCallbackDelegate} for input callbacks.
*
* @see Builder#Builder(InputCallback)
*/
- @RequiresCarApi(2)
@NonNull
public InputCallbackDelegate getInputCallbackDelegate() {
return requireNonNull(mInputCallbackDelegate);
@@ -255,7 +238,6 @@
mInputType = builder.mInputType;
mErrorMessage = builder.mErrorMessage;
mKeyboardType = builder.mKeyboardType;
- mOnInputCompletedDelegate = builder.mOnInputCompletedDelegate;
mInputCallbackDelegate = builder.mInputCallbackDelegate;
mShowKeyboardByDefault = builder.mShowKeyboardByDefault;
}
@@ -267,14 +249,12 @@
mInputType = INPUT_TYPE_DEFAULT;
mErrorMessage = null;
mKeyboardType = KEYBOARD_DEFAULT;
- mOnInputCompletedDelegate = null;
mInputCallbackDelegate = null;
mShowKeyboardByDefault = false;
}
/** A builder of {@link InputSignInMethod}. */
public static final class Builder {
- @Nullable final OnInputCompletedDelegate mOnInputCompletedDelegate;
@Nullable final InputCallbackDelegate mInputCallbackDelegate;
@Nullable
CarText mHint;
@@ -399,29 +379,11 @@
* <p>Note that the listener relates to UI events and will be executed on the main thread
* using {@link Looper#getMainLooper()}.
*
- * @param listener the {@link OnInputCompletedListener} to be notified of input events
- * @throws NullPointerException if {@code listener} is {@code null}
- */
- @SuppressLint("ExecutorRegistration")
- public Builder(@NonNull OnInputCompletedListener listener) {
- mInputCallbackDelegate = null;
- mOnInputCompletedDelegate = OnInputCompletedDelegateImpl.create(
- requireNonNull(listener));
- }
-
- /**
- * Returns an {@link InputSignInMethod.Builder} instance.
- *
- * <p>Note that the listener relates to UI events and will be executed on the main thread
- * using {@link Looper#getMainLooper()}.
- *
* @param listener the {@link InputCallbackDelegate} to be notified of input events
* @throws NullPointerException if {@code listener} is {@code null}
*/
- @RequiresCarApi(2)
@SuppressLint("ExecutorRegistration")
public Builder(@NonNull InputCallback listener) {
- mOnInputCompletedDelegate = null;
mInputCallbackDelegate = InputCallbackDelegateImpl.create(
requireNonNull(listener));
}
diff --git a/car/app/app/src/main/java/androidx/car/app/navigation/model/TravelEstimate.java b/car/app/app/src/main/java/androidx/car/app/navigation/model/TravelEstimate.java
index 16ff2cf6..68c5ed0 100644
--- a/car/app/app/src/main/java/androidx/car/app/navigation/model/TravelEstimate.java
+++ b/car/app/app/src/main/java/androidx/car/app/navigation/model/TravelEstimate.java
@@ -199,7 +199,6 @@
* @throws NullPointerException if {@code remainingDistance} or
* {@code arrivalTimeAtDestination} are {@code null}
*/
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(26)
@SuppressWarnings("AndroidJdkLibsChecker")
public Builder(
diff --git a/car/app/app/src/test/java/androidx/car/app/model/signin/InputSignInMethodTest.java b/car/app/app/src/test/java/androidx/car/app/model/signin/InputSignInMethodTest.java
index dc23b8b..70149e2 100644
--- a/car/app/app/src/test/java/androidx/car/app/model/signin/InputSignInMethodTest.java
+++ b/car/app/app/src/test/java/androidx/car/app/model/signin/InputSignInMethodTest.java
@@ -29,8 +29,6 @@
import androidx.car.app.OnDoneCallback;
import androidx.car.app.model.InputCallback;
import androidx.car.app.model.InputCallbackDelegate;
-import androidx.car.app.model.OnInputCompletedDelegate;
-import androidx.car.app.model.OnInputCompletedListener;
import org.junit.Rule;
import org.junit.Test;
@@ -49,26 +47,17 @@
public final MockitoRule mockito = MockitoJUnit.rule();
@Mock
- OnInputCompletedListener mListener;
- @Mock
InputCallback mCallback;
@Test
public void create_defaultValues() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener).build();
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback).build();
assertThat(signIn.getInputType()).isEqualTo(INPUT_TYPE_DEFAULT);
assertThat(signIn.getKeyboardType()).isEqualTo(KEYBOARD_DEFAULT);
assertThat(signIn.getHint()).isNull();
assertThat(signIn.getErrorMessage()).isNull();
assertThat(signIn.isShowKeyboardByDefault()).isFalse();
-
- OnInputCompletedDelegate delegate = signIn.getOnInputCompletedDelegate();
- OnDoneCallback onDoneCallback = mock(OnDoneCallback.class);
- delegate.sendInputCompleted("ABC", onDoneCallback);
-
- verify(mListener).onInputCompleted("ABC");
- verify(onDoneCallback).onSuccess(null);
}
@Test
@@ -97,7 +86,7 @@
@Test
public void create_withInputType() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(INPUT_TYPE_PASSWORD)
.build();
@@ -106,7 +95,7 @@
@Test
public void create_withKeyboardType() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setKeyboardType(KEYBOARD_EMAIL)
.build();
@@ -115,7 +104,7 @@
@Test
public void create_wtihPrompt() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setHint("Signin")
.build();
@@ -124,7 +113,7 @@
@Test
public void create_withMessage() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setErrorMessage("error")
.build();
@@ -133,7 +122,7 @@
@Test
public void create_showKeyboard() {
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setShowKeyboardByDefault(true)
.build();
@@ -147,7 +136,7 @@
String message = "error";
String instructions = "sign";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -156,7 +145,7 @@
.build();
assertThat(signIn)
- .isEqualTo(new InputSignInMethod.Builder(mListener)
+ .isEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -171,7 +160,7 @@
String message = "error";
String instructions = "sign";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(INPUT_TYPE_PASSWORD)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -180,7 +169,7 @@
.build();
assertThat(signIn)
- .isNotEqualTo(new InputSignInMethod.Builder(mListener)
+ .isNotEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(INPUT_TYPE_DEFAULT)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -195,7 +184,7 @@
String message = "error";
String instructions = "sign";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(KEYBOARD_EMAIL)
.setHint(instructions)
@@ -204,7 +193,7 @@
.build();
assertThat(signIn)
- .isNotEqualTo(new InputSignInMethod.Builder(mListener)
+ .isNotEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(KEYBOARD_DEFAULT)
.setHint(instructions)
@@ -219,7 +208,7 @@
int keyboardType = KEYBOARD_EMAIL;
String message = "error";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint("signin")
@@ -228,7 +217,7 @@
.build();
assertThat(signIn)
- .isNotEqualTo(new InputSignInMethod.Builder(mListener)
+ .isNotEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint("sign2")
@@ -243,7 +232,7 @@
int keyboardType = KEYBOARD_EMAIL;
String instructions = "sign";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -252,7 +241,7 @@
.build();
assertThat(signIn)
- .isNotEqualTo(new InputSignInMethod.Builder(mListener)
+ .isNotEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -268,7 +257,7 @@
String message = "error";
String instructions = "sign";
- InputSignInMethod signIn = new InputSignInMethod.Builder(mListener)
+ InputSignInMethod signIn = new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
@@ -277,7 +266,7 @@
.build();
assertThat(signIn)
- .isNotEqualTo(new InputSignInMethod.Builder(mListener)
+ .isNotEqualTo(new InputSignInMethod.Builder(mCallback)
.setInputType(inputType)
.setKeyboardType(keyboardType)
.setHint(instructions)
diff --git a/compose/animation/animation-core/src/androidMain/baseline-prof.txt b/compose/animation/animation-core/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..cc79ea0
--- /dev/null
+++ b/compose/animation/animation-core/src/androidMain/baseline-prof.txt
@@ -0,0 +1,8 @@
+# Baseline profile rules for androidx.compose.animation.core
+# =============================================
+# In practice it seems like almost every class in animation/core ends up getting loaded in even a
+# relatively small sample, and most end up getting marked as "HSP". Since Animation is a high value
+# target for performance (fade in, scroll, etc) we are going to be liberal in the animation profile
+# rules and just mark the entire module.
+HSPLandroidx/compose/animation/core/**;->**(**)**
+Landroidx/compose/animation/core/**;
\ No newline at end of file
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
index 6199066..1b0b921 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/AnimateAsState.kt
@@ -362,7 +362,7 @@
val animSpec by rememberUpdatedState(animationSpec)
val channel = remember { Channel<T>(Channel.CONFLATED) }
SideEffect {
- channel.offer(targetValue)
+ channel.trySend(targetValue)
}
LaunchedEffect(channel) {
for (target in channel) {
@@ -371,7 +371,7 @@
// will be received.
// It may not be an issue elsewhere, but in animation we want to avoid being one
// frame late.
- val newTarget = channel.poll() ?: target
+ val newTarget = channel.tryReceive().getOrNull() ?: target
launch {
if (newTarget != animatable.targetValue) {
animatable.animateTo(newTarget, animSpec)
diff --git a/compose/animation/animation/src/androidMain/baseline-prof.txt b/compose/animation/animation/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..3abf971
--- /dev/null
+++ b/compose/animation/animation/src/androidMain/baseline-prof.txt
@@ -0,0 +1,22 @@
+# Baseline profile rules for androidx.compose.animation
+# =============================================
+HSPLandroidx/compose/animation/FlingCalculatorKt;->**(**)**
+HSPLandroidx/compose/animation/SplineBasedDecayKt;->**(**)**
+HSPLandroidx/compose/animation/AndroidFlingSpline$FlingResult;-><init>(FF)V
+HSPLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->getDistanceCoefficient()F
+HSPLandroidx/compose/animation/AndroidFlingSpline$FlingResult;->getVelocityCoefficient()F
+HSPLandroidx/compose/animation/AndroidFlingSpline;->**(**)**
+HSPLandroidx/compose/animation/FlingCalculator;->**(**)**
+HSPLandroidx/compose/animation/FlingCalculator$FlingInfo;-><init>(FFJ)V
+HSPLandroidx/compose/animation/FlingCalculator$FlingInfo;->position(J)F
+HSPLandroidx/compose/animation/FlingCalculator$FlingInfo;->velocity(J)F
+HSPLandroidx/compose/animation/AndroidFlingSpline;->**(**)**
+HSPLandroidx/compose/animation/AnimatedVisibilityKt**->**(**)**
+HSPLandroidx/compose/animation/AnimatedVisibilityScope;-><init>(**)V
+HSPLandroidx/compose/animation/CrossfadeKt**->**(**)**
+HSPLandroidx/compose/animation/TransitionData;->**(**)**
+HSPLandroidx/compose/animation/SplineBasedFloatDecayAnimationSpec**->**(**)**
+HSPLandroidx/compose/animation/ChangeSize;->**(**)**
+HSPLandroidx/compose/animation/CrossfadeAnimationItem;->**(**)**
+HSPLandroidx/compose/animation/EnterExitTransitionKt;->**(**)**
+Landroidx/compose/animation/*;
\ No newline at end of file
diff --git a/compose/benchmark-utils/lint-baseline.xml b/compose/benchmark-utils/lint-baseline.xml
deleted file mode 100644
index 42a176b..0000000
--- a/compose/benchmark-utils/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.0.0-alpha15" type="baseline" client="cli" name="Lint" variant="all" version="7.0.0-alpha15">
-
-</issues>
diff --git a/compose/desktop/desktop/lint-baseline.xml b/compose/desktop/desktop/lint-baseline.xml
deleted file mode 100644
index 297ae16..0000000
--- a/compose/desktop/desktop/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-beta02" client="gradle" version="4.2.0-beta02">
-
-</issues>
diff --git a/compose/foundation/foundation-layout/api/1.0.0-beta09.txt b/compose/foundation/foundation-layout/api/1.0.0-beta09.txt
index f0785dd..c5b29be 100644
--- a/compose/foundation/foundation-layout/api/1.0.0-beta09.txt
+++ b/compose/foundation/foundation-layout/api/1.0.0-beta09.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/api/current.txt b/compose/foundation/foundation-layout/api/current.txt
index f0785dd..c5b29be 100644
--- a/compose/foundation/foundation-layout/api/current.txt
+++ b/compose/foundation/foundation-layout/api/current.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/api/public_plus_experimental_1.0.0-beta09.txt b/compose/foundation/foundation-layout/api/public_plus_experimental_1.0.0-beta09.txt
index 100fb08..a6093dd 100644
--- a/compose/foundation/foundation-layout/api/public_plus_experimental_1.0.0-beta09.txt
+++ b/compose/foundation/foundation-layout/api/public_plus_experimental_1.0.0-beta09.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
index 100fb08..a6093dd 100644
--- a/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation-layout/api/public_plus_experimental_current.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/api/restricted_1.0.0-beta09.txt b/compose/foundation/foundation-layout/api/restricted_1.0.0-beta09.txt
index 4b4369b..7dd49e8 100644
--- a/compose/foundation/foundation-layout/api/restricted_1.0.0-beta09.txt
+++ b/compose/foundation/foundation-layout/api/restricted_1.0.0-beta09.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/api/restricted_current.txt b/compose/foundation/foundation-layout/api/restricted_current.txt
index 4b4369b..7dd49e8 100644
--- a/compose/foundation/foundation-layout/api/restricted_current.txt
+++ b/compose/foundation/foundation-layout/api/restricted_current.txt
@@ -53,17 +53,17 @@
field public static final androidx.compose.foundation.layout.Arrangement.Absolute INSTANCE;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Horizontal {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Horizontal {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, androidx.compose.ui.unit.LayoutDirection layoutDirection, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.HorizontalOrVertical extends androidx.compose.foundation.layout.Arrangement.Horizontal androidx.compose.foundation.layout.Arrangement.Vertical {
property public default float spacing;
}
- @androidx.compose.runtime.Immutable public static interface Arrangement.Vertical {
+ @androidx.compose.runtime.Stable public static interface Arrangement.Vertical {
method public void arrange(androidx.compose.ui.unit.Density, int totalSize, int[] sizes, int[] outPositions);
method public default float getSpacing-D9Ej5fM();
property public default float spacing;
diff --git a/compose/foundation/foundation-layout/src/androidMain/baseline-prof.txt b/compose/foundation/foundation-layout/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..78b1a2f
--- /dev/null
+++ b/compose/foundation/foundation-layout/src/androidMain/baseline-prof.txt
@@ -0,0 +1,6 @@
+# Baseline profile rules for androidx.compose.foundation.layout
+# =============================================
+# Layout is incredibly important for performance, and represents many hot code paths. For now, we
+# will include all of the layout namespace
+HSPLandroidx/compose/foundation/layout/**->**(**)**
+Landroidx/compose/foundation/layout/**;
\ No newline at end of file
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
index 0a5320d..4fe2fd4 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/Arrangement.kt
@@ -35,7 +35,7 @@
/**
* Used to specify the horizontal arrangement of the layout's children in layouts like [Row].
*/
- @Immutable
+ @Stable
interface Horizontal {
/**
* Spacing that should be added between any two adjacent layout children.
@@ -63,7 +63,7 @@
/**
* Used to specify the vertical arrangement of the layout's children in layouts like [Column].
*/
- @Immutable
+ @Stable
interface Vertical {
/**
* Spacing that should be added between any two adjacent layout children.
@@ -90,7 +90,7 @@
* like [Row], or the vertical arrangement of the layout's children in vertical layouts like
* [Column].
*/
- @Immutable
+ @Stable
interface HorizontalOrVertical : Horizontal, Vertical {
/**
* Spacing that should be added between any two adjacent layout children.
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
index 625c3aa..e38a03a 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyColumnTest.kt
@@ -34,6 +34,7 @@
import androidx.compose.foundation.layout.requiredSizeIn
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -41,7 +42,6 @@
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.testutils.WithTouchSlop
import androidx.compose.testutils.assertIsEqualTo
@@ -89,9 +89,7 @@
import com.google.common.truth.IntegerSubject
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test
@@ -1542,15 +1540,12 @@
@Test
fun animateScrollToItemDoesNotScrollPastItem() {
lateinit var state: LazyListState
- lateinit var scope: CoroutineScope
var target = 0
var reverse = false
rule.setContent {
val listState = rememberLazyListState()
- val effectScope = rememberCoroutineScope()
SideEffect {
state = listState
- scope = effectScope
}
LazyColumn(Modifier.fillMaxSize(), listState) {
items(2500) { _ ->
@@ -1568,24 +1563,61 @@
// Try a bunch of different targets with varying spacing
listOf(500, 800, 1500, 1600, 1800).forEach {
target = it
- scope.launch {
- state.animateScrollToItem(target)
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.animateScrollToItem(target)
+ }
}
- rule.waitForIdle()
- assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
}
reverse = true
listOf(1600, 1500, 800, 500, 0).forEach {
target = it
- scope.launch {
- state.animateScrollToItem(target)
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.animateScrollToItem(target)
+ }
}
- rule.waitForIdle()
- assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
+ }
+ }
+
+ @Test
+ fun animateScrollToTheLastItemWhenItemsAreLargerThenTheScreen() {
+ lateinit var state: LazyListState
+ rule.setContent {
+ state = rememberLazyListState()
+ LazyColumn(Modifier.width(150.dp).height(100.dp), state) {
+ items(20) {
+ Box(Modifier.size(150.dp))
+ }
+ }
+ }
+
+ // Try a bunch of different start indexes
+ listOf(0, 5, 12).forEach {
+ val startIndex = it
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.scrollToItem(startIndex)
+ state.animateScrollToItem(19)
+ }
+ }
+
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(19)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt
index b24e18c..d081014 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListLayoutInfoTest.kt
@@ -247,11 +247,15 @@
@Test
fun viewportOffsetsAreCorrectWithContentPadding() {
val sizePx = 45
- val topPaddingPx = 10
- val bottomPaddingPx = 15
+ val startPaddingPx = 10
+ val endPaddingPx = 15
val sizeDp = with(rule.density) { sizePx.toDp() }
- val topPaddingDp = with(rule.density) { topPaddingPx.toDp() }
- val bottomPaddingDp = with(rule.density) { bottomPaddingPx.toDp() }
+ val topPaddingDp = with(rule.density) {
+ if (!reverseLayout) startPaddingPx.toDp() else endPaddingPx.toDp()
+ }
+ val bottomPaddingDp = with(rule.density) {
+ if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
+ }
lateinit var state: LazyListState
rule.setContent {
LazyColumn(
@@ -267,8 +271,8 @@
}
rule.runOnIdle {
- assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-topPaddingPx)
- assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - topPaddingPx)
+ assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
+ assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
index 74bf477..9be61a2 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyListsContentPaddingTest.kt
@@ -28,6 +28,7 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertHeightIsEqualTo
+import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo
import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
import androidx.compose.ui.test.assertWidthIsEqualTo
@@ -360,6 +361,42 @@
}
@Test
+ fun column_contentPaddingAndReverseLayout() {
+ val topPadding = itemSize * 2
+ val bottomPadding = itemSize / 2
+ val listSize = itemSize * 3
+ lateinit var state: LazyListState
+ rule.setContentWithTestViewConfiguration {
+ LazyColumn(
+ reverseLayout = true,
+ state = rememberLazyListState().also { state = it },
+ modifier = Modifier.requiredSize(listSize),
+ contentPadding = PaddingValues(top = topPadding, bottom = bottomPadding),
+ ) {
+ items(3) { index ->
+ Box(Modifier.requiredSize(itemSize).testTag("$index"))
+ }
+ }
+ }
+
+ rule.onNodeWithTag("0")
+ .assertTopPositionInRootIsEqualTo(listSize - bottomPadding - itemSize)
+ rule.onNodeWithTag("1")
+ .assertTopPositionInRootIsEqualTo(listSize - bottomPadding - itemSize * 2)
+ // Partially visible.
+ rule.onNodeWithTag("2")
+ .assertTopPositionInRootIsEqualTo(-itemSize / 2)
+
+ // Scroll to the top.
+ state.scrollBy(itemSize * 2.5f)
+
+ rule.onNodeWithTag("2").assertTopPositionInRootIsEqualTo(topPadding)
+ // Shouldn't be visible
+ rule.onNodeWithTag("1").assertIsNotDisplayed()
+ rule.onNodeWithTag("0").assertIsNotDisplayed()
+ }
+
+ @Test
fun row_contentPaddingIsApplied() {
lateinit var state: LazyListState
val containerSize = itemSize * 2
@@ -655,6 +692,42 @@
.assertHeightIsEqualTo(12.dp)
}
+ @Test
+ fun row_contentPaddingAndReverseLayout() {
+ val startPadding = itemSize * 2
+ val endPadding = itemSize / 2
+ val listSize = itemSize * 3
+ lateinit var state: LazyListState
+ rule.setContentWithTestViewConfiguration {
+ LazyRow(
+ reverseLayout = true,
+ state = rememberLazyListState().also { state = it },
+ modifier = Modifier.requiredSize(listSize),
+ contentPadding = PaddingValues(start = startPadding, end = endPadding),
+ ) {
+ items(3) { index ->
+ Box(Modifier.requiredSize(itemSize).testTag("$index"))
+ }
+ }
+ }
+
+ rule.onNodeWithTag("0")
+ .assertLeftPositionInRootIsEqualTo(listSize - endPadding - itemSize)
+ rule.onNodeWithTag("1")
+ .assertLeftPositionInRootIsEqualTo(listSize - endPadding - itemSize * 2)
+ // Partially visible.
+ rule.onNodeWithTag("2")
+ .assertLeftPositionInRootIsEqualTo(-itemSize / 2)
+
+ // Scroll to the top.
+ state.scrollBy(itemSize * 2.5f)
+
+ rule.onNodeWithTag("2").assertLeftPositionInRootIsEqualTo(startPadding)
+ // Shouldn't be visible
+ rule.onNodeWithTag("1").assertIsNotDisplayed()
+ rule.onNodeWithTag("0").assertIsNotDisplayed()
+ }
+
private fun LazyListState.scrollBy(offset: Dp) {
runBlocking(Dispatchers.Main + AutoTestFrameClock()) {
animateScrollBy(with(rule.density) { offset.roundToPx().toFloat() }, snap())
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
index c1a3382..fd60d67 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/LazyRowTest.kt
@@ -26,6 +26,7 @@
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredSize
@@ -38,7 +39,6 @@
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.testutils.assertIsEqualTo
import androidx.compose.testutils.assertShape
@@ -76,9 +76,7 @@
import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Rule
import org.junit.Test
@@ -1238,15 +1236,12 @@
@Test
fun animateScrollToItemDoesNotScrollPastItem() {
lateinit var state: LazyListState
- lateinit var scope: CoroutineScope
var target = 0
var reverse = false
rule.setContent {
val listState = rememberLazyListState()
- val effectScope = rememberCoroutineScope()
SideEffect {
state = listState
- scope = effectScope
}
LazyRow(Modifier.fillMaxSize(), listState) {
items(2500) { _ ->
@@ -1264,24 +1259,61 @@
// Try a bunch of different targets with varying spacing
listOf(500, 800, 1500, 1600, 1800).forEach {
target = it
- scope.launch {
- state.animateScrollToItem(target)
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.animateScrollToItem(target)
+ }
}
- rule.waitForIdle()
- assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
}
reverse = true
listOf(1600, 1500, 800, 500, 0).forEach {
target = it
- scope.launch {
- state.animateScrollToItem(target)
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.animateScrollToItem(target)
+ }
}
- rule.waitForIdle()
- assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(target)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
+ }
+ }
+
+ @Test
+ fun animateScrollToTheLastItemWhenItemsAreLargerThenTheScreen() {
+ lateinit var state: LazyListState
+ rule.setContent {
+ state = rememberLazyListState()
+ LazyRow(Modifier.height(150.dp).width(100.dp), state) {
+ items(20) {
+ Box(Modifier.size(150.dp))
+ }
+ }
+ }
+
+ // Try a bunch of different start indexes
+ listOf(0, 5, 12).forEach {
+ val startIndex = it
+ rule.runOnIdle {
+ runBlocking(AutoTestFrameClock()) {
+ state.scrollToItem(startIndex)
+ state.animateScrollToItem(19)
+ }
+ }
+
+ rule.runOnIdle {
+ assertThat(state.firstVisibleItemIndex).isEqualTo(19)
+ assertThat(state.firstVisibleItemScrollOffset).isEqualTo(0)
+ }
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
index 13ee796..18d3368 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/text/selection/TextSelectionColorsScreenshotTest.kt
@@ -27,23 +27,21 @@
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.testutils.assertAgainstGolden
import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.captureToImage
import androidx.compose.ui.test.center
import androidx.compose.ui.test.click
-import androidx.compose.ui.test.height
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.longClick
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performGesture
-import androidx.compose.ui.test.width
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.ResolvedTextDirection
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.screenshot.AndroidXScreenshotTestRule
@@ -68,7 +66,6 @@
@get:Rule
val screenshotRule = AndroidXScreenshotTestRule(GOLDEN_UI)
- @FlakyTest(bugId = 179770443)
@Test
fun text_defaultSelectionColors() {
rule.setContent {
@@ -87,7 +84,6 @@
.assertAgainstGolden(screenshotRule, "text_defaultSelectionColors")
}
- @FlakyTest(bugId = 179770443)
@Test
fun text_customSelectionColors() {
rule.setContent {
@@ -111,7 +107,6 @@
.assertAgainstGolden(screenshotRule, "text_customSelectionColors")
}
- @FlakyTest(bugId = 179770443)
@Test
fun textField_defaultSelectionColors() {
rule.setContent {
@@ -127,20 +122,11 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "textField_defaultSelectionColors")
}
- @FlakyTest(bugId = 188572883)
@Test
fun textField_customSelectionColors() {
rule.setContent {
@@ -161,14 +147,6 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "textField_customSelectionColors")
@@ -205,10 +183,15 @@
private fun TextFieldTestContent(textSelectionColors: TextSelectionColors) {
CompositionLocalProvider(LocalTextSelectionColors provides textSelectionColors) {
Box(Modifier.testTag(Tag)) {
- BasicTextField(value = Text, onValueChange = {})
+ BasicTextField(value = TextFieldText, onValueChange = {})
}
}
}
private const val Text = "Selected text"
+private val TextFieldText = TextFieldValue(
+ text = "Selected text",
+ selection = TextRange(0, 8),
+ composition = TextRange(0, 8)
+)
private const val Tag = "TestTag"
diff --git a/compose/foundation/foundation/src/androidMain/baseline-prof.txt b/compose/foundation/foundation/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..a43178c
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/baseline-prof.txt
@@ -0,0 +1,41 @@
+# Baseline profile rules for androidx.compose.foundation
+# =============================================
+#
+# Include all methods in common top level classes
+HSPLandroidx/compose/foundation/Background;->**(**)**
+HSPLandroidx/compose/foundation/BackgroundKt;->**(**)**
+HSPLandroidx/compose/foundation/BorderKt**->**(**)**
+HSPLandroidx/compose/foundation/BorderStroke;->**(**)**
+HSPLandroidx/compose/foundation/CanvasKt;->**(**)**
+HSPLandroidx/compose/foundation/Clickable**->**(**)**
+HSPLandroidx/compose/foundation/Focusable**->**(**)**
+HSPLandroidx/compose/foundation/ImageKt**->**(**)**
+HSPLandroidx/compose/foundation/IndicationKt**->**(**)**
+HSPLandroidx/compose/foundation/IndicationModifier;->**(**)**
+HSPLandroidx/compose/foundation/MutatorMutex;->**(**)**
+HSPLandroidx/compose/foundation/ScrollKt**->**(**)**
+HSPLandroidx/compose/foundation/ScrollState**->**(**)**
+HSPLandroidx/compose/foundation/ScrollingLayoutModifier**->**(**)**
+#
+# Include everything inside of the gestures namespace
+HSPLandroidx/compose/foundation/gestures/**;->**(**)**
+#
+# Include everything inside of the interaction namespace
+HSPLandroidx/compose/foundation/interaction/*;->**(**)**
+#
+# Include everything inside of the lazy namespace
+HSPLandroidx/compose/foundation/lazy/*;->**(**)**
+#
+# common shape classes
+HSPLandroidx/compose/foundation/shape/CornerBasedShape;->**(**)**
+HSPLandroidx/compose/foundation/shape/RoundedCornerShape;->**(**)**
+HSPLandroidx/compose/foundation/shape/CornerSizeKt;->**(**)**
+HSPLandroidx/compose/foundation/shape/DpCornerSize;->**(**)**
+#
+# Include everything inside of the text namespace
+HSPLandroidx/compose/foundation/text/*;->**(**)**
+HSPLandroidx/compose/foundation/text/selection/SimpleLayoutKt**->**(**)**
+HSPLandroidx/compose/foundation/text/selection/TextFieldSelectionManager;->**(**)**
+#
+# Include all of foundation
+Landroidx/compose/foundation/**;
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcher.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcher.android.kt
index 0b4c29c..ab9e342 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcher.android.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/lazy/LazyListPrefetcher.android.kt
@@ -295,10 +295,10 @@
if (premeasuringIsNeeded && index != -1) {
val itemProvider = stateOfItemsProvider.value
if (index < itemProvider.itemsCount) {
- val composedViaRegularFlow = result.visibleItemsInfo.fastAny {
- it.index == index
- }
- if (composedViaRegularFlow) {
+ val isVisibleAlready = result.visibleItemsInfo.fastAny { it.index == index }
+ val composedButNotVisible = result.composedButNotVisibleItems != null &&
+ result.composedButNotVisibleItems.fastAny { it.index == index }
+ if (isVisibleAlready || composedButNotVisible) {
premeasuringIsNeeded = false
} else {
val key = itemProvider.getKey(index)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
index 74241b8..4e484f4 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
@@ -271,7 +271,7 @@
isDragSuccessful = false
if (!isActive) throw cancellation
} finally {
- channel.offer(if (isDragSuccessful) DragStopped else DragCancelled)
+ channel.trySend(if (isDragSuccessful) DragStopped else DragCancelled)
}
}
}
@@ -318,9 +318,9 @@
val overSlopOffset = initialDelta.toOffset(orientation)
val adjustedStart = startEvent.position - overSlopOffset *
sign(startEvent.position.toFloat(orientation))
- channel.offer(DragStarted(adjustedStart))
+ channel.trySend(DragStarted(adjustedStart))
- channel.offer(
+ channel.trySend(
DragDelta(
if (reverseDirection) initialDelta * -1 else initialDelta,
startEvent.uptimeMillis
@@ -330,7 +330,7 @@
val dragTick: (PointerInputChange) -> Unit = { event: PointerInputChange ->
val delta = event.positionChange().toFloat(orientation)
event.consumePositionChange()
- channel.offer(DragDelta(if (reverseDirection) delta * -1 else delta, event.uptimeMillis))
+ channel.trySend(DragDelta(if (reverseDirection) delta * -1 else delta, event.uptimeMillis))
}
return if (orientation == Orientation.Vertical) {
verticalDrag(startEvent.id, dragTick)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TapGestureDetector.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TapGestureDetector.kt
index afbb6d1c..eef7db7 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TapGestureDetector.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/TapGestureDetector.kt
@@ -321,28 +321,28 @@
// wait for the main pass of the initial event we already have eaten above
awaitPointerEvent()
}
- channel.offer(AllUp)
+ channel.trySend(AllUp)
consumeAllUntilUp.value = false
} else if (event.changes.fastAll { it.changedToDown() }) {
val change = event.changes[0]
change.consumeDownChange()
- channel.offer(Down(change.position, change.uptimeMillis))
+ channel.trySend(Down(change.position, change.uptimeMillis))
} else if (!detectDownsOnly.value) {
if (event.changes.fastAll { it.changedToUp() }) {
// All pointers are up
val change = event.changes[0]
change.consumeDownChange()
- channel.offer(Up(change.position, change.uptimeMillis))
+ channel.trySend(Up(change.position, change.uptimeMillis))
} else if (
event.changes.fastAny { it.consumed.downChange || it.isOutOfBounds(size) }
) {
- channel.offer(Cancel)
+ channel.trySend(Cancel)
} else {
// Check for cancel by position consumption. We can look on the Final pass of the
// existing pointer event because it comes after the Main pass we checked above.
val consumeCheck = awaitPointerEvent(PointerEventPass.Final)
if (consumeCheck.changes.fastAny { it.positionChangeConsumed() }) {
- channel.offer(Cancel)
+ channel.trySend(Cancel)
}
}
}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
index 24a46fbaa..1b86b93 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyList.kt
@@ -153,8 +153,8 @@
itemsCount = itemsCount,
itemProvider = itemProvider,
mainAxisMaxSize = mainAxisMaxSize,
- startContentPadding = startContentPadding,
- endContentPadding = endContentPadding,
+ startContentPadding = if (reverseLayout) endContentPadding else startContentPadding,
+ endContentPadding = if (reverseLayout) startContentPadding else endContentPadding,
firstVisibleItemIndex = state.firstVisibleItemIndexNonObservable,
firstVisibleItemScrollOffset = state.firstVisibleItemScrollOffsetNonObservable,
scrollToBeConsumed = state.scrollToBeConsumed,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
index dbc8974..6eb219c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
@@ -58,6 +58,7 @@
firstVisibleItemScrollOffset = 0,
canScrollForward = false,
consumedScroll = 0f,
+ composedButNotVisibleItems = null,
layoutWidth = constraints.minWidth,
layoutHeight = constraints.minHeight,
placementBlock = {},
@@ -256,6 +257,7 @@
firstVisibleItemScrollOffset = currentFirstItemScrollOffset,
canScrollForward = mainAxisUsed > maxOffset,
consumedScroll = consumedScroll,
+ composedButNotVisibleItems = notUsedButComposedItems,
layoutWidth = layoutWidth,
layoutHeight = layoutHeight,
placementBlock = {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt
index aa59a7a..773c0f7 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasureResult.kt
@@ -31,6 +31,8 @@
val canScrollForward: Boolean,
/** The amount of scroll consumed during the measure pass.*/
val consumedScroll: Float,
+ /** List of items which were composed, but are not a part of [visibleItemsInfo].*/
+ val composedButNotVisibleItems: List<LazyMeasuredItem>?,
// properties to be used by the Layout's measure result
/** The calculated layout width */
val layoutWidth: Int,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt
index cd3157f..1ddc32e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListScrolling.kt
@@ -70,7 +70,7 @@
sequentialAnimation = (anim.velocity != 0f)
) {
// If we haven't found the item yet, check if it's visible.
- val targetItem = getTargetItem()
+ var targetItem = getTargetItem()
if (targetItem == null) {
// Springs can overshoot their target, clamp to the desired range
@@ -85,43 +85,48 @@
}
val consumed = scrollBy(delta)
- if (delta != consumed) {
- debugLog { "Hit end" }
- cancelAnimation()
- loop = false
- return@animateTo
- }
- prevValue += delta
- if (forward) {
- if (value > boundDistancePx) {
- debugLog { "Struck bound going forward" }
- cancelAnimation()
- }
+ targetItem = getTargetItem()
+ if (targetItem != null) {
+ debugLog { "Found the item after performing scrollBy()" }
} else {
- if (value < -boundDistancePx) {
- debugLog { "Struck bound going backward" }
+ if (delta != consumed) {
+ debugLog { "Hit end without finding the item" }
cancelAnimation()
+ loop = false
+ return@animateTo
}
- }
+ prevValue += delta
+ if (forward) {
+ if (value > boundDistancePx) {
+ debugLog { "Struck bound going forward" }
+ cancelAnimation()
+ }
+ } else {
+ if (value < -boundDistancePx) {
+ debugLog { "Struck bound going backward" }
+ cancelAnimation()
+ }
+ }
- // Magic constants for teleportation chosen arbitrarily by experiment
- if (forward) {
- if (
- loops >= 2 &&
- index - layoutInfo.visibleItemsInfo.last().index > 100
- ) {
- // Teleport
- debugLog { "Teleport forward" }
- snapToItemIndexInternal(index = index - 100, scrollOffset = 0)
- }
- } else {
- if (
- loops >= 2 &&
- layoutInfo.visibleItemsInfo.first().index - index > 100
- ) {
- // Teleport
- debugLog { "Teleport backward" }
- snapToItemIndexInternal(index = index + 100, scrollOffset = 0)
+ // Magic constants for teleportation chosen arbitrarily by experiment
+ if (forward) {
+ if (
+ loops >= 2 &&
+ index - layoutInfo.visibleItemsInfo.last().index > 100
+ ) {
+ // Teleport
+ debugLog { "Teleport forward" }
+ snapToItemIndexInternal(index = index - 100, scrollOffset = 0)
+ }
+ } else {
+ if (
+ loops >= 2 &&
+ layoutInfo.visibleItemsInfo.first().index - index > 100
+ ) {
+ // Teleport
+ debugLog { "Teleport backward" }
+ snapToItemIndexInternal(index = index + 100, scrollOffset = 0)
+ }
}
}
}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt
index 074ee43..de92935 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/DarkTheme.desktop.kt
@@ -18,6 +18,8 @@
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
+import org.jetbrains.skiko.SystemTheme
+import org.jetbrains.skiko.currentSystemTheme
/**
* This function should be used to help build responsive UIs that follow the system setting, to
@@ -43,6 +45,5 @@
@Composable
@ReadOnlyComposable
internal actual fun _isSystemInDarkTheme(): Boolean {
- // TODO: Fix after we get a skiko build with https://github.com/JetBrains/skiko/pull/118
- return false
+ return currentSystemTheme == SystemTheme.DARK
}
diff --git a/compose/integration-tests/docs-snippets/build.gradle b/compose/integration-tests/docs-snippets/build.gradle
index 2f632fb..2d3862e 100644
--- a/compose/integration-tests/docs-snippets/build.gradle
+++ b/compose/integration-tests/docs-snippets/build.gradle
@@ -33,6 +33,7 @@
implementation(project(":compose:material:material-icons-extended"))
implementation(project(":compose:runtime:runtime"))
implementation(project(":compose:runtime:runtime-livedata"))
+ implementation(project(":compose:ui:ui-graphics"))
implementation(project(":compose:ui:ui-test-junit4"))
implementation(project(":compose:ui:ui-tooling"))
implementation(project(":compose:ui:ui-viewbinding"))
diff --git a/compose/integration-tests/docs-snippets/lint-baseline.xml b/compose/integration-tests/docs-snippets/lint-baseline.xml
deleted file mode 100644
index 42a176b..0000000
--- a/compose/integration-tests/docs-snippets/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.0.0-alpha15" type="baseline" client="cli" name="Lint" variant="all" version="7.0.0-alpha15">
-
-</issues>
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/graphics/graphics.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/graphics/graphics.kt
new file mode 100644
index 0000000..ade0982
--- /dev/null
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/graphics/graphics.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2020 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.
+ */
+
+// Ignore lint warnings in documentation snippets
+@file:Suppress("unused", "UNUSED_PARAMETER", "UNUSED_VARIABLE")
+
+package androidx.compose.integration.docs.graphics
+
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.drawscope.inset
+import androidx.compose.ui.graphics.drawscope.rotate
+import androidx.compose.ui.graphics.drawscope.withTransform
+
+/**
+ * This file lets DevRel track changes to snippets present in
+ * https://developer.android.com/jetpack/compose/graphics
+ *
+ * No action required if it's modified.
+ */
+
+@Composable
+private fun GraphicsSnippet1() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ }
+}
+
+@Composable
+private fun GraphicsSnippet2() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+
+ drawLine(
+ start = Offset(x = canvasWidth, y = 0f),
+ end = Offset(x = 0f, y = canvasHeight),
+ color = Color.Blue
+ )
+ }
+}
+
+@Composable
+private fun GraphicsSnippet3() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+
+ drawLine(
+ start = Offset(x = canvasWidth, y = 0f),
+ end = Offset(x = 0f, y = canvasHeight),
+ color = Color.Blue,
+ strokeWidth = 5F
+ )
+ }
+}
+
+@Composable
+private fun GraphicsSnippet4() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+ drawCircle(
+ color = Color.Blue,
+ center = Offset(x = canvasWidth / 2, y = canvasHeight / 2),
+ radius = size.minDimension / 4
+ )
+ }
+}
+
+@Composable
+private fun GraphicsSnippet5() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasQuadrantSize = size / 2F
+ drawRect(
+ color = Color.Green,
+ size = canvasQuadrantSize
+ )
+ }
+}
+
+@Composable
+private fun GraphicsSnippet6() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+
+ val canvasQuadrantSize = size / 2F
+ inset(50F, 30F) {
+ drawRect(
+ color = Color.Green,
+ size = canvasQuadrantSize
+ )
+ }
+ }
+}
+
+@Composable
+private fun GraphicsSnippet7() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasSize = size
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+ drawRect(
+ color = Color.Gray,
+ topLeft = Offset(x = canvasWidth / 3F, y = canvasHeight / 3F),
+ size = canvasSize / 3F
+ )
+ }
+}
+
+@Composable
+private fun GraphicsSnippet8() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasSize = size
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+
+ rotate(degrees = 45F) {
+ drawRect(
+ color = Color.Gray,
+ topLeft = Offset(x = canvasWidth / 3F, y = canvasHeight / 3F),
+ size = canvasSize / 3F
+ )
+ }
+ }
+}
+
+@Composable
+private fun GraphicsSnippet9() {
+ Canvas(modifier = Modifier.fillMaxSize()) {
+ val canvasSize = size
+ val canvasWidth = size.width
+ val canvasHeight = size.height
+
+ withTransform({
+ translate(left = canvasWidth / 5F)
+ rotate(degrees = 45F)
+ }) {
+ drawRect(
+ color = Color.Gray,
+ topLeft = Offset(x = canvasWidth / 3F, y = canvasHeight / 3F),
+ size = canvasSize / 3F
+ )
+ }
+ }
+}
diff --git a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/testing/CheatSheet.kt b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/testing/CheatSheet.kt
index 14bfe86..35c82124 100644
--- a/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/testing/CheatSheet.kt
+++ b/compose/integration-tests/docs-snippets/src/main/java/androidx/compose/integration/docs/testing/CheatSheet.kt
@@ -164,6 +164,7 @@
import androidx.compose.ui.test.width
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import android.view.KeyEvent as AndroidKeyEvent
@@ -370,6 +371,7 @@
.getUnclippedBoundsInRoot()
}
+@OptIn(DelicateCoroutinesApi::class)
@RequiresApi(Build.VERSION_CODES.O)
private fun TestingCheatSheetOther() {
diff --git a/compose/material/material-ripple/src/androidMain/baseline-prof.txt b/compose/material/material-ripple/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..2533c51
--- /dev/null
+++ b/compose/material/material-ripple/src/androidMain/baseline-prof.txt
@@ -0,0 +1,11 @@
+# Baseline profile rules for androidx.compose.material.ripple
+# =============================================
+HSPLandroidx/compose/material/ripple/AndroidRippleIndicationInstance;->**(**)**
+HSPLandroidx/compose/material/ripple/PlatformRipple;->**(**)**
+HSPLandroidx/compose/material/ripple/Ripple;->**(**)**
+HSPLandroidx/compose/material/ripple/UnprojectedRipple;->**(**)**
+HSPLandroidx/compose/material/ripple/RippleHostView;->**(**)**
+HSPLandroidx/compose/material/ripple/RippleHostMap;->**(**)**
+HSPLandroidx/compose/material/ripple/RippleContainer;->**(**)**
+HSPLandroidx/compose/material/ripple/RippleAlpha;->**(**)**
+Landroidx/compose/material/ripple/*;
\ No newline at end of file
diff --git a/compose/material/material/api/1.0.0-beta09.txt b/compose/material/material/api/1.0.0-beta09.txt
index 621b01d..b6e8f4d 100644
--- a/compose/material/material/api/1.0.0-beta09.txt
+++ b/compose/material/material/api/1.0.0-beta09.txt
@@ -469,6 +469,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/compose/material/material/api/current.txt b/compose/material/material/api/current.txt
index 621b01d..b6e8f4d 100644
--- a/compose/material/material/api/current.txt
+++ b/compose/material/material/api/current.txt
@@ -469,6 +469,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/compose/material/material/api/public_plus_experimental_1.0.0-beta09.txt b/compose/material/material/api/public_plus_experimental_1.0.0-beta09.txt
index 9b8a1af..a7a2c2d 100644
--- a/compose/material/material/api/public_plus_experimental_1.0.0-beta09.txt
+++ b/compose/material/material/api/public_plus_experimental_1.0.0-beta09.txt
@@ -609,6 +609,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void Surface-VL29DuM(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/material/material/api/public_plus_experimental_current.txt b/compose/material/material/api/public_plus_experimental_current.txt
index 9b8a1af..a7a2c2d 100644
--- a/compose/material/material/api/public_plus_experimental_current.txt
+++ b/compose/material/material/api/public_plus_experimental_current.txt
@@ -609,6 +609,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
method @androidx.compose.material.ExperimentalMaterialApi @androidx.compose.runtime.Composable public static void Surface-VL29DuM(kotlin.jvm.functions.Function0<kotlin.Unit> onClick, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.foundation.Indication? indication, optional boolean enabled, optional String? onClickLabel, optional androidx.compose.ui.semantics.Role? role, kotlin.jvm.functions.Function0<kotlin.Unit> content);
diff --git a/compose/material/material/api/restricted_1.0.0-beta09.txt b/compose/material/material/api/restricted_1.0.0-beta09.txt
index 621b01d..b6e8f4d 100644
--- a/compose/material/material/api/restricted_1.0.0-beta09.txt
+++ b/compose/material/material/api/restricted_1.0.0-beta09.txt
@@ -469,6 +469,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/compose/material/material/api/restricted_current.txt b/compose/material/material/api/restricted_current.txt
index 621b01d..b6e8f4d 100644
--- a/compose/material/material/api/restricted_current.txt
+++ b/compose/material/material/api/restricted_current.txt
@@ -469,6 +469,9 @@
enum_constant public static final androidx.compose.material.SnackbarResult Dismissed;
}
+ public final class Strings_androidKt {
+ }
+
public final class SurfaceKt {
method @androidx.compose.runtime.Composable public static void Surface-IHU7g64(optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Shape shape, optional long color, optional long contentColor, optional androidx.compose.foundation.BorderStroke? border, optional float elevation, kotlin.jvm.functions.Function0<kotlin.Unit> content);
}
diff --git a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
index 585bead..4c44b76 100644
--- a/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
+++ b/compose/material/material/integration-tests/material-demos/src/main/java/androidx/compose/material/demos/MaterialTextField.kt
@@ -137,7 +137,7 @@
TextField(
value = text.value,
onValueChange = { text.value = it },
- label = { if (label.value) Text("Label") },
+ label = if (label.value) { @Composable { Text("Label") } } else null,
singleLine = singleLine.value,
modifier = textFieldModifier
)
@@ -145,7 +145,7 @@
OutlinedTextField(
value = text.value,
onValueChange = { text.value = it },
- label = { if (label.value) Text("Label") },
+ label = if (label.value) { @Composable { Text("Label") } } else null,
singleLine = singleLine.value,
modifier = textFieldModifier
)
@@ -179,11 +179,15 @@
"Label" + if (selectedOption == Option.Error) "*" else ""
Text(text = label)
},
- leadingIcon = {
- if (leadingChecked) Icon(Icons.Filled.Favorite, "Favorite")
+ leadingIcon = if (leadingChecked) {
+ @Composable { Icon(Icons.Filled.Favorite, "Favorite") }
+ } else {
+ null
},
- trailingIcon = {
- if (trailingChecked) Icon(Icons.Filled.Info, "Info")
+ trailingIcon = if (trailingChecked) {
+ @Composable { Icon(Icons.Filled.Info, "Info") }
+ } else {
+ null
},
isError = selectedOption == Option.Error,
modifier = Modifier.requiredWidth(300.dp)
@@ -200,11 +204,15 @@
"Label" + if (selectedOption == Option.Error) "*" else ""
Text(text = label)
},
- leadingIcon = {
- if (leadingChecked) Icon(Icons.Filled.Favorite, "Favorite")
+ leadingIcon = if (leadingChecked) {
+ @Composable { Icon(Icons.Filled.Favorite, "Favorite") }
+ } else {
+ null
},
- trailingIcon = {
- if (trailingChecked) Icon(Icons.Filled.Info, "Info")
+ trailingIcon = if (trailingChecked) {
+ @Composable { Icon(Icons.Filled.Info, "Info") }
+ } else {
+ null
},
isError = selectedOption == Option.Error,
modifier = Modifier.requiredWidth(300.dp)
diff --git a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
index 3d6c1b2..370b121 100644
--- a/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
+++ b/compose/material/material/samples/src/main/java/androidx/compose/material/samples/ScaffoldSamples.kt
@@ -289,7 +289,7 @@
text = { Text("Show snackbar") },
onClick = {
// offset snackbar data to the business logic
- channel.offer(++clickCount)
+ channel.trySend(++clickCount)
}
)
},
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
index 60c549e..f194676 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/DrawerTest.kt
@@ -43,6 +43,7 @@
import androidx.compose.ui.test.click
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onParent
import androidx.compose.ui.test.performClick
@@ -231,19 +232,41 @@
@Test
@SmallTest
fun bottomDrawer_hasPaneTitle() {
+ lateinit var navigationMenu: String
rule.setMaterialContent {
BottomDrawer(
- drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed),
+ drawerState = rememberBottomDrawerState(BottomDrawerValue.Open),
drawerContent = {
Box(Modifier.fillMaxSize().testTag(bottomDrawerTag))
},
content = {}
)
+ navigationMenu = getString(Strings.NavigationMenu)
}
rule.onNodeWithTag(bottomDrawerTag, useUnmergedTree = true)
.onParent()
- .assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.PaneTitle))
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.PaneTitle, navigationMenu))
+ }
+
+ @Test
+ @SmallTest
+ fun modalDrawer_hasPaneTitle() {
+ lateinit var navigationMenu: String
+ rule.setMaterialContent {
+ ModalDrawer(
+ drawerState = rememberDrawerState(DrawerValue.Open),
+ drawerContent = {
+ Box(Modifier.fillMaxSize().testTag("modalDrawerTag"))
+ },
+ content = {}
+ )
+ navigationMenu = getString(Strings.NavigationMenu)
+ }
+
+ rule.onNodeWithTag("modalDrawerTag", useUnmergedTree = true)
+ .onParent()
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.PaneTitle, navigationMenu))
}
@Test
@@ -738,6 +761,7 @@
fun bottomDrawer_scrim_doesNotClickWhenTransparent() {
val topTag = "BottomDrawer"
val scrimColor = mutableStateOf(Color.Red)
+ lateinit var closeDrawer: String
rule.setMaterialContent {
BottomDrawer(
modifier = Modifier.testTag(topTag),
@@ -750,6 +774,7 @@
Box(Modifier.fillMaxSize().testTag("body"))
}
)
+ closeDrawer = getString(Strings.CloseDrawer)
}
val height = rule.rootHeight()
@@ -761,8 +786,7 @@
var topNode = rule.onNodeWithTag(topTag).fetchSemanticsNode()
assertEquals(3, topNode.children.size)
- rule.onNodeWithTag(topTag)
- .onChildAt(1)
+ rule.onNodeWithContentDescription(closeDrawer)
.assertHasClickAction()
rule.runOnIdle {
@@ -1098,6 +1122,7 @@
@Test
fun modalDrawer_scrimNode_reportToSemanticsWhenOpen_notReportToSemanticsWhenClosed() {
val topTag = "ModalDrawer"
+ lateinit var closeDrawer: String
rule.setMaterialContent {
ModalDrawer(
modifier = Modifier.testTag(topTag),
@@ -1109,6 +1134,7 @@
Box(Modifier.fillMaxSize().testTag("body"))
}
)
+ closeDrawer = getString(Strings.CloseDrawer)
}
// The drawer should be opened
@@ -1116,8 +1142,7 @@
var topNode = rule.onNodeWithTag(topTag).fetchSemanticsNode()
assertEquals(3, topNode.children.size)
- rule.onNodeWithTag(topTag)
- .onChildAt(1)
+ rule.onNodeWithContentDescription(closeDrawer)
.assertHasClickAction()
.performSemanticsAction(SemanticsActions.OnClick)
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
index c8853dd..e73e6c7 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/MaterialTextSelectionColorsScreenshotTest.kt
@@ -23,21 +23,19 @@
import androidx.compose.runtime.Composable
import androidx.compose.testutils.assertAgainstGolden
import androidx.compose.ui.Modifier
-import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.captureToImage
import androidx.compose.ui.test.click
-import androidx.compose.ui.test.height
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.longClick
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performGesture
-import androidx.compose.ui.test.width
+import androidx.compose.ui.text.TextRange
+import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.test.screenshot.AndroidXScreenshotTestRule
@@ -87,7 +85,6 @@
.isEqualTo(darkPrimary.copy(alpha = 0.375f))
}
- @FlakyTest(bugId = 179770443)
@Test
fun text_lightThemeSelectionColors() {
rule.setContent {
@@ -106,7 +103,6 @@
.assertAgainstGolden(screenshotRule, "text_lightThemeSelectionColors")
}
- @FlakyTest(bugId = 179770443)
@Test
fun text_darkThemeSelectionColors() {
rule.setContent {
@@ -140,14 +136,6 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "filledTextField_lightThemeSelectionColors")
@@ -168,20 +156,11 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "filledTextField_darkThemeSelectionColors")
}
- @FlakyTest(bugId = 190120675)
@Test
fun outlinedTextField_lightThemeSelectionColors() {
rule.setContent {
@@ -197,14 +176,6 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "outlinedTextField_lightThemeSelectionColors")
@@ -225,14 +196,6 @@
rule.waitForIdle()
- // Long click to start text selection
- rule.onNodeWithText(Text)
- .performGesture {
- longClick(Offset(width / 5f, height / 2f))
- }
-
- rule.waitForIdle()
-
rule.onNodeWithTag(Tag)
.captureToImage()
.assertAgainstGolden(screenshotRule, "outlinedTextField_darkThemeSelectionColors")
@@ -254,7 +217,11 @@
private fun FilledTextFieldTestContent(colors: Colors) {
MaterialTheme(colors) {
Surface(Modifier.testTag(Tag)) {
- TextField(value = Text, onValueChange = {}, modifier = Modifier.requiredWidth(280.dp))
+ TextField(
+ value = TextFieldText,
+ onValueChange = {},
+ modifier = Modifier.requiredWidth(280.dp)
+ )
}
}
}
@@ -264,7 +231,7 @@
MaterialTheme(colors) {
Surface(Modifier.testTag(Tag)) {
OutlinedTextField(
- value = Text,
+ value = TextFieldText,
onValueChange = {},
modifier = Modifier.requiredWidth(280.dp)
)
@@ -273,4 +240,9 @@
}
private const val Text = "Selected text"
+private val TextFieldText = TextFieldValue(
+ text = "Selected text",
+ selection = TextRange(0, 8),
+ composition = TextRange(0, 8)
+)
private const val Tag = "TestTag"
\ No newline at end of file
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ModalBottomSheetTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ModalBottomSheetTest.kt
index 22c0082..4119872 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ModalBottomSheetTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/ModalBottomSheetTest.kt
@@ -35,6 +35,7 @@
import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChildAt
+import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onParent
import androidx.compose.ui.test.performGesture
@@ -437,9 +438,10 @@
}
@Test
- fun modalBottomSheet_scrim_doesNotClickWhenTransparent() {
+ fun modalBottomSheet_scrim_doesNotClickWhenClosed_hasContentDescriptionWhenOpen() {
val topTag = "ModalBottomSheetLayout"
val scrimColor = mutableStateOf(Color.Red)
+ lateinit var closeSheet: String
rule.setMaterialContent {
ModalBottomSheetLayout(
modifier = Modifier.testTag(topTag),
@@ -448,6 +450,7 @@
content = { Box(Modifier.fillMaxSize().testTag(contentTag)) },
sheetContent = { Box(Modifier.fillMaxSize().testTag(sheetTag)) }
)
+ closeSheet = getString(Strings.CloseSheet)
}
val height = rule.rootHeight()
@@ -455,8 +458,7 @@
.assertTopPositionInRootIsEqualTo(height / 2)
var topNode = rule.onNodeWithTag(topTag).fetchSemanticsNode()
assertEquals(3, topNode.children.size)
- rule.onNodeWithTag(topTag)
- .onChildAt(1)
+ rule.onNodeWithContentDescription(closeSheet)
.assertHasClickAction()
rule.runOnIdle {
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
index 24ea3e2..be2b9ff5 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
@@ -30,6 +30,8 @@
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Divider
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
import androidx.compose.material.LocalContentAlpha
import androidx.compose.material.LocalContentColor
import androidx.compose.material.LocalTextStyle
@@ -39,6 +41,9 @@
import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.TextFieldPadding
+import androidx.compose.material.getString
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.runOnIdleWithDensity
import androidx.compose.material.setMaterialContent
import androidx.compose.material.setMaterialContentForSizeAssertions
@@ -115,7 +120,6 @@
OutlinedTextField(
value = "input",
onValueChange = {},
- label = {},
modifier = Modifier.requiredWidth(40.dp)
)
}
@@ -127,8 +131,7 @@
rule.setMaterialContentForSizeAssertions {
OutlinedTextField(
value = "input",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
.assertWidthIsEqualTo(ExpectedDefaultTextFieldWidth)
@@ -149,16 +152,14 @@
.testTag(textField1Tag)
.onFocusChanged { textField1Focused = it.isFocused },
value = "input1",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
OutlinedTextField(
modifier = Modifier
.testTag(textField2Tag)
.onFocusChanged { textField2Focused = it.isFocused },
value = "input2",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
}
@@ -188,8 +189,7 @@
.testTag(TextfieldTag)
.onFocusChanged { focused = it.isFocused },
value = "input",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
}
@@ -434,7 +434,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "",
onValueChange = {},
- label = {},
placeholder = {
Text(
text = "placeholder",
@@ -460,9 +459,7 @@
ExpectedPadding.roundToPx().toFloat()
)
// placeholder is placed with fixed padding plus additional 8.dp padding on top
- assertThat(placeholderPosition.value?.y).isEqualTo(
- TextFieldPadding.roundToPx() + 8.dp.roundToPx()
- )
+ assertThat(placeholderPosition.value?.y).isEqualTo(TextFieldPadding.roundToPx())
}
}
@@ -476,7 +473,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "input",
onValueChange = {},
- label = {},
placeholder = {
Text(
text = "placeholder",
@@ -506,7 +502,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "",
onValueChange = {},
- label = {},
placeholder = {
Text("placeholder")
assertThat(
@@ -530,62 +525,202 @@
}
@Test
- fun testOutlinedTextField_trailingAndLeading_sizeAndPosition() {
+ fun testOutlinedTextField_trailingAndLeading_sizeAndPosition_defaultIcon() {
val textFieldWidth = 300.dp
- val size = 30.dp
val leadingPosition = Ref<Offset>()
val leadingSize = Ref<IntSize>()
val trailingPosition = Ref<Offset>()
val trailingSize = Ref<IntSize>()
-
+ val density = Density(2f)
rule.setMaterialContent {
- OutlinedTextField(
- value = "text",
- onValueChange = {},
- modifier = Modifier.width(textFieldWidth),
- label = {},
- leadingIcon = {
- Box(
- Modifier.size(size).onGloballyPositioned {
- leadingPosition.value = it.positionInRoot()
- leadingSize.value = it.size
- }
- )
- },
- trailingIcon = {
- Box(
- Modifier.size(size).onGloballyPositioned {
- trailingPosition.value = it.positionInRoot()
- trailingSize.value = it.size
- }
- )
- }
- )
+ CompositionLocalProvider(LocalDensity provides density) {
+ OutlinedTextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.width(textFieldWidth),
+ label = { Text("label") },
+ leadingIcon = {
+ Icon(
+ Icons.Default.Favorite,
+ null,
+ Modifier.onGloballyPositioned {
+ leadingPosition.value = it.positionInRoot()
+ leadingSize.value = it.size
+ }
+ )
+ },
+ trailingIcon = {
+ Icon(
+ Icons.Default.Favorite,
+ null,
+ Modifier.onGloballyPositioned {
+ trailingPosition.value = it.positionInRoot()
+ trailingSize.value = it.size
+ }
+ )
+ },
+ )
+ }
}
- rule.runOnIdleWithDensity {
- val minimumHeight = ExpectedMinimumTextFieldHeight.roundToPx()
- // leading
- assertThat(leadingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
- assertThat(leadingPosition.value?.x).isEqualTo(IconPadding.roundToPx().toFloat())
- assertThat(leadingPosition.value?.y).isEqualTo(
- ((minimumHeight - leadingSize.value!!.height) / 2f).roundToInt() + 8.dp.roundToPx()
- )
- // trailing
- assertThat(trailingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
- assertThat(trailingPosition.value?.x).isEqualTo(
- (textFieldWidth.roundToPx() - IconPadding.roundToPx() - trailingSize.value!!.width)
- .toFloat()
- )
- assertThat(trailingPosition.value?.y).isEqualTo(
- ((minimumHeight - trailingSize.value!!.height) / 2f).roundToInt() + 8.dp.roundToPx()
- )
+ rule.runOnIdle {
+ with(density) {
+ val minimumHeight = ExpectedMinimumTextFieldHeight.roundToPx()
+ val size = 24.dp // default icon size
+ // leading
+ assertThat(leadingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition.value?.x).isEqualTo(IconPadding.roundToPx().toFloat())
+ assertThat(leadingPosition.value?.y).isEqualTo(
+ ((minimumHeight - leadingSize.value!!.height) / 2f).roundToInt() +
+ 8.dp.roundToPx()
+ )
+ // trailing
+ assertThat(trailingSize.value).isEqualTo(
+ IntSize(
+ size.roundToPx(),
+ size.roundToPx()
+ )
+ )
+ assertThat(trailingPosition.value?.x).isEqualTo(
+ (
+ textFieldWidth.roundToPx() - IconPadding.roundToPx() -
+ trailingSize.value!!.width
+ ).toFloat()
+ )
+ assertThat(trailingPosition.value?.y).isEqualTo(
+ ((minimumHeight - trailingSize.value!!.height) / 2f).roundToInt() +
+ 8.dp.roundToPx()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testOutlinedTextField_trailingAndLeading_sizeAndPosition_defaultIconButton() {
+ val textFieldWidth = 300.dp
+ val textFieldHeight = 80.dp
+ val density = Density(2f)
+
+ var leadingPosition: Offset? = null
+ var leadingSize: IntSize? = null
+ var trailingPosition: Offset? = null
+ var trailingSize: IntSize? = null
+
+ rule.setMaterialContent {
+ CompositionLocalProvider(LocalDensity provides density) {
+ OutlinedTextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.width(textFieldWidth).height(textFieldHeight),
+ leadingIcon = {
+ IconButton(
+ onClick = {},
+ modifier = Modifier.onGloballyPositioned {
+ leadingPosition = it.positionInRoot()
+ leadingSize = it.size
+ }
+ ) { Icon(Icons.Default.Favorite, null) }
+ },
+ trailingIcon = {
+ IconButton(
+ onClick = {},
+ modifier = Modifier.onGloballyPositioned {
+ trailingPosition = it.positionInRoot()
+ trailingSize = it.size
+ }
+ ) { Icon(Icons.Default.Favorite, null) }
+ }
+ )
+ }
+ }
+
+ rule.runOnIdle {
+ val size = 48.dp // default IconButton size
+
+ with(density) {
+ // leading
+ assertThat(leadingSize).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition?.x).isEqualTo(0f)
+ assertThat(leadingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - leadingSize!!.height) / 2f).roundToInt()
+ )
+ // trailing
+ assertThat(trailingSize).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(trailingPosition?.x).isEqualTo(
+ (textFieldWidth.roundToPx() - trailingSize!!.width).toFloat()
+ )
+ assertThat(trailingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - trailingSize!!.height) / 2f).roundToInt()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testOutlinedTextField_trailingAndLeading_sizeAndPosition_nonDefaultSizeIcon() {
+ val textFieldWidth = 300.dp
+ val textFieldHeight = 80.dp
+ val size = 72.dp
+ val density = Density(2f)
+
+ var leadingPosition: Offset? = null
+ var leadingSize: IntSize? = null
+ var trailingPosition: Offset? = null
+ var trailingSize: IntSize? = null
+
+ rule.setMaterialContent {
+ CompositionLocalProvider(LocalDensity provides density) {
+ OutlinedTextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.width(textFieldWidth).height(textFieldHeight),
+ leadingIcon = {
+ Box(
+ Modifier.size(size).onGloballyPositioned {
+ leadingPosition = it.positionInRoot()
+ leadingSize = it.size
+ }
+ )
+ },
+ trailingIcon = {
+ Box(
+ Modifier.size(size).onGloballyPositioned {
+ trailingPosition = it.positionInRoot()
+ trailingSize = it.size
+ }
+ )
+ },
+ )
+ }
+ }
+
+ rule.runOnIdle {
+ with(density) {
+ // leading
+ assertThat(leadingSize).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition?.x).isEqualTo(0f)
+ assertThat(leadingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - leadingSize!!.height) / 2f).roundToInt()
+ )
+ // trailing
+ assertThat(trailingSize).isEqualTo(
+ IntSize(
+ size.roundToPx(),
+ size.roundToPx()
+ )
+ )
+ assertThat(trailingPosition?.x).isEqualTo(
+ (textFieldWidth.roundToPx() - trailingSize!!.width).toFloat()
+ )
+ assertThat(trailingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - trailingSize!!.height) / 2f).roundToInt()
+ )
+ }
}
}
@Test
fun testOutlinedTextField_labelPositionX_initial_withTrailingAndLeading() {
- val iconSize = 30.dp
val labelPosition = Ref<Offset>()
rule.setMaterialContent {
Box {
@@ -600,13 +735,14 @@
}
)
},
- trailingIcon = { Box(Modifier.size(iconSize)) },
- leadingIcon = { Box(Modifier.size(iconSize)) }
+ trailingIcon = { Icon(Icons.Default.Favorite, null) },
+ leadingIcon = { Icon(Icons.Default.Favorite, null) }
)
}
}
rule.runOnIdleWithDensity {
+ val iconSize = 24.dp // default icon size
assertThat(labelPosition.value?.x).isEqualTo(
(ExpectedPadding.roundToPx() + IconPadding.roundToPx() + iconSize.roundToPx())
.toFloat()
@@ -615,7 +751,7 @@
}
@Test
- fun testOutlinedTextField_labelPositionX_initial_withEmptyTrailingAndLeading() {
+ fun testOutlinedTextField_labelPositionX_initial_withNullTrailingAndLeading() {
val labelPosition = Ref<Offset>()
rule.setMaterialContent {
Box {
@@ -630,8 +766,8 @@
}
)
},
- trailingIcon = {},
- leadingIcon = {}
+ trailingIcon = null,
+ leadingIcon = null
)
}
}
@@ -649,7 +785,6 @@
OutlinedTextField(
value = "",
onValueChange = {},
- label = {},
isError = false,
leadingIcon = {
assertThat(LocalContentColor.current)
@@ -677,7 +812,6 @@
OutlinedTextField(
value = "",
onValueChange = {},
- label = {},
isError = true,
leadingIcon = {
assertThat(LocalContentColor.current)
@@ -707,7 +841,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = text.value,
onValueChange = { text.value = it },
- label = {},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Go,
keyboardType = KeyboardType.Email
@@ -743,7 +876,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "qwerty",
onValueChange = {},
- label = {},
visualTransformation = PasswordVisualTransformation('\u0020')
)
}
@@ -763,18 +895,20 @@
@Test
fun testErrorSemantics_defaultMessage() {
+ lateinit var errorMessage: String
rule.setMaterialContent {
OutlinedTextField(
value = "test",
onValueChange = {},
isError = true
)
+ errorMessage = getString(Strings.DefaultErrorMessage)
}
rule.onNodeWithText("test")
.assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
.assert(
- SemanticsMatcher.expectValue(SemanticsProperties.Error, Strings.DefaultErrorMessage)
+ SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage)
)
}
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
index 600912f..a1404f8 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
@@ -38,15 +38,17 @@
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Divider
import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
import androidx.compose.material.LocalContentAlpha
import androidx.compose.material.LocalContentColor
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.MaterialTheme
-import androidx.compose.material.Strings.DefaultErrorMessage
+import androidx.compose.material.Strings.Companion.DefaultErrorMessage
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.TextFieldPadding
+import androidx.compose.material.getString
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.runOnIdleWithDensity
@@ -70,6 +72,7 @@
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.node.Ref
+import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.platform.LocalView
@@ -101,6 +104,7 @@
import androidx.compose.ui.text.input.TextInputService
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
+import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@@ -145,7 +149,6 @@
TextField(
value = "input",
onValueChange = {},
- label = {},
modifier = Modifier.height(20.dp)
)
}
@@ -158,7 +161,6 @@
TextField(
value = "input",
onValueChange = {},
- label = {},
modifier = Modifier.requiredWidth(40.dp)
)
}
@@ -170,8 +172,7 @@
rule.setMaterialContentForSizeAssertions {
TextField(
value = "input",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
.assertWidthIsEqualTo(ExpectedDefaultTextFieldWidth)
@@ -193,14 +194,12 @@
modifier = Modifier.testTag(textField1Tag),
value = "input1",
onValueChange = {},
- label = {},
interactionSource = interactionSource1
)
TextField(
modifier = Modifier.testTag(textField2Tag),
value = "input2",
onValueChange = {},
- label = {},
interactionSource = interactionSource2
)
}
@@ -251,7 +250,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "input",
onValueChange = {},
- label = {},
interactionSource = interactionSource
)
}
@@ -292,8 +290,7 @@
.focusRequester(focusRequester)
.testTag(TextfieldTag),
value = "input",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
}
@@ -324,8 +321,7 @@
.focusRequester(focusRequester)
.testTag(TextfieldTag),
value = "input",
- onValueChange = {},
- label = {}
+ onValueChange = {}
)
}
}
@@ -603,7 +599,6 @@
modifier = Modifier.height(height).testTag(TextfieldTag),
value = "",
onValueChange = {},
- label = {},
placeholder = {
Text(
text = "placeholder",
@@ -645,7 +640,7 @@
modifier = Modifier.testTag(TextfieldTag),
value = "input",
onValueChange = {},
- label = {},
+
placeholder = {
Text(
text = "placeholder",
@@ -675,7 +670,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = "",
onValueChange = {},
- label = {},
placeholder = {
Text("placeholder")
assertThat(
@@ -699,66 +693,213 @@
}
@Test
- fun testTextField_trailingAndLeading_sizeAndPosition() {
+ fun testTextField_trailingAndLeading_sizeAndPosition_defaultIcon() {
val textFieldHeight = 60.dp
val textFieldWidth = 300.dp
- val size = 30.dp
val leadingPosition = Ref<Offset>()
val leadingSize = Ref<IntSize>()
val trailingPosition = Ref<Offset>()
val trailingSize = Ref<IntSize>()
+ val density = Density(2f)
rule.setMaterialContent {
- TextField(
- value = "text",
- onValueChange = {},
- modifier = Modifier.size(textFieldWidth, textFieldHeight),
- label = {},
- leadingIcon = {
- Box(
- Modifier.size(size).onGloballyPositioned {
- leadingPosition.value = it.positionInRoot()
- leadingSize.value = it.size
- }
- )
- },
- trailingIcon = {
- Box(
- Modifier.size(size).onGloballyPositioned {
- trailingPosition.value = it.positionInRoot()
- trailingSize.value = it.size
- }
- )
- }
- )
+ CompositionLocalProvider(LocalDensity provides density) {
+ TextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.size(textFieldWidth, textFieldHeight),
+ leadingIcon = {
+ Icon(
+ Icons.Default.Favorite,
+ null,
+ Modifier.onGloballyPositioned {
+ leadingPosition.value = it.positionInRoot()
+ leadingSize.value = it.size
+ }
+ )
+ },
+ trailingIcon = {
+ Icon(
+ Icons.Default.Favorite,
+ null,
+ Modifier.onGloballyPositioned {
+ trailingPosition.value = it.positionInRoot()
+ trailingSize.value = it.size
+ }
+ )
+ }
+ )
+ }
}
- rule.runOnIdleWithDensity {
- // leading
- assertThat(leadingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
- assertThat(leadingPosition.value?.x).isEqualTo(IconPadding.roundToPx().toFloat())
- assertThat(leadingPosition.value?.y).isEqualTo(
- ((textFieldHeight.roundToPx() - leadingSize.value!!.height) / 2f).roundToInt()
- .toFloat()
- )
- // trailing
- assertThat(trailingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
- assertThat(trailingPosition.value?.x).isEqualTo(
- (textFieldWidth.roundToPx() - IconPadding.roundToPx() - trailingSize.value!!.width)
- .toFloat()
- )
- assertThat(trailingPosition.value?.y)
- .isEqualTo(
- ((textFieldHeight.roundToPx() - trailingSize.value!!.height) / 2f)
- .roundToInt().toFloat()
+ rule.runOnIdle {
+ val size = 24.dp // default icon size
+ with(density) {
+ // leading
+ assertThat(leadingSize.value).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition.value?.x).isEqualTo(IconPadding.roundToPx().toFloat())
+ assertThat(leadingPosition.value?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - leadingSize.value!!.height) / 2f).roundToInt()
+ .toFloat()
)
+ // trailing
+ assertThat(trailingSize.value).isEqualTo(
+ IntSize(
+ size.roundToPx(),
+ size.roundToPx()
+ )
+ )
+ assertThat(trailingPosition.value?.x).isEqualTo(
+ (
+ textFieldWidth.roundToPx() - IconPadding.roundToPx() -
+ trailingSize.value!!.width
+ ).toFloat()
+ )
+ assertThat(trailingPosition.value?.y)
+ .isEqualTo(
+ ((textFieldHeight.roundToPx() - trailingSize.value!!.height) / 2f)
+ .roundToInt().toFloat()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testTextField_trailingAndLeading_sizeAndPosition_iconButton() {
+ val textFieldHeight = 80.dp
+ val textFieldWidth = 300.dp
+ val density = Density(2f)
+
+ var leadingPosition: Offset? = null
+ var leadingSize: IntSize? = null
+ var trailingPosition: Offset? = null
+ var trailingSize: IntSize? = null
+
+ rule.setMaterialContent {
+ CompositionLocalProvider(LocalDensity provides density) {
+ TextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.size(textFieldWidth, textFieldHeight),
+ leadingIcon = {
+ IconButton(
+ onClick = {},
+ modifier = Modifier.onGloballyPositioned {
+ leadingPosition = it.positionInRoot()
+ leadingSize = it.size
+ }
+ ) {
+ Icon(Icons.Default.Favorite, null)
+ }
+ },
+ trailingIcon = {
+ IconButton(
+ onClick = {},
+ modifier = Modifier.onGloballyPositioned {
+ trailingPosition = it.positionInRoot()
+ trailingSize = it.size
+ }
+ ) {
+ Icon(Icons.Default.Favorite, null)
+ }
+ }
+ )
+ }
+ }
+
+ rule.runOnIdle {
+ val size = 48.dp // default IconButton size
+
+ with(density) {
+ // leading
+ assertThat(leadingSize).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition?.x).isEqualTo(0f)
+ assertThat(leadingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - leadingSize!!.height) / 2f).roundToInt()
+ .toFloat()
+ )
+ // trailing
+ assertThat(trailingSize).isEqualTo(
+ IntSize(size.roundToPx(), size.roundToPx())
+ )
+ assertThat(trailingPosition?.x).isEqualTo(
+ (textFieldWidth.roundToPx() - trailingSize!!.width).toFloat()
+ )
+ assertThat(trailingPosition?.y)
+ .isEqualTo(
+ ((textFieldHeight.roundToPx() - trailingSize!!.height) / 2f)
+ .roundToInt().toFloat()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun testTextField_trailingAndLeading_sizeAndPosition_nonDefaultSizeIcon() {
+ val textFieldHeight = 80.dp
+ val textFieldWidth = 300.dp
+ val density = Density(2f)
+ val size = 70.dp
+
+ var leadingPosition: Offset? = null
+ var leadingSize: IntSize? = null
+ var trailingPosition: Offset? = null
+ var trailingSize: IntSize? = null
+
+ rule.setMaterialContent {
+ CompositionLocalProvider(LocalDensity provides density) {
+ TextField(
+ value = "text",
+ onValueChange = {},
+ modifier = Modifier.size(textFieldWidth, textFieldHeight),
+ leadingIcon = {
+ Box(
+ Modifier.size(size).onGloballyPositioned {
+ leadingPosition = it.positionInRoot()
+ leadingSize = it.size
+ }
+ )
+ },
+ trailingIcon = {
+ Box(
+ Modifier.size(size).onGloballyPositioned {
+ trailingPosition = it.positionInRoot()
+ trailingSize = it.size
+ }
+ )
+ }
+ )
+ }
+ }
+
+ rule.runOnIdle {
+ with(density) {
+ // leading
+ assertThat(leadingSize).isEqualTo(IntSize(size.roundToPx(), size.roundToPx()))
+ assertThat(leadingPosition?.x).isEqualTo(0f)
+ assertThat(leadingPosition?.y).isEqualTo(
+ ((textFieldHeight.roundToPx() - leadingSize!!.height) / 2f).roundToInt()
+ .toFloat()
+ )
+ // trailing
+ assertThat(trailingSize).isEqualTo(
+ IntSize(size.roundToPx(), size.roundToPx())
+ )
+ assertThat(trailingPosition?.x).isEqualTo(
+ (textFieldWidth.roundToPx() - trailingSize!!.width).toFloat()
+ )
+ assertThat(trailingPosition?.y)
+ .isEqualTo(
+ ((textFieldHeight.roundToPx() - trailingSize!!.height) / 2f)
+ .roundToInt().toFloat()
+ )
+ }
}
}
@Test
fun testTextField_labelPositionX_initial_withTrailingAndLeading() {
val height = 60.dp
- val iconSize = 30.dp
val labelPosition = Ref<Offset>()
rule.setMaterialContent {
Box {
@@ -774,13 +915,14 @@
}
)
},
- trailingIcon = { Box(Modifier.size(iconSize)) },
- leadingIcon = { Box(Modifier.size(iconSize)) }
+ trailingIcon = { Icon(Icons.Default.Favorite, null) },
+ leadingIcon = { Icon(Icons.Default.Favorite, null) }
)
}
}
rule.runOnIdleWithDensity {
+ val iconSize = 24.dp // default icon size
assertThat(labelPosition.value?.x).isEqualTo(
(ExpectedPadding.roundToPx() + IconPadding.roundToPx() + iconSize.roundToPx())
.toFloat()
@@ -789,7 +931,7 @@
}
@Test
- fun testTextField_labelPositionX_initial_withEmptyTrailingAndLeading() {
+ fun testTextField_labelPositionX_initial_withNullTrailingAndLeading() {
val height = 60.dp
val labelPosition = Ref<Offset>()
rule.setMaterialContent {
@@ -806,8 +948,8 @@
}
)
},
- trailingIcon = {},
- leadingIcon = {}
+ trailingIcon = null,
+ leadingIcon = null
)
}
}
@@ -825,7 +967,6 @@
TextField(
value = "",
onValueChange = {},
- label = {},
isError = false,
leadingIcon = {
assertThat(LocalContentColor.current)
@@ -853,7 +994,6 @@
TextField(
value = "",
onValueChange = {},
- label = {},
isError = true,
leadingIcon = {
assertThat(LocalContentColor.current)
@@ -883,7 +1023,6 @@
modifier = Modifier.testTag(TextfieldTag),
value = text.value,
onValueChange = { text.value = it },
- label = {},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Go,
keyboardType = KeyboardType.Email
@@ -1077,17 +1216,19 @@
@Test
fun testErrorSemantics_defaultMessage() {
+ lateinit var errorMessage: String
rule.setMaterialContent {
TextField(
value = "test",
onValueChange = {},
isError = true
)
+ errorMessage = getString(DefaultErrorMessage)
}
rule.onNodeWithText("test")
.assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
- .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, DefaultErrorMessage))
+ .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage))
}
@Test
diff --git a/compose/material/material/src/androidMain/baseline-prof.txt b/compose/material/material/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..e98ec55
--- /dev/null
+++ b/compose/material/material/src/androidMain/baseline-prof.txt
@@ -0,0 +1,26 @@
+# Baseline profile rules for androidx.compose.material
+# =============================================
+HSPLandroidx/compose/material/Colors;->**(**)**
+HSPLandroidx/compose/material/ButtonKt**->**(**)**
+HSPLandroidx/compose/material/AppBarKt**->**(**)**
+HPLandroidx/compose/material/ProgressIndicatorKt;->**(**)**
+HPLandroidx/compose/material/IconKt;->**(**)**
+HSPLandroidx/compose/material/ContentAlpha;->**(**)**
+HSPLandroidx/compose/material/ComposableSingletons$**->**(**)**
+HSPLandroidx/compose/material/DrawerKt;->**(**)**
+HSPLandroidx/compose/material/DrawerState;->**(**)**
+HSPLandroidx/compose/material/FadeInFadeOutState;->**(**)**
+HSPLandroidx/compose/material/FabPosition;->**(**)**
+HSPLandroidx/compose/material/FloatingActionButtonKt**->**(**)**
+HSPLandroidx/compose/material/MaterialTheme;->**(**)**
+HSPLandroidx/compose/material/MaterialTextSelectionColorsKt;->**(**)**
+HSPLandroidx/compose/material/MaterialRippleTheme;->**(**)**
+HSPLandroidx/compose/material/ScaffoldKt**->**(**)**
+HSPLandroidx/compose/material/SnackbarHostKt**->**(**)**
+HSPLandroidx/compose/material/SurfaceKt**->**(**)**
+HSPLandroidx/compose/material/SwipeableKt**->**(**)**
+HSPLandroidx/compose/material/SwipeableState**->**(**)**
+HSPLandroidx/compose/material/TextKt**->**(**)**
+HSPLandroidx/compose/material/Typography;->**(**)**
+# Prioritize only the top level classes for material. (Notably, this ignores icons)
+Landroidx/compose/material/*;
\ No newline at end of file
diff --git a/compose/material/material/src/androidMain/kotlin/androidx/compose/material/Strings.android.kt b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/Strings.android.kt
new file mode 100644
index 0000000..cc6d98b
--- /dev/null
+++ b/compose/material/material/src/androidMain/kotlin/androidx/compose/material/Strings.android.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2021 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.material
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.R
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
+
+@Composable
+internal actual fun getString(string: Strings): String {
+ LocalConfiguration.current
+ val resources = LocalContext.current.resources
+ return when (string) {
+ Strings.NavigationMenu -> resources.getString(R.string.navigation_menu)
+ Strings.CloseDrawer -> resources.getString(R.string.close_drawer)
+ Strings.CloseSheet -> resources.getString(R.string.close_sheet)
+ Strings.DefaultErrorMessage -> resources.getString(R.string.default_error_message)
+ else -> ""
+ }
+}
\ No newline at end of file
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
index e06fa92..394e4a3 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Drawer.kt
@@ -424,6 +424,7 @@
},
color = scrimColor
)
+ val navigationMenu = getString(Strings.NavigationMenu)
Surface(
modifier = with(LocalDensity.current) {
Modifier
@@ -437,7 +438,7 @@
.offset { IntOffset(drawerState.offset.value.roundToInt(), 0) }
.padding(end = EndDrawerPadding)
.semantics {
- paneTitle = Strings.NavigationMenu
+ paneTitle = navigationMenu
if (drawerState.isOpen) {
dismiss {
if (
@@ -561,6 +562,7 @@
},
visible = drawerState.targetValue != BottomDrawerValue.Closed
)
+ val navigationMenu = getString(Strings.NavigationMenu)
Surface(
drawerConstraints
.offset { IntOffset(x = 0, y = drawerState.offset.value.roundToInt()) }
@@ -568,7 +570,7 @@
drawerHeight = position.size.height.toFloat()
}
.semantics {
- paneTitle = Strings.NavigationMenu
+ paneTitle = navigationMenu
if (drawerState.isOpen) {
// TODO(b/180101663) The action currently doesn't return the correct results
dismiss {
@@ -623,13 +625,14 @@
targetValue = if (visible) 1f else 0f,
animationSpec = TweenSpec()
)
+ val closeDrawer = getString(Strings.CloseDrawer)
val dismissModifier = if (visible) {
Modifier
.pointerInput(onDismiss) {
detectTapGestures { onDismiss() }
}
.semantics(mergeDescendants = true) {
- contentDescription = Strings.CloseDrawer
+ contentDescription = closeDrawer
onClick { onDismiss(); true }
}
} else {
@@ -653,11 +656,12 @@
fraction: () -> Float,
color: Color
) {
+ val closeDrawer = getString(Strings.CloseDrawer)
val dismissDrawer = if (open) {
Modifier
.pointerInput(onClose) { detectTapGestures { onClose() } }
.semantics(mergeDescendants = true) {
- contentDescription = Strings.CloseDrawer
+ contentDescription = closeDrawer
onClick { onClose(); true }
}
} else {
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
index bf1ce75..1142c71 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/ModalBottomSheet.kt
@@ -357,11 +357,12 @@
targetValue = if (visible) 1f else 0f,
animationSpec = TweenSpec()
)
+ val closeSheet = getString(Strings.CloseSheet)
val dismissModifier = if (visible) {
Modifier
.pointerInput(onDismiss) { detectTapGestures { onDismiss() } }
.semantics(mergeDescendants = true) {
- contentDescription = Strings.CloseSheet
+ contentDescription = closeSheet
onClick { onDismiss(); true }
}
} else {
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
index 0837cb5..4805fb8 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
@@ -403,7 +403,10 @@
)
if (leading != null) {
- Box(Modifier.layoutId(LeadingId).iconPadding(start = HorizontalIconPadding)) {
+ Box(
+ modifier = Modifier.layoutId(LeadingId).then(IconDefaultSizeModifier),
+ contentAlignment = Alignment.Center
+ ) {
Decoration(
contentColor = leadingColor,
content = leading
@@ -411,19 +414,27 @@
}
}
if (trailing != null) {
- Box(Modifier.layoutId(TrailingId).iconPadding(end = HorizontalIconPadding)) {
+ Box(
+ modifier = Modifier.layoutId(TrailingId).then(IconDefaultSizeModifier),
+ contentAlignment = Alignment.Center
+ ) {
Decoration(
contentColor = trailingColor,
content = trailing
)
}
}
+ val paddingToIcon = TextFieldPadding - HorizontalIconPadding
+ val padding = Modifier.padding(
+ start = if (leading != null) paddingToIcon else TextFieldPadding,
+ end = if (trailing != null) paddingToIcon else TextFieldPadding
+ )
if (placeholder != null) {
- placeholder(Modifier.layoutId(PlaceholderId).padding(horizontal = TextFieldPadding))
+ placeholder(Modifier.layoutId(PlaceholderId).then(padding))
}
Box(
- modifier = Modifier.layoutId(TextFieldId).padding(horizontal = TextFieldPadding),
+ modifier = Modifier.layoutId(TextFieldId).then(padding),
propagateMinConstraints = true
) {
textField()
@@ -603,6 +614,7 @@
density: Float
) {
val topBottomPadding = (TextFieldPadding.value * density).roundToInt()
+ val iconPadding = HorizontalIconPadding.value * density
// placed center vertically and to the start edge horizontally
leadingPlaceable?.placeRelative(
@@ -626,9 +638,14 @@
}
val positionY =
startPositionY * (1 - animationProgress) - (it.height / 2) * animationProgress
- val positionX = (TextFieldPadding.value * density) +
- widthOrZero(leadingPlaceable) * (1 - animationProgress)
- it.placeRelative(positionX.roundToInt(), positionY.roundToInt())
+ val positionX = (
+ if (leadingPlaceable == null) {
+ 0f
+ } else {
+ (widthOrZero(leadingPlaceable) - iconPadding) * (1 - animationProgress)
+ }
+ ).roundToInt() + topBottomPadding
+ it.placeRelative(positionX, positionY.roundToInt())
}
// placed center vertically and after the leading icon horizontally if single line text field
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Strings.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Strings.kt
index 9dc477c..688038a 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Strings.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Strings.kt
@@ -16,11 +16,19 @@
package androidx.compose.material
-// TODO(b/138327849): (STOPSHIP) Move all of these to resources once we have a real resources system,
-// then delete this class
-internal object Strings {
- const val NavigationMenu = "Navigation menu"
- const val CloseDrawer = "Close navigation menu"
- const val CloseSheet = "Close sheet"
- const val DefaultErrorMessage = "Invalid input"
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Immutable
+
+@Suppress("INLINE_CLASS_DEPRECATED")
+@Immutable
+internal inline class Strings private constructor(@Suppress("unused") private val value: Int) {
+ companion object {
+ val NavigationMenu = Strings(0)
+ val CloseDrawer = Strings(1)
+ val CloseSheet = Strings(2)
+ val DefaultErrorMessage = Strings(3)
+ }
}
+
+@Composable
+internal expect fun getString(string: Strings): String
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
index 6d0ea40..f370a43 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
@@ -404,7 +404,10 @@
Layout(
content = {
if (leading != null) {
- Box(Modifier.layoutId(LeadingId).iconPadding(start = HorizontalIconPadding)) {
+ Box(
+ modifier = Modifier.layoutId(LeadingId).then(IconDefaultSizeModifier),
+ contentAlignment = Alignment.Center
+ ) {
Decoration(
contentColor = leadingColor,
content = leading
@@ -412,26 +415,27 @@
}
}
if (trailing != null) {
- Box(Modifier.layoutId(TrailingId).iconPadding(end = HorizontalIconPadding)) {
+ Box(
+ modifier = Modifier.layoutId(TrailingId).then(IconDefaultSizeModifier),
+ contentAlignment = Alignment.Center
+ ) {
Decoration(
contentColor = trailingColor,
content = trailing
)
}
}
- val padding = Modifier.padding(horizontal = TextFieldPadding)
+
+ val paddingToIcon = TextFieldPadding - HorizontalIconPadding
+ val padding = Modifier.padding(
+ start = if (leading != null) paddingToIcon else TextFieldPadding,
+ end = if (trailing != null) paddingToIcon else TextFieldPadding
+ )
if (placeholder != null) {
placeholder(Modifier.layoutId(PlaceholderId).then(padding))
}
if (label != null) {
- Box(
- modifier = Modifier
- .layoutId(LabelId)
- .iconPadding(
- start = TextFieldPadding,
- end = TextFieldPadding
- )
- ) { label() }
+ Box(Modifier.layoutId(LabelId).then(padding)) { label() }
}
Box(
modifier = Modifier.layoutId(TextFieldId).then(padding),
@@ -529,7 +533,7 @@
)
return layout(width, height) {
- if (widthOrZero(labelPlaceable) != 0) {
+ if (labelPlaceable != null) {
// label's final position is always relative to the baseline
val labelEndPosition = (baseLineOffset - lastBaseline).coerceAtLeast(0)
placeWithLabel(
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
index 01b48f06..8a025cd 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
@@ -25,9 +25,10 @@
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
-import androidx.compose.material.Strings.DefaultErrorMessage
+import androidx.compose.material.Strings.Companion.DefaultErrorMessage
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
@@ -37,24 +38,15 @@
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.takeOrElse
-import androidx.compose.ui.layout.LayoutModifier
-import androidx.compose.ui.layout.Measurable
-import androidx.compose.ui.layout.MeasureResult
-import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.layout.Placeable
-import androidx.compose.ui.platform.InspectorValueInfo
-import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.error
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.lerp
-import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.constrainWidth
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.offset
internal enum class TextFieldType {
Filled, Outlined
@@ -138,7 +130,8 @@
// Developers need to handle invalid input manually. But since we don't provide error
// message slot API, we can set the default error message in case developers forget about
// it.
- val textFieldModifier = modifier.semantics { if (isError) error(DefaultErrorMessage) }
+ val defaultErrorMessage = getString(DefaultErrorMessage)
+ val textFieldModifier = modifier.semantics { if (isError) error(defaultErrorMessage) }
when (type) {
TextFieldType.Filled -> {
TextFieldLayout(
@@ -233,37 +226,6 @@
internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0
-/**
- * A modifier that applies padding only if the size of the element is not zero
- */
-internal fun Modifier.iconPadding(start: Dp = 0.dp, end: Dp = 0.dp) =
- this.then(
- @Suppress("ModifierInspectorInfo")
- object : LayoutModifier, InspectorValueInfo(
- debugInspectorInfo {
- name = "iconPadding"
- properties["start"] = start
- properties["end"] = end
- }
- ) {
- override fun MeasureScope.measure(
- measurable: Measurable,
- constraints: Constraints
- ): MeasureResult {
- val horizontal = start.roundToPx() + end.roundToPx()
- val placeable = measurable.measure(constraints.offset(-horizontal))
- val width = if (placeable.nonZero) {
- constraints.constrainWidth(placeable.width + horizontal)
- } else {
- 0
- }
- return layout(width, placeable.height) {
- placeable.placeRelative(start.roundToPx(), 0)
- }
- }
- }
- )
-
private object TextFieldTransitionScope {
@Composable
fun Transition(
@@ -363,3 +325,5 @@
private val IndicatorFocusedWidth = 2.dp
internal val TextFieldPadding = 16.dp
internal val HorizontalIconPadding = 12.dp
+
+internal val IconDefaultSizeModifier = Modifier.defaultMinSize(48.dp, 48.dp)
\ No newline at end of file
diff --git a/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
new file mode 100644
index 0000000..6873b2d
--- /dev/null
+++ b/compose/material/material/src/desktopMain/kotlin/androidx/compose/material/Strings.desktop.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2021 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.material
+
+import androidx.compose.runtime.Composable
+
+@Composable
+internal actual fun getString(string: Strings): String {
+ return when (string) {
+ Strings.NavigationMenu -> "Navigation menu"
+ Strings.CloseDrawer -> "Close navigation menu"
+ Strings.CloseSheet -> "Close sheet"
+ Strings.DefaultErrorMessage -> "Invalid input"
+ else -> ""
+ }
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime-saveable/src/androidMain/baseline-prof.txt b/compose/runtime/runtime-saveable/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..1127602
--- /dev/null
+++ b/compose/runtime/runtime-saveable/src/androidMain/baseline-prof.txt
@@ -0,0 +1,8 @@
+# Baseline profile rules for androidx.compose.runtime.saveable
+# =============================================
+HSPLandroidx/compose/runtime/saveable/RememberSaveableKt**->**(**)**
+HSPLandroidx/compose/runtime/saveable/SaveableStateHolderImpl**->**(**)**
+HSPLandroidx/compose/runtime/saveable/SaveableStateHolderKt**->**(**)**
+HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryKt;->**(**)**
+HSPLandroidx/compose/runtime/saveable/SaveableStateRegistryImpl;->**(**)**
+Landroidx/compose/runtime/saveable/*;
\ No newline at end of file
diff --git a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/ProduceStateTests.kt b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/ProduceStateTests.kt
index cbc3a37..a550adb 100644
--- a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/ProduceStateTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/ProduceStateTests.kt
@@ -51,7 +51,7 @@
assertEquals(0, observedResult, "observedResult after initial composition")
- emitter.offer(1)
+ emitter.trySend(1)
rule.runOnIdle {
assertEquals(1, observedResult, "observedResult after emitting new value")
}
diff --git a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt
index 68f2966..2d95d76 100644
--- a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SideEffectTests.kt
@@ -298,10 +298,10 @@
}
}.then {
assertEquals(1, counter)
- ch.offer(Unit)
+ ch.trySend(Unit)
}.then {
assertEquals(2, counter)
- ch.offer(Unit)
+ ch.trySend(Unit)
}.then {
assertEquals(3, counter)
}
@@ -405,10 +405,10 @@
}.then {
myComposableArg = "world"
}.then {
- val offerSucceeded = pleaseSend.offer(Unit)
+ val offerSucceeded = pleaseSend.trySend(Unit).isSuccess
assertTrue(offerSucceeded, "task wasn't awaiting send signal")
}.then {
- val receivedResult = output.poll()
+ val receivedResult = output.tryReceive().getOrNull()
assertEquals("world", receivedResult)
}
}
diff --git a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SuspendingEffectsTests.kt b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SuspendingEffectsTests.kt
index 2f7677b..09cdb86 100644
--- a/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SuspendingEffectsTests.kt
+++ b/compose/runtime/runtime/integration-tests/src/androidAndroidTest/kotlin/androidx/compose/runtime/SuspendingEffectsTests.kt
@@ -56,10 +56,10 @@
}
}.then {
assertEquals(1, counter)
- ch.offer(Unit)
+ ch.trySend(Unit)
}.then {
assertEquals(2, counter)
- ch.offer(Unit)
+ ch.trySend(Unit)
}.then {
assertEquals(3, counter)
}
diff --git a/compose/runtime/runtime/src/androidMain/baseline-prof.txt b/compose/runtime/runtime/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..bd32703
--- /dev/null
+++ b/compose/runtime/runtime/src/androidMain/baseline-prof.txt
@@ -0,0 +1,945 @@
+# Baseline profile rules for androidx.compose.runtime
+# =============================================
+#
+# We prioritize everything at the top level, and a few sub-namespaces
+Landroidx/compose/runtime/*;
+Landroidx/compose/runtime/snapshots/*;
+Landroidx/compose/runtime/internal/*;
+Landroidx/compose/runtime/external/kotlinx/collections/immutable/**;
+#
+# Core runtime classes
+# ====
+# Note: AbstractApplier might benefit from inline caches. consider removing.
+HSPLandroidx/compose/runtime/AbstractApplier;->**(**)**
+HSPLandroidx/compose/runtime/Anchor;->**(**)**
+HSPLandroidx/compose/runtime/Applier$DefaultImpls;->**(**)**
+HSPLandroidx/compose/runtime/BroadcastFrameClock**->**(**)**
+HSPLandroidx/compose/runtime/ComposablesKt;->**(**)**
+HSPLandroidx/compose/runtime/ComposerImpl**->**(**)**
+HSPLandroidx/compose/runtime/ComposerKt**->**(**)**
+HSPLandroidx/compose/runtime/CompositionContext;->**(**)**
+HSPLandroidx/compose/runtime/CompositionImpl**->**(**)**
+HSPLandroidx/compose/runtime/CompositionKt;->**(**)**
+HSPLandroidx/compose/runtime/CompositionLocal;->**(**)**
+HSPLandroidx/compose/runtime/CompositionLocalKt;->**(**)**
+HSPLandroidx/compose/runtime/CompositionScopedCoroutineScopeCanceller;->**(**)**
+HSPLandroidx/compose/runtime/DerivedSnapshotState**->**(**)**
+HSPLandroidx/compose/runtime/DisposableEffectImpl;->**(**)**
+HSPLandroidx/compose/runtime/DynamicProvidableCompositionLocal;->**(**)**
+HSPLandroidx/compose/runtime/EffectsKt;->**(**)**
+HSPLandroidx/compose/runtime/GroupInfo;->**(**)**
+HSPLandroidx/compose/runtime/InvalidationResult;->**(**)**
+HSPLandroidx/compose/runtime/Invalidation;->**(**)**
+HSPLandroidx/compose/runtime/KeyInfo;->**(**)**
+HSPLandroidx/compose/runtime/Latch;->**(**)**
+HSPLandroidx/compose/runtime/LaunchedEffectImpl;->**(**)**
+HSPLandroidx/compose/runtime/LazyValueHolder;->**(**)**
+HSPLandroidx/compose/runtime/MonotonicFrameClock**->**(**)**
+HSPLandroidx/compose/runtime/NeverEqualPolicy;->**(**)**
+HSPLandroidx/compose/runtime/OpaqueKey;->**(**)**
+HSPLandroidx/compose/runtime/ParcelableSnapshotMutableState**->**(**)**
+HSPLandroidx/compose/runtime/PausableMonotonicFrameClock;->**(**)**
+HSPLandroidx/compose/runtime/Pending**->**(**)**
+HSPLandroidx/compose/runtime/ProvidableCompositionLocal;->**(**)**
+HSPLandroidx/compose/runtime/ProvidedValue;->**(**)**
+HSPLandroidx/compose/runtime/RecomposeScopeImpl;->**(**)**
+HSPLandroidx/compose/runtime/Recomposer**->**(**)**
+HSPLandroidx/compose/runtime/SkippableUpdater;->**(**)**
+HSPLandroidx/compose/runtime/SlotReader;->**(**)**
+HSPLandroidx/compose/runtime/SlotTable;->**(**)**
+HSPLandroidx/compose/runtime/SlotTableKt;->**(**)**
+HSPLandroidx/compose/runtime/SlotWriter;->**(**)**
+HSPLandroidx/compose/runtime/SnapshotMutableStateImpl**->**(**)**
+HSPLandroidx/compose/runtime/SnapshotStateKt**->**(**)**
+HSPLandroidx/compose/runtime/SnapshotThreadLocal;->**(**)**
+HSPLandroidx/compose/runtime/StaticProvidableCompositionLocal;->**(**)**
+HSPLandroidx/compose/runtime/StaticValueHolder;->**(**)**
+HSPLandroidx/compose/runtime/StructuralEqualityPolicy;->**(**)**
+HSPLandroidx/compose/runtime/Trace;->**(**)**
+HSPLandroidx/compose/runtime/Updater**->**(**)**
+HSPLandroidx/compose/runtime/internal/ComposableLambdaImpl**->**(**)**
+HSPLandroidx/compose/runtime/internal/ComposableLambdaKt;->**(**)**
+HSPLandroidx/compose/runtime/ActualJvm_jvmKt;->identityHashCode(Ljava/lang/Object;)I
+#
+# Snapshot related stuff
+HSPLandroidx/compose/runtime/snapshots/MutableSnapshot;->**(**)**
+HSPLandroidx/compose/runtime/snapshots/NestedMutableSnapshot;->**(**)**
+HSPLandroidx/compose/runtime/snapshots/Snapshot**->**(**)**
+HSPLandroidx/compose/runtime/snapshots/ListUtilsKt;->fastToSet(Ljava/util/List;)Ljava/util/Set;
+HSPLandroidx/compose/runtime/snapshots/SnapshotApplyResult**->**(**)**
+HSPLandroidx/compose/runtime/snapshots/SnapshotIdSet**->**(**)**
+HSPLandroidx/compose/runtime/snapshots/SnapshotStateList**->**(**)**
+HSPLandroidx/compose/runtime/snapshots/SnapshotStateObserver**->**(**)**
+HSPLandroidx/compose/runtime/snapshots/StateRecord;->**(**)**
+HSPLandroidx/compose/runtime/snapshots/TransparentObserverMutableSnapshot;->**(**)**
+#
+# MutableVector and other purpose-built data structures are hot paths
+HSPLandroidx/compose/runtime/collection/**->**(**)**
+HSPLandroidx/compose/runtime/Stack;->**(**)**
+HSPLandroidx/compose/runtime/IntStack;->**(**)**
+HSPLandroidx/compose/runtime/internal/ThreadMap;->**(**)**
+#
+# kotlinx.collections.immutable copy
+# ====
+# We only use a subset of these methods but haven't gotten rid of all of the APIs to preserve
+# source. Since this is very niche usage, this should stay pretty consistent.
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentHashMapOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentListOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/ExtensionsKt;->persistentSetOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/AbstractPersistentList;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector$Companion;->getEMPTY()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;-><init>([Ljava/lang/Object;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->add(Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->addAll(Ljava/util/Collection;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->get(I)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/SmallPersistentVector;->getSize()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableList/UtilsKt;->persistentVectorOf()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentList;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;->getKey()Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/MapEntry;->getValue()Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap$Companion;->emptyOf$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->builder()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap$Builder;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->builder()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->containsKey(Ljava/lang/Object;)Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->createEntries()Landroidx/compose/runtime/external/kotlinx/collections/immutable/ImmutableSet;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getEntries()Ljava/util/Set;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getNode$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->getSize()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;->put(Ljava/lang/Object;Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;[Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->checkHasNext()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->ensureNextEntryIsReady()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->hasNext()Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->moveToNextNodeWithData(I)I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBaseIterator;->next()Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->build()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->build()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getModCount$runtime_release()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getOwnership$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->getSize()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->putAll(Ljava/util/Map;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setModCount$runtime_release(I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setOperationResult$runtime_release(Ljava/lang/Object;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;->setSize(I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;->getSize()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntries;->iterator()Ljava/util/Iterator;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapEntriesIterator;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$Companion;->getEMPTY$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;-><init>(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;->getNode()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;->getSizeDelta()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;-><init>(II[Ljava/lang/Object;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;-><init>(II[Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->asInsertResult()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->containsKey(ILjava/lang/Object;I)Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->elementsIdentityEquals(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;)Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->entryCount$runtime_release()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->entryKeyIndex$runtime_release(I)I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->get(ILjava/lang/Object;I)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->getBuffer$runtime_release()[Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->hasEntryAt$runtime_release(I)Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->hasNodeAt(I)Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->insertEntryAt(ILjava/lang/Object;Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->keyAtIndex(I)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->makeNode(ILjava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutableInsertEntryAt(ILjava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePut(ILjava/lang/Object;Ljava/lang/Object;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePutAll(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;ILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutablePutAllFromOtherNodeCell(Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;IILandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->mutableUpdateValueAtIndex(ILjava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMapBuilder;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->nodeAtIndex$runtime_release(I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->nodeIndex$runtime_release(I)I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->put(ILjava/lang/Object;Ljava/lang/Object;I)Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode$ModificationResult;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNode;->valueAtKeyIndex(I)Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->getBuffer()[Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->getIndex()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->hasNextKey()Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->hasNextNode()Z
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->reset([Ljava/lang/Object;I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->reset([Ljava/lang/Object;II)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeBaseIterator;->setIndex(I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;->next()Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeEntriesIterator;->next()Ljava/util/Map$Entry;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->access$insertEntryAtIndex([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->indexSegment(II)I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/TrieNodeKt;->insertEntryAtIndex([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;)[Ljava/lang/Object;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/Links;-><init>(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet$Companion;->emptyOf$runtime_release()Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;-><init>(Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/immutableMap/PersistentHashMap;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->access$getEMPTY$cp()Landroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->add(Ljava/lang/Object;)Landroidx/compose/runtime/external/kotlinx/collections/immutable/PersistentSet;
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/implementations/persistentOrderedSet/PersistentOrderedSet;->getSize()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/CommonFunctionsKt;->assert(Z)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;-><init>(I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;-><init>(IILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;->getCount()I
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/DeltaCounter;->setCount(I)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/EndOfChain;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/ListImplementation;-><init>()V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/ListImplementation;->checkElementIndex$runtime_release(II)V
+HSPLandroidx/compose/runtime/external/kotlinx/collections/immutable/internal/MutabilityOwnership;-><init>()V
+#
+# important external / stdlib methods and classes
+# Since compose heavily relies on various kotlin standard libraries, it is important that these get
+# compiled as well. Since the std libraries are large and we don't use everything, we are
+# conservative here and avoid wildcards and instead use profile dumps to guide us
+HSPLkotlin/ULong$Companion;-><init>()V
+HSPLkotlin/ULong$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/ULong;->constructor-impl(J)J
+HSPLkotlin/UnsignedKt;->ulongToDouble(J)D
+HSPLkotlin/collections/AbstractCollection;-><init>()V
+HSPLkotlin/collections/AbstractCollection;->isEmpty()Z
+HSPLkotlin/collections/AbstractCollection;->size()I
+HSPLkotlin/collections/AbstractList$Companion;-><init>()V
+HSPLkotlin/collections/AbstractList$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/collections/AbstractList$IteratorImpl;-><init>(Lkotlin/collections/AbstractList;)V
+HSPLkotlin/collections/AbstractList$IteratorImpl;->hasNext()Z
+HSPLkotlin/collections/AbstractList$IteratorImpl;->next()Ljava/lang/Object;
+HSPLkotlin/collections/AbstractList;-><init>()V
+HSPLkotlin/collections/AbstractList;->iterator()Ljava/util/Iterator;
+HSPLkotlin/collections/AbstractMap$Companion;-><init>()V
+HSPLkotlin/collections/AbstractMap$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/collections/AbstractMap;-><init>()V
+HSPLkotlin/collections/AbstractMap;->containsEntry$kotlin_stdlib(Ljava/util/Map$Entry;)Z
+HSPLkotlin/collections/AbstractMap;->entrySet()Ljava/util/Set;
+HSPLkotlin/collections/AbstractMap;->equals(Ljava/lang/Object;)Z
+HSPLkotlin/collections/AbstractMap;->size()I
+HSPLkotlin/collections/AbstractMutableList;-><init>()V
+HSPLkotlin/collections/AbstractMutableList;->size()I
+HSPLkotlin/collections/AbstractMutableMap;-><init>()V
+HSPLkotlin/collections/AbstractMutableMap;->size()I
+HSPLkotlin/collections/AbstractSet$Companion;-><init>()V
+HSPLkotlin/collections/AbstractSet$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/collections/AbstractSet$Companion;->setEquals$kotlin_stdlib(Ljava/util/Set;Ljava/util/Set;)Z
+HSPLkotlin/collections/AbstractSet;-><init>()V
+HSPLkotlin/collections/AbstractSet;->equals(Ljava/lang/Object;)Z
+HSPLkotlin/collections/ArrayAsCollection;-><init>([Ljava/lang/Object;Z)V
+HSPLkotlin/collections/ArrayAsCollection;->toArray()[Ljava/lang/Object;
+HSPLkotlin/collections/ArrayDeque$Companion;-><init>()V
+HSPLkotlin/collections/ArrayDeque$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/collections/ArrayDeque$Companion;->newCapacity$kotlin_stdlib(II)I
+HSPLkotlin/collections/ArrayDeque;-><init>()V
+HSPLkotlin/collections/ArrayDeque;->access$getElementData$p(Lkotlin/collections/ArrayDeque;)[Ljava/lang/Object;
+HSPLkotlin/collections/ArrayDeque;->access$getHead$p(Lkotlin/collections/ArrayDeque;)I
+HSPLkotlin/collections/ArrayDeque;->access$positiveMod(Lkotlin/collections/ArrayDeque;I)I
+HSPLkotlin/collections/ArrayDeque;->addLast(Ljava/lang/Object;)V
+HSPLkotlin/collections/ArrayDeque;->copyElements(I)V
+HSPLkotlin/collections/ArrayDeque;->ensureCapacity(I)V
+HSPLkotlin/collections/ArrayDeque;->getSize()I
+HSPLkotlin/collections/ArrayDeque;->incremented(I)I
+HSPLkotlin/collections/ArrayDeque;->isEmpty()Z
+HSPLkotlin/collections/ArrayDeque;->positiveMod(I)I
+HSPLkotlin/collections/ArrayDeque;->removeFirst()Ljava/lang/Object;
+HSPLkotlin/collections/ArrayDeque;->removeFirstOrNull()Ljava/lang/Object;
+HSPLkotlin/collections/ArraysKt__ArraysJVMKt;->copyOfRangeToIndexCheck(II)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt$asList$5;-><init>([F)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt$asList$5;->get(I)Ljava/lang/Float;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt$asList$5;->get(I)Ljava/lang/Object;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt$asList$5;->getSize()I
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->asList([F)Ljava/util/List;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->asList([Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([F[FIIIILjava/lang/Object;)[F
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([I[IIIIILjava/lang/Object;)[I
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto$default([Ljava/lang/Object;[Ljava/lang/Object;IIIILjava/lang/Object;)[Ljava/lang/Object;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([F[FIII)[F
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([I[IIII)[I
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyInto([Ljava/lang/Object;[Ljava/lang/Object;III)[Ljava/lang/Object;
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->copyOfRange([FII)[F
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill$default([IIIIILjava/lang/Object;)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill([IIII)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->fill([Ljava/lang/Object;Ljava/lang/Object;II)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->sort([Ljava/lang/Object;)V
+HSPLkotlin/collections/ArraysKt___ArraysJvmKt;->sortWith([Ljava/lang/Object;Ljava/util/Comparator;II)V
+HSPLkotlin/collections/ArraysKt___ArraysKt;->contains([CC)Z
+HSPLkotlin/collections/ArraysKt___ArraysKt;->first([Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlin/collections/ArraysKt___ArraysKt;->getLastIndex([Ljava/lang/Object;)I
+HSPLkotlin/collections/ArraysKt___ArraysKt;->indexOf([CC)I
+HSPLkotlin/collections/ArraysKt___ArraysKt;->slice([FLkotlin/ranges/IntRange;)Ljava/util/List;
+HSPLkotlin/collections/ArraysKt___ArraysKt;->toList([Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/ArraysKt___ArraysKt;->toMutableList([Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/ArraysUtilJVM;->asList([Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt__CollectionsJVMKt;->copyToArrayOfAny([Ljava/lang/Object;Z)[Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt__CollectionsJVMKt;->listOf(Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt__CollectionsKt;->arrayListOf([Ljava/lang/Object;)Ljava/util/ArrayList;
+HSPLkotlin/collections/CollectionsKt__CollectionsKt;->asCollection([Ljava/lang/Object;)Ljava/util/Collection;
+HSPLkotlin/collections/CollectionsKt__CollectionsKt;->emptyList()Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt__CollectionsKt;->getLastIndex(Ljava/util/List;)I
+HSPLkotlin/collections/CollectionsKt__CollectionsKt;->listOf([Ljava/lang/Object;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt__IterablesKt;->collectionSizeOrDefault(Ljava/lang/Iterable;I)I
+HSPLkotlin/collections/CollectionsKt__MutableCollectionsJVMKt;->sortWith(Ljava/util/List;Ljava/util/Comparator;)V
+HSPLkotlin/collections/CollectionsKt__MutableCollectionsKt;->addAll(Ljava/util/Collection;Ljava/lang/Iterable;)Z
+HSPLkotlin/collections/CollectionsKt__MutableCollectionsKt;->removeFirstOrNull(Ljava/util/List;)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->distinct(Ljava/lang/Iterable;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->filterNotNull(Ljava/lang/Iterable;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->filterNotNullTo(Ljava/lang/Iterable;Ljava/util/Collection;)Ljava/util/Collection;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->first(Ljava/util/List;)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->firstOrNull(Ljava/util/List;)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->getOrNull(Ljava/util/List;I)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->last(Ljava/util/List;)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->lastOrNull(Ljava/util/List;)Ljava/lang/Object;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->maxOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->minOrNull(Ljava/lang/Iterable;)Ljava/lang/Float;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->plus(Ljava/util/Collection;Ljava/lang/Iterable;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toFloatArray(Ljava/util/Collection;)[F
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toIntArray(Ljava/util/Collection;)[I
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toList(Ljava/lang/Iterable;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toMutableList(Ljava/util/Collection;)Ljava/util/List;
+HSPLkotlin/collections/CollectionsKt___CollectionsKt;->toMutableSet(Ljava/lang/Iterable;)Ljava/util/Set;
+HSPLkotlin/collections/EmptyList;-><init>()V
+HSPLkotlin/collections/EmptyList;->equals(Ljava/lang/Object;)Z
+HSPLkotlin/collections/EmptyList;->getSize()I
+HSPLkotlin/collections/EmptyList;->isEmpty()Z
+HSPLkotlin/collections/EmptyList;->size()I
+HSPLkotlin/collections/EmptyList;->toArray()[Ljava/lang/Object;
+HSPLkotlin/collections/EmptyMap;-><init>()V
+HSPLkotlin/collections/EmptyMap;->containsKey(Ljava/lang/Object;)Z
+HSPLkotlin/collections/EmptyMap;->equals(Ljava/lang/Object;)Z
+HSPLkotlin/collections/EmptyMap;->get(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlin/collections/EmptyMap;->get(Ljava/lang/Object;)Ljava/lang/Void;
+HSPLkotlin/collections/EmptyMap;->isEmpty()Z
+HSPLkotlin/collections/IntIterator;-><init>()V
+HSPLkotlin/collections/MapsKt__MapWithDefaultKt;->getOrImplicitDefaultNullable(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlin/collections/MapsKt__MapsJVMKt;->mapCapacity(I)I
+HSPLkotlin/collections/MapsKt__MapsKt;->emptyMap()Ljava/util/Map;
+HSPLkotlin/collections/MapsKt__MapsKt;->getValue(Ljava/util/Map;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlin/collections/MapsKt__MapsKt;->mapOf([Lkotlin/Pair;)Ljava/util/Map;
+HSPLkotlin/collections/MapsKt__MapsKt;->putAll(Ljava/util/Map;Ljava/lang/Iterable;)V
+HSPLkotlin/collections/MapsKt__MapsKt;->putAll(Ljava/util/Map;[Lkotlin/Pair;)V
+HSPLkotlin/collections/MapsKt__MapsKt;->toMap(Ljava/lang/Iterable;)Ljava/util/Map;
+HSPLkotlin/collections/MapsKt__MapsKt;->toMap(Ljava/lang/Iterable;Ljava/util/Map;)Ljava/util/Map;
+HSPLkotlin/collections/MapsKt__MapsKt;->toMap([Lkotlin/Pair;Ljava/util/Map;)Ljava/util/Map;
+HSPLkotlin/collections/MapsKt__MapsKt;->toMutableMap(Ljava/util/Map;)Ljava/util/Map;
+HSPLkotlin/comparisons/ComparisonsKt__ComparisonsKt;->compareValues(Ljava/lang/Comparable;Ljava/lang/Comparable;)I
+HSPLkotlin/jvm/internal/CollectionToArray;->toArray(Ljava/util/Collection;)[Ljava/lang/Object;
+HSPLkotlin/jvm/internal/FloatCompanionObject;-><init>()V
+HSPLkotlin/jvm/internal/FunctionReference;-><init>(ILjava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
+HSPLkotlin/jvm/internal/FunctionReference;->equals(Ljava/lang/Object;)Z
+HSPLkotlin/jvm/internal/FunctionReferenceImpl;-><init>(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
+HSPLkotlin/jvm/internal/FunctionReferenceImpl;-><init>(ILjava/lang/Object;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V
+HSPLkotlin/jvm/internal/InlineMarker;->mark(I)V
+HSPLkotlin/jvm/internal/IntCompanionObject;-><init>()V
+HSPLkotlin/jvm/internal/Intrinsics;->areEqual(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLkotlin/jvm/internal/Intrinsics;->checkExpressionValueIsNotNull(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLkotlin/jvm/internal/Intrinsics;->checkNotNull(Ljava/lang/Object;)V
+HSPLkotlin/jvm/internal/Intrinsics;->checkNotNullExpressionValue(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLkotlin/jvm/internal/Intrinsics;->checkNotNullParameter(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLkotlin/jvm/internal/Intrinsics;->checkParameterIsNotNull(Ljava/lang/Object;Ljava/lang/String;)V
+HSPLkotlin/jvm/internal/Intrinsics;->compare(II)I
+HSPLkotlin/jvm/internal/Lambda;-><init>(I)V
+HSPLkotlin/jvm/internal/Lambda;->getArity()I
+HSPLkotlin/math/MathKt__MathJVMKt;->getSign(I)I
+HSPLkotlin/math/MathKt__MathJVMKt;->roundToInt(F)I
+HSPLkotlin/ranges/IntRange$Companion;-><init>()V
+HSPLkotlin/ranges/IntRange$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/ranges/IntRange;-><init>(II)V
+HSPLkotlin/ranges/IntRange;->getEndInclusive()Ljava/lang/Integer;
+HSPLkotlin/ranges/IntRange;->getStart()Ljava/lang/Integer;
+HSPLkotlin/ranges/IntRange;->isEmpty()Z
+HSPLkotlin/ranges/RangesKt__RangesKt;->checkStepIsPositive(ZLjava/lang/Number;)V
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(II)I
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(JJ)J
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtLeast(Ljava/lang/Comparable;Ljava/lang/Comparable;)Ljava/lang/Comparable;
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtMost(II)I
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceAtMost(JJ)J
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(DDD)D
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(FFF)F
+HSPLkotlin/ranges/RangesKt___RangesKt;->coerceIn(III)I
+HSPLkotlin/ranges/RangesKt___RangesKt;->step(Lkotlin/ranges/IntProgression;I)Lkotlin/ranges/IntProgression;
+HSPLkotlin/ranges/RangesKt___RangesKt;->until(II)Lkotlin/ranges/IntRange;
+HSPLkotlinx/coroutines/AbstractCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Z)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->afterResume(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->cancellationExceptionMessage()Ljava/lang/String;
+HSPLkotlinx/coroutines/AbstractCoroutine;->getContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/AbstractCoroutine;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/AbstractCoroutine;->initParentJob$kotlinx_coroutines_core()V
+HSPLkotlinx/coroutines/AbstractCoroutine;->isActive()Z
+HSPLkotlinx/coroutines/AbstractCoroutine;->onCancelled(Ljava/lang/Throwable;Z)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->onCompleted(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->onCompletionInternal(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->resumeWith(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/AbstractCoroutine;->start(Lkotlinx/coroutines/CoroutineStart;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
+HSPLkotlinx/coroutines/Active;-><init>()V
+HSPLkotlinx/coroutines/BeforeResumeCancelHandler;-><init>()V
+HSPLkotlinx/coroutines/BlockingEventLoop;-><init>(Ljava/lang/Thread;)V
+HSPLkotlinx/coroutines/BuildersKt;->launch$default(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/BuildersKt;->launch(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/BuildersKt;->withContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->launch$default(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->launch(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;Lkotlinx/coroutines/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/BuildersKt__Builders_commonKt;->withContext(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancelHandler;-><init>()V
+HSPLkotlinx/coroutines/CancelHandlerBase;-><init>()V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;-><init>(Lkotlin/coroutines/Continuation;I)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->callCancelHandler(Lkotlinx/coroutines/CancelHandler;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancel(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancelCompletedResult$kotlinx_coroutines_core(Ljava/lang/Object;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->cancelLater(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->checkCompleted()Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->completeResume(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->detachChild$kotlinx_coroutines_core()V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->detachChildIfNonResuable()V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->dispatchResume(I)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getContinuationCancellationCause(Lkotlinx/coroutines/Job;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getDelegate$kotlinx_coroutines_core()Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getExceptionalResult$kotlinx_coroutines_core(Ljava/lang/Object;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getParentHandle()Lkotlinx/coroutines/DisposableHandle;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getResult()Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getState$kotlinx_coroutines_core()Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->getSuccessfulResult$kotlinx_coroutines_core(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->initCancellability()V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->invokeOnCancellation(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->isCompleted()Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->isReusable()Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->makeCancelHandler(Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/CancelHandler;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->parentCancelled$kotlinx_coroutines_core(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resetStateReusable()Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeImpl$default(Lkotlinx/coroutines/CancellableContinuationImpl;Ljava/lang/Object;ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeImpl(Ljava/lang/Object;ILkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeUndispatched(Lkotlinx/coroutines/CoroutineDispatcher;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumeWith(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->resumedState(Lkotlinx/coroutines/NotCompleted;Ljava/lang/Object;ILkotlin/jvm/functions/Function1;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->setParentHandle(Lkotlinx/coroutines/DisposableHandle;)V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->setupCancellation()V
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->takeState$kotlinx_coroutines_core()Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResume()Z
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResume(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->tryResumeImpl(Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/CancellableContinuationImpl;->trySuspend()Z
+HSPLkotlinx/coroutines/CancellableContinuationKt;->disposeOnCancellation(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/DisposableHandle;)V
+HSPLkotlinx/coroutines/CancellableContinuationKt;->getOrCreateCancellableContinuation(Lkotlin/coroutines/Continuation;)Lkotlinx/coroutines/CancellableContinuationImpl;
+HSPLkotlinx/coroutines/CancellableContinuationKt;->removeOnCancellation(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/CancelledContinuation;-><init>(Lkotlin/coroutines/Continuation;Ljava/lang/Throwable;Z)V
+HSPLkotlinx/coroutines/CancelledContinuation;->makeResumed()Z
+HSPLkotlinx/coroutines/ChildContinuation;-><init>(Lkotlinx/coroutines/CancellableContinuationImpl;)V
+HSPLkotlinx/coroutines/ChildContinuation;->invoke(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/ChildHandleNode;-><init>(Lkotlinx/coroutines/ChildJob;)V
+HSPLkotlinx/coroutines/ChildHandleNode;->childCancelled(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/ChildHandleNode;->invoke(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CompletedContinuation;-><init>(Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CompletedContinuation;-><init>(Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/CompletedContinuation;->copy$default(Lkotlinx/coroutines/CompletedContinuation;Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;ILjava/lang/Object;)Lkotlinx/coroutines/CompletedContinuation;
+HSPLkotlinx/coroutines/CompletedContinuation;->copy(Ljava/lang/Object;Lkotlinx/coroutines/CancelHandler;Lkotlin/jvm/functions/Function1;Ljava/lang/Object;Ljava/lang/Throwable;)Lkotlinx/coroutines/CompletedContinuation;
+HSPLkotlinx/coroutines/CompletedContinuation;->getCancelled()Z
+HSPLkotlinx/coroutines/CompletedContinuation;->invokeHandlers(Lkotlinx/coroutines/CancellableContinuationImpl;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/CompletedExceptionally;-><init>(Ljava/lang/Throwable;Z)V
+HSPLkotlinx/coroutines/CompletedExceptionally;-><init>(Ljava/lang/Throwable;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/CompletedExceptionally;->getHandled()Z
+HSPLkotlinx/coroutines/CompletedExceptionally;->makeHandled()Z
+HSPLkotlinx/coroutines/CompletionHandlerBase;-><init>()V
+HSPLkotlinx/coroutines/CompletionStateKt;->recoverResult(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CompletionStateKt;->toState$default(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CompletionStateKt;->toState(Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CompletionStateKt;->toState(Ljava/lang/Object;Lkotlinx/coroutines/CancellableContinuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CoroutineContextKt;->createDefaultDispatcher()Lkotlinx/coroutines/CoroutineDispatcher;
+HSPLkotlinx/coroutines/CoroutineContextKt;->newCoroutineContext(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/CoroutineContext;)Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/CoroutineDispatcher$Key$1;-><init>()V
+HSPLkotlinx/coroutines/CoroutineDispatcher$Key;-><init>()V
+HSPLkotlinx/coroutines/CoroutineDispatcher$Key;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/CoroutineDispatcher;-><init>()V
+HSPLkotlinx/coroutines/CoroutineDispatcher;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+HSPLkotlinx/coroutines/CoroutineDispatcher;->interceptContinuation(Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/CoroutineDispatcher;->isDispatchNeeded(Lkotlin/coroutines/CoroutineContext;)Z
+HSPLkotlinx/coroutines/CoroutineDispatcher;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/CoroutineDispatcher;->releaseInterceptedContinuation(Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/CoroutineExceptionHandler$Key;-><init>()V
+HSPLkotlinx/coroutines/CoroutineScopeKt;->CoroutineScope(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/CoroutineScope;
+HSPLkotlinx/coroutines/CoroutineScopeKt;->cancel$default(Lkotlinx/coroutines/CoroutineScope;Ljava/util/concurrent/CancellationException;ILjava/lang/Object;)V
+HSPLkotlinx/coroutines/CoroutineScopeKt;->cancel(Lkotlinx/coroutines/CoroutineScope;Ljava/util/concurrent/CancellationException;)V
+HSPLkotlinx/coroutines/CoroutineScopeKt;->coroutineScope(Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/CoroutineScopeKt;->isActive(Lkotlinx/coroutines/CoroutineScope;)Z
+HSPLkotlinx/coroutines/CoroutineStart;-><init>(Ljava/lang/String;I)V
+HSPLkotlinx/coroutines/CoroutineStart;->invoke(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/CoroutineStart;->isLazy()Z
+HSPLkotlinx/coroutines/CoroutineStart;->values()[Lkotlinx/coroutines/CoroutineStart;
+HSPLkotlinx/coroutines/DebugKt;->getASSERTIONS_ENABLED()Z
+HSPLkotlinx/coroutines/DebugKt;->getDEBUG()Z
+HSPLkotlinx/coroutines/DebugKt;->getRECOVER_STACK_TRACES()Z
+HSPLkotlinx/coroutines/DebugStringsKt;->getClassSimpleName(Ljava/lang/Object;)Ljava/lang/String;
+HSPLkotlinx/coroutines/DefaultExecutor;-><init>()V
+HSPLkotlinx/coroutines/DefaultExecutor;->createThreadSync()Ljava/lang/Thread;
+HSPLkotlinx/coroutines/DefaultExecutor;->getThread()Ljava/lang/Thread;
+HSPLkotlinx/coroutines/DefaultExecutor;->isShutdownRequested()Z
+HSPLkotlinx/coroutines/DefaultExecutor;->notifyStartup()Z
+HSPLkotlinx/coroutines/DefaultExecutor;->run()V
+HSPLkotlinx/coroutines/DefaultExecutorKt;->getDefaultDelay()Lkotlinx/coroutines/Delay;
+HSPLkotlinx/coroutines/DelayKt;->delay(JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/DelayKt;->getDelay(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Delay;
+HSPLkotlinx/coroutines/DispatchedTask;-><init>(I)V
+HSPLkotlinx/coroutines/DispatchedTask;->getExceptionalResult$kotlinx_coroutines_core(Ljava/lang/Object;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/DispatchedTask;->getSuccessfulResult$kotlinx_coroutines_core(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/DispatchedTask;->handleFatalException(Ljava/lang/Throwable;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/DispatchedTask;->run()V
+HSPLkotlinx/coroutines/DispatchedTaskKt;->dispatch(Lkotlinx/coroutines/DispatchedTask;I)V
+HSPLkotlinx/coroutines/DispatchedTaskKt;->isCancellableMode(I)Z
+HSPLkotlinx/coroutines/DispatchedTaskKt;->isReusableMode(I)Z
+HSPLkotlinx/coroutines/DispatchedTaskKt;->resume(Lkotlinx/coroutines/DispatchedTask;Lkotlin/coroutines/Continuation;Z)V
+HSPLkotlinx/coroutines/DispatchedTaskKt;->resumeUnconfined(Lkotlinx/coroutines/DispatchedTask;)V
+HSPLkotlinx/coroutines/Dispatchers;-><init>()V
+HSPLkotlinx/coroutines/Dispatchers;->getDefault()Lkotlinx/coroutines/CoroutineDispatcher;
+HSPLkotlinx/coroutines/DisposeOnCancel;-><init>(Lkotlinx/coroutines/DisposableHandle;)V
+HSPLkotlinx/coroutines/Empty;-><init>(Z)V
+HSPLkotlinx/coroutines/Empty;->getList()Lkotlinx/coroutines/NodeList;
+HSPLkotlinx/coroutines/Empty;->isActive()Z
+HSPLkotlinx/coroutines/EventLoop;-><init>()V
+HSPLkotlinx/coroutines/EventLoop;->decrementUseCount(Z)V
+HSPLkotlinx/coroutines/EventLoop;->delta(Z)J
+HSPLkotlinx/coroutines/EventLoop;->getNextTime()J
+HSPLkotlinx/coroutines/EventLoop;->incrementUseCount$default(Lkotlinx/coroutines/EventLoop;ZILjava/lang/Object;)V
+HSPLkotlinx/coroutines/EventLoop;->incrementUseCount(Z)V
+HSPLkotlinx/coroutines/EventLoop;->isUnconfinedLoopActive()Z
+HSPLkotlinx/coroutines/EventLoop;->processUnconfinedEvent()Z
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedResumeTask;-><init>(Lkotlinx/coroutines/EventLoopImplBase;JLkotlinx/coroutines/CancellableContinuation;)V
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedResumeTask;->run()V
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTask;-><init>(J)V
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTask;->scheduleTask(JLkotlinx/coroutines/EventLoopImplBase$DelayedTaskQueue;Lkotlinx/coroutines/EventLoopImplBase;)I
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTask;->setHeap(Lkotlinx/coroutines/internal/ThreadSafeHeap;)V
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTask;->setIndex(I)V
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTask;->timeToExecute(J)Z
+HSPLkotlinx/coroutines/EventLoopImplBase$DelayedTaskQueue;-><init>(J)V
+HSPLkotlinx/coroutines/EventLoopImplBase;-><init>()V
+HSPLkotlinx/coroutines/EventLoopImplBase;->access$isCompleted$p(Lkotlinx/coroutines/EventLoopImplBase;)Z
+HSPLkotlinx/coroutines/EventLoopImplBase;->dequeue()Ljava/lang/Runnable;
+HSPLkotlinx/coroutines/EventLoopImplBase;->enqueueImpl(Ljava/lang/Runnable;)Z
+HSPLkotlinx/coroutines/EventLoopImplBase;->getNextTime()J
+HSPLkotlinx/coroutines/EventLoopImplBase;->isCompleted()Z
+HSPLkotlinx/coroutines/EventLoopImplBase;->processNextEvent()J
+HSPLkotlinx/coroutines/EventLoopImplBase;->schedule(JLkotlinx/coroutines/EventLoopImplBase$DelayedTask;)V
+HSPLkotlinx/coroutines/EventLoopImplBase;->scheduleImpl(JLkotlinx/coroutines/EventLoopImplBase$DelayedTask;)I
+HSPLkotlinx/coroutines/EventLoopImplBase;->scheduleResumeAfterDelay(JLkotlinx/coroutines/CancellableContinuation;)V
+HSPLkotlinx/coroutines/EventLoopImplBase;->shouldUnpark(Lkotlinx/coroutines/EventLoopImplBase$DelayedTask;)Z
+HSPLkotlinx/coroutines/EventLoopImplPlatform;-><init>()V
+HSPLkotlinx/coroutines/EventLoopImplPlatform;->unpark()V
+HSPLkotlinx/coroutines/EventLoopKt;->createEventLoop()Lkotlinx/coroutines/EventLoop;
+HSPLkotlinx/coroutines/EventLoop_commonKt;->access$getCLOSED_EMPTY$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/EventLoop_commonKt;->access$getDISPOSED_TASK$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/EventLoop_commonKt;->delayToNanos(J)J
+HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key$1;-><init>()V
+HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key;-><init>()V
+HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher$Key;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/ExecutorCoroutineDispatcher;-><init>()V
+HSPLkotlinx/coroutines/GlobalScope;-><init>()V
+HSPLkotlinx/coroutines/GlobalScope;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/InvokeOnCancel;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/InvokeOnCancel;->invoke(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/InvokeOnCompletion;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/Job$DefaultImpls;->cancel$default(Lkotlinx/coroutines/Job;Ljava/util/concurrent/CancellationException;ILjava/lang/Object;)V
+HSPLkotlinx/coroutines/Job$DefaultImpls;->fold(Lkotlinx/coroutines/Job;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/Job$DefaultImpls;->get(Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+HSPLkotlinx/coroutines/Job$DefaultImpls;->invokeOnCompletion$default(Lkotlinx/coroutines/Job;ZZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/DisposableHandle;
+HSPLkotlinx/coroutines/Job$DefaultImpls;->minusKey(Lkotlinx/coroutines/Job;Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/Job$Key;-><init>()V
+HSPLkotlinx/coroutines/JobCancellationException;-><init>(Ljava/lang/String;Ljava/lang/Throwable;Lkotlinx/coroutines/Job;)V
+HSPLkotlinx/coroutines/JobCancellationException;->equals(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/JobCancellationException;->fillInStackTrace()Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/JobCancellingNode;-><init>()V
+HSPLkotlinx/coroutines/JobImpl;-><init>(Lkotlinx/coroutines/Job;)V
+HSPLkotlinx/coroutines/JobImpl;->getHandlesException$kotlinx_coroutines_core()Z
+HSPLkotlinx/coroutines/JobImpl;->getOnCancelComplete$kotlinx_coroutines_core()Z
+HSPLkotlinx/coroutines/JobImpl;->handlesException()Z
+HSPLkotlinx/coroutines/JobKt;->Job$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
+HSPLkotlinx/coroutines/JobKt;->Job(Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
+HSPLkotlinx/coroutines/JobKt;->ensureActive(Lkotlinx/coroutines/Job;)V
+HSPLkotlinx/coroutines/JobKt;->getJob(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/JobKt;->isActive(Lkotlin/coroutines/CoroutineContext;)Z
+HSPLkotlinx/coroutines/JobKt__JobKt;->Job$default(Lkotlinx/coroutines/Job;ILjava/lang/Object;)Lkotlinx/coroutines/CompletableJob;
+HSPLkotlinx/coroutines/JobKt__JobKt;->Job(Lkotlinx/coroutines/Job;)Lkotlinx/coroutines/CompletableJob;
+HSPLkotlinx/coroutines/JobKt__JobKt;->ensureActive(Lkotlinx/coroutines/Job;)V
+HSPLkotlinx/coroutines/JobKt__JobKt;->getJob(Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Job;
+HSPLkotlinx/coroutines/JobKt__JobKt;->isActive(Lkotlin/coroutines/CoroutineContext;)Z
+HSPLkotlinx/coroutines/JobNode;-><init>()V
+HSPLkotlinx/coroutines/JobNode;->dispose()V
+HSPLkotlinx/coroutines/JobNode;->getJob()Lkotlinx/coroutines/JobSupport;
+HSPLkotlinx/coroutines/JobNode;->getList()Lkotlinx/coroutines/NodeList;
+HSPLkotlinx/coroutines/JobNode;->isActive()Z
+HSPLkotlinx/coroutines/JobNode;->setJob(Lkotlinx/coroutines/JobSupport;)V
+HSPLkotlinx/coroutines/JobSupport$Finishing;-><init>(Lkotlinx/coroutines/NodeList;ZLjava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport$Finishing;->addExceptionLocked(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport$Finishing;->allocateList()Ljava/util/ArrayList;
+HSPLkotlinx/coroutines/JobSupport$Finishing;->getExceptionsHolder()Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport$Finishing;->getList()Lkotlinx/coroutines/NodeList;
+HSPLkotlinx/coroutines/JobSupport$Finishing;->getRootCause()Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/JobSupport$Finishing;->isActive()Z
+HSPLkotlinx/coroutines/JobSupport$Finishing;->isCancelling()Z
+HSPLkotlinx/coroutines/JobSupport$Finishing;->isCompleting()Z
+HSPLkotlinx/coroutines/JobSupport$Finishing;->sealLocked(Ljava/lang/Throwable;)Ljava/util/List;
+HSPLkotlinx/coroutines/JobSupport$Finishing;->setCompleting(Z)V
+HSPLkotlinx/coroutines/JobSupport$Finishing;->setExceptionsHolder(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/JobSupport$Finishing;->setRootCause(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/JobSupport;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport$addLastAtomic$$inlined$addLastIf$1;->prepare(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;-><init>(Z)V
+HSPLkotlinx/coroutines/JobSupport;->access$cancellationExceptionMessage(Lkotlinx/coroutines/JobSupport;)Ljava/lang/String;
+HSPLkotlinx/coroutines/JobSupport;->addLastAtomic(Ljava/lang/Object;Lkotlinx/coroutines/NodeList;Lkotlinx/coroutines/JobNode;)Z
+HSPLkotlinx/coroutines/JobSupport;->addSuppressedExceptions(Ljava/lang/Throwable;Ljava/util/List;)V
+HSPLkotlinx/coroutines/JobSupport;->afterCompletion(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/JobSupport;->attachChild(Lkotlinx/coroutines/ChildJob;)Lkotlinx/coroutines/ChildHandle;
+HSPLkotlinx/coroutines/JobSupport;->cancel(Ljava/util/concurrent/CancellationException;)V
+HSPLkotlinx/coroutines/JobSupport;->cancelImpl$kotlinx_coroutines_core(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/JobSupport;->cancelInternal(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport;->cancelMakeCompleting(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->cancelParent(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/JobSupport;->cancellationExceptionMessage()Ljava/lang/String;
+HSPLkotlinx/coroutines/JobSupport;->childCancelled(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/JobSupport;->completeStateFinalization(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/JobSupport;->createCauseException(Ljava/lang/Object;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/JobSupport;->finalizeFinishingState(Lkotlinx/coroutines/JobSupport$Finishing;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->firstChild(Lkotlinx/coroutines/Incomplete;)Lkotlinx/coroutines/ChildHandleNode;
+HSPLkotlinx/coroutines/JobSupport;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+HSPLkotlinx/coroutines/JobSupport;->getCancellationException()Ljava/util/concurrent/CancellationException;
+HSPLkotlinx/coroutines/JobSupport;->getChildJobCancellationCause()Ljava/util/concurrent/CancellationException;
+HSPLkotlinx/coroutines/JobSupport;->getFinalRootCause(Lkotlinx/coroutines/JobSupport$Finishing;Ljava/util/List;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/JobSupport;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
+HSPLkotlinx/coroutines/JobSupport;->getOnCancelComplete$kotlinx_coroutines_core()Z
+HSPLkotlinx/coroutines/JobSupport;->getOrPromoteCancellingList(Lkotlinx/coroutines/Incomplete;)Lkotlinx/coroutines/NodeList;
+HSPLkotlinx/coroutines/JobSupport;->getParentHandle$kotlinx_coroutines_core()Lkotlinx/coroutines/ChildHandle;
+HSPLkotlinx/coroutines/JobSupport;->getState$kotlinx_coroutines_core()Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->initParentJobInternal$kotlinx_coroutines_core(Lkotlinx/coroutines/Job;)V
+HSPLkotlinx/coroutines/JobSupport;->invokeOnCompletion(Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle;
+HSPLkotlinx/coroutines/JobSupport;->invokeOnCompletion(ZZLkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/DisposableHandle;
+HSPLkotlinx/coroutines/JobSupport;->isActive()Z
+HSPLkotlinx/coroutines/JobSupport;->isCompleted()Z
+HSPLkotlinx/coroutines/JobSupport;->isScopedCoroutine()Z
+HSPLkotlinx/coroutines/JobSupport;->makeCancelling(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->makeCompletingOnce$kotlinx_coroutines_core(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->makeNode(Lkotlin/jvm/functions/Function1;Z)Lkotlinx/coroutines/JobNode;
+HSPLkotlinx/coroutines/JobSupport;->minusKey(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/JobSupport;->nextChild(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Lkotlinx/coroutines/ChildHandleNode;
+HSPLkotlinx/coroutines/JobSupport;->notifyCancelling(Lkotlinx/coroutines/NodeList;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport;->notifyCompletion(Lkotlinx/coroutines/NodeList;Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport;->onCancelling(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/JobSupport;->onCompletionInternal(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/JobSupport;->parentCancelled(Lkotlinx/coroutines/ParentJob;)V
+HSPLkotlinx/coroutines/JobSupport;->promoteSingleToNodeList(Lkotlinx/coroutines/JobNode;)V
+HSPLkotlinx/coroutines/JobSupport;->removeNode$kotlinx_coroutines_core(Lkotlinx/coroutines/JobNode;)V
+HSPLkotlinx/coroutines/JobSupport;->setParentHandle$kotlinx_coroutines_core(Lkotlinx/coroutines/ChildHandle;)V
+HSPLkotlinx/coroutines/JobSupport;->start()Z
+HSPLkotlinx/coroutines/JobSupport;->startInternal(Ljava/lang/Object;)I
+HSPLkotlinx/coroutines/JobSupport;->toCancellationException(Ljava/lang/Throwable;Ljava/lang/String;)Ljava/util/concurrent/CancellationException;
+HSPLkotlinx/coroutines/JobSupport;->tryFinalizeSimpleState(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/JobSupport;->tryMakeCancelling(Lkotlinx/coroutines/Incomplete;Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/JobSupport;->tryMakeCompleting(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupport;->tryMakeCompletingSlowPath(Lkotlinx/coroutines/Incomplete;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupportKt;->access$getCOMPLETING_ALREADY$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/JobSupportKt;->access$getCOMPLETING_RETRY$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/JobSupportKt;->access$getEMPTY_ACTIVE$p()Lkotlinx/coroutines/Empty;
+HSPLkotlinx/coroutines/JobSupportKt;->access$getSEALED$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/JobSupportKt;->access$getTOO_LATE_TO_CANCEL$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/JobSupportKt;->boxIncomplete(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/JobSupportKt;->unboxState(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/MainCoroutineDispatcher;-><init>()V
+HSPLkotlinx/coroutines/NodeList;-><init>()V
+HSPLkotlinx/coroutines/NodeList;->getList()Lkotlinx/coroutines/NodeList;
+HSPLkotlinx/coroutines/NodeList;->isActive()Z
+HSPLkotlinx/coroutines/NonDisposableHandle;-><init>()V
+HSPLkotlinx/coroutines/NonDisposableHandle;->dispose()V
+HSPLkotlinx/coroutines/RemoveOnCancel;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/StandaloneCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Z)V
+HSPLkotlinx/coroutines/ThreadLocalEventLoop;-><init>()V
+HSPLkotlinx/coroutines/ThreadLocalEventLoop;->getEventLoop$kotlinx_coroutines_core()Lkotlinx/coroutines/EventLoop;
+HSPLkotlinx/coroutines/ThreadLocalEventLoop;->setEventLoop$kotlinx_coroutines_core(Lkotlinx/coroutines/EventLoop;)V
+HSPLkotlinx/coroutines/TimeSourceKt;->getTimeSource()Lkotlinx/coroutines/TimeSource;
+HSPLkotlinx/coroutines/Unconfined;-><init>()V
+HSPLkotlinx/coroutines/UndispatchedCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/UndispatchedMarker;-><init>()V
+HSPLkotlinx/coroutines/UndispatchedMarker;->fold(Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/UndispatchedMarker;->get(Lkotlin/coroutines/CoroutineContext$Key;)Lkotlin/coroutines/CoroutineContext$Element;
+HSPLkotlinx/coroutines/UndispatchedMarker;->getKey()Lkotlin/coroutines/CoroutineContext$Key;
+HSPLkotlinx/coroutines/YieldKt;->checkCompletion(Lkotlin/coroutines/CoroutineContext;)V
+HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;)V
+HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/android/HandlerContext;-><init>(Landroid/os/Handler;Ljava/lang/String;Z)V
+HSPLkotlinx/coroutines/android/HandlerContext;->getImmediate()Lkotlinx/coroutines/android/HandlerContext;
+HSPLkotlinx/coroutines/android/HandlerContext;->getImmediate()Lkotlinx/coroutines/android/HandlerDispatcher;
+HSPLkotlinx/coroutines/android/HandlerContext;->isDispatchNeeded(Lkotlin/coroutines/CoroutineContext;)Z
+HSPLkotlinx/coroutines/android/HandlerDispatcher;-><init>()V
+HSPLkotlinx/coroutines/android/HandlerDispatcher;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/android/HandlerDispatcherKt;->asHandler(Landroid/os/Looper;Z)Landroid/os/Handler;
+HSPLkotlinx/coroutines/android/HandlerDispatcherKt;->from(Landroid/os/Handler;Ljava/lang/String;)Lkotlinx/coroutines/android/HandlerDispatcher;
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;-><init>(Lkotlinx/coroutines/channels/AbstractChannel;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNext(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNextResult(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->hasNextSuspend(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->next()Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel$Itr;->setResult(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;-><init>(Lkotlinx/coroutines/CancellableContinuation;I)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->completeResumeReceive(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->resumeValue(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveElement;->tryResumeReceive(Ljava/lang/Object;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;-><init>(Lkotlinx/coroutines/channels/AbstractChannel$Itr;Lkotlinx/coroutines/CancellableContinuation;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->completeResumeReceive(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->resumeOnCancellationFun(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
+HSPLkotlinx/coroutines/channels/AbstractChannel$ReceiveHasNext;->tryResumeReceive(Ljava/lang/Object;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/channels/AbstractChannel$RemoveReceiveOnCancel;-><init>(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/channels/Receive;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$RemoveReceiveOnCancel;->invoke(Ljava/lang/Throwable;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/channels/AbstractChannel;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel$enqueueReceiveInternal$$inlined$addLastIfPrevAndIf$1;->prepare(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel;->access$enqueueReceive(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/channels/Receive;)Z
+HSPLkotlinx/coroutines/channels/AbstractChannel;->access$removeReceiveOnCancel(Lkotlinx/coroutines/channels/AbstractChannel;Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/channels/Receive;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel;->enqueueReceive(Lkotlinx/coroutines/channels/Receive;)Z
+HSPLkotlinx/coroutines/channels/AbstractChannel;->enqueueReceiveInternal(Lkotlinx/coroutines/channels/Receive;)Z
+HSPLkotlinx/coroutines/channels/AbstractChannel;->iterator()Lkotlinx/coroutines/channels/ChannelIterator;
+HSPLkotlinx/coroutines/channels/AbstractChannel;->onReceiveDequeued()V
+HSPLkotlinx/coroutines/channels/AbstractChannel;->onReceiveEnqueued()V
+HSPLkotlinx/coroutines/channels/AbstractChannel;->pollInternal()Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel;->receive(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel;->receiveSuspend(ILkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractChannel;->removeReceiveOnCancel(Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/channels/Receive;)V
+HSPLkotlinx/coroutines/channels/AbstractChannel;->takeFirstReceiveOrPeekClosed()Lkotlinx/coroutines/channels/ReceiveOrClosed;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;-><init>(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->completeResumeSend()V
+HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->getPollResult()Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel$SendBuffered;->tryResumeSend(Lkotlinx/coroutines/internal/LockFreeLinkedListNode$PrepareOp;)Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->getClosedForSend()Lkotlinx/coroutines/channels/Closed;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->getQueue()Lkotlinx/coroutines/internal/LockFreeLinkedListHead;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->offer(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->sendBuffered(Ljava/lang/Object;)Lkotlinx/coroutines/channels/ReceiveOrClosed;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->takeFirstReceiveOrPeekClosed()Lkotlinx/coroutines/channels/ReceiveOrClosed;
+HSPLkotlinx/coroutines/channels/AbstractSendChannel;->takeFirstSendOrPeekClosed()Lkotlinx/coroutines/channels/Send;
+HSPLkotlinx/coroutines/channels/BufferOverflow;-><init>(Ljava/lang/String;I)V
+HSPLkotlinx/coroutines/channels/ChannelKt;->Channel$default(ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlinx/coroutines/channels/Channel;
+HSPLkotlinx/coroutines/channels/ChannelKt;->Channel(ILkotlinx/coroutines/channels/BufferOverflow;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/channels/Channel;
+HSPLkotlinx/coroutines/channels/ConflatedChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->enqueueReceiveInternal(Lkotlinx/coroutines/channels/Receive;)Z
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->isBufferAlwaysEmpty()Z
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->isBufferEmpty()Z
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->pollInternal()Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/ConflatedChannel;->updateValueLocked(Ljava/lang/Object;)Lkotlinx/coroutines/internal/UndeliveredElementException;
+HSPLkotlinx/coroutines/channels/LinkedListChannel;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/channels/LinkedListChannel;->isBufferAlwaysEmpty()Z
+HSPLkotlinx/coroutines/channels/LinkedListChannel;->offerInternal(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/Receive;-><init>()V
+HSPLkotlinx/coroutines/channels/Receive;->getOfferResult()Ljava/lang/Object;
+HSPLkotlinx/coroutines/channels/Receive;->getOfferResult()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/channels/Receive;->resumeOnCancellationFun(Ljava/lang/Object;)Lkotlin/jvm/functions/Function1;
+HSPLkotlinx/coroutines/channels/Send;-><init>()V
+HSPLkotlinx/coroutines/flow/AbstractFlow;-><init>()V
+HSPLkotlinx/coroutines/flow/FlowKt;->first(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/FlowKt;->flow(Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
+HSPLkotlinx/coroutines/flow/FlowKt;->take(Lkotlinx/coroutines/flow/Flow;I)Lkotlinx/coroutines/flow/Flow;
+HSPLkotlinx/coroutines/flow/FlowKt__BuildersKt;->flow(Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow;
+HSPLkotlinx/coroutines/flow/FlowKt__LimitKt$take$$inlined$unsafeFlow$1;-><init>(Lkotlinx/coroutines/flow/Flow;I)V
+HSPLkotlinx/coroutines/flow/FlowKt__LimitKt;->take(Lkotlinx/coroutines/flow/Flow;I)Lkotlinx/coroutines/flow/Flow;
+HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2$1;-><init>(Lkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;-><init>(Lkotlin/jvm/functions/Function2;Lkotlin/jvm/internal/Ref$ObjectRef;)V
+HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$$inlined$collectWhile$2;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt$first$3;-><init>(Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/flow/FlowKt__ReduceKt;->first(Lkotlinx/coroutines/flow/Flow;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SafeFlow;-><init>(Lkotlin/jvm/functions/Function2;)V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl$collect$1;-><init>(Lkotlinx/coroutines/flow/SharedFlowImpl;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl$collect$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;-><init>(IILkotlinx/coroutines/channels/BufferOverflow;)V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->access$tryPeekLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;Lkotlinx/coroutines/flow/SharedFlowSlot;)J
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->awaitValue(Lkotlinx/coroutines/flow/SharedFlowSlot;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->cleanupTailLocked()V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlot()Lkotlinx/coroutines/flow/SharedFlowSlot;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/SharedFlowSlot;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->emit(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->enqueueLocked(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->findSlotsToResumeLocked([Lkotlin/coroutines/Continuation;)[Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getBufferEndIndex()J
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getHead()J
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getPeekedValueLockedAt(J)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getQueueEndIndex()J
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getReplaySize()I
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->getTotalSize()I
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->growBuffer([Ljava/lang/Object;II)[Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmit(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmitLocked(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryEmitNoCollectorsLocked(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryPeekLocked(Lkotlinx/coroutines/flow/SharedFlowSlot;)J
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->tryTakeValue(Lkotlinx/coroutines/flow/SharedFlowSlot;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateBufferLocked(JJJJ)V
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateCollectorIndexLocked$kotlinx_coroutines_core(J)[Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/flow/SharedFlowImpl;->updateNewCollectorIndexLocked$kotlinx_coroutines_core()J
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->MutableSharedFlow$default(IILkotlinx/coroutines/channels/BufferOverflow;ILjava/lang/Object;)Lkotlinx/coroutines/flow/MutableSharedFlow;
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->MutableSharedFlow(IILkotlinx/coroutines/channels/BufferOverflow;)Lkotlinx/coroutines/flow/MutableSharedFlow;
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->access$getBufferAt([Ljava/lang/Object;J)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->access$setBufferAt([Ljava/lang/Object;JLjava/lang/Object;)V
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->getBufferAt([Ljava/lang/Object;J)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/SharedFlowKt;->setBufferAt([Ljava/lang/Object;JLjava/lang/Object;)V
+HSPLkotlinx/coroutines/flow/SharedFlowSlot;-><init>()V
+HSPLkotlinx/coroutines/flow/SharedFlowSlot;->allocateLocked(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/SharedFlowSlot;->allocateLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;)Z
+HSPLkotlinx/coroutines/flow/SharedFlowSlot;->freeLocked(Ljava/lang/Object;)[Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/flow/SharedFlowSlot;->freeLocked(Lkotlinx/coroutines/flow/SharedFlowImpl;)[Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/flow/StateFlowImpl$collect$1;-><init>(Lkotlinx/coroutines/flow/StateFlowImpl;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/flow/StateFlowImpl$collect$1;->invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;-><init>(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->collect(Lkotlinx/coroutines/flow/FlowCollector;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->compareAndSet(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlot()Lkotlinx/coroutines/flow/StateFlowSlot;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/StateFlowSlot;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->createSlotArray(I)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->getValue()Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->setValue(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/flow/StateFlowImpl;->updateState(Ljava/lang/Object;Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/StateFlowKt;->MutableStateFlow(Ljava/lang/Object;)Lkotlinx/coroutines/flow/MutableStateFlow;
+HSPLkotlinx/coroutines/flow/StateFlowKt;->access$getNONE$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/flow/StateFlowKt;->access$getPENDING$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/flow/StateFlowSlot;-><init>()V
+HSPLkotlinx/coroutines/flow/StateFlowSlot;->allocateLocked(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/flow/StateFlowSlot;->allocateLocked(Lkotlinx/coroutines/flow/StateFlowImpl;)Z
+HSPLkotlinx/coroutines/flow/StateFlowSlot;->awaitPending(Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/flow/StateFlowSlot;->makePending()V
+HSPLkotlinx/coroutines/flow/StateFlowSlot;->takePending()Z
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;-><init>()V
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->access$getNCollectors$p(Lkotlinx/coroutines/flow/internal/AbstractSharedFlow;)I
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->access$getSlots$p(Lkotlinx/coroutines/flow/internal/AbstractSharedFlow;)[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->allocateSlot()Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->freeSlot(Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;)V
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->getNCollectors()I
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlow;->getSlots()[Lkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;
+HSPLkotlinx/coroutines/flow/internal/AbstractSharedFlowSlot;-><init>()V
+HSPLkotlinx/coroutines/internal/AtomicOp;-><init>()V
+HSPLkotlinx/coroutines/internal/AtomicOp;->decide(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/AtomicOp;->perform(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/ContextScope;-><init>(Lkotlin/coroutines/CoroutineContext;)V
+HSPLkotlinx/coroutines/internal/ContextScope;->getCoroutineContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;-><init>(Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->checkPostponedCancellation(Lkotlinx/coroutines/CancellableContinuation;)Ljava/lang/Throwable;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->claimReusableCancellableContinuation()Lkotlinx/coroutines/CancellableContinuationImpl;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getContext()Lkotlin/coroutines/CoroutineContext;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getDelegate$kotlinx_coroutines_core()Lkotlin/coroutines/Continuation;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->getReusableCancellableContinuation()Lkotlinx/coroutines/CancellableContinuationImpl;
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->isReusable(Lkotlinx/coroutines/CancellableContinuationImpl;)Z
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->postponeCancellation(Ljava/lang/Throwable;)Z
+HSPLkotlinx/coroutines/internal/DispatchedContinuation;->takeState$kotlinx_coroutines_core()Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/DispatchedContinuationKt;->access$getUNDEFINED$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/internal/DispatchedContinuationKt;->resumeCancellableWith(Lkotlin/coroutines/Continuation;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListHead;-><init>()V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListHead;->isRemoved()Z
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListKt;->unwrap(Ljava/lang/Object;)Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;->complete(Ljava/lang/Object;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;->complete(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;-><init>()V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->access$finishAdd(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->addNext(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Z
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->addOneIfEmpty(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Z
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->correctPrev(Lkotlinx/coroutines/internal/OpDescriptor;)Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->finishAdd(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getNext()Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getNextNode()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->getPrevNode()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->isRemoved()Z
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->remove()Z
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removeFirstOrNull()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removeOrNext()Lkotlinx/coroutines/internal/LockFreeLinkedListNode;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->removed()Lkotlinx/coroutines/internal/Removed;
+HSPLkotlinx/coroutines/internal/LockFreeLinkedListNode;->tryCondAddNext(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode$CondAddOp;)I
+HSPLkotlinx/coroutines/internal/LockFreeTaskQueue;-><init>(Z)V
+HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore$Companion;-><init>()V
+HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/internal/LockFreeTaskQueueCore;-><init>(IZ)V
+HSPLkotlinx/coroutines/internal/OpDescriptor;-><init>()V
+HSPLkotlinx/coroutines/internal/Removed;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)V
+HSPLkotlinx/coroutines/internal/ScopeCoroutine;-><init>(Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/internal/ScopeCoroutine;->afterResume(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/internal/ScopeCoroutine;->isScopedCoroutine()Z
+HSPLkotlinx/coroutines/internal/Symbol;-><init>(Ljava/lang/String;)V
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->getAVAILABLE_PROCESSORS()I
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp$default(Ljava/lang/String;IIIILjava/lang/Object;)I
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp$default(Ljava/lang/String;JJJILjava/lang/Object;)J
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;)Ljava/lang/String;
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;III)I
+HSPLkotlinx/coroutines/internal/SystemPropsKt;->systemProp(Ljava/lang/String;JJJ)J
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;->getAVAILABLE_PROCESSORS()I
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemPropsKt;->systemProp(Ljava/lang/String;)Ljava/lang/String;
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp$default(Ljava/lang/String;IIIILjava/lang/Object;)I
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp$default(Ljava/lang/String;JJJILjava/lang/Object;)J
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp(Ljava/lang/String;III)I
+HSPLkotlinx/coroutines/internal/SystemPropsKt__SystemProps_commonKt;->systemProp(Ljava/lang/String;JJJ)J
+HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;-><init>()V
+HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;->invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/ThreadContextKt$countAll$1;->invoke(Ljava/lang/Object;Lkotlin/coroutines/CoroutineContext$Element;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/ThreadContextKt$findOne$1;-><init>()V
+HSPLkotlinx/coroutines/internal/ThreadContextKt$updateState$1;-><init>()V
+HSPLkotlinx/coroutines/internal/ThreadContextKt;->restoreThreadContext(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/internal/ThreadContextKt;->threadContextElements(Lkotlin/coroutines/CoroutineContext;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/ThreadContextKt;->updateThreadContext(Lkotlin/coroutines/CoroutineContext;Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;-><init>()V
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->addImpl(Lkotlinx/coroutines/internal/ThreadSafeHeapNode;)V
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->firstImpl()Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->getSize()I
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->isEmpty()Z
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->peek()Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->realloc()[Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->removeAtImpl(I)Lkotlinx/coroutines/internal/ThreadSafeHeapNode;
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->setSize(I)V
+HSPLkotlinx/coroutines/internal/ThreadSafeHeap;->siftUpFrom(I)V
+HSPLkotlinx/coroutines/intrinsics/CancellableKt;->startCoroutineCancellable$default(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
+HSPLkotlinx/coroutines/intrinsics/CancellableKt;->startCoroutineCancellable(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;Lkotlin/jvm/functions/Function1;)V
+HSPLkotlinx/coroutines/intrinsics/UndispatchedKt;->startCoroutineUndispatched(Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)V
+HSPLkotlinx/coroutines/intrinsics/UndispatchedKt;->startUndispatchedOrReturn(Lkotlinx/coroutines/internal/ScopeCoroutine;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/scheduling/CoroutineScheduler$Companion;-><init>()V
+HSPLkotlinx/coroutines/scheduling/CoroutineScheduler$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/scheduling/CoroutineScheduler;-><init>(IIJLjava/lang/String;)V
+HSPLkotlinx/coroutines/scheduling/DefaultScheduler;-><init>()V
+HSPLkotlinx/coroutines/scheduling/DefaultScheduler;->getIO()Lkotlinx/coroutines/CoroutineDispatcher;
+HSPLkotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher;-><init>(IIJLjava/lang/String;)V
+HSPLkotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher;-><init>(IILjava/lang/String;)V
+HSPLkotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher;-><init>(IILjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher;->createScheduler()Lkotlinx/coroutines/scheduling/CoroutineScheduler;
+HSPLkotlinx/coroutines/scheduling/GlobalQueue;-><init>()V
+HSPLkotlinx/coroutines/scheduling/LimitingDispatcher;-><init>(Lkotlinx/coroutines/scheduling/ExperimentalCoroutineDispatcher;ILjava/lang/String;I)V
+HSPLkotlinx/coroutines/scheduling/NanoTimeSource;-><init>()V
+HSPLkotlinx/coroutines/scheduling/NonBlockingContext;-><init>()V
+HSPLkotlinx/coroutines/scheduling/NonBlockingContext;->afterTask()V
+HSPLkotlinx/coroutines/scheduling/SchedulerTimeSource;-><init>()V
+HSPLkotlinx/coroutines/scheduling/Task;-><init>()V
+HSPLkotlinx/coroutines/scheduling/Task;-><init>(JLkotlinx/coroutines/scheduling/TaskContext;)V
+HSPLkotlinx/coroutines/sync/Empty;-><init>(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/Mutex$DefaultImpls;->lock$default(Lkotlinx/coroutines/sync/Mutex;Ljava/lang/Object;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/Mutex$DefaultImpls;->tryLock$default(Lkotlinx/coroutines/sync/Mutex;Ljava/lang/Object;ILjava/lang/Object;)Z
+HSPLkotlinx/coroutines/sync/Mutex$DefaultImpls;->unlock$default(Lkotlinx/coroutines/sync/Mutex;Ljava/lang/Object;ILjava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$LockCont$tryResumeLockWaiter$1;-><init>(Lkotlinx/coroutines/sync/MutexImpl$LockCont;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;-><init>(Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;Lkotlinx/coroutines/CancellableContinuation;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;->completeResumeLockWaiter(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$LockCont;->tryResumeLockWaiter()Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/MutexImpl$LockWaiter;-><init>(Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$LockedQueue;-><init>(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$lockSuspend$$inlined$suspendCancellableCoroutineReusable$lambda$2;-><init>(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Lkotlinx/coroutines/internal/LockFreeLinkedListNode;Ljava/lang/Object;Lkotlinx/coroutines/CancellableContinuation;Lkotlinx/coroutines/sync/MutexImpl$LockCont;Lkotlinx/coroutines/sync/MutexImpl;Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexImpl$lockSuspend$$inlined$suspendCancellableCoroutineReusable$lambda$2;->prepare(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/MutexImpl$lockSuspend$$inlined$suspendCancellableCoroutineReusable$lambda$2;->prepare(Lkotlinx/coroutines/internal/LockFreeLinkedListNode;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/MutexImpl;-><init>(Z)V
+HSPLkotlinx/coroutines/sync/MutexImpl;->lock(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/MutexImpl;->lockSuspend(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
+HSPLkotlinx/coroutines/sync/MutexImpl;->tryLock(Ljava/lang/Object;)Z
+HSPLkotlinx/coroutines/sync/MutexImpl;->unlock(Ljava/lang/Object;)V
+HSPLkotlinx/coroutines/sync/MutexKt;->Mutex$default(ZILjava/lang/Object;)Lkotlinx/coroutines/sync/Mutex;
+HSPLkotlinx/coroutines/sync/MutexKt;->Mutex(Z)Lkotlinx/coroutines/sync/Mutex;
+HSPLkotlinx/coroutines/sync/MutexKt;->access$getEMPTY_LOCKED$p()Lkotlinx/coroutines/sync/Empty;
+HSPLkotlinx/coroutines/sync/MutexKt;->access$getEMPTY_UNLOCKED$p()Lkotlinx/coroutines/sync/Empty;
+HSPLkotlinx/coroutines/sync/MutexKt;->access$getLOCKED$p()Lkotlinx/coroutines/internal/Symbol;
+HSPLkotlinx/coroutines/sync/MutexKt;->access$getUNLOCKED$p()Lkotlinx/coroutines/internal/Symbol;
\ No newline at end of file
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ReadOnlyComposable.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ReadOnlyComposable.kt
index 2bdb54c..e0d3685 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ReadOnlyComposable.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/ReadOnlyComposable.kt
@@ -23,7 +23,7 @@
* This will result in slightly more efficient code.
*
* A common use case for this are for functions that only need to be composable in order to read
- * [Ambient] values, but don't call any other composables.
+ * [CompositionLocal] values, but don't call any other composables.
*
* Caution: Use of this annotation means that the annotated declaration *MUST* comply with this
* contract, or else the resulting code's behavior will be undefined.
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
index dfee58f..4a47257 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SnapshotState.kt
@@ -831,13 +831,13 @@
val readSet = mutableSetOf<Any>()
val readObserver: (Any) -> Unit = { readSet.add(it) }
- // This channel may not block or lose data on an offer call.
+ // This channel may not block or lose data on a trySend call.
val appliedChanges = Channel<Set<Any>>(Channel.UNLIMITED)
// Register the apply observer before running for the first time
// so that we don't miss updates.
val unregisterApplyObserver = Snapshot.registerApplyObserver { changed, _ ->
- appliedChanges.offer(changed)
+ appliedChanges.trySend(changed)
}
try {
@@ -859,7 +859,7 @@
while (true) {
// Assumption: readSet will typically be smaller than changed
found = found || readSet.intersects(changedObjects)
- changedObjects = appliedChanges.poll() ?: break
+ changedObjects = appliedChanges.tryReceive().getOrNull() ?: break
}
if (found) {
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
index 6d7d1d8..3448a42 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
@@ -113,6 +113,9 @@
if (!isObserving) {
isObserving = true
try {
+ applyMap.map.removeValueIf {
+ it === scope
+ }
Snapshot.observe(readObserver, null, block)
} finally {
isObserving = false
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/RecomposerTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/RecomposerTests.kt
index 0dc4e9e..845e672 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/RecomposerTests.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/RecomposerTests.kt
@@ -277,7 +277,7 @@
val threadLog = Channel<Thread>(Channel.BUFFERED)
lateinit var recomposeScope: RecomposeScope
composition.setContent {
- threadLog.offer(Thread.currentThread())
+ threadLog.trySend(Thread.currentThread())
val scope = currentRecomposeScope
SideEffect {
recomposeScope = scope
@@ -356,7 +356,7 @@
val recompositionThread = Channel<Thread>(1)
composition.setContent {
if (recomposition) {
- recompositionThread.offer(Thread.currentThread())
+ recompositionThread.trySend(Thread.currentThread())
}
}
diff --git a/compose/test-utils/lint-baseline.xml b/compose/test-utils/lint-baseline.xml
deleted file mode 100644
index 453a386..0000000
--- a/compose/test-utils/lint-baseline.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.1.0-alpha01" type="baseline" client="cli" name="Lint" variant="all" version="7.1.0-alpha01">
-
- <issue
- id="BanTargetApiAnnotation"
- message="Uses @TargetApi annotation"
- errorLine1="@TargetApi(Build.VERSION_CODES.Q)"
- errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="345"
- column="1"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 28; however, the containing class androidx.compose.testutils.AndroidComposeTestCaseRunner is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" bitmap = Bitmap.createBitmap(picture)"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="274"
- column="29"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.testutils.RenderNodeCapture is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" private val renderNode = RenderNode("Test")"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="347"
- column="30"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.testutils.RenderNodeCapture is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" renderNode.setPosition(0, 0, width, height)"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="350"
- column="20"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.testutils.RenderNodeCapture is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" return renderNode.beginRecording()"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="351"
- column="27"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.testutils.RenderNodeCapture is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" renderNode.endRecording()"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt"
- line="355"
- column="20"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.testutils.ViewCapture_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" decorView.viewTreeObserver.registerFrameCommitCallback {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt"
- line="68"
- column="40"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 26; however, the containing class androidx.compose.testutils.ViewCapture_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" PixelCopy.request(windowToCapture, boundsInWindow, destBitmap, onCopyFinished, handler)"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt"
- line="104"
- column="15"/>
- </issue>
-
-</issues>
diff --git a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
index 9aad576d..549af41 100644
--- a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
+++ b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
@@ -30,7 +30,7 @@
import androidx.annotation.RequiresApi
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
-import androidx.compose.runtime.MonotonicFrameClock
+import androidx.annotation.DoNotInline
import androidx.compose.runtime.Recomposer
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.platform.ViewRootForTest
@@ -41,7 +41,6 @@
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineDispatcher
-import java.util.concurrent.atomic.AtomicLong
/**
* Factory method to provide implementation of [ComposeBenchmarkScope].
@@ -87,15 +86,6 @@
private var canvas: Canvas? = null
- private class AutoFrameClock(
- private val singleFrameTimeNanos: Long = 16_000_000
- ) : MonotonicFrameClock {
- private val lastFrameTime = AtomicLong(0L)
-
- override suspend fun <R> withFrameNanos(onFrame: (Long) -> R): R =
- onFrame(lastFrameTime.getAndAdd(singleFrameTimeNanos))
- }
-
private val testCoroutineDispatcher = TestCoroutineDispatcher()
private val frameClock = TestMonotonicFrameClock(CoroutineScope(testCoroutineDispatcher))
private val recomposerApplyCoroutineScope = CoroutineScope(
@@ -271,7 +261,7 @@
val imageView = ImageView(activity)
val bitmap: Bitmap
if (Build.VERSION.SDK_INT >= 28) {
- bitmap = Bitmap.createBitmap(picture)
+ bitmap = BitmapHelper.createBitmap(picture)
} else {
val width = picture.width.coerceAtLeast(1)
val height = picture.height.coerceAtLeast(1)
@@ -383,4 +373,12 @@
renderNode.end(canvas!!)
canvas = null
}
+}
+
+@RequiresApi(28)
+private object BitmapHelper {
+ @DoNotInline
+ fun createBitmap(picture: Picture): Bitmap {
+ return Bitmap.createBitmap(picture)
+ }
}
\ No newline at end of file
diff --git a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt
index 5253670..e03df74 100644
--- a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt
+++ b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/ViewCapture.android.kt
@@ -16,17 +16,20 @@
package androidx.compose.testutils
-import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.graphics.Bitmap
+import android.graphics.Rect
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.view.PixelCopy
+import android.view.PixelCopy.OnPixelCopyFinishedListener
import android.view.View
import android.view.ViewTreeObserver
+import android.view.Window
+import androidx.annotation.DoNotInline
import androidx.annotation.RequiresApi
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
@@ -41,13 +44,12 @@
* in the bitmap as this is taken from the component's window surface.
*/
@RequiresApi(Build.VERSION_CODES.O)
-@SuppressLint("UnsafeNewApiCall") // Seems like lint is giving false red flags
fun View.captureToImage(): ImageBitmap {
val locationInWindow = intArrayOf(0, 0)
getLocationInWindow(locationInWindow)
val x = locationInWindow[0]
val y = locationInWindow[1]
- val boundsInWindow = android.graphics.Rect(x, y, x + width, y + height)
+ val boundsInWindow = Rect(x, y, x + width, y + height)
fun Context.getActivity(): Activity? {
return when (this) {
@@ -65,7 +67,7 @@
val decorView = windowToCapture.decorView
handler.post {
if (Build.VERSION.SDK_INT >= 29 && decorView.isHardwareAccelerated) {
- decorView.viewTreeObserver.registerFrameCommitCallback {
+ FrameCommitCallbackHelper.registerFrameCommitCallback(decorView.viewTreeObserver) {
drawLatch.countDown()
}
} else {
@@ -97,11 +99,11 @@
val latch = CountDownLatch(1)
var copyResult = 0
- val onCopyFinished = PixelCopy.OnPixelCopyFinishedListener { result ->
+ val onCopyFinished = OnPixelCopyFinishedListener { result ->
copyResult = result
latch.countDown()
}
- PixelCopy.request(windowToCapture, boundsInWindow, destBitmap, onCopyFinished, handler)
+ PixelCopyHelper.request(windowToCapture, boundsInWindow, destBitmap, onCopyFinished, handler)
if (!latch.await(1, TimeUnit.SECONDS)) {
throw AssertionError("Failed waiting for PixelCopy!")
@@ -110,4 +112,26 @@
throw AssertionError("PixelCopy failed!")
}
return destBitmap.asImageBitmap()
-}
\ No newline at end of file
+}
+
+@RequiresApi(29)
+private object FrameCommitCallbackHelper {
+ @DoNotInline
+ fun registerFrameCommitCallback(viewTreeObserver: ViewTreeObserver, runnable: Runnable) {
+ viewTreeObserver.registerFrameCommitCallback(runnable)
+ }
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private object PixelCopyHelper {
+ @DoNotInline
+ fun request(
+ source: Window,
+ srcRect: Rect?,
+ dest: Bitmap,
+ listener: OnPixelCopyFinishedListener,
+ listenerThread: Handler
+ ) {
+ PixelCopy.request(source, srcRect, dest, listener, listenerThread)
+ }
+}
diff --git a/compose/ui/ui-geometry/src/androidMain/baseline-prof.txt b/compose/ui/ui-geometry/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..f737387
--- /dev/null
+++ b/compose/ui/ui-geometry/src/androidMain/baseline-prof.txt
@@ -0,0 +1,5 @@
+# Baseline profile rules for androidx.compose.ui.geometry
+# =============================================
+# All of geometry is highly used, small, and mathy, so we include everything
+HSPLandroidx/compose/ui/geometry/*->**(**)**
+Landroidx/compose/ui/geometry/*;
\ No newline at end of file
diff --git a/compose/ui/ui-graphics/benchmark/lint-baseline.xml b/compose/ui/ui-graphics/benchmark/lint-baseline.xml
deleted file mode 100644
index 42a176b..0000000
--- a/compose/ui/ui-graphics/benchmark/lint-baseline.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.0.0-alpha15" type="baseline" client="cli" name="Lint" variant="all" version="7.0.0-alpha15">
-
-</issues>
diff --git a/compose/ui/ui-graphics/lint-baseline.xml b/compose/ui/ui-graphics/lint-baseline.xml
deleted file mode 100644
index c2ed54b..0000000
--- a/compose/ui/ui-graphics/lint-baseline.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.1.0-alpha01" type="baseline" client="cli" name="Lint" variant="all" version="7.1.0-alpha01">
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.graphics.AndroidColorFilter_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" BlendModeColorFilter(color.toArgb(), blendMode.toAndroidBlendMode())"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidColorFilter.android.kt"
- line="39"
- column="9"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.graphics.CanvasUtils is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" canvas.enableZ()"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt"
- line="39"
- column="24"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.graphics.CanvasUtils is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" canvas.disableZ()"
- errorLine2=" ~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt"
- line="41"
- column="24"/>
- </issue>
-
-</issues>
diff --git a/compose/ui/ui-graphics/src/androidMain/baseline-prof.txt b/compose/ui/ui-graphics/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..7952c8a
--- /dev/null
+++ b/compose/ui/ui-graphics/src/androidMain/baseline-prof.txt
@@ -0,0 +1,71 @@
+# Baseline profile rules for androidx.compose.ui.graphics
+# =============================================
+HSPLandroidx/compose/ui/graphics/AndroidCanvas**->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidColorFilter_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidImageBitmap;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidImageBitmap_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidMatrixConversions_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidPaint;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidPaint_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidPath;->**(**)**
+HSPLandroidx/compose/ui/graphics/AndroidPath_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/BlendMode**->**(**)**
+HSPLandroidx/compose/ui/graphics/BlockGraphicsLayerModifier**->**(**)**
+HSPLandroidx/compose/ui/graphics/Brush;->**(**)**
+HSPLandroidx/compose/ui/graphics/Canvas$DefaultImpls;->**(**)**
+HSPLandroidx/compose/ui/graphics/CanvasHolder;->**(**)**
+HSPLandroidx/compose/ui/graphics/CanvasKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/ClipOp**->**(**)**
+HSPLandroidx/compose/ui/graphics/Color**->**(**)**
+HSPLandroidx/compose/ui/graphics/ColorFilter**->**(**)**
+HSPLandroidx/compose/ui/graphics/ColorKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/Float16**->**(**)**
+HSPLandroidx/compose/ui/graphics/GraphicsLayerModifierKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/Matrix;->**(**)**
+HSPLandroidx/compose/ui/graphics/ImageBitmapConfig**->**(**)**
+HSPLandroidx/compose/ui/graphics/MatrixKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/Outline**->**(**)**
+HSPLandroidx/compose/ui/graphics/PaintingStyle**->**(**)**
+HSPLandroidx/compose/ui/graphics/PathFillType**->**(**)**
+HSPLandroidx/compose/ui/graphics/RectangleShapeKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/RectHelper_androidKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/ReusableGraphicsLayerScope;->**(**)**
+HSPLandroidx/compose/ui/graphics/Shadow;->**(**)**
+HSPLandroidx/compose/ui/graphics/SimpleGraphicsLayerModifier**->**(**)**
+HSPLandroidx/compose/ui/graphics/SolidColor;->**(**)**
+HSPLandroidx/compose/ui/graphics/StrokeCap**->**(**)**
+HSPLandroidx/compose/ui/graphics/StrokeJoin**->**(**)**
+HSPLandroidx/compose/ui/graphics/TransformOrigin**->**(**)**
+HSPLandroidx/compose/ui/graphics/painter/BitmapPainter;->**(**)**
+HSPLandroidx/compose/ui/graphics/painter/Painter**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/DrawCache;->**(**)**
+#
+# All of colorspace
+HSPLandroidx/compose/ui/graphics/colorspace/**->**(**)**
+#
+# All of drawscope
+HSPLandroidx/compose/ui/graphics/drawscope/**->**(**)**
+#
+# Vector stuff
+HSPLandroidx/compose/ui/graphics/vector/DefaultVectorOverride;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/DrawCache;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/GroupComponent;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/ImageVector**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/PathBuilder;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/PathComponent;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/PathNode**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/PathParser**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/Stack;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VNode;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorApplier;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorComponent;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorComposeKt**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorGroup;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorKt;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorPainter**->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/VectorPath;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/compat/AndroidVectorResources;->**(**)**
+HSPLandroidx/compose/ui/graphics/vector/compat/XmlVectorParser_androidKt;->**(**)**
+#
+# Assume ~all classes will get loaded
+Landroidx/compose/ui/graphics/**;
\ No newline at end of file
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidColorFilter.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidColorFilter.android.kt
index 5c53c36..9287c0f 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidColorFilter.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidColorFilter.android.kt
@@ -16,10 +16,11 @@
package androidx.compose.ui.graphics
-import android.annotation.SuppressLint
import android.graphics.BlendModeColorFilter
import android.graphics.PorterDuffColorFilter
import android.os.Build
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
internal actual typealias NativeColorFilter = android.graphics.ColorFilter
@@ -34,9 +35,8 @@
fun android.graphics.ColorFilter.asComposeColorFilter(): ColorFilter = ColorFilter(this)
internal actual fun actualTintColorFilter(color: Color, blendMode: BlendMode): ColorFilter {
- @SuppressLint("UnsafeNewApiCall")
val androidColorFilter = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- BlendModeColorFilter(color.toArgb(), blendMode.toAndroidBlendMode())
+ BlendModeColorFilterHelper.BlendModeColorFilter(color, blendMode)
} else {
PorterDuffColorFilter(color.toArgb(), blendMode.toPorterDuffMode())
}
@@ -47,4 +47,12 @@
ColorFilter(android.graphics.ColorMatrixColorFilter(colorMatrix.values))
internal actual fun actualLightingColorFilter(multiply: Color, add: Color): ColorFilter =
- ColorFilter(android.graphics.LightingColorFilter(multiply.toArgb(), add.toArgb()))
\ No newline at end of file
+ ColorFilter(android.graphics.LightingColorFilter(multiply.toArgb(), add.toArgb()))
+
+@RequiresApi(Build.VERSION_CODES.Q)
+private object BlendModeColorFilterHelper {
+ @DoNotInline
+ fun BlendModeColorFilter(color: Color, blendMode: BlendMode): BlendModeColorFilter {
+ return BlendModeColorFilter(color.toArgb(), blendMode.toAndroidBlendMode())
+ }
+}
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
index 8fafaac..14f77ec 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
@@ -133,9 +133,7 @@
override fun addRect(rect: Rect) {
check(_rectIsValid(rect))
- rectF.set(rect.toAndroidRect())
- // TODO(njawad) figure out what to do with Path Direction,
- // Flutter does not use it, Platform does
+ rectF.set(rect.toAndroidRectF())
internalPath.addRect(rectF, android.graphics.Path.Direction.CCW)
}
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt
index 0b885ea..3f3d9ac 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/CanvasUtils.android.kt
@@ -19,6 +19,8 @@
import android.annotation.SuppressLint
import android.graphics.Canvas
import android.os.Build
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
@@ -35,11 +37,7 @@
@SuppressLint("SoonBlockedPrivateApi")
fun enableZ(canvas: Canvas, enable: Boolean) {
if (Build.VERSION.SDK_INT >= 29) {
- if (enable) {
- canvas.enableZ()
- } else {
- canvas.disableZ()
- }
+ CanvasZHelper.enableZ(canvas, enable)
} else {
if (!orderMethodsFetched) {
try {
@@ -89,3 +87,15 @@
}
}
}
+
+@RequiresApi(29)
+private object CanvasZHelper {
+ @DoNotInline
+ fun enableZ(canvas: Canvas, enable: Boolean) {
+ if (enable) {
+ canvas.enableZ()
+ } else {
+ canvas.disableZ()
+ }
+ }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
index 6580236..6065fd0 100644
--- a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTreeTest.kt
@@ -74,6 +74,7 @@
import androidx.compose.ui.tooling.data.position
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
@@ -747,6 +748,33 @@
assertThat(first.packageHash).isEqualTo(hash)
}
+ @Composable
+ fun InlineParameters(size: Dp, fontSize: TextUnit) {
+ Text("$size $fontSize")
+ }
+
+ @Test
+ fun testInlineParameterTypes() {
+ val slotTableRecord = CompositionDataRecord.create()
+
+ show {
+ Inspectable(slotTableRecord) {
+ InlineParameters(20.5.dp, 30.sp)
+ }
+ }
+ val androidComposeView = findAndroidComposeView()
+ androidComposeView.setTag(R.id.inspection_slot_table_set, slotTableRecord.store)
+ val builder = LayoutInspectorTree()
+ builder.hideSystemNodes = false
+ val inlineParameters = builder.convert(androidComposeView)
+ .flatMap { flatten(it) }
+ .first { it.name == "InlineParameters" }
+ assertThat(inlineParameters.parameters[0].name).isEqualTo("size")
+ assertThat(inlineParameters.parameters[0].value?.javaClass).isEqualTo(Dp::class.java)
+ assertThat(inlineParameters.parameters[1].name).isEqualTo("fontSize")
+ assertThat(inlineParameters.parameters[1].value?.javaClass).isEqualTo(TextUnit::class.java)
+ }
+
@Suppress("SameParameterValue")
private fun validate(
result: List<InspectorNode>,
diff --git a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
index c335f85..91087fb 100644
--- a/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
+++ b/compose/ui/ui-inspection/src/androidTest/java/androidx/compose/ui/inspection/inspector/ParameterFactoryTest.kt
@@ -959,7 +959,7 @@
maxRecursions: Int,
maxInitialIterableSize: Int
) {
- factory.clearCacheFor(ROOT_ID)
+ factory.clearReferenceCache()
val reference = NodeParameterReference(NODE_ID, ParameterKind.Normal, PARAM_INDEX, indices)
val expanded = expand(
name,
diff --git a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
index d9c435d..3a917f6 100644
--- a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
+++ b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/LayoutInspectorTree.kt
@@ -17,6 +17,7 @@
package androidx.compose.ui.inspection.inspector
import android.view.View
+import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.InternalComposeApi
import androidx.compose.runtime.tooling.CompositionData
@@ -75,6 +76,7 @@
"ProvideCommonCompositionLocals",
)
+@OptIn(ExperimentalStdlibApi::class)
@VisibleForTesting
fun packageNameHash(packageName: String) =
packageName.fold(0) { hash, char -> hash * 31 + char.code }.absoluteValue
@@ -82,6 +84,7 @@
/**
* Generator of a tree for the Layout Inspector.
*/
+@RequiresApi(29)
class LayoutInspectorTree {
@Suppress("MemberVisibilityCanBePrivate")
var hideSystemNodes = true
@@ -202,6 +205,7 @@
@Suppress("unused")
fun resetAccumulativeState() {
subCompositions.resetAccumulativeState()
+ parameterFactory.clearReferenceCache()
// Reset the generated id. Nodes are assigned an id if there isn't a layout node id present.
generatedId = -1L
}
@@ -547,10 +551,13 @@
@OptIn(UiToolingDataApi::class)
private fun castValue(parameter: ParameterInformation): Any? {
val value = parameter.value ?: return null
- if (parameter.inlineClass == null || !value.javaClass.isPrimitive) return value
+ if (parameter.inlineClass == null || !isPrimitive(value.javaClass)) return value
return inlineClassConverter.castParameterValue(parameter.inlineClass, value)
}
+ private fun isPrimitive(cls: Class<*>): Boolean =
+ cls.kotlin.javaPrimitiveType != null
+
private fun unwantedGroup(node: MutableInspectorNode): Boolean =
(node.packageHash in systemPackages && hideSystemNodes) ||
node.name.isEmpty() ||
diff --git a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt
index 20af4db..9d4b77f 100644
--- a/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt
+++ b/compose/ui/ui-inspection/src/main/java/androidx/compose/ui/inspection/inspector/ParameterFactory.kt
@@ -18,6 +18,7 @@
import android.util.Log
import android.view.View
+import androidx.annotation.RequiresApi
import androidx.compose.runtime.internal.ComposableLambda
import androidx.compose.ui.AbsoluteAlignment
import androidx.compose.ui.Modifier
@@ -64,6 +65,7 @@
*
* Each parameter value is converted to a user readable value.
*/
+@RequiresApi(29)
internal class ParameterFactory(private val inlineClassConverter: InlineClassConverter) {
/**
* A map from known values to a user readable string representation.
@@ -190,9 +192,9 @@
}
}
- fun clearCacheFor(rootId: Long) {
+ fun clearReferenceCache() {
val creator = creatorCache ?: return
- creator.clearCacheFor(rootId)
+ creator.clearReferenceCache()
}
private fun loadConstantsFrom(javaClass: Class<*>) {
@@ -382,8 +384,8 @@
return parameter
}
- fun clearCacheFor(rootId: Long) {
- rootValueIndexCache.remove(rootId)
+ fun clearReferenceCache() {
+ rootValueIndexCache.clear()
}
private fun setup(
diff --git a/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle b/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
index ed7d966..0da3410 100644
--- a/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
+++ b/compose/ui/ui-test-manifest/integration-tests/testapp/build.gradle
@@ -26,6 +26,7 @@
debugImplementation(project(":compose:ui:ui-test-manifest"))
+ implementation(project(":compose:ui:ui"))
androidTestImplementation(project(":compose:ui:ui-test-junit4"))
androidTestImplementation(libs.testRunner)
androidTestImplementation(libs.testCore)
diff --git a/compose/ui/ui-test/lint-baseline.xml b/compose/ui/ui-test/lint-baseline.xml
deleted file mode 100644
index 6021987..0000000
--- a/compose/ui/ui-test/lint-baseline.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.1.0-alpha01" type="baseline" client="cli" name="Lint" variant="all" version="7.1.0-alpha01">
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.test.android.WindowCapture_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" decorView.viewTreeObserver.registerFrameCommitCallback {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt"
- line="64"
- column="40"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 26; however, the containing class androidx.compose.ui.test.android.WindowCapture_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" PixelCopy.request(windowToCapture, captureRectInWindow, destBitmap, onCopyFinished, handler)"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt"
- line="100"
- column="15"/>
- </issue>
-
-</issues>
diff --git a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt
index 85a3ab5..1946548 100644
--- a/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt
+++ b/compose/ui/ui-test/src/androidMain/kotlin/androidx/compose/ui/test/android/WindowCapture.android.kt
@@ -28,6 +28,7 @@
import android.view.View
import android.view.ViewTreeObserver
import android.view.Window
+import androidx.annotation.DoNotInline
import androidx.annotation.RequiresApi
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
@@ -60,8 +61,8 @@
var drawDone = false
val decorView = windowToCapture.decorView
handler.post {
- if (Build.VERSION.SDK_INT >= 29 && decorView.isHardwareAccelerated()) {
- decorView.viewTreeObserver.registerFrameCommitCallback {
+ if (Build.VERSION.SDK_INT >= 29 && decorView.isHardwareAccelerated) {
+ FrameCommitCallbackHelper.registerFrameCommitCallback(decorView.viewTreeObserver) {
drawDone = true
}
} else {
@@ -97,7 +98,13 @@
copyResult = result
latch.countDown()
}
- PixelCopy.request(windowToCapture, captureRectInWindow, destBitmap, onCopyFinished, handler)
+ PixelCopyHelper.request(
+ windowToCapture,
+ captureRectInWindow,
+ destBitmap,
+ onCopyFinished,
+ handler
+ )
if (!latch.await(1, TimeUnit.SECONDS)) {
throw AssertionError("Failed waiting for PixelCopy!")
@@ -124,4 +131,26 @@
)
}
}
-}
\ No newline at end of file
+}
+
+@RequiresApi(29)
+private object FrameCommitCallbackHelper {
+ @DoNotInline
+ fun registerFrameCommitCallback(viewTreeObserver: ViewTreeObserver, runnable: Runnable) {
+ viewTreeObserver.registerFrameCommitCallback(runnable)
+ }
+}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private object PixelCopyHelper {
+ @DoNotInline
+ fun request(
+ source: Window,
+ srcRect: Rect?,
+ dest: Bitmap,
+ listener: PixelCopy.OnPixelCopyFinishedListener,
+ listenerThread: Handler
+ ) {
+ PixelCopy.request(source, srcRect, dest, listener, listenerThread)
+ }
+}
diff --git a/compose/ui/ui-text/src/androidMain/baseline-prof.txt b/compose/ui/ui-text/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..13ae261
--- /dev/null
+++ b/compose/ui/ui-text/src/androidMain/baseline-prof.txt
@@ -0,0 +1,107 @@
+# Baseline profile rules for androidx.compose.ui.text
+# =============================================
+HSPLandroidx/compose/ui/text/AnnotatedString**->**(**)**
+HSPLandroidx/compose/ui/text/MultiParagraph;->**(**)**
+HSPLandroidx/compose/ui/text/MultiParagraphIntrinsics**->**(**)**
+HSPLandroidx/compose/ui/text/ParagraphInfo;->**(**)**
+HSPLandroidx/compose/ui/text/ParagraphIntrinsicInfo;->**(**)**
+HSPLandroidx/compose/ui/text/ParagraphStyle;->**(**)**
+HSPLandroidx/compose/ui/text/ParagraphKt;->**(**)**
+HSPLandroidx/compose/ui/text/SpanStyle;->**(**)**
+HSPLandroidx/compose/ui/text/TextLayoutInput;->**(**)**
+HSPLandroidx/compose/ui/text/TextLayoutResult;->**(**)**
+HSPLandroidx/compose/ui/text/TextPainter;->**(**)**
+HSPLandroidx/compose/ui/text/TextRange**->**(**)**
+HSPLandroidx/compose/ui/text/TextStyle**->**(**)**
+HSPLandroidx/compose/ui/text/android/BoringLayoutFactory;->**(**)**
+HSPLandroidx/compose/ui/text/android/CharSequenceCharacterIterator;->**(**)**
+HSPLandroidx/compose/ui/text/android/LayoutIntrinsics**->**(**)**
+HSPLandroidx/compose/ui/text/android/StaticLayoutFactory**->**(**)**
+HSPLandroidx/compose/ui/text/android/StaticLayoutParams;->**(**)**
+HSPLandroidx/compose/ui/text/android/TextAlignmentAdapter;->**(**)**
+HSPLandroidx/compose/ui/text/android/TextLayout;->**(**)**
+HSPLandroidx/compose/ui/text/android/style/BaselineShiftSpan;->**(**)**
+HSPLandroidx/compose/ui/text/android/style/LetterSpacingSpanPx;->**(**)**
+HSPLandroidx/compose/ui/text/android/style/LineHeightSpan;->**(**)**
+HSPLandroidx/compose/ui/text/android/style/TypefaceSpan;->**(**)**
+HSPLandroidx/compose/ui/text/font/DefaultFontFamily;->**(**)**
+HSPLandroidx/compose/ui/text/font/FileBasedFontFamily;->**(**)**
+HSPLandroidx/compose/ui/text/font/FontFamily**->**(**)**
+HSPLandroidx/compose/ui/text/font/FontKt;->**(**)**
+HSPLandroidx/compose/ui/text/font/FontListFontFamily;->**(**)**
+HSPLandroidx/compose/ui/text/font/FontMatcher;->**(**)**
+HSPLandroidx/compose/ui/text/font/FontStyle;->**(**)**
+HSPLandroidx/compose/ui/text/font/FontWeight**->**(**)**
+HSPLandroidx/compose/ui/text/font/GenericFontFamily;->**(**)**
+HSPLandroidx/compose/ui/text/font/ResourceFont;->**(**)**
+HSPLandroidx/compose/ui/text/font/SystemFontFamily;->**(**)**
+HSPLandroidx/compose/ui/text/input/EditProcessor;->**(**)**
+HSPLandroidx/compose/ui/text/input/EditingBuffer;->**(**)**
+HSPLandroidx/compose/ui/text/input/ImeAction**->**(**)**
+HSPLandroidx/compose/ui/text/input/ImeOptions**->**(**)**
+HSPLandroidx/compose/ui/text/input/KeyboardType**->**(**)**
+HSPLandroidx/compose/ui/text/input/TextFieldValue;->**(**)**
+HSPLandroidx/compose/ui/text/input/TextInputService**->**(**)**
+HSPLandroidx/compose/ui/text/input/TransformedText;->**(**)**
+HSPLandroidx/compose/ui/text/intl/AndroidLocale**->**(**)**
+HSPLandroidx/compose/ui/text/intl/Locale**->**(**)**
+HSPLandroidx/compose/ui/text/platform/AndroidParagraph;->**(**)**
+HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics;->**(**)**
+HSPLandroidx/compose/ui/text/platform/AndroidParagraphIntrinsics_androidKt;->**(**)**
+HSPLandroidx/compose/ui/text/platform/AndroidParagraph_androidKt;->**(**)**
+HSPLandroidx/compose/ui/text/platform/AndroidTextPaint;->**(**)**
+HSPLandroidx/compose/ui/text/platform/TypefaceAdapter;->**(**)**
+HSPLandroidx/compose/ui/text/platform/TypefaceAdapterHelperMethods;->**(**)**
+HSPLandroidx/compose/ui/text/platform/extensions/SpanRange;->**(**)**
+HSPLandroidx/compose/ui/text/platform/extensions/SpannableExtensions_androidKt;->**(**)**
+HSPLandroidx/compose/ui/text/platform/extensions/TextPaintExtensions_androidKt;->**(**)**
+HSPLandroidx/compose/ui/text/style/BaselineShift**->**(**)**
+HSPLandroidx/compose/ui/text/style/ResolvedTextDirection;->**(**)**
+HSPLandroidx/compose/ui/text/style/TextAlign;->**(**)**
+HSPLandroidx/compose/ui/text/style/TextDecoration;->**(**)**
+HSPLandroidx/compose/ui/text/style/TextDirection;->**(**)**
+HSPLandroidx/compose/ui/text/style/TextGeometricTransform;->**(**)**
+HSPLandroidx/compose/ui/text/style/TextIndent;->**(**)**
+Landroidx/compose/ui/text/**
+#
+# We rely heavily on some text methods in kotlin stdlib, so makes sense to include them here
+HSPLkotlin/text/CharsKt__CharJVMKt;->isWhitespace(C)Z
+HSPLkotlin/text/MatcherMatchResult$groups$1;-><init>(Lkotlin/text/MatcherMatchResult;)V
+HSPLkotlin/text/MatcherMatchResult;-><init>(Ljava/util/regex/Matcher;Ljava/lang/CharSequence;)V
+HSPLkotlin/text/MatcherMatchResult;->getMatchResult()Ljava/util/regex/MatchResult;
+HSPLkotlin/text/MatcherMatchResult;->getRange()Lkotlin/ranges/IntRange;
+HSPLkotlin/text/MatcherMatchResult;->getValue()Ljava/lang/String;
+HSPLkotlin/text/MatcherMatchResult;->next()Lkotlin/text/MatchResult;
+HSPLkotlin/text/Regex$Companion;-><init>()V
+HSPLkotlin/text/Regex$Companion;-><init>(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+HSPLkotlin/text/Regex$findAll$1;-><init>(Lkotlin/text/Regex;Ljava/lang/CharSequence;I)V
+HSPLkotlin/text/Regex$findAll$1;->invoke()Ljava/lang/Object;
+HSPLkotlin/text/Regex$findAll$1;->invoke()Lkotlin/text/MatchResult;
+HSPLkotlin/text/Regex$findAll$2;-><init>()V
+HSPLkotlin/text/Regex$findAll$2;->invoke(Ljava/lang/Object;)Ljava/lang/Object;
+HSPLkotlin/text/Regex$findAll$2;->invoke(Lkotlin/text/MatchResult;)Lkotlin/text/MatchResult;
+HSPLkotlin/text/Regex;-><init>(Ljava/lang/String;)V
+HSPLkotlin/text/Regex;-><init>(Ljava/util/regex/Pattern;)V
+HSPLkotlin/text/Regex;->find(Ljava/lang/CharSequence;I)Lkotlin/text/MatchResult;
+HSPLkotlin/text/Regex;->findAll$default(Lkotlin/text/Regex;Ljava/lang/CharSequence;IILjava/lang/Object;)Lkotlin/sequences/Sequence;
+HSPLkotlin/text/Regex;->findAll(Ljava/lang/CharSequence;I)Lkotlin/sequences/Sequence;
+HSPLkotlin/text/RegexKt;->access$findNext(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Lkotlin/text/MatchResult;
+HSPLkotlin/text/RegexKt;->access$range(Ljava/util/regex/MatchResult;)Lkotlin/ranges/IntRange;
+HSPLkotlin/text/RegexKt;->findNext(Ljava/util/regex/Matcher;ILjava/lang/CharSequence;)Lkotlin/text/MatchResult;
+HSPLkotlin/text/RegexKt;->range(Ljava/util/regex/MatchResult;)Lkotlin/ranges/IntRange;
+HSPLkotlin/text/StringsKt__StringsJVMKt;->endsWith$default(Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Z
+HSPLkotlin/text/StringsKt__StringsJVMKt;->endsWith(Ljava/lang/String;Ljava/lang/String;Z)Z
+HSPLkotlin/text/StringsKt__StringsJVMKt;->isBlank(Ljava/lang/CharSequence;)Z
+HSPLkotlin/text/StringsKt__StringsJVMKt;->repeat(Ljava/lang/CharSequence;I)Ljava/lang/String;
+HSPLkotlin/text/StringsKt__StringsKt;->endsWith$default(Ljava/lang/CharSequence;Ljava/lang/CharSequence;ZILjava/lang/Object;)Z
+HSPLkotlin/text/StringsKt__StringsKt;->endsWith(Ljava/lang/CharSequence;Ljava/lang/CharSequence;Z)Z
+HSPLkotlin/text/StringsKt__StringsKt;->getIndices(Ljava/lang/CharSequence;)Lkotlin/ranges/IntRange;
+HSPLkotlin/text/StringsKt__StringsKt;->getLastIndex(Ljava/lang/CharSequence;)I
+HSPLkotlin/text/StringsKt__StringsKt;->lastIndexOf$default(Ljava/lang/CharSequence;CIZILjava/lang/Object;)I
+HSPLkotlin/text/StringsKt__StringsKt;->lastIndexOf(Ljava/lang/CharSequence;CIZ)I
+HSPLkotlin/text/StringsKt__StringsKt;->substring(Ljava/lang/String;Lkotlin/ranges/IntRange;)Ljava/lang/String;
+HSPLkotlin/text/StringsKt__StringsKt;->substringAfterLast$default(Ljava/lang/String;CLjava/lang/String;ILjava/lang/Object;)Ljava/lang/String;
+HSPLkotlin/text/StringsKt__StringsKt;->substringAfterLast(Ljava/lang/String;CLjava/lang/String;)Ljava/lang/String;
+HSPLkotlin/text/StringsKt__StringsKt;->trim(Ljava/lang/String;[C)Ljava/lang/String;
+HSPLkotlin/text/StringsKt___StringsKt;->first(Ljava/lang/CharSequence;)C
+HSPLkotlin/text/StringsKt___StringsKt;->slice(Ljava/lang/String;Lkotlin/ranges/IntRange;)Ljava/lang/String;
\ No newline at end of file
diff --git a/compose/ui/ui-tooling/lint-baseline.xml b/compose/ui/ui-tooling/lint-baseline.xml
index f445f79..5f2bf52 100644
--- a/compose/ui/ui-tooling/lint-baseline.xml
+++ b/compose/ui/ui-tooling/lint-baseline.xml
@@ -23,15 +23,4 @@
column="30"/>
</issue>
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 26; however, the containing class androidx.compose.ui.tooling.preview.LayoutlibFontResourceLoader is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" is ResourceFont -> context.resources.getFont(font.resId)"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/tooling/preview/LayoutlibFontResourceLoader.kt"
- line="33"
- column="50"/>
- </issue>
-
</issues>
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/LayoutlibFontResourceLoader.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/LayoutlibFontResourceLoader.kt
index 662a422..0c85551 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/LayoutlibFontResourceLoader.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/LayoutlibFontResourceLoader.kt
@@ -19,6 +19,7 @@
import android.content.Context
import android.graphics.Typeface
import android.os.Build
+import androidx.annotation.DoNotInline
import androidx.annotation.RequiresApi
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.ResourceFont
@@ -27,11 +28,19 @@
* Layoutlib implementation for [Font.ResourceLoader]
*/
internal class LayoutlibFontResourceLoader(private val context: Context) : Font.ResourceLoader {
- @RequiresApi(Build.VERSION_CODES.O)
override fun load(font: Font): Typeface {
- return when (font) {
- is ResourceFont -> context.resources.getFont(font.resId)
- else -> throw IllegalArgumentException("Unknown font type: ${font.javaClass.name}")
+ return if (font is ResourceFont && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ ResourceFontHelper.load(context, font)
+ } else {
+ throw IllegalArgumentException("Unknown font type: ${font.javaClass.name}")
}
}
}
+
+@RequiresApi(Build.VERSION_CODES.O)
+private object ResourceFontHelper {
+ @DoNotInline
+ fun load(context: Context, font: ResourceFont): Typeface {
+ return context.resources.getFont(font.resId)
+ }
+}
diff --git a/compose/ui/ui-unit/src/androidMain/baseline-prof.txt b/compose/ui/ui-unit/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..860e61e
--- /dev/null
+++ b/compose/ui/ui-unit/src/androidMain/baseline-prof.txt
@@ -0,0 +1,5 @@
+# Baseline profile rules for androidx.compose.ui.unit
+# =============================================
+# everything in unit is relatively small and in the hot path, so we just add everything
+HSPLandroidx/compose/ui/unit/**->**(**)**
+Landroidx/compose/ui/unit/**;
\ No newline at end of file
diff --git a/compose/ui/ui-util/src/androidMain/baseline-prof.txt b/compose/ui/ui-util/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..21a0cfc
--- /dev/null
+++ b/compose/ui/ui-util/src/androidMain/baseline-prof.txt
@@ -0,0 +1,4 @@
+# Baseline profile rules for androidx.compose.ui.util
+# =============================================
+HSPLandroidx/compose/ui/util/MathHelpersKt;->lerp(FFF)F
+Landroidx/compose/ui/util/MathHelpersKt;
\ No newline at end of file
diff --git a/compose/ui/ui/api/1.0.0-beta09.txt b/compose/ui/ui/api/1.0.0-beta09.txt
index bb0a58a..f0cf560 100644
--- a/compose/ui/ui/api/1.0.0-beta09.txt
+++ b/compose/ui/ui/api/1.0.0-beta09.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -150,9 +150,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2015,6 +2012,9 @@
public final class JvmActuals_jvmKt {
}
+ public final class ShapeContainingUtilKt {
+ }
+
public final class TestTagKt {
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier testTag(androidx.compose.ui.Modifier, String tag);
}
diff --git a/compose/ui/ui/api/current.ignore b/compose/ui/ui/api/current.ignore
index 72e6f85..91311ea 100644
--- a/compose/ui/ui/api/current.ignore
+++ b/compose/ui/ui/api/current.ignore
@@ -27,6 +27,8 @@
Attempted to change parameter name from p to value in method androidx.compose.ui.layout.Placeable.setMeasurementConstraints-BRTryo0
+RemovedClass: androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt:
+ Removed class androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt
RemovedClass: androidx.compose.ui.input.pointer.RequestDisallowInterceptTouchEvent:
Removed class androidx.compose.ui.input.pointer.RequestDisallowInterceptTouchEvent
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index bb0a58a..f0cf560 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -150,9 +150,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2015,6 +2012,9 @@
public final class JvmActuals_jvmKt {
}
+ public final class ShapeContainingUtilKt {
+ }
+
public final class TestTagKt {
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier testTag(androidx.compose.ui.Modifier, String tag);
}
diff --git a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta09.txt b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta09.txt
index 035b992..d1da62e 100644
--- a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta09.txt
+++ b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta09.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -156,9 +156,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2143,6 +2140,9 @@
field public static final androidx.compose.ui.platform.LocalSoftwareKeyboardController INSTANCE;
}
+ public final class ShapeContainingUtilKt {
+ }
+
@androidx.compose.runtime.Stable @androidx.compose.ui.ExperimentalComposeUiApi public interface SoftwareKeyboardController {
method public void hide();
method @Deprecated public default void hideSoftwareKeyboard();
@@ -2773,6 +2773,7 @@
}
@androidx.compose.runtime.Immutable public final class PopupProperties {
+ ctor @androidx.compose.ui.ExperimentalComposeUiApi public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled, optional boolean useDefaultMaxWidth);
ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled);
method public boolean getClippingEnabled();
method public boolean getDismissOnBackPress();
@@ -2780,12 +2781,14 @@
method public boolean getExcludeFromSystemGesture();
method public boolean getFocusable();
method public androidx.compose.ui.window.SecureFlagPolicy getSecurePolicy();
+ method @androidx.compose.ui.ExperimentalComposeUiApi public boolean getUseDefaultMaxWidth();
property public final boolean clippingEnabled;
property public final boolean dismissOnBackPress;
property public final boolean dismissOnClickOutside;
property public final boolean excludeFromSystemGesture;
property public final boolean focusable;
property public final androidx.compose.ui.window.SecureFlagPolicy securePolicy;
+ property @androidx.compose.ui.ExperimentalComposeUiApi public final boolean useDefaultMaxWidth;
}
public enum SecureFlagPolicy {
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 035b992..d1da62e 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -156,9 +156,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2143,6 +2140,9 @@
field public static final androidx.compose.ui.platform.LocalSoftwareKeyboardController INSTANCE;
}
+ public final class ShapeContainingUtilKt {
+ }
+
@androidx.compose.runtime.Stable @androidx.compose.ui.ExperimentalComposeUiApi public interface SoftwareKeyboardController {
method public void hide();
method @Deprecated public default void hideSoftwareKeyboard();
@@ -2773,6 +2773,7 @@
}
@androidx.compose.runtime.Immutable public final class PopupProperties {
+ ctor @androidx.compose.ui.ExperimentalComposeUiApi public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled, optional boolean useDefaultMaxWidth);
ctor public PopupProperties(optional boolean focusable, optional boolean dismissOnBackPress, optional boolean dismissOnClickOutside, optional androidx.compose.ui.window.SecureFlagPolicy securePolicy, optional boolean excludeFromSystemGesture, optional boolean clippingEnabled);
method public boolean getClippingEnabled();
method public boolean getDismissOnBackPress();
@@ -2780,12 +2781,14 @@
method public boolean getExcludeFromSystemGesture();
method public boolean getFocusable();
method public androidx.compose.ui.window.SecureFlagPolicy getSecurePolicy();
+ method @androidx.compose.ui.ExperimentalComposeUiApi public boolean getUseDefaultMaxWidth();
property public final boolean clippingEnabled;
property public final boolean dismissOnBackPress;
property public final boolean dismissOnClickOutside;
property public final boolean excludeFromSystemGesture;
property public final boolean focusable;
property public final androidx.compose.ui.window.SecureFlagPolicy securePolicy;
+ property @androidx.compose.ui.ExperimentalComposeUiApi public final boolean useDefaultMaxWidth;
}
public enum SecureFlagPolicy {
diff --git a/compose/ui/ui/api/restricted_1.0.0-beta09.txt b/compose/ui/ui/api/restricted_1.0.0-beta09.txt
index f0d7adf..cea0677 100644
--- a/compose/ui/ui/api/restricted_1.0.0-beta09.txt
+++ b/compose/ui/ui/api/restricted_1.0.0-beta09.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -150,9 +150,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2045,6 +2042,9 @@
public final class JvmActuals_jvmKt {
}
+ public final class ShapeContainingUtilKt {
+ }
+
public final class TestTagKt {
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier testTag(androidx.compose.ui.Modifier, String tag);
}
diff --git a/compose/ui/ui/api/restricted_current.ignore b/compose/ui/ui/api/restricted_current.ignore
index 72e6f85..91311ea 100644
--- a/compose/ui/ui/api/restricted_current.ignore
+++ b/compose/ui/ui/api/restricted_current.ignore
@@ -27,6 +27,8 @@
Attempted to change parameter name from p to value in method androidx.compose.ui.layout.Placeable.setMeasurementConstraints-BRTryo0
+RemovedClass: androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt:
+ Removed class androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt
RemovedClass: androidx.compose.ui.input.pointer.RequestDisallowInterceptTouchEvent:
Removed class androidx.compose.ui.input.pointer.RequestDisallowInterceptTouchEvent
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index f0d7adf..cea0677 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -21,7 +21,7 @@
field public static final androidx.compose.ui.AbsoluteAlignment INSTANCE;
}
- @androidx.compose.runtime.Immutable public fun interface Alignment {
+ @androidx.compose.runtime.Stable public fun interface Alignment {
method public long align-oYSo38o(long size, long space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
field public static final androidx.compose.ui.Alignment.Companion Companion;
}
@@ -59,11 +59,11 @@
property public final androidx.compose.ui.Alignment TopStart;
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Horizontal {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Horizontal {
method public int align(int size, int space, androidx.compose.ui.unit.LayoutDirection layoutDirection);
}
- @androidx.compose.runtime.Immutable public static fun interface Alignment.Vertical {
+ @androidx.compose.runtime.Stable public static fun interface Alignment.Vertical {
method public int align(int size, int space);
}
@@ -150,9 +150,6 @@
package androidx.compose.ui.autofill {
- public final class AndroidAutofillDebugUtils_androidKt {
- }
-
public final class AndroidAutofillType_androidKt {
}
@@ -2045,6 +2042,9 @@
public final class JvmActuals_jvmKt {
}
+ public final class ShapeContainingUtilKt {
+ }
+
public final class TestTagKt {
method @androidx.compose.runtime.Stable public static androidx.compose.ui.Modifier testTag(androidx.compose.ui.Modifier, String tag);
}
diff --git a/compose/ui/ui/build.gradle b/compose/ui/ui/build.gradle
index 1447013..8a4e3a5 100644
--- a/compose/ui/ui/build.gradle
+++ b/compose/ui/ui/build.gradle
@@ -65,6 +65,7 @@
implementation("androidx.lifecycle:lifecycle-common-java8:2.3.0")
implementation("androidx.lifecycle:lifecycle-runtime:2.3.0")
implementation("androidx.lifecycle:lifecycle-viewmodel:2.3.0")
+ implementation(project(":profileinstaller:profileinstaller"))
testImplementation(libs.testRules)
testImplementation(libs.testRunner)
diff --git a/compose/ui/ui/lint-baseline.xml b/compose/ui/ui/lint-baseline.xml
index 56574e2..62a8a2f 100644
--- a/compose/ui/ui/lint-baseline.xml
+++ b/compose/ui/ui/lint-baseline.xml
@@ -22,60 +22,4 @@
line="341"
column="17"/>
</issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 26; however, the containing class androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" autofillManager.registerCallback(AutofillCallback)"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillDebugUtils.android.kt"
- line="67"
- column="21"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 26; however, the containing class androidx.compose.ui.autofill.AndroidAutofillDebugUtils_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" autofillManager.unregisterCallback(AutofillCallback)"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillDebugUtils.android.kt"
- line="77"
- column="21"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 23; however, the containing class androidx.compose.ui.res.ColorResources_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" Color(context.resources.getColor(id, context.theme))"
- errorLine2=" ~~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/res/ColorResources.android.kt"
- line="37"
- column="33"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.input.pointer.MotionEventAdapter_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" return Offset(getRawX(index), getRawY(index))"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt"
- line="194"
- column="19"/>
- </issue>
-
- <issue
- id="ClassVerificationFailure"
- message="This call references a method added in API level 29; however, the containing class androidx.compose.ui.input.pointer.MotionEventAdapter_androidKt is reachable from earlier API levels and will fail run-time class verification."
- errorLine1=" return Offset(getRawX(index), getRawY(index))"
- errorLine2=" ~~~~~~~">
- <location
- file="src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt"
- line="194"
- column="35"/>
- </issue>
-
</issues>
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
index 60f297a..ba91108 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidLayoutDrawTest.kt
@@ -3461,6 +3461,57 @@
assertTrue(latch.await(1, TimeUnit.SECONDS))
}
+ @Test
+ fun noRemeasureWhenWeStopUsingStateInMeasuring() = with(density) {
+ val counter = mutableStateOf(0)
+ var latch = CountDownLatch(1)
+ var parentRemeasures = 0
+ var measurePolicy = mutableStateOf(
+ MeasurePolicy { measurables, constraints ->
+ counter.value
+ parentRemeasures++
+ measurables.first().measure(constraints)
+ layout(1, 1) { }
+ }
+ )
+ activityTestRule.runOnUiThread {
+ activity.setContent {
+ Layout(
+ content = {
+ Layout(
+ content = {}
+ ) { _, _ ->
+ counter.value
+ latch.countDown()
+ layout(1, 1) { }
+ }
+ },
+ measurePolicy = measurePolicy.value
+ )
+ }
+ }
+
+ assertTrue(latch.await(1, TimeUnit.SECONDS))
+ assertEquals(1, parentRemeasures)
+
+ latch = CountDownLatch(1)
+ measurePolicy.value = MeasurePolicy { measurables, constraints ->
+ // not using counter anymore
+ parentRemeasures++
+ measurables.first().measure(constraints)
+ layout(1, 1) { }
+ }
+
+ assertTrue(latch.await(10000, TimeUnit.SECONDS))
+ assertEquals(2, parentRemeasures)
+
+ latch = CountDownLatch(1)
+ counter.value = 1
+
+ assertTrue(latch.await(10000, TimeUnit.SECONDS))
+ assertEquals(2, parentRemeasures)
+ }
+
private fun composeSquares(model: SquareModel) {
activityTestRule.runOnUiThreadIR {
activity.setContent {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/ClipPointerInputTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/ClipPointerInputTest.kt
index 7dfeec5..905cbb2 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/ClipPointerInputTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/ClipPointerInputTest.kt
@@ -21,18 +21,28 @@
import android.view.ViewGroup
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.shape.GenericShape
+import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.Size
import androidx.compose.ui.gesture.MotionEvent
import androidx.compose.ui.gesture.PointerCoords
import androidx.compose.ui.gesture.PointerProperties
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.layout.Layout
+import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.runOnUiThreadIR
import androidx.compose.ui.test.TestActivity
+import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
@@ -313,6 +323,227 @@
assertThat(loggingPim4.log).isEqualTo(listOf(Offset(0f, 0f)))
}
+ /**
+ * This test creates a layout clipped to a rounded rectangle shape (circle).
+ * We'll touch in and out of the rounded area.
+ */
+ @Test
+ fun clip_roundedRect() {
+ pokeAroundCircle(RoundedCornerShape(50))
+ }
+
+ /**
+ * This test creates a layout clipped to a rounded rectangle shape (circle), but the
+ * corners are defined as larger than the side length
+ * We'll touch in and out of the rounded area.
+ */
+ @Test
+ fun clip_roundedRectLargeCorner() {
+ pokeAroundCircle(RoundedCornerShape(1.1f))
+ }
+
+ /**
+ * This test creates a layout clipped to a generic shape (circle).
+ * We'll touch in and out of the rounded area.
+ */
+ @Test
+ fun clip_genericShape() {
+ pokeAroundCircle(
+ GenericShape { size, _ ->
+ addOval(Rect(0f, 0f, size.width, size.height))
+ }
+ )
+ }
+
+ /**
+ * This test creates a layout clipped to a circle shape.
+ * We'll touch in and out of the rounded area.
+ */
+ fun pokeAroundCircle(shape: Shape) {
+
+ val setupLatch = CountDownLatch(1)
+
+ val loggingPim = LoggingPim()
+
+ rule.runOnUiThreadIR {
+ activity.setContent {
+ Child(
+ Modifier.clip(shape)
+ .then(loggingPim)
+ .layout { measurable, constraints ->
+ val p = measurable.measure(constraints)
+ layout(p.width, p.height) {
+ p.place(0, 0)
+ setupLatch.countDown()
+ }
+ }
+ )
+ }
+
+ view = activity.findViewById<ViewGroup>(android.R.id.content)
+ setupLatch.countDown()
+ }
+
+ assertThat(setupLatch.await(2, TimeUnit.SECONDS)).isTrue()
+
+ val offset = 1f / 128f
+ val above0 = offset
+ val below2 = 2f - offset
+ val above2 = 2f + offset
+ val below0 = -offset
+
+ val offsetsThatHit =
+ listOf(
+ Offset(above0, 1f),
+ Offset(1f, above0),
+ Offset(1f, below2),
+ Offset(below2, 1f),
+ Offset(1f, 1f),
+ Offset(0.5f, 0.5f),
+ Offset(0.5f, 1.5f),
+ Offset(1.5f, 0.5f),
+ Offset(1.5f, 1.5f),
+ )
+ val offsetsThatMiss =
+ listOf(
+ Offset(above0, above0),
+ Offset(above0, below2),
+ Offset(below2, above0),
+ Offset(below2, below2),
+ Offset(1f, below0),
+ Offset(above2, 1f),
+ Offset(below0, 1f),
+ Offset(1f, above2),
+ )
+
+ val downEvents = mutableListOf<MotionEvent>()
+ (offsetsThatHit + offsetsThatMiss).forEachIndexed { index, value ->
+ downEvents.add(
+ MotionEvent(
+ index,
+ MotionEvent.ACTION_DOWN,
+ 1,
+ 0,
+ arrayOf(PointerProperties(0)),
+ arrayOf(PointerCoords(value.x, value.y)),
+ view
+ )
+ )
+ }
+
+ // Act
+ rule.runOnUiThreadIR {
+ downEvents.forEach {
+ view.dispatchTouchEvent(it)
+ }
+ }
+
+ // Assert
+ assertThat(loggingPim.log).isEqualTo(offsetsThatHit)
+ }
+
+ /**
+ * This creates a clipped rectangle that is smaller than the bounds and ensures that only the
+ * clipped area receives touches
+ */
+ @Test
+ fun clip_smallRect() {
+ val rectangleShape: Shape = object : Shape {
+ override fun createOutline(
+ size: Size,
+ layoutDirection: LayoutDirection,
+ density: Density
+ ) =
+ Outline.Rectangle(
+ Rect(
+ size.width * 0.25f,
+ size.height * 0.25f,
+ size.width * 0.75f,
+ size.height * 0.75f,
+ )
+ )
+ }
+
+ val setupLatch = CountDownLatch(1)
+
+ val loggingPim = LoggingPim()
+
+ rule.runOnUiThreadIR {
+ activity.setContent {
+ Child(
+ Modifier.clip(rectangleShape)
+ .then(loggingPim)
+ .layout { measurable, constraints ->
+ val p = measurable.measure(constraints)
+ layout(p.width, p.height) {
+ p.place(0, 0)
+ setupLatch.countDown()
+ }
+ }
+ )
+ }
+
+ view = activity.findViewById<ViewGroup>(android.R.id.content)
+ setupLatch.countDown()
+ }
+
+ assertThat(setupLatch.await(2, TimeUnit.SECONDS)).isTrue()
+ val offset = 1f / 128f
+ val justIn = 1.5f - offset
+ val justOut = 0.5f - offset
+
+ val offsetsThatHit =
+ listOf(
+ Offset(0.5f, 0.5f),
+ Offset(justIn, 0.5f),
+ Offset(0.5f, justIn),
+ Offset(justIn, justIn),
+
+ Offset(1f, 0.5f),
+ Offset(0.5f, 1f),
+ Offset(1f, justIn),
+ Offset(justIn, 1f),
+
+ Offset(1f, 1f),
+ )
+ val offsetsThatMiss =
+ listOf(
+ Offset(justOut, 0.5f),
+ Offset(0.5f, justOut),
+ Offset(1.5f, 0.5f),
+ Offset(justIn, justOut),
+ Offset(0.5f, 1.5f),
+ Offset(justOut, justIn),
+ Offset(justIn, 1.5f),
+ Offset(1.5f, justIn),
+ )
+
+ val downEvents = mutableListOf<MotionEvent>()
+ (offsetsThatHit + offsetsThatMiss).forEachIndexed { index, value ->
+ downEvents.add(
+ MotionEvent(
+ index,
+ MotionEvent.ACTION_DOWN,
+ 1,
+ 0,
+ arrayOf(PointerProperties(0)),
+ arrayOf(PointerCoords(value.x, value.y)),
+ view
+ )
+ )
+ }
+
+ // Act
+ rule.runOnUiThreadIR {
+ downEvents.forEach {
+ view.dispatchTouchEvent(it)
+ }
+ }
+
+ // Assert
+ assertThat(loggingPim.log).isEqualTo(offsetsThatHit)
+ }
+
@Composable
fun Child(modifier: Modifier) {
Layout(content = {}, modifier = modifier) { _, _ ->
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index 49c2c27..9992c25 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -103,7 +103,7 @@
with(filter) {
awaitPointerEventScope {
repeat(3) {
- results.offer(awaitPointerEvent())
+ results.trySend(awaitPointerEvent())
}
results.close()
}
@@ -138,7 +138,7 @@
with(filter) {
awaitPointerEventScope {
repeat(3) {
- results.offer(awaitPointerEvent())
+ results.trySend(awaitPointerEvent())
}
results.close()
}
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/RemeasureWithIntrinsicsTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/RemeasureWithIntrinsicsTest.kt
new file mode 100644
index 0000000..58071f5
--- /dev/null
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/RemeasureWithIntrinsicsTest.kt
@@ -0,0 +1,535 @@
+/*
+ * Copyright 2021 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.ui.layout
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.foundation.layout.requiredSizeIn
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.AndroidOwnerExtraAssertionsRule
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.TestActivity
+import androidx.compose.ui.test.assertHeightIsEqualTo
+import androidx.compose.ui.test.assertWidthIsEqualTo
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class RemeasureWithIntrinsicsTest {
+
+ @get:Rule
+ val rule = createAndroidComposeRule<TestActivity>()
+
+ @get:Rule
+ val excessiveAssertions = AndroidOwnerExtraAssertionsRule()
+
+ @Test
+ fun remeasuringChildWhenParentUsedIntrinsicSizes() {
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+
+ rule.setContent {
+ LayoutUsingIntrinsics {
+ LayoutWithIntrinsics(
+ intrinsicWidth,
+ intrinsicHeight,
+ Modifier.testTag("child")
+ )
+ }
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(40.dp)
+ .assertHeightIsEqualTo(50.dp)
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun updatingChildIntrinsicsViaModifierWhenParentUsedIntrinsicSizes() {
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+
+ rule.setContent {
+ LayoutUsingIntrinsics {
+ Box(
+ Modifier
+ .testTag("child")
+ .withIntrinsics(intrinsicWidth, intrinsicHeight)
+ )
+ }
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(40.dp)
+ .assertHeightIsEqualTo(50.dp)
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun remeasuringGrandChildWhenGrandParentUsedIntrinsicSizes() {
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+
+ rule.setContent {
+ LayoutUsingIntrinsics {
+ Box(propagateMinConstraints = true) {
+ LayoutWithIntrinsics(
+ intrinsicWidth,
+ intrinsicHeight,
+ Modifier.testTag("child")
+ )
+ }
+ }
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(40.dp)
+ .assertHeightIsEqualTo(50.dp)
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun updatingGrandChildIntrinsicsViaModifierWhenGrandParentUsedIntrinsicSizes() {
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+
+ rule.setContent {
+ LayoutUsingIntrinsics {
+ Box(propagateMinConstraints = true) {
+ Box(
+ Modifier
+ .testTag("child")
+ .withIntrinsics(intrinsicWidth, intrinsicHeight)
+ )
+ }
+ }
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(40.dp)
+ .assertHeightIsEqualTo(50.dp)
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.onNodeWithTag("child")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun nodeDoesNotCauseRemeasureOfAncestor_whenItsIntrinsicsAreUnused() {
+ var measures = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ rule.setContent {
+ LayoutUsingIntrinsics(
+ onMeasure = { ++measures },
+ modifier = Modifier.testTag("parent")
+ ) {
+ LayoutWithIntrinsics(20.dp, 20.dp) {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ }
+ }
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(1, measures)
+ }
+ rule.onNodeWithTag("parent")
+ .assertWidthIsEqualTo(20.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun causesRemeasureOfAllDependantAncestors() {
+ var measures1 = 0
+ var measures2 = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ rule.setContent {
+ LayoutUsingIntrinsics(
+ modifier = Modifier.testTag("parent1"),
+ onMeasure = { ++measures1 }
+ ) {
+ Box {
+ LayoutUsingIntrinsics(
+ modifier = Modifier.testTag("parent2"),
+ onMeasure = { ++measures2 }
+ ) {
+ Box {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ }
+ }
+ }
+ }
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(2, measures1)
+ assertEquals(2, measures2)
+ }
+ }
+
+ @Test
+ fun whenOwnerDoesNotQueryAnymore() {
+ var measures1 = 0
+ var measures2 = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ var uses by mutableStateOf(true)
+ rule.setContent {
+ LayoutUsingIntrinsics(onMeasure = { ++measures1 }) {
+ // Box needed to ensure its child is measured with the same constraints,
+ // so remeasurement can be skipped, but is not fixed size such that intrinsics
+ // can be skipped.
+ Box(Modifier.requiredSizeIn(0.dp, 0.dp, 1.dp, 1.dp)) {
+ LayoutMaybeUsingIntrinsics({ uses }, onMeasure = { ++measures2 }) {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ }
+ }
+ }
+
+ rule.runOnIdle {
+ uses = false
+ }
+
+ rule.runOnIdle {
+ measures1 = 0
+ measures2 = 0
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(1, measures1)
+ assertEquals(0, measures2)
+ }
+ }
+
+ @Test
+ fun whenConnectionFromOwnerDoesNotQueryAnymore() {
+ var measures = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ var connectionModifier by mutableStateOf(Modifier as Modifier)
+
+ val parentLayoutPolicy = MeasurePolicy { measurables, constraints ->
+ ++measures
+ val measurable = measurables.first()
+ // Query intrinsics but do not size child to them, to make sure we are
+ // remeasured when the connectionModifier is added.
+ measurable.maxIntrinsicWidth(constraints.maxHeight)
+ measurable.maxIntrinsicHeight(constraints.maxWidth)
+ val placeable = measurable.measure(constraints)
+ layout(constraints.maxWidth, constraints.maxHeight) {
+ placeable.place(0, 0)
+ }
+ }
+
+ rule.setContent {
+ Layout(
+ {
+ Box(modifier = connectionModifier) {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ },
+ measurePolicy = parentLayoutPolicy
+ )
+ }
+
+ rule.runOnIdle {
+ assertEquals(1, measures)
+ connectionModifier = Modifier.size(10.dp)
+ }
+
+ rule.runOnIdle {
+ assertEquals(2, measures)
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(2, measures)
+ }
+ }
+
+ @Test
+ fun whenQueriedFromModifier() {
+ var parentMeasures = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ rule.setContent {
+ LayoutMaybeUsingIntrinsics({ false }, onMeasure = { ++parentMeasures }) {
+ // Box used to fast return intrinsics and do not remeasure when the size
+ // of the inner Box is changing after the intrinsics change.
+ Box(Modifier.requiredSize(100.dp)) {
+ Box(Modifier.testTag("box").then(ModifierUsingIntrinsics)) {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ }
+ }
+ }
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(1, parentMeasures)
+ }
+
+ rule.onNodeWithTag("box")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+
+ @Test
+ fun whenQueriedFromModifier_andAParentQueriesAbove() {
+ var parentMeasures = 0
+ var intrinsicWidth by mutableStateOf(40.dp)
+ var intrinsicHeight by mutableStateOf(50.dp)
+ rule.setContent {
+ LayoutUsingIntrinsics(onMeasure = { ++parentMeasures }) {
+ // Box used to fast return intrinsics and do not remeasure when the size
+ // of the inner Box is changing after the intrinsics change.
+ Box(Modifier.requiredSize(100.dp)) {
+ Box(Modifier.testTag("box").then(ModifierUsingIntrinsics)) {
+ LayoutWithIntrinsics(intrinsicWidth, intrinsicHeight)
+ }
+ }
+ }
+ }
+
+ rule.runOnIdle {
+ intrinsicWidth = 30.dp
+ intrinsicHeight = 20.dp
+ }
+
+ rule.runOnIdle {
+ assertEquals(1, parentMeasures)
+ }
+
+ rule.onNodeWithTag("box")
+ .assertWidthIsEqualTo(30.dp)
+ .assertHeightIsEqualTo(20.dp)
+ }
+}
+
+@Composable
+private fun LayoutWithIntrinsics(
+ width: Dp,
+ height: Dp,
+ modifier: Modifier = Modifier,
+ onMeasure: () -> Unit = {},
+ content: @Composable () -> Unit = {}
+) {
+ Layout(
+ content = content,
+ modifier = modifier,
+ measurePolicy = object : MeasurePolicy {
+ override fun MeasureScope.measure(
+ measurables: List<Measurable>,
+ constraints: Constraints
+ ): MeasureResult {
+ onMeasure()
+ return layout(constraints.minWidth, constraints.minHeight) {}
+ }
+
+ override fun IntrinsicMeasureScope.maxIntrinsicWidth(
+ measurables: List<IntrinsicMeasurable>,
+ height: Int
+ ): Int = width.roundToPx()
+
+ override fun IntrinsicMeasureScope.maxIntrinsicHeight(
+ measurables: List<IntrinsicMeasurable>,
+ width: Int
+ ): Int = height.roundToPx()
+ }
+ )
+}
+
+@Composable
+private fun LayoutMaybeUsingIntrinsics(
+ useIntrinsics: () -> Boolean,
+ modifier: Modifier = Modifier,
+ onMeasure: () -> Unit = {},
+ content: @Composable () -> Unit
+) {
+ val measurePolicy = remember {
+ object : MeasurePolicy {
+ override fun MeasureScope.measure(
+ measurables: List<Measurable>,
+ constraints: Constraints
+ ): MeasureResult {
+ require(measurables.size == 1)
+ onMeasure()
+ val childConstraints = if (useIntrinsics()) {
+ val width = measurables.first().maxIntrinsicWidth(constraints.maxHeight)
+ val height = measurables.first().maxIntrinsicHeight(constraints.maxWidth)
+ Constraints.fixed(width, height)
+ } else {
+ constraints
+ }
+ val placeable = measurables.first().measure(childConstraints)
+ return layout(placeable.width, placeable.height) {
+ placeable.place(0, 0)
+ }
+ }
+
+ override fun IntrinsicMeasureScope.minIntrinsicWidth(
+ measurables: List<IntrinsicMeasurable>,
+ height: Int
+ ) = measurables.first().minIntrinsicWidth(height)
+
+ override fun IntrinsicMeasureScope.minIntrinsicHeight(
+ measurables: List<IntrinsicMeasurable>,
+ width: Int
+ ) = measurables.first().minIntrinsicHeight(width)
+
+ override fun IntrinsicMeasureScope.maxIntrinsicWidth(
+ measurables: List<IntrinsicMeasurable>,
+ height: Int
+ ) = measurables.first().maxIntrinsicWidth(height)
+
+ override fun IntrinsicMeasureScope.maxIntrinsicHeight(
+ measurables: List<IntrinsicMeasurable>,
+ width: Int
+ ) = measurables.first().maxIntrinsicHeight(width)
+ }
+ }
+ Layout(content, modifier, measurePolicy)
+}
+
+@Composable
+private fun LayoutUsingIntrinsics(
+ modifier: Modifier = Modifier,
+ onMeasure: () -> Unit = {},
+ content: @Composable () -> Unit
+) = LayoutMaybeUsingIntrinsics({ true }, modifier, onMeasure, content)
+
+private val ModifierUsingIntrinsics = object : LayoutModifier {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ val width = measurable.maxIntrinsicWidth(constraints.maxHeight)
+ val height = measurable.maxIntrinsicHeight(constraints.maxWidth)
+ val placeable = measurable.measure(Constraints.fixed(width, height))
+ return layout(placeable.width, placeable.height) {
+ placeable.place(0, 0)
+ }
+ }
+
+ override fun IntrinsicMeasureScope.minIntrinsicWidth(
+ measurable: IntrinsicMeasurable,
+ height: Int
+ ) = measurable.minIntrinsicWidth(height)
+
+ override fun IntrinsicMeasureScope.minIntrinsicHeight(
+ measurable: IntrinsicMeasurable,
+ width: Int
+ ) = measurable.minIntrinsicHeight(width)
+
+ override fun IntrinsicMeasureScope.maxIntrinsicWidth(
+ measurable: IntrinsicMeasurable,
+ height: Int
+ ) = measurable.maxIntrinsicWidth(height)
+
+ override fun IntrinsicMeasureScope.maxIntrinsicHeight(
+ measurable: IntrinsicMeasurable,
+ width: Int
+ ) = measurable.maxIntrinsicHeight(width)
+}
+
+private fun Modifier.withIntrinsics(width: Dp, height: Dp): Modifier {
+ return this.then(object : LayoutModifier {
+ override fun MeasureScope.measure(
+ measurable: Measurable,
+ constraints: Constraints
+ ): MeasureResult {
+ val placeable = measurable.measure(constraints)
+ return layout(placeable.width, placeable.height) {
+ placeable.place(0, 0)
+ }
+ }
+
+ override fun IntrinsicMeasureScope.maxIntrinsicWidth(
+ measurable: IntrinsicMeasurable,
+ height: Int
+ ): Int = width.roundToPx()
+
+ override fun IntrinsicMeasureScope.maxIntrinsicHeight(
+ measurable: IntrinsicMeasurable,
+ width: Int
+ ): Int = height.roundToPx()
+ })
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/WindowRecomposerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/WindowRecomposerTest.kt
index 7efb51d..395b7a0 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/WindowRecomposerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/platform/WindowRecomposerTest.kt
@@ -34,6 +34,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.filters.MediumTest
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -52,7 +53,7 @@
* Test that a Recomposer that doesn't shut down with the activity doesn't inadvertently
* keep a reference to the Activity
*/
- @OptIn(InternalComposeUiApi::class)
+ @kotlin.OptIn(DelicateCoroutinesApi::class, InternalComposeUiApi::class)
@Test
@LargeTest
fun activityGarbageCollected() {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
index af16ced..65adcb0 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTest.kt
@@ -16,8 +16,11 @@
package androidx.compose.ui.window
import android.view.View
+import android.view.View.MEASURED_STATE_TOO_SMALL
+import android.view.ViewGroup
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.requiredWidth
@@ -27,15 +30,19 @@
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
+import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.onGloballyPositioned
+import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.node.Owner
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.TestActivity
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.getUnclippedBoundsInRoot
import androidx.compose.ui.test.isRoot
-import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onFirst
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.unit.IntOffset
@@ -62,13 +69,14 @@
import org.junit.runner.RunWith
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
+import kotlin.math.roundToInt
@MediumTest
@RunWith(AndroidJUnit4::class)
class PopupTest {
@get:Rule
- val rule = createComposeRule()
+ val rule = createAndroidComposeRule<TestActivity>()
private val testTag = "testedPopup"
private val offset = IntOffset(10, 10)
@@ -352,6 +360,89 @@
rule.onNodeWithTag(testTag).assertIsDisplayed()
}
+ @OptIn(ExperimentalComposeUiApi::class)
+ @Test
+ fun canFillScreenWidth_dependingOnProperty() {
+ var box1Width = 0
+ var box2Width = 0
+ rule.setContent {
+ Popup {
+ Box(Modifier.fillMaxSize().onSizeChanged { box1Width = it.width })
+ }
+ Popup(properties = PopupProperties(useDefaultMaxWidth = true)) {
+ Box(Modifier.fillMaxSize().onSizeChanged { box2Width = it.width })
+ }
+ }
+ rule.runOnIdle {
+ assertThat(box1Width).isEqualTo(
+ (rule.activity.resources.configuration.screenWidthDp * rule.density.density)
+ .roundToInt()
+ )
+ assertThat(box2Width).isLessThan(box1Width)
+ }
+ }
+
+ @Test
+ fun didNotMeasureTooSmallLast() {
+ rule.setContent {
+ PopupTestTag(testTag) {
+ Popup {
+ Box(Modifier.fillMaxWidth())
+ }
+ }
+ }
+
+ rule.popupMatches(
+ testTag,
+ object : TypeSafeMatcher<View>() {
+ override fun describeTo(description: Description?) {
+ description?.appendText("Did not end up in MEASURE_STATE_TOO_SMALL")
+ }
+
+ override fun matchesSafely(item: View): Boolean {
+ val popupLayout = item.parent as ViewGroup
+ return popupLayout.measuredState != MEASURED_STATE_TOO_SMALL
+ }
+ }
+ )
+ }
+
+ @Test
+ fun doesNotMeasureContentMultipleTimes() {
+ var measurements = 0
+ rule.setContent {
+ Popup {
+ Box {
+ Layout({}) { _, constraints ->
+ ++measurements
+ // We size to maxWidth to make ViewRootImpl measure multiple times.
+ layout(constraints.maxWidth, 0) {}
+ }
+ }
+ }
+ }
+ rule.runOnIdle {
+ assertThat(measurements).isEqualTo(1)
+ }
+ }
+
+ @Test
+ fun resizesWhenContentResizes() {
+ val size1 = 20
+ val size2 = 30
+ var size by mutableStateOf(size1)
+ rule.setContent {
+ PopupTestTag(testTag) {
+ Popup {
+ Box(Modifier.size(with(rule.density) { size.toDp() }))
+ }
+ }
+ }
+ rule.popupMatches(testTag, matchesSize(20, 20))
+ rule.runOnIdle { size = size2 }
+ rule.popupMatches(testTag, matchesSize(30, 30))
+ }
+
private fun matchesSize(width: Int, height: Int): BoundedMatcher<View, View> {
return object : BoundedMatcher<View, View>(View::class.java) {
override fun matchesSafely(item: View?): Boolean {
diff --git a/compose/ui/ui/src/androidMain/baseline-prof.txt b/compose/ui/ui/src/androidMain/baseline-prof.txt
new file mode 100644
index 0000000..f1c9338
--- /dev/null
+++ b/compose/ui/ui/src/androidMain/baseline-prof.txt
@@ -0,0 +1,96 @@
+# Baseline profile rules for androidx.compose.ui
+# =============================================
+#
+# nested scroll
+HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDelegatingWrapper;->**(**)**
+HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollDispatcher**->**(**)**
+HSPLandroidx/compose/ui/input/nestedscroll/NestedScrollModifier**->**(**)**
+#
+# pointer input
+HSPLandroidx/compose/ui/input/pointer/ConsumedData;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/HitPathTracker;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/InternalPointerEvent;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/MotionEventAdapter_androidKt;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/Node;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/NodeParent;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerEvent;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerEventKt;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerEventPass;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerId;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputChange;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputChangeEventProducer**->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputEvent;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputEventData;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputEventProcessor;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputFilter;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInputModifier$DefaultImpls;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerInteropFilter**->**(**)**
+HSPLandroidx/compose/ui/input/pointer/RequestDisallowInterceptTouchEvent;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/ProcessResult;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/PointerType;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/SuspendingPointerInputFilter**->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/Matrix;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/PointAtTime;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/PolynomialFit;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/Vector;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/VelocityEstimate;->**(**)**
+HSPLandroidx/compose/ui/input/pointer/util/VelocityTracker;->**(**)**
+#
+# layout. include everything
+HSPLandroidx/compose/ui/layout/**->**(**)**
+#
+# node. include everything
+HSPLandroidx/compose/ui/node/**->**(**)**
+#
+# platform
+HSPLandroidx/compose/ui/platform/AndroidComposeView**->**(**)**
+HSPLandroidx/compose/ui/platform/AbstractComposeView**->**(**)**
+HSPLandroidx/compose/ui/platform/AndroidComposeView_androidKt;->**(**)**
+HSPLandroidx/compose/ui/platform/AndroidCompositionLocals_androidKt**->**(**)**
+HSPLandroidx/compose/ui/platform/AndroidFontResourceLoader;->**(**)**
+HSPLandroidx/compose/ui/platform/AndroidUiDispatcher**->**(**)**
+HSPLandroidx/compose/ui/platform/AndroidUiFrameClock**->**(**)**
+HSPLandroidx/compose/ui/platform/CompositionLocalsKt**->**(**)**
+HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry;->**(**)**
+HSPLandroidx/compose/ui/platform/DisposableSaveableStateRegistry_androidKt**->**(**)**
+HSPLandroidx/compose/ui/platform/GlobalSnapshotManager**->**(**)**
+HSPLandroidx/compose/ui/platform/InspectableValueKt$NoInspectorInfo$1;-><init>()V
+HSPLandroidx/compose/ui/platform/InspectableValueKt;->getNoInspectorInfo()Lkotlin/jvm/functions/Function1;
+HSPLandroidx/compose/ui/platform/InspectableValueKt;->isDebugInspectorInfoEnabled()Z
+HSPLandroidx/compose/ui/platform/InspectorValueInfo;-><init>(Lkotlin/jvm/functions/Function1;)V
+HSPLandroidx/compose/ui/platform/RenderNodeLayer;->**(**)**
+HSPLandroidx/compose/ui/platform/RenderNodeApi29;->**(**)**
+HSPLandroidx/compose/ui/platform/OutlineResolver;->**(**)**
+HSPLandroidx/compose/ui/platform/RenderNodeMatrixCache;->**(**)**
+HSPLandroidx/compose/ui/platform/WindowRecomposerPolicy**->**(**)**
+HSPLandroidx/compose/ui/platform/WindowRecomposer_androidKt**->**(**)**
+HSPLandroidx/compose/ui/platform/WrappedComposition**->**(**)**
+HSPLandroidx/compose/ui/res/StringResources_androidKt;->**(**)**
+HSPLandroidx/compose/ui/res/PainterResources_androidKt;->**(**)**
+HSPLandroidx/compose/ui/res/ImageResources_androidKt;->**(**)**
+#
+# semantics
+HSPLandroidx/compose/ui/semantics/AccessibilityAction;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsActions;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsConfiguration;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsModifier$DefaultImpls;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsModifierCore$Companion;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsModifierCore;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsModifierKt**->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsNode;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsNodeKt;->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsProperties**->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsPropertiesKt**->**(**)**
+HSPLandroidx/compose/ui/semantics/SemanticsWrapper;->**(**)**
+#
+# res
+HSPLandroidx/compose/ui/res/StringResources_androidKt;->**(**)**
+HSPLandroidx/compose/ui/res/PainterResources_androidKt;->**(**)**
+HSPLandroidx/compose/ui/res/ImageResources_androidKt;->**(**)**
+HSPLandroidx/compose/ui/BiasAlignment**->**(**)**
+HSPLandroidx/compose/ui/Alignment**->**(**)**
+#
+# root level things
+HSPLandroidx/compose/ui/Modifier**->**(**)**
+HSPLandroidx/compose/ui/ComposedModifier**->**(**)**
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillDebugUtils.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillCallback.android.kt
similarity index 80%
rename from compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillDebugUtils.android.kt
rename to compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillCallback.android.kt
index 79ada4f..a7b4d15 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillDebugUtils.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AutofillCallback.android.kt
@@ -31,7 +31,7 @@
* for debug purposes.
*/
@RequiresApi(Build.VERSION_CODES.O)
-private object AutofillCallback : AutofillManager.AutofillCallback() {
+internal object AutofillCallback : AutofillManager.AutofillCallback() {
override fun onAutofillEvent(view: View, virtualId: Int, event: Int) {
super.onAutofillEvent(view, virtualId, event)
Log.d(
@@ -55,24 +55,22 @@
}
)
}
-}
-/**
- * Registers the autofill debug callback.
- */
-@ExperimentalComposeUiApi
-@RequiresApi(Build.VERSION_CODES.O)
-@DoNotInline
-internal fun AndroidAutofill.registerCallback() {
- autofillManager.registerCallback(AutofillCallback)
-}
+ /**
+ * Registers the autofill debug callback.
+ */
+ @ExperimentalComposeUiApi
+ @DoNotInline
+ fun register(autofill: AndroidAutofill) {
+ autofill.autofillManager.registerCallback(this)
+ }
-/**
- * Unregisters the autofill debug callback.
- */
-@ExperimentalComposeUiApi
-@RequiresApi(Build.VERSION_CODES.O)
-@DoNotInline
-internal fun AndroidAutofill.unregisterCallback() {
- autofillManager.unregisterCallback(AutofillCallback)
+ /**
+ * Unregisters the autofill debug callback.
+ */
+ @ExperimentalComposeUiApi
+ @DoNotInline
+ fun unregister(autofill: AndroidAutofill) {
+ autofill.autofillManager.unregisterCallback(this)
+ }
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
index 7ebf120..d864a9f 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/pointer/MotionEventAdapter.android.kt
@@ -16,7 +16,6 @@
package androidx.compose.ui.input.pointer
-import android.annotation.SuppressLint
import android.os.Build
import android.view.MotionEvent
import android.view.MotionEvent.ACTION_CANCEL
@@ -158,7 +157,7 @@
rawPosition = Offset(motionEvent.rawX, motionEvent.rawY)
position = positionCalculator.screenToLocal(rawPosition)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- rawPosition = motionEvent.toRawOffset(index)
+ rawPosition = MotionEventHelper.toRawOffset(motionEvent, index)
position = positionCalculator.screenToLocal(rawPosition)
} else {
rawPosition = positionCalculator.localToScreen(position)
@@ -188,8 +187,9 @@
* which use this method will pass.
*/
@RequiresApi(Build.VERSION_CODES.Q)
-@DoNotInline
-@SuppressLint("UnsafeNewApiCall") // not sure why RequiresApi is not enough
-private fun MotionEvent.toRawOffset(index: Int): Offset {
- return Offset(getRawX(index), getRawY(index))
+private object MotionEventHelper {
+ @DoNotInline
+ fun toRawOffset(motionEvent: MotionEvent, index: Int): Offset {
+ return Offset(motionEvent.getRawX(index), motionEvent.getRawY(index))
+ }
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index e83a616..f533f76 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -44,11 +44,10 @@
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.AndroidAutofill
import androidx.compose.ui.autofill.Autofill
+import androidx.compose.ui.autofill.AutofillCallback
import androidx.compose.ui.autofill.AutofillTree
import androidx.compose.ui.autofill.performAutofill
import androidx.compose.ui.autofill.populateViewStructure
-import androidx.compose.ui.autofill.registerCallback
-import androidx.compose.ui.autofill.unregisterCallback
import androidx.compose.ui.focus.FOCUS_TAG
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusDirection.Companion.Down
@@ -770,7 +769,11 @@
invalidateLayoutNodeMeasurement(root)
invalidateLayers(root)
snapshotObserver.startObserving()
- ifDebug { if (autofillSupported()) _autofill?.registerCallback() }
+ ifDebug {
+ if (autofillSupported()) {
+ _autofill?.let { AutofillCallback.register(it) }
+ }
+ }
val lifecycleOwner = ViewTreeLifecycleOwner.get(this)
val savedStateRegistryOwner = ViewTreeSavedStateRegistryOwner.get(this)
@@ -817,7 +820,11 @@
super.onDetachedFromWindow()
snapshotObserver.stopObserving()
viewTreeOwners?.lifecycleOwner?.lifecycle?.removeObserver(this)
- ifDebug { if (autofillSupported()) _autofill?.unregisterCallback() }
+ ifDebug {
+ if (autofillSupported()) {
+ _autofill?.let { AutofillCallback.unregister(it) }
+ }
+ }
viewTreeObserver.removeOnGlobalLayoutListener(globalLayoutListener)
viewTreeObserver.removeOnScrollChangedListener(scrollChangedListener)
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
index 9d23df0..b441e23 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
@@ -1517,7 +1517,7 @@
private fun notifySubtreeAccessibilityStateChangedIfNeeded(layoutNode: LayoutNode) {
if (subtreeChangedLayoutNodes.add(layoutNode)) {
- boundsUpdateChannel.offer(Unit)
+ boundsUpdateChannel.trySend(Unit)
}
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
index 69f0564..7d4b421 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ComposeView.android.kt
@@ -262,6 +262,11 @@
final override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
ensureCompositionCreated()
+ internalOnMeasure(widthMeasureSpec, heightMeasureSpec)
+ }
+
+ @Suppress("WrongCall")
+ internal open fun internalOnMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val child = getChildAt(0)
if (child == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
@@ -280,7 +285,16 @@
)
}
- final override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ final override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) =
+ internalOnLayout(changed, left, top, right, bottom)
+
+ internal open fun internalOnLayout(
+ changed: Boolean,
+ left: Int,
+ top: Int,
+ right: Int,
+ bottom: Int
+ ) {
getChildAt(0)?.layout(
paddingLeft,
paddingTop,
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.android.kt
index 3116d17..8663ca3 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.android.kt
@@ -47,7 +47,7 @@
}
}
Snapshot.registerGlobalWriteObserver {
- channel.offer(Unit)
+ channel.trySend(Unit)
}
}
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/OutlineResolver.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/OutlineResolver.android.kt
index e5fd8b0..bba2c16 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/OutlineResolver.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/OutlineResolver.android.kt
@@ -17,6 +17,7 @@
package androidx.compose.ui.platform
import android.os.Build
+import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.geometry.Size
@@ -111,6 +112,10 @@
private var layoutDirection = LayoutDirection.Ltr
+ private var tmpTouchPointPath: Path? = null
+ private var tmpOpPath: Path? = null
+ private var calculatedOutline: Outline? = null
+
/**
* Updates the values of the outline. Returns `true` when the shape has changed.
*/
@@ -145,6 +150,18 @@
}
/**
+ * Returns true if there is a outline and [position] is outside the outline.
+ */
+ fun isInOutline(position: Offset): Boolean {
+ if (!outlineNeeded) {
+ return true
+ }
+ val outline = calculatedOutline ?: return true
+
+ return isInOutline(outline, position.x, position.y, tmpTouchPointPath, tmpOpPath)
+ }
+
+ /**
* Updates the size.
*/
fun update(size: Size) {
@@ -163,7 +180,9 @@
// The methods to configure the outline will determine/update the flag
// if it not supported on the API level
isSupportedOutline = true
- when (val outline = shape.createOutline(size, layoutDirection, density)) {
+ val outline = shape.createOutline(size, layoutDirection, density)
+ calculatedOutline = outline
+ when (outline) {
is Outline.Rectangle -> updateCacheWithRect(outline.rect)
is Outline.Rounded -> updateCacheWithRoundRect(outline.roundRect)
is Outline.Generic -> updateCacheWithPath(outline.path)
@@ -214,4 +233,10 @@
}
outlinePath = composePath
}
+
+ companion object {
+ // Because we only use these on the main thread, we can allocate just one
+ private val tmpOpPath = Path()
+ private val tmpTouchPointPath = Path()
+ }
}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/RenderNodeLayer.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/RenderNodeLayer.android.kt
index 94f6758..604f30f 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/RenderNodeLayer.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/RenderNodeLayer.android.kt
@@ -151,6 +151,20 @@
matrixCache.invalidate()
}
+ override fun isInLayer(position: Offset): Boolean {
+ val x = position.x
+ val y = position.y
+ if (renderNode.clipToBounds) {
+ return 0f <= x && x < renderNode.width && 0f <= y && y < renderNode.height
+ }
+
+ if (renderNode.clipToOutline) {
+ return outlineResolver.isInOutline(position)
+ }
+
+ return true
+ }
+
override fun resize(size: IntSize) {
val width = size.width
val height = size.height
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewLayer.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewLayer.android.kt
index 2c33801..d640eb3 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewLayer.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/ViewLayer.android.kt
@@ -169,6 +169,20 @@
matrixCache.invalidate()
}
+ override fun isInLayer(position: Offset): Boolean {
+ val x = position.x
+ val y = position.y
+ if (clipToBounds) {
+ return 0f <= x && x < width && 0f <= y && y < height
+ }
+
+ if (clipToOutline) {
+ return outlineResolver.isInOutline(position)
+ }
+
+ return true
+ }
+
private fun updateOutlineResolver() {
this.outlineProvider = if (outlineResolver.outline != null) {
OutlineProvider
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/WindowRecomposer.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/WindowRecomposer.android.kt
index f946d04..350c695 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/WindowRecomposer.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/WindowRecomposer.android.kt
@@ -30,6 +30,7 @@
import androidx.lifecycle.ViewTreeLifecycleOwner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.launch
@@ -149,6 +150,7 @@
}
}
+ @OptIn(DelicateCoroutinesApi::class)
internal fun createAndInstallWindowRecomposer(rootView: View): Recomposer {
val newRecomposer = factory.get().createRecomposer(rootView)
rootView.compositionContext = newRecomposer
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/ColorResources.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/ColorResources.android.kt
index d56ac0c..257c8b5 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/ColorResources.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/res/ColorResources.android.kt
@@ -16,8 +16,11 @@
package androidx.compose.ui.res
+import android.content.Context
import android.os.Build
import androidx.annotation.ColorRes
+import androidx.annotation.DoNotInline
+import androidx.annotation.RequiresApi
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color
@@ -34,9 +37,17 @@
fun colorResource(@ColorRes id: Int): Color {
val context = LocalContext.current
return if (Build.VERSION.SDK_INT >= 23) {
- Color(context.resources.getColor(id, context.theme))
+ ColorResourceHelper.getColor(context, id)
} else {
@Suppress("DEPRECATION")
Color(context.resources.getColor(id))
}
-}
\ No newline at end of file
+}
+
+@RequiresApi(23)
+private object ColorResourceHelper {
+ @DoNotInline
+ fun getColor(context: Context, @ColorRes id: Int): Color {
+ return Color(context.resources.getColor(id, context.theme))
+ }
+}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
index f19e992..e61215c 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/text/input/TextInputServiceAndroid.android.kt
@@ -165,12 +165,12 @@
override fun showSoftwareKeyboard() {
if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.showSoftwareKeyboard") }
- showKeyboardChannel.offer(true)
+ showKeyboardChannel.trySend(true)
}
override fun hideSoftwareKeyboard() {
if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.hideSoftwareKeyboard") }
- showKeyboardChannel.offer(false)
+ showKeyboardChannel.trySend(false)
}
suspend fun keyboardVisibilityEventLoop() {
@@ -180,7 +180,7 @@
// on the same thread, there is a possibility that we have a stale value in the channel
// because we start consuming from it before we finish producing all the values. We poll
// to make sure that we use the most recent value.
- if (showKeyboardChannel.poll() ?: showKeyboard) {
+ if (showKeyboardChannel.tryReceive().getOrNull() ?: showKeyboard) {
if (DEBUG) { Log.d(TAG, "$DEBUG_CLASS.keyboardVisibilityEventLoop.showSoftInput") }
inputMethodManager.showSoftInput(view)
} else {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
index b37b3e1..b7ec8da5 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
@@ -205,11 +205,6 @@
return true
}
- override fun requestTransparentRegion(child: View?) {
- // We are not going to respect children's attempts for using transparent regions.
- // See gatherTransparentRegion.
- }
-
/**
* A [LayoutNode] tree representation for this Android [View] holder.
* The [LayoutNode] will proxy the Compose core calls to the [View].
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
index 45c4c1a..9bb1313 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/window/AndroidPopup.android.kt
@@ -26,6 +26,7 @@
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
+import android.view.View.MeasureSpec.makeMeasureSpec
import android.view.ViewOutlineProvider
import android.view.WindowManager
import androidx.annotation.RequiresApi
@@ -93,16 +94,39 @@
* screen. By default the window is clipped to the screen boundaries. Setting this to false will
* allow windows to be accurately positioned.
* The default value is true.
+ * @property useDefaultMaxWidth Whether the width of the popup's content should be limited to
+ * the platform default, which is smaller than the screen width.
*/
@Immutable
-class PopupProperties(
+class PopupProperties @ExperimentalComposeUiApi constructor(
val focusable: Boolean = false,
val dismissOnBackPress: Boolean = true,
val dismissOnClickOutside: Boolean = true,
val securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
val excludeFromSystemGesture: Boolean = true,
- val clippingEnabled: Boolean = true
+ val clippingEnabled: Boolean = true,
+ @get:ExperimentalComposeUiApi
+ val useDefaultMaxWidth: Boolean = false
) {
+ @OptIn(ExperimentalComposeUiApi::class)
+ constructor(
+ focusable: Boolean = false,
+ dismissOnBackPress: Boolean = true,
+ dismissOnClickOutside: Boolean = true,
+ securePolicy: SecureFlagPolicy = SecureFlagPolicy.Inherit,
+ excludeFromSystemGesture: Boolean = true,
+ clippingEnabled: Boolean = true,
+ ) : this (
+ focusable = focusable,
+ dismissOnBackPress = dismissOnBackPress,
+ dismissOnClickOutside = dismissOnClickOutside,
+ securePolicy = securePolicy,
+ excludeFromSystemGesture = excludeFromSystemGesture,
+ clippingEnabled = clippingEnabled,
+ useDefaultMaxWidth = false
+ )
+
+ @OptIn(ExperimentalComposeUiApi::class)
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is PopupProperties) return false
@@ -113,10 +137,12 @@
if (securePolicy != other.securePolicy) return false
if (excludeFromSystemGesture != other.excludeFromSystemGesture) return false
if (clippingEnabled != other.clippingEnabled) return false
+ if (useDefaultMaxWidth != other.useDefaultMaxWidth) return false
return true
}
+ @OptIn(ExperimentalComposeUiApi::class)
override fun hashCode(): Int {
var result = dismissOnBackPress.hashCode()
result = 31 * result + focusable.hashCode()
@@ -125,6 +151,7 @@
result = 31 * result + securePolicy.hashCode()
result = 31 * result + excludeFromSystemGesture.hashCode()
result = 31 * result + clippingEnabled.hashCode()
+ result = 31 * result + useDefaultMaxWidth.hashCode()
return result
}
}
@@ -406,6 +433,42 @@
content()
}
+ override fun internalOnMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ if (properties.useDefaultMaxWidth) {
+ super.internalOnMeasure(widthMeasureSpec, heightMeasureSpec)
+ } else {
+ // useDefaultMaxWidth false, so don't want to limit the popup width to the Android
+ // platform default. Therefore, we create a new measure spec for width, which
+ // corresponds to the full screen width. We do the same for height, even if
+ // ViewRootImpl gives it to us from the first measure.
+ val displayWidthMeasureSpec = makeMeasureSpec(displayWidth, MeasureSpec.AT_MOST)
+ val displayHeightMeasureSpec = makeMeasureSpec(displayHeight, MeasureSpec.AT_MOST)
+ super.internalOnMeasure(displayWidthMeasureSpec, displayHeightMeasureSpec)
+ }
+ }
+
+ override fun internalOnLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
+ super.internalOnLayout(changed, left, top, right, bottom)
+ // Now set the content size as fixed layout params, such that ViewRootImpl knows
+ // the exact window size.
+ val child = getChildAt(0) ?: return
+ params.width = child.measuredWidth
+ params.height = child.measuredHeight
+ windowManager.updateViewLayout(this, params)
+ }
+
+ private val displayWidth: Int
+ get() {
+ val density = context.resources.displayMetrics.density
+ return (context.resources.configuration.screenWidthDp * density).roundToInt()
+ }
+
+ private val displayHeight: Int
+ get() {
+ val density = context.resources.displayMetrics.density
+ return (context.resources.configuration.screenHeightDp * density).roundToInt()
+ }
+
/**
* Taken from PopupWindow
*/
diff --git a/compose/ui/ui/src/androidMain/res/values/strings.xml b/compose/ui/ui/src/androidMain/res/values/strings.xml
index a436d5e..b8bd334 100644
--- a/compose/ui/ui/src/androidMain/res/values/strings.xml
+++ b/compose/ui/ui/src/androidMain/res/values/strings.xml
@@ -32,4 +32,14 @@
<string name="in_progress">In progress</string>
<!-- Spoken description of a Tab. -->
<string name="tab">Tab</string>
+ <!-- Spoken title when a navigation drawer opens. -->
+ <string name="navigation_menu">"Navigation menu"</string>
+ <!--
+ Spoken content description of an element which will close the navigation menu when clicked.
+ -->
+ <string name="close_drawer">"Close navigation menu"</string>
+ <!-- Spoken content description of an element which will close the sheet when clicked. -->
+ <string name="close_sheet">"Close sheet"</string>
+ <!-- Default accessibility error text for an editable text field. -->
+ <string name="default_error_message">"Invalid input"</string>
</resources>
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
index 16ae2cf..0a56eb3 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/Alignment.kt
@@ -31,7 +31,7 @@
* @see BiasAlignment
* @see BiasAbsoluteAlignment
*/
-@Immutable
+@Stable
fun interface Alignment {
/**
* Calculates the position of a box of size [size] relative to the top left corner of an area
@@ -45,7 +45,7 @@
* [Alignment.Horizontal] is often used to define the horizontal alignment of a layout inside a
* parent layout.
*/
- @Immutable
+ @Stable
fun interface Horizontal {
/**
* Calculates the horizontal position of a box of width [size] relative to the left
@@ -61,7 +61,7 @@
* height. [Alignment.Vertical] is often used to define the vertical alignment of a
* layout inside a parent layout.
*/
- @Immutable
+ @Stable
fun interface Vertical {
/**
* Calculates the vertical position of a box of height [size] relative to the top edge of
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
index face545..348f3db 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/PointerEvent.kt
@@ -208,6 +208,18 @@
consumed,
type
)
+
+ override fun toString(): String {
+ return "PointerInputChange(id=$id, " +
+ "uptimeMillis=$uptimeMillis, " +
+ "position=$position, " +
+ "pressed=$pressed, " +
+ "previousUptimeMillis=$previousUptimeMillis, " +
+ "previousPosition=$previousPosition, " +
+ "previousPressed=$previousPressed, " +
+ "consumed=$consumed, " +
+ "type=$type)"
+ }
}
/**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
index 162c404..46c5bb8 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/InnerPlaceable.kt
@@ -64,29 +64,17 @@
override fun findLastKeyInputWrapper(): ModifiedKeyInputNode? = findPreviousKeyInputWrapper()
- override fun minIntrinsicWidth(height: Int): Int {
- return with(layoutNode.measurePolicy) {
- measureScope.minIntrinsicWidth(layoutNode.children, height)
- }
- }
+ override fun minIntrinsicWidth(height: Int) =
+ layoutNode.intrinsicsPolicy.minIntrinsicWidth(height)
- override fun minIntrinsicHeight(width: Int): Int {
- return with(layoutNode.measurePolicy) {
- measureScope.minIntrinsicHeight(layoutNode.children, width)
- }
- }
+ override fun minIntrinsicHeight(width: Int) =
+ layoutNode.intrinsicsPolicy.minIntrinsicHeight(width)
- override fun maxIntrinsicWidth(height: Int): Int {
- return with(layoutNode.measurePolicy) {
- measureScope.maxIntrinsicWidth(layoutNode.children, height)
- }
- }
+ override fun maxIntrinsicWidth(height: Int) =
+ layoutNode.intrinsicsPolicy.maxIntrinsicWidth(height)
- override fun maxIntrinsicHeight(width: Int): Int {
- return with(layoutNode.measurePolicy) {
- measureScope.maxIntrinsicHeight(layoutNode.children, width)
- }
- }
+ override fun maxIntrinsicHeight(width: Int) =
+ layoutNode.intrinsicsPolicy.maxIntrinsicHeight(width)
override fun placeAt(
position: IntOffset,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/IntrinsicsPolicy.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/IntrinsicsPolicy.kt
new file mode 100644
index 0000000..d709076
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/IntrinsicsPolicy.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 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.ui.node
+
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.layout.MeasurePolicy
+
+/**
+ * Calculates intrinsic measurements. The queries are backed by state depending on the layout
+ * node's [MeasurePolicy], such that when the policy is changing, ancestors depending on the
+ * result of these intrinsic measurements have their own layout recalculated.
+ */
+internal class IntrinsicsPolicy(val layoutNode: LayoutNode) {
+ private var measurePolicyState: MutableState<MeasurePolicy>? = null
+
+ private var pendingMeasurePolicy: MeasurePolicy? = null
+
+ fun updateFrom(measurePolicy: MeasurePolicy) {
+ if (measurePolicyState != null) {
+ measurePolicyState!!.value = measurePolicy
+ } else {
+ pendingMeasurePolicy = measurePolicy
+ }
+ }
+
+ fun minIntrinsicWidth(height: Int) = with(measurePolicyFromState()) {
+ layoutNode.measureScope.minIntrinsicWidth(layoutNode.children, height)
+ }
+
+ fun minIntrinsicHeight(width: Int) = with(measurePolicyFromState()) {
+ layoutNode.measureScope.minIntrinsicHeight(layoutNode.children, width)
+ }
+
+ fun maxIntrinsicWidth(height: Int) = with(measurePolicyFromState()) {
+ layoutNode.measureScope.maxIntrinsicWidth(layoutNode.children, height)
+ }
+
+ fun maxIntrinsicHeight(width: Int) = with(measurePolicyFromState()) {
+ layoutNode.measureScope.maxIntrinsicHeight(layoutNode.children, width)
+ }
+
+ private fun measurePolicyFromState(): MeasurePolicy {
+ val currentState = measurePolicyState
+ ?: mutableStateOf(pendingMeasurePolicy ?: error(NoPolicyError))
+ measurePolicyState = currentState
+ return currentState.value
+ }
+
+ private companion object {
+ private const val NoPolicyError =
+ "Intrinsic size is queried but there is no measure policy in place."
+ }
+}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
index 6cca794..828aba8 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
@@ -358,7 +358,6 @@
parent.requestRemeasure()
}
alignmentLines.reset()
- alignmentUsageByParent = UsageByParent.NotUsed
onDetach?.invoke(owner)
forEachDelegate { it.detach() }
innerLayoutNodeWrapper.detach()
@@ -463,11 +462,19 @@
set(value) {
if (field != value) {
field = value
+ intrinsicsPolicy.updateFrom(measurePolicy)
requestRemeasure()
}
}
/**
+ * The intrinsic measurements of this layout, backed up by states to trigger
+ * correct remeasurement for layouts using the intrinsics of this layout
+ * when the [measurePolicy] is changing.
+ */
+ internal val intrinsicsPolicy = IntrinsicsPolicy(this)
+
+ /**
* The screen density to be used by this layout.
*/
override var density: Density = Density(1f)
@@ -518,9 +525,9 @@
override val height: Int get() = outerMeasurablePlaceable.height
/**
- * State corresponding to the alignment lines of this layout, inherited + intrinsic
+ * State corresponding to the alignment lines of this layout, inherited + intrinsic.
*/
- internal var alignmentLines = LayoutNodeAlignmentLines(this)
+ internal val alignmentLines = LayoutNodeAlignmentLines(this)
internal val mDrawScope: LayoutNodeDrawScope = sharedDrawScope
@@ -557,8 +564,6 @@
*/
internal var measuredByParent: UsageByParent = UsageByParent.NotUsed
- internal var alignmentUsageByParent = UsageByParent.NotUsed
-
@Deprecated("Temporary API to support ConstraintLayout prototyping.")
internal var canMultiMeasure: Boolean = false
@@ -1050,8 +1055,9 @@
* Used to request a new measurement + layout pass from the owner.
*/
internal fun requestRemeasure() {
+ val owner = owner ?: return
if (!ignoreRemeasureRequests && !isVirtual) {
- owner?.onRequestMeasure(this)
+ owner.onRequestMeasure(this)
}
}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
index baf4f59..478e5ba 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNodeWrapper.kt
@@ -178,16 +178,6 @@
private val snapshotObserver get() = layoutNode.requireOwner().snapshotObserver
- /**
- * Whether a pointer that is relative to the [LayoutNodeWrapper] is in the bounds of this
- * LayoutNodeWrapper.
- */
- fun isPointerInBounds(pointerPosition: Offset): Boolean {
- val x = pointerPosition.x
- val y = pointerPosition.y
- return x >= 0f && y >= 0f && x < measuredWidth && y < measuredHeight
- }
-
protected inline fun performingMeasure(
constraints: Constraints,
block: () -> Placeable
@@ -601,8 +591,9 @@
}
protected fun withinLayerBounds(pointerPosition: Offset): Boolean {
+ val layer = layer
if (layer != null && isClipping) {
- return isPointerInBounds(pointerPosition)
+ return layer.isInLayer(pointerPosition)
}
// If we are here, either we aren't clipping to bounds or we are and the pointer was in
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
index bcf5547..69a1192 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/ModifiedLayoutNode.kt
@@ -16,6 +16,8 @@
package androidx.compose.ui.node
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
@@ -40,25 +42,39 @@
}
override fun minIntrinsicWidth(height: Int): Int =
- with(modifier) {
+ with(modifierFromState()) {
measureScope.minIntrinsicWidth(wrapped, height)
}
override fun maxIntrinsicWidth(height: Int): Int =
- with(modifier) {
+ with(modifierFromState()) {
measureScope.maxIntrinsicWidth(wrapped, height)
}
override fun minIntrinsicHeight(width: Int): Int =
- with(modifier) {
+ with(modifierFromState()) {
measureScope.minIntrinsicHeight(wrapped, width)
}
override fun maxIntrinsicHeight(width: Int): Int =
- with(modifier) {
+ with(modifierFromState()) {
measureScope.maxIntrinsicHeight(wrapped, width)
}
+ private var modifierState: MutableState<LayoutModifier>? = null
+
+ @Suppress("ModifierFactoryExtensionFunction", "ModifierFactoryReturnType")
+ private fun modifierFromState(): LayoutModifier {
+ val currentModifierState = modifierState ?: mutableStateOf(modifier)
+ modifierState = currentModifierState
+ return currentModifierState.value
+ }
+
+ override fun onModifierChanged() {
+ super.onModifierChanged()
+ modifierState?.value = modifier
+ }
+
override fun calculateAlignmentLine(alignmentLine: AlignmentLine): Int {
if (measureResult.alignmentLines.containsKey(alignmentLine)) {
return measureResult.alignmentLines[alignmentLine] ?: AlignmentLine.Unspecified
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OwnedLayer.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OwnedLayer.kt
index 481c363..1e78135 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OwnedLayer.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/OwnedLayer.kt
@@ -55,6 +55,12 @@
)
/**
+ * Returns `false` if [position] is outside the clipped region or `true` if clipping
+ * is disabled or it is within the clipped region.
+ */
+ fun isInLayer(position: Offset): Boolean
+
+ /**
* Changes the position of the layer contents.
*/
fun move(position: IntOffset)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/PointerInputDelegatingWrapper.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/PointerInputDelegatingWrapper.kt
index 2370c49..859f6a4 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/PointerInputDelegatingWrapper.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/PointerInputDelegatingWrapper.kt
@@ -40,15 +40,24 @@
pointerPosition: Offset,
hitPointerInputFilters: MutableList<PointerInputFilter>
) {
- if (isPointerInBounds(pointerPosition)) {
+ if (isPointerInBounds(pointerPosition) && withinLayerBounds(pointerPosition)) {
// If the pointer is in bounds, we hit the pointer input filter, so add it!
hitPointerInputFilters.add(modifier.pointerInputFilter)
- }
- // Also, keep looking to see if we also might hit any children.
- super.hitTest(
- pointerPosition,
- hitPointerInputFilters
- )
+ // Also, keep looking to see if we also might hit any children.
+ // This avoids checking layer bounds twice as when we call super.hitTest()
+ val positionInWrapped = wrapped.fromParentPosition(pointerPosition)
+ wrapped.hitTest(positionInWrapped, hitPointerInputFilters)
+ }
}
-}
\ No newline at end of file
+
+ /**
+ * Whether a pointer that is relative to the [LayoutNodeWrapper] is in the bounds of this
+ * LayoutNodeWrapper.
+ */
+ private fun isPointerInBounds(pointerPosition: Offset): Boolean {
+ val x = pointerPosition.x
+ val y = pointerPosition.y
+ return x >= 0f && y >= 0f && x < measuredWidth && y < measuredHeight
+ }
+}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ShapeContainingUtil.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ShapeContainingUtil.kt
new file mode 100644
index 0000000..25b3abb
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ShapeContainingUtil.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2021 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.ui.platform
+
+import androidx.compose.ui.geometry.CornerRadius
+import androidx.compose.ui.graphics.Outline
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.geometry.RoundRect
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.PathOperation
+
+/**
+ * Returns `true` if ([x], [y]) is within [outline]. For some outlines that don't require a [Path],
+ * the exact point is used to calculate whether the point is inside [outline]. When a [Path] is
+ * required, a 0.01 x 0.01 box around ([x], [y]) is used to intersect with the path to determine
+ * the result.
+ *
+ * The [tmpTouchPointPath] and [tmpOpPath] are temporary Paths that are cleared after use and will
+ * be used in the calculation of the intersection. These must be empty when passed as parameters or
+ * can be `null` to allocate locally.
+ */
+internal fun isInOutline(
+ outline: Outline,
+ x: Float,
+ y: Float,
+ tmpTouchPointPath: Path? = null,
+ tmpOpPath: Path? = null
+): Boolean = when (outline) {
+ is Outline.Rectangle -> isInRectangle(outline.rect, x, y)
+ is Outline.Rounded -> isInRoundedRect(outline, x, y, tmpTouchPointPath, tmpOpPath)
+ is Outline.Generic -> isInPath(outline.path, x, y, tmpTouchPointPath, tmpOpPath)
+}
+
+private fun isInRectangle(rect: Rect, x: Float, y: Float) =
+ rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom
+
+/**
+ * Returns `true` if ([x], [y]) is within [outline].
+ */
+private fun isInRoundedRect(
+ outline: Outline.Rounded,
+ x: Float,
+ y: Float,
+ touchPointPath: Path?,
+ opPath: Path?
+): Boolean {
+ val rrect = outline.roundRect
+
+ // first, everything that is outside the rect
+ if (x < rrect.left || x >= rrect.right || y < rrect.top || y >= rrect.bottom) {
+ return false
+ }
+
+ // This algorithm assumes that the corner radius isn't greater than the size of the Rect.
+ // There's a complex algorithm to handle cases beyond that, so we'll fall back to
+ // the Path algorithm to handle it
+ if (!rrect.cornersFit()) {
+ val path = opPath ?: Path()
+ path.addRoundRect(rrect)
+ return isInPath(path, x, y, touchPointPath, opPath)
+ }
+
+ val topLeftX = rrect.left + rrect.topLeftCornerRadius.x
+ val topLeftY = rrect.top + rrect.topLeftCornerRadius.y
+
+ val topRightX = rrect.right - rrect.topRightCornerRadius.x
+ val topRightY = rrect.top + rrect.topRightCornerRadius.y
+
+ val bottomRightX = rrect.right - rrect.bottomRightCornerRadius.x
+ val bottomRightY = rrect.bottom - rrect.bottomRightCornerRadius.y
+
+ val bottomLeftX = rrect.bottom - rrect.bottomLeftCornerRadius.y
+ val bottomLeftY = rrect.left + rrect.bottomLeftCornerRadius.x
+
+ return if (x < topLeftX && y < topLeftY) {
+ // top-left corner
+ isWithinEllipse(x, y, rrect.topLeftCornerRadius, topLeftX, topLeftY)
+ } else if (x < bottomLeftY && y > bottomLeftX) {
+ // bottom-left corner
+ isWithinEllipse(x, y, rrect.bottomLeftCornerRadius, bottomLeftY, bottomLeftX)
+ } else if (x > topRightX && y < topRightY) {
+ // top-right corner
+ isWithinEllipse(x, y, rrect.topRightCornerRadius, topRightX, topRightY)
+ } else if (x > bottomRightX && y > bottomRightY) {
+ // bottom-right corner
+ isWithinEllipse(x, y, rrect.bottomRightCornerRadius, bottomRightX, bottomRightY)
+ } else {
+ true // not at a corner, so it must be inside
+ }
+}
+
+/**
+ * Returns `true` if the rounded rectangle has rounded corners that fit within the sides or
+ * `false` if the rounded sides add up to a greater size that a side.
+ */
+private fun RoundRect.cornersFit() = topLeftCornerRadius.x + topRightCornerRadius.x <= width &&
+ bottomLeftCornerRadius.x + bottomRightCornerRadius.x <= width &&
+ topLeftCornerRadius.y + bottomLeftCornerRadius.y <= height &&
+ topRightCornerRadius.y + bottomRightCornerRadius.y <= height
+
+/**
+ * Used to determine whether a point is within a rounded corner, this returns `true` if the point
+ * ([x], [y]) is within the ellipse centered at ([centerX], [centerY]) with the horizontal and
+ * vertical radii given by [cornerRadius].
+ */
+private fun isWithinEllipse(
+ x: Float,
+ y: Float,
+ cornerRadius: CornerRadius,
+ centerX: Float,
+ centerY: Float
+): Boolean {
+ val px = x - centerX
+ val py = y - centerY
+ val radiusX = cornerRadius.x
+ val radiusY = cornerRadius.y
+ return (px * px) / (radiusX * radiusX) + (py * py) / (radiusY * radiusY) <= 1f
+}
+
+/**
+ * Returns `true` if the 0.01 x 0.01 box around ([x], [y]) has any point with [path].
+ *
+ * The [tmpTouchPointPath] and [tmpOpPath] are temporary Paths that are cleared after use and will
+ * be used in the calculation of the intersection. These must be empty when passed as parameters or
+ * can be `null` to allocate locally.
+ */
+private fun isInPath(
+ path: Path,
+ x: Float,
+ y: Float,
+ tmpTouchPointPath: Path?,
+ tmpOpPath: Path?
+): Boolean {
+ val rect = Rect(x - 0.005f, y - 0.005f, x + 0.005f, y + 0.005f)
+ val touchPointPath = tmpTouchPointPath ?: Path()
+ touchPointPath.addRect(
+ rect
+ )
+
+ val opPath = tmpOpPath ?: Path()
+ opPath.op(path, touchPointPath, PathOperation.Intersect)
+
+ val isClipped = opPath.isEmpty
+ opPath.reset()
+ touchPointPath.reset()
+ return !isClipped
+}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AWTDebounceEventQueue.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AWTDebounceEventQueue.desktop.kt
index ea7a5df..5fdfb29 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AWTDebounceEventQueue.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/desktop/AWTDebounceEventQueue.desktop.kt
@@ -16,6 +16,7 @@
package androidx.compose.desktop
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.Channel
@@ -38,6 +39,7 @@
* Without dispatching events we may have a situation
* when 30 events of scroll block AWT Thread for 1 second, without rerendering content.
*/
+@OptIn(DelicateCoroutinesApi::class)
internal class AWTDebounceEventQueue constructor(
// 4 ms is enough for the user not to see the lags
private val maxNanosToBlockThread: Long = 4_000_000, // 4 milliseconds
@@ -63,6 +65,6 @@
}
fun post(event: () -> Unit) {
- queue.offer(event)
+ queue.trySend(event)
}
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.desktop.kt
index fd87f34..afd95d6 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/GlobalSnapshotManager.desktop.kt
@@ -49,7 +49,7 @@
}
}
Snapshot.registerGlobalWriteObserver {
- channel.offer(Unit)
+ channel.trySend(Unit)
}
}
}
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.desktop.kt
index be64355..899b377 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/platform/SkijaLayer.desktop.kt
@@ -112,6 +112,20 @@
getMatrix(inverse).map(rect)
}
+ override fun isInLayer(position: Offset): Boolean {
+ if (!clip) {
+ return true
+ }
+
+ val x = position.x
+ val y = position.y
+ if (outlineCache.shape === RectangleShape) {
+ return 0f <= x && x < size.width && 0f <= y && y < size.height
+ }
+
+ return isInOutline(outlineCache.outline!!, x, y)
+ }
+
private fun getMatrix(inverse: Boolean): Matrix {
return if (inverse) {
Matrix().apply {
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt
index 7bf3dd9..6c7d385 100644
--- a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/res/DesktopSvgResources.desktop.kt
@@ -30,8 +30,11 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import org.jetbrains.skija.Data
-import org.jetbrains.skija.Point
import org.jetbrains.skija.svg.SVGDOM
+import org.jetbrains.skija.svg.SVGLength
+import org.jetbrains.skija.svg.SVGLengthUnit
+import org.jetbrains.skija.svg.SVGPreserveAspectRatio
+import org.jetbrains.skija.svg.SVGPreserveAspectRatioAlign
import java.io.InputStream
import kotlin.math.ceil
@@ -66,15 +69,18 @@
}
private class SVGPainter(
- private val SVGDOM: SVGDOM,
+ private val dom: SVGDOM,
private val density: Density
) : Painter() {
+ private val root = dom.root
+
private val defaultSizePx: Size = run {
- val containerSize = SVGDOM.containerSize
- if (containerSize.x == 0f && containerSize.y == 0f) {
+ val width = root?.width?.withUnit(SVGLengthUnit.PX)?.value ?: 0f
+ val height = root?.height?.withUnit(SVGLengthUnit.PX)?.value ?: 0f
+ if (width == 0f && height == 0f) {
Size.Unspecified
} else {
- Size(containerSize.x, containerSize.y)
+ Size(width, height)
}
}
@@ -118,9 +124,11 @@
}
private fun DrawScope.drawSvg(size: Size) {
- drawIntoCanvas {
- SVGDOM.containerSize = Point(size.width, size.height)
- SVGDOM.render(it.nativeCanvas)
+ drawIntoCanvas { canvas ->
+ root?.width = SVGLength(size.width, SVGLengthUnit.PX)
+ root?.height = SVGLength(size.height, SVGLengthUnit.PX)
+ root?.preserveAspectRatio = SVGPreserveAspectRatio(SVGPreserveAspectRatioAlign.NONE)
+ dom.render(canvas.nativeCanvas)
}
}
}
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt
similarity index 72%
copy from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
copy to compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt
index 3d934fd..d32a665 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/TestUtils.kt
@@ -14,11 +14,9 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.compose.ui
-import android.app.Activity
-
-/**
- * A test [Activity] for testing purposes.
- */
-public class TestActivity : Activity()
\ No newline at end of file
+private val os = System.getProperty("os.name").lowercase()
+internal val isLinux = os.startsWith("linux")
+internal val isWindows = os.startsWith("win")
+internal val isMacOs = os.startsWith("mac")
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt
index ee37c55..f4cc9bd 100644
--- a/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt
+++ b/compose/ui/ui/src/desktopTest/kotlin/androidx/compose/ui/res/DesktopSvgResourcesTest.kt
@@ -17,15 +17,18 @@
package androidx.compose.ui.res
import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
+import androidx.compose.ui.isLinux
+import androidx.compose.ui.isWindows
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.TestComposeWindow
import androidx.compose.ui.test.junit4.DesktopScreenshotTestRule
import androidx.compose.ui.unit.dp
import org.junit.Assume.assumeTrue
import org.junit.Rule
import org.junit.Test
-import java.util.Locale
class DesktopSvgResourcesTest {
@get:Rule
@@ -33,7 +36,7 @@
@Test
fun `load SVG with specified size`() {
- assumeLinuxOrWindows()
+ assumeTrue(isLinux || isWindows)
val window = TestComposeWindow(width = 200, height = 200)
window.setContent {
@@ -47,9 +50,9 @@
@Test
fun `load SVG with unspecified size`() {
- assumeLinuxOrWindows()
+ assumeTrue(isLinux || isWindows)
- val window = TestComposeWindow(width = 200, height = 300)
+ val window = TestComposeWindow(width = 200, height = 200)
window.setContent {
Image(
svgResource("androidx/compose/ui/res/star-size-unspecified.svg"),
@@ -60,13 +63,27 @@
}
@Test
- fun `load SVG with custom size`() {
- assumeLinuxOrWindows()
+ fun `load SVG with unspecified viewbox`() {
+ assumeTrue(isLinux || isWindows)
val window = TestComposeWindow(width = 200, height = 200)
window.setContent {
Image(
- svgResource("androidx/compose/ui/res/star-size-unspecified.svg"),
+ svgResource("androidx/compose/ui/res/star-viewbox-unspecified.svg"),
+ contentDescription = "Star"
+ )
+ }
+ screenshotRule.snap(window.surface)
+ }
+
+ @Test
+ fun `load SVG with custom size`() {
+ assumeTrue(isLinux || isWindows)
+
+ val window = TestComposeWindow(width = 200, height = 200)
+ window.setContent {
+ Image(
+ svgResource("androidx/compose/ui/res/star-size-100.svg"),
contentDescription = "Star",
modifier = Modifier.size(50.dp)
)
@@ -74,8 +91,19 @@
screenshotRule.snap(window.surface)
}
- private fun assumeLinuxOrWindows() {
- val os = System.getProperty("os.name").lowercase(Locale.US)
- assumeTrue(os.startsWith("linux") || os.startsWith("win"))
+ @Test
+ fun `load SVG and fill bounds`() {
+ assumeTrue(isLinux || isWindows)
+
+ val window = TestComposeWindow(width = 200, height = 300)
+ window.setContent {
+ Image(
+ svgResource("androidx/compose/ui/res/star-size-100.svg"),
+ contentDescription = "Star",
+ contentScale = ContentScale.FillBounds,
+ modifier = Modifier.fillMaxSize()
+ )
+ }
+ screenshotRule.snap(window.surface)
}
}
\ No newline at end of file
diff --git a/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg b/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg
new file mode 100644
index 0000000..946a744
--- /dev/null
+++ b/compose/ui/ui/src/desktopTest/resources/androidx/compose/ui/res/star-viewbox-unspecified.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns="http://www.w3.org/2000/svg" width="100" height="100" version="1.1"
+ id="svg8">
+ <defs
+ id="defs2" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(0,-197)"
+ id="layer1">
+ <path
+ id="path3703"
+ d="M 50.000001,197 59.567086,223.90301 85.35534,211.64466 73.096987,237.43292 100,247 73.096986,256.56709 85.355338,282.35534 59.567084,270.09699 49.999999,297 40.432914,270.09699 14.64466,282.35534 26.903013,256.56708 0,247 26.903014,237.43291 14.644662,211.64466 40.432916,223.90301 Z"
+ style="fill:#ff5555;stroke-width:0.21590135" />
+ </g>
+</svg>
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index 4206975..e37273a 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -1853,6 +1853,8 @@
) {
}
+ override fun isInLayer(position: Offset) = true
+
override fun move(position: IntOffset) {
}
diff --git a/concurrent/futures-ktx/src/test/java/androidx/concurrent/futures/ListenableFutureTest.kt b/concurrent/futures-ktx/src/test/java/androidx/concurrent/futures/ListenableFutureTest.kt
index 562b8a0..27f7bcd 100644
--- a/concurrent/futures-ktx/src/test/java/androidx/concurrent/futures/ListenableFutureTest.kt
+++ b/concurrent/futures-ktx/src/test/java/androidx/concurrent/futures/ListenableFutureTest.kt
@@ -20,6 +20,7 @@
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
@@ -37,6 +38,7 @@
import kotlin.test.assertFailsWith
@RunWith(JUnit4::class)
+@OptIn(DelicateCoroutinesApi::class)
class ListenableFutureTest {
private var actionIndex = AtomicInteger()
private var finished = AtomicBoolean()
diff --git a/coordinatorlayout/coordinatorlayout/build.gradle b/coordinatorlayout/coordinatorlayout/build.gradle
index 8acc494..569b8bf 100644
--- a/coordinatorlayout/coordinatorlayout/build.gradle
+++ b/coordinatorlayout/coordinatorlayout/build.gradle
@@ -1,6 +1,4 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
@@ -14,14 +12,14 @@
implementation("androidx.collection:collection:1.0.0")
api("androidx.customview:customview:1.0.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(ESPRESSO_CONTRIB, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.espressoContrib, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-runtime"), {
exclude group: "androidx.coordinatorlayout", module: "coordinatorlayout"
})
diff --git a/coordinatorlayout/coordinatorlayout/src/androidTest/java/androidx/coordinatorlayout/widget/CoordinatorSnackbarWithButtonTest.java b/coordinatorlayout/coordinatorlayout/src/androidTest/java/androidx/coordinatorlayout/widget/CoordinatorSnackbarWithButtonTest.java
index 01d5bd8..203ba8b 100644
--- a/coordinatorlayout/coordinatorlayout/src/androidTest/java/androidx/coordinatorlayout/widget/CoordinatorSnackbarWithButtonTest.java
+++ b/coordinatorlayout/coordinatorlayout/src/androidTest/java/androidx/coordinatorlayout/widget/CoordinatorSnackbarWithButtonTest.java
@@ -35,6 +35,7 @@
import androidx.test.annotation.UiThreadTest;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.hamcrest.Matcher;
@@ -116,6 +117,7 @@
}
}
+ @FlakyTest(bugId = 190609153)
@Test
public void testBehaviorBasedSlidingFromLayoutAttribute() {
// Use a layout in which a TextView child has Behavior object configured via
diff --git a/core/core-animation-integration-tests/testapp/build.gradle b/core/core-animation-integration-tests/testapp/build.gradle
index f1a3103..47cab8d 100644
--- a/core/core-animation-integration-tests/testapp/build.gradle
+++ b/core/core-animation-integration-tests/testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -27,7 +25,7 @@
implementation(project(":core:core-animation"))
implementation(project(":core:core-animation-testing"))
- implementation(ANDROIDX_TEST_EXT_JUNIT, excludes.espresso)
- implementation(ANDROIDX_TEST_CORE, excludes.espresso)
- implementation(ANDROIDX_TEST_RULES, excludes.espresso)
+ implementation(libs.testExtJunit, excludes.espresso)
+ implementation(libs.testCore, excludes.espresso)
+ implementation(libs.testRules, excludes.espresso)
}
diff --git a/core/core-animation-testing/build.gradle b/core/core-animation-testing/build.gradle
index 0adb553..88bbec3 100644
--- a/core/core-animation-testing/build.gradle
+++ b/core/core-animation-testing/build.gradle
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -28,8 +27,8 @@
api("androidx.annotation:annotation:1.1.0")
implementation("androidx.core:core:1.3.1")
implementation(project(":core:core-animation"))
- implementation(ANDROIDX_TEST_EXT_JUNIT)
- implementation(ANDROIDX_TEST_CORE)
+ implementation(libs.testExtJunit)
+ implementation(libs.testCore)
}
androidx {
diff --git a/core/core-animation/build.gradle b/core/core-animation/build.gradle
index d963b61..103b2d3 100644
--- a/core/core-animation/build.gradle
+++ b/core/core-animation/build.gradle
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -29,8 +28,8 @@
implementation("androidx.core:core:1.3.1")
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT, excludes.espresso)
- androidTestImplementation(ANDROIDX_TEST_RULES, excludes.espresso)
+ androidTestImplementation(libs.testExtJunit, excludes.espresso)
+ androidTestImplementation(libs.testRules, excludes.espresso)
}
androidx {
diff --git a/core/core-ktx/build.gradle b/core/core-ktx/build.gradle
index 3a4be30..9c96d97 100644
--- a/core/core-ktx/build.gradle
+++ b/core/core-ktx/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -10,16 +9,16 @@
}
dependencies {
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
api("androidx.annotation:annotation:1.1.0")
api(project(":core:core"))
- androidTestImplementation(JUNIT)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.truth)
androidTestImplementation(project(":internal-testutils-truth"))
}
diff --git a/core/core-role/build.gradle b/core/core-role/build.gradle
index b2ac038..2b28cf1 100644
--- a/core/core-role/build.gradle
+++ b/core/core-role/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -9,11 +8,11 @@
}
dependencies {
- annotationProcessor(NULLAWAY)
+ annotationProcessor(libs.nullaway)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
}
androidx {
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 6f6ac82..9daf595 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -988,8 +988,12 @@
}
public final class IntentCompat {
+ method public static boolean areUnusedAppRestrictionsAllowlisted(android.content.Context);
+ method public static boolean areUnusedAppRestrictionsAvailable(android.content.Context);
+ method public static android.content.Intent makeIntentToAllowlistUnusedAppRestrictions(android.content.Context, String);
method public static android.content.Intent makeMainSelectorActivity(String, String);
field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index c70a4319..3ab1f4d 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -988,8 +988,12 @@
}
public final class IntentCompat {
+ method public static boolean areUnusedAppRestrictionsAllowlisted(android.content.Context);
+ method public static boolean areUnusedAppRestrictionsAvailable(android.content.Context);
+ method public static android.content.Intent makeIntentToAllowlistUnusedAppRestrictions(android.content.Context, String);
method public static android.content.Intent makeMainSelectorActivity(String, String);
field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 8b57a96..7b2d5de 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -1091,8 +1091,12 @@
}
public final class IntentCompat {
+ method public static boolean areUnusedAppRestrictionsAllowlisted(android.content.Context);
+ method public static boolean areUnusedAppRestrictionsAvailable(android.content.Context);
+ method public static android.content.Intent makeIntentToAllowlistUnusedAppRestrictions(android.content.Context, String);
method public static android.content.Intent makeMainSelectorActivity(String, String);
field public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
+ field public static final String ACTION_UNUSED_APP_RESTRICTIONS = "android.intent.action.AUTO_REVOKE_PERMISSIONS";
field public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
field public static final String EXTRA_HTML_TEXT = "android.intent.extra.HTML_TEXT";
field public static final String EXTRA_START_PLAYBACK = "android.intent.extra.START_PLAYBACK";
diff --git a/core/core/build.gradle b/core/core/build.gradle
index ed910f4..fe66457 100644
--- a/core/core/build.gradle
+++ b/core/core/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -17,26 +16,27 @@
implementation("androidx.collection:collection:1.0.0")
// Required for -Werror due to annotation-experimental use of Kotlin
- compileOnly(KOTLIN_STDLIB)
+ compileOnly(libs.kotlinStdlib)
// We don't ship this as a public artifact, so it must remain a project-type dependency.
annotationProcessor(project(":versionedparcelable:versionedparcelable-compiler"))
- androidTestImplementation(KOTLIN_STDLIB)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(TRUTH)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(MULTIDEX)
+ androidTestImplementation("junit:junit:4.13")
+ androidTestImplementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.multidex)
// Including both dexmakers allows support for all API levels plus final mocking support on
// API 28+. The implementation is swapped based on the finality of the mock type. This
// delegation is handled manually inside androidx.core.util.mockito.CustomMockMaker.
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO_INLINE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockitoInline, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation("androidx.appcompat:appcompat:1.1.0") {
exclude group: "androidx.core", module: "core"
}
@@ -45,10 +45,11 @@
})
androidTestImplementation(project(":internal-testutils-mockito"))
- testImplementation(ANDROIDX_TEST_CORE)
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(TRUTH)
- testImplementation(ROBOLECTRIC)
+ testImplementation("junit:junit:4.13")
+ testImplementation(libs.testCore)
+ testImplementation(libs.testRunner)
+ testImplementation(libs.truth)
+ testImplementation(libs.robolectric)
}
android {
diff --git a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
index 3bc7c00..53eebef 100644
--- a/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/app/NotificationCompatTest.java
@@ -65,6 +65,7 @@
import androidx.core.content.pm.ShortcutInfoCompat;
import androidx.core.graphics.drawable.IconCompat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
@@ -227,6 +228,7 @@
assertEquals("testSubText", NotificationCompat.getSubText(n));
}
+ @FlakyTest(bugId = 190533219)
@Test
public void testActions() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext);
@@ -555,6 +557,7 @@
assertNotificationEquals(original, recovered);
}
+ @FlakyTest(bugId = 190533219)
@Test
public void testNotificationBuilder_createContentView() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext, "channelId");
diff --git a/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java
new file mode 100644
index 0000000..355a92f
--- /dev/null
+++ b/core/core/src/androidTest/java/androidx/core/content/IntentCompatTest.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2021 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.core.content;
+
+import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
+import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
+import static android.os.Build.VERSION_CODES.LOLLIPOP;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.Q;
+import static android.os.Build.VERSION_CODES.R;
+import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SdkSuppress;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+/** Tests for {@link IntentCompat}. */
+public class IntentCompatTest {
+
+ private Context mContext;
+ private PackageManager mPackageManager = mock(PackageManager.class);
+ private static final String SYSTEM_APP_PACKAGE_NAME = "system.app";
+
+ @Before
+ public void setUp() {
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = ICE_CREAM_SANDWICH)
+ public void makeMainSelectorActivity_preApi14() {
+ String selectorAction = Intent.ACTION_MAIN;
+ String selectorCategory = Intent.CATEGORY_APP_BROWSER;
+
+ Intent activityIntent = IntentCompat.makeMainSelectorActivity(selectorAction,
+ selectorCategory);
+
+ assertThat(activityIntent.getAction()).isEqualTo(selectorAction);
+ assertThat(activityIntent.getCategories()).containsExactly(selectorCategory);
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = ICE_CREAM_SANDWICH_MR1)
+ public void makeMainSelectorActivity() {
+ String selectorAction = Intent.ACTION_MAIN;
+ String selectorCategory = Intent.CATEGORY_APP_BROWSER;
+
+ Intent activityIntent = IntentCompat.makeMainSelectorActivity(selectorAction,
+ selectorCategory);
+
+ Intent expectedIntent = Intent.makeMainSelectorActivity(selectorAction,
+ selectorCategory);
+ assertThat(activityIntent.filterEquals(expectedIntent)).isTrue();
+ }
+
+ @Test
+ // TODO: replace with VERSION_CODES.S once it's defined
+ @SdkSuppress(minSdkVersion = 31)
+ public void makeIntentToAllowlistUnusedAppRestrictions_api31Plus() {
+ String packageName = "package.name";
+ Intent activityIntent = IntentCompat.makeIntentToAllowlistUnusedAppRestrictions(
+ mContext, packageName);
+
+ assertThat(activityIntent.getAction()).isEqualTo(ACTION_APPLICATION_DETAILS_SETTINGS);
+ assertThat(activityIntent.getData()).isEqualTo(Uri.parse(packageName));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = R, maxSdkVersion = R)
+ public void makeIntentToAllowlistUnusedAppRestrictions_api30() {
+ String packageName = "package.name";
+ Intent activityIntent = IntentCompat.makeIntentToAllowlistUnusedAppRestrictions(
+ mContext, packageName);
+
+ assertThat(activityIntent.getAction())
+ .isEqualTo("android.intent.action.AUTO_REVOKE_PERMISSIONS");
+ assertThat(activityIntent.getData()).isEqualTo(Uri.parse(packageName));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = M, maxSdkVersion = Q)
+ public void makeIntentToAllowlistUnusedAppRestrictions_preApi30_revocationSystemAppNotExists() {
+ // Don't install a system app that can resolve the permission auto-revocation intent
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> IntentCompat.makeIntentToAllowlistUnusedAppRestrictions(
+ mContext, "package.name"));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = M, maxSdkVersion = Q)
+ public void makeIntentToAllowlistUnusedAppRestrictions_preApi30_revocationSystemAppExists() {
+ setupPermissionRevocationSystemApp(SYSTEM_APP_PACKAGE_NAME);
+ Intent activityIntent = IntentCompat.makeIntentToAllowlistUnusedAppRestrictions(
+ mContext, "package.name");
+
+ assertThat(activityIntent.getAction()).isEqualTo(
+ "android.intent.action.AUTO_REVOKE_PERMISSIONS");
+ assertThat(activityIntent.getPackage()).isEqualTo(SYSTEM_APP_PACKAGE_NAME);
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = LOLLIPOP)
+ public void makeIntentToAllowlistUnusedAppRestrictions_preApi23() {
+ assertThrows(UnsupportedOperationException.class,
+ () -> IntentCompat.makeIntentToAllowlistUnusedAppRestrictions(
+ mContext, "package.name"));
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = R)
+ public void areUnusedAppRestrictionsAvailable_api30Plus_returnsTrue() {
+ assertThat(IntentCompat.areUnusedAppRestrictionsAvailable(mContext)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = M, maxSdkVersion = Q)
+ public void areUnusedAppRestrictionsAvailable_preApi30_noRevocationSystemApps_returnsFalse() {
+ // Don't install a system app that can resolve the permission auto-revocation intent
+
+ assertThat(IntentCompat.areUnusedAppRestrictionsAvailable(mContext)).isFalse();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = M, maxSdkVersion = Q)
+ public void areUnusedAppRestrictionsAvailable_preApi30_revocationSystemApp_returnsTrue() {
+ setupPermissionRevocationSystemApp(SYSTEM_APP_PACKAGE_NAME);
+
+ assertThat(IntentCompat.areUnusedAppRestrictionsAvailable(mContext)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = LOLLIPOP)
+ public void areUnusedAppRestrictionsAvailable_preApi23_returnsFalse() {
+ assertThat(IntentCompat.areUnusedAppRestrictionsAvailable(mContext)).isFalse();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = R)
+ public void areUnusedAppRestrictionsAllowlisted_api30Plus_returnsPackageManagerAllowlisted() {
+ when(mPackageManager.isAutoRevokeWhitelisted()).thenReturn(true);
+
+ assertThat(IntentCompat.areUnusedAppRestrictionsAllowlisted(mContext)).isTrue();
+ }
+
+ @Test
+ @SdkSuppress(minSdkVersion = M, maxSdkVersion = Q)
+ public void areUnusedAppRestrictionsAllowlisted_preApi30_returnsFalse() {
+ assertThat(IntentCompat.areUnusedAppRestrictionsAllowlisted(mContext)).isFalse();
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = LOLLIPOP)
+ public void areUnusedAppRestrictionsAllowlisted_preApi23_returnsFalse() {
+ assertThat(IntentCompat.areUnusedAppRestrictionsAllowlisted(mContext)).isFalse();
+ }
+
+ /**
+ * Setup an application that can handle unused app restriction features. In this case, this is
+ * a permission revocation system app.
+ */
+ private void setupPermissionRevocationSystemApp(String packageName) {
+ ApplicationInfo appInfo = new ApplicationInfo();
+ appInfo.uid = 12345;
+ appInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+ appInfo.packageName = packageName;
+
+ ActivityInfo activityInfo = new ActivityInfo();
+ activityInfo.packageName = packageName;
+ activityInfo.name = "Name needed to keep toString() happy :)";
+ activityInfo.applicationInfo = appInfo;
+
+ ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.activityInfo = activityInfo;
+ resolveInfo.providerInfo = new ProviderInfo();
+ resolveInfo.providerInfo.name = "Name needed to keep toString() happy :)";
+
+ // Mark the application as being able to resolve the intent
+ when(mPackageManager.queryIntentActivities(
+ nullable(Intent.class), eq(PackageManager.MATCH_SYSTEM_ONLY)))
+ .thenReturn(Arrays.asList(resolveInfo));
+ }
+}
diff --git a/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
index 83f26de..affaea7 100644
--- a/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/res/ResourcesCompatTest.java
@@ -39,6 +39,7 @@
import androidx.core.provider.MockFontProvider;
import androidx.core.test.R;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -452,6 +453,7 @@
assertSame(font, font2);
}
+ @FlakyTest(bugId = 190534138)
@Test
public void testSystemFontFamilyReturnsSystemFont() {
Typeface typeface = ResourcesCompat.getFont(mContext, R.font.samplexmldownloadedfont);
diff --git a/core/core/src/androidTest/java/androidx/core/view/ContentInfoCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/ContentInfoCompatTest.java
index 15b5fa7..74dd573 100644
--- a/core/core/src/androidTest/java/androidx/core/view/ContentInfoCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/ContentInfoCompatTest.java
@@ -40,7 +40,7 @@
public void testPartition_multipleItems() throws Exception {
Uri sampleUri = Uri.parse("content://com.example/path");
ClipData clip = ClipData.newPlainText("", "Hello");
- clip.addItem(new ClipData.Item("Hi", "<b>Salut</b>"));
+ clip.addItem(new ClipData.Item("Hi"));
clip.addItem(new ClipData.Item(sampleUri));
ContentInfoCompat payload = new ContentInfoCompat.Builder(clip, SOURCE_CLIPBOARD)
.setFlags(ContentInfoCompat.FLAG_CONVERT_TO_PLAIN_TEXT)
diff --git a/core/core/src/androidTest/java/androidx/core/view/ViewCompatTest.java b/core/core/src/androidTest/java/androidx/core/view/ViewCompatTest.java
index 3bd4559..47cb5a7 100644
--- a/core/core/src/androidTest/java/androidx/core/view/ViewCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/ViewCompatTest.java
@@ -50,6 +50,7 @@
import androidx.core.test.R;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
@@ -88,6 +89,7 @@
assertEquals("RTL constants", View.LAYOUT_DIRECTION_RTL, ViewCompat.LAYOUT_DIRECTION_RTL);
}
+ @FlakyTest(bugId = 190537195)
@Test
public void testGetDisplay() {
final Display display = ViewCompat.getDisplay(mView);
diff --git a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
index 4f40563..6c9cb39 100644
--- a/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/view/WindowInsetsControllerCompatActivityTest.kt
@@ -31,6 +31,7 @@
import androidx.test.espresso.matcher.ViewMatchers.assertThat
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.filters.SdkSuppress
import androidx.testutils.withActivity
@@ -83,6 +84,7 @@
/**
* IME visibility is only reliable on API 23+, where we have access to the root WindowInsets
*/
+ @FlakyTest(bugId = 190537405)
@SdkSuppress(minSdkVersion = 23)
@Test
public fun toggleIME() {
diff --git a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
index ffdde65..10a341e 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
+++ b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewNestedScrollingFlingVelocityTest.kt
@@ -24,6 +24,7 @@
import android.widget.FrameLayout
import androidx.core.view.NestedScrollingParent3
import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.closeTo
@@ -83,6 +84,7 @@
testContentView.awaitLayouts(2)
}
+ @FlakyTest(bugId = 190538334)
@Test
fun uiFingerFling_flingVelocityIsCorrect() {
diff --git a/core/core/src/main/java/androidx/core/content/IntentCompat.java b/core/core/src/main/java/androidx/core/content/IntentCompat.java
index 0dbc0c0..0da1d586 100644
--- a/core/core/src/main/java/androidx/core/content/IntentCompat.java
+++ b/core/core/src/main/java/androidx/core/content/IntentCompat.java
@@ -16,11 +16,20 @@
package androidx.core.content;
+import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
+
import android.annotation.SuppressLint;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import java.util.List;
/**
* Helper for accessing features in {@link android.content.Intent}.
@@ -50,6 +59,14 @@
public static final String ACTION_CREATE_REMINDER = "android.intent.action.CREATE_REMINDER";
/**
+ * Activity action: creates an intent to redirect the user to UI to turn on/off their
+ * unused app restriction settings.
+ */
+ @SuppressLint("ActionValue")
+ public static final String ACTION_UNUSED_APP_RESTRICTIONS =
+ "android.intent.action.AUTO_REVOKE_PERMISSIONS";
+
+ /**
* A constant String that is associated with the Intent, used with
* {@link android.content.Intent#ACTION_SEND} to supply an alternative to
* {@link android.content.Intent#EXTRA_TEXT}
@@ -115,4 +132,146 @@
return intent;
}
}
+
+ /**
+ * Make an Intent to redirect the user to UI to turn on/off their unused app restriction
+ * settings for a particular app (e.g. permission revocation, app hibernation).
+ *
+ * Note: developers must first call {@link #areUnusedAppRestrictionsAvailable} to make sure
+ * that unused app restriction features are available on the device before attempting to create
+ * an intent using this method.
+ *
+ * Compatibility behavior:
+ * <ul>
+ * <li>SDK 31 and above, this method generates an intent with action {@code Intent
+ * .ACTION_APPLICATION_DETAILS_SETTINGS} and {@code packageName} as data.
+ * <li>SDK 30, this method generates an intent with action {@code Intent
+ * .ACTION_AUTO_REVOKE_PERMISSIONS} and {@code packageName} as data.
+ * <li>SDK 23 through 29, if {@link #areUnusedAppRestrictionsAvailable} returns true,
+ * this method will generate an intent with action {@code Intent
+ * .ACTION_AUTO_REVOKE_PERMISSIONS} and the package as the first system app that can
+ * resolve the intent. Otherwise, this method will throw an
+ * {@link UnsupportedOperationException}.
+ * <li>SDK 22 and below, this method will throw an {@link UnsupportedOperationException}
+ * </ul>
+ *
+ * @param context The {@link Context} of the calling application.
+ * @param packageName The package name of the calling application.
+ *
+ * @return Returns a newly created Intent that can be used to launch an activity where users
+ * can enable and disable unused app restrictions for a specific app.
+ */
+ @NonNull
+ public static Intent makeIntentToAllowlistUnusedAppRestrictions(@NonNull Context context,
+ @NonNull String packageName) {
+ if (!areUnusedAppRestrictionsAvailable(context)) {
+ throw new UnsupportedOperationException(
+ "Unused App Restrictions are not available on this device");
+ }
+
+ // If the OS version is S+, generate the intent using the Application Details Settings
+ // intent action to support compatibility with the App Hibernation feature
+ // TODO: replace with VERSION_CODES.S once it's defined
+ if (Build.VERSION.SDK_INT >= 31) {
+ return new Intent(ACTION_APPLICATION_DETAILS_SETTINGS)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK).setData(Uri.parse(packageName));
+ }
+
+ Intent unusedAppRestrictionsIntent =
+ new Intent(ACTION_UNUSED_APP_RESTRICTIONS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // If the OS version is R, then just add the package name to the intent.
+ // No need to add any other data or flags, since we're relying on the Android R system
+ // feature.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ return unusedAppRestrictionsIntent.setData(Uri.parse(packageName));
+ } else {
+ PackageManager packageManager = context.getPackageManager();
+ // Only allow system apps to resolve the intent.
+ String intentResolverName =
+ packageManager.queryIntentActivities(
+ unusedAppRestrictionsIntent, PackageManager.MATCH_SYSTEM_ONLY)
+ .get(0).activityInfo.packageName;
+ unusedAppRestrictionsIntent.setPackage(intentResolverName);
+ return unusedAppRestrictionsIntent;
+ }
+ }
+
+ /**
+ * Checks to see whether unused app restrictions (e.g. permission revocation, app hibernation)
+ * are available on this device.
+ *
+ * Compatibility behavior:
+ * <ul>
+ * <li>SDK 30 and above, this method always returns {@code true} as unused app restrictions
+ * are built into the Android OS.
+ * <li>SDK 23 through 29, this method checks for a system app that can resolve the {@code
+ * Intent.ACTION_AUTO_REVOKE_PERMISSIONS} intent.
+ * <li>SDK 22 and below, this method always returns {@code false} as runtime permissions did
+ * not exist yet.
+ * </ul>
+ *
+ * @param context The {@link Context} of the calling application.
+ *
+ * @return Returns a boolean indicating whether permission auto-revocation is available on
+ * the device, whether through the Android Operating System or a system app.
+ */
+ public static boolean areUnusedAppRestrictionsAvailable(@NonNull Context context) {
+ // Return false if the Android OS version is before M, because Android M introduced runtime
+ // permissions
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false;
+
+ // Check that the Android OS version is R+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) return true;
+
+ // Else, check for a system app that can resolve the intent
+ PackageManager packageManager = context.getPackageManager();
+ // Alternatively, check if there's another system app that can resolve the intent.
+ List<ResolveInfo> intentResolvers =
+ packageManager.queryIntentActivities(
+ new Intent(ACTION_UNUSED_APP_RESTRICTIONS),
+ PackageManager.MATCH_SYSTEM_ONLY);
+ return !intentResolvers.isEmpty();
+ }
+
+ /**
+ * Checks whether an application is exempt from unused app restrictions (e.g. permission
+ * revocation, app hibernation).
+ *
+ * Compatibility behavior:
+ * <ul>
+ * <li>SDK 30 and above, this method returns the value of {@code PackageManager
+ * .isAutoRevokeWhitelisted}
+ * <li>SDK 23 through 29, this method returns {@code false}.
+ * <li>SDK 22 and below, this method always returns {@code false} as runtime
+ * permissions did not exist yet.
+ * </ul>
+ */
+ public static boolean areUnusedAppRestrictionsAllowlisted(@NonNull Context context) {
+ // Return false if the Android OS version is before M, because Android M introduced runtime
+ // permissions
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return false;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ return Api30Impl.areUnusedAppRestrictionsAllowlisted(context);
+ }
+
+ // TODO(b/177234481): Implement the backport behavior of this API
+ return false;
+ }
+
+ /**
+ * We create this static class to avoid Class Verification Failures from referencing a method
+ * only added in Android R.
+ *
+ * <p>Gating references on SDK checks does not address class verification failures, hence the
+ * need for this inner class.
+ */
+ @RequiresApi(Build.VERSION_CODES.R)
+ private static class Api30Impl {
+ private Api30Impl() {}
+ static boolean areUnusedAppRestrictionsAllowlisted(@NonNull Context context) {
+ return context.getPackageManager().isAutoRevokeWhitelisted();
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
index 74c875b..ce65b9d 100644
--- a/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/content/pm/ShortcutInfoCompat.java
@@ -879,7 +879,6 @@
/**
* Creates a {@link ShortcutInfoCompat} instance.
*/
- @SuppressLint("UnsafeNewApiCall")
@NonNull
public ShortcutInfoCompat build() {
// Verify the arguments
diff --git a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
index 304d94d..379701b 100644
--- a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
@@ -19,7 +19,6 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Typeface;
@@ -43,7 +42,6 @@
/**
* Helper for accessing features in {@link Typeface}.
*/
-@SuppressLint("NewApi") // TODO: Remove this suppression once Q SDK is released.
public class TypefaceCompat {
private static final TypefaceCompatBaseImpl sTypefaceCompatImpl;
static {
diff --git a/core/core/src/main/java/androidx/core/provider/FontProvider.java b/core/core/src/main/java/androidx/core/provider/FontProvider.java
index 5a1e691..d6d4da3 100644
--- a/core/core/src/main/java/androidx/core/provider/FontProvider.java
+++ b/core/core/src/main/java/androidx/core/provider/FontProvider.java
@@ -109,7 +109,6 @@
* Do not access directly, visible for testing only.
* @return
*/
- @SuppressWarnings("UnsafeNewApiCall")
@VisibleForTesting
@NonNull
static FontInfo[] query(
diff --git a/core/core/src/main/java/androidx/core/text/PrecomputedTextCompat.java b/core/core/src/main/java/androidx/core/text/PrecomputedTextCompat.java
index 90d69e4..94cb19a 100644
--- a/core/core/src/main/java/androidx/core/text/PrecomputedTextCompat.java
+++ b/core/core/src/main/java/androidx/core/text/PrecomputedTextCompat.java
@@ -18,7 +18,6 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import android.annotation.SuppressLint;
import android.os.Build;
import android.text.Layout;
import android.text.PrecomputedText;
@@ -192,7 +191,6 @@
}
}
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
Params(@NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir,
int strategy, int frequency) {
if (Build.VERSION.SDK_INT >= 29) {
@@ -427,7 +425,6 @@
* @param params parameters that define how text will be precomputed
* @return A {@link PrecomputedText}
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
public static PrecomputedTextCompat create(@NonNull CharSequence text, @NonNull Params params) {
Preconditions.checkNotNull(text);
Preconditions.checkNotNull(params);
@@ -526,7 +523,6 @@
/**
* Returns the count of paragraphs.
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
public @IntRange(from = 0) int getParagraphCount() {
if (Build.VERSION.SDK_INT >= 29) {
return mWrapped.getParagraphCount();
@@ -538,7 +534,6 @@
/**
* Returns the paragraph start offset of the text.
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
public @IntRange(from = 0) int getParagraphStart(@IntRange(from = 0) int paraIndex) {
Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
if (Build.VERSION.SDK_INT >= 29) {
@@ -551,7 +546,6 @@
/**
* Returns the paragraph end offset of the text.
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
public @IntRange(from = 0) int getParagraphEnd(@IntRange(from = 0) int paraIndex) {
Preconditions.checkArgumentInRange(paraIndex, 0, getParagraphCount(), "paraIndex");
if (Build.VERSION.SDK_INT >= 29) {
@@ -672,7 +666,6 @@
/**
* @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified.
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
@Override
public void setSpan(Object what, int start, int end, int flags) {
if (what instanceof MetricAffectingSpan) {
@@ -689,7 +682,6 @@
/**
* @throws IllegalArgumentException if {@link MetricAffectingSpan} is specified.
*/
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
@Override
public void removeSpan(Object what) {
if (what instanceof MetricAffectingSpan) {
@@ -708,7 +700,6 @@
//
// Just proxy for underlying mText if appropriate.
- @SuppressLint("NewApi") // TODO: Remove once Q SDK is released
@Override
public <T> T[] getSpans(int start, int end, Class<T> type) {
if (Build.VERSION.SDK_INT >= 29) {
diff --git a/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java b/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
index 493c688..e225630 100644
--- a/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
+++ b/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
@@ -18,7 +18,6 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
-import android.annotation.SuppressLint;
import android.os.Build;
import android.text.Spannable;
import android.text.SpannableString;
@@ -252,7 +251,6 @@
* over which pattern matches are to be converted into links.
* @param transformFilter Filter to allow the client code to update the link found.
*/
- @SuppressLint("NewApi")
public static void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
@Nullable String defaultScheme, @Nullable String[] schemes,
@Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
@@ -328,7 +326,6 @@
*
* @return True if at least one link is found and applied.
*/
- @SuppressLint("NewApi")
public static boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
@Nullable String defaultScheme, @Nullable String[] schemes,
@Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
diff --git a/core/core/src/main/java/androidx/core/view/MenuCompat.java b/core/core/src/main/java/androidx/core/view/MenuCompat.java
index 8292a95..3512c11 100644
--- a/core/core/src/main/java/androidx/core/view/MenuCompat.java
+++ b/core/core/src/main/java/androidx/core/view/MenuCompat.java
@@ -16,7 +16,6 @@
package androidx.core.view;
-import android.annotation.SuppressLint;
import android.os.Build;
import android.view.Menu;
import android.view.MenuItem;
@@ -43,7 +42,6 @@
* @param menu Menu to enable/disable dividers on.
* @param enabled True if enabled
*/
- @SuppressLint("NewApi")
public static void setGroupDividerEnabled(Menu menu, boolean enabled) {
if (menu instanceof SupportMenu) {
((SupportMenu) menu).setGroupDividerEnabled(enabled);
diff --git a/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt b/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt
index 8f7d54a..4f1ed0b 100644
--- a/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt
+++ b/datastore/datastore-core/src/main/java/androidx/datastore/core/SimpleActor.kt
@@ -20,6 +20,8 @@
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
+import kotlinx.coroutines.channels.ClosedSendChannelException
+import kotlinx.coroutines.channels.onClosed
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import java.util.concurrent.atomic.AtomicInteger
@@ -64,19 +66,10 @@
messageQueue.close(ex)
- var msg = try {
- messageQueue.poll()
- } catch (rethrownEx: Throwable) {
- return@invokeOnCompletion
- }
-
- while (msg != null) {
- onUndeliveredElement(msg, ex)
- try {
- msg = messageQueue.poll()
- } catch (rethrownEx: Throwable) {
- return@invokeOnCompletion
- }
+ while (true) {
+ messageQueue.tryReceive().getOrNull()?.let { msg ->
+ onUndeliveredElement(msg, ex)
+ } ?: break
}
}
}
@@ -107,7 +100,11 @@
*/
// should never return false bc the channel capacity is unlimited
- check(messageQueue.offer(msg))
+ check(
+ messageQueue.trySend(msg)
+ .onClosed { throw it ?: ClosedSendChannelException("Channel was closed normally") }
+ .isSuccess
+ )
// If the number of remaining messages was 0, there is no active consumer, since it quits
// consuming once remaining messages hits 0. We must kick off a new consumer.
diff --git a/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreStressTest.kt b/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreStressTest.kt
index d8f25c3..dcefa82 100644
--- a/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreStressTest.kt
+++ b/datastore/datastore-core/src/test/java/androidx/datastore/core/SingleProcessDataStoreStressTest.kt
@@ -44,6 +44,7 @@
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import kotlin.time.ExperimentalTime
+import kotlin.time.seconds
@RunWith(JUnit4::class)
@ExperimentalTime
@@ -97,7 +98,8 @@
// There's no reason this should take more than a few seconds once writers complete and
// there's no reason writers won't complete.
- withTimeout(10000L) {
+ @Suppress("DEPRECATION")
+ withTimeout(10.seconds) {
readers.awaitAll()
}
}
@@ -161,7 +163,8 @@
// There's no reason this should take more than a few seconds once writers complete and
// there's no reason writers won't complete.
- withTimeout(10000L) {
+ @Suppress("DEPRECATION")
+ withTimeout(10.seconds) {
readers.awaitAll()
}
}
@@ -221,7 +224,8 @@
// There's no reason this should take more than a few seconds once writers complete and
// there's no reason writers won't complete.
- withTimeout(10000L) {
+ @Suppress("DEPRECATION")
+ withTimeout(10.seconds) {
readers.awaitAll()
}
}
diff --git a/datastore/datastore-rxjava2/src/test/java/androidx/datastore/rxjava2/RxDataStoreTest.java b/datastore/datastore-rxjava2/src/test/java/androidx/datastore/rxjava2/RxDataStoreTest.java
index 5a5c816..36471e8 100644
--- a/datastore/datastore-rxjava2/src/test/java/androidx/datastore/rxjava2/RxDataStoreTest.java
+++ b/datastore/datastore-rxjava2/src/test/java/androidx/datastore/rxjava2/RxDataStoreTest.java
@@ -160,11 +160,13 @@
assertThat(testSubscriber.awaitTerminalEvent()).isTrue();
testSubscriber.assertTerminated()
- // Note(rohitsat): this is different from coroutines bc asFlowable converts the
- // CancellationException to onComplete.
- .assertNoErrors()
- .assertComplete()
- .assertValueCount(0);
+ // FIXME: This used to be different from coroutines bc asFlowable used to convert
+ // the CancellationException to onComplete. This behavior changed with
+ // kotlinx-coroutines-rx2:1.5.0
+ // https://github.com/Kotlin/kotlinx.coroutines/issues/2173
+ //.assertNoErrors()
+ //.assertComplete()
+ .assertNoValues();
// NOTE(rohitsat): this is different from data()
diff --git a/datastore/datastore-rxjava3/src/test/java/androidx/datastore/rxjava3/RxDataStoreTest.java b/datastore/datastore-rxjava3/src/test/java/androidx/datastore/rxjava3/RxDataStoreTest.java
index 9da1bfd..39da7e1 100644
--- a/datastore/datastore-rxjava3/src/test/java/androidx/datastore/rxjava3/RxDataStoreTest.java
+++ b/datastore/datastore-rxjava3/src/test/java/androidx/datastore/rxjava3/RxDataStoreTest.java
@@ -159,11 +159,12 @@
assertThat(testSubscriber.await(5, TimeUnit.SECONDS)).isTrue();
- // Note(rohitsat): this is different from coroutines bc asFlowable converts the
- // CancellationException to onComplete
- testSubscriber.assertNoErrors()
- .assertComplete()
- .assertValueCount(0);
+ // FIXME: This used to be different from coroutines bc asFlowable used to convert
+ // the CancellationException to onComplete. This behavior changed with
+ // kotlinx-coroutines-rx3:1.5.0
+ // https://github.com/Kotlin/kotlinx.coroutines/issues/2173
+ // testSubscriber.assertNoErrors().assertComplete();
+ testSubscriber.assertNoValues();
// NOTE(rohitsat): this is different from data()
diff --git a/datastore/datastore-sampleapp/build.gradle b/datastore/datastore-sampleapp/build.gradle
index 6a59706..6ef3ba4 100644
--- a/datastore/datastore-sampleapp/build.gradle
+++ b/datastore/datastore-sampleapp/build.gradle
@@ -15,7 +15,6 @@
*/
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
import static androidx.build.dependencies.DependenciesKt.PROTOBUF_COMPILER
plugins {
@@ -43,7 +42,7 @@
// For settings fragment
implementation("androidx.preference:preference:1.1.1")
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation("androidx.navigation:navigation-fragment-ktx:2.3.2")
// For kotlin serialization
diff --git a/development/build_log_simplifier/message-flakes.ignore b/development/build_log_simplifier/message-flakes.ignore
index 773ffda..110863e 100644
--- a/development/build_log_simplifier/message-flakes.ignore
+++ b/development/build_log_simplifier/message-flakes.ignore
@@ -78,8 +78,8 @@
# > Task :internal-testutils-common:lintAnalyze
Scanning .*:
Failure reading binary cache file .*\.android\/cache\/api\-versions\-[0-9]+\-[0-9A-Z]+rev[0-9]+\.bin
-Please delete the file and restart the IDE\/lint\: .*\.android\/cache\/api\-versions\-[0-9]+\-[0-9]+rev[0-9]+\.bin
-java\.io\.FileNotFoundException\: .*\.android\/cache\/api\-versions\-[0-9]+\-[0-9]+rev[0-9]+\.bin \(No such file or directory\)
+Please delete the file and restart the IDE\/lint\: .*\.android\/cache\/api\-versions\-[0-9]+\-[0-9A-Z]+rev[0-9]+\.bin
+java\.io\.FileNotFoundException\: .*\.android\/cache\/api\-versions\-[0-9]+\-[0-9A-Z]+rev[0-9]+\.bin \(No such file or directory\)
at com\.google\.common\.io\.Files\$FileByteSource\.openStream\(Files\.java\:[0-9]+\)
at com\.google\.common\.io\.Files\$FileByteSource\.read\(Files\.java\:[0-9]+\)
at com\.google\.common\.io\.Files\.toByteArray\(Files\.java\:[0-9]+\)
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index b95764e..63d763a 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -154,6 +154,9 @@
# > Configure project :compose:test\-utils
The following Kotlin source sets were configured but not added to any Kotlin compilation:
\* androidAndroidTestRelease
+\* androidTestFixtures
+\* androidTestFixturesDebug
+\* androidTestFixturesRelease
\* androidTestRelease
\* test
You can add a source set to a target's compilation by connecting it with the compilation's default source set using 'dependsOn'\.
@@ -568,6 +571,8 @@
# > Task :docs-public:dokkaKotlinDocs
No documentation for .*
Found an unresolved type in androidx\.compose\.animation\.AnimatedContentScope\$using\(androidx\.compose\.animation\.ContentTransform, androidx\.compose\.animation\.SizeTransform\) \(AnimatedContent\.kt:[0-9]+\)
+Found an unresolved type in androidx\.compose\.runtime\.BroadcastFrameClock\$cancel\(\) \(BroadcastFrameClock\.kt:[0-9]+\)
+Found an unresolved type in androidx\.datastore\.rxjava[0-9]+\.RxDataStore\$dispose\(\) \(RxDataStore\.kt:[0-9]+\)
Found an unresolved type in androidx\.compose\.runtime\.Updater\$set\(kotlin\.Int, kotlin\.Function[0-9]+\(\(androidx\.compose\.runtime\.Updater\.T, kotlin\.Int, kotlin\.Unit\)\)\) \(Composer\.kt:[0-9]+\)
Found an unresolved type in androidx\.compose\.runtime\.Updater\$set\(androidx\.compose\.runtime\.Updater\.set\.V, kotlin\.Function[0-9]+\(\(androidx\.compose\.runtime\.Updater\.T, androidx\.compose\.runtime\.Updater\.set\.V, kotlin\.Unit\)\)\) \(Composer\.kt:[0-9]+\)
Found an unresolved type in androidx\.compose\.runtime\.Updater\$update\(kotlin\.Int, kotlin\.Function[0-9]+\(\(androidx\.compose\.runtime\.Updater\.T, kotlin\.Int, kotlin\.Unit\)\)\) \(Composer\.kt:[0-9]+\)
@@ -597,6 +602,9 @@
# See b/180023439 for hiltNavGraphViewModel warning.
Found an unresolved type in androidx\.hilt\.navigation\.compose\$hiltNavGraphViewModel\(androidx\.navigation\.NavController, kotlin\.String\) \(NavHostController\.kt:[0-9]+\)
Unresolved link to .*
+Found an unresolved type in androidx\.compose\.foundation\.MutatorMutex\$mutate\(androidx\.compose\.foundation\.MutatePriority, kotlin\.coroutines\.SuspendFunction[0-9]+\(\(androidx\.compose\.foundation\.MutatorMutex\.mutate\.R\)\)\) \(MutatorMutex\.kt:[0-9]+\)
+Found an unresolved type in androidx\.compose\.foundation\.MutatorMutex\$mutateWith\(androidx\.compose\.foundation\.MutatorMutex\.mutateWith\.T, androidx\.compose\.foundation\.MutatePriority, kotlin\.coroutines\.SuspendFunction[0-9]+\(\(androidx\.compose\.foundation\.MutatorMutex\.mutateWith\.T, androidx\.compose\.foundation\.MutatorMutex\.mutateWith\.R\)\)\) \(MutatorMutex\.kt:[0-9]+\)
+Found an unresolved type in androidx\.compose\.foundation\.gestures\$detectTapGestures\(androidx\.compose\.ui\.input\.pointer\.PointerInputScope, kotlin\.Function[0-9]+\(\(androidx\.compose\.ui\.geometry\.Offset, kotlin\.Unit\)\), kotlin\.Function[0-9]+\(\(androidx\.compose\.ui\.geometry\.Offset, kotlin\.Unit\)\), kotlin\.coroutines\.SuspendFunction[0-9]+\(\(androidx\.compose\.foundation\.gestures\.PressGestureScope, androidx\.compose\.ui\.geometry\.Offset, kotlin\.Unit\)\), kotlin\.Function[0-9]+\(\(androidx\.compose\.ui\.geometry\.Offset, kotlin\.Unit\)\)\) \(TapGestureDetector\.kt:[0-9]+\)
Found an unresolved type in androidx\.paging\.rxjava[0-9]+\.RxPagedListBuilder\$setInitialLoadKey\(androidx\.paging\.rxjava[0-9]+\.RxPagedListBuilder\.Key\) \(RxPagedListBuilder\.kt:[0-9]+\)
Found an unresolved type in androidx\.paging\.rxjava[0-9]+\.RxPagedListBuilder\$setBoundaryCallback\(androidx\.paging\.PagedList\.BoundaryCallback\(\(androidx\.paging\.rxjava[0-9]+\.RxPagedListBuilder\.Value\)\)\) \(RxPagedListBuilder\.kt:[0-9]+\)
Found an unresolved type in androidx\.paging\.rxjava[0-9]+\.RxPagedListBuilder\$setNotifyScheduler\(io\.reactivex\.rxjava[0-9]+\.core\.Scheduler\) \(RxPagedListBuilder\.kt:[0-9]+\)
@@ -693,6 +701,7 @@
Extension: org\.jetbrains\.dokka\.base\.DokkaBase/fallbackMerger,
Extension: org\.jetbrains\.dokka\.base\.DokkaBase/docTagToContentConverter,
Extension: com\.google\.devsite\.DevsitePlugin/translator,
+Extension: com\.google\.devsite\.DevsitePlugin/hideFilter,
Extension: org\.jetbrains\.dokka\.base\.DokkaBase/extensionsExtractor,
Extension: org\.jetbrains\.dokka\.base\.DokkaBase/undocumentedCodeReporter,
Extension: org\.jetbrains\.dokka\.base\.DokkaBase/inheritorsExtractor,
@@ -1096,6 +1105,7 @@
Info: Methods with invalid locals information:
java\.lang\.Object androidx\.compose\.foundation\.gestures\.DraggableKt\$draggable\$[0-9]+\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
Type information in locals\-table is inconsistent\. Cannot constrain type: @Nullable androidx\.compose\.foundation\.gestures\.DragLogic \{\} for value: v[0-9]+\(\$this\$invokeSuspend_u[0-9]+lambda_u[0-9]+d[0-9]+\) by constraint INT\.
+java\.lang\.Object androidx\.compose\.ui\.platform\.GlobalSnapshotManager\$ensureStarted\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
java\.lang\.Object androidx\.wear\.watchface\.WatchFaceService\$EngineWrapper\.createWatchFaceImpl\(android\.icu\.util\.Calendar, androidx\.wear\.watchface\.ComplicationsManager, androidx\.wear\.watchface\.style\.CurrentUserStyleRepository, kotlinx\.coroutines\.CompletableDeferred, kotlinx\.coroutines\.CompletableDeferred, androidx\.wear\.watchface\.WatchState, kotlin\.coroutines\.Continuation\)
java\.lang\.Object androidx\.wear\.watchface\.WatchFaceService\$EngineWrapper\.setUserStyle\$wear_watchface_release\(androidx\.wear\.watchface\.style\.data\.UserStyleWireFormat, kotlin\.coroutines\.Continuation\)
java\.lang\.Object androidx\.wear\.watchface\.editor\.BaseEditorSession\$fetchComplicationsData\$[0-9]+\.invokeSuspend\(java\.lang\.Object\)
@@ -1147,4 +1157,7 @@
# > Task :lint-checks:integration-tests:copyDebugAndroidLintReports
Copying lint text report to .*
# > Task :wear:compose:compose-material-benchmark:processReleaseAndroidTestManifest
-\$SUPPORT/wear/compose/material/benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
\ No newline at end of file
+\$SUPPORT/wear/compose/material/benchmark/src/androidTest/AndroidManifest\.xml:[0-9]+:[0-9]+\-[0-9]+:[0-9]+ Warning:
+# > Configure project :ads-identifier
+WARNING\:The option setting \'android\.experimental\.enableArtProfiles\=true\' is experimental\.
+The current default is \'false\'\.
\ No newline at end of file
diff --git a/development/project-creator/compose-template/groupId/artifactId/build.gradle b/development/project-creator/compose-template/groupId/artifactId/build.gradle
index 2d4b5d1..efbf6f2 100644
--- a/development/project-creator/compose-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/compose-template/groupId/artifactId/build.gradle
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
@@ -27,7 +27,7 @@
dependencies {
kotlinPlugin project(":compose:compiler:compiler")
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
// Add dependencies here
}
diff --git a/development/project-creator/java-template/groupId/artifactId/build.gradle b/development/project-creator/java-template/groupId/artifactId/build.gradle
index 01f3a79..f7d1aef 100644
--- a/development/project-creator/java-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/java-template/groupId/artifactId/build.gradle
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
@@ -24,7 +24,7 @@
}
dependencies {
- annotationProcessor(NULLAWAY)
+ annotationProcessor(libs.nullaway)
// Add dependencies here
}
diff --git a/development/project-creator/kotlin-template/groupId/artifactId/build.gradle b/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
index 28e4583..06d9511 100644
--- a/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
+++ b/development/project-creator/kotlin-template/groupId/artifactId/build.gradle
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
@@ -25,7 +25,7 @@
}
dependencies {
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
// Add dependencies here
}
diff --git a/development/referenceDocs/stageReferenceDocsWithDackka.sh b/development/referenceDocs/stageReferenceDocsWithDackka.sh
index 21d7068..b69bb6c 100755
--- a/development/referenceDocs/stageReferenceDocsWithDackka.sh
+++ b/development/referenceDocs/stageReferenceDocsWithDackka.sh
@@ -34,7 +34,7 @@
"compose"
# "collection"
"navigation"
-# "paging"
+ "paging"
"window"
)
diff --git a/development/versionCatalogMigrate.sh b/development/versionCatalogMigrate.sh
index 0e36b76..2bab61c 100755
--- a/development/versionCatalogMigrate.sh
+++ b/development/versionCatalogMigrate.sh
@@ -15,6 +15,7 @@
find -iname build.gradle | xargs sed -i "s/APACHE_COMMONS_CODEC/libs.apacheCommonsCodec/"
find -iname build.gradle | xargs sed -i "s/ASSERTJ/libs.assertj/"
find -iname build.gradle | xargs sed -i "s/CHECKER_FRAMEWORK/libs.checkerframework/"
+find -iname build.gradle | xargs sed -i "s/CONSTRAINT_LAYOUT/libs.constraintLayout/"
find -iname build.gradle | xargs sed -i "s/DAGGER/libs.dagger/"
find -iname build.gradle | xargs sed -i "s/DEXMAKER_MOCKITO/libs.dexmakerMockito/"
find -iname build.gradle | xargs sed -i "s/DEXMAKER_MOCKITO_INLINE/libs.dexmakerMockitoInline/"
diff --git a/drawerlayout/drawerlayout/build.gradle b/drawerlayout/drawerlayout/build.gradle
index cbec63b..79cf175 100644
--- a/drawerlayout/drawerlayout/build.gradle
+++ b/drawerlayout/drawerlayout/build.gradle
@@ -1,9 +1,6 @@
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -14,11 +11,11 @@
api("androidx.core:core:1.2.0")
api(project(":customview:customview"))
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.truth)
}
androidx {
diff --git a/dynamic-animation/dynamic-animation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java b/dynamic-animation/dynamic-animation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
index 4669660..854994c 100644
--- a/dynamic-animation/dynamic-animation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
+++ b/dynamic-animation/dynamic-animation/src/androidTest/java/androidx/dynamicanimation/tests/SpringTests.java
@@ -46,6 +46,7 @@
import androidx.dynamicanimation.animation.SpringForce;
import androidx.dynamicanimation.test.R;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -639,6 +640,7 @@
/**
* Makes sure all the properties getter works.
*/
+ @FlakyTest(bugId = 190540065)
@Test
public void testAllProperties() {
final DynamicAnimation.ViewProperty[] properties = {
diff --git a/emoji/core/build.gradle b/emoji/core/build.gradle
index 34ca766a..4440cbd 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -3,8 +3,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -27,13 +25,13 @@
api("androidx.core:core:1.3.0-rc01")
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-runtime"))
}
diff --git a/emoji2/emoji2-benchmark/build.gradle b/emoji2/emoji2-benchmark/build.gradle
index a4709c1..4ebdafd 100644
--- a/emoji2/emoji2-benchmark/build.gradle
+++ b/emoji2/emoji2-benchmark/build.gradle
@@ -17,8 +17,6 @@
import androidx.build.LibraryGroups
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -29,15 +27,15 @@
dependencies {
androidTestImplementation(project(":emoji2:emoji2"))
androidTestImplementation(projectOrArtifact(":benchmark:benchmark-junit4"))
- androidTestImplementation(JUNIT)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation project(':internal-testutils-runtime')
- androidTestImplementation(KOTLIN_STDLIB)
+ androidTestImplementation(libs.kotlinStdlib)
}
androidx {
diff --git a/emoji2/emoji2-bundled/build.gradle b/emoji2/emoji2-bundled/build.gradle
index 7d6c347..7d70ae4 100644
--- a/emoji2/emoji2-bundled/build.gradle
+++ b/emoji2/emoji2-bundled/build.gradle
@@ -2,8 +2,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -35,13 +33,13 @@
dependencies {
api(project(":emoji2:emoji2"))
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation project(':internal-testutils-runtime')
// view tests that use font are in this module as well; for licensing reasons
diff --git a/emoji2/emoji2-views-helper/build.gradle b/emoji2/emoji2-views-helper/build.gradle
index 038f23c..7b02cc4 100644
--- a/emoji2/emoji2-views-helper/build.gradle
+++ b/emoji2/emoji2-views-helper/build.gradle
@@ -2,8 +2,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -16,13 +14,13 @@
api("androidx.core:core:1.3.0")
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation project(':internal-testutils-runtime')
}
diff --git a/emoji2/emoji2-views/build.gradle b/emoji2/emoji2-views/build.gradle
index a7b3177..80f5267 100644
--- a/emoji2/emoji2-views/build.gradle
+++ b/emoji2/emoji2-views/build.gradle
@@ -2,8 +2,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -17,13 +15,13 @@
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation project(':internal-testutils-runtime')
}
diff --git a/emoji2/emoji2/build.gradle b/emoji2/emoji2/build.gradle
index ef1872e..73c2a4d 100644
--- a/emoji2/emoji2/build.gradle
+++ b/emoji2/emoji2/build.gradle
@@ -3,8 +3,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -28,13 +26,13 @@
api("androidx.startup:startup-runtime:1.0.0")
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation project(':internal-testutils-runtime')
}
diff --git a/emoji2/integration-tests/init-disabled-macrobenchmark-target/build.gradle b/emoji2/integration-tests/init-disabled-macrobenchmark-target/build.gradle
index 5f1098a..00d0464 100644
--- a/emoji2/integration-tests/init-disabled-macrobenchmark-target/build.gradle
+++ b/emoji2/integration-tests/init-disabled-macrobenchmark-target/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -33,10 +31,10 @@
}
dependencies {
- implementation(KOTLIN_STDLIB)
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.kotlinStdlib)
+ implementation(libs.constraintLayout, { transitive = true })
implementation(project(":arch:core:core-runtime"))
implementation(project(":appcompat:appcompat"))
implementation(project(":startup:startup-runtime"))
- implementation(MATERIAL)
+ implementation(libs.material)
}
diff --git a/emoji2/integration-tests/init-disabled-macrobenchmark/build.gradle b/emoji2/integration-tests/init-disabled-macrobenchmark/build.gradle
index 1ef079d..3e0c916 100644
--- a/emoji2/integration-tests/init-disabled-macrobenchmark/build.gradle
+++ b/emoji2/integration-tests/init-disabled-macrobenchmark/build.gradle
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-import static androidx.build.dependencies.DependenciesKt.*
-import androidx.build.LibraryGroups
-import androidx.build.Publish
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -36,10 +29,10 @@
dependencies {
androidTestImplementation(project(":benchmark:benchmark-macro-junit4"))
androidTestImplementation(project(":internal-testutils-macrobenchmark"))
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
}
def installReleaseTarget = tasks.getByPath(
diff --git a/emoji2/integration-tests/init-enabled-macrobenchmark-target/build.gradle b/emoji2/integration-tests/init-enabled-macrobenchmark-target/build.gradle
index 9c0aa54..8985bb8 100644
--- a/emoji2/integration-tests/init-enabled-macrobenchmark-target/build.gradle
+++ b/emoji2/integration-tests/init-enabled-macrobenchmark-target/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -33,9 +31,9 @@
}
dependencies {
- implementation(KOTLIN_STDLIB)
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.kotlinStdlib)
+ implementation(libs.constraintLayout, { transitive = true })
implementation(project(":arch:core:core-runtime"))
implementation(project(":appcompat:appcompat"))
- implementation(MATERIAL)
+ implementation(libs.material)
}
diff --git a/emoji2/integration-tests/init-enabled-macrobenchmark/build.gradle b/emoji2/integration-tests/init-enabled-macrobenchmark/build.gradle
index c9ebc39..5529d60 100644
--- a/emoji2/integration-tests/init-enabled-macrobenchmark/build.gradle
+++ b/emoji2/integration-tests/init-enabled-macrobenchmark/build.gradle
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-import static androidx.build.dependencies.DependenciesKt.*
-import androidx.build.LibraryGroups
-import androidx.build.Publish
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -37,10 +30,10 @@
androidTestImplementation(project(":emoji2:emoji2"))
androidTestImplementation(project(":benchmark:benchmark-macro-junit4"))
androidTestImplementation(project(":internal-testutils-macrobenchmark"))
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
}
def installReleaseTarget = tasks.getByPath(
diff --git a/fragment/fragment-lint/build.gradle b/fragment/fragment-lint/build.gradle
index c660740..cdd6531 100644
--- a/fragment/fragment-lint/build.gradle
+++ b/fragment/fragment-lint/build.gradle
@@ -17,8 +17,6 @@
import androidx.build.LibraryGroups
import androidx.build.LibraryType
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
diff --git a/fragment/fragment/api/current.txt b/fragment/fragment/api/current.txt
index f56726e..7a3af0e 100644
--- a/fragment/fragment/api/current.txt
+++ b/fragment/fragment/api/current.txt
@@ -196,7 +196,6 @@
ctor public FragmentContainerView(android.content.Context);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
- method @RequiresApi(20) protected boolean fitSystemWindows(android.graphics.Rect);
method public <F extends androidx.fragment.app.Fragment> F? getFragment();
}
diff --git a/fragment/fragment/api/public_plus_experimental_current.txt b/fragment/fragment/api/public_plus_experimental_current.txt
index f56726e..7a3af0e 100644
--- a/fragment/fragment/api/public_plus_experimental_current.txt
+++ b/fragment/fragment/api/public_plus_experimental_current.txt
@@ -196,7 +196,6 @@
ctor public FragmentContainerView(android.content.Context);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
- method @RequiresApi(20) protected boolean fitSystemWindows(android.graphics.Rect);
method public <F extends androidx.fragment.app.Fragment> F? getFragment();
}
diff --git a/fragment/fragment/api/restricted_current.txt b/fragment/fragment/api/restricted_current.txt
index 86bd304..1012495 100644
--- a/fragment/fragment/api/restricted_current.txt
+++ b/fragment/fragment/api/restricted_current.txt
@@ -201,7 +201,6 @@
ctor public FragmentContainerView(android.content.Context);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?);
ctor public FragmentContainerView(android.content.Context, android.util.AttributeSet?, int);
- method @RequiresApi(20) protected boolean fitSystemWindows(android.graphics.Rect);
method public <F extends androidx.fragment.app.Fragment> F? getFragment();
}
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
index dfb33c3..6b60563 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/strictmode/FragmentStrictModeTest.kt
@@ -205,6 +205,7 @@
}
}
+ @Suppress("DEPRECATION")
@Test
public fun detectFragmentTagUsage() {
var violation: Violation? = null
@@ -216,7 +217,14 @@
with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
withActivity { setContentView(R.layout.activity_inflated_fragment) }
+ val fragment = withActivity {
+ supportFragmentManager.findFragmentById(R.id.inflated_fragment)!!
+ }
+ val container = withActivity { findViewById(R.id.inflated_layout) }
assertThat(violation).isInstanceOf(FragmentTagUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to use <fragment> tag to add fragment $fragment to container $container"
+ )
}
}
@@ -230,12 +238,19 @@
.build()
FragmentStrictMode.setDefaultPolicy(policy)
- StrictFragment().retainInstance = true
+ val fragment = StrictFragment()
+ fragment.retainInstance = true
assertThat(violation).isInstanceOf(SetRetainInstanceUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to set retain instance for fragment $fragment"
+ )
violation = null
- StrictFragment().retainInstance
+ fragment.retainInstance
assertThat(violation).isInstanceOf(GetRetainInstanceUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to get retain instance for fragment $fragment"
+ )
}
@Suppress("DEPRECATION")
@@ -266,16 +281,29 @@
.build()
FragmentStrictMode.setDefaultPolicy(policy)
- StrictFragment().setTargetFragment(StrictFragment(), 1)
+ val fragment = StrictFragment()
+ val targetFragment = StrictFragment()
+ val requestCode = 1
+ fragment.setTargetFragment(targetFragment, requestCode)
assertThat(violation).isInstanceOf(SetTargetFragmentUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to set target fragment $targetFragment " +
+ "with request code $requestCode for fragment $fragment"
+ )
violation = null
- StrictFragment().targetFragment
+ fragment.targetFragment
assertThat(violation).isInstanceOf(GetTargetFragmentUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to get target fragment from fragment $fragment"
+ )
violation = null
- StrictFragment().targetRequestCode
+ fragment.targetRequestCode
assertThat(violation).isInstanceOf(GetTargetFragmentRequestCodeUsageViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to get target request code from fragment $fragment"
+ )
}
@Test
@@ -290,18 +318,30 @@
with(ActivityScenario.launch(FragmentTestActivity::class.java)) {
val fragmentManager = withActivity { supportFragmentManager }
+ val fragment1 = StrictFragment()
fragmentManager.beginTransaction()
- .add(R.id.content, StrictFragment())
+ .add(R.id.content, fragment1)
.commit()
executePendingTransactions()
+ val container1 = withActivity { findViewById(R.id.content) }
assertThat(violation).isInstanceOf(WrongFragmentContainerViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to add fragment $fragment1 to container " +
+ "$container1 which is not a FragmentContainerView"
+ )
violation = null
+ val fragment2 = StrictFragment()
fragmentManager.beginTransaction()
- .replace(R.id.content, StrictFragment())
+ .replace(R.id.content, fragment2)
.commit()
executePendingTransactions()
+ val container2 = withActivity { findViewById(R.id.content) }
assertThat(violation).isInstanceOf(WrongFragmentContainerViolation::class.java)
+ assertThat(violation).hasMessageThat().contains(
+ "Attempting to add fragment $fragment2 to container " +
+ "$container2 which is not a FragmentContainerView"
+ )
}
}
diff --git a/fragment/fragment/src/androidTest/res/layout/activity_inflated_fragment.xml b/fragment/fragment/src/androidTest/res/layout/activity_inflated_fragment.xml
index 8c49fcb..f49c777 100644
--- a/fragment/fragment/src/androidTest/res/layout/activity_inflated_fragment.xml
+++ b/fragment/fragment/src/androidTest/res/layout/activity_inflated_fragment.xml
@@ -16,11 +16,14 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <fragment android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/inflated_fragment"
- android:name="androidx.fragment.app.StrictViewFragment"/>
+ android:id="@+id/inflated_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <fragment
+ android:id="@+id/inflated_fragment"
+ android:name="androidx.fragment.app.StrictViewFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
</LinearLayout>
\ No newline at end of file
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.java
index b5edacc..bc5fe97 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentContainerView.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.AttributeSet;
@@ -248,14 +247,6 @@
return insets;
}
- @RequiresApi(20)
- @Override
- @SuppressWarnings("deprecation")
- protected boolean fitSystemWindows(@NonNull Rect insets) {
- throw new UnsupportedOperationException("FragmentContainerView does not support "
- + "fitSystemWindows(). Insets should be handled directly by a fragment's view.");
- }
-
@Override
protected void dispatchDraw(@NonNull Canvas canvas) {
if (mDrawDisappearingViewsFirst && mDisappearingFragmentChildren != null) {
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentTagUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentTagUsageViolation.java
index 9dffe58..c5d9b7c 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentTagUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/FragmentTagUsageViolation.java
@@ -41,4 +41,11 @@
public ViewGroup getParentContainer() {
return mContainer;
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to use <fragment> tag to add fragment " + mFragment + " to container "
+ + mContainer;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetRetainInstanceUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetRetainInstanceUsageViolation.java
index 6ed5a3d..96f00db 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetRetainInstanceUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetRetainInstanceUsageViolation.java
@@ -25,4 +25,10 @@
GetRetainInstanceUsageViolation(@NonNull Fragment fragment) {
super(fragment);
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to get retain instance for fragment " + mFragment;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentRequestCodeUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentRequestCodeUsageViolation.java
index 84053ee..cfcb5ab 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentRequestCodeUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentRequestCodeUsageViolation.java
@@ -25,4 +25,10 @@
GetTargetFragmentRequestCodeUsageViolation(@NonNull Fragment fragment) {
super(fragment);
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to get target request code from fragment " + mFragment;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentUsageViolation.java
index da46c84..db862c8 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/GetTargetFragmentUsageViolation.java
@@ -25,4 +25,10 @@
GetTargetFragmentUsageViolation(@NonNull Fragment fragment) {
super(fragment);
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to get target fragment from fragment " + mFragment;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetRetainInstanceUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetRetainInstanceUsageViolation.java
index dbeb9be..c46cd61 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetRetainInstanceUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetRetainInstanceUsageViolation.java
@@ -25,4 +25,10 @@
SetRetainInstanceUsageViolation(@NonNull Fragment fragment) {
super(fragment);
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to set retain instance for fragment " + mFragment;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetTargetFragmentUsageViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetTargetFragmentUsageViolation.java
index 8d4374c..ce8aa7f 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetTargetFragmentUsageViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/SetTargetFragmentUsageViolation.java
@@ -42,4 +42,11 @@
public int getRequestCode() {
return mRequestCode;
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to set target fragment " + mTargetFragment + " with request code "
+ + mRequestCode + " for fragment " + mFragment;
+ }
}
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/WrongFragmentContainerViolation.java b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/WrongFragmentContainerViolation.java
index 2dd613e..61fb15d 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/WrongFragmentContainerViolation.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/strictmode/WrongFragmentContainerViolation.java
@@ -39,4 +39,11 @@
public ViewGroup getContainer() {
return mContainer;
}
+
+ @NonNull
+ @Override
+ public String getMessage() {
+ return "Attempting to add fragment " + mFragment + " to container " + mContainer
+ + " which is not a FragmentContainerView";
+ }
}
diff --git a/gradle.properties b/gradle.properties
index fc4663d..9ef8a54 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -28,3 +28,8 @@
# Do not automatically include stdlib
kotlin.stdlib.default.dependency=false
+
+# Enable adding baseline-prof.txt files to AAR artifacts
+android.experimental.enableArtProfiles=true
+
+android.experimental.runLintInProcess=false
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 51b11dc..e684404 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
# -----------------------------------------------------------------------------
# All of the following should be updated in sync.
# -----------------------------------------------------------------------------
-androidGradlePlugin = "7.1.0-alpha01"
+androidGradlePlugin = "7.1.0-alpha02"
# NOTE: When updating the lint version we also need to update the `api` version
# supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "30.1.0-alpha01"
+androidLint = "30.1.0-alpha02"
# Once you have a chosen version of AGP to upgrade to, go to
# https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2021.1.1.1"
+androidStudio = "2021.1.1.2"
# -----------------------------------------------------------------------------
androidLintMin = "26.3.0"
@@ -22,7 +22,7 @@
incap = "0.2"
kotlin = "1.5.10"
kotlinCompileTesting = "1.4.1"
-kotlinCoroutines = "1.4.3"
+kotlinCoroutines = "1.5.0"
ksp = "1.5.10-1.0.0-beta01"
leakcanary = "2.2"
mockito = "2.25.0"
@@ -35,6 +35,7 @@
androidLintMin = { module = "com.android.tools.lint:lint", version.ref = "androidLintMin" }
androidLintApi = { module = "com.android.tools.lint:lint-api", version.ref = "androidLint" }
androidLintMinApi = { module = "com.android.tools.lint:lint-api", version.ref = "androidLintMin" }
+androidLintChecks = { module = "com.android.tools.lint:lint-checks", version.ref = "androidLint" }
androidLintTests = { module = "com.android.tools.lint:lint-tests", version.ref = "androidLint" }
autoCommon = { module = "com.google.auto:auto-common", version = "0.11" }
autoServiceAnnotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" }
@@ -46,6 +47,7 @@
apacheCommonsCodec = { module = "commons-codec:commons-codec", version = "1.10" }
assertj = { module = "org.assertj:assertj-core", version = "3.11.1" }
checkerframework = { module = "org.checkerframework:checker-qual", version = "2.5.3" }
+constraintLayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.0.1"}
dagger = { module = "com.google.dagger:dagger-compiler", version = "2.35" }
dexmakerMockito = { module = "com.linkedin.dexmaker:dexmaker-mockito", version.ref = "dexmaker" }
dexmakerMockitoInline = { module = "com.linkedin.dexmaker:dexmaker-mockito-inline", version.ref = "dexmaker" }
@@ -131,7 +133,7 @@
shadow = { module = "com.github.jengelman.gradle.plugins:shadow", version = "6.1.0" }
sqldelightAndroid = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" }
sqldelightCoroutinesExt = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
-sqliteJdbc = { module = "org.xerial:sqlite-jdbc", version = "3.25.2" }
+sqliteJdbc = { module = "org.xerial:sqlite-jdbc", version = "3.34.0" }
testCore = { module = "androidx.test:core", version.ref = "androidxTest" }
testExtJunit = { module = "androidx.test.ext:junit", version.ref = "androidxTestExt" }
testExtJunitKtx = { module = "androidx.test.ext:junit-ktx", version.ref = "androidxTestExt" }
diff --git a/gridlayout/gridlayout/src/androidTest/java/androidx/gridlayout/widget/GridLayoutTest.java b/gridlayout/gridlayout/src/androidTest/java/androidx/gridlayout/widget/GridLayoutTest.java
index ae786be..dd9198d 100644
--- a/gridlayout/gridlayout/src/androidTest/java/androidx/gridlayout/widget/GridLayoutTest.java
+++ b/gridlayout/gridlayout/src/androidTest/java/androidx/gridlayout/widget/GridLayoutTest.java
@@ -30,6 +30,7 @@
import androidx.gridlayout.test.R;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -125,6 +126,7 @@
assertEquals(total, left);
}
+ @FlakyTest(bugId = 190539262)
@Test
public void testWrapContentInOtherDirection() throws Throwable {
setContentView(R.layout.height_wrap_content_test);
diff --git a/hilt/hilt-navigation-compose/api/current.txt b/hilt/hilt-navigation-compose/api/current.txt
index 447d5c6..ffa3e52 100644
--- a/hilt/hilt-navigation-compose/api/current.txt
+++ b/hilt/hilt-navigation-compose/api/current.txt
@@ -5,8 +5,7 @@
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel();
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavController, String route);
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel();
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner);
}
}
diff --git a/hilt/hilt-navigation-compose/api/public_plus_experimental_current.txt b/hilt/hilt-navigation-compose/api/public_plus_experimental_current.txt
index 447d5c6..ffa3e52 100644
--- a/hilt/hilt-navigation-compose/api/public_plus_experimental_current.txt
+++ b/hilt/hilt-navigation-compose/api/public_plus_experimental_current.txt
@@ -5,8 +5,7 @@
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel();
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavController, String route);
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel();
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner);
}
}
diff --git a/hilt/hilt-navigation-compose/api/restricted_current.txt b/hilt/hilt-navigation-compose/api/restricted_current.txt
index 0b008ea..74cf2f4 100644
--- a/hilt/hilt-navigation-compose/api/restricted_current.txt
+++ b/hilt/hilt-navigation-compose/api/restricted_current.txt
@@ -2,12 +2,11 @@
package androidx.hilt.navigation.compose {
public final class HiltViewModelKt {
+ method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static androidx.lifecycle.ViewModelProvider.Factory? createHiltViewModelFactory(androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner);
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel();
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltNavGraphViewModel(androidx.navigation.NavController, String route);
- method @androidx.compose.runtime.Composable @kotlin.PublishedApi internal static <VM extends androidx.lifecycle.ViewModel> VM hiltViewModel(kotlin.reflect.KClass<VM> kClass, androidx.navigation.NavBackStackEntry backStackEntry);
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel();
- method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(androidx.navigation.NavBackStackEntry backStackEntry);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! hiltViewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner);
}
}
diff --git a/hilt/hilt-navigation-compose/src/androidTest/java/androidx/hilt/navigation/compose/HiltViewModelComposeTest.kt b/hilt/hilt-navigation-compose/src/androidTest/java/androidx/hilt/navigation/compose/HiltViewModelComposeTest.kt
index 9db8b224f..2e0ebfb 100644
--- a/hilt/hilt-navigation-compose/src/androidTest/java/androidx/hilt/navigation/compose/HiltViewModelComposeTest.kt
+++ b/hilt/hilt-navigation-compose/src/androidTest/java/androidx/hilt/navigation/compose/HiltViewModelComposeTest.kt
@@ -30,6 +30,7 @@
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navigation
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
import dagger.hilt.android.AndroidEntryPoint
@@ -52,6 +53,7 @@
@get:Rule
val composeTestRule = createAndroidComposeRule<TestActivity>()
+ @FlakyTest(bugId = 190539286)
@Test
fun verifyCurrentNavGraphViewModel() {
lateinit var firstViewModel: SimpleViewModel
@@ -74,6 +76,7 @@
assertThat(firstViewModel).isNotSameInstanceAs(secondViewModel)
}
+ @FlakyTest(bugId = 190539286)
@Test
fun differentViewModelAcrossRoutes() {
lateinit var firstViewModel: SimpleViewModel
diff --git a/hilt/hilt-navigation-compose/src/main/java/androidx/hilt/navigation/compose/HiltViewModel.kt b/hilt/hilt-navigation-compose/src/main/java/androidx/hilt/navigation/compose/HiltViewModel.kt
index 7a1210c..2b5ed13 100644
--- a/hilt/hilt-navigation-compose/src/main/java/androidx/hilt/navigation/compose/HiltViewModel.kt
+++ b/hilt/hilt-navigation-compose/src/main/java/androidx/hilt/navigation/compose/HiltViewModel.kt
@@ -21,11 +21,11 @@
import androidx.hilt.navigation.HiltViewModelFactory
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
-import kotlin.reflect.KClass
/**
* Returns an existing
@@ -37,15 +37,16 @@
* fragment or an activity.
*
* @sample androidx.hilt.navigation.compose.samples.NavComposable
+ * @sample androidx.hilt.navigation.compose.samples.NestedNavComposable
*/
@Composable
-inline fun <reified VM : ViewModel> hiltViewModel(): VM {
- val owner = LocalViewModelStoreOwner.current
- return if (owner is NavBackStackEntry) {
- hiltViewModel(VM::class, owner)
- } else {
- viewModel()
+inline fun <reified VM : ViewModel> hiltViewModel(
+ viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
+ "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
}
+): VM {
+ val factory = createHiltViewModelFactory(viewModelStoreOwner)
+ return viewModel(viewModelStoreOwner, factory = factory)
}
/**
@@ -71,23 +72,9 @@
* the [NavController] back stack.
*
* @param backStackEntry The entry of a [NavController] back stack.
- *
- * @sample androidx.hilt.navigation.compose.samples.NestedNavComposable
- */
-@Composable
-inline fun <reified VM : ViewModel> hiltViewModel(backStackEntry: NavBackStackEntry) =
- hiltViewModel(VM::class, backStackEntry)
-
-/**
- * Returns an existing
- * [HiltViewModel](https://dagger.dev/api/latest/dagger/hilt/android/lifecycle/HiltViewModel)
- * -annotated [ViewModel] or creates a new one scoped to the current navigation graph present on
- * the [NavController] back stack.
- *
- * @param backStackEntry The entry of a [NavController] back stack.
*/
@Deprecated(
- message = "Use hiltViewModel(NavBackStackEntry) instead.",
+ message = "Use hiltViewModel(ViewModelStoreOwner) instead.",
replaceWith = ReplaceWith("hiltViewModel(backStackEntry)"),
)
@Composable
@@ -103,7 +90,7 @@
* @param route route of a destination that exists on the [NavController] back stack.
*/
@Deprecated(
- message = "Use hiltViewModel(NavBackStackEntry) in combination with " +
+ message = "Use hiltViewModel(ViewModelStoreOwner) in combination with " +
"NavController#getBackStackEntry(String). This API will be removed in a future version.",
replaceWith = ReplaceWith("hiltViewModel(this.getBackStackEntry(route))"),
level = DeprecationLevel.ERROR
@@ -114,13 +101,15 @@
@Composable
@PublishedApi
-internal fun <VM : ViewModel> hiltViewModel(
- kClass: KClass<VM>,
- backStackEntry: NavBackStackEntry
-): VM {
- val viewModelFactory = HiltViewModelFactory(
+internal fun createHiltViewModelFactory(
+ viewModelStoreOwner: ViewModelStoreOwner
+): ViewModelProvider.Factory? = if (viewModelStoreOwner is NavBackStackEntry) {
+ HiltViewModelFactory(
context = LocalContext.current,
- navBackStackEntry = backStackEntry
+ navBackStackEntry = viewModelStoreOwner
)
- return ViewModelProvider(backStackEntry, viewModelFactory).get(kClass.java)
+} else {
+ // Use the default factory provided by the ViewModelStoreOwner
+ // and assume it is an @AndroidEntryPoint annotated fragment or activity
+ null
}
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/hilt/hilt-navigation-compose/src/test/kotlin/EmptyFile.kt
similarity index 79%
copy from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
copy to hilt/hilt-navigation-compose/src/test/kotlin/EmptyFile.kt
index 3d934fd..b1634a1 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/hilt/hilt-navigation-compose/src/test/kotlin/EmptyFile.kt
@@ -14,11 +14,5 @@
* limitations under the License.
*/
-package androidx.window.test
-
-import android.app.Activity
-
-/**
- * A test [Activity] for testing purposes.
- */
-public class TestActivity : Activity()
\ No newline at end of file
+// NOTE(b/190438045):
+// This file is intentionally left empty to temporarily work around a bug in AGP 7.1.0-alpha02
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/hilt/hilt-navigation-fragment/src/test/kotlin/EmptyFile.kt
similarity index 79%
copy from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
copy to hilt/hilt-navigation-fragment/src/test/kotlin/EmptyFile.kt
index 3d934fd..b1634a1 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/hilt/hilt-navigation-fragment/src/test/kotlin/EmptyFile.kt
@@ -14,11 +14,5 @@
* limitations under the License.
*/
-package androidx.window.test
-
-import android.app.Activity
-
-/**
- * A test [Activity] for testing purposes.
- */
-public class TestActivity : Activity()
\ No newline at end of file
+// NOTE(b/190438045):
+// This file is intentionally left empty to temporarily work around a bug in AGP 7.1.0-alpha02
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/hilt/integration-tests/viewmodelapp/src/test/kotlin/EmptyFile.kt
similarity index 79%
copy from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
copy to hilt/integration-tests/viewmodelapp/src/test/kotlin/EmptyFile.kt
index 3d934fd..b1634a1 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/hilt/integration-tests/viewmodelapp/src/test/kotlin/EmptyFile.kt
@@ -14,11 +14,5 @@
* limitations under the License.
*/
-package androidx.window.test
-
-import android.app.Activity
-
-/**
- * A test [Activity] for testing purposes.
- */
-public class TestActivity : Activity()
\ No newline at end of file
+// NOTE(b/190438045):
+// This file is intentionally left empty to temporarily work around a bug in AGP 7.1.0-alpha02
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/hilt/integration-tests/workerapp/src/test/kotlin/EmptyFile.kt
similarity index 79%
copy from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
copy to hilt/integration-tests/workerapp/src/test/kotlin/EmptyFile.kt
index 3d934fd..b1634a1 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/hilt/integration-tests/workerapp/src/test/kotlin/EmptyFile.kt
@@ -14,11 +14,5 @@
* limitations under the License.
*/
-package androidx.window.test
-
-import android.app.Activity
-
-/**
- * A test [Activity] for testing purposes.
- */
-public class TestActivity : Activity()
\ No newline at end of file
+// NOTE(b/190438045):
+// This file is intentionally left empty to temporarily work around a bug in AGP 7.1.0-alpha02
\ No newline at end of file
diff --git a/inspection/inspection-gradle-plugin/build.gradle b/inspection/inspection-gradle-plugin/build.gradle
index 9e6ded91..51e1c0e 100644
--- a/inspection/inspection-gradle-plugin/build.gradle
+++ b/inspection/inspection-gradle-plugin/build.gradle
@@ -19,8 +19,6 @@
import androidx.build.Publish
import androidx.build.SdkResourceGenerator
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -33,16 +31,16 @@
dependencies {
implementation(findGradleKotlinDsl())
implementation(gradleApi())
- implementation(AGP_LATEST)
- implementation(KOTLIN_STDLIB)
+ implementation(libs.androidGradlePlugin)
+ implementation(libs.kotlinStdlib)
implementation(libs.protobufGradlePlugin)
implementation(libs.shadow)
testImplementation(project(":internal-testutils-gradle-plugin"))
testImplementation(gradleTestKit())
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(JUNIT)
- testImplementation(KOTLIN_TEST)
+ testImplementation(libs.testRunner)
+ testImplementation(libs.junit)
+ testImplementation(libs.kotlinTest)
}
gradlePlugin {
diff --git a/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/InspectionPlugin.kt b/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/InspectionPlugin.kt
index 13a107d..4f63abc 100644
--- a/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/InspectionPlugin.kt
+++ b/inspection/inspection-gradle-plugin/src/main/kotlin/androidx/inspection/gradle/InspectionPlugin.kt
@@ -80,6 +80,8 @@
project.apply(plugin = "com.google.protobuf")
project.plugins.all {
if (it is ProtobufPlugin) {
+ // https://github.com/google/protobuf-gradle-plugin/issues/505
+ @Suppress("DEPRECATION")
val protobufConvention = project.convention.getPlugin<ProtobufConvention>()
protobufConvention.protobuf.apply {
protoc {
diff --git a/inspection/inspection-testing/build.gradle b/inspection/inspection-testing/build.gradle
index d19bf24..b93b52d 100644
--- a/inspection/inspection-testing/build.gradle
+++ b/inspection/inspection-testing/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.Publish
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -29,13 +27,13 @@
dependencies {
api("androidx.annotation:annotation:1.1.0")
api(project(":inspection:inspection"))
- implementation(KOTLIN_STDLIB)
- implementation(KOTLIN_COROUTINES_ANDROID)
+ implementation(libs.kotlinStdlib)
+ implementation(libs.kotlinCoroutinesAndroid)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(KOTLIN_COROUTINES_TEST)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.kotlinCoroutinesTest)
+ androidTestImplementation(libs.truth)
}
androidx {
diff --git a/inspection/inspection-testing/src/androidTest/java/androidx/inspection/testing/echo/TickleManager.kt b/inspection/inspection-testing/src/androidTest/java/androidx/inspection/testing/echo/TickleManager.kt
index a5ed775..6d63471 100644
--- a/inspection/inspection-testing/src/androidTest/java/androidx/inspection/testing/echo/TickleManager.kt
+++ b/inspection/inspection-testing/src/androidTest/java/androidx/inspection/testing/echo/TickleManager.kt
@@ -33,6 +33,6 @@
}
fun tickle() {
- channel.offer(Unit)
+ channel.trySend(Unit)
}
}
\ No newline at end of file
diff --git a/inspection/inspection/build.gradle b/inspection/inspection/build.gradle
index 23295cb..3ee849b 100644
--- a/inspection/inspection/build.gradle
+++ b/inspection/inspection/build.gradle
@@ -15,12 +15,8 @@
*/
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
-import androidx.build.RunApiTasks
-
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.Publish
+import androidx.build.RunApiTasks
plugins {
id("AndroidXPlugin")
@@ -30,9 +26,9 @@
dependencies {
api("androidx.annotation:annotation:1.1.0")
- testImplementation(TRUTH)
- testImplementation(KOTLIN_STDLIB)
- testImplementation(JUNIT)
+ testImplementation(libs.truth)
+ testImplementation(libs.kotlinStdlib)
+ testImplementation(libs.junit)
}
androidx {
diff --git a/jetifier/jetifier/core/build.gradle b/jetifier/jetifier/core/build.gradle
index b94dae3..7e6696f 100644
--- a/jetifier/jetifier/core/build.gradle
+++ b/jetifier/jetifier/core/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryType
import androidx.build.LibraryVersions
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -28,9 +26,9 @@
dependencies {
api("com.google.code.gson:gson:2.8.0")
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
testImplementation("junit:junit:4.12")
- testImplementation(TRUTH)
+ testImplementation(libs.truth)
}
androidx {
diff --git a/jetifier/jetifier/processor/build.gradle b/jetifier/jetifier/processor/build.gradle
index 71565e7..7d7049b 100644
--- a/jetifier/jetifier/processor/build.gradle
+++ b/jetifier/jetifier/processor/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryType
import androidx.build.LibraryVersions
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -31,12 +29,12 @@
api("org.ow2.asm:asm-util:8.0.1")
api("org.ow2.asm:asm-commons:8.0.1")
api("org.jdom:jdom2:2.0.6")
- api(KOTLIN_STDLIB)
- api(KOTLIN_METADATA_JVM)
+ api(libs.kotlinStdlib)
+ api(libs.kotlinMetadataJvm)
testImplementation("junit:junit:4.12")
- testImplementation(TRUTH)
- testImplementation(KOTLIN_REFLECT)
- testImplementation(KOTLIN_COMPILE_TESTING)
+ testImplementation(libs.truth)
+ testImplementation(libs.kotlinReflect)
+ testImplementation(libs.kotlinCompileTesting)
}
androidx {
diff --git a/leanback/leanback-paging/build.gradle b/leanback/leanback-paging/build.gradle
index 18e9338..3585e40 100644
--- a/leanback/leanback-paging/build.gradle
+++ b/leanback/leanback-paging/build.gradle
@@ -2,7 +2,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
plugins {
id("AndroidXPlugin")
@@ -15,20 +14,20 @@
api("androidx.leanback:leanback:1.1.0-beta01")
api("androidx.paging:paging-runtime:3.0.0-beta03")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-espresso"))
androidTestImplementation(project(":internal-testutils-runtime"))
androidTestImplementation(project(":internal-testutils-common"))
androidTestImplementation(project(":internal-testutils-ktx"))
androidTestImplementation(project(":internal-testutils-paging"))
- androidTestImplementation(KOTLIN_TEST)
- androidTestImplementation(KOTLIN_COROUTINES_TEST)
+ androidTestImplementation(libs.kotlinTest)
+ androidTestImplementation(libs.kotlinCoroutinesTest)
androidTestImplementation("androidx.arch.core:core-testing:2.1.0")
androidTestImplementation(project(":lifecycle:lifecycle-runtime-testing"))
}
diff --git a/leanback/leanback-tab/build.gradle b/leanback/leanback-tab/build.gradle
index 587ee18..f7db959 100644
--- a/leanback/leanback-tab/build.gradle
+++ b/leanback/leanback-tab/build.gradle
@@ -2,15 +2,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_CORE
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_EXT_JUNIT
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_RULES
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_RUNNER
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-import static androidx.build.dependencies.DependenciesKt.DEXMAKER_MOCKITO
-import static androidx.build.dependencies.DependenciesKt.ESPRESSO_CORE
-import static androidx.build.dependencies.DependenciesKt.MOCKITO_CORE
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -21,20 +12,19 @@
api("com.google.android.material:material:1.0.0")
api("androidx.viewpager:viewpager:1.0.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-espresso"))
androidTestImplementation(project(":internal-testutils-runtime"))
androidTestImplementation(project(":internal-testutils-common"))
androidTestImplementation(project(":leanback:leanback"))
androidTestImplementation("androidx.appcompat:appcompat:1.0.0")
- androidTestImplementation(CONSTRAINT_LAYOUT, { transitive = true })
-
+ androidTestImplementation(libs.constraintLayout)
}
android {
diff --git a/leanback/leanback/build.gradle b/leanback/leanback/build.gradle
index cbc1960..7f7d047 100644
--- a/leanback/leanback/build.gradle
+++ b/leanback/leanback/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -18,14 +17,14 @@
api("androidx.recyclerview:recyclerview:1.2.0-rc01")
api("androidx.appcompat:appcompat:1.0.0")
- androidTestImplementation(KOTLIN_STDLIB)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-espresso"))
androidTestImplementation(project(":internal-testutils-runtime"))
androidTestImplementation(project(":internal-testutils-common"))
diff --git a/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java b/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
index d5bf761..2bf59e9 100644
--- a/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
+++ b/lifecycle/integration-tests/testapp/src/androidTest/java/androidx/lifecycle/PartiallyCoveredActivityTest.java
@@ -122,14 +122,14 @@
}
@Test
- @FlakyTest
+ @FlakyTest(bugId = 173596006)
public void coveredWithDialog_activity() throws Throwable {
final CollectingSupportActivity activity = activityRule.getActivity();
runTest(activity);
}
@Test
- @FlakyTest
+ @FlakyTest(bugId = 173596006)
public void coveredWithDialog_fragment() throws Throwable {
CollectingSupportFragment fragment = new CollectingSupportFragment();
activityRule.runOnUiThread(() -> activityRule.getActivity().replaceFragment(fragment));
@@ -137,7 +137,7 @@
}
@Test
- @FlakyTest
+ @FlakyTest(bugId = 173596006)
public void coveredWithDialog_childFragment() throws Throwable {
CollectingSupportFragment parentFragment = new CollectingSupportFragment();
CollectingSupportFragment childFragment = new CollectingSupportFragment();
diff --git a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
index 34ff630..12b0831 100644
--- a/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
+++ b/lifecycle/lifecycle-livedata-core-ktx-lint/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryType
import androidx.build.LibraryVersions
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
index 0e3f903..538a417 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
@@ -20,6 +20,7 @@
import android.os.Build
import androidx.annotation.RequiresApi
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -88,10 +89,11 @@
* BackPressure: the returned flow is conflated. There is no mechanism to suspend an emission by
* LiveData due to a slow collector, so collector always gets the most recent value emitted.
*/
+@OptIn(DelicateCoroutinesApi::class)
public fun <T> LiveData<T>.asFlow(): Flow<T> = flow {
val channel = Channel<T>(Channel.CONFLATED)
val observer = Observer<T> {
- channel.offer(it)
+ channel.trySend(it)
}
withContext(Dispatchers.Main.immediate) {
observeForever(observer)
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt b/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
index 808c882..9ef1f3f 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
+++ b/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
@@ -83,10 +83,10 @@
var closeCalled = false
val ld = callbackFlow {
testScope.launch {
- offer(1)
- offer(2)
+ trySend(1)
+ trySend(2)
delay(1000)
- offer(3)
+ trySend(3)
}
awaitClose {
closeCalled = true
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/current.txt b/lifecycle/lifecycle-viewmodel-compose/api/current.txt
index 6fe3f20..cf7f13f 100644
--- a/lifecycle/lifecycle-viewmodel-compose/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel-compose/api/current.txt
@@ -9,8 +9,8 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
- method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static <VM extends androidx.lifecycle.ViewModel> VM viewModel(Class<VM> modelClass, optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! viewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
}
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
index 6fe3f20..cf7f13f 100644
--- a/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-viewmodel-compose/api/public_plus_experimental_current.txt
@@ -9,8 +9,8 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
- method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static <VM extends androidx.lifecycle.ViewModel> VM viewModel(Class<VM> modelClass, optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! viewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
}
diff --git a/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
index 6fe3f20..cf7f13f 100644
--- a/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
+++ b/lifecycle/lifecycle-viewmodel-compose/api/restricted_current.txt
@@ -9,8 +9,8 @@
}
public final class ViewModelKt {
- method @androidx.compose.runtime.Composable public static <T extends androidx.lifecycle.ViewModel> T viewModel(Class<T> modelClass, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
- method @androidx.compose.runtime.Composable public static inline <reified T extends androidx.lifecycle.ViewModel> T! viewModel(optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static <VM extends androidx.lifecycle.ViewModel> VM viewModel(Class<VM> modelClass, optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String? key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
+ method @androidx.compose.runtime.Composable public static inline <reified VM extends androidx.lifecycle.ViewModel> VM! viewModel(optional androidx.lifecycle.ViewModelStoreOwner viewModelStoreOwner, optional String key, optional androidx.lifecycle.ViewModelProvider.Factory? factory);
}
}
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
index fbc90b5..594a2e2 100644
--- a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInComponentActivityTest.kt
@@ -22,6 +22,7 @@
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.LifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.MediumTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
@@ -62,6 +63,7 @@
assertEquals(activity, owner)
}
+ @FlakyTest(bugId = 190609144)
@Test
public fun lifecycleOwnerIsAvailableWhenComposedIntoViewGroup() {
val latch = CountDownLatch(1)
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
index a6ba005..1e7ebc0 100644
--- a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelInFragmentTest.kt
@@ -24,6 +24,7 @@
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.ViewModel
+import androidx.test.filters.FlakyTest
import androidx.test.filters.MediumTest
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -55,6 +56,7 @@
activity = activityTestRule.activity
}
+ @FlakyTest(bugId = 190608770)
@Test
public fun viewModelCreatedInFragment() {
val fragment = TestFragment(viewModelClass)
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
index a35f98b..e4a868d 100644
--- a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
@@ -81,13 +81,16 @@
@Test
public fun viewModelCreatedViaDefaultFactory() {
val owner = FakeViewModelStoreOwner()
+ var createdInComposition: Any? = null
rule.setContent {
CompositionLocalProvider(LocalViewModelStoreOwner provides owner) {
- viewModel<TestViewModel>()
+ createdInComposition = viewModel<TestViewModel>()
}
}
assertThat(owner.factory.createCalled).isTrue()
+ val createdManually = ViewModelProvider(owner).get(TestViewModel::class.java)
+ assertThat(createdInComposition).isEqualTo(createdManually)
}
@Test
@@ -96,36 +99,6 @@
var createdInComposition: Any? = null
rule.setContent {
CompositionLocalProvider(LocalViewModelStoreOwner provides owner) {
- createdInComposition = viewModel<TestViewModel>()
- }
- }
-
- assertThat(owner.factory.createCalled).isTrue()
- val createdManually = ViewModelProvider(owner).get(TestViewModel::class.java)
- assertThat(createdInComposition).isEqualTo(createdManually)
- }
-
- @Test
- public fun createdViewModelIsEqualsToCreatedManually() {
- val owner = FakeViewModelStoreOwner()
- var createdInComposition: Any? = null
- rule.setContent {
- CompositionLocalProvider(LocalViewModelStoreOwner provides owner) {
- createdInComposition = viewModel<TestViewModel>()
- }
- }
-
- assertThat(owner.factory.createCalled).isTrue()
- val createdManually = ViewModelProvider(owner).get(TestViewModel::class.java)
- assertThat(createdInComposition).isEqualTo(createdManually)
- }
-
- @Test
- public fun createdViewModelIsEqualsToCreatedManuallyWithKey() {
- val owner = FakeViewModelStoreOwner()
- var createdInComposition: Any? = null
- rule.setContent {
- CompositionLocalProvider(LocalViewModelStoreOwner provides owner) {
createdInComposition =
viewModel<TestViewModel>(key = "test")
}
@@ -137,6 +110,23 @@
}
@Test
+ public fun viewModelCreatedViaDefaultFactoryWithCustomOwner() {
+ val customOwner = FakeViewModelStoreOwner()
+ val owner = FakeViewModelStoreOwner()
+ var createdInComposition: Any? = null
+ rule.setContent {
+ CompositionLocalProvider(LocalViewModelStoreOwner provides owner) {
+ createdInComposition = viewModel<TestViewModel>(customOwner)
+ }
+ }
+
+ assertThat(owner.factory.createCalled).isFalse()
+ assertThat(customOwner.factory.createCalled).isTrue()
+ val createdManually = ViewModelProvider(customOwner).get(TestViewModel::class.java)
+ assertThat(createdInComposition).isEqualTo(createdManually)
+ }
+
+ @Test
public fun customFactoryIsUsedWhenProvided() {
val owner = FakeViewModelStoreOwner()
val customFactory = FakeViewModelProviderFactory()
@@ -150,6 +140,17 @@
}
@Test
+ public fun customFactoryProducerIsUsedWhenProvided() {
+ val owner = FakeViewModelStoreOwner()
+ val customFactory = FakeViewModelProviderFactory()
+ rule.setContent {
+ viewModel<TestViewModel>(owner, factory = customFactory)
+ }
+
+ assertThat(customFactory.createCalled).isTrue()
+ }
+
+ @Test
public fun defaultFactoryIsNotUsedWhenCustomProvided() {
val owner = FakeViewModelStoreOwner()
val customFactory = FakeViewModelProviderFactory()
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt
index f6f32e2..70bf232 100644
--- a/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/main/java/androidx/lifecycle/viewmodel/compose/ViewModel.kt
@@ -22,51 +22,60 @@
import androidx.lifecycle.ViewModelStoreOwner
/**
- * Returns an existing [ViewModel] or creates a new one in the scope (usually, a fragment or
- * an activity)
+ * Returns an existing [ViewModel] or creates a new one in the given owner (usually, a fragment or
+ * an activity), defaulting to the owner provided by [LocalViewModelStoreOwner].
*
- * The created [ViewModel] is associated with the given scope and will be retained
- * as long as the scope is alive (e.g. if it is an activity, until it is
+ * The created [ViewModel] is associated with the given [viewModelStoreOwner] and will be retained
+ * as long as the owner is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
+ * @param viewModelStoreOwner The owner of the [ViewModel] that controls the scope and lifetime
+ * of the returned [ViewModel]. Defaults to using [LocalViewModelStoreOwner].
* @param key The key to use to identify the [ViewModel].
- * @return A [ViewModel] that is an instance of the given [T] type.
+ * @param factory The [ViewModelProvider.Factory] that should be used to create the [ViewModel]
+ * or null if you would like to use the default factory from the [LocalViewModelStoreOwner]
+ * @return A [ViewModel] that is an instance of the given [VM] type.
*/
@Suppress("MissingJvmstatic")
@Composable
-public inline fun <reified T : ViewModel> viewModel(
+public inline fun <reified VM : ViewModel> viewModel(
+ viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
+ "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
+ },
key: String? = null,
factory: ViewModelProvider.Factory? = null
-): T = viewModel(T::class.java, key, factory)
+): VM = viewModel(VM::class.java, viewModelStoreOwner, key, factory)
/**
* Returns an existing [ViewModel] or creates a new one in the scope (usually, a fragment or
* an activity)
*
- * The created [ViewModel] is associated with the given scope and will be retained
+ * The created [ViewModel] is associated with the given [viewModelStoreOwner] and will be retained
* as long as the scope is alive (e.g. if it is an activity, until it is
* finished or process is killed).
*
* @param modelClass The class of the [ViewModel] to create an instance of it if it is not
* present.
+ * @param viewModelStoreOwner The scope that the created [ViewModel] should be associated with.
* @param key The key to use to identify the [ViewModel].
- * @return A [ViewModel] that is an instance of the given [T] type.
+ * @return A [ViewModel] that is an instance of the given [VM] type.
*/
@Suppress("MissingJvmstatic")
@Composable
-public fun <T : ViewModel> viewModel(
- modelClass: Class<T>,
+public fun <VM : ViewModel> viewModel(
+ modelClass: Class<VM>,
+ viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
+ "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
+ },
key: String? = null,
factory: ViewModelProvider.Factory? = null
-): T = checkNotNull(LocalViewModelStoreOwner.current) {
- "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
-}.get(modelClass, key, factory)
+): VM = viewModelStoreOwner.get(modelClass, key, factory)
-private fun <T : ViewModel> ViewModelStoreOwner.get(
- javaClass: Class<T>,
+private fun <VM : ViewModel> ViewModelStoreOwner.get(
+ javaClass: Class<VM>,
key: String? = null,
factory: ViewModelProvider.Factory? = null
-): T {
+): VM {
val provider = if (factory != null) {
ViewModelProvider(this, factory)
} else {
diff --git a/lint-checks/build.gradle b/lint-checks/build.gradle
index 00164a2..daf6692 100644
--- a/lint-checks/build.gradle
+++ b/lint-checks/build.gradle
@@ -16,8 +16,6 @@
import androidx.build.LibraryType
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -33,7 +31,7 @@
dependencies {
compileOnly(libs.androidLintApi)
- compileOnly(LINT_CHECKS_LATEST)
+ compileOnly(libs.androidLintChecks)
compileOnly(libs.kotlinStdlib)
testImplementation(libs.kotlinStdlib)
diff --git a/lint-checks/integration-tests/src/main/java/androidx/ClassVerificationFailureFromJava.java b/lint-checks/integration-tests/src/main/java/androidx/ClassVerificationFailureFromJava.java
index e0cea96..9aaa657 100644
--- a/lint-checks/integration-tests/src/main/java/androidx/ClassVerificationFailureFromJava.java
+++ b/lint-checks/integration-tests/src/main/java/androidx/ClassVerificationFailureFromJava.java
@@ -16,7 +16,6 @@
package androidx;
-import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.os.Build;
import android.view.View;
@@ -53,7 +52,6 @@
/**
* Unsafe reference to a new API whose auto-fix collides with the existing Api28Impl class.
*/
- @SuppressLint("NewApi")
CharSequence unsafeReferenceWithAutoFixCollision(View view) {
return view.getAccessibilityClassName();
}
diff --git a/media/media/src/main/java/androidx/media/AudioAttributesImplApi21.java b/media/media/src/main/java/androidx/media/AudioAttributesImplApi21.java
index 001a470..6e0f68f 100644
--- a/media/media/src/main/java/androidx/media/AudioAttributesImplApi21.java
+++ b/media/media/src/main/java/androidx/media/AudioAttributesImplApi21.java
@@ -19,7 +19,6 @@
import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static androidx.media.AudioAttributesCompat.INVALID_STREAM_TYPE;
-import android.annotation.SuppressLint;
import android.media.AudioAttributes;
import androidx.annotation.NonNull;
@@ -72,7 +71,6 @@
}
@Override
- @SuppressLint("NewApi")
public int getVolumeControlStream() {
// TODO: address the framework change ag/4995785.
return AudioAttributesCompat.toVolumeStreamType(true, getFlags(), getUsage());
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderService.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderService.java
index 3956711..3da9950 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderService.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouteProviderService.java
@@ -56,7 +56,6 @@
import static androidx.mediarouter.media.MediaRouteProviderProtocol.isValidRemoteMessenger;
import static androidx.mediarouter.media.MediaRouter.UNSELECT_REASON_UNKNOWN;
-import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
@@ -180,8 +179,6 @@
/**
* Creates a media route provider service.
*/
- //TODO: Remove SuppressLint when R version is finalized.
- @SuppressLint("NewApi")
public MediaRouteProviderService() {
mReceiveHandler = new ReceiveHandler(this);
mReceiveMessenger = new Messenger(mReceiveHandler);
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
index 91db8ba..360efa1 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/MediaRouter2Utils.java
@@ -26,7 +26,6 @@
import static androidx.mediarouter.media.MediaRouter.RouteInfo.DEVICE_TYPE_TV;
import static androidx.mediarouter.media.MediaRouter.RouteInfo.DEVICE_TYPE_UNKNOWN;
-import android.annotation.SuppressLint;
import android.content.IntentFilter;
import android.media.MediaRoute2Info;
import android.media.RouteDiscoveryPreference;
@@ -45,8 +44,6 @@
import java.util.List;
import java.util.Set;
-//TODO: Remove SuppressLInt
-@SuppressLint("NewApi")
@RequiresApi(api = Build.VERSION_CODES.R)
class MediaRouter2Utils {
static final String FEATURE_EMPTY = "android.media.route.feature.EMPTY";
diff --git a/mppsample/mppsample-executable/build.gradle b/mppsample/mppsample-executable/build.gradle
index ce5abc6..332519e 100644
--- a/mppsample/mppsample-executable/build.gradle
+++ b/mppsample/mppsample-executable/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("kotlin-multiplatform")
}
diff --git a/mppsample/mppsample-library/build.gradle b/mppsample/mppsample-library/build.gradle
index 398c66f..45ddd3f 100644
--- a/mppsample/mppsample-library/build.gradle
+++ b/mppsample/mppsample-library/build.gradle
@@ -16,8 +16,6 @@
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("kotlin-multiplatform")
id("AndroidXPlugin")
@@ -39,13 +37,13 @@
// included (implicit "dependsOn") in all sourcesets in the Kotlin MPP presets.
commonMain {
dependencies {
- implementation(KOTLIN_STDLIB_COMMON)
+ implementation(libs.kotlinStdlibCommon)
}
}
commonTest {
dependencies {
- implementation(KOTLIN_TEST_COMMON)
- implementation(KOTLIN_TEST_ANNOTATIONS_COMMON)
+ implementation(libs.kotlinTestCommon)
+ implementation(libs.kotlinTestAnnotationsCommon)
}
}
// Note that although we don't have androidXYZ/ directories, Android targets are still
@@ -62,25 +60,25 @@
}
jvmMain {
dependencies {
- implementation(KOTLIN_STDLIB_JDK8)
+ implementation(libs.kotlinStdlibJdk8)
}
}
// jvmTest differs from androidTest in that it fails at compile-time if any android
// dependencies are included, whereas androidTest fails at runtime only if they are used.
jvmTest {
dependencies {
- implementation(KOTLIN_TEST)
- implementation(KOTLIN_TEST_JUNIT)
+ implementation(libs.kotlinTest)
+ implementation(libs.kotlinTestJunit)
}
}
jsMain {
dependencies {
- implementation(KOTLIN_STDLIB_JS)
+ implementation(libs.kotlinStdlibJs)
}
}
jsTest {
dependencies {
- implementation(KOTLIN_TEST_JS)
+ implementation(libs.kotlinTestJs)
}
}
}
diff --git a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
index c2e4857..a958422 100644
--- a/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
+++ b/navigation/navigation-runtime/src/androidTest/java/androidx/navigation/NavControllerTest.kt
@@ -855,6 +855,22 @@
@UiThreadTest
@Test
+ fun testNavigateFromOnDestinationChangedListener() {
+ val navController = createNavController()
+ navController.setGraph(R.navigation.nav_simple)
+
+ var lastReceivedDestinationId = -1
+ navController.addOnDestinationChangedListener { _, destination, _ ->
+ lastReceivedDestinationId = destination.id
+ if (destination.id == R.id.start_test) {
+ navController.navigate(R.id.second_test)
+ }
+ }
+ assertThat(lastReceivedDestinationId).isEqualTo(R.id.second_test)
+ }
+
+ @UiThreadTest
+ @Test
fun testNavigateArgs() {
val navController = createNavController()
navController.setGraph(R.navigation.nav_arguments)
@@ -1642,6 +1658,27 @@
@UiThreadTest
@Test
+ fun testNavigateOptionPopNestedGraph() {
+ val navController = createNavController()
+ navController.setGraph(R.navigation.nav_multiple_navigation)
+ assertThat(navController.currentDestination?.id ?: 0)
+ .isEqualTo(R.id.simple_child_start_test)
+ val navigator = navController.navigatorProvider.getNavigator(TestNavigator::class.java)
+ assertThat(navigator.backStack.size).isEqualTo(1)
+
+ navController.navigate(R.id.navigate_pop_base)
+ assertThat(navController.currentDestination?.id ?: 0)
+ .isEqualTo(R.id.deep_link_child_start_test)
+ assertThat(navigator.backStack.size).isEqualTo(1)
+
+ navController.navigate(R.id.navigate_start_pop_base)
+ assertThat(navController.currentDestination?.id ?: 0)
+ .isEqualTo(R.id.simple_child_start_test)
+ assertThat(navigator.backStack.size).isEqualTo(1)
+ }
+
+ @UiThreadTest
+ @Test
fun testNavigateViaActionWithArgs() {
val navController = createNavController()
navController.setGraph(R.navigation.nav_arguments)
diff --git a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml
index 1f62231..dbf8e76f 100644
--- a/navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml
+++ b/navigation/navigation-runtime/src/androidTest/res/navigation/nav_multiple_navigation.xml
@@ -30,6 +30,11 @@
app:destination="@+id/simple_child_second_test"
app:popUpTo="@id/simple_child_start_test"
app:popUpToInclusive="true"/>
+ <action
+ android:id="@+id/navigate_pop_base"
+ app:destination="@+id/deep_link_child_start"
+ app:popUpTo="@id/nav_multi_module_base"
+ app:popUpToInclusive="true"/>
</test>
<test android:id="@+id/simple_child_second_test"/>
</navigation>
@@ -40,6 +45,11 @@
<test android:id="@+id/deep_link_child_start_test">
<action android:id="@+id/deep_link_child_second"
app:destination="@+id/deep_link_child_second_test" />
+ <action
+ android:id="@+id/navigate_start_pop_base"
+ app:destination="@+id/simple_child_start"
+ app:popUpTo="@id/nav_multi_module_base"
+ app:popUpToInclusive="true"/>
</test>
<test android:id="@+id/deep_link_child_second_test">
diff --git a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
index fc4bde0..a05bb45 100644
--- a/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
+++ b/navigation/navigation-runtime/src/main/java/androidx/navigation/NavController.kt
@@ -293,6 +293,8 @@
* @param listener the listener to receive events
*/
public open fun addOnDestinationChangedListener(listener: OnDestinationChangedListener) {
+ onDestinationChangedListeners.add(listener)
+
// Inform the new listener of our current state, if any
if (backQueue.isNotEmpty()) {
val backStackEntry = backQueue.last()
@@ -302,7 +304,6 @@
backStackEntry.arguments
)
}
- onDestinationChangedListeners.add(listener)
}
/**
@@ -1534,6 +1535,18 @@
) {
// Keep popping
}
+
+ // The _graph should always be on the top of the back stack after you navigate()
+ val firstEntry = backQueue.firstOrNull() ?: hierarchy.firstOrNull()
+ if (firstEntry?.destination != _graph) {
+ val entry = restoredEntries.lastOrNull { restoredEntry ->
+ restoredEntry.destination == _graph!!
+ } ?: NavBackStackEntry.create(
+ context, _graph!!, _graph!!.addInDefaultArgs(finalArgs), lifecycleOwner, viewModel
+ )
+ hierarchy.addFirst(entry)
+ }
+
// Now add the parent hierarchy to the NavigatorStates and back stack
hierarchy.forEach { entry ->
val navigator = _navigatorProvider.getNavigator<Navigator<*>>(
@@ -1545,22 +1558,7 @@
navigatorBackStack.addInternal(entry)
}
backQueue.addAll(hierarchy)
- // The _graph should always be on the back stack after you navigate()
- if (backQueue.isEmpty() || backQueue.first().destination !== _graph) {
- val entry = restoredEntries.lastOrNull { restoredEntry ->
- restoredEntry.destination == _graph!!
- } ?: NavBackStackEntry.create(
- context, _graph!!, _graph!!.addInDefaultArgs(finalArgs), lifecycleOwner, viewModel
- )
- val navigator = _navigatorProvider.getNavigator<Navigator<*>>(
- entry.destination.navigatorName
- )
- val navigatorBackStack = checkNotNull(navigatorState[navigator]) {
- "NavigatorBackStack for ${node.navigatorName} should already be created"
- }
- navigatorBackStack.addInternal(entry)
- backQueue.addFirst(entry)
- }
+
// And finally, add the new destination
backQueue.add(backStackEntry)
}
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
index 395be34..1ee2895 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/ArgumentsGenerationTask.kt
@@ -55,7 +55,7 @@
abstract val useAndroidX: Property<Boolean>
@get:Input
- abstract var generateKotlin: Property<Boolean>
+ abstract val generateKotlin: Property<Boolean>
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
index d9253cd..c711491 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
@@ -73,8 +73,16 @@
variantExtension.onVariants { variant ->
when (variant) {
is ApplicationVariant, is DynamicFeatureVariant ->
- applicationIds.getOrPut(variant.name) {
- variant.applicationId
+ // Using reflection for AGP 7.0+ cause it can't resolve that
+ // DynamicFeatureVariant implements GeneratesApk so the `applicationId`
+ // property is actually available. Once we upgrade to 7.0 we will use
+ // getNamespace().
+ variant::class.java.getDeclaredMethod("getApplicationId").let { method ->
+ method.trySetAccessible()
+ applicationIds.getOrPut(variant.name) {
+ @kotlin.Suppress("UNCHECKED_CAST")
+ method.invoke(variant) as Provider<String>
+ }
}
}
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
index cdf77c1..2dff161 100644
--- a/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/LegacyPagingSource.kt
@@ -25,6 +25,7 @@
import androidx.paging.LoadType.PREPEND
import androidx.paging.LoadType.REFRESH
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -34,6 +35,7 @@
*
* @hide
*/
+@OptIn(DelicateCoroutinesApi::class)
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class LegacyPagingSource<Key : Any, Value : Any>(
private val fetchDispatcher: CoroutineDispatcher,
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
index c849a44..6f942fc 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -100,7 +100,7 @@
// Wrap collection behind a RendezvousChannel to prevent the RetryChannel from buffering
// retry signals.
val retryChannel = Channel<Unit>(Channel.RENDEZVOUS)
- launch { retryFlow.collect { retryChannel.offer(it) } }
+ launch { retryFlow.collect { retryChannel.trySend(it) } }
// Start collection on retry signals.
launch {
diff --git a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshotState.kt b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshotState.kt
index b27e1b8..dcf138b 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshotState.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PageFetcherSnapshotState.kt
@@ -110,12 +110,12 @@
fun consumePrependGenerationIdAsFlow(): Flow<Int> {
return prependGenerationIdCh.consumeAsFlow()
- .onStart { prependGenerationIdCh.offer(prependGenerationId) }
+ .onStart { prependGenerationIdCh.trySend(prependGenerationId) }
}
fun consumeAppendGenerationIdAsFlow(): Flow<Int> {
return appendGenerationIdCh.consumeAsFlow()
- .onStart { appendGenerationIdCh.offer(appendGenerationId) }
+ .onStart { appendGenerationIdCh.trySend(appendGenerationId) }
}
fun setSourceLoadState(type: LoadType, newState: LoadState): Boolean {
@@ -251,7 +251,7 @@
placeholdersBefore = event.placeholdersRemaining
prependGenerationId++
- prependGenerationIdCh.offer(prependGenerationId)
+ prependGenerationIdCh.trySend(prependGenerationId)
}
APPEND -> {
repeat(event.pageCount) { _pages.removeAt(pages.size - 1) }
@@ -259,7 +259,7 @@
placeholdersAfter = event.placeholdersRemaining
appendGenerationId++
- appendGenerationIdCh.offer(appendGenerationId)
+ appendGenerationIdCh.trySend(appendGenerationId)
}
else -> throw IllegalArgumentException("cannot drop ${event.loadType}")
}
diff --git a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
index 39b8e5c..149958d 100644
--- a/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
+++ b/paging/common/src/main/kotlin/androidx/paging/PagedList.kt
@@ -21,6 +21,7 @@
import androidx.annotation.RestrictTo
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
@@ -258,6 +259,7 @@
private var dataSource: DataSource<Key, Value>?
private val initialPage: PagingSource.LoadResult.Page<Key, Value>?
private val config: Config
+ @OptIn(DelicateCoroutinesApi::class)
private var coroutineScope: CoroutineScope = GlobalScope
private var notifyDispatcher: CoroutineDispatcher? = null
private var fetchDispatcher: CoroutineDispatcher? = null
diff --git a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
index 0334f4f..71166f4 100644
--- a/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/LegacyPageFetcherTest.kt
@@ -27,6 +27,7 @@
import androidx.paging.PagingSource.LoadResult
import androidx.paging.PagingSource.LoadResult.Page
import androidx.testutils.TestDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
@@ -110,6 +111,7 @@
}
}
+ @OptIn(DelicateCoroutinesApi::class)
private fun createPager(
consumer: MockConsumer,
start: Int = 0,
diff --git a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
index 8320485..e1562f4 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PageFetcherSnapshotTest.kt
@@ -35,6 +35,7 @@
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
@@ -3338,6 +3339,7 @@
}
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun pageEventSentAfterChannelClosed() {
val pager = PageFetcherSnapshot(
diff --git a/paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt b/paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
index 883b4f2..2b02f56 100644
--- a/paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/PagingDataDifferTest.kt
@@ -149,7 +149,7 @@
val differ = SimpleDiffer(dummyDifferCallback)
val pageEventCh = Channel<PageEvent<Int>>(Channel.UNLIMITED)
- pageEventCh.offer(
+ pageEventCh.trySend(
Refresh(
pages = listOf(TransformablePage(0, listOf(0, 1))),
placeholdersBefore = 4,
@@ -157,14 +157,14 @@
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-1, listOf(-1, -2))),
placeholdersBefore = 2,
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Append(
pages = listOf(TransformablePage(1, listOf(2, 3))),
placeholdersAfter = 2,
@@ -205,7 +205,7 @@
// Insert a new page, PagingDataDiffer should try to resend hint since index 0 still points
// to a placeholder:
// [null, null, [], [-1], [1], [3], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-2, listOf())),
placeholdersBefore = 2,
@@ -227,7 +227,7 @@
// Now index 0 has been loaded:
// [[-3], [], [-1], [1], [3], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-3, listOf(-3, -4))),
placeholdersBefore = 0,
@@ -257,7 +257,7 @@
// Should only resend the hint for index 5, since index 0 has already been loaded:
// [[-3], [], [-1], [1], [3], [], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Append(
pages = listOf(TransformablePage(2, listOf())),
placeholdersAfter = 2,
@@ -283,7 +283,7 @@
// Index 5 hasn't loaded, but we are at the end of the list:
// [[-3], [], [-1], [1], [3], [], [5]]
- pageEventCh.offer(
+ pageEventCh.trySend(
Append(
pages = listOf(TransformablePage(3, listOf(4, 5))),
placeholdersAfter = 0,
@@ -305,7 +305,7 @@
val differ = SimpleDiffer(dummyDifferCallback)
val pageEventCh = Channel<PageEvent<Int>>(Channel.UNLIMITED)
- pageEventCh.offer(
+ pageEventCh.trySend(
Refresh(
pages = listOf(TransformablePage(0, listOf(0, 1))),
placeholdersBefore = 4,
@@ -313,14 +313,14 @@
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-1, listOf(-1, -2))),
placeholdersBefore = 2,
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Append(
pages = listOf(TransformablePage(1, listOf(2, 3))),
placeholdersAfter = 2,
@@ -361,7 +361,7 @@
// Insert a new page, PagingDataDiffer should try to resend hint since index 0 still points
// to a placeholder:
// [null, null, [], [-1], [1], [3], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-2, listOf())),
placeholdersBefore = 2,
@@ -383,7 +383,7 @@
// Drop the previous page, which reset resendable index state in the PREPEND direction.
// [null, null, [-1], [1], [3], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Drop(
loadType = PREPEND,
minPageOffset = -2,
@@ -395,7 +395,7 @@
// Re-insert the previous page, which should not trigger resending the index due to
// previous page drop:
// [[-3], [], [-1], [1], [3], null, null]
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-2, listOf())),
placeholdersBefore = 2,
@@ -410,7 +410,7 @@
fun peek() = testScope.runBlockingTest {
val differ = SimpleDiffer(dummyDifferCallback)
val pageEventCh = Channel<PageEvent<Int>>(Channel.UNLIMITED)
- pageEventCh.offer(
+ pageEventCh.trySend(
Refresh(
pages = listOf(TransformablePage(0, listOf(0, 1))),
placeholdersBefore = 4,
@@ -418,14 +418,14 @@
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Prepend(
pages = listOf(TransformablePage(-1, listOf(-1, -2))),
placeholdersBefore = 2,
combinedLoadStates = CombinedLoadStates.IDLE_SOURCE
)
)
- pageEventCh.offer(
+ pageEventCh.trySend(
Append(
pages = listOf(TransformablePage(1, listOf(2, 3))),
placeholdersAfter = 2,
@@ -471,7 +471,7 @@
differ.collectFrom(PagingData(pageEventCh.consumeAsFlow(), uiReceiver))
}
- pageEventCh.offer(
+ pageEventCh.trySend(
Refresh(
pages = listOf(TransformablePage(emptyList())),
placeholdersBefore = 0,
diff --git a/paging/common/src/test/kotlin/androidx/paging/SingleRunnerTest.kt b/paging/common/src/test/kotlin/androidx/paging/SingleRunnerTest.kt
index 7e6ec72..fe0890e 100644
--- a/paging/common/src/test/kotlin/androidx/paging/SingleRunnerTest.kt
+++ b/paging/common/src/test/kotlin/androidx/paging/SingleRunnerTest.kt
@@ -18,6 +18,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
@@ -140,6 +141,7 @@
assertThat(output.joinToString("")).isEqualTo("0a1b2c3d")
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun ensureIsolation_whenCancelationIsIgnoredByThePreviousBlock() {
// make sure we wait for previous one if it ignores cancellation
diff --git a/paging/paging-compose/src/androidTest/java/androidx/paging/compose/LazyPagingItemsTest.kt b/paging/paging-compose/src/androidTest/java/androidx/paging/compose/LazyPagingItemsTest.kt
index 186fb30..e641eb0 100644
--- a/paging/paging-compose/src/androidTest/java/androidx/paging/compose/LazyPagingItemsTest.kt
+++ b/paging/paging-compose/src/androidTest/java/androidx/paging/compose/LazyPagingItemsTest.kt
@@ -34,6 +34,7 @@
import androidx.paging.PagingSource
import androidx.paging.TestPagingSource
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
@@ -63,6 +64,7 @@
return Pager(config = config, pagingSourceFactory = pagingSourceFactory)
}
+ @FlakyTest(bugId = 190609811)
@Test
fun lazyPagingColumnShowsItems() {
val pager = createPager()
@@ -120,6 +122,7 @@
.assertDoesNotExist()
}
+ @FlakyTest(bugId = 190609811)
@Test
fun lazyPagingRowShowsItems() {
val pager = createPager()
@@ -366,6 +369,7 @@
.assertDoesNotExist()
}
+ @FlakyTest(bugId = 190609811)
@Test
fun updatingItem() {
val items = mutableListOf(1, 2, 3)
diff --git a/paging/runtime/ktx/build.gradle b/paging/runtime/ktx/build.gradle
index 93115b1..96c0ff3 100644
--- a/paging/runtime/ktx/build.gradle
+++ b/paging/runtime/ktx/build.gradle
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
plugins {
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListTest.kt b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListTest.kt
index 8a8be14..c3138ca 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListTest.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/LivePagedListTest.kt
@@ -26,6 +26,7 @@
import androidx.test.filters.SmallTest
import androidx.testutils.TestDispatcher
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
@@ -44,6 +45,7 @@
@Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun instantiatesPagingSourceOnFetchDispatcher() {
var pagingSourcesCreated = 0
diff --git a/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt b/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
index 801ffb9..2f208b5 100644
--- a/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
+++ b/paging/runtime/src/androidTest/java/androidx/paging/StringPagedList.kt
@@ -19,6 +19,7 @@
import androidx.paging.PagingSource.LoadResult.Error
import androidx.paging.PagingSource.LoadResult.Page
import androidx.testutils.DirectDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
@@ -46,6 +47,7 @@
override fun getRefreshKey(state: PagingState<Any, Value>): Any? = null
}
+@OptIn(DelicateCoroutinesApi::class)
@Suppress("TestFunctionName", "DEPRECATION")
fun StringPagedList(
leadingNulls: Int,
diff --git a/paging/runtime/src/main/java/androidx/paging/LivePagedList.kt b/paging/runtime/src/main/java/androidx/paging/LivePagedList.kt
index e9b696a..4addf51 100644
--- a/paging/runtime/src/main/java/androidx/paging/LivePagedList.kt
+++ b/paging/runtime/src/main/java/androidx/paging/LivePagedList.kt
@@ -23,6 +23,7 @@
import androidx.paging.LoadType.REFRESH
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.asCoroutineDispatcher
@@ -228,6 +229,7 @@
*
* @see LivePagedListBuilder
*/
+@OptIn(DelicateCoroutinesApi::class)
@Suppress("DEPRECATION")
@Deprecated(
message = "PagedList is deprecated and has been replaced by PagingData",
@@ -286,6 +288,7 @@
*
* @see LivePagedListBuilder
*/
+@OptIn(DelicateCoroutinesApi::class)
@Suppress("DEPRECATION")
@Deprecated(
message = "PagedList is deprecated and has been replaced by PagingData",
diff --git a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
index 907a45a..c770466 100644
--- a/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
+++ b/paging/runtime/src/main/java/androidx/paging/LivePagedListBuilder.kt
@@ -19,6 +19,7 @@
import androidx.arch.core.executor.ArchTaskExecutor
import androidx.lifecycle.LiveData
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executor
@@ -43,6 +44,7 @@
@Suppress("DEPRECATION")
private val config: PagedList.Config
+ @OptIn(DelicateCoroutinesApi::class)
private var coroutineScope: CoroutineScope = GlobalScope
private var initialLoadKey: Key? = null
diff --git a/paging/rxjava2/ktx/build.gradle b/paging/rxjava2/ktx/build.gradle
index 84384a3..bcf38de 100644
--- a/paging/rxjava2/ktx/build.gradle
+++ b/paging/rxjava2/ktx/build.gradle
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
plugins {
diff --git a/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt b/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
index 9397d75..b3b7ad4 100644
--- a/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
+++ b/paging/rxjava2/src/main/java/androidx/paging/RxPagedListBuilder.kt
@@ -27,6 +27,7 @@
import io.reactivex.Scheduler
import io.reactivex.functions.Cancellable
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@@ -334,6 +335,7 @@
return buildObservable().toFlowable(backpressureStrategy)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Suppress("DEPRECATION")
internal class PagingObservableOnSubscribe<Key : Any, Value : Any>(
initialLoadKey: Key?,
diff --git a/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxPagingData.kt b/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxPagingData.kt
index 1fac47a..35d63af 100644
--- a/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxPagingData.kt
+++ b/paging/rxjava2/src/main/java/androidx/paging/rxjava2/RxPagingData.kt
@@ -28,6 +28,7 @@
import io.reactivex.Maybe
import io.reactivex.Single
import kotlinx.coroutines.rx2.await
+import kotlinx.coroutines.rx2.awaitSingleOrNull
/**
* Returns a [PagingData] containing the result of applying the given [transform] to each
@@ -72,4 +73,6 @@
@CheckResult
fun <T : R, R : Any> PagingData<T>.insertSeparatorsAsync(
generator: (T?, T?) -> Maybe<R>
-): PagingData<R> = insertSeparators { before, after -> generator(before, after).await() }
+): PagingData<R> = insertSeparators { before, after ->
+ generator(before, after).awaitSingleOrNull()
+}
diff --git a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagedListBuilder.kt b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagedListBuilder.kt
index 0a48711..a183075 100644
--- a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagedListBuilder.kt
+++ b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagedListBuilder.kt
@@ -36,6 +36,7 @@
import io.reactivex.rxjava3.core.Scheduler
import io.reactivex.rxjava3.functions.Cancellable
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@@ -343,6 +344,7 @@
return buildObservable().toFlowable(backpressureStrategy)
}
+ @OptIn(DelicateCoroutinesApi::class)
@Suppress("DEPRECATION")
internal class PagingObservableOnSubscribe<Key : Any, Value : Any>(
initialLoadKey: Key?,
diff --git a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagingData.kt b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagingData.kt
index c834f33..d5d9a2e 100644
--- a/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagingData.kt
+++ b/paging/rxjava3/src/main/java/androidx/paging/rxjava3/RxPagingData.kt
@@ -28,6 +28,7 @@
import io.reactivex.rxjava3.core.Maybe
import io.reactivex.rxjava3.core.Single
import kotlinx.coroutines.rx3.await
+import kotlinx.coroutines.rx3.awaitSingleOrNull
/**
* Returns a [PagingData] containing the result of applying the given [transform] to each
@@ -72,4 +73,6 @@
@CheckResult
fun <T : R, R : Any> PagingData<T>.insertSeparatorsAsync(
generator: (T?, T?) -> Maybe<R>
-): PagingData<R> = insertSeparators { before, after -> generator(before, after).await() }
+): PagingData<R> = insertSeparators { before, after ->
+ generator(before, after).awaitSingleOrNull()
+}
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index 89d8c66..76f0b30 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -26,7 +26,7 @@
kotlin.code.style=official
# Disable docs
androidx.enableDocumentation=false
-androidx.playground.snapshotBuildId=7405385
+androidx.playground.snapshotBuildId=7440113
androidx.playground.metalavaBuildId=7255182
androidx.playground.dokkaBuildId=7299536
androidx.studio.type=playground
diff --git a/profileinstaller/profileinstaller-benchmark/src/androidTest/java/androidx/profileinstaller/benchmark/ProfileInstallerTranscodeBenchmark.kt b/profileinstaller/profileinstaller-benchmark/src/androidTest/java/androidx/profileinstaller/benchmark/ProfileInstallerTranscodeBenchmark.kt
index 1812a8f..f415a66 100644
--- a/profileinstaller/profileinstaller-benchmark/src/androidTest/java/androidx/profileinstaller/benchmark/ProfileInstallerTranscodeBenchmark.kt
+++ b/profileinstaller/profileinstaller-benchmark/src/androidTest/java/androidx/profileinstaller/benchmark/ProfileInstallerTranscodeBenchmark.kt
@@ -59,6 +59,7 @@
runWithTimingDisabled {
transcoder = DeviceProfileWriter(
assets,
+ Runnable::run,
Diagnostics(),
PROFILE_LOCATION,
mTempCurFile!!,
@@ -71,6 +72,7 @@
private fun assumeDeviceSupportsAot() {
val transcoder = DeviceProfileWriter(
assets,
+ Runnable::run,
Diagnostics(),
PROFILE_LOCATION,
mTempCurFile!!,
@@ -86,6 +88,7 @@
fun deviceAllowsProfileInstallerAotWrites() {
val transcoder = DeviceProfileWriter(
assets,
+ Runnable::run,
Diagnostics(),
PROFILE_LOCATION,
mTempCurFile!!,
@@ -137,6 +140,7 @@
benchmarkRule.measureRepeated {
val transcoder = DeviceProfileWriter(
assets,
+ Runnable::run,
Diagnostics(),
PROFILE_LOCATION,
mTempCurFile!!,
@@ -154,12 +158,12 @@
const val PROFILE_LOCATION = "golden/profileinstaller.prof"
}
- class Diagnostics : ProfileInstaller.Diagnostics {
- override fun diagnostic(code: Int, data: Any?) {
+ class Diagnostics : ProfileInstaller.DiagnosticsCallback {
+ override fun onDiagnosticReceived(code: Int, data: Any?) {
/* no-op */
}
- override fun result(code: Int, data: Any?) {
+ override fun onResultReceived(code: Int, data: Any?) {
/* no-op */
}
}
diff --git a/profileinstaller/profileinstaller/api/1.0.0-beta01.txt b/profileinstaller/profileinstaller/api/1.0.0-beta01.txt
new file mode 100644
index 0000000..80c25f8
--- /dev/null
+++ b/profileinstaller/profileinstaller/api/1.0.0-beta01.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.profileinstaller {
+
+ public class ProfileInstallReceiver extends android.content.BroadcastReceiver {
+ ctor public ProfileInstallReceiver();
+ method public void onReceive(android.content.Context, android.content.Intent?);
+ field public static final String ACTION_INSTALL_PROFILE = "androidx.profileinstaller.action.INSTALL_PROFILE";
+ }
+
+ public class ProfileInstaller {
+ method @WorkerThread public static void writeProfile(android.content.Context);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
+ field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
+ field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
+ field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
+ field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
+ field public static final int RESULT_INSTALL_SUCCESS = 1; // 0x1
+ field public static final int RESULT_IO_EXCEPTION = 7; // 0x7
+ field public static final int RESULT_NOT_WRITABLE = 4; // 0x4
+ field public static final int RESULT_PARSE_EXCEPTION = 8; // 0x8
+ field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
+ }
+
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
+ }
+
+ public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
+ ctor public ProfileInstallerInitializer();
+ method public androidx.profileinstaller.ProfileInstallerInitializer.Result create(android.content.Context);
+ method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+ }
+
+ public static class ProfileInstallerInitializer.Result {
+ ctor public ProfileInstallerInitializer.Result();
+ }
+
+}
+
diff --git a/profileinstaller/profileinstaller/api/current.txt b/profileinstaller/profileinstaller/api/current.txt
index 1f9d6d2..80c25f8 100644
--- a/profileinstaller/profileinstaller/api/current.txt
+++ b/profileinstaller/profileinstaller/api/current.txt
@@ -9,12 +9,11 @@
public class ProfileInstaller {
method @WorkerThread public static void writeProfile(android.content.Context);
- method @WorkerThread public static void writeProfile(android.content.Context, androidx.profileinstaller.ProfileInstaller.Diagnostics);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
- field public static final androidx.profileinstaller.ProfileInstaller.Diagnostics LOG_DIAGNOSTICS;
field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
@@ -25,9 +24,9 @@
field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
}
- public static interface ProfileInstaller.Diagnostics {
- method public void diagnostic(int, Object?);
- method public void result(int, Object?);
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
}
public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
diff --git a/profileinstaller/profileinstaller/api/public_plus_experimental_1.0.0-beta01.txt b/profileinstaller/profileinstaller/api/public_plus_experimental_1.0.0-beta01.txt
new file mode 100644
index 0000000..80c25f8
--- /dev/null
+++ b/profileinstaller/profileinstaller/api/public_plus_experimental_1.0.0-beta01.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.profileinstaller {
+
+ public class ProfileInstallReceiver extends android.content.BroadcastReceiver {
+ ctor public ProfileInstallReceiver();
+ method public void onReceive(android.content.Context, android.content.Intent?);
+ field public static final String ACTION_INSTALL_PROFILE = "androidx.profileinstaller.action.INSTALL_PROFILE";
+ }
+
+ public class ProfileInstaller {
+ method @WorkerThread public static void writeProfile(android.content.Context);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
+ field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
+ field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
+ field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
+ field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
+ field public static final int RESULT_INSTALL_SUCCESS = 1; // 0x1
+ field public static final int RESULT_IO_EXCEPTION = 7; // 0x7
+ field public static final int RESULT_NOT_WRITABLE = 4; // 0x4
+ field public static final int RESULT_PARSE_EXCEPTION = 8; // 0x8
+ field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
+ }
+
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
+ }
+
+ public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
+ ctor public ProfileInstallerInitializer();
+ method public androidx.profileinstaller.ProfileInstallerInitializer.Result create(android.content.Context);
+ method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+ }
+
+ public static class ProfileInstallerInitializer.Result {
+ ctor public ProfileInstallerInitializer.Result();
+ }
+
+}
+
diff --git a/profileinstaller/profileinstaller/api/public_plus_experimental_current.txt b/profileinstaller/profileinstaller/api/public_plus_experimental_current.txt
index 1f9d6d2..80c25f8 100644
--- a/profileinstaller/profileinstaller/api/public_plus_experimental_current.txt
+++ b/profileinstaller/profileinstaller/api/public_plus_experimental_current.txt
@@ -9,12 +9,11 @@
public class ProfileInstaller {
method @WorkerThread public static void writeProfile(android.content.Context);
- method @WorkerThread public static void writeProfile(android.content.Context, androidx.profileinstaller.ProfileInstaller.Diagnostics);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
- field public static final androidx.profileinstaller.ProfileInstaller.Diagnostics LOG_DIAGNOSTICS;
field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
@@ -25,9 +24,9 @@
field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
}
- public static interface ProfileInstaller.Diagnostics {
- method public void diagnostic(int, Object?);
- method public void result(int, Object?);
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
}
public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
diff --git a/profileinstaller/profileinstaller/api/res-1.0.0-beta01.txt b/profileinstaller/profileinstaller/api/res-1.0.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/profileinstaller/profileinstaller/api/res-1.0.0-beta01.txt
diff --git a/profileinstaller/profileinstaller/api/restricted_1.0.0-beta01.txt b/profileinstaller/profileinstaller/api/restricted_1.0.0-beta01.txt
new file mode 100644
index 0000000..80c25f8
--- /dev/null
+++ b/profileinstaller/profileinstaller/api/restricted_1.0.0-beta01.txt
@@ -0,0 +1,43 @@
+// Signature format: 4.0
+package androidx.profileinstaller {
+
+ public class ProfileInstallReceiver extends android.content.BroadcastReceiver {
+ ctor public ProfileInstallReceiver();
+ method public void onReceive(android.content.Context, android.content.Intent?);
+ field public static final String ACTION_INSTALL_PROFILE = "androidx.profileinstaller.action.INSTALL_PROFILE";
+ }
+
+ public class ProfileInstaller {
+ method @WorkerThread public static void writeProfile(android.content.Context);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
+ field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
+ field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
+ field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
+ field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
+ field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
+ field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
+ field public static final int RESULT_INSTALL_SUCCESS = 1; // 0x1
+ field public static final int RESULT_IO_EXCEPTION = 7; // 0x7
+ field public static final int RESULT_NOT_WRITABLE = 4; // 0x4
+ field public static final int RESULT_PARSE_EXCEPTION = 8; // 0x8
+ field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
+ }
+
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
+ }
+
+ public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
+ ctor public ProfileInstallerInitializer();
+ method public androidx.profileinstaller.ProfileInstallerInitializer.Result create(android.content.Context);
+ method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+ }
+
+ public static class ProfileInstallerInitializer.Result {
+ ctor public ProfileInstallerInitializer.Result();
+ }
+
+}
+
diff --git a/profileinstaller/profileinstaller/api/restricted_current.txt b/profileinstaller/profileinstaller/api/restricted_current.txt
index 1f9d6d2..80c25f8 100644
--- a/profileinstaller/profileinstaller/api/restricted_current.txt
+++ b/profileinstaller/profileinstaller/api/restricted_current.txt
@@ -9,12 +9,11 @@
public class ProfileInstaller {
method @WorkerThread public static void writeProfile(android.content.Context);
- method @WorkerThread public static void writeProfile(android.content.Context, androidx.profileinstaller.ProfileInstaller.Diagnostics);
+ method @WorkerThread public static void writeProfile(android.content.Context, java.util.concurrent.Executor, androidx.profileinstaller.ProfileInstaller.DiagnosticsCallback);
field public static final int DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST = 2; // 0x2
field public static final int DIAGNOSTIC_CURRENT_PROFILE_EXISTS = 1; // 0x1
field public static final int DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST = 4; // 0x4
field public static final int DIAGNOSTIC_REF_PROFILE_EXISTS = 3; // 0x3
- field public static final androidx.profileinstaller.ProfileInstaller.Diagnostics LOG_DIAGNOSTICS;
field public static final int RESULT_ALREADY_INSTALLED = 2; // 0x2
field public static final int RESULT_BASELINE_PROFILE_NOT_FOUND = 6; // 0x6
field public static final int RESULT_DESIRED_FORMAT_UNSUPPORTED = 5; // 0x5
@@ -25,9 +24,9 @@
field public static final int RESULT_UNSUPPORTED_ART_VERSION = 3; // 0x3
}
- public static interface ProfileInstaller.Diagnostics {
- method public void diagnostic(int, Object?);
- method public void result(int, Object?);
+ public static interface ProfileInstaller.DiagnosticsCallback {
+ method public void onDiagnosticReceived(int, Object?);
+ method public void onResultReceived(int, Object?);
}
public class ProfileInstallerInitializer implements androidx.startup.Initializer<androidx.profileinstaller.ProfileInstallerInitializer.Result> {
diff --git a/profileinstaller/profileinstaller/build.gradle b/profileinstaller/profileinstaller/build.gradle
index 6d6ad00..40b7e91 100644
--- a/profileinstaller/profileinstaller/build.gradle
+++ b/profileinstaller/profileinstaller/build.gradle
@@ -34,7 +34,6 @@
androidx {
name = "androidx.profileinstaller:profileinstaller"
type = LibraryType.PUBLISHED_LIBRARY
- mavenVersion = LibraryVersions.PROFILEINSTALLER
mavenGroup = LibraryGroups.PROFILEINSTALLER
inceptionYear = "2021"
description = "Allows libraries to prepopulate ahead of time compilation traces to be read by" +
diff --git a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
index 543983b..41bc835 100644
--- a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
+++ b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/DeviceProfileWriter.java
@@ -35,6 +35,7 @@
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Map;
+import java.util.concurrent.Executor;
/**
* Orchestrate device-level profiler decisions.
@@ -62,7 +63,9 @@
@NonNull
private final AssetManager mAssetManager;
@NonNull
- private final ProfileInstaller.Diagnostics mDiagnostics;
+ private final Executor mExecutor;
+ @NonNull
+ private final ProfileInstaller.DiagnosticsCallback mDiagnostics;
@Nullable
private final byte[] mDesiredVersion;
@NonNull
@@ -77,16 +80,23 @@
@Nullable
private byte[] mTranscodedProfile;
+ private void result(@ProfileInstaller.ResultCode int code, @Nullable Object data) {
+ mExecutor.execute(() -> { mDiagnostics.onResultReceived(code, data); });
+ }
+
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
public DeviceProfileWriter(@NonNull AssetManager assetManager,
- @NonNull ProfileInstaller.Diagnostics diagnostics,
- @NonNull String profileSourceLocation, @NonNull File curProfile,
+ @NonNull Executor executor,
+ @NonNull ProfileInstaller.DiagnosticsCallback diagnosticsCallback,
+ @NonNull String profileSourceLocation,
+ @NonNull File curProfile,
@NonNull File refProfile) {
mAssetManager = assetManager;
- mDiagnostics = diagnostics;
+ mExecutor = executor;
+ mDiagnostics = diagnosticsCallback;
mProfileSourceLocation = profileSourceLocation;
mCurProfile = curProfile;
mRefProfile = refProfile;
@@ -99,8 +109,7 @@
@RestrictTo(RestrictTo.Scope.LIBRARY)
public boolean deviceAllowsProfileInstallerAotWrites() {
if (mDesiredVersion == null) {
- mDiagnostics.result(ProfileInstaller.RESULT_UNSUPPORTED_ART_VERSION,
- Build.VERSION.SDK_INT);
+ result(ProfileInstaller.RESULT_UNSUPPORTED_ART_VERSION, Build.VERSION.SDK_INT);
return false;
}
@@ -108,7 +117,7 @@
// It's possible that some OEMs might not allow writing to this directory. If this is
// the case, there's not really anything we can do, so we should quit before doing
// any unnecessary work.
- mDiagnostics.result(ProfileInstaller.RESULT_NOT_WRITABLE, null);
+ result(ProfileInstaller.RESULT_NOT_WRITABLE, null);
return false;
}
@@ -167,16 +176,19 @@
ProfileTranscoder.writeHeader(os, desiredVersion);
Encoding.writeAll(is, os);
}
- mDiagnostics.result(ProfileInstaller.RESULT_INSTALL_SUCCESS, null);
+ mDiagnostics.onResultReceived(
+ ProfileInstaller.RESULT_INSTALL_SUCCESS,
+ null
+ );
}
}
}
} catch (FileNotFoundException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_BASELINE_PROFILE_NOT_FOUND, e);
+ mDiagnostics.onResultReceived(ProfileInstaller.RESULT_BASELINE_PROFILE_NOT_FOUND, e);
} catch (IOException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_IO_EXCEPTION, e);
+ mDiagnostics.onResultReceived(ProfileInstaller.RESULT_IO_EXCEPTION, e);
} catch (IllegalStateException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_PARSE_EXCEPTION, e);
+ mDiagnostics.onResultReceived(ProfileInstaller.RESULT_PARSE_EXCEPTION, e);
}
return this;
}
@@ -216,16 +228,19 @@
);
if (!success) {
- mDiagnostics.result(ProfileInstaller.RESULT_DESIRED_FORMAT_UNSUPPORTED, null);
+ mDiagnostics.onResultReceived(
+ ProfileInstaller.RESULT_DESIRED_FORMAT_UNSUPPORTED,
+ null
+ );
mProfile = null;
return this;
}
mTranscodedProfile = os.toByteArray();
} catch (IOException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_IO_EXCEPTION, e);
+ mDiagnostics.onResultReceived(ProfileInstaller.RESULT_IO_EXCEPTION, e);
} catch (IllegalStateException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_PARSE_EXCEPTION, e);
+ mDiagnostics.onResultReceived(ProfileInstaller.RESULT_PARSE_EXCEPTION, e);
}
mProfile = null;
return this;
@@ -252,11 +267,11 @@
OutputStream os = new FileOutputStream(mCurProfile)
) {
Encoding.writeAll(bis, os);
- mDiagnostics.result(ProfileInstaller.RESULT_INSTALL_SUCCESS, null);
+ result(ProfileInstaller.RESULT_INSTALL_SUCCESS, null);
} catch (FileNotFoundException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_BASELINE_PROFILE_NOT_FOUND, e);
+ result(ProfileInstaller.RESULT_BASELINE_PROFILE_NOT_FOUND, e);
} catch (IOException e) {
- mDiagnostics.result(ProfileInstaller.RESULT_IO_EXCEPTION, e);
+ result(ProfileInstaller.RESULT_IO_EXCEPTION, e);
} finally {
mTranscodedProfile = null;
mProfile = null;
diff --git a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstallReceiver.java b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstallReceiver.java
index aeeaf2e..43a28ad 100644
--- a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstallReceiver.java
+++ b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstallReceiver.java
@@ -43,18 +43,18 @@
public void onReceive(@NonNull Context context, @Nullable Intent intent) {
if (intent == null) return;
if (!ACTION_INSTALL_PROFILE.equals(intent.getAction())) return;
- ProfileInstaller.writeProfile(context, new ResultDiagnostics());
+ ProfileInstaller.writeProfile(context, Runnable::run, new ResultDiagnostics());
}
- class ResultDiagnostics implements ProfileInstaller.Diagnostics {
+ class ResultDiagnostics implements ProfileInstaller.DiagnosticsCallback {
@Override
- public void diagnostic(int code, @Nullable Object data) {
- ProfileInstaller.LOG_DIAGNOSTICS.diagnostic(code, data);
+ public void onDiagnosticReceived(int code, @Nullable Object data) {
+ ProfileInstaller.LOG_DIAGNOSTICS.onDiagnosticReceived(code, data);
}
@Override
- public void result(int code, @Nullable Object data) {
- ProfileInstaller.LOG_DIAGNOSTICS.result(code, data);
+ public void onResultReceived(int code, @Nullable Object data) {
+ ProfileInstaller.LOG_DIAGNOSTICS.onResultReceived(code, data);
setResultCode(code);
}
}
diff --git a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstaller.java b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstaller.java
index b378f5c..349db88 100644
--- a/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstaller.java
+++ b/profileinstaller/profileinstaller/src/main/java/androidx/profileinstaller/ProfileInstaller.java
@@ -30,6 +30,7 @@
import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* Install ahead of time tracing profiles to configure ART to precompile bundled libraries.
@@ -60,7 +61,7 @@
* An object which can be passed to the ProfileInstaller which will receive information
* during the installation process which can be used for logging and telemetry.
*/
- public interface Diagnostics {
+ public interface DiagnosticsCallback {
/**
* The diagnostic method will get called 0 to many times during the installation process,
* and is passed a [code] and optionally [data] which provides some information around
@@ -68,7 +69,7 @@
* @param code An int specifying which diagnostic situation has occurred.
* @param data Optional data passed in that relates to the code passed.
*/
- void diagnostic(@DiagnosticCode int code, @Nullable Object data);
+ void onDiagnosticReceived(@DiagnosticCode int code, @Nullable Object data);
/**
* The result method will get called exactly once per installation, with a [code]
@@ -77,27 +78,46 @@
* @param code An int specifying which result situation has occurred.
* @param data Optional data passed in that relates to the code that was passed.
*/
- void result(@ResultCode int code, @Nullable Object data);
+ void onResultReceived(@ResultCode int code, @Nullable Object data);
}
- private static final Diagnostics EMPTY_DIAGNOSTICS = new Diagnostics() {
+ @SuppressWarnings("SameParameterValue")
+ static void result(
+ @NonNull Executor executor,
+ @NonNull DiagnosticsCallback diagnostics,
+ @ResultCode int code,
+ @Nullable Object data
+ ) {
+ executor.execute(() -> diagnostics.onResultReceived(code, data));
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ static void diagnostic(
+ @NonNull Executor executor,
+ @NonNull DiagnosticsCallback diagnostics,
+ @DiagnosticCode int code,
+ @Nullable Object data
+ ) {
+ executor.execute(() -> diagnostics.onDiagnosticReceived(code, data));
+ }
+
+ private static final DiagnosticsCallback EMPTY_DIAGNOSTICS = new DiagnosticsCallback() {
@Override
- public void diagnostic(int code, @Nullable Object data) {
+ public void onDiagnosticReceived(int code, @Nullable Object data) {
// do nothing
}
@Override
- public void result(int code, @Nullable Object data) {
+ public void onResultReceived(int code, @Nullable Object data) {
// do nothing
}
};
- @SuppressWarnings("unused")
@NonNull
- public static final Diagnostics LOG_DIAGNOSTICS = new Diagnostics() {
+ static final DiagnosticsCallback LOG_DIAGNOSTICS = new DiagnosticsCallback() {
static final String TAG = "ProfileInstaller";
@Override
- public void diagnostic(int code, @Nullable Object data) {
+ public void onDiagnosticReceived(int code, @Nullable Object data) {
String msg = "";
switch (code) {
case DIAGNOSTIC_CURRENT_PROFILE_EXISTS:
@@ -117,7 +137,7 @@
}
@Override
- public void result(int code, @Nullable Object data) {
+ public void onResultReceived(int code, @Nullable Object data) {
String msg = "";
switch (code) {
case RESULT_INSTALL_SUCCESS: msg = "RESULT_INSTALL_SUCCESS";
@@ -258,7 +278,8 @@
@ResultCode public static final int RESULT_PARSE_EXCEPTION = 8;
static boolean shouldSkipInstall(
- @NonNull Diagnostics diagnostics,
+ @NonNull Executor executor,
+ @NonNull DiagnosticsCallback diagnostics,
long baselineLength,
boolean curExists,
long curLength,
@@ -267,22 +288,22 @@
) {
if (curExists && curLength > MIN_MEANINGFUL_LENGTH) {
// There's a non-empty profile sitting in this directory
- diagnostics.diagnostic(DIAGNOSTIC_CURRENT_PROFILE_EXISTS, null);
+ diagnostic(executor, diagnostics, DIAGNOSTIC_CURRENT_PROFILE_EXISTS, null);
} else {
- diagnostics.diagnostic(DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST, null);
+ diagnostic(executor, diagnostics, DIAGNOSTIC_CURRENT_PROFILE_DOES_NOT_EXIST, null);
}
if (refExists && refLength > MIN_MEANINGFUL_LENGTH) {
- diagnostics.diagnostic(DIAGNOSTIC_REF_PROFILE_EXISTS, null);
+ diagnostic(executor, diagnostics, DIAGNOSTIC_REF_PROFILE_EXISTS, null);
} else {
- diagnostics.diagnostic(DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST, null);
+ diagnostic(executor, diagnostics, DIAGNOSTIC_REF_PROFILE_DOES_NOT_EXIST, null);
}
if (baselineLength > 0 && baselineLength == curLength) {
// If the profiles are exactly the same size, we make the assumption that
// they are in fact the same profile. In this case, there is no work for
// us to do and we can exit early.
- diagnostics.result(RESULT_ALREADY_INSTALLED, null);
+ result(executor, diagnostics, RESULT_ALREADY_INSTALLED, null);
return true;
}
@@ -290,7 +311,7 @@
// If the profiles are exactly the same size, we make the assumption that
// they are in fact the same profile. In this case, there is no work for
// us to do and we can exit early.
- diagnostics.result(RESULT_ALREADY_INSTALLED, null);
+ result(executor, diagnostics, RESULT_ALREADY_INSTALLED, null);
return true;
}
@@ -305,7 +326,7 @@
// TODO: we could do something a bit smarter here to indicate that we've
// already written the profile. For instance, we could save a file marking the
// install and look at that.
- diagnostics.result(RESULT_ALREADY_INSTALLED, null);
+ result(executor, diagnostics, RESULT_ALREADY_INSTALLED, null);
return true;
}
return false;
@@ -317,22 +338,28 @@
*
* @param assets the asset manager to read source file from dexopt/baseline.prof
* @param packageName package name of the current apk
- * @param diagnostics The diagnostics object to pass diagnostics to
+ * @param diagnostics The diagnostics callback to pass diagnostics to
*/
private static void transcodeAndWrite(
@NonNull AssetManager assets,
@NonNull String packageName,
- @NonNull Diagnostics diagnostics
+ @NonNull Executor executor,
+ @NonNull DiagnosticsCallback diagnostics
) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- diagnostics.result(ProfileInstaller.RESULT_UNSUPPORTED_ART_VERSION, null);
+ result(executor, diagnostics, ProfileInstaller.RESULT_UNSUPPORTED_ART_VERSION, null);
return;
}
File curProfile = new File(new File(PROFILE_BASE_DIR, packageName), PROFILE_FILE);
File refProfile = new File(new File(PROFILE_REF_BASE_DIR, packageName), PROFILE_FILE);
- DeviceProfileWriter deviceProfileWriter = new DeviceProfileWriter(assets, diagnostics,
- PROFILE_SOURCE_LOCATION, curProfile, refProfile);
+ DeviceProfileWriter deviceProfileWriter = new DeviceProfileWriter(assets,
+ executor,
+ diagnostics,
+ PROFILE_SOURCE_LOCATION,
+ curProfile,
+ refProfile
+ );
if (!deviceProfileWriter.deviceAllowsProfileInstallerAotWrites()) {
return; /* nothing else to do here */
@@ -340,9 +367,14 @@
DeviceProfileWriter.SkipStrategy skipStrategy =
(newProfileLength, existingProfileState) -> shouldSkipInstall(
- diagnostics, newProfileLength,
- existingProfileState.hasCurFile(), existingProfileState.getCurLength(),
- existingProfileState.hasRefFile(), existingProfileState.getRefLength());
+ executor,
+ diagnostics,
+ newProfileLength,
+ existingProfileState.hasCurFile(),
+ existingProfileState.getCurLength(),
+ existingProfileState.hasRefFile(),
+ existingProfileState.getRefLength()
+ );
deviceProfileWriter.copyProfileOrRead(skipStrategy)
.transcodeIfNeeded()
@@ -374,7 +406,7 @@
*/
@WorkerThread
public static void writeProfile(@NonNull Context context) {
- writeProfile(context, EMPTY_DIAGNOSTICS);
+ writeProfile(context, Runnable::run, EMPTY_DIAGNOSTICS);
}
/**
@@ -400,13 +432,19 @@
*
* @param context context to read assets from
- * @param diagnostics an object which will receive diagnostic information about the installation
+ * @param diagnostics an object which will receive diagnostic information about the
+ * installation
+ * @param executor the executor to run the diagnostic events through
*/
@WorkerThread
- public static void writeProfile(@NonNull Context context, @NonNull Diagnostics diagnostics) {
+ public static void writeProfile(
+ @NonNull Context context,
+ @NonNull Executor executor,
+ @NonNull DiagnosticsCallback diagnostics
+ ) {
Context appContext = context.getApplicationContext();
String packageName = appContext.getPackageName();
AssetManager assetManager = appContext.getAssets();
- transcodeAndWrite(assetManager, packageName, diagnostics);
+ transcodeAndWrite(assetManager, packageName, executor, diagnostics);
}
}
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
index eb54e54..10330e8 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/ItemTouchHelperTest.java
@@ -35,6 +35,7 @@
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.Suppress;
@@ -146,6 +147,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Test
+ @FlakyTest(bugId = 190192628)
public void swipeEndInRTL() throws Throwable {
mSetupRTL = true;
basicSwipeTest(END, START | END, -getActivity().getWindow().getDecorView().getWidth());
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java
index db358cf..0e48cb7 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewNestedScrolling3RequestDisallowInterceptTouchTest.java
@@ -37,6 +37,7 @@
import androidx.core.view.NestedScrollingParentHelper;
import androidx.core.view.ViewCompat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -79,6 +80,7 @@
}
@Test
+ @FlakyTest(bugId = 190192628)
public void parentConsumes1pxRvConsumes0px() {
mParent.consumeY = 1;
@@ -89,6 +91,7 @@
}
@Test
+ @FlakyTest(bugId = 190192628)
public void parentConsumes0pxRvConsumes1px() {
// RecyclerView consumes all because we scroll down, and we're already at the top
swipeVertically(-mTouchSlop - 1);
@@ -97,6 +100,7 @@
}
@Test
+ @FlakyTest(bugId = 190192628)
public void parentConsumes0pxRvConsumes0px() {
// RecyclerView consumes nothing because we scroll up, and we're already at the top
swipeVertically(mTouchSlop + 100);
@@ -105,6 +109,7 @@
}
@Test
+ @FlakyTest(bugId = 190192628)
public void parentPreConsumes1pxRvConsumes0px() {
mParent.consumePreY = 1;
diff --git a/resourceinspection/resourceinspection-processor/build.gradle b/resourceinspection/resourceinspection-processor/build.gradle
index 8e8f114..fe0b165 100644
--- a/resourceinspection/resourceinspection-processor/build.gradle
+++ b/resourceinspection/resourceinspection-processor/build.gradle
@@ -19,7 +19,6 @@
import androidx.build.SupportConfig
import static androidx.build.SdkHelperKt.getSdkPath
-import static androidx.build.dependencies.DependenciesKt.*
plugins {
id("AndroidXPlugin")
@@ -28,27 +27,27 @@
}
dependencies {
- implementation(AUTO_COMMON)
- implementation(AUTO_SERVICE_ANNOTATIONS)
- implementation(GRADLE_INCAP_HELPER)
- implementation(GUAVA)
- implementation(JAVAPOET)
- implementation(KOTLIN_STDLIB)
+ implementation(libs.autoCommon)
+ implementation(libs.autoServiceAnnotations)
+ implementation(libs.gradleIncapHelper)
+ implementation(libs.guava)
+ implementation(libs.javapoet)
+ implementation(libs.kotlinStdlib)
- kapt(GRADLE_INCAP_HELPER_PROCESSOR)
- kapt(AUTO_SERVICE_PROCESSOR)
+ kapt(libs.gradleIncapHelperProcessor)
+ kapt(libs.autoService)
- testImplementation(JUNIT)
- testImplementation(GOOGLE_COMPILE_TESTING)
- testImplementation(TRUTH)
+ testImplementation(libs.junit)
+ testImplementation(libs.googleCompileTesting)
+ testImplementation(libs.truth)
testRuntimeOnly(project(":resourceinspection:resourceinspection-annotation"))
testRuntimeOnly(project(":annotation:annotation"))
testRuntimeOnly(fileTree(
dir: "${getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
include : "android.jar"))
- testRuntimeOnly(INTELLIJ_ANNOTATIONS)
- testRuntimeOnly(JSR250)
+ testRuntimeOnly(libs.intellijAnnotations)
+ testRuntimeOnly(libs.jsr250)
}
androidx {
diff --git a/room/room-compiler-processing-testing/build.gradle b/room/room-compiler-processing-testing/build.gradle
index a82aae8..240c8c5 100644
--- a/room/room-compiler-processing-testing/build.gradle
+++ b/room/room-compiler-processing-testing/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
@@ -53,8 +51,8 @@
it.file("androidx.room.compiler.processing.util.CompilationTestCapabilities.Config" +
".properties")
})
- property("kotlinVersion", KOTLIN_VERSION)
- property("kspVersion", KSP_VERSION)
+ property("kotlinVersion", libs.versions.kotlin.get())
+ property("kspVersion", libs.versions.ksp.get())
}
java {
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationTestCapabilities.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationTestCapabilities.kt
index b5a1934..d611ef2 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationTestCapabilities.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationTestCapabilities.kt
@@ -55,17 +55,16 @@
}
/**
- * Reduces the version to some approximation by taking major and minor versions and the
- * first character of the patch. We use this to check if ksp and kotlin are compatible,
- * feel free to change it if it does not work as it is only an approximation
- * e.g. 1.4.20 becomes 1.4.2, 1.40.210-foobar becomes 1.40.2
+ * Reduces the version to some approximation by taking major and minor versions.
+ * We use this to check if ksp and kotlin are compatible, feel free to change it if it
+ * does not work as it is only an approximation
+ * e.g. 1.4.20 becomes 1.4, 1.40.210-foobar becomes 1.4
*/
private fun reduceVersions(version: String): Array<String?> {
val sections = version.split('.')
return arrayOf(
sections.getOrNull(0),
- sections.getOrNull(1),
- sections.getOrNull(2)?.trim()?.first()?.toString(),
+ sections.getOrNull(1)
)
}
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestConfigTest.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestConfigTest.kt
index f442790..d5c7eb1 100644
--- a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestConfigTest.kt
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/TestConfigTest.kt
@@ -41,7 +41,7 @@
kotlinVersion = "1.4.30",
kspVersion = "1.4.20-blah-blah"
).canEnableKsp()
- ).isFalse()
+ ).isTrue()
assertThat(
Config(
kotlinVersion = "1.5.30",
@@ -59,6 +59,6 @@
kotlinVersion = "1.5",
kspVersion = "1.5.20-blah-blah"
).canEnableKsp()
- ).isFalse()
+ ).isTrue()
}
}
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
index 7a93f35..dd6e2bd 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
@@ -22,6 +22,7 @@
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSName
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.symbol.KSTypeAlias
import com.google.devtools.ksp.symbol.KSTypeArgument
@@ -35,6 +36,7 @@
import com.squareup.javapoet.TypeName
import com.squareup.javapoet.TypeVariableName
import com.squareup.javapoet.WildcardTypeName
+import kotlin.IllegalStateException
// Catch-all type name when we cannot resolve to anything. This is what KAPT uses as error type
// and we use the same type in KSP for consistency.
@@ -42,23 +44,50 @@
internal val ERROR_TYPE_NAME = ClassName.get("error", "NonExistentClass")
/**
+ * To handle self referencing types and avoid infinite recursion, we keep a lookup map for
+ * TypeVariables.
+ */
+private typealias TypeArgumentTypeLookup = LinkedHashMap<KSName, TypeName>
+
+/**
* Turns a KSTypeReference into a TypeName in java's type system.
*/
-internal fun KSTypeReference?.typeName(resolver: Resolver): TypeName {
+internal fun KSTypeReference?.typeName(resolver: Resolver): TypeName =
+ typeName(
+ resolver = resolver,
+ typeArgumentTypeLookup = TypeArgumentTypeLookup()
+ )
+
+private fun KSTypeReference?.typeName(
+ resolver: Resolver,
+ typeArgumentTypeLookup: TypeArgumentTypeLookup
+): TypeName {
return if (this == null) {
ERROR_TYPE_NAME
} else {
- resolve().typeName(resolver)
+ resolve().typeName(resolver, typeArgumentTypeLookup)
}
}
/**
* Turns a KSDeclaration into a TypeName in java's type system.
*/
+internal fun KSDeclaration.typeName(resolver: Resolver): TypeName =
+ typeName(
+ resolver = resolver,
+ typeArgumentTypeLookup = TypeArgumentTypeLookup()
+ )
+
@OptIn(KspExperimental::class)
-internal fun KSDeclaration.typeName(resolver: Resolver): TypeName {
+private fun KSDeclaration.typeName(
+ resolver: Resolver,
+ typeArgumentTypeLookup: TypeArgumentTypeLookup
+): TypeName {
if (this is KSTypeAlias) {
- return this.type.typeName(resolver)
+ return this.type.typeName(resolver, typeArgumentTypeLookup)
+ }
+ if (this is KSTypeParameter) {
+ return this.typeName(resolver, typeArgumentTypeLookup)
}
// if there is no qualified name, it is a resolution error so just return shared instance
// KSP may improve that later and if not, we can improve it in Room
@@ -68,9 +97,7 @@
if (jvmSignature != null && jvmSignature.isNotBlank()) {
return jvmSignature.typeNameFromJvmSignature()
}
- if (this is KSTypeParameter) {
- return TypeVariableName.get(name.asString())
- }
+
// fallback to custom generation, it is very likely that this is an unresolved type
// get the package name first, it might throw for invalid types, hence we use
// safeGetPackageName
@@ -90,10 +117,44 @@
internal fun KSTypeArgument.typeName(
param: KSTypeParameter,
resolver: Resolver
+): TypeName = typeName(
+ param = param,
+ resolver = resolver,
+ typeArgumentTypeLookup = TypeArgumentTypeLookup()
+)
+
+private fun KSTypeParameter.typeName(
+ resolver: Resolver,
+ typeArgumentTypeLookup: TypeArgumentTypeLookup
): TypeName {
+ // see https://github.com/square/javapoet/issues/842
+ typeArgumentTypeLookup[name]?.let {
+ return it
+ }
+ val mutableBounds = mutableListOf<TypeName>()
+ val typeName = createModifiableTypeVariableName(name = name.asString(), bounds = mutableBounds)
+ typeArgumentTypeLookup[name] = typeName
+ val resolvedBounds = bounds.map {
+ it.typeName(resolver, typeArgumentTypeLookup).tryBox()
+ }.toList()
+ if (resolvedBounds.isNotEmpty()) {
+ mutableBounds.addAll(resolvedBounds)
+ mutableBounds.remove(TypeName.OBJECT)
+ }
+ typeArgumentTypeLookup.remove(name)
+ return typeName
+}
+
+private fun KSTypeArgument.typeName(
+ param: KSTypeParameter,
+ resolver: Resolver,
+ typeArgumentTypeLookup: TypeArgumentTypeLookup
+): TypeName {
+ fun resolveTypeName() = type.typeName(resolver, typeArgumentTypeLookup).tryBox()
+
return when (variance) {
- Variance.CONTRAVARIANT -> WildcardTypeName.supertypeOf(type.typeName(resolver).tryBox())
- Variance.COVARIANT -> WildcardTypeName.subtypeOf(type.typeName(resolver).tryBox())
+ Variance.CONTRAVARIANT -> WildcardTypeName.supertypeOf(resolveTypeName())
+ Variance.COVARIANT -> WildcardTypeName.subtypeOf(resolveTypeName())
Variance.STAR -> {
// for star projected types, JavaPoet uses the name from the declaration if
// * is not given explicitly
@@ -101,27 +162,40 @@
// explicit *
WildcardTypeName.subtypeOf(TypeName.OBJECT)
} else {
- TypeVariableName.get(param.name.asString(), type.typeName(resolver).tryBox())
+ param.typeName(resolver, typeArgumentTypeLookup)
}
}
- else -> type.typeName(resolver).tryBox()
+ else -> resolveTypeName()
}
}
/**
* Turns a KSType into a TypeName in java's type system.
*/
-internal fun KSType.typeName(resolver: Resolver): TypeName {
+internal fun KSType.typeName(resolver: Resolver): TypeName =
+ typeName(
+ resolver = resolver,
+ typeArgumentTypeLookup = TypeArgumentTypeLookup()
+ )
+
+private fun KSType.typeName(
+ resolver: Resolver,
+ typeArgumentTypeLookup: TypeArgumentTypeLookup
+): TypeName {
return if (this.arguments.isNotEmpty()) {
val args: Array<TypeName> = this.arguments.mapIndexed { index, typeArg ->
typeArg.typeName(
- this.declaration.typeParameters[index],
- resolver
+ param = this.declaration.typeParameters[index],
+ resolver = resolver,
+ typeArgumentTypeLookup = typeArgumentTypeLookup
)
}.map {
it.tryBox()
}.toTypedArray()
- when (val typeName = declaration.typeName(resolver).tryBox()) {
+ when (
+ val typeName = declaration
+ .typeName(resolver, typeArgumentTypeLookup).tryBox()
+ ) {
is ArrayTypeName -> ArrayTypeName.of(args.single())
is ClassName -> ParameterizedTypeName.get(
typeName,
@@ -130,7 +204,7 @@
else -> error("Unexpected type name for KSType: $typeName")
}
} else {
- this.declaration.typeName(resolver)
+ this.declaration.typeName(resolver, typeArgumentTypeLookup)
}
}
@@ -164,3 +238,40 @@
XNullability.NONNULL -> makeNotNullable()
else -> throw IllegalArgumentException("Cannot set KSType nullability to platform")
}
+
+/**
+ * The private constructor of [TypeVariableName] which receives a list.
+ * We use this in [createModifiableTypeVariableName] to create a [TypeVariableName] whose bounds
+ * can be modified afterwards.
+ */
+private val typeVarNameConstructor by lazy {
+ try {
+ TypeVariableName::class.java.getDeclaredConstructor(
+ String::class.java,
+ List::class.java
+ ).also {
+ it.trySetAccessible()
+ }
+ } catch (ex: NoSuchMethodException) {
+ throw IllegalStateException(
+ """
+ Room couldn't find the constructor it is looking for in JavaPoet. Please file a bug at
+ https://issuetracker.google.com/issues/new?component=413107
+ """.trimIndent(),
+ ex
+ )
+ }
+}
+
+/**
+ * Creates a TypeVariableName where we can change the bounds after constructor.
+ * This is used to workaround a case for self referencing type declarations.
+ * see b/187572913 for more details
+ */
+private fun createModifiableTypeVariableName(
+ name: String,
+ bounds: List<TypeName>
+): TypeVariableName = typeVarNameConstructor.newInstance(
+ name,
+ bounds
+) as TypeVariableName
\ No newline at end of file
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
index 3aa2c26..eabf0a3 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeTest.kt
@@ -32,6 +32,7 @@
import com.google.devtools.ksp.getClassDeclarationByName
import com.squareup.javapoet.ClassName
import com.squareup.javapoet.ParameterizedTypeName
+import com.squareup.javapoet.TypeName
import com.squareup.javapoet.TypeVariableName
import org.junit.Test
import org.junit.runner.RunWith
@@ -401,4 +402,257 @@
}
}
}
+
+ @Test
+ fun selfReferencingType_kotlin() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ class SelfReferencing<T : SelfReferencing<T>>
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val elm = invocation.processingEnv.requireTypeElement("SelfReferencing")
+ val typeName = elm.type.typeName
+ assertThat(typeName.dumpToString(5)).isEqualTo(
+ """
+ SelfReferencing<T>
+ | T
+ | > SelfReferencing<T>
+ | > | T
+ | > | > SelfReferencing<T>
+ | > | > | T
+ """.trimIndent()
+ )
+ }
+ }
+
+ @Test
+ fun selfReferencingType_java() {
+ val src = Source.java(
+ "SelfReferencing",
+ """
+ class SelfReferencing<T extends SelfReferencing<T>> {
+ }
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val elm = invocation.processingEnv.requireTypeElement("SelfReferencing")
+ val dump = elm.type.typeName.dumpToString(5)
+ if (invocation.isKsp) {
+ // KSP fails to resolve self referencing java types:
+ // https://github.com/google/ksp/issues/476
+ // keeping this bad assertion here so that when the bug is fixed,
+ // test will fail and it will be cleaned up.
+
+ assertThat(dump).isEqualTo(
+ """
+ SelfReferencing<T>
+ | T
+ | > SelfReferencing<error.NonExistentClass>
+ | > | error.NonExistentClass
+ """.trimIndent()
+ )
+ } else {
+ assertThat(dump).isEqualTo(
+ """
+ SelfReferencing<T>
+ | T
+ | > SelfReferencing<T>
+ | > | T
+ | > | > SelfReferencing<T>
+ | > | > | T
+ """.trimIndent()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun multiLevelSelfReferencingType() {
+ val src = Source.kotlin(
+ "Foo.kt",
+ """
+ open class Node<TX : Node<TX, RX>, RX : Node<RX, TX>> {
+ }
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val nodeElm = invocation.processingEnv.requireType("Node")
+ val nodeTypeName = nodeElm.typeName
+ assertThat(nodeTypeName.dumpToString(5)).isEqualTo(
+ """
+ Node<TX, RX>
+ | TX
+ | > Node<TX, RX>
+ | > | TX
+ | > | > Node<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ | > | RX
+ | > | > Node<RX, TX>
+ | > | > | RX
+ | > | > | TX
+ | RX
+ | > Node<RX, TX>
+ | > | RX
+ | > | > Node<RX, TX>
+ | > | > | RX
+ | > | > | TX
+ | > | TX
+ | > | > Node<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ """.trimIndent()
+ )
+ }
+ }
+
+ @Test
+ fun selfReferencing_withGenericClassBounds() {
+ val src = Source.kotlin(
+ "SelfReferencing.kt",
+ """
+ class SelfReferencing<TX : SelfReferencing<TX, RX>, RX : List<TX>>
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val elm = invocation.processingEnv.requireTypeElement("SelfReferencing")
+ val typeDump = elm.type.typeName.dumpToString(5)
+ // KSP and Javac diverge here when the generic type parameter in the declaration has
+ // variance. This test is kept here to know that the difference is expected.
+ // KAPT generates a wildcard for the List<T> from the variance of it. In XProcessing,
+ // such resolution is expected to happen at code generation time.
+ //
+ // This inconsistency is not great but it is fairly complicated to do variance
+ // resolution (see: OverrideVarianceResolver.kt) and this level of detail almost
+ // never matters.
+ if (invocation.isKsp) {
+ assertThat(typeDump).isEqualTo(
+ """
+ SelfReferencing<TX, RX>
+ | TX
+ | > SelfReferencing<TX, RX>
+ | > | TX
+ | > | > SelfReferencing<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ | > | RX
+ | > | > java.util.List<TX>
+ | > | > | TX
+ | RX
+ | > java.util.List<TX>
+ | > | TX
+ | > | > SelfReferencing<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ """.trimIndent()
+ )
+ } else {
+ assertThat(typeDump).isEqualTo(
+ """
+ SelfReferencing<TX, RX>
+ | TX
+ | > SelfReferencing<TX, RX>
+ | > | TX
+ | > | > SelfReferencing<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ | > | RX
+ | > | > java.util.List<? extends TX>
+ | > | > | ? extends TX
+ | RX
+ | > java.util.List<? extends TX>
+ | > | ? extends TX
+ """.trimIndent()
+ )
+ }
+ }
+ }
+
+ @Test
+ fun selfReferencing_withGeneric() {
+ val src = Source.kotlin(
+ "SelfReferencing.kt",
+ """
+ class Generic<T>
+ class SelfReferencing<TX : SelfReferencing<TX, RX>, RX : Generic<TX>>
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val elm = invocation.processingEnv.requireTypeElement("SelfReferencing")
+ val typeName = elm.type.typeName
+ assertThat(typeName.dumpToString(5)).isEqualTo(
+ """
+ SelfReferencing<TX, RX>
+ | TX
+ | > SelfReferencing<TX, RX>
+ | > | TX
+ | > | > SelfReferencing<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ | > | RX
+ | > | > Generic<TX>
+ | > | > | TX
+ | RX
+ | > Generic<TX>
+ | > | TX
+ | > | > SelfReferencing<TX, RX>
+ | > | > | TX
+ | > | > | RX
+ """.trimIndent()
+ )
+ }
+ }
+
+ /**
+ * Dumps the typename with its bounds in a given depth.
+ * This makes tests more readable.
+ */
+ private fun TypeName.dumpToString(depth: Int): String {
+ return dump(depth).toString()
+ }
+
+ private fun TypeName.dump(depth: Int): TypeNameNode? {
+ if (depth < 0) return null
+ return when (this) {
+ is ParameterizedTypeName -> TypeNameNode(
+ text = this.toString(),
+ typeArgs = this.typeArguments.mapNotNull { it.dump(depth - 1) }
+ )
+ is TypeVariableName -> TypeNameNode(
+ text = this.toString(),
+ bounds = bounds.map { it.dump(depth - 1) }.filterNotNull()
+ )
+ else -> TypeNameNode(text = toString())
+ }
+ }
+
+ private data class TypeNameNode(
+ val text: String,
+ val bounds: List<TypeNameNode> = emptyList(),
+ val typeArgs: List<TypeNameNode> = emptyList()
+ ) {
+ override fun toString(): String {
+ return buildString {
+ appendLine(text)
+ bounds.forEach {
+ appendLine(it.toString().prependIndent("> "))
+ }
+ typeArgs.forEach {
+ appendLine(it.toString().prependIndent("| "))
+ }
+ }.trim()
+ }
+ }
}
diff --git a/room/room-compiler/build.gradle b/room/room-compiler/build.gradle
index 364f385..58921f9 100644
--- a/room/room-compiler/build.gradle
+++ b/room/room-compiler/build.gradle
@@ -22,8 +22,6 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ConfigureShadowRelocation
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("kotlin")
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt b/room/room-compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
index d7fd403..b435de1 100644
--- a/room/room-compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
+++ b/room/room-compiler/src/main/kotlin/androidx/room/verifier/DatabaseVerifier.kt
@@ -26,7 +26,6 @@
import androidx.room.vo.Warning
import columnInfo
import org.sqlite.JDBC
-import org.sqlite.SQLiteJDBCLoader
import java.io.File
import java.sql.Connection
import java.sql.SQLException
@@ -68,7 +67,7 @@
// multiple library versions, process isolation and multiple class loaders by using
// UUID named library files.
synchronized(System::class.java) {
- SQLiteJDBCLoader.initialize() // extract and loads native library
+ NativeSQLiteLoader.load() // extract and loads native library
JDBC.isValidURL(CONNECTION_URL) // call to register driver
}
}
diff --git a/room/room-compiler/src/main/kotlin/androidx/room/verifier/NativeSQLiteLoader.kt b/room/room-compiler/src/main/kotlin/androidx/room/verifier/NativeSQLiteLoader.kt
new file mode 100644
index 0000000..677411c
--- /dev/null
+++ b/room/room-compiler/src/main/kotlin/androidx/room/verifier/NativeSQLiteLoader.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2021 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.room.verifier
+
+import org.sqlite.SQLiteJDBCLoader
+import org.sqlite.util.OSInfo
+import java.io.File
+import java.io.IOException
+import java.io.InputStream
+import java.util.UUID
+
+/**
+ * A custom sqlite-jdbc native library extractor and loader.
+ *
+ * This class is used instead of [SQLiteJDBCLoader.initialize] since it workarounds current issues
+ * in the loading strategy, specifically: https://github.com/xerial/sqlite-jdbc/pull/578.
+ */
+internal object NativeSQLiteLoader {
+
+ private var loaded = false
+
+ private val tempDir: File by lazy {
+ File(System.getProperty("org.sqlite.tmpdir", System.getProperty("java.io.tmpdir")))
+ }
+
+ private val version: String by lazy { SQLiteJDBCLoader.getVersion() }
+
+ @JvmStatic
+ fun load() = synchronized(loaded) {
+ if (loaded) return
+ try {
+ // Cleanup target temporary folder for a new extraction.
+ cleanupTempFolder()
+ // Extract and load native library.
+ loadNativeLibrary()
+ // Reflect into original loader and mark library as extracted.
+ SQLiteJDBCLoader::class.java.getDeclaredField("extracted")
+ .apply { trySetAccessible() }
+ .set(null, true)
+ } catch (ex: Exception) {
+ // Fallback to main library if our attempt failed, do print error juuust in case, so if
+ // there is an error with our approach we get to know, instead of fully swallowing it.
+ RuntimeException("Failed to load native SQLite library, will try again though.", ex)
+ .printStackTrace()
+ SQLiteJDBCLoader.initialize()
+ }
+ loaded = true
+ }
+
+ private fun cleanupTempFolder() {
+ tempDir.listFiles { file ->
+ file.name.startsWith("sqlite-$version") && !file.name.endsWith(".lck")
+ }?.forEach { libFile ->
+ val lckFile = File(libFile.absolutePath + ".lck")
+ if (!lckFile.exists()) {
+ libFile.delete()
+ }
+ }
+ }
+
+ // Load the OS-dependent library from the Jar file.
+ private fun loadNativeLibrary() {
+ val packagePath =
+ SQLiteJDBCLoader::class.java.getPackage().name.replace(".", "/")
+ val nativeLibraryPath =
+ "/$packagePath/native/${OSInfo.getNativeLibFolderPathForCurrentOS()}"
+ val nativeLibraryName = let {
+ val libName = System.mapLibraryName("sqlitejdbc")
+ .apply { replace("dylib", "jnilib") }
+ if (hasResource("$nativeLibraryPath/$libName")) {
+ return@let libName
+ }
+ if (OSInfo.getOSName() == "Mac") {
+ // Fix for openjdk7 for Mac
+ val altLibName = "libsqlitejdbc.jnilib"
+ if (hasResource("$nativeLibraryPath/$altLibName")) {
+ return@let altLibName
+ }
+ }
+ error(
+ "No native library is found for os.name=${OSInfo.getOSName()} and " +
+ "os.arch=${OSInfo.getArchName()}. path=$nativeLibraryPath"
+ )
+ }
+
+ val extractedNativeLibraryFile = try {
+ extractNativeLibrary(nativeLibraryPath, nativeLibraryName, tempDir.absolutePath)
+ } catch (ex: IOException) {
+ throw RuntimeException("Couldn't extract native SQLite library.", ex)
+ }
+ try {
+ @Suppress("UnsafeDynamicallyLoadedCode") // Loading an from an absolute path.
+ System.load(extractedNativeLibraryFile.absolutePath)
+ } catch (ex: UnsatisfiedLinkError) {
+ throw RuntimeException("Couldn't load native SQLite library.", ex)
+ }
+ }
+
+ private fun extractNativeLibrary(
+ libraryPath: String,
+ libraryName: String,
+ targetDirPath: String
+ ): File {
+ val libraryFilePath = "$libraryPath/$libraryName"
+ // Include arch name in temporary filename in order to avoid conflicts when multiple JVMs
+ // with different architectures are running.
+ val outputLibraryFile = File(
+ targetDirPath,
+ "sqlite-$version-${UUID.randomUUID()}-$libraryName"
+ ).apply { deleteOnExit() }
+ val outputLibraryLckFile = File(
+ targetDirPath,
+ "${outputLibraryFile.name}.lck"
+ ).apply { deleteOnExit() }
+ if (!outputLibraryLckFile.exists()) {
+ outputLibraryLckFile.outputStream().close()
+ }
+ getResourceAsStream(libraryFilePath).use { inputStream ->
+ outputLibraryFile.outputStream().use { outputStream ->
+ inputStream.copyTo(outputStream)
+ }
+ }
+ // Set executable flag (x) to enable loading the library.
+ outputLibraryFile.setReadable(true)
+ outputLibraryFile.setExecutable(true)
+ return outputLibraryFile
+ }
+
+ private fun hasResource(path: String) = SQLiteJDBCLoader::class.java.getResource(path) != null
+
+ // Replacement of java.lang.Class#getResourceAsStream(String) to disable sharing the resource
+ // stream in multiple class loaders and specifically to avoid
+ // https://bugs.openjdk.java.net/browse/JDK-8205976
+ private fun getResourceAsStream(name: String): InputStream {
+ // Remove leading '/' since all our resource paths include a leading directory
+ // See: https://github.com/openjdk/jdk/blob/jdk-11+0/src/java.base/share/classes/java/lang/Class.java#L2573
+ val resolvedName = name.drop(1)
+ val url = SQLiteJDBCLoader::class.java.classLoader.getResource(resolvedName)
+ ?: throw IOException("Resource '$resolvedName' could not be found.")
+ return url.openConnection().apply {
+ defaultUseCaches = false
+ }.getInputStream()
+ }
+}
\ No newline at end of file
diff --git a/room/room-compiler/src/test/kotlin/androidx/room/verifier/NativeSQLiteLoaderTest.kt b/room/room-compiler/src/test/kotlin/androidx/room/verifier/NativeSQLiteLoaderTest.kt
new file mode 100644
index 0000000..8cf547b
--- /dev/null
+++ b/room/room-compiler/src/test/kotlin/androidx/room/verifier/NativeSQLiteLoaderTest.kt
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 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.room.verifier
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import java.io.File
+import java.net.URL
+import java.net.URLClassLoader
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicInteger
+import java.util.jar.JarEntry
+import java.util.jar.JarOutputStream
+
+@RunWith(JUnit4::class)
+class NativeSQLiteLoaderTest {
+
+ @Test
+ fun multipleClassLoader() {
+ // Get current classpath
+ val stringUrls = System.getProperty("java.class.path")!!
+ .split(System.getProperty("path.separator")!!).toTypedArray()
+ // Find classes under test.
+ val targetDirName = "room-compiler/build/classes/kotlin/main"
+ val classesDirPath = stringUrls.first { it.contains(targetDirName) }
+ // Create a JAR file out the classes and resources
+ val jarFile = File.createTempFile("jar-for-test-", ".jar")
+ createJar(classesDirPath, jarFile)
+ val jarUrl = URL("file://${jarFile.absolutePath}")
+ // Find Kotlin stdlibs (will need them to load class under test)
+ val kotlinStdbLibUrls = stringUrls
+ .filter { it.contains("kotlin-stdlib") && it.endsWith(".jar") }
+ .map { URL("file://$it") }
+ // Also find sqlite-jdbc since it is a hard dep of NativeSQLiteLoader
+ val sqliteJdbcJarUrl = stringUrls
+ .filter { it.contains("sqlite-jdbc") && it.endsWith(".jar") }
+ .map { URL("file://$it") }
+ // Spawn a few threads and have them all in parallel load the native lib
+ val completedThreads = AtomicInteger(0)
+ val numOfThreads = 8
+ val pool = Executors.newFixedThreadPool(numOfThreads)
+ val loadedClasses = arrayOfNulls<Class<*>>(numOfThreads)
+ for (i in 1..numOfThreads) {
+ pool.execute {
+ try {
+ Thread.sleep((i * 10).toLong())
+ // Create an isolated class loader, it should load *different* instances
+ // of NativeSQLiteLoader.class
+ val classLoader = URLClassLoader(
+ (kotlinStdbLibUrls + sqliteJdbcJarUrl + jarUrl).toTypedArray(),
+ ClassLoader.getSystemClassLoader().parent
+ )
+ val clazz =
+ classLoader.loadClass("androidx.room.verifier.NativeSQLiteLoader")
+ clazz.getDeclaredMethod("load").invoke(null)
+ classLoader.close()
+ loadedClasses[i - 1] = clazz
+ } catch (e: Throwable) {
+ e.printStackTrace()
+ fail(e.message)
+ }
+ completedThreads.incrementAndGet()
+ }
+ }
+ // Verify all threads completed
+ pool.shutdown()
+ pool.awaitTermination(3, TimeUnit.SECONDS)
+ assertThat(completedThreads.get()).isEqualTo(numOfThreads)
+ // Verify all loaded classes are different from each other
+ loadedClasses.forEachIndexed { i, clazz1 ->
+ loadedClasses.forEachIndexed { j, clazz2 ->
+ if (i == j) {
+ assertThat(clazz1).isEqualTo(clazz2)
+ } else {
+ assertThat(clazz1).isNotEqualTo(clazz2)
+ }
+ }
+ }
+ }
+
+ private fun createJar(inputDir: String, outputFile: File) {
+ JarOutputStream(outputFile.outputStream()).use {
+ addJarEntry(File(inputDir), inputDir, it)
+ }
+ }
+
+ private fun addJarEntry(source: File, changeDir: String, target: JarOutputStream) {
+ if (source.isDirectory) {
+ var name = source.path.replace("\\", "/")
+ if (name.isNotEmpty()) {
+ if (!name.endsWith("/")) {
+ name += "/"
+ }
+ val entry = JarEntry(name.substring(changeDir.length + 1))
+ entry.time = source.lastModified()
+ target.putNextEntry(entry)
+ target.closeEntry()
+ }
+ source.listFiles()!!.forEach { nestedFile ->
+ addJarEntry(nestedFile, changeDir, target)
+ }
+ } else if (source.isFile) {
+ val entry = JarEntry(
+ source.path.replace("\\", "/").substring(changeDir.length + 1)
+ )
+ entry.time = source.lastModified()
+ target.putNextEntry(entry)
+ source.inputStream().use { inputStream ->
+ inputStream.copyTo(target)
+ }
+ target.closeEntry()
+ }
+ }
+}
\ No newline at end of file
diff --git a/room/room-ktx/src/androidTest/java/androidx/room/CoroutineRoomCancellationTest.kt b/room/room-ktx/src/androidTest/java/androidx/room/CoroutineRoomCancellationTest.kt
index 96c5369..252b1b1 100644
--- a/room/room-ktx/src/androidTest/java/androidx/room/CoroutineRoomCancellationTest.kt
+++ b/room/room-ktx/src/androidTest/java/androidx/room/CoroutineRoomCancellationTest.kt
@@ -22,6 +22,7 @@
import androidx.test.filters.SdkSuppress
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
@@ -47,6 +48,7 @@
private val database = TestDatabase()
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testSuspend_cancellable_duringLongQuery() = runBlocking {
database.backingFieldMap["QueryDispatcher"] = Dispatchers.IO
@@ -80,7 +82,7 @@
assertThat(cancellationSignal.isCanceled).isTrue()
}
- @OptIn(ExperimentalCoroutinesApi::class)
+ @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class)
@Test
fun testSuspend_cancellable_beforeQueryStarts() = runBlocking {
database.backingFieldMap["QueryDispatcher"] = testDispatcher
@@ -118,6 +120,7 @@
assertThat(cancellationSignal.isCanceled).isTrue()
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testSuspend_exception_in_query() = runBlocking {
database.backingFieldMap["QueryDispatcher"] = Dispatchers.IO
diff --git a/room/room-ktx/src/main/java/androidx/room/CoroutinesRoom.kt b/room/room-ktx/src/main/java/androidx/room/CoroutinesRoom.kt
index 8a71fe9..aee1d64 100644
--- a/room/room-ktx/src/main/java/androidx/room/CoroutinesRoom.kt
+++ b/room/room-ktx/src/main/java/androidx/room/CoroutinesRoom.kt
@@ -21,6 +21,7 @@
import androidx.annotation.RestrictTo
import androidx.sqlite.db.SupportSQLiteCompat
import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.channels.Channel
@@ -65,6 +66,7 @@
}
}
+ @OptIn(DelicateCoroutinesApi::class)
@JvmStatic
public suspend fun <R> execute(
db: RoomDatabase,
@@ -110,10 +112,10 @@
val observerChannel = Channel<Unit>(Channel.CONFLATED)
val observer = object : InvalidationTracker.Observer(tableNames) {
override fun onInvalidated(tables: MutableSet<String>) {
- observerChannel.offer(Unit)
+ observerChannel.trySend(Unit)
}
}
- observerChannel.offer(Unit) // Initial signal to perform first query.
+ observerChannel.trySend(Unit) // Initial signal to perform first query.
val queryContext = coroutineContext[TransactionElement]?.transactionDispatcher
?: if (inTransaction) db.transactionDispatcher else db.queryDispatcher
val resultChannel = Channel<R>()
diff --git a/room/room-paging/build.gradle b/room/room-paging/build.gradle
index e9645b8..0150da1 100644
--- a/room/room-paging/build.gradle
+++ b/room/room-paging/build.gradle
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
-import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
@@ -26,7 +25,7 @@
}
dependencies {
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
// Add dependencies here
}
diff --git a/room/room-runtime/src/androidTest/java/androidx/room/AutoClosingRoomOpenHelperTest.kt b/room/room-runtime/src/androidTest/java/androidx/room/AutoClosingRoomOpenHelperTest.kt
index dd0693c..2da5170 100644
--- a/room/room-runtime/src/androidTest/java/androidx/room/AutoClosingRoomOpenHelperTest.kt
+++ b/room/room-runtime/src/androidTest/java/androidx/room/AutoClosingRoomOpenHelperTest.kt
@@ -24,13 +24,13 @@
import androidx.sqlite.db.SupportSQLiteOpenHelper
import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
import androidx.test.core.app.ApplicationProvider
+import androidx.test.filters.FlakyTest
import androidx.test.filters.SdkSuppress
import androidx.testutils.assertThrows
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import java.io.IOException
-import java.lang.UnsupportedOperationException
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@@ -138,6 +138,7 @@
}
}
+ @FlakyTest(bugId = 190607416)
@Test
public fun testOnOpenCalledOnEachOpen() {
val countingCallback = object : Callback() {
diff --git a/room/room-runtime/src/main/java/androidx/room/AutoClosingRoomOpenHelper.java b/room/room-runtime/src/main/java/androidx/room/AutoClosingRoomOpenHelper.java
index 430df67..03e68d4 100644
--- a/room/room-runtime/src/main/java/androidx/room/AutoClosingRoomOpenHelper.java
+++ b/room/room-runtime/src/main/java/androidx/room/AutoClosingRoomOpenHelper.java
@@ -16,7 +16,6 @@
package androidx.room;
-import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.CharArrayBuffer;
@@ -441,7 +440,6 @@
});
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void setForeignKeyConstraintsEnabled(boolean enable) {
@@ -465,7 +463,6 @@
+ "OpenHelper instead of on the database directly.");
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public boolean isWriteAheadLoggingEnabled() {
@@ -699,7 +696,6 @@
mDelegate.setNotificationUri(cr, uri);
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.Q)
@Override
public void setNotificationUris(@NonNull ContentResolver cr,
@@ -707,14 +703,12 @@
SupportSQLiteCompat.Api29Impl.setNotificationUris(mDelegate, cr, uris);
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public Uri getNotificationUri() {
return SupportSQLiteCompat.Api19Impl.getNotificationUri(mDelegate);
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.Q)
@Nullable
@Override
@@ -727,7 +721,6 @@
return mDelegate.getWantsAllOnMoveCalls();
}
- @SuppressLint("UnsafeNewApiCall")
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void setExtras(Bundle extras) {
diff --git a/room/room-runtime/src/main/java/androidx/room/RoomDatabase.java b/room/room-runtime/src/main/java/androidx/room/RoomDatabase.java
index b6cf417..1b5ef23 100644
--- a/room/room-runtime/src/main/java/androidx/room/RoomDatabase.java
+++ b/room/room-runtime/src/main/java/androidx/room/RoomDatabase.java
@@ -736,7 +736,6 @@
* Resolves {@link #AUTOMATIC} to either {@link #TRUNCATE} or
* {@link #WRITE_AHEAD_LOGGING}.
*/
- @SuppressLint("NewApi")
JournalMode resolve(Context context) {
if (this != AUTOMATIC) {
return this;
diff --git a/samples/Support4Demos/src/main/java/com/example/android/supportv4/widget/SlidingPaneLayoutActivity.java b/samples/Support4Demos/src/main/java/com/example/android/supportv4/widget/SlidingPaneLayoutActivity.java
index c330ff7..3c84764 100644
--- a/samples/Support4Demos/src/main/java/com/example/android/supportv4/widget/SlidingPaneLayoutActivity.java
+++ b/samples/Support4Demos/src/main/java/com/example/android/supportv4/widget/SlidingPaneLayoutActivity.java
@@ -17,7 +17,6 @@
package com.example.android.supportv4.widget;
-import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.os.Build;
import android.os.Bundle;
@@ -198,7 +197,6 @@
*/
class FirstLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
@Override
- @SuppressLint("UnsafeNewApiCall")
public void onGlobalLayout() {
mActionBar.onFirstLayout();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
diff --git a/samples/SupportLeanbackDemos/build.gradle b/samples/SupportLeanbackDemos/build.gradle
index 38daec1..1c59f74 100644
--- a/samples/SupportLeanbackDemos/build.gradle
+++ b/samples/SupportLeanbackDemos/build.gradle
@@ -1,5 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -13,7 +11,7 @@
implementation("com.google.code.gson:gson:2.6.2")
implementation("androidx.room:room-runtime:2.3.0-alpha01")
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
annotationProcessor("androidx.room:room-compiler:2.3.0-alpha01")
}
diff --git a/security/identity-credential/src/main/java/androidx/security/identity/SoftwareIdentityCredential.java b/security/identity-credential/src/main/java/androidx/security/identity/SoftwareIdentityCredential.java
index 2260baf..1eed78d 100644
--- a/security/identity-credential/src/main/java/androidx/security/identity/SoftwareIdentityCredential.java
+++ b/security/identity-credential/src/main/java/androidx/security/identity/SoftwareIdentityCredential.java
@@ -16,7 +16,6 @@
package androidx.security.identity;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.icu.util.Calendar;
import android.security.keystore.KeyProperties;
@@ -190,7 +189,6 @@
return result;
}
- @SuppressLint("NewApi")
@Override
public @NonNull KeyPair createEphemeralKeyPair() {
if (mEphemeralKeyPair == null) {
diff --git a/settings.gradle b/settings.gradle
index b623f63..a151454 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -598,6 +598,7 @@
includeProject(":wear:tiles:tiles", "wear/tiles/tiles", [BuildType.MAIN, BuildType.WEAR])
includeProject(":wear:tiles:tiles-proto", "wear/tiles/tiles-proto", [BuildType.MAIN, BuildType.WEAR])
includeProject(":wear:tiles:tiles-renderer", "wear/tiles/tiles-renderer", [BuildType.MAIN, BuildType.WEAR])
+includeProject(":wear:tiles:tiles-testing", "wear/tiles/tiles-testing", [BuildType.MAIN, BuildType.WEAR])
includeProject(":wear:wear-watchface", "wear/wear-watchface", [BuildType.MAIN, BuildType.WEAR])
includeProject(":wear:wear-watchface-complications-rendering", "wear/wear-watchface-complications-rendering", [BuildType.MAIN, BuildType.WEAR])
includeProject(":wear:wear-watchface-client", "wear/wear-watchface-client", [BuildType.MAIN, BuildType.WEAR])
diff --git a/sharetarget/integration-tests/testapp/build.gradle b/sharetarget/integration-tests/testapp/build.gradle
index 7cdbf10..40934d8 100644
--- a/sharetarget/integration-tests/testapp/build.gradle
+++ b/sharetarget/integration-tests/testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -25,5 +23,5 @@
api("androidx.core:core:1.3.2")
api(project(":sharetarget:sharetarget"))
api("androidx.appcompat:appcompat:1.2.0")
- api(CONSTRAINT_LAYOUT, { transitive = true })
+ api(libs.constraintLayout)
}
diff --git a/slices/benchmark/build.gradle b/slices/benchmark/build.gradle
index 7b04353..97aeb78 100644
--- a/slices/benchmark/build.gradle
+++ b/slices/benchmark/build.gradle
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
+
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -30,14 +30,14 @@
androidTestImplementation(project(":slice-core"))
androidTestImplementation(project(":slice-builders"))
androidTestImplementation(project(":benchmark:benchmark-junit4"))
- androidTestImplementation(JUNIT)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
}
androidx {
diff --git a/slices/builders/build.gradle b/slices/builders/build.gradle
index 67df8f5..038f13f 100644
--- a/slices/builders/build.gradle
+++ b/slices/builders/build.gradle
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-import androidx.build.LibraryVersions
import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
diff --git a/slices/builders/ktx/build.gradle b/slices/builders/ktx/build.gradle
index 864fbe8..3d668da 100644
--- a/slices/builders/ktx/build.gradle
+++ b/slices/builders/ktx/build.gradle
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-import androidx.build.LibraryVersions
import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
@@ -36,13 +35,13 @@
api "androidx.annotation:annotation:1.1.0"
implementation("androidx.core:core:1.3.0-beta01")
api(project(":slice-builders"))
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
- androidTestImplementation(JUNIT)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
}
androidx {
diff --git a/slices/core/build.gradle b/slices/core/build.gradle
index 90affdb..648ff24 100644
--- a/slices/core/build.gradle
+++ b/slices/core/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -30,11 +28,11 @@
implementation(project(":appcompat:appcompat"))
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
annotationProcessor (project(":versionedparcelable:versionedparcelable-compiler"))
}
diff --git a/slices/remotecallback/build.gradle b/slices/remotecallback/build.gradle
index c906165..2a4a76b 100644
--- a/slices/remotecallback/build.gradle
+++ b/slices/remotecallback/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
import androidx.build.LibraryGroups
import androidx.build.LibraryVersions
import androidx.build.Publish
@@ -31,11 +29,11 @@
implementation(project(":slice-core"))
implementation(project(":remotecallback:remotecallback"))
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
androidTestAnnotationProcessor project(":remotecallback:remotecallback-processor")
}
diff --git a/slices/test/build.gradle b/slices/test/build.gradle
index 351e96a..380f058 100644
--- a/slices/test/build.gradle
+++ b/slices/test/build.gradle
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryVersions
import androidx.build.LibraryGroups
import androidx.build.Publish
@@ -31,12 +30,12 @@
implementation("androidx.collection:collection:1.1.0")
api("androidx.lifecycle:lifecycle-livedata-core:2.0.0")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
}
androidx {
diff --git a/slices/view/build.gradle b/slices/view/build.gradle
index 48025cc..daa639d 100644
--- a/slices/view/build.gradle
+++ b/slices/view/build.gradle
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryVersions
import androidx.build.LibraryGroups
import androidx.build.Publish
@@ -33,13 +32,13 @@
androidTestImplementation(project(":slice-builders"))
androidTestImplementation(project(":slice-test"))
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy)
}
androidx {
diff --git a/slidingpanelayout/slidingpanelayout/build.gradle b/slidingpanelayout/slidingpanelayout/build.gradle
index 4ac36e3..8e17990e6 100644
--- a/slidingpanelayout/slidingpanelayout/build.gradle
+++ b/slidingpanelayout/slidingpanelayout/build.gradle
@@ -1,4 +1,3 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.Publish
@@ -14,11 +13,11 @@
api("androidx.customview:customview:1.1.0")
implementation(project(":window:window"))
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(KOTLIN_STDLIB)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.truth)
androidTestImplementation(project(':internal-testutils-runtime'))
}
diff --git a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
index b245d3d..2c110f6 100644
--- a/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
+++ b/slidingpanelayout/slidingpanelayout/src/androidTest/java/androidx/slidingpanelayout/widget/FoldTest.kt
@@ -24,6 +24,7 @@
import androidx.slidingpanelayout.widget.helpers.findViewX
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.testutils.withActivity
import androidx.window.WindowManager
@@ -47,6 +48,7 @@
/**
* Test split views in middle when fold vertically
*/
+ @FlakyTest(bugId = 190609880)
@Test
public fun testFoldVertical() {
TestActivity.onActivityCreated = { activity ->
@@ -107,6 +109,7 @@
/**
* Test split views when fold pane is smaller than required min width
*/
+ @FlakyTest(bugId = 190609880)
@Test
public fun testFoldExceedMinWidth() {
val detailViewExtraWidth = 200
diff --git a/sqlite/integration-tests/inspection-room-testapp/build.gradle b/sqlite/integration-tests/inspection-room-testapp/build.gradle
index 356c268..0084551 100644
--- a/sqlite/integration-tests/inspection-room-testapp/build.gradle
+++ b/sqlite/integration-tests/inspection-room-testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -24,12 +22,12 @@
}
dependencies {
- implementation(KOTLIN_STDLIB)
- androidTestImplementation(JUNIT)
- androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
- androidTestImplementation(ANDROIDX_TEST_EXT_KTX)
- androidTestImplementation(TRUTH)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ implementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.kotlinCoroutinesAndroid)
+ androidTestImplementation(libs.testExtJunitKtx)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.testRunner)
androidTestImplementation(project(":room:room-runtime"))
androidTestImplementation(project(":sqlite:sqlite-inspection"))
androidTestImplementation(project(":inspection:inspection-testing"))
diff --git a/sqlite/integration-tests/inspection-sqldelight-testapp/build.gradle b/sqlite/integration-tests/inspection-sqldelight-testapp/build.gradle
index 3ff0a85..8de9c32 100644
--- a/sqlite/integration-tests/inspection-sqldelight-testapp/build.gradle
+++ b/sqlite/integration-tests/inspection-sqldelight-testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -23,14 +21,14 @@
}
dependencies {
- implementation(KOTLIN_STDLIB)
- implementation(SQLDELIGHT_ANDROID)
- androidTestImplementation(JUNIT)
- androidTestImplementation(SQLDELIGHT_COROUTINES_EXT)
- androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
- androidTestImplementation(ANDROIDX_TEST_EXT_KTX)
- androidTestImplementation(TRUTH)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ implementation(libs.kotlinStdlib)
+ implementation(libs.sqldelightAndroid)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.sqldelightCoroutinesExt)
+ androidTestImplementation(libs.kotlinCoroutinesAndroid)
+ androidTestImplementation(libs.testExtJunitKtx)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.testRunner)
androidTestImplementation(project(":sqlite:sqlite-inspection"))
androidTestImplementation(project(":inspection:inspection-testing"))
androidTestImplementation("com.google.protobuf:protobuf-javalite:3.10.0")
diff --git a/sqlite/sqlite-framework/build.gradle b/sqlite/sqlite-framework/build.gradle
index 3b7799f..bfac2ce 100644
--- a/sqlite/sqlite-framework/build.gradle
+++ b/sqlite/sqlite-framework/build.gradle
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
plugins {
diff --git a/sqlite/sqlite-inspection/build.gradle b/sqlite/sqlite-inspection/build.gradle
index 22e08ca..140b1b4 100644
--- a/sqlite/sqlite-inspection/build.gradle
+++ b/sqlite/sqlite-inspection/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -32,12 +30,12 @@
compileOnly(project(":inspection:inspection"))
androidTestImplementation(project(":inspection:inspection-testing"))
- androidTestImplementation(KOTLIN_STDLIB)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(TRUTH)
- androidTestImplementation(KOTLIN_COROUTINES_ANDROID)
- androidTestImplementation(KOTLIN_COROUTINES_TEST)
+ androidTestImplementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.kotlinCoroutinesAndroid)
+ androidTestImplementation(libs.kotlinCoroutinesTest)
}
androidx {
diff --git a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/CancellationQueryTest.kt b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/CancellationQueryTest.kt
index 873ccbd..997730a 100644
--- a/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/CancellationQueryTest.kt
+++ b/sqlite/sqlite-inspection/src/androidTest/java/androidx/sqlite/inspection/test/CancellationQueryTest.kt
@@ -63,7 +63,7 @@
assertThat(countingExecutorService.events.receive()).isEqualTo(STARTED)
assertThat(countingExecutorService.events.receive()).isEqualTo(FINISHED)
assertThat(result.rowsCount).isEqualTo(22)
- assertThat(countingExecutorService.events.poll()).isNull()
+ assertThat(countingExecutorService.events.tryReceive().getOrNull()).isNull()
job.cancelAndJoin()
// check that task finished after cancellation
assertThat(countingExecutorService.events.receive()).isEqualTo(FINISHED)
@@ -83,11 +83,11 @@
override fun execute(command: Runnable) {
executor.execute {
- channel.offer(STARTED)
+ channel.trySend(STARTED)
try {
command.run()
} finally {
- channel.offer(FINISHED)
+ channel.trySend(FINISHED)
}
}
}
diff --git a/sqlite/sqlite-ktx/build.gradle b/sqlite/sqlite-ktx/build.gradle
index 6e6090c..c4601f50 100644
--- a/sqlite/sqlite-ktx/build.gradle
+++ b/sqlite/sqlite-ktx/build.gradle
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
plugins {
@@ -28,10 +25,10 @@
dependencies {
api(project(":sqlite:sqlite"))
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
- testImplementation(JUNIT)
- testImplementation(MOCKITO_CORE)
+ testImplementation(libs.junit)
+ testImplementation(libs.mockitoCore)
}
androidx {
diff --git a/sqlite/sqlite/build.gradle b/sqlite/sqlite/build.gradle
index ce6519c..5d410d5 100644
--- a/sqlite/sqlite/build.gradle
+++ b/sqlite/sqlite/build.gradle
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
-import androidx.build.AndroidXExtension
import androidx.build.Publish
plugins {
@@ -27,8 +24,8 @@
dependencies {
api("androidx.annotation:annotation:1.0.0")
- testImplementation(JUNIT)
- testImplementation(MOCKITO_CORE)
+ testImplementation(libs.junit)
+ testImplementation(libs.mockitoCore)
}
// Used by testImplementation in room-compiler
diff --git a/startup/integration-tests/test-app/build.gradle b/startup/integration-tests/test-app/build.gradle
index 833c186..ff9abe7 100644
--- a/startup/integration-tests/test-app/build.gradle
+++ b/startup/integration-tests/test-app/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -34,7 +32,7 @@
implementation(libs.kotlinStdlib)
implementation(project(":startup:integration-tests:first-library"))
implementation(project(":startup:integration-tests:second-library"))
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation("androidx.arch.core:core-runtime:2.1.0")
implementation("androidx.appcompat:appcompat:1.2.0")
}
diff --git a/swiperefreshlayout/swiperefreshlayout/build.gradle b/swiperefreshlayout/swiperefreshlayout/build.gradle
index 94f6bce..81c571b 100644
--- a/swiperefreshlayout/swiperefreshlayout/build.gradle
+++ b/swiperefreshlayout/swiperefreshlayout/build.gradle
@@ -1,6 +1,4 @@
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.LibraryVersions
import androidx.build.Publish
plugins {
@@ -13,15 +11,15 @@
api("androidx.core:core:1.1.0")
api("androidx.interpolator:interpolator:1.0.0")
- androidTestImplementation(JUNIT)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(ESPRESSO_CONTRIB, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.espressoContrib, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
androidTestImplementation(project(":internal-testutils-espresso"))
androidTestImplementation(project(":internal-testutils-runtime"), {
exclude group: "androidx.swiperefreshlayout", module: "swiperefreshlayout"
diff --git a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutRequestDisallowInterceptBaseTest.java b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutRequestDisallowInterceptBaseTest.java
index 87d8cde..9af786e 100644
--- a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutRequestDisallowInterceptBaseTest.java
+++ b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutRequestDisallowInterceptBaseTest.java
@@ -24,6 +24,7 @@
import android.view.ViewConfiguration;
+import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.testutils.SwipeInjector;
@@ -65,6 +66,7 @@
assertThat(mRecyclerView.mRequestDisallowInterceptFalseCalled, equalTo(false));
}
+ @FlakyTest(bugId = 190613223)
@Test
public void swipeMoreThanTouchSlop_requestDisallowIsCalled() {
assertThat(mRecyclerView.mRequestDisallowInterceptTrueCalled, equalTo(false));
diff --git a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutTest.java b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutTest.java
index bf17eca..af8af21 100644
--- a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutTest.java
+++ b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutTest.java
@@ -69,6 +69,7 @@
mSwipeRefresh = mActivityTestRule.getActivity().findViewById(R.id.swipe_refresh);
}
+ @FlakyTest(bugId = 113347851)
@Test
@LargeTest
public void testStartAndStopRefreshing() throws Throwable {
diff --git a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutWithHorizontallyScrollingChildTest.java b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutWithHorizontallyScrollingChildTest.java
index 66631cd..0b88a46 100644
--- a/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutWithHorizontallyScrollingChildTest.java
+++ b/swiperefreshlayout/swiperefreshlayout/src/androidTest/java/androidx/swiperefreshlayout/widget/SwipeRefreshLayoutWithHorizontallyScrollingChildTest.java
@@ -40,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.testutils.SwipeInjector;
@@ -93,6 +94,7 @@
}
@Test
+ @FlakyTest(bugId = 190192628)
public void refreshWhileScrollingRecyclerView() {
// When we drag the RecyclerView horizontally, and then move the pointer down,
SwipeInjector swiper = new SwipeInjector(InstrumentationRegistry.getInstrumentation());
@@ -115,6 +117,7 @@
@Test
@SuppressWarnings("deprecation")
+ @FlakyTest(bugId = 190192628)
public void refreshWhileScrollingRecyclerView_legacy() {
// If the legacy behavior is enabled
mSwipeRefreshLayout.setLegacyRequestDisallowInterceptTouchEventEnabled(true);
diff --git a/text/text/build.gradle b/text/text/build.gradle
index b5c5320..e118354 100644
--- a/text/text/build.gradle
+++ b/text/text/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -28,25 +26,25 @@
}
dependencies {
- implementation(KOTLIN_STDLIB)
+ implementation(libs.kotlinStdlib)
api "androidx.annotation:annotation:1.1.0"
- testImplementation(ANDROIDX_TEST_RULES)
- testImplementation(ANDROIDX_TEST_RUNNER)
- testImplementation(JUNIT)
+ testImplementation(libs.testRules)
+ testImplementation(libs.testRunner)
+ testImplementation(libs.junit)
androidTestImplementation("androidx.core:core:1.5.0-rc02")
androidTestImplementation(project(":compose:ui:ui-test-font"))
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(ESPRESSO_CORE)
- androidTestImplementation(JUNIT)
- androidTestImplementation(TRUTH)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it"s own MockMaker
- androidTestImplementation(MOCKITO_KOTLIN, {
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.espressoCore)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(libs.mockitoKotlin, {
exclude group: "org.mockito" // to keep control on the mockito version
})
}
diff --git a/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt b/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
index ea867df..915ecb6 100644
--- a/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
+++ b/transition/transition-ktx/src/androidTest/java/androidx/transition/TransitionTest.kt
@@ -19,6 +19,7 @@
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
+import androidx.test.filters.FlakyTest
import androidx.test.filters.MediumTest
import androidx.test.filters.SdkSuppress
import androidx.test.platform.app.InstrumentationRegistry
@@ -44,6 +45,7 @@
transition = Fade().setDuration(50)
}
+ @FlakyTest(bugId = 190193705)
@Test fun testDoOnStart() {
val called = AtomicBoolean()
transition.doOnStart {
@@ -54,6 +56,7 @@
assertTrue(called.get())
}
+ @FlakyTest(bugId = 190193705)
@Test fun testDoOnEnd() {
val called = AtomicBoolean()
transition.doOnEnd {
diff --git a/transition/transition/build.gradle b/transition/transition/build.gradle
index 6fd5d13a..e364dae 100644
--- a/transition/transition/build.gradle
+++ b/transition/transition/build.gradle
@@ -1,8 +1,6 @@
import androidx.build.LibraryGroups
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.MULTIDEX
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
diff --git a/vectordrawable/vectordrawable-animated/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/AnimatedVectorDrawableTest.java b/vectordrawable/vectordrawable-animated/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/AnimatedVectorDrawableTest.java
index d4556d7..b2fa23a 100644
--- a/vectordrawable/vectordrawable-animated/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/AnimatedVectorDrawableTest.java
+++ b/vectordrawable/vectordrawable-animated/src/androidTest/java/androidx/vectordrawable/graphics/drawable/tests/AnimatedVectorDrawableTest.java
@@ -42,6 +42,7 @@
import androidx.core.view.ViewCompat;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -399,6 +400,7 @@
* Test show that callback is successfully registered.
* Note that this test requires screen is on.
*/
+ @FlakyTest(bugId = 190193710)
public void testRegisterCallback() throws Throwable {
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
diff --git a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/BaseViewPagerTest.java b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/BaseViewPagerTest.java
index c1baf88..50a69c9 100644
--- a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/BaseViewPagerTest.java
+++ b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/BaseViewPagerTest.java
@@ -410,6 +410,7 @@
ViewPagerActions.arrowScroll(View.FOCUS_RIGHT), ViewPagerActions.arrowScroll(View.FOCUS_LEFT));
}
+ @FlakyTest(bugId = 112265192)
@Test
@LargeTest
public void testPageSwipesComposite() {
@@ -649,12 +650,14 @@
assertStripInteraction(smoothScroll);
}
+ @FlakyTest(bugId = 112265192)
@Test
@LargeTest
public void testPagerStripImmediate() {
verifyPagerStrip(false);
}
+ @FlakyTest(bugId = 112265192)
@Test
@LargeTest
public void testPagerStripSmooth() {
@@ -1030,6 +1033,7 @@
mViewPager.removeOnPageChangeListener(mockPageChangeListener);
}
+ @FlakyTest(bugId = 112265192)
@Test
@MediumTest
public void testPageScrollPositionChangesImmediate() {
@@ -1068,7 +1072,7 @@
@Test
@LargeTest
- @FlakyTest(bugId = 188565856)
+ @FlakyTest(bugId = 112265192)
public void testPageScrollPositionChangesSwipe() {
// Swipe one page to the left
verifyScrollCallbacksToHigherPage(ViewPagerActions.wrap(swipeLeft()), 1);
@@ -1080,7 +1084,7 @@
verifyScrollCallbacksToLowerPage(ViewPagerActions.wrap(swipeRight()), 0);
}
- @FlakyTest(bugId = 38260187)
+ @FlakyTest(bugId = 112265192)
@Test
@LargeTest
public void testKeyboardNavigation() {
diff --git a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTabStripTest.java b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTabStripTest.java
index 4a0c74c..4e89e33 100644
--- a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTabStripTest.java
+++ b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTabStripTest.java
@@ -30,7 +30,6 @@
/**
* Provides assertions that depend on the interactive nature of <code>PagerTabStrip</code>.
*/
-@FlakyTest(bugId = 112265192)
public class ViewPagerWithTabStripTest extends BaseViewPagerTest<ViewPagerWithTabStripActivity> {
public ViewPagerWithTabStripTest() {
super(ViewPagerWithTabStripActivity.class);
diff --git a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTitleStripTest.java b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTitleStripTest.java
index 7f3f941..ae5c889 100644
--- a/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTitleStripTest.java
+++ b/viewpager/viewpager/src/androidTest/java/androidx/viewpager/widget/ViewPagerWithTitleStripTest.java
@@ -30,7 +30,6 @@
/**
* Provides assertions that depend on the non-interactive nature of <code>PagerTabStrip</code>.
*/
-@FlakyTest(bugId = 112265192)
public class ViewPagerWithTitleStripTest
extends BaseViewPagerTest<ViewPagerWithTitleStripActivity> {
public ViewPagerWithTitleStripTest() {
diff --git a/viewpager2/integration-tests/testapp/build.gradle b/viewpager2/integration-tests/testapp/build.gradle
index 676d328..3c2e9d5 100644
--- a/viewpager2/integration-tests/testapp/build.gradle
+++ b/viewpager2/integration-tests/testapp/build.gradle
@@ -14,12 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_EXT_JUNIT
-import static androidx.build.dependencies.DependenciesKt.ANDROIDX_TEST_RULES
-import static androidx.build.dependencies.DependenciesKt.ESPRESSO_CORE
-import static androidx.build.dependencies.DependenciesKt.KOTLIN_STDLIB
-import static androidx.build.dependencies.DependenciesKt.MATERIAL
-
buildscript {
// TODO: Remove this when this test app no longer depends on 1.0.0 of vectordrawable-animated.
// vectordrawable and vectordrawable-animated were accidentally using the same package name
@@ -34,14 +28,14 @@
}
dependencies {
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
implementation(project(":viewpager2:viewpager2"))
implementation("androidx.activity:activity-ktx:1.2.0")
- implementation(MATERIAL) {
+ implementation(libs.material) {
exclude group: "androidx.viewpager2", module: "viewpager2"
}
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ESPRESSO_CORE)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.espressoCore)
}
diff --git a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MarginPageTransformerTest.kt b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MarginPageTransformerTest.kt
index 5e65603..15a13ba 100644
--- a/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MarginPageTransformerTest.kt
+++ b/viewpager2/integration-tests/testapp/src/androidTest/java/androidx/viewpager2/integration/testapp/test/MarginPageTransformerTest.kt
@@ -24,6 +24,7 @@
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.viewpager2.integration.testapp.PageTransformerActivity
import androidx.viewpager2.integration.testapp.R
@@ -55,6 +56,7 @@
testMargin(null)
}
+ @FlakyTest(bugId = 190611098)
@Test
fun testMargin_offscreenLimit_default() {
testMargin(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT)
diff --git a/viewpager2/viewpager2/build.gradle b/viewpager2/viewpager2/build.gradle
index 8ac831b..6933d03 100644
--- a/viewpager2/viewpager2/build.gradle
+++ b/viewpager2/viewpager2/build.gradle
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.Publish
@@ -31,14 +30,14 @@
api("androidx.recyclerview:recyclerview:1.2.0-alpha06")
implementation("androidx.collection:collection:1.1.0")
- androidTestImplementation(ANDROIDX_TEST_UIAUTOMATOR)
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_CORE)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(ESPRESSO_CORE, excludes.espresso)
- androidTestImplementation(MOCKITO_CORE, excludes.bytebuddy) // DexMaker has it's own MockMaker
- androidTestImplementation(DEXMAKER_MOCKITO, excludes.bytebuddy) // DexMaker has it's own MockMaker
+ androidTestImplementation(libs.testUiautomator)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testCore)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.espressoCore, excludes.espresso)
+ androidTestImplementation(libs.mockitoCore, excludes.bytebuddy) // DexMaker has it's own MockMaker
+ androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it's own MockMaker
androidTestImplementation(project(":internal-testutils-espresso"))
androidTestImplementation(project(":internal-testutils-appcompat"), {
exclude group: "androidx.viewpager2", module: "viewpager2"
@@ -48,7 +47,7 @@
})
// ... therefore we manually depend on AppCompat v1.1.0
androidTestImplementation("androidx.appcompat:appcompat:1.1.0")
- androidTestImplementation(KOTLIN_STDLIB)
+ androidTestImplementation(libs.kotlinStdlib)
}
androidx {
diff --git a/wear/compose/foundation/build.gradle b/wear/compose/foundation/build.gradle
index eab3404..845d675 100644
--- a/wear/compose/foundation/build.gradle
+++ b/wear/compose/foundation/build.gradle
@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
import androidx.build.RunApiTasks
import androidx.build.AndroidXComposePlugin
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -47,10 +46,10 @@
*/
sourceSets {
commonMain.dependencies {
- implementation(KOTLIN_STDLIB_COMMON)
+ implementation(libs.kotlinStdlibCommon)
}
jvmMain.dependencies {
- implementation(KOTLIN_STDLIB)
+ implementation(libs.kotlinStdlib)
}
androidMain {
dependsOn(jvmMain)
@@ -63,10 +62,10 @@
implementation(kotlin("test-junit"))
}
androidAndroidTest.dependencies {
- implementation(ANDROIDX_TEST_EXT_JUNIT)
- implementation(ANDROIDX_TEST_RULES)
- implementation(ANDROIDX_TEST_RUNNER)
- implementation(TRUTH)
+ implementation(libs.testExtJunit)
+ implementation(libs.testRules)
+ implementation(libs.testRunner)
+ implementation(libs.truth)
}
}
}
diff --git a/wear/compose/material/benchmark/build.gradle b/wear/compose/material/benchmark/build.gradle
index 0cbfebd..4c7b67e 100644
--- a/wear/compose/material/benchmark/build.gradle
+++ b/wear/compose/material/benchmark/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -46,10 +44,10 @@
androidTestImplementation project(":compose:benchmark-utils")
androidTestImplementation project(":wear:compose:compose-foundation")
androidTestImplementation project(":wear:compose:compose-material")
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(JUNIT)
- androidTestImplementation(KOTLIN_STDLIB)
- androidTestImplementation(KOTLIN_REFLECT)
- androidTestImplementation(KOTLIN_TEST_COMMON)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.junit)
+ androidTestImplementation(libs.kotlinStdlib)
+ androidTestImplementation(libs.kotlinReflect)
+ androidTestImplementation(libs.kotlinTestCommon)
+ androidTestImplementation(libs.truth)
}
\ No newline at end of file
diff --git a/wear/compose/material/build.gradle b/wear/compose/material/build.gradle
index c9abd4d..f6f0baf 100644
--- a/wear/compose/material/build.gradle
+++ b/wear/compose/material/build.gradle
@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
import androidx.build.RunApiTasks
import androidx.build.AndroidXComposePlugin
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
@@ -46,7 +45,7 @@
androidTestImplementation project(path: ':compose:ui:ui-test-junit4')
androidTestImplementation project(path: ':compose:test-utils')
androidTestImplementation project(":test-screenshot")
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(libs.testRunner)
}
}
@@ -61,7 +60,7 @@
*/
sourceSets {
commonMain.dependencies {
- implementation(KOTLIN_STDLIB_COMMON)
+ implementation(libs.kotlinStdlibCommon)
api(project(":compose:foundation:foundation"))
api(project(":compose:ui:ui"))
@@ -72,7 +71,7 @@
implementation(project(":compose:material:material-ripple"))
}
jvmMain.dependencies {
- implementation(KOTLIN_STDLIB)
+ implementation(libs.kotlinStdlib)
}
androidMain {
dependsOn(jvmMain)
@@ -85,10 +84,10 @@
implementation(kotlin("test-junit"))
}
androidAndroidTest.dependencies {
- implementation(ANDROIDX_TEST_EXT_JUNIT)
- implementation(ANDROIDX_TEST_RULES)
- implementation(ANDROIDX_TEST_RUNNER)
- implementation(TRUTH)
+ implementation(libs.testExtJunit)
+ implementation(libs.testRules)
+ implementation(libs.testRunner)
+ implementation(libs.truth)
implementation(project(path: ':compose:ui:ui-test'))
implementation(project(path: ':compose:ui:ui-test-junit4'))
implementation(project(path: ':compose:test-utils'))
diff --git a/wear/tiles/tiles-testing/api/current.txt b/wear/tiles/tiles-testing/api/current.txt
new file mode 100644
index 0000000..e53d376
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.wear.tiles.testing {
+
+ public final class TestingTileProviderClient<T extends androidx.wear.tiles.TileProviderService> implements androidx.wear.tiles.client.TileProviderClient {
+ ctor public TestingTileProviderClient(T service, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+ ctor public TestingTileProviderClient(T service, java.util.concurrent.Executor executor);
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getApiVersion();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileAdded();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileEnter();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileLeave();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileRemoved();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> resourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> tileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+ }
+
+}
+
diff --git a/wear/tiles/tiles-testing/api/public_plus_experimental_current.txt b/wear/tiles/tiles-testing/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..e53d376
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/public_plus_experimental_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.wear.tiles.testing {
+
+ public final class TestingTileProviderClient<T extends androidx.wear.tiles.TileProviderService> implements androidx.wear.tiles.client.TileProviderClient {
+ ctor public TestingTileProviderClient(T service, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+ ctor public TestingTileProviderClient(T service, java.util.concurrent.Executor executor);
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getApiVersion();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileAdded();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileEnter();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileLeave();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileRemoved();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> resourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> tileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+ }
+
+}
+
diff --git a/wear/tiles/tiles-testing/api/res-current.txt b/wear/tiles/tiles-testing/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/res-current.txt
diff --git a/wear/tiles/tiles-testing/api/restricted_current.txt b/wear/tiles/tiles-testing/api/restricted_current.txt
new file mode 100644
index 0000000..e53d376
--- /dev/null
+++ b/wear/tiles/tiles-testing/api/restricted_current.txt
@@ -0,0 +1,17 @@
+// Signature format: 4.0
+package androidx.wear.tiles.testing {
+
+ public final class TestingTileProviderClient<T extends androidx.wear.tiles.TileProviderService> implements androidx.wear.tiles.client.TileProviderClient {
+ ctor public TestingTileProviderClient(T service, kotlinx.coroutines.CoroutineScope coroutineScope, kotlinx.coroutines.CoroutineDispatcher coroutineDispatcher);
+ ctor public TestingTileProviderClient(T service, java.util.concurrent.Executor executor);
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Integer> getApiVersion();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileAdded();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileEnter();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileLeave();
+ method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void> onTileRemoved();
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.ResourceBuilders.Resources> resourcesRequest(androidx.wear.tiles.RequestBuilders.ResourcesRequest requestParams);
+ method public com.google.common.util.concurrent.ListenableFuture<androidx.wear.tiles.TileBuilders.Tile> tileRequest(androidx.wear.tiles.RequestBuilders.TileRequest requestParams);
+ }
+
+}
+
diff --git a/wear/tiles/tiles-testing/build.gradle b/wear/tiles/tiles-testing/build.gradle
new file mode 100644
index 0000000..526dbc2
--- /dev/null
+++ b/wear/tiles/tiles-testing/build.gradle
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 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.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryType
+import androidx.build.LibraryVersions
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("kotlin-android")
+ id("com.google.protobuf")
+}
+
+dependencies {
+ api("androidx.annotation:annotation:1.1.0")
+ api(libs.guavaListenableFuture)
+
+ implementation "androidx.concurrent:concurrent-futures:1.1.0"
+ implementation "androidx.concurrent:concurrent-futures-ktx:1.1.0"
+ implementation "androidx.core:core:1.3.2"
+ implementation "androidx.wear:wear:1.2.0-alpha09"
+
+ implementation(project(":wear:tiles:tiles"))
+ implementation(project(":wear:tiles:tiles-renderer"))
+ implementation(libs.kotlinCoroutinesCore)
+ implementation(libs.kotlinCoroutinesAndroid)
+ implementation(libs.robolectric)
+ implementation(libs.testCore)
+
+ testImplementation(libs.testExtJunit)
+ testImplementation(libs.testExtTruth)
+ testImplementation(libs.testCore)
+ testImplementation(libs.testRunner)
+ testImplementation(libs.testRules)
+ testImplementation(libs.robolectric)
+ testImplementation(libs.truth)
+}
+
+android {
+ defaultConfig {
+ minSdkVersion 26
+ targetSdkVersion 29
+ }
+
+ // Use Robolectric 4.+
+ testOptions.unitTests.includeAndroidResources = true
+}
+
+androidx {
+ name = "Android Wear Tiles Testing Utilities"
+ type = LibraryType.PUBLISHED_LIBRARY
+ mavenGroup = LibraryGroups.WEAR_TILES
+ mavenVersion = LibraryVersions.WEAR_TILES
+ inceptionYear = "2021"
+ description = "Testing utilities for Android Wear Tiles."
+}
diff --git a/wear/tiles/tiles-testing/src/main/AndroidManifest.xml b/wear/tiles/tiles-testing/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..6238b06
--- /dev/null
+++ b/wear/tiles/tiles-testing/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2021 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"
+ package="androidx.wear.tiles.testing">
+</manifest>
diff --git a/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestingTileProviderClient.kt b/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestingTileProviderClient.kt
new file mode 100644
index 0000000..d49d6b3
--- /dev/null
+++ b/wear/tiles/tiles-testing/src/main/java/androidx/wear/tiles/testing/TestingTileProviderClient.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2021 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.wear.tiles.testing
+
+import android.app.Application
+import android.app.Service
+import android.content.ComponentName
+import android.content.Intent
+import androidx.test.core.app.ApplicationProvider.getApplicationContext
+import androidx.wear.tiles.RequestBuilders
+import androidx.wear.tiles.ResourceBuilders
+import androidx.wear.tiles.TileBuilders
+import androidx.wear.tiles.TileProviderService
+import androidx.wear.tiles.client.TileProviderClient
+import androidx.wear.tiles.connection.DefaultTileProviderClient
+import com.google.common.util.concurrent.ListenableFuture
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import org.robolectric.Shadows.shadowOf
+import org.robolectric.android.controller.ServiceController
+import java.util.concurrent.Executor
+
+/**
+ * TileProviderClient for testing purposes. This will pass calls through to the given instance of
+ * [TileProviderService], handling all the service binding (via Robolectric), and
+ * serialization/deserialization.
+ *
+ * Note that this class will not drive the full service lifecycle for the passed service instance.
+ * On the first call to any of these methods, it will call your service's [Service.onCreate] method,
+ * however, it will never call [Service.onDestroy]. Equally, where [DefaultTileProviderClient] will
+ * unbind after a period of time, potentially destroying the service, this class wil Client will
+ * unbind, but not destroy the service. If you wish to test service destruction, you can instead
+ * call [Service.onDestroy] on the passed in `service` instance.
+ */
+public class TestingTileProviderClient<T : TileProviderService> : TileProviderClient {
+ private val controller: ServiceController<T>
+ private val componentName: ComponentName
+ private val innerTileProvider: DefaultTileProviderClient
+ private var hasBound = false
+
+ public constructor(
+ service: T,
+ coroutineScope: CoroutineScope,
+ coroutineDispatcher: CoroutineDispatcher
+ ) {
+ val bindIntent = Intent(TileProviderService.ACTION_BIND_TILE_PROVIDER)
+ this.componentName = ComponentName(getApplicationContext(), service.javaClass)
+
+ bindIntent.component = componentName
+ this.controller = ServiceController.of(service, bindIntent)
+
+ this.innerTileProvider = DefaultTileProviderClient(
+ getApplicationContext(),
+ componentName,
+ coroutineScope,
+ coroutineDispatcher
+ )
+ }
+
+ public constructor(service: T, executor: Executor) {
+ val bindIntent = Intent(TileProviderService.ACTION_BIND_TILE_PROVIDER)
+ this.componentName = ComponentName(getApplicationContext(), service.javaClass)
+
+ bindIntent.component = componentName
+ this.controller = ServiceController.of(service, bindIntent)
+
+ this.innerTileProvider = DefaultTileProviderClient(
+ getApplicationContext(),
+ componentName,
+ executor
+ )
+ }
+
+ override fun getApiVersion(): ListenableFuture<Int> {
+ maybeBind()
+ return innerTileProvider.apiVersion
+ }
+
+ override fun tileRequest(
+ requestParams: RequestBuilders.TileRequest
+ ): ListenableFuture<TileBuilders.Tile> {
+ maybeBind()
+ return innerTileProvider.tileRequest(requestParams)
+ }
+
+ override fun resourcesRequest(
+ requestParams: RequestBuilders.ResourcesRequest
+ ): ListenableFuture<ResourceBuilders.Resources> {
+ maybeBind()
+ return innerTileProvider.resourcesRequest(requestParams)
+ }
+
+ override fun onTileAdded(): ListenableFuture<Void?> {
+ maybeBind()
+ return innerTileProvider.onTileAdded()
+ }
+
+ override fun onTileRemoved(): ListenableFuture<Void?> {
+ maybeBind()
+ return innerTileProvider.onTileRemoved()
+ }
+
+ override fun onTileEnter(): ListenableFuture<Void?> {
+ maybeBind()
+ return innerTileProvider.onTileEnter()
+ }
+
+ override fun onTileLeave(): ListenableFuture<Void?> {
+ maybeBind()
+ return innerTileProvider.onTileLeave()
+ }
+
+ private fun maybeBind() {
+ if (!hasBound) {
+ val binder = controller.create().get().onBind(controller.intent)
+
+ shadowOf(getApplicationContext<Application>())
+ .setComponentNameAndServiceForBindServiceForIntent(
+ controller.intent,
+ componentName,
+ binder
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestingTileProviderClientTest.kt b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestingTileProviderClientTest.kt
new file mode 100644
index 0000000..dd31596
--- /dev/null
+++ b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TestingTileProviderClientTest.kt
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2021 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.wear.tiles.testing
+
+import android.os.Looper
+import androidx.concurrent.futures.ResolvableFuture
+import androidx.wear.tiles.EventBuilders
+import androidx.wear.tiles.RequestBuilders
+import androidx.wear.tiles.ResourceBuilders
+import androidx.wear.tiles.TileBuilders
+import androidx.wear.tiles.TileProvider
+import androidx.wear.tiles.TileProviderService
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.ListenableFuture
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.Shadows.shadowOf
+import org.robolectric.android.util.concurrent.InlineExecutorService
+import org.robolectric.annotation.internal.DoNotInstrument
+
+@RunWith(TilesTestingTestRunner::class)
+@DoNotInstrument
+public class TestingTileProviderClientTest {
+ private companion object {
+ private val RESOURCES_VERSION = "10"
+ }
+ private val fakeTileProvider = FakeTileProviderService()
+ private lateinit var clientUnderTest: TestingTileProviderClient<FakeTileProviderService>
+
+ @Before
+ public fun setUp() {
+ val executor = InlineExecutorService()
+ clientUnderTest = TestingTileProviderClient(fakeTileProvider, executor)
+ }
+
+ @Test
+ public fun canCallGetApiVersion() {
+ val future = clientUnderTest.apiVersion
+
+ shadowOf(Looper.getMainLooper()).idle()
+ assertThat(future.isDone).isTrue()
+ assertThat(future.get()).isEqualTo(TileProvider.API_VERSION)
+ }
+
+ @Test
+ public fun canCallOnTileRequest() {
+ val future = clientUnderTest.tileRequest(RequestBuilders.TileRequest.builder().build())
+
+ shadowOf(Looper.getMainLooper()).idle()
+ assertThat(future.isDone).isTrue()
+ assertThat(future.get().resourcesVersion).isEqualTo(RESOURCES_VERSION)
+ }
+
+ @Test
+ public fun canCallOnResourcesRequest() {
+ val future = clientUnderTest.resourcesRequest(
+ RequestBuilders.ResourcesRequest.builder().build()
+ )
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(future.isDone).isTrue()
+ assertThat(future.get().version).isEqualTo(RESOURCES_VERSION)
+ }
+
+ @Test
+ public fun canCallOnTileAdd() {
+ val f = clientUnderTest.onTileAdded()
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(f.isDone).isTrue()
+ assertThat(fakeTileProvider.onTileAddFired).isTrue()
+ assertThat(fakeTileProvider.onTileRemoveFired).isFalse()
+ assertThat(fakeTileProvider.onTileEnterFired).isFalse()
+ assertThat(fakeTileProvider.onTileLeaveFired).isFalse()
+ }
+
+ @Test
+ public fun canCallOnTileRemove() {
+ val f = clientUnderTest.onTileRemoved()
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(f.isDone).isTrue()
+ assertThat(fakeTileProvider.onTileAddFired).isFalse()
+ assertThat(fakeTileProvider.onTileRemoveFired).isTrue()
+ assertThat(fakeTileProvider.onTileEnterFired).isFalse()
+ assertThat(fakeTileProvider.onTileLeaveFired).isFalse()
+ }
+
+ @Test
+ public fun canCallOnTileEnter() {
+ val f = clientUnderTest.onTileEnter()
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(f.isDone).isTrue()
+ assertThat(fakeTileProvider.onTileAddFired).isFalse()
+ assertThat(fakeTileProvider.onTileRemoveFired).isFalse()
+ assertThat(fakeTileProvider.onTileEnterFired).isTrue()
+ assertThat(fakeTileProvider.onTileLeaveFired).isFalse()
+ }
+
+ @Test
+ public fun canCallOnTileLeave() {
+ val f = clientUnderTest.onTileLeave()
+
+ shadowOf(Looper.getMainLooper()).idle()
+
+ assertThat(f.isDone).isTrue()
+ assertThat(fakeTileProvider.onTileAddFired).isFalse()
+ assertThat(fakeTileProvider.onTileRemoveFired).isFalse()
+ assertThat(fakeTileProvider.onTileEnterFired).isFalse()
+ assertThat(fakeTileProvider.onTileLeaveFired).isTrue()
+ }
+
+ public inner class FakeTileProviderService : TileProviderService() {
+ internal var onTileAddFired = false
+ internal var onTileRemoveFired = false
+ internal var onTileEnterFired = false
+ internal var onTileLeaveFired = false
+
+ override fun onTileRequest(
+ requestParams: RequestBuilders.TileRequest
+ ): ListenableFuture<TileBuilders.Tile> {
+ val f = ResolvableFuture.create<TileBuilders.Tile>()
+
+ f.set(TileBuilders.Tile.builder().setResourcesVersion(RESOURCES_VERSION).build())
+
+ return f
+ }
+
+ override fun onResourcesRequest(
+ requestParams: RequestBuilders.ResourcesRequest
+ ): ListenableFuture<ResourceBuilders.Resources> {
+ val f = ResolvableFuture.create<ResourceBuilders.Resources>()
+
+ f.set(ResourceBuilders.Resources.builder().setVersion(RESOURCES_VERSION).build())
+
+ return f
+ }
+
+ override fun onTileAddEvent(requestParams: EventBuilders.TileAddEvent) {
+ onTileAddFired = true
+ }
+
+ override fun onTileRemoveEvent(requestParams: EventBuilders.TileRemoveEvent) {
+ onTileRemoveFired = true
+ }
+
+ override fun onTileEnterEvent(requestParams: EventBuilders.TileEnterEvent) {
+ onTileEnterFired = true
+ }
+
+ override fun onTileLeaveEvent(requestParams: EventBuilders.TileLeaveEvent) {
+ onTileLeaveFired = true
+ }
+ }
+}
diff --git a/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TilesTestingTestRunner.kt b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TilesTestingTestRunner.kt
new file mode 100644
index 0000000..5392776
--- /dev/null
+++ b/wear/tiles/tiles-testing/src/test/java/androidx/wear/tiles/testing/TilesTestingTestRunner.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 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.wear.tiles.testing
+
+import org.junit.runners.model.FrameworkMethod
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.internal.bytecode.InstrumentationConfiguration
+
+public class TilesTestingTestRunner(testClass: Class<*>) : RobolectricTestRunner(testClass) {
+ override fun createClassLoaderConfig(method: FrameworkMethod): InstrumentationConfiguration =
+ InstrumentationConfiguration.Builder(super.createClassLoaderConfig(method))
+ .doNotInstrumentPackage("androidx.wear.tiles.connection")
+ .doNotInstrumentPackage("androidx.wear.tiles.testing")
+ .build()
+}
\ No newline at end of file
diff --git a/wear/wear-complications-data/src/main/java/androidx/wear/utility/TraceEvent.kt b/wear/wear-complications-data/src/main/java/androidx/wear/utility/TraceEvent.kt
index 083d0f8..3404479 100644
--- a/wear/wear-complications-data/src/main/java/androidx/wear/utility/TraceEvent.kt
+++ b/wear/wear-complications-data/src/main/java/androidx/wear/utility/TraceEvent.kt
@@ -16,7 +16,6 @@
package androidx.wear.utility
-import android.annotation.SuppressLint
import android.os.Build
import android.os.Trace
import androidx.annotation.DoNotInline
@@ -49,7 +48,6 @@
*
* @hide
**/
-@SuppressLint("UnsafeNewApiCall")
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class AsyncTraceEvent(private val traceName: String) : Closeable {
internal companion object {
@@ -103,4 +101,4 @@
block.invoke(this)
}
}
-}
\ No newline at end of file
+}
diff --git a/wear/wear-watchface-client/guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt b/wear/wear-watchface-client/guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
index c37c6b3..5a06d40 100644
--- a/wear/wear-watchface-client/guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
+++ b/wear/wear-watchface-client/guava/src/main/java/androidx/wear/watchface/client/ListenableWatchFaceControlClient.kt
@@ -16,7 +16,6 @@
package androidx.wear.watchface.client
-import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import androidx.concurrent.futures.ResolvableFuture
@@ -102,7 +101,6 @@
* to a [ListenableWatchFaceControlClient] or throws a [ServiceNotBoundException] if the
* watch face control service can not be bound.
*/
- @SuppressLint("NewApi") // For ACTION_WATCHFACE_CONTROL_SERVICE
@JvmStatic
public fun createWatchFaceControlClient(
context: Context,
diff --git a/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt b/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
index 513e655..3ce706d 100644
--- a/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
+++ b/wear/wear-watchface-client/src/main/java/androidx/wear/watchface/client/WatchFaceControlClient.kt
@@ -16,7 +16,6 @@
package androidx.wear.watchface.client
-import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -64,7 +63,6 @@
* @throws [ServiceNotBoundException] if the watch face control service can not be bound or
* a [ServiceStartFailureException] if the watch face dies during startup.
*/
- @SuppressLint("NewApi") // For ACTION_WATCHFACE_CONTROL_SERVICE
@JvmStatic
public suspend fun createWatchFaceControlClient(
context: Context,
diff --git a/wear/wear/src/androidTest/java/androidx/wear/widget/ConfirmationOverlayTest.java b/wear/wear/src/androidTest/java/androidx/wear/widget/ConfirmationOverlayTest.java
index 2063f3f..1cd7644 100644
--- a/wear/wear/src/androidTest/java/androidx/wear/widget/ConfirmationOverlayTest.java
+++ b/wear/wear/src/androidTest/java/androidx/wear/widget/ConfirmationOverlayTest.java
@@ -29,6 +29,7 @@
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.wear.R;
@@ -74,6 +75,7 @@
}
@Test
+ @FlakyTest(bugId = 190194611)
public void testDefaults_onActivity() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
final ConfirmationOverlay overlay = new ConfirmationOverlay();
@@ -116,6 +118,7 @@
}
@Test
+ @FlakyTest(bugId = 190194611)
public void testSuccess_onActivity() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
final ConfirmationOverlay overlay = new ConfirmationOverlay()
@@ -147,6 +150,7 @@
}
@Test
+ @FlakyTest(bugId = 190194611)
public void testFailure_onActivity() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
final ConfirmationOverlay overlay = new ConfirmationOverlay()
@@ -178,6 +182,7 @@
}
@Test
+ @FlakyTest(bugId = 190194611)
public void testOpenOnPhone_onActivity() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
final ConfirmationOverlay overlay = new ConfirmationOverlay()
@@ -250,6 +255,7 @@
}
@Test
+ @FlakyTest(bugId = 190194611)
public void testOverlayHiddenAfterSpecifiedDuration() throws Throwable {
final CountDownLatch latch = new CountDownLatch(1);
final int overlayDurationMillis = 2000;
diff --git a/webkit/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatForceDarkTest.java b/webkit/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatForceDarkTest.java
index 52fd3b0..6975136 100644
--- a/webkit/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatForceDarkTest.java
+++ b/webkit/webkit/src/androidTest/java/androidx/webkit/WebSettingsCompatForceDarkTest.java
@@ -28,6 +28,7 @@
import androidx.core.graphics.ColorUtils;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
@@ -99,6 +100,7 @@
* should be reflected in that test as necessary. See http://go/modifying-webview-cts.
*/
@Test
+ @FlakyTest(bugId = 190195340)
public void testForceDark_rendersDark() throws Throwable {
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK);
WebkitUtils.checkFeature(WebViewFeature.OFF_SCREEN_PRERASTER);
@@ -132,6 +134,7 @@
* i.e. web contents are always darkened by a user agent.
*/
@Test
+ @FlakyTest(bugId = 190195340)
public void testForceDark_userAgentDarkeningOnly() {
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK);
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK_STRATEGY);
@@ -162,6 +165,7 @@
* i.e. web contents are darkened only by web theme.
*/
@Test
+ @FlakyTest(bugId = 190195340)
public void testForceDark_webThemeDarkeningOnly() {
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK);
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK_STRATEGY);
@@ -192,6 +196,7 @@
* i.e. web contents are darkened by a user agent if there is no dark web theme.
*/
@Test
+ @FlakyTest(bugId = 190195340)
public void testForceDark_preferWebThemeOverUADarkening() {
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK);
WebkitUtils.checkFeature(WebViewFeature.FORCE_DARK_STRATEGY);
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java
index fc99bcb..a1f7c0d 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebResourceRequestCompat.java
@@ -16,7 +16,6 @@
package androidx.webkit;
-import android.annotation.SuppressLint;
import android.webkit.WebResourceRequest;
import androidx.annotation.NonNull;
@@ -43,7 +42,6 @@
*
* @return whether the request was a result of a server-side redirect.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.WEB_RESOURCE_REQUEST_IS_REDIRECT,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static boolean isRedirect(@NonNull WebResourceRequest request) {
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
index 7d079ab..1b31dca 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
@@ -16,7 +16,6 @@
package androidx.webkit;
-import android.annotation.SuppressLint;
import android.webkit.WebSettings;
import androidx.annotation.IntDef;
@@ -58,7 +57,6 @@
* {@link WebViewFeature#isFeatureSupported(String)}
* returns true for {@link WebViewFeature#OFF_SCREEN_PRERASTER}.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.OFF_SCREEN_PRERASTER,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setOffscreenPreRaster(@NonNull WebSettings settings, boolean enabled) {
@@ -84,7 +82,6 @@
* @return {@code true} if this WebView will raster tiles when it is
* offscreen but attached to a window.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.OFF_SCREEN_PRERASTER,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static boolean getOffscreenPreRaster(@NonNull WebSettings settings) {
@@ -117,7 +114,6 @@
*
* @param enabled Whether Safe Browsing is enabled.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SAFE_BROWSING_ENABLE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setSafeBrowsingEnabled(@NonNull WebSettings settings, boolean enabled) {
@@ -142,7 +138,6 @@
*
* @return {@code true} if Safe Browsing is enabled and {@code false} otherwise.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SAFE_BROWSING_ENABLE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static boolean getSafeBrowsingEnabled(@NonNull WebSettings settings) {
@@ -180,7 +175,6 @@
*
* @param menuItems an integer field flag for the menu items to be disabled.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setDisabledActionModeMenuItems(@NonNull WebSettings settings,
@@ -207,7 +201,6 @@
*
* @return all the disabled menu item flags combined with bitwise OR.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.DISABLED_ACTION_MODE_MENU_ITEMS,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @MenuItemFlags int getDisabledActionModeMenuItems(@NonNull WebSettings settings) {
@@ -239,7 +232,6 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SUPPRESS_ERROR_PAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setWillSuppressErrorPage(@NonNull WebSettings settings,
@@ -268,7 +260,6 @@
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY)
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SUPPRESS_ERROR_PAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static boolean willSuppressErrorPage(@NonNull WebSettings settings) {
@@ -344,7 +335,6 @@
* @param forceDarkMode the force dark mode to set.
* @see #getForceDark
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.FORCE_DARK,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setForceDark(@NonNull WebSettings settings,
@@ -373,7 +363,6 @@
* @return the currently set force dark mode.
* @see #setForceDark
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.FORCE_DARK,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @ForceDark int getForceDark(@NonNull WebSettings settings) {
@@ -457,7 +446,6 @@
* @param forceDarkBehavior the force dark strategy to set.
* @see #getForceDarkStrategy
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.FORCE_DARK_STRATEGY,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setForceDarkStrategy(@NonNull WebSettings settings,
@@ -485,7 +473,6 @@
* @return the currently set force dark strategy.
* @see #setForceDarkStrategy
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.FORCE_DARK_STRATEGY,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @ForceDarkStrategy int getForceDarkStrategy(@NonNull WebSettings settings) {
diff --git a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index 547a9bd..68a57ab 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -156,7 +156,6 @@
* requests with callbacks.
* @param callback The callback to be invoked.
*/
- @SuppressWarnings("NewApi")
@RequiresFeature(name = WebViewFeature.VISUAL_STATE_CALLBACK,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void postVisualStateCallback(@NonNull WebView webview, long requestId,
@@ -201,7 +200,6 @@
* @param callback will be called on the UI thread with {@code true} if initialization is
* successful, {@code false} otherwise.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.START_SAFE_BROWSING,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void startSafeBrowsing(@NonNull Context context,
@@ -244,7 +242,6 @@
* allowlist, {@code false} if any hosts are malformed. The callback will be run on the UI
* thread
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SAFE_BROWSING_ALLOWLIST,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setSafeBrowsingAllowlist(@NonNull Set<String> hosts,
@@ -298,7 +295,6 @@
* @deprecated Please use {@link #setSafeBrowsingAllowlist(Set, ValueCallback)} instead.
*/
@Deprecated
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.SAFE_BROWSING_WHITELIST,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setSafeBrowsingWhitelist(@NonNull List<String> hosts,
@@ -316,7 +312,6 @@
*
* @return the url pointing to a privacy policy document which can be displayed to users.
*/
- @SuppressLint("NewApi")
@NonNull
@RequiresFeature(name = WebViewFeature.SAFE_BROWSING_PRIVACY_POLICY_URL,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
@@ -442,7 +437,6 @@
*
* @return an array of size two, containing the two message ports that form the message channel.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.CREATE_WEB_MESSAGE_CHANNEL,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @NonNull WebMessagePortCompat[] createWebMessageChannel(
@@ -474,7 +468,6 @@
* @param message the WebMessage
* @param targetOrigin the target origin.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.POST_WEB_MESSAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void postWebMessage(@NonNull WebView webview, @NonNull WebMessageCompat message,
@@ -758,7 +751,6 @@
*
* @return the WebViewClient, or a default client if not yet set
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.GET_WEB_VIEW_CLIENT,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @NonNull WebViewClient getWebViewClient(@NonNull WebView webview) {
@@ -782,7 +774,6 @@
*
* @return the WebChromeClient, or {@code null} if not yet set
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.GET_WEB_CHROME_CLIENT,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @Nullable WebChromeClient getWebChromeClient(@NonNull WebView webview) {
@@ -817,7 +808,6 @@
* with this {@link android.webkit.WebView}, or {@code null} if
* WebView is not running in multiprocess mode.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.GET_WEB_VIEW_RENDERER,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @Nullable WebViewRenderProcess getWebViewRenderProcess(@NonNull WebView webview) {
@@ -864,7 +854,7 @@
*/
// WebViewRenderProcessClient is a callback class, so it should be last. See
// https://issuetracker.google.com/issues/139770271.
- @SuppressLint({"LambdaLast", "NewApi"})
+ @SuppressLint({"LambdaLast"})
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setWebViewRenderProcessClient(
@@ -904,7 +894,6 @@
* @param webViewRenderProcessClient the {@link WebViewRenderProcessClient} to set for
* callbacks.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static void setWebViewRenderProcessClient(
@@ -935,7 +924,6 @@
* {@link #setWebViewRenderProcessClient(WebView,WebViewRenderProcessClient)} or {@code null}
* otherwise.
*/
- @SuppressLint("NewApi")
@RequiresFeature(name = WebViewFeature.WEB_VIEW_RENDERER_CLIENT_BASIC_USAGE,
enforcement = "androidx.webkit.WebViewFeature#isFeatureSupported")
public static @Nullable WebViewRenderProcessClient getWebViewRenderProcessClient(
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/SafeBrowsingResponseImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/SafeBrowsingResponseImpl.java
index fe0c9e5..f4a0ecd 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/SafeBrowsingResponseImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/SafeBrowsingResponseImpl.java
@@ -16,7 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
import android.webkit.SafeBrowsingResponse;
import androidx.annotation.NonNull;
@@ -77,7 +76,6 @@
return mBoundaryInterface;
}
- @SuppressLint("NewApi")
@Override
public void showInterstitial(boolean allowReporting) {
final WebViewFeatureInternal feature =
@@ -91,7 +89,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void proceed(boolean report) {
final WebViewFeatureInternal feature =
@@ -105,7 +102,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void backToSafety(boolean report) {
final WebViewFeatureInternal feature =
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java
index 068031b..87b1dd0 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerControllerImpl.java
@@ -16,7 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
import android.webkit.ServiceWorkerController;
import androidx.annotation.NonNull;
@@ -39,7 +38,6 @@
private ServiceWorkerControllerBoundaryInterface mBoundaryInterface;
private final ServiceWorkerWebSettingsCompat mWebSettings;
- @SuppressLint("NewApi")
public ServiceWorkerControllerImpl() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_BASIC_USAGE;
if (feature.isSupportedByFramework()) {
@@ -80,7 +78,6 @@
return mWebSettings;
}
- @SuppressLint("NewApi")
@Override
public void setServiceWorkerClient(@Nullable ServiceWorkerClientCompat client) {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_BASIC_USAGE;
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java
index cad3ccb..d246d6d 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/ServiceWorkerWebSettingsImpl.java
@@ -16,7 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
import android.webkit.ServiceWorkerWebSettings;
import androidx.annotation.NonNull;
@@ -87,7 +86,6 @@
return mBoundaryInterface;
}
- @SuppressLint("NewApi")
@Override
public void setCacheMode(int mode) {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
@@ -100,7 +98,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public int getCacheMode() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CACHE_MODE;
@@ -113,7 +110,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void setAllowContentAccess(boolean allow) {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
@@ -126,7 +122,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public boolean getAllowContentAccess() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_CONTENT_ACCESS;
@@ -139,7 +134,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void setAllowFileAccess(boolean allow) {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
@@ -152,7 +146,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public boolean getAllowFileAccess() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.SERVICE_WORKER_FILE_ACCESS;
@@ -165,7 +158,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void setBlockNetworkLoads(boolean flag) {
final WebViewFeatureInternal feature =
@@ -179,7 +171,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public boolean getBlockNetworkLoads() {
final WebViewFeatureInternal feature =
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/TracingControllerImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/TracingControllerImpl.java
index cb37552..9492e87 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/TracingControllerImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/TracingControllerImpl.java
@@ -16,8 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
-
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.webkit.TracingConfig;
@@ -37,7 +35,6 @@
private android.webkit.TracingController mFrameworksImpl;
private TracingControllerBoundaryInterface mBoundaryInterface;
- @SuppressLint("NewApi")
public TracingControllerImpl() {
final WebViewFeatureInternal feature =
WebViewFeatureInternal.TRACING_CONTROLLER_BASIC_USAGE;
@@ -67,7 +64,6 @@
return mBoundaryInterface;
}
- @SuppressLint("NewApi")
@Override
public boolean isTracing() {
final WebViewFeatureInternal feature =
@@ -81,7 +77,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void start(@NonNull TracingConfig tracingConfig) {
if (tracingConfig == null) {
@@ -105,7 +100,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public boolean stop(OutputStream outputStream, Executor executor) {
final WebViewFeatureInternal feature =
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java
index 88d5b52..8f41bdc5 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebMessagePortImpl.java
@@ -16,7 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
import android.os.Handler;
import android.webkit.WebMessage;
import android.webkit.WebMessagePort;
@@ -70,7 +69,6 @@
return mBoundaryInterface;
}
- @SuppressLint("NewApi")
@Override
public void postMessage(@NonNull WebMessageCompat message) {
final WebViewFeatureInternal feature = WebViewFeatureInternal.WEB_MESSAGE_PORT_POST_MESSAGE;
@@ -85,7 +83,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void close() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.WEB_MESSAGE_PORT_CLOSE;
@@ -98,7 +95,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void setWebMessageCallback(@NonNull final WebMessageCallbackCompat callback) {
final WebViewFeatureInternal feature =
@@ -106,7 +102,6 @@
if (feature.isSupportedByFramework()) {
getFrameworksImpl().setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
- @SuppressWarnings("NewApi")
public void onMessage(WebMessagePort port, WebMessage message) {
callback.onMessage(new WebMessagePortImpl(port),
frameworkMessageToCompat(message));
@@ -121,7 +116,6 @@
}
}
- @SuppressLint("NewApi")
@Override
public void setWebMessageCallback(Handler handler,
@NonNull final WebMessageCallbackCompat callback) {
@@ -129,7 +123,6 @@
if (feature.isSupportedByFramework()) {
getFrameworksImpl().setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
- @SuppressWarnings("NewApi")
public void onMessage(WebMessagePort port, WebMessage message) {
callback.onMessage(new WebMessagePortImpl(port),
frameworkMessageToCompat(message));
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java
index 806afb0..2a79eae 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebResourceErrorImpl.java
@@ -16,7 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
import android.webkit.WebResourceError;
import androidx.annotation.NonNull;
@@ -76,7 +75,6 @@
return mBoundaryInterface;
}
- @SuppressLint("NewApi")
@Override
public int getErrorCode() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.WEB_RESOURCE_ERROR_GET_CODE;
@@ -90,7 +88,6 @@
}
@NonNull
- @SuppressLint("NewApi")
@Override
public CharSequence getDescription() {
final WebViewFeatureInternal feature =
diff --git a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
index 6ccde44..d8308fe 100644
--- a/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
+++ b/webkit/webkit/src/main/java/androidx/webkit/internal/WebViewRenderProcessImpl.java
@@ -16,8 +16,6 @@
package androidx.webkit.internal;
-import android.annotation.SuppressLint;
-
import androidx.annotation.NonNull;
import androidx.webkit.WebViewRenderProcess;
@@ -85,7 +83,6 @@
return renderer;
}
- @SuppressLint("NewApi")
@Override
public boolean terminate() {
final WebViewFeatureInternal feature = WebViewFeatureInternal.WEB_VIEW_RENDERER_TERMINATE;
diff --git a/window/window-java/build.gradle b/window/window-java/build.gradle
index 1b5c379..c6531386 100644
--- a/window/window-java/build.gradle
+++ b/window/window-java/build.gradle
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("AndroidXPlugin")
diff --git a/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt b/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
index 688df0e..d87aed7 100644
--- a/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
+++ b/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
@@ -117,7 +117,7 @@
unitUnderTest.addWindowLayoutInfoListener(Runnable::run, testConsumer)
unitUnderTest.addWindowLayoutInfoListener(Runnable::run, mock())
unitUnderTest.removeWindowLayoutInfoListener(testConsumer)
- val accepted = channel.offer(info)
+ val accepted = channel.trySend(info).isSuccess
assertTrue(accepted)
testConsumer.assertEmpty()
diff --git a/window/window-rxjava2/build.gradle b/window/window-rxjava2/build.gradle
index 47307ed..ed28279 100644
--- a/window/window-rxjava2/build.gradle
+++ b/window/window-rxjava2/build.gradle
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-import androidx.build.Publish
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
+import androidx.build.Publish
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("AndroidXPlugin")
diff --git a/window/window-rxjava3/build.gradle b/window/window-rxjava3/build.gradle
index 84e67ad..4e6db4f 100644
--- a/window/window-rxjava3/build.gradle
+++ b/window/window-rxjava3/build.gradle
@@ -19,8 +19,6 @@
import androidx.build.LibraryVersions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import static androidx.build.dependencies.DependenciesKt.*
-
plugins {
id("AndroidXPlugin")
id("com.android.library")
diff --git a/window/window-samples/build.gradle b/window/window-samples/build.gradle
index 062d89b..c9960e0 100644
--- a/window/window-samples/build.gradle
+++ b/window/window-samples/build.gradle
@@ -18,8 +18,6 @@
import androidx.build.LibraryVersions
import androidx.build.Publish
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
plugins {
id("AndroidXPlugin")
id("com.android.application")
@@ -36,7 +34,7 @@
dependencies {
implementation("androidx.appcompat:appcompat:1.2.0")
implementation("androidx.core:core-ktx:1.3.2")
- api(CONSTRAINT_LAYOUT, {transitive = true})
+ api(libs.constraintLayout)
// TODO(b/152245564) Conflicting dependencies cause IDE errors.
implementation("androidx.lifecycle:lifecycle-viewmodel:2.2.0")
diff --git a/window/window-testing/api/current.txt b/window/window-testing/api/current.txt
index e0d15ce..b564bd4 100644
--- a/window/window-testing/api/current.txt
+++ b/window/window-testing/api/current.txt
@@ -1,5 +1,5 @@
// Signature format: 4.0
-package androidx.window.test {
+package androidx.window.testing {
public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
ctor public WindowLayoutInfoPublisherRule();
diff --git a/window/window-testing/api/public_plus_experimental_current.txt b/window/window-testing/api/public_plus_experimental_current.txt
index f00e796..729cf86 100644
--- a/window/window-testing/api/public_plus_experimental_current.txt
+++ b/window/window-testing/api/public_plus_experimental_current.txt
@@ -1,5 +1,5 @@
// Signature format: 4.0
-package androidx.window.test {
+package androidx.window.testing {
public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
ctor public WindowLayoutInfoPublisherRule();
diff --git a/window/window-testing/api/restricted_current.txt b/window/window-testing/api/restricted_current.txt
index e0d15ce..b564bd4 100644
--- a/window/window-testing/api/restricted_current.txt
+++ b/window/window-testing/api/restricted_current.txt
@@ -1,5 +1,5 @@
// Signature format: 4.0
-package androidx.window.test {
+package androidx.window.testing {
public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
ctor public WindowLayoutInfoPublisherRule();
diff --git a/window/window-testing/build.gradle b/window/window-testing/build.gradle
index 5a706af..64ad304 100644
--- a/window/window-testing/build.gradle
+++ b/window/window-testing/build.gradle
@@ -14,12 +14,10 @@
* limitations under the License.
*/
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-
-import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
import androidx.build.LibraryType
import androidx.build.LibraryVersions
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("AndroidXPlugin")
@@ -34,17 +32,17 @@
}
dependencies {
- api(KOTLIN_STDLIB)
+ api(libs.kotlinStdlib)
api(project(":window:window"))
- api(JUNIT)
+ api(libs.junit)
implementation("androidx.core:core:1.3.2")
- androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
- androidTestImplementation(ANDROIDX_TEST_RUNNER)
- androidTestImplementation(ANDROIDX_TEST_RULES)
- androidTestImplementation(KOTLIN_COROUTINES_TEST)
- androidTestImplementation(MULTIDEX)
- androidTestImplementation(TRUTH)
+ androidTestImplementation(libs.testExtJunit)
+ androidTestImplementation(libs.testRunner)
+ androidTestImplementation(libs.testRules)
+ androidTestImplementation(libs.kotlinCoroutinesTest)
+ androidTestImplementation(libs.multidex)
+ androidTestImplementation(libs.truth)
}
androidx {
diff --git a/window/window-testing/src/androidTest/AndroidManifest.xml b/window/window-testing/src/androidTest/AndroidManifest.xml
index 7d587da..5d5fa1c 100644
--- a/window/window-testing/src/androidTest/AndroidManifest.xml
+++ b/window/window-testing/src/androidTest/AndroidManifest.xml
@@ -15,7 +15,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.window.test">
+ package="androidx.window.testing">
<application>
<activity android:name="TestActivity"/>
</application>
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt b/window/window-testing/src/androidTest/java/androidx/window/testing/TestActivity.kt
similarity index 95%
rename from window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
rename to window/window-testing/src/androidTest/java/androidx/window/testing/TestActivity.kt
index 3d934fd..510278d 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
+++ b/window/window-testing/src/androidTest/java/androidx/window/testing/TestActivity.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import android.app.Activity
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt b/window/window-testing/src/androidTest/java/androidx/window/testing/WindowLayoutInfoPublisherRuleTest.kt
similarity index 98%
rename from window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt
rename to window/window-testing/src/androidTest/java/androidx/window/testing/WindowLayoutInfoPublisherRuleTest.kt
index a93682b..51dac78 100644
--- a/window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt
+++ b/window/window-testing/src/androidTest/java/androidx/window/testing/WindowLayoutInfoPublisherRuleTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import android.graphics.Rect
import androidx.test.ext.junit.rules.ActivityScenarioRule
diff --git a/window/window-testing/src/main/AndroidManifest.xml b/window/window-testing/src/main/AndroidManifest.xml
index 4bd698f..9582ba4 100644
--- a/window/window-testing/src/main/AndroidManifest.xml
+++ b/window/window-testing/src/main/AndroidManifest.xml
@@ -15,5 +15,5 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.window.test">
+ package="androidx.window.testing">
</manifest>
\ No newline at end of file
diff --git a/window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt b/window/window-testing/src/main/java/androidx/window/testing/PublishLayoutInfoRepo.kt
similarity index 96%
rename from window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt
rename to window/window-testing/src/main/java/androidx/window/testing/PublishLayoutInfoRepo.kt
index b3591df..476f250 100644
--- a/window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/PublishLayoutInfoRepo.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import androidx.window.WindowInfoRepo
import androidx.window.WindowLayoutInfo
diff --git a/window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt b/window/window-testing/src/main/java/androidx/window/testing/PublishWindowInfoRepoDecorator.kt
similarity index 96%
rename from window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt
rename to window/window-testing/src/main/java/androidx/window/testing/PublishWindowInfoRepoDecorator.kt
index 7cf34ba..c26b204 100644
--- a/window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/PublishWindowInfoRepoDecorator.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import androidx.window.WindowInfoRepo
import androidx.window.WindowInfoRepoDecorator
diff --git a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt b/window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisher.kt
similarity index 97%
rename from window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt
rename to window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisher.kt
index 2261e68..ac1766f 100644
--- a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisher.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import androidx.window.WindowInfoRepo
import androidx.window.WindowLayoutInfo
diff --git a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt b/window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisherRule.kt
similarity index 98%
rename from window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt
rename to window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisherRule.kt
index f9e92fc..3194bc2 100644
--- a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/WindowLayoutInfoPublisherRule.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package androidx.window.test
+package androidx.window.testing
import androidx.window.WindowInfoRepo
import androidx.window.WindowLayoutInfo
diff --git a/window/window/src/androidTest/AndroidManifest.xml b/window/window/src/androidTest/AndroidManifest.xml
index d5eba48..5efaf0f7 100644
--- a/window/window/src/androidTest/AndroidManifest.xml
+++ b/window/window/src/androidTest/AndroidManifest.xml
@@ -15,7 +15,7 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="androidx.window.test">
+ package="androidx.window.testing">
<application>
<uses-library android:name="androidx.window.extension" android:required="false" />
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
index f3f0105..206f2c0 100644
--- a/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
@@ -100,7 +100,7 @@
*/
override val windowLayoutInfo: Flow<WindowLayoutInfo>
get() = callbackFlow {
- val callback = Consumer<WindowLayoutInfo> { info -> offer(info) }
+ val callback = Consumer<WindowLayoutInfo> { info -> trySend(info) }
windowBackend.registerLayoutChangeCallback(activity, Runnable::run, callback)
awaitClose { windowBackend.unregisterLayoutChangeCallback(callback) }
}.buffer(capacity = UNLIMITED)
diff --git a/work/integration-tests/testapp/build.gradle b/work/integration-tests/testapp/build.gradle
index eb0bdf7..9ee4ee9 100644
--- a/work/integration-tests/testapp/build.gradle
+++ b/work/integration-tests/testapp/build.gradle
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-import static androidx.build.dependencies.DependenciesKt.CONSTRAINT_LAYOUT
-
buildscript {
// TODO: Remove this when this test app no longer depends on 1.0.0 of vectordrawable-animated.
// vectordrawable and vectordrawable-animated were accidentally using the same package name
@@ -61,7 +59,7 @@
implementation("androidx.room:room-runtime:2.2.5")
}
- implementation(CONSTRAINT_LAYOUT, { transitive = true })
+ implementation(libs.constraintLayout)
implementation("androidx.lifecycle:lifecycle-service:2.2.0")
implementation(project(":work:work-runtime-ktx"))
implementation(project(":work:work-multiprocess"))
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt
index 5f26e92..3774674 100644
--- a/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt
@@ -21,6 +21,7 @@
import androidx.concurrent.futures.ResolvableFuture
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@@ -33,6 +34,7 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
class ListenableFutureTest {
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testFutureWithResult() {
val future: ResolvableFuture<Int> = ResolvableFuture.create()
@@ -45,6 +47,7 @@
job.join()
}
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testFutureWithException() {
val future: ResolvableFuture<Int> = ResolvableFuture.create()
@@ -62,6 +65,7 @@
job.join()
}
}
+ @OptIn(DelicateCoroutinesApi::class)
@Test
fun testFutureCancellation() {
val future: ResolvableFuture<Int> = ResolvableFuture.create()
diff --git a/work/workmanager-lint/build.gradle b/work/workmanager-lint/build.gradle
index 7329d99..a8faacc 100644
--- a/work/workmanager-lint/build.gradle
+++ b/work/workmanager-lint/build.gradle
@@ -17,15 +17,13 @@
import androidx.build.LibraryGroups
import androidx.build.LibraryType
-import static androidx.build.dependencies.DependenciesKt.LINT_API_MIN
-
plugins {
id("AndroidXPlugin")
id("kotlin")
}
dependencies {
- compileOnly(LINT_API_MIN)
+ compileOnly(libs.androidLintMinApi)
compileOnly(libs.kotlinStdlib)
testImplementation(libs.kotlinStdlib)
diff --git a/work/workmanager-multiprocess/build.gradle b/work/workmanager-multiprocess/build.gradle
index c4ae2b1..fbd4ecad 100644
--- a/work/workmanager-multiprocess/build.gradle
+++ b/work/workmanager-multiprocess/build.gradle
@@ -34,6 +34,7 @@
api(libs.kotlinStdlib)
api(libs.kotlinCoroutinesAndroid)
api(libs.guavaListenableFuture)
+ implementation("androidx.core:core:1.1.0")
implementation("androidx.room:room-runtime:2.2.5")
androidTestImplementation(libs.kotlinStdlib)
androidTestImplementation(libs.testExtJunit)
diff --git a/work/workmanager-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt b/work/workmanager-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
index f74b7cf..547e261 100644
--- a/work/workmanager-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
+++ b/work/workmanager-multiprocess/src/androidTest/java/androidx/work/multiprocess/RemoteWorkManagerClientTest.kt
@@ -37,6 +37,7 @@
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
@@ -110,7 +111,7 @@
val remoteDispatcher =
mock(RemoteDispatcher::class.java) as RemoteDispatcher<IWorkManagerImpl>
val remoteStub = mock(IWorkManagerImpl::class.java)
- val callback = spy(RemoteCallback())
+ val callback = spy(RemoteWorkManagerClient.SessionRemoteCallback(mClient))
val message = "Something bad happened"
`when`(remoteDispatcher.execute(remoteStub, callback)).thenThrow(RuntimeException(message))
`when`(remoteStub.asBinder()).thenReturn(binder)
@@ -125,6 +126,7 @@
assertNotNull(exception)
verify(callback).onFailure(message)
verify(mClient, never()).cleanUp()
+ verify(callback, atLeastOnce()).onRequestCompleted()
}
@Test
@@ -138,7 +140,7 @@
val remoteDispatcher =
mock(RemoteDispatcher::class.java) as RemoteDispatcher<IWorkManagerImpl>
- val callback = spy(RemoteCallback())
+ val callback = spy(RemoteWorkManagerClient.SessionRemoteCallback(mClient))
val session = SettableFuture.create<IWorkManagerImpl>()
session.setException(RuntimeException("Something bad happened"))
var exception: Throwable? = null
@@ -150,6 +152,7 @@
assertNotNull(exception)
verify(callback).onFailure(anyString())
verify(mClient).cleanUp()
+ verify(callback, atLeastOnce()).onRequestCompleted()
}
@Test
@@ -165,7 +168,7 @@
callback.onSuccess(ByteArray(0))
}
val remoteStub = mock(IWorkManagerImpl::class.java)
- val callback = spy(RemoteCallback())
+ val callback = spy(RemoteWorkManagerClient.SessionRemoteCallback(mClient))
`when`(remoteStub.asBinder()).thenReturn(binder)
val session = SettableFuture.create<IWorkManagerImpl>()
session.set(remoteStub)
@@ -178,5 +181,6 @@
assertNull(exception)
verify(callback).onSuccess(any())
verify(mClient, never()).cleanUp()
+ verify(callback, atLeastOnce()).onRequestCompleted()
}
}
diff --git a/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteCallback.java b/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteCallback.java
index f274a86..c82e16c 100644
--- a/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteCallback.java
+++ b/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteCallback.java
@@ -69,6 +69,7 @@
public void onSuccess(@NonNull byte[] result) throws RemoteException {
mFuture.set(result);
unlinkToDeath();
+ onRequestCompleted();
}
@Override
@@ -76,9 +77,18 @@
onFailure(new RuntimeException(error));
}
+ /**
+ * This method can be used by {@link RemoteCallback} implementations to keep track of
+ * the lengths of the session after completion of a request.
+ */
+ protected void onRequestCompleted() {
+ // Does nothing.
+ }
+
private void onFailure(@NonNull Throwable throwable) {
mFuture.setException(throwable);
unlinkToDeath();
+ onRequestCompleted();
}
private void unlinkToDeath() {
diff --git a/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java b/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
index 8c2ec7f..ff89d80 100644
--- a/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
+++ b/work/workmanager-multiprocess/src/main/java/androidx/work/multiprocess/RemoteWorkManagerClient.java
@@ -27,14 +27,17 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.RemoteException;
-import androidx.annotation.Keep;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.arch.core.util.Function;
+import androidx.core.os.HandlerCompat;
import androidx.work.Data;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ExistingWorkPolicy;
@@ -69,26 +72,45 @@
*
* @hide
*/
+@SuppressLint("BanKeepAnnotation")
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class RemoteWorkManagerClient extends RemoteWorkManager {
+ /* The session timeout. */
+ private static final long SESSION_TIMEOUT_MILLIS = 60 * 1000;
+
+ // Synthetic access
static final String TAG = Logger.tagWithPrefix("RemoteWorkManagerClient");
+ // Synthetic access
+ Session mSession;
+
final Context mContext;
final WorkManagerImpl mWorkManager;
final Executor mExecutor;
final Object mLock;
- private Session mSession;
+ private volatile long mSessionIndex;
+ private final long mSessionTimeout;
+ private final Handler mHandler;
+ private final SessionTracker mSessionTracker;
- @SuppressLint("BanKeepAnnotation")
- @Keep
public RemoteWorkManagerClient(@NonNull Context context, @NonNull WorkManagerImpl workManager) {
+ this(context, workManager, SESSION_TIMEOUT_MILLIS);
+ }
+
+ public RemoteWorkManagerClient(
+ @NonNull Context context,
+ @NonNull WorkManagerImpl workManager,
+ long sessionTimeout) {
mContext = context.getApplicationContext();
mWorkManager = workManager;
mExecutor = mWorkManager.getWorkTaskExecutor().getBackgroundExecutor();
mLock = new Object();
mSession = null;
+ mSessionTracker = new SessionTracker(this);
+ mSessionTimeout = sessionTimeout;
+ mHandler = HandlerCompat.createAsync(Looper.getMainLooper());
}
@NonNull
@@ -266,7 +288,7 @@
@NonNull
public ListenableFuture<byte[]> execute(
@NonNull final RemoteDispatcher<IWorkManagerImpl> dispatcher) {
- return execute(getSession(), dispatcher, new RemoteCallback());
+ return execute(getSession(), dispatcher, new SessionRemoteCallback(this));
}
/**
@@ -278,6 +300,68 @@
return getSession(newIntent(mContext));
}
+ /**
+ * @return The application {@link Context}.
+ */
+ @NonNull
+ public Context getContext() {
+ return mContext;
+ }
+
+ /**
+ * @return The session timeout in milliseconds.
+ */
+ public long getSessionTimeout() {
+ return mSessionTimeout;
+ }
+
+ /**
+ * @return The current {@link Session} in use by {@link RemoteWorkManagerClient}.
+ */
+ @Nullable
+ public Session getCurrentSession() {
+ return mSession;
+ }
+
+ /**
+ * @return The {@link Handler} managing session timeouts.
+ */
+ @NonNull
+ public Handler getSessionHandler() {
+ return mHandler;
+ }
+
+ /**
+ * @return the {@link SessionTracker} instance.
+ */
+ @NonNull
+ public SessionTracker getSessionTracker() {
+ return mSessionTracker;
+ }
+
+ /**
+ * @return The {@link Object} session lock.
+ */
+ @NonNull
+ public Object getSessionLock() {
+ return mLock;
+ }
+
+ /**
+ * @return The background {@link Executor} used by {@link RemoteWorkManagerClient}.
+ */
+ @NonNull
+ public Executor getExecutor() {
+ return mExecutor;
+ }
+
+ /**
+ * @return The session index.
+ */
+ public long getSessionIndex() {
+ return mSessionIndex;
+ }
+
@NonNull
@VisibleForTesting
ListenableFuture<byte[]> execute(
@@ -316,6 +400,7 @@
@VisibleForTesting
ListenableFuture<IWorkManagerImpl> getSession(@NonNull Intent intent) {
synchronized (mLock) {
+ mSessionIndex += 1;
if (mSession == null) {
Logger.get().debug(TAG, "Creating a new session");
mSession = new Session(this);
@@ -328,6 +413,8 @@
unableToBind(mSession, throwable);
}
}
+ // Reset session tracker.
+ mHandler.removeCallbacks(mSessionTracker);
return mSession.mFuture;
}
}
@@ -390,6 +477,13 @@
@Override
public void onBindingDied(@NonNull ComponentName name) {
+ onBindingDied();
+ }
+
+ /**
+ * Clean-up client when a binding dies.
+ */
+ public void onBindingDied() {
Logger.get().debug(TAG, "Binding died");
mFuture.setException(new RuntimeException("Binding died"));
mClient.cleanUp();
@@ -402,4 +496,60 @@
new RuntimeException(String.format("Cannot bind to service %s", name)));
}
}
+
+ /**
+ * An extension of {@link RemoteCallback} that kills a {@link Session} after a timeout has
+ * elapsed.
+ */
+ public static class SessionRemoteCallback extends RemoteCallback {
+ private final RemoteWorkManagerClient mClient;
+
+ public SessionRemoteCallback(@NonNull RemoteWorkManagerClient client) {
+ mClient = client;
+ }
+
+ @Override
+ protected void onRequestCompleted() {
+ super.onRequestCompleted();
+ Handler handler = mClient.getSessionHandler();
+ SessionTracker tracker = mClient.getSessionTracker();
+ // Start tracking for session timeout.
+ // These callbacks are removed when the session timeout has expired or when getSession()
+ // is called.
+ handler.postDelayed(tracker, mClient.getSessionTimeout());
+ }
+ }
+
+ /**
+ * A {@link Runnable} that enforces a TTL for a {@link RemoteWorkManagerClient} session.
+ */
+ public static class SessionTracker implements Runnable {
+ private static final String TAG = Logger.tagWithPrefix("SessionHandler");
+ private final RemoteWorkManagerClient mClient;
+
+ public SessionTracker(@NonNull RemoteWorkManagerClient client) {
+ mClient = client;
+ }
+
+ @Override
+ public void run() {
+ final long preLockIndex = mClient.getSessionIndex();
+ synchronized (mClient.getSessionLock()) {
+ final long sessionIndex = mClient.getSessionIndex();
+ final Session currentSession = mClient.getCurrentSession();
+ // We check for a session index here. This is because if the index changes
+ // while we acquire a lock, that would mean that a new session request came through.
+ if (currentSession != null) {
+ if (preLockIndex == sessionIndex) {
+ Logger.get().debug(TAG, "Unbinding service");
+ mClient.getContext().unbindService(currentSession);
+ // Cleanup as well.
+ currentSession.onBindingDied();
+ } else {
+ Logger.get().debug(TAG, "Ignoring request to unbind.");
+ }
+ }
+ }
+ }
+ }
}
diff --git a/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobInfoConverter.java b/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobInfoConverter.java
index ac259b5..2541438 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobInfoConverter.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/background/systemjob/SystemJobInfoConverter.java
@@ -18,7 +18,6 @@
import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE;
-import android.annotation.SuppressLint;
import android.app.job.JobInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -139,7 +138,6 @@
* @param builder The instance of {@link JobInfo.Builder}.
* @param networkType The {@link NetworkType} instance.
*/
- @SuppressLint("UnsafeNewApiCall")
static void setRequiredNetwork(
@NonNull JobInfo.Builder builder,
@NonNull NetworkType networkType) {
diff --git a/work/workmanager/src/main/java/androidx/work/impl/model/WorkTypeConverters.java b/work/workmanager/src/main/java/androidx/work/impl/model/WorkTypeConverters.java
index 4e665ea..fb15ba8 100644
--- a/work/workmanager/src/main/java/androidx/work/impl/model/WorkTypeConverters.java
+++ b/work/workmanager/src/main/java/androidx/work/impl/model/WorkTypeConverters.java
@@ -195,7 +195,6 @@
* @return The associated int constant
*/
@TypeConverter
- @SuppressWarnings("NewApi")
public static int networkTypeToInt(NetworkType networkType) {
switch (networkType) {
case NOT_REQUIRED: