Merge "Import translations. DO NOT MERGE ANYWHERE" into androidx-main
diff --git a/ads/ads-identifier-provider/integration-tests/testapp/lint-baseline.xml b/ads/ads-identifier-provider/integration-tests/testapp/lint-baseline.xml
index 7683bde..0160194 100644
--- a/ads/ads-identifier-provider/integration-tests/testapp/lint-baseline.xml
+++ b/ads/ads-identifier-provider/integration-tests/testapp/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/annotation/annotation/lint-baseline.xml b/annotation/annotation/lint-baseline.xml
deleted file mode 100644
index a148b58..0000000
--- a/annotation/annotation/lint-baseline.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="SupportAnnotationUsage"
-        message="Do not use `@java.lang.annotation.Target` here; it will cause the annotation to not be allowed on **any** element types from Java"
-        errorLine1="@java.lang.annotation.Target("
-        errorLine2="                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/annotation/Keep.kt"/>
-    </issue>
-
-    <issue
-        id="SupportAnnotationUsage"
-        message="Do not use `@java.lang.annotation.Target` here; it will cause the annotation to not be allowed on **any** element types from Java"
-        errorLine1="@java.lang.annotation.Target("
-        errorLine2="                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/annotation/NonNull.kt"/>
-    </issue>
-
-    <issue
-        id="SupportAnnotationUsage"
-        message="Do not use `@java.lang.annotation.Target` here; it will cause the annotation to not be allowed on **any** element types from Java"
-        errorLine1="@java.lang.annotation.Target(METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE)"
-        errorLine2="                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/annotation/Nullable.kt"/>
-    </issue>
-
-    <issue
-        id="SupportAnnotationUsage"
-        message="Do not use `@java.lang.annotation.Target` here; it will cause the annotation to not be allowed on **any** element types from Java"
-        errorLine1="@java.lang.annotation.Target(TYPE, METHOD, CONSTRUCTOR, FIELD, PACKAGE)"
-        errorLine2="                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/annotation/RequiresApi.kt"/>
-    </issue>
-
-    <issue
-        id="SupportAnnotationUsage"
-        message="Do not use `@java.lang.annotation.Target` here; it will cause the annotation to not be allowed on **any** element types from Java"
-        errorLine1="@java.lang.annotation.Target("
-        errorLine2="                      ~~~~~~">
-        <location
-            file="src/main/java/androidx/annotation/RestrictTo.kt"/>
-    </issue>
-
-</issues>
diff --git a/appcompat/appcompat/src/main/res/values-ro/strings.xml b/appcompat/appcompat/src/main/res/values-ro/strings.xml
index 037261b..d5bde8f 100644
--- a/appcompat/appcompat/src/main/res/values-ro/strings.xml
+++ b/appcompat/appcompat/src/main/res/values-ro/strings.xml
@@ -17,8 +17,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="abc_action_mode_done" msgid="4692188335987374352">"Gata"</string>
-    <string name="abc_action_bar_home_description" msgid="5976598919945601918">"Navigați la ecranul de pornire"</string>
-    <string name="abc_action_bar_up_description" msgid="8388173803310557296">"Navigați în sus"</string>
+    <string name="abc_action_bar_home_description" msgid="5976598919945601918">"Navighează la ecranul de pornire"</string>
+    <string name="abc_action_bar_up_description" msgid="8388173803310557296">"Navighează în sus"</string>
     <string name="abc_action_menu_overflow_description" msgid="3937310113216875497">"Mai multe opțiuni"</string>
     <string name="abc_toolbar_collapse_description" msgid="1656852541809559762">"Restrânge"</string>
     <string name="abc_searchview_description_search" msgid="3417662926640357176">"Caută"</string>
diff --git a/appsearch/appsearch/lint-baseline.xml b/appsearch/appsearch/lint-baseline.xml
index 9eebc3d..fa994f2 100644
--- a/appsearch/appsearch/lint-baseline.xml
+++ b/appsearch/appsearch/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="SupportAnnotationUsage"
diff --git a/arch/core/core-testing/lint-baseline.xml b/arch/core/core-testing/lint-baseline.xml
index e4e77e4..0004e63 100644
--- a/arch/core/core-testing/lint-baseline.xml
+++ b/arch/core/core-testing/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/buildSrc/apply/applyAndroidXLayoutlibImplPlugin.gradle b/buildSrc/apply/applyAndroidXLayoutlibImplPlugin.gradle
new file mode 100644
index 0000000..c89f0f4
--- /dev/null
+++ b/buildSrc/apply/applyAndroidXLayoutlibImplPlugin.gradle
@@ -0,0 +1,9 @@
+import androidx.build.layoutlib.AndroidXLayoutlibImplPlugin
+
+buildscript {
+    dependencies {
+        classpath(project.files("${project.rootProject.ext["buildSrcOut"]}/private/build/libs/private.jar"))
+    }
+}
+
+apply plugin: AndroidXLayoutlibImplPlugin
diff --git a/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle b/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle
deleted file mode 100644
index ece0f79..0000000
--- a/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle
+++ /dev/null
@@ -1,9 +0,0 @@
-import androidx.build.paparazzi.AndroidXPaparazziImplPlugin
-
-buildscript {
-    dependencies {
-        classpath(project.files("${project.rootProject.ext["buildSrcOut"]}/private/build/libs/private.jar"))
-    }
-}
-
-apply plugin: AndroidXPaparazziImplPlugin
diff --git a/buildSrc/plugins/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziPlugin.kt b/buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXLayoutlibPlugin.kt
similarity index 86%
rename from buildSrc/plugins/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziPlugin.kt
rename to buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXLayoutlibPlugin.kt
index 98fc29f..f6cd2a5 100644
--- a/buildSrc/plugins/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziPlugin.kt
+++ b/buildSrc/plugins/src/main/kotlin/androidx/build/AndroidXLayoutlibPlugin.kt
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package androidx.build.paparazzi
+package androidx.build
 
-import androidx.build.getSupportRootFolder
 import org.gradle.api.Plugin
 import org.gradle.api.Project
 
@@ -25,12 +24,12 @@
  *
  * The actual implementation is in AndroidXPaparazziImplPlugin.
  */
-class AndroidXPaparazziPlugin : Plugin<Project> {
+class AndroidXLayoutlibPlugin : Plugin<Project> {
     override fun apply(project: Project) {
         val supportRoot = project.getSupportRootFolder()
         project.apply(
             mapOf(
-                "from" to "$supportRoot/buildSrc/apply/applyAndroidXPaparazziImplPlugin.gradle"
+                "from" to "$supportRoot/buildSrc/apply/applyAndroidXLayoutlibImplPlugin.gradle"
             )
         )
     }
diff --git a/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties b/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXLayoutlibPlugin.properties
similarity index 89%
rename from buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties
rename to buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXLayoutlibPlugin.properties
index b95a130..9d8b362 100644
--- a/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziPlugin.properties
+++ b/buildSrc/plugins/src/main/resources/META-INF/gradle-plugins/AndroidXLayoutlibPlugin.properties
@@ -14,4 +14,4 @@
 # limitations under the License.
 #
 
-implementation-class=androidx.build.paparazzi.AndroidXPaparazziPlugin
+implementation-class=androidx.build.AndroidXLayoutlibPlugin
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/layoutlib/AndroidXLayoutlibImplPlugin.kt
similarity index 96%
rename from buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt
rename to buildSrc/private/src/main/kotlin/androidx/build/layoutlib/AndroidXLayoutlibImplPlugin.kt
index 778810b..f4bff37 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/AndroidXPaparazziImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/layoutlib/AndroidXLayoutlibImplPlugin.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.build.paparazzi
+package androidx.build.layoutlib
 
 import androidx.build.OperatingSystem
 import androidx.build.SupportConfig.COMPILE_SDK_VERSION
@@ -38,7 +38,7 @@
 /**
  * Configures screenshot testing using Paparazzi for AndroidX projects.
  */
-class AndroidXPaparazziImplPlugin : Plugin<Project> {
+class AndroidXLayoutlibImplPlugin : Plugin<Project> {
     override fun apply(project: Project) {
         val paparazziNative = project.createUnzippedPaparazziNativeDependency()
         project.afterEvaluate {
@@ -121,7 +121,7 @@
 
     private companion object {
         /** Package name of the test library, used to namespace system properties */
-        const val PACKAGE_NAME = "androidx.test.screenshot.paparazzi"
+        const val PACKAGE_NAME = "androidx.test.screenshot.layoutlib"
 
         /** Artifact type attribute for unzipped Paparazzi layoutlib unzipped artifacts */
         const val UNZIPPED_PAPARAZZI_NATIVE = "unzipped-paparazzi-native"
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt b/buildSrc/private/src/main/kotlin/androidx/build/layoutlib/UnzipPaparazziNativeTransform.kt
similarity index 98%
rename from buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt
rename to buildSrc/private/src/main/kotlin/androidx/build/layoutlib/UnzipPaparazziNativeTransform.kt
index 0af7ef7..5ba6ef5 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/paparazzi/UnzipPaparazziNativeTransform.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/layoutlib/UnzipPaparazziNativeTransform.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.build.paparazzi
+package androidx.build.layoutlib
 
 import java.util.zip.ZipInputStream
 import org.gradle.api.artifacts.transform.CacheableTransform
diff --git a/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties b/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties
index 0ea8b07..eacaf4a 100644
--- a/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties
+++ b/buildSrc/private/src/main/resources/META-INF/gradle-plugins/AndroidXPaparazziImplPlugin.properties
@@ -14,4 +14,4 @@
 # limitations under the License.
 #
 
-implementation-class=androidx.build.paparazzi.AndroidXPaparazziImplPlugin
+implementation-class=androidx.build.layoutlib.AndroidXLayoutlibImplPlugin
diff --git a/camera/camera-camera2-pipe-integration/lint-baseline.xml b/camera/camera-camera2-pipe-integration/lint-baseline.xml
index acec75e..76fc250 100644
--- a/camera/camera-camera2-pipe-integration/lint-baseline.xml
+++ b/camera/camera-camera2-pipe-integration/lint-baseline.xml
@@ -4,8 +4,8 @@
     <issue
         id="SupportAnnotationUsage"
         message="Did you mean `@get:VisibleForTesting`? Without `get:` this annotates the constructor parameter itself instead of the associated getter."
-        errorLine1="    @VisibleForTesting"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~">
+        errorLine1="    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal val requestListener:"
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/main/java/androidx/camera/camera2/pipe/integration/interop/Camera2CameraControl.kt"/>
     </issue>
diff --git a/car/app/app-samples/navigation/common/lint-baseline.xml b/car/app/app-samples/navigation/common/lint-baseline.xml
index f493425..bbc7529 100644
--- a/car/app/app-samples/navigation/common/lint-baseline.xml
+++ b/car/app/app-samples/navigation/common/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="ClassVerificationFailure"
diff --git a/car/app/app/api/public_plus_experimental_1.3.0-beta02.txt b/car/app/app/api/public_plus_experimental_1.3.0-beta02.txt
index 108129b..514019a 100644
--- a/car/app/app/api/public_plus_experimental_1.3.0-beta02.txt
+++ b/car/app/app/api/public_plus_experimental_1.3.0-beta02.txt
@@ -841,6 +841,44 @@
 
 }
 
+package androidx.car.app.messaging.model {
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class CarMessage {
+    method public androidx.car.app.model.CarText getBody();
+    method public long getReceivedTimeEpochMillis();
+    method public androidx.core.app.Person getSender();
+    method public boolean isRead();
+  }
+
+  public static final class CarMessage.Builder {
+    ctor public CarMessage.Builder();
+    method public androidx.car.app.messaging.model.CarMessage build();
+    method public androidx.car.app.messaging.model.CarMessage.Builder setBody(androidx.car.app.model.CarText);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setRead(boolean);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setReceivedTimeEpochMillis(long);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setSender(androidx.core.app.Person);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class ConversationItem implements androidx.car.app.model.Item {
+    method public androidx.car.app.model.CarIcon? getIcon();
+    method public String getId();
+    method public java.util.List<androidx.car.app.messaging.model.CarMessage!> getMessages();
+    method public androidx.car.app.model.CarText getTitle();
+    method public boolean isGroupConversation();
+  }
+
+  public static final class ConversationItem.Builder {
+    ctor public ConversationItem.Builder();
+    method public androidx.car.app.messaging.model.ConversationItem build();
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
+  }
+
+}
+
 package androidx.car.app.model {
 
   @androidx.car.app.annotations.CarProtocol public final class Action {
diff --git a/car/app/app/api/public_plus_experimental_current.txt b/car/app/app/api/public_plus_experimental_current.txt
index 108129b..514019a 100644
--- a/car/app/app/api/public_plus_experimental_current.txt
+++ b/car/app/app/api/public_plus_experimental_current.txt
@@ -841,6 +841,44 @@
 
 }
 
+package androidx.car.app.messaging.model {
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class CarMessage {
+    method public androidx.car.app.model.CarText getBody();
+    method public long getReceivedTimeEpochMillis();
+    method public androidx.core.app.Person getSender();
+    method public boolean isRead();
+  }
+
+  public static final class CarMessage.Builder {
+    ctor public CarMessage.Builder();
+    method public androidx.car.app.messaging.model.CarMessage build();
+    method public androidx.car.app.messaging.model.CarMessage.Builder setBody(androidx.car.app.model.CarText);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setRead(boolean);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setReceivedTimeEpochMillis(long);
+    method public androidx.car.app.messaging.model.CarMessage.Builder setSender(androidx.core.app.Person);
+  }
+
+  @androidx.car.app.annotations.CarProtocol @androidx.car.app.annotations.ExperimentalCarApi @androidx.car.app.annotations.RequiresCarApi(6) public class ConversationItem implements androidx.car.app.model.Item {
+    method public androidx.car.app.model.CarIcon? getIcon();
+    method public String getId();
+    method public java.util.List<androidx.car.app.messaging.model.CarMessage!> getMessages();
+    method public androidx.car.app.model.CarText getTitle();
+    method public boolean isGroupConversation();
+  }
+
+  public static final class ConversationItem.Builder {
+    ctor public ConversationItem.Builder();
+    method public androidx.car.app.messaging.model.ConversationItem build();
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setGroupConversation(boolean);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setIcon(androidx.car.app.model.CarIcon);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setId(String);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setMessages(java.util.List<androidx.car.app.messaging.model.CarMessage!>);
+    method public androidx.car.app.messaging.model.ConversationItem.Builder setTitle(androidx.car.app.model.CarText);
+  }
+
+}
+
 package androidx.car.app.model {
 
   @androidx.car.app.annotations.CarProtocol public final class Action {
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
new file mode 100644
index 0000000..f5bd59f
--- /dev/null
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/CarMessage.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2022 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.messaging.model;
+
+import static java.util.Objects.requireNonNull;
+
+import androidx.annotation.Keep;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.car.app.annotations.CarProtocol;
+import androidx.car.app.annotations.ExperimentalCarApi;
+import androidx.car.app.annotations.RequiresCarApi;
+import androidx.car.app.model.CarText;
+import androidx.core.app.Person;
+
+/** Represents a single message in a {@link ConversationItem} */
+@ExperimentalCarApi
+@CarProtocol
+@RequiresCarApi(6)
+public class CarMessage {
+    @Keep
+    @NonNull
+    private final Person mSender;
+
+    @Keep
+    @NonNull
+    private final CarText mBody;
+    @Keep
+    private final long mReceivedTimeEpochMillis;
+
+    @Keep
+    private final boolean mIsRead;
+
+    CarMessage(@NonNull Builder builder) {
+        this.mSender = requireNonNull(builder.mSender);
+        this.mBody = requireNonNull(builder.mBody);
+        this.mReceivedTimeEpochMillis = builder.mReceivedTimeEpochMillis;
+        this.mIsRead = builder.mIsRead;
+    }
+
+    /** Default constructor for serialization. */
+    private CarMessage() {
+        this.mSender = new Person.Builder().setName("").build();
+        this.mBody = new CarText.Builder("").build();
+        this.mReceivedTimeEpochMillis = 0;
+        this.mIsRead = false;
+    }
+
+
+    /** Returns a {@link Person} representing the message sender */
+    @NonNull public Person getSender() {
+        return mSender;
+    }
+
+    /** Returns a {@link CarText} representing the message body */
+    @NonNull
+    public CarText getBody() {
+        return mBody;
+    }
+
+    /** Returns a {@code long} representing the message timestamp (in epoch millis) */
+    public long getReceivedTimeEpochMillis() {
+        return mReceivedTimeEpochMillis;
+    }
+
+    /** Returns a {@link boolean}, indicating whether the message has been read */
+    public boolean isRead() {
+        return mIsRead;
+    }
+
+    /** A builder for {@link CarMessage} */
+    public static final class Builder {
+        @Nullable
+        Person mSender;
+        @Nullable
+        CarText mBody;
+        long mReceivedTimeEpochMillis;
+        boolean mIsRead;
+
+        /** Sets a {@link Person} representing the message sender */
+        public @NonNull Builder setSender(@NonNull Person sender) {
+            mSender = sender;
+            return this;
+        }
+
+        /** Sets a {@link CarText} representing the message body */
+        public @NonNull Builder setBody(@NonNull CarText body) {
+            mBody = body;
+            return this;
+        }
+
+        /** Sets a {@code long} representing the message timestamp (in epoch millis) */
+        public @NonNull Builder setReceivedTimeEpochMillis(long receivedTimeEpochMillis) {
+            mReceivedTimeEpochMillis = receivedTimeEpochMillis;
+            return this;
+        }
+
+        /** Sets a {@link boolean}, indicating whether the message has been read */
+        public @NonNull Builder setRead(boolean isRead) {
+            mIsRead = isRead;
+            return this;
+        }
+
+        /** Returns a new {@link CarMessage} instance defined by this builder */
+        public @NonNull CarMessage build() {
+            return new CarMessage(this);
+        }
+    }
+}
diff --git a/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
new file mode 100644
index 0000000..42eeeba
--- /dev/null
+++ b/car/app/app/src/main/java/androidx/car/app/messaging/model/ConversationItem.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2022 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.messaging.model;
+
+import static java.util.Objects.requireNonNull;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.car.app.annotations.CarProtocol;
+import androidx.car.app.annotations.ExperimentalCarApi;
+import androidx.car.app.annotations.RequiresCarApi;
+import androidx.car.app.model.CarIcon;
+import androidx.car.app.model.CarText;
+import androidx.car.app.model.Item;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Represents a conversation */
+@ExperimentalCarApi
+@CarProtocol
+@RequiresCarApi(6)
+public class ConversationItem implements Item {
+    @NonNull private final String mId;
+    @NonNull private final CarText mTitle;
+    @Nullable
+    private final CarIcon mIcon;
+    private final boolean mIsGroupConversation;
+    @NonNull private final List<CarMessage> mMessages;
+
+    ConversationItem(@NonNull Builder builder) {
+        this.mId = requireNonNull(builder.mId);
+        this.mTitle = requireNonNull(builder.mTitle);
+        this.mIcon = builder.mIcon;
+        this.mIsGroupConversation = builder.mIsGroupConversation;
+        this.mMessages = requireNonNull(builder.mMessages);
+    }
+
+    /** Default constructor for serialization. */
+    private ConversationItem() {
+        mId = "";
+        mTitle = new CarText.Builder("").build();
+        mIcon = null;
+        mIsGroupConversation = false;
+        mMessages = new ArrayList<>();
+    }
+
+    /**
+     * Returns a unique identifier for the conversation
+     *
+     * @see Builder#setId
+     */
+    public @NonNull String getId() {
+        return mId;
+    }
+
+    /** Returns the title of the conversation */
+    public @NonNull CarText getTitle() {
+        return mTitle;
+    }
+
+    /** Returns a {@link CarIcon} for the conversation, or {@code null} if not set */
+    public @Nullable CarIcon getIcon() {
+        return mIcon;
+    }
+
+    /**
+     * Returns whether this conversation involves 3+ participants (a "group" conversation)
+     *
+     * @see Builder#setGroupConversation(boolean)
+     */
+    public boolean isGroupConversation() {
+        return mIsGroupConversation;
+    }
+
+    /** Returns a list of messages for this {@link ConversationItem} */
+    public @NonNull List<CarMessage> getMessages() {
+        return mMessages;
+    }
+
+    /** A builder for {@link ConversationItem} */
+    public static final class Builder {
+        @Nullable
+        String mId;
+        @Nullable
+        CarText mTitle;
+        @Nullable
+        CarIcon mIcon;
+        boolean mIsGroupConversation;
+        @Nullable
+        List<CarMessage> mMessages;
+
+        /**
+         * Specifies a unique identifier for the conversation
+         *
+         * <p> IDs may be used for a variety of purposes, including...
+         * <ul>
+         *     <li> Distinguishing new {@link ConversationItem}s from updated
+         *     {@link ConversationItem}s in the UI, when data is refreshed
+         *     <li> Identifying {@link ConversationItem}s in "mark as read" / "reply" callbacks
+         * </ul>
+         */
+        public @NonNull Builder setId(@NonNull String id) {
+            mId = id;
+            return this;
+        }
+
+        /** Sets the title of the conversation */
+        public @NonNull Builder setTitle(@NonNull CarText title) {
+            mTitle = title;
+            return this;
+        }
+
+        /** Sets a {@link CarIcon} for the conversation */
+        public @NonNull Builder setIcon(@NonNull CarIcon icon) {
+            mIcon = icon;
+            return this;
+        }
+
+        /**
+         * Specifies whether this conversation involves 3+ participants (a "group" conversation)
+         *
+         * <p> If unspecified, conversations are assumed to have exactly two participants (a "1:1"
+         * conversation)
+         *
+         * <p> UX presentation may differ slightly between group and 1:1 conversations. As a
+         * historical example, message readout may include sender names for group conversations, but
+         * omit them for 1:1 conversations.
+         */
+        public @NonNull Builder setGroupConversation(boolean isGroupConversation) {
+            mIsGroupConversation = isGroupConversation;
+            return this;
+        }
+
+        /** Specifies a list of messages for the conversation */
+        public @NonNull Builder setMessages(@NonNull List<CarMessage> messages) {
+            mMessages = messages;
+            return this;
+        }
+
+        /** Returns a new {@link ConversationItem} instance defined by this builder */
+        public @NonNull ConversationItem build() {
+            return new ConversationItem(this);
+        }
+    }
+}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt
index 0c54c3c1..3c9694c 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/grid/LazyGridPrefetcherTest.kt
@@ -33,6 +33,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.LargeTest
 import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -60,7 +61,7 @@
 
     @Test
     fun notPrefetchingForwardInitially() {
-        composeList()
+        composeGrid()
 
         rule.onNodeWithTag("4")
             .assertDoesNotExist()
@@ -68,7 +69,7 @@
 
     @Test
     fun notPrefetchingBackwardInitially() {
-        composeList(firstItem = 4)
+        composeGrid(firstItem = 4)
 
         rule.onNodeWithTag("0")
             .assertDoesNotExist()
@@ -76,7 +77,7 @@
 
     @Test
     fun prefetchingForwardAfterSmallScroll() {
-        composeList()
+        composeGrid()
 
         rule.runOnIdle {
             runBlocking {
@@ -96,7 +97,7 @@
 
     @Test
     fun prefetchingBackwardAfterSmallScroll() {
-        composeList(firstItem = 4, itemOffset = 10)
+        composeGrid(firstItem = 4, itemOffset = 10)
 
         rule.runOnIdle {
             runBlocking {
@@ -116,7 +117,7 @@
 
     @Test
     fun prefetchingForwardAndBackward() {
-        composeList(firstItem = 2)
+        composeGrid(firstItem = 2)
 
         rule.runOnIdle {
             runBlocking {
@@ -152,7 +153,7 @@
 
     @Test
     fun prefetchingForwardTwice() {
-        composeList()
+        composeGrid()
 
         rule.runOnIdle {
             runBlocking {
@@ -181,7 +182,7 @@
 
     @Test
     fun prefetchingBackwardTwice() {
-        composeList(firstItem = 8)
+        composeGrid(firstItem = 8)
 
         rule.runOnIdle {
             runBlocking {
@@ -212,7 +213,7 @@
 
     @Test
     fun prefetchingForwardAndBackwardReverseLayout() {
-        composeList(firstItem = 2, reverseLayout = true)
+        composeGrid(firstItem = 2, reverseLayout = true)
 
         rule.runOnIdle {
             runBlocking {
@@ -253,7 +254,7 @@
     @Test
     fun prefetchingForwardAndBackwardWithContentPadding() {
         val halfItemSize = itemsSizeDp / 2f
-        composeList(
+        composeGrid(
             firstItem = 4,
             itemOffset = 5,
             contentPadding = PaddingValues(mainAxis = halfItemSize)
@@ -383,6 +384,40 @@
         }
     }
 
+    @Test
+    fun scrollingByListSizeCancelsPreviousPrefetch() {
+        composeGrid()
+
+        // now we have items 0-3 visible
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 2-5 are visible
+                // and schedule a prefetching for 6-7
+                state.scrollBy(itemsSizePx.toFloat())
+
+                // move viewport by screen size to items 8-11, so item 6 is just behind
+                // the first visible item
+                state.scrollBy(itemsSizePx * 3f)
+
+                // move scroll further to items 10-13, so item 6 is reused
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(13)
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // scroll again to ensure item 6 was dropped
+                state.scrollBy(itemsSizePx * 100f)
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(activeNodes).doesNotContain(6)
+        }
+    }
+
     private fun waitForPrefetch(index: Int) {
         rule.waitUntil {
             activeNodes.contains(index) && activeMeasuredNodes.contains(index)
@@ -392,7 +427,7 @@
     private val activeNodes = mutableSetOf<Int>()
     private val activeMeasuredNodes = mutableSetOf<Int>()
 
-    private fun composeList(
+    private fun composeGrid(
         firstItem: Int = 0,
         itemOffset: Int = 0,
         reverseLayout: Boolean = false,
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
index 59e1c8c..7e40b9b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/list/LazyListPrefetcherTest.kt
@@ -417,6 +417,40 @@
         }
     }
 
+    @Test
+    fun scrollingByListSizeCancelsPreviousPrefetch() {
+        composeList()
+
+        // now we have items 0-1 visible
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 1-2 are visible
+                // and schedule a prefetching for 3
+                state.scrollBy(itemsSizePx.toFloat())
+
+                // move viewport by screen size to items 4-5, so item 3 is just behind
+                // the first visible item
+                state.scrollBy(itemsSizePx * 3f)
+
+                // move scroll further to items 5-6, so item 3 is reused
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(7)
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // scroll again to ensure item 3 was dropped
+                state.scrollBy(itemsSizePx * 100f)
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(activeNodes).doesNotContain(3)
+        }
+    }
+
     private fun waitForPrefetch(index: Int) {
         rule.waitUntil {
             activeNodes.contains(index) && activeMeasuredNodes.contains(index)
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridPrefetcherTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridPrefetcherTest.kt
index 7747c93..ddaa888 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridPrefetcherTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridPrefetcherTest.kt
@@ -35,6 +35,7 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.Dp
 import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -371,44 +372,154 @@
         rule.runOnIdle { }
     }
 
-//    @Test
-//    fun snappingToOtherPositionWhilePrefetchIsScheduled() {
-//        val composedItems = mutableListOf<Int>()
-//        rule.setContent {
-//            state = rememberLazyGridState()
-//            LazyGrid(
-//                1,
-//                Modifier.mainAxisSize(itemsSizeDp * 1.5f),
-//                state,
-//            ) {
-//                items(1000) {
-//                    composedItems.add(it)
-//                    Spacer(Modifier.mainAxisSize(itemsSizeDp))
-//                }
-//            }
-//        }
-//
-//        rule.runOnIdle {
-//            // now we have items 0 and 1 visible
-//            runBlocking(AutoTestFrameClock()) {
-//                // this will move the viewport so items 1 and 2 are visible
-//                // and schedule a prefetching for 3
-//                state.scrollBy(itemsSizePx.toFloat())
-//                // then we move so that items 100 and 101 are visible.
-//                // this should cancel the prefetch for 3
-//                state.scrollToItem(100)
-//            }
-//        }
-//
-//        // wait a few frames to make sure prefetch happens if was scheduled
-//        rule.waitForIdle()
-//        rule.waitForIdle()
-//        rule.waitForIdle()
-//
-//        rule.runOnIdle {
-//            Truth.assertThat(composedItems).doesNotContain(3)
-//        }
-//    }
+    @Test
+    fun snappingToOtherPositionWhilePrefetchIsScheduled() {
+        val composedItems = mutableListOf<Int>()
+        rule.setContent {
+            state = rememberLazyStaggeredGridState()
+            LazyStaggeredGrid(
+                1,
+                Modifier.mainAxisSize(itemsSizeDp * 1.5f),
+                state,
+            ) {
+                items(1000) {
+                    composedItems.add(it)
+                    Spacer(Modifier.mainAxisSize(itemsSizeDp))
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            // now we have items 0 and 1 visible
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 1 and 2 are visible
+                // and schedule a prefetching for 3
+                state.scrollBy(itemsSizePx.toFloat())
+                // then we move so that items 100 and 101 are visible.
+                // this should cancel the prefetch for 3
+                state.scrollToItem(100)
+            }
+        }
+
+        // wait a few frames to make sure prefetch happens if was scheduled
+        rule.waitForIdle()
+        rule.waitForIdle()
+        rule.waitForIdle()
+
+        rule.runOnIdle {
+            assertThat(composedItems).doesNotContain(3)
+        }
+    }
+
+    @Test
+    fun scrollingByListSizeCancelsPreviousPrefetch() {
+        composeStaggeredGrid()
+
+        // now we have items 0-3 visible
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 2-5 are visible
+                // and schedule a prefetching for 6-7
+                state.scrollBy(itemsSizePx.toFloat())
+
+                // move viewport by screen size to items 8-11, so item 6 is just behind
+                // the first visible item
+                state.scrollBy(itemsSizePx * 3f)
+
+                // move scroll further to items 10-13, so item 6 is reused
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(13)
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // scroll again to ensure item 6 was dropped
+                state.scrollBy(itemsSizePx * 100f)
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(activeNodes).doesNotContain(6)
+        }
+    }
+
+    @Test
+    fun scrollingWithStaggeredItemsPrefetchesCorrectly() {
+        rule.setContent {
+            state = rememberLazyStaggeredGridState()
+            LazyStaggeredGrid(
+                2,
+                Modifier.mainAxisSize(itemsSizeDp * 5f),
+                state,
+            ) {
+                items(100) {
+                    DisposableEffect(it) {
+                        activeNodes.add(it)
+                        onDispose {
+                            activeNodes.remove(it)
+                            activeMeasuredNodes.remove(it)
+                        }
+                    }
+                    Spacer(
+                        Modifier
+                            .mainAxisSize(if (it == 0) itemsSizeDp else itemsSizeDp * 2)
+                            .border(Dp.Hairline, Color.Black)
+                            .testTag("$it")
+                            .layout { measurable, constraints ->
+                                val placeable = measurable.measure(constraints)
+                                activeMeasuredNodes.add(it)
+                                layout(placeable.width, placeable.height) {
+                                    placeable.place(0, 0)
+                                }
+                            }
+                    )
+                }
+            }
+        }
+
+        // ┌─┬─┐
+        // ├─┤1│
+        // │2├─┤
+        // ├─┤3│
+        // │4├─┤
+        // └─┴─┘
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so item 6 is visible
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(7)
+        waitForPrefetch(8)
+
+        // ┌─┬─┐
+        // │2├─┤
+        // ├─┤3│
+        // │4├─┤
+        // ├─┤5│
+        // └─┴─┘
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so item 7 is visible
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+            assertThat(activeNodes).contains(8)
+        }
+
+        // ┌─┬─┐
+        // ├─┤3│
+        // │4├─┤
+        // ├─┤5│
+        // │6├─┤
+        // └─┴─┘
+
+        waitForPrefetch(9)
+    }
 
     private fun waitForPrefetch(index: Int) {
         rule.waitUntil {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
index 0d23f23..ffb504c 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListState.kt
@@ -341,8 +341,12 @@
 
     private fun cancelPrefetchIfVisibleItemsChanged(info: LazyListLayoutInfo) {
         if (indexToPrefetch != -1 && info.visibleItemsInfo.isNotEmpty()) {
-            if (indexToPrefetch != info.visibleItemsInfo.first().index - 1 &&
-                indexToPrefetch != info.visibleItemsInfo.last().index + 1) {
+            val expectedPrefetchIndex = if (wasScrollingForward) {
+                info.visibleItemsInfo.last().index + 1
+            } else {
+                info.visibleItemsInfo.first().index - 1
+            }
+            if (indexToPrefetch != expectedPrefetchIndex) {
                 indexToPrefetch = -1
                 currentPrefetchHandle?.cancel()
                 currentPrefetchHandle = null
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridState.kt
index 3f8fdca..428f04e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/grid/LazyGridState.kt
@@ -359,13 +359,16 @@
 
     private fun cancelPrefetchIfVisibleItemsChanged(info: LazyGridLayoutInfo) {
         if (lineToPrefetch != -1 && info.visibleItemsInfo.isNotEmpty()) {
-            val firstLine = info.visibleItemsInfo.first().let {
-                if (isVertical) it.row else it.column
+            val expectedLineToPrefetch = if (wasScrollingForward) {
+                info.visibleItemsInfo.last().let {
+                    if (isVertical) it.row else it.column
+                } + 1
+            } else {
+                info.visibleItemsInfo.first().let {
+                    if (isVertical) it.row else it.column
+                } - 1
             }
-            val lastLine = info.visibleItemsInfo.last().let {
-                if (isVertical) it.row else it.column
-            }
-            if (lineToPrefetch != firstLine - 1 && lineToPrefetch != lastLine + 1) {
+            if (lineToPrefetch != expectedLineToPrefetch) {
                 lineToPrefetch = -1
                 currentLinePrefetchHandles.forEach { it.cancel() }
                 currentLinePrefetchHandles.clear()
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
index 90db4a2..d285d87 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/staggeredgrid/LazyStaggeredGridState.kt
@@ -29,7 +29,6 @@
 import androidx.compose.foundation.lazy.layout.animateScrollToItem
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.saveable.listSaver
 import androidx.compose.runtime.saveable.rememberSaveable
@@ -158,11 +157,10 @@
     internal var measurePassCount = 0
 
     /** states required for prefetching **/
-    private var wasScrollingForward = true
     internal var isVertical = false
     internal var laneWidthsPrefixSum: IntArray = IntArray(0)
     private var prefetchBaseIndex: Int = -1
-    private val currentItemPrefetchHandles = mutableVectorOf<PrefetchHandle>()
+    private val currentItemPrefetchHandles = mutableMapOf<Int, PrefetchHandle>()
 
     /** state required for implementing [animateScrollScope] **/
     internal var density: Density = Density(1f, 1f)
@@ -296,15 +294,6 @@
         if (info.visibleItemsInfo.isNotEmpty()) {
             val scrollingForward = delta < 0
 
-            if (wasScrollingForward != scrollingForward) {
-                // the scrolling direction has been changed which means the last prefetched item
-                // is not going to be reached anytime soon so it is safer to dispose it.
-                // if this item is already visible it is safe to call the method anyway
-                // as it will be a no-op
-                currentItemPrefetchHandles.forEach { it.cancel() }
-            }
-
-            wasScrollingForward = scrollingForward
             val prefetchIndex = if (scrollingForward) {
                 info.visibleItemsInfo.last().index
             } else {
@@ -316,8 +305,8 @@
                 return
             }
             prefetchBaseIndex = prefetchIndex
-            currentItemPrefetchHandles.clear()
 
+            val prefetchHandlesUsed = mutableSetOf<Int>()
             var targetIndex = prefetchIndex
             for (lane in laneWidthsPrefixSum.indices) {
                 val previousIndex = targetIndex
@@ -330,11 +319,16 @@
                 }
                 if (
                     targetIndex !in (0 until info.totalItemsCount) ||
-                        previousIndex == targetIndex
+                    previousIndex == targetIndex
                 ) {
                     return
                 }
 
+                prefetchHandlesUsed += targetIndex
+                if (targetIndex in currentItemPrefetchHandles) {
+                    continue
+                }
+
                 val crossAxisSize = laneWidthsPrefixSum[lane] -
                     if (lane == 0) 0 else laneWidthsPrefixSum[lane - 1]
 
@@ -344,13 +338,24 @@
                     Constraints.fixedHeight(crossAxisSize)
                 }
 
-                currentItemPrefetchHandles.add(
-                    prefetchState.schedulePrefetch(
-                        index = targetIndex,
-                        constraints = constraints
-                    )
+                currentItemPrefetchHandles[targetIndex] = prefetchState.schedulePrefetch(
+                    index = targetIndex,
+                    constraints = constraints
                 )
             }
+
+            clearLeftoverPrefetchHandles(prefetchHandlesUsed)
+        }
+    }
+
+    private fun clearLeftoverPrefetchHandles(prefetchHandlesUsed: Set<Int>) {
+        val iterator = currentItemPrefetchHandles.iterator()
+        while (iterator.hasNext()) {
+            val entry = iterator.next()
+            if (entry.key !in prefetchHandlesUsed) {
+                entry.value.cancel()
+                iterator.remove()
+            }
         }
     }
 
@@ -359,7 +364,7 @@
         if (prefetchBaseIndex != -1 && items.isNotEmpty()) {
             if (prefetchBaseIndex !in items.first().index..items.last().index) {
                 prefetchBaseIndex = -1
-                currentItemPrefetchHandles.forEach { it.cancel() }
+                currentItemPrefetchHandles.values.forEach { it.cancel() }
                 currentItemPrefetchHandles.clear()
             }
         }
diff --git a/compose/material3/material3/lint-baseline.xml b/compose/material3/material3/lint-baseline.xml
deleted file mode 100644
index 328b7622..0000000
--- a/compose/material3/material3/lint-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="IllegalExperimentalApiUsage"
-        message="`Experimental` and `RequiresOptIn` APIs may only be used within the same-version group where they were defined."
-        errorLine1="@OptIn(ExperimentalTextApi::class)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/material3/IncludeFontPaddingHelper.android.kt"/>
-    </issue>
-
-</issues>
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFontTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFontTest.kt
index 172ced7..716e856 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFontTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFontTest.kt
@@ -33,6 +33,12 @@
 
     val context = InstrumentationRegistry.getInstrumentation().context
 
+    @Test
+    fun variationSettings_arEmpty() {
+        val font = Font(DeviceFontFamilyName("any name")) as AndroidFont
+        assertThat(font.variationSettings.settings).isEmpty()
+    }
+
     @Test(expected = IllegalArgumentException::class)
     fun emptyFamilyName_throwsIllegalArgumentException() {
         Font(DeviceFontFamilyName(""))
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/HyphensTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/HyphensTest.kt
new file mode 100644
index 0000000..cb93b53
--- /dev/null
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/HyphensTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2022 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.text.style
+
+import androidx.compose.ui.text.ExperimentalTextApi
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+@OptIn(ExperimentalTextApi::class)
+class HyphensTest : TextLineBreaker() {
+    private val text = "Transformation"
+
+    @Test
+    fun check_hyphens_Auto() {
+        val brokenLines = breakTextIntoLines(
+            text = text,
+            hyphens = Hyphens.Auto,
+            maxWidth = 30
+        )
+        val expected = listOf(
+            "Tran",
+            "sfor",
+            "ma",
+            "tion"
+        )
+        assertThat(brokenLines).isEqualTo(expected)
+    }
+
+    @Test
+    fun check_hyphens_None() {
+        val brokenLines = breakTextIntoLines(
+            text = text,
+            hyphens = Hyphens.None,
+            maxWidth = 30
+        )
+        val expected = listOf(
+            "Tran",
+            "sfor",
+            "mati",
+            "on"
+        )
+        assertThat(brokenLines).isEqualTo(expected)
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
index e3610d6..69d112c 100644
--- a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/LineBreakTest.kt
@@ -16,33 +16,17 @@
 
 package androidx.compose.ui.text.style
 
-import androidx.compose.ui.text.AnnotatedString
 import androidx.compose.ui.text.ExperimentalTextApi
-import androidx.compose.ui.text.MultiParagraph
-import androidx.compose.ui.text.TextLayoutInput
-import androidx.compose.ui.text.TextLayoutResult
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.createFontFamilyResolver
-import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.Density
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.LayoutDirection
-import androidx.compose.ui.unit.constrain
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth.assertThat
-import kotlin.math.ceil
 import org.junit.Test
 import org.junit.runner.RunWith
 
 @OptIn(ExperimentalTextApi::class)
 @RunWith(AndroidJUnit4::class)
 @SmallTest
-class LineBreakTest {
-    private val defaultDensity = Density(1f)
-    private val context = InstrumentationRegistry.getInstrumentation().context
-    private val fontFamilyResolver = createFontFamilyResolver(context)
+class LineBreakTest : TextLineBreaker() {
     private val textToLineBreak = "This is an example text"
 
     @Test
@@ -263,63 +247,4 @@
 
         assertThat(brokenLines).isEqualTo(expectedBrokenLines)
     }
-
-    private fun constructTextLayoutResult(
-        text: String,
-        textStyle: TextStyle,
-        maxWidth: Int = Constraints.Infinity
-    ): TextLayoutResult {
-        val constraints = Constraints(maxWidth = maxWidth)
-
-        val input = TextLayoutInput(
-            text = AnnotatedString(text),
-            style = textStyle,
-            placeholders = listOf(),
-            maxLines = Int.MAX_VALUE,
-            softWrap = true,
-            overflow = TextOverflow.Visible,
-            density = defaultDensity,
-            layoutDirection = LayoutDirection.Ltr,
-            fontFamilyResolver = fontFamilyResolver,
-            constraints = constraints
-        )
-
-        val paragraph = MultiParagraph(
-            annotatedString = input.text,
-            style = input.style,
-            constraints = input.constraints,
-            density = input.density,
-            fontFamilyResolver = input.fontFamilyResolver
-        )
-
-        return TextLayoutResult(
-            layoutInput = input,
-            multiParagraph = paragraph,
-            size = constraints.constrain(
-                IntSize(
-                    ceil(paragraph.width).toInt(),
-                    ceil(paragraph.height).toInt()
-                )
-            )
-        )
-    }
-
-    private fun breakTextIntoLines(
-        text: String,
-        lineBreak: LineBreak,
-        maxWidth: Int
-    ): List<String> {
-        val layoutResult = constructTextLayoutResult(
-            text = text,
-            textStyle = TextStyle(lineBreak = lineBreak),
-            maxWidth = maxWidth
-        )
-
-        return (0 until layoutResult.lineCount).map { lineIndex ->
-            text.substring(
-                layoutResult.getLineStart(lineIndex),
-                layoutResult.getLineEnd(lineIndex)
-            )
-        }
-    }
 }
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt
new file mode 100644
index 0000000..6f3ff165
--- /dev/null
+++ b/compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/style/TextLineBreaker.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2022 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.text.style
+
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.MultiParagraph
+import androidx.compose.ui.text.TextLayoutInput
+import androidx.compose.ui.text.TextLayoutResult
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.createFontFamilyResolver
+import androidx.compose.ui.unit.Constraints
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.constrain
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.math.ceil
+
+@OptIn(ExperimentalTextApi::class)
+open class TextLineBreaker {
+    private val defaultDensity = Density(1f)
+    private val context = InstrumentationRegistry.getInstrumentation().context
+    private val fontFamilyResolver = createFontFamilyResolver(context)
+    private val defaultHyphens = Hyphens.None
+    private val defaultLineBreak = LineBreak.Simple
+
+    private fun constructTextLayoutResult(
+        text: String,
+        textStyle: TextStyle,
+        maxWidth: Int = Constraints.Infinity
+    ): TextLayoutResult {
+        val constraints = Constraints(maxWidth = maxWidth)
+
+        val input = TextLayoutInput(
+            text = AnnotatedString(text),
+            style = textStyle,
+            placeholders = listOf(),
+            maxLines = Int.MAX_VALUE,
+            softWrap = true,
+            overflow = TextOverflow.Visible,
+            density = defaultDensity,
+            layoutDirection = LayoutDirection.Ltr,
+            fontFamilyResolver = fontFamilyResolver,
+            constraints = constraints
+        )
+
+        val paragraph = MultiParagraph(
+            annotatedString = input.text,
+            style = input.style,
+            constraints = input.constraints,
+            density = input.density,
+            fontFamilyResolver = input.fontFamilyResolver
+        )
+
+        return TextLayoutResult(
+            layoutInput = input,
+            multiParagraph = paragraph,
+            size = constraints.constrain(
+                IntSize(
+                    ceil(paragraph.width).toInt(),
+                    ceil(paragraph.height).toInt()
+                )
+            )
+        )
+    }
+
+    fun breakTextIntoLines(
+        text: String,
+        hyphens: Hyphens = defaultHyphens,
+        lineBreak: LineBreak = defaultLineBreak,
+        maxWidth: Int
+    ): List<String> {
+        val layoutResult = constructTextLayoutResult(
+            text = text,
+            textStyle = TextStyle(hyphens = hyphens, lineBreak = lineBreak),
+            maxWidth = maxWidth
+        )
+
+        return (0 until layoutResult.lineCount).map { lineIndex ->
+            text.substring(
+                layoutResult.getLineStart(lineIndex),
+                layoutResult.getLineEnd(lineIndex)
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFont.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFont.kt
index f80d7e2..b9459b5 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFont.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/DeviceFontFamilyNameFont.kt
@@ -41,9 +41,15 @@
  * This Font can not describe the system-installed [Typeface.DEFAULT]. All other system-installed
  * fonts are allowed.
  *
+ * Note: When setting [variationSettings] any unset axis may be reset to the font default, ignoring
+ * any axis restrictions in `fonts.xml` or `font_customizations.xml`. This may have surprising
+ * side-effects when named fonts differ only by the default axis settings in XML. When setting
+ * variation axis for device fonts, ensure you set all possible settings for the font.
+ *
  * @param familyName Android system-installed font family name
  * @param weight weight to load
  * @param style style to load
+ * @param variationSettings font variation settings, unset by default to load default VF from system
  *
  * @throws IllegalArgumentException if familyName is empty
  */
@@ -52,7 +58,7 @@
     familyName: DeviceFontFamilyName,
     weight: FontWeight = FontWeight.Normal,
     style: FontStyle = FontStyle.Normal,
-    variationSettings: FontVariation.Settings = FontVariation.Settings(weight, style)
+    variationSettings: FontVariation.Settings = FontVariation.Settings()
 ): Font {
     return DeviceFontFamilyNameFont(familyName, weight, style, variationSettings)
 }
@@ -60,6 +66,8 @@
 /**
  * An Android system installed font family name as used by [Typeface.create].
  *
+ * See `/system/etc/fonts.xml` and `/product/etc/fonts_customization.xml` on a device.
+ *
  * @see Typeface
  * @param name System fontFamilyName as passed to [Typeface.create]
  * @throws IllegalArgumentException if name is empty
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/recyclerview/RecyclerViewInteropDemoFragment.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/recyclerview/RecyclerViewInteropDemoFragment.kt
index 08b683d..507e519 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/recyclerview/RecyclerViewInteropDemoFragment.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/recyclerview/RecyclerViewInteropDemoFragment.kt
@@ -28,12 +28,12 @@
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.foundation.lazy.LazyRow
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.key
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
@@ -66,6 +66,8 @@
     }
 
     inner class MainAdapter : RecyclerView.Adapter<MainAdapter.ViewHolder>() {
+        private val rowStates = mutableMapOf<Int, LazyListState>()
+
         inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
             val itemRow: ComposeItemRow = itemView.findViewById(R.id.itemRow)
         }
@@ -76,7 +78,9 @@
         }
 
         override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+            val state = rowStates.getOrPut(position) { LazyListState() }
             holder.itemRow.index = position
+            holder.itemRow.rowState = state
         }
 
         override fun getItemCount(): Int = 50
@@ -84,7 +88,7 @@
 }
 
 @Composable
-fun ItemRow(index: Int) {
+fun ItemRow(index: Int, state: LazyListState) {
     DisposableEffect(Unit) {
         println("ItemRow $index composed")
 
@@ -92,12 +96,14 @@
     }
     Column(Modifier.fillMaxWidth()) {
         Text("Row #${index + 1}", Modifier.padding(horizontal = 8.dp))
-        LazyRow {
+
+        LazyRow(state = state) {
             items(25) { colIdx ->
                 Column(
                     Modifier
                         .padding(8.dp)
-                        .size(96.dp, 144.dp)) {
+                        .size(96.dp, 144.dp)
+                ) {
                     Box(
                         Modifier
                             .fillMaxWidth()
@@ -117,11 +123,10 @@
     defStyle: Int = 0
 ) : AbstractComposeView(context, attrs, defStyle) {
     var index by mutableStateOf(0)
+    var rowState: LazyListState? by mutableStateOf(null)
 
     @Composable
     override fun Content() {
-        key(index) {
-            ItemRow(index)
-        }
+        ItemRow(index, rowState!!)
     }
 }
diff --git a/contentpager/contentpager/lint-baseline.xml b/contentpager/contentpager/lint-baseline.xml
index 87af2b4..de601d0 100644
--- a/contentpager/contentpager/lint-baseline.xml
+++ b/contentpager/contentpager/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="NewApi"
diff --git a/core/core-appdigest/lint-baseline.xml b/core/core-appdigest/lint-baseline.xml
index f90928c..0907387 100644
--- a/core/core-appdigest/lint-baseline.xml
+++ b/core/core-appdigest/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="NewApi"
diff --git a/core/core/lint-baseline.xml b/core/core/lint-baseline.xml
index c7ef3b1..7762518 100644
--- a/core/core/lint-baseline.xml
+++ b/core/core/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="NewApi"
@@ -697,33 +697,6 @@
     <issue
         id="WrongConstant"
         message="Must be one of: Action.SEMANTIC_ACTION_NONE, Action.SEMANTIC_ACTION_REPLY, Action.SEMANTIC_ACTION_MARK_AS_READ, Action.SEMANTIC_ACTION_MARK_AS_UNREAD, Action.SEMANTIC_ACTION_DELETE, Action.SEMANTIC_ACTION_ARCHIVE, Action.SEMANTIC_ACTION_MUTE, Action.SEMANTIC_ACTION_UNMUTE, Action.SEMANTIC_ACTION_THUMBS_UP, Action.SEMANTIC_ACTION_THUMBS_DOWN, Action.SEMANTIC_ACTION_CALL"
-        errorLine1="                    builder.setSemanticAction(action.getSemanticAction());"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="                            ? remoteInput.getEditChoicesBeforeSending()"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: RemoteInput.EDIT_CHOICES_BEFORE_SENDING_AUTO, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_DISABLED, RemoteInput.EDIT_CHOICES_BEFORE_SENDING_ENABLED"
-        errorLine1="                                ? src.getEditChoicesBeforeSending()"
-        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="WrongConstant"
-        message="Must be one of: Action.SEMANTIC_ACTION_NONE, Action.SEMANTIC_ACTION_REPLY, Action.SEMANTIC_ACTION_MARK_AS_READ, Action.SEMANTIC_ACTION_MARK_AS_UNREAD, Action.SEMANTIC_ACTION_DELETE, Action.SEMANTIC_ACTION_ARCHIVE, Action.SEMANTIC_ACTION_MUTE, Action.SEMANTIC_ACTION_UNMUTE, Action.SEMANTIC_ACTION_THUMBS_UP, Action.SEMANTIC_ACTION_THUMBS_DOWN, Action.SEMANTIC_ACTION_CALL"
         errorLine1="                actionBuilder.setSemanticAction(action.getSemanticAction());"
         errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
@@ -2181,927 +2154,9 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        this(channel.getId(), channel.getImportance());"
-        errorLine2="                     ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        this(channel.getId(), channel.getImportance());"
-        errorLine2="                                      ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mName = channel.getName();"
-        errorLine2="                        ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mDescription = channel.getDescription();"
-        errorLine2="                               ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mGroupId = channel.getGroup();"
-        errorLine2="                           ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mShowBadge = channel.canShowBadge();"
-        errorLine2="                             ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mSound = channel.getSound();"
-        errorLine2="                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mAudioAttributes = channel.getAudioAttributes();"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mLights = channel.shouldShowLights();"
-        errorLine2="                          ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mLightColor = channel.getLightColor();"
-        errorLine2="                              ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mVibrationEnabled = channel.shouldVibrate();"
-        errorLine2="                                    ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mVibrationPattern = channel.getVibrationPattern();"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mParentId = channel.getParentChannelId();"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mConversationId = channel.getConversationId();"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mBypassDnd = channel.canBypassDnd();"
-        errorLine2="                             ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mLockscreenVisibility = channel.getLockscreenVisibility();"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mCanBubble = channel.canBubble();"
-        errorLine2="                                 ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mImportantConversation = channel.isImportantConversation();"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        NotificationChannel channel = new NotificationChannel(mId, mName, mImportance);"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setDescription(mDescription);"
-        errorLine2="                ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setGroup(mGroupId);"
-        errorLine2="                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setShowBadge(mShowBadge);"
-        errorLine2="                ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setSound(mSound, mAudioAttributes);"
-        errorLine2="                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.enableLights(mLights);"
-        errorLine2="                ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setLightColor(mLightColor);"
-        errorLine2="                ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.setVibrationPattern(mVibrationPattern);"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        channel.enableVibration(mVibrationEnabled);"
-        errorLine2="                ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationChannelCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            channel.setConversationId(mParentId, mConversationId);"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        this(group.getId());"
-        errorLine2="                   ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        mName = group.getName();"
-        errorLine2="                      ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mDescription = group.getDescription();"
-        errorLine2="                                 ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mBlocked = group.isBlocked();"
-        errorLine2="                             ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mChannels = getChannelsCompat(group.getChannels());"
-        errorLine2="                                                ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            if (mId.equals(channel.getGroup())) {"
-        errorLine2="                                   ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        NotificationChannelGroup group = new NotificationChannelGroup(mId, mName);"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationChannelGroupCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            group.setDescription(mDescription);"
-        errorLine2="                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationChannelGroupCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                this.mSmallIcon = notification.getSmallIcon();"
-        errorLine2="                                               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                mNotification.audioAttributes = new AudioAttributes.Builder()"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)"
-        errorLine2="                         ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setUsage(AudioAttributes.USAGE_NOTIFICATION)"
-        errorLine2="                         ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .build();"
-        errorLine2="                         ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                mNotification.audioAttributes = new AudioAttributes.Builder()"
-        errorLine2="                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)"
-        errorLine2="                         ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .setLegacyStreamType(streamType)"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 21; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .build();"
-        errorLine2="                         ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                return Notification.Builder.recoverBuilder(mContext, notification)"
-        errorLine2="                                            ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .createContentView();"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                return Notification.Builder.recoverBuilder(mContext, notification)"
-        errorLine2="                                            ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        .createBigContentView();"
-        errorLine2="                         ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        Notification.Builder.recoverBuilder(mContext, notification);"
-        errorLine2="                                             ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                return platformBuilder.createHeadsUpContentView();"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.Style is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    contentView.setTextViewTextSize(R.id.text, TypedValue.COMPLEX_UNIT_PX,"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.Style is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                contentView.setViewPadding(R.id.line1, 0, 0, 0, 0);"
-        errorLine2="                            ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Style is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        contentView.setChronometerCountDown(R.id.chronometer,"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.Style is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                outerView.setViewPadding(R.id.notification_main_column_container,"
-        errorLine2="                          ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigPictureStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        new Notification.BigPictureStyle(builder.getBuilder())"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigPictureStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .setBigContentTitle(mBigContentTitle);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigPictureStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        style = style.bigPicture(mPictureIcon.getBitmap());"
-        errorLine2="                                      ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigTextStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        new Notification.BigTextStyle(builder.getBuilder())"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigTextStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .setBigContentTitle(mBigContentTitle)"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigTextStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .bigText(mBigText);"
-        errorLine2="                                 ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.BigTextStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    style.setSummaryText(mSummaryText);"
-        errorLine2="                          ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkStyle = new Notification.MessagingStyle(mUser.toAndroidPerson());"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkStyle = new Notification.MessagingStyle(mUser.getName());"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkStyle.addMessage(message.toAndroidMessage());"
-        errorLine2="                                   ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        frameworkStyle.addHistoricMessage(historicMessage.toAndroidMessage());"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkStyle.setConversationTitle(mConversationTitle);"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkStyle.setGroupConversation(mIsGroupConversation);"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                frameworkStyle.setBuilder(builder.getBuilder());"
-        errorLine2="                               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    new Notification.BigTextStyle(builder.getBuilder())"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                            .setBigContentTitle(null)"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                            .bigText(completeMessage);"
-        errorLine2="                             ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle.Message is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkMessage = new Notification.MessagingStyle.Message("
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle.Message is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkMessage = new Notification.MessagingStyle.Message("
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.MessagingStyle.Message is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    frameworkMessage.setData(getDataMimeType(), getDataUri());"
-        errorLine2="                                     ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.InboxStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        new Notification.InboxStyle(builder.getBuilder())"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.InboxStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .setBigContentTitle(mBigContentTitle);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.InboxStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    style.setSummaryText(mSummaryText);"
-        errorLine2="                          ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.InboxStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    style.addLine(text);"
-        errorLine2="                          ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 16; however, the containing class androidx.core.app.NotificationCompat.DecoratedCustomViewStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                builder.getBuilder().setStyle(new Notification.DecoratedCustomViewStyle());"
-        errorLine2="                                     ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.DecoratedCustomViewStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                builder.getBuilder().setStyle(new Notification.DecoratedCustomViewStyle());"
-        errorLine2="                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 15; however, the containing class androidx.core.app.NotificationCompat.DecoratedCustomViewStyle is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                button.setContentDescription(R.id.action_container, action.title);"
-        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                if (Build.VERSION.SDK_INT >= 23 &amp;&amp; action.getIcon() != null) {"
-        errorLine2="                                                          ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    IconCompat iconCompat = IconCompat.createFromIcon(action.getIcon());"
-        errorLine2="                                                                             ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    android.app.RemoteInput[] remoteInputs = action.getRemoteInputs();"
-        errorLine2="                                                                    ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    builder.mAllowGeneratedReplies = action.getAllowGeneratedReplies();"
-        errorLine2="                                                            ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    builder.setSemanticAction(action.getSemanticAction());"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    builder.setContextual(action.isContextual());"
-        errorLine2="                                                 ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 31; however, the containing class androidx.core.app.NotificationCompat.Action.Builder is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    builder.setAuthenticationRequired(action.isAuthenticationRequired());"
-        errorLine2="                                                             ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                actionBuilder = new Notification.Action.Builder("
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                actionBuilder = new Notification.Action.Builder("
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                actionBuilder.setAllowGeneratedReplies(actionCompat.getAllowGeneratedReplies());"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 31; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                actionBuilder.setAuthenticationRequired(actionCompat.isAuthenticationRequired());"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            actionBuilder.addExtras(actionExtras);"
-        errorLine2="                          ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    actionBuilder.addRemoteInput(remoteInput);"
-        errorLine2="                                  ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.WearableExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return actionBuilder.build();"
-        errorLine2="                                 ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    ? new RemoteInput(remoteInput.getResultKey(),"
-        errorLine2="                                                  ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    remoteInput.getLabel(),"
-        errorLine2="                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    remoteInput.getChoices(),"
-        errorLine2="                                ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    remoteInput.getAllowFreeFormInput(),"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                            ? remoteInput.getEditChoicesBeforeSending()"
-        errorLine2="                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    remoteInput.getExtras(),"
-        errorLine2="                                ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        new android.app.RemoteInput.Builder(remoteInputCompat.getResultKey())"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine1="                        Api20Impl.build(new android.app.RemoteInput.Builder("
+        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/main/java/androidx/core/app/NotificationCompat.java"/>
     </issue>
@@ -3136,7 +2191,7 @@
     <issue
         id="ClassVerificationFailure"
         message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .addExtras(remoteInputCompat.getExtras())"
+        errorLine1="                                .addExtras(remoteInputCompat.getExtras()));"
         errorLine2="                                 ~~~~~~~~~">
         <location
             file="src/main/java/androidx/core/app/NotificationCompat.java"/>
@@ -3144,303 +2199,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat.CarExtender is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                .build();"
-        errorLine2="                                 ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return BubbleMetadata.fromPlatform(notification.getBubbleMetadata());"
-        errorLine2="                                                            ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        final android.app.RemoteInput[] srcArray = action.getRemoteInputs();"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        src.getResultKey(),"
-        errorLine2="                            ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        src.getLabel(),"
-        errorLine2="                            ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        src.getChoices(),"
-        errorLine2="                            ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        src.getAllowFreeFormInput(),"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                                ? src.getEditChoicesBeforeSending()"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        src.getExtras(),"
-        errorLine2="                            ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            allowGeneratedReplies = action.getExtras().getBoolean("
-        errorLine2="                                           ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    || action.getAllowGeneratedReplies();"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            allowGeneratedReplies = action.getExtras().getBoolean("
-        errorLine2="                                           ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                action.getExtras().getBoolean(Action.EXTRA_SHOWS_USER_INTERFACE, true);"
-        errorLine2="                       ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            semanticAction = action.getSemanticAction();"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            semanticAction = action.getExtras().getInt("
-        errorLine2="                                    ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="        final boolean isContextual = Build.VERSION.SDK_INT >= 29 ? action.isContextual() : false;"
-        errorLine2="                                                                          ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 31; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                Build.VERSION.SDK_INT >= 31 ? action.isAuthenticationRequired() : false;"
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            if (action.getIcon() == null &amp;&amp; action.icon != 0) {"
-        errorLine2="                       ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        action.getExtras(), remoteInputs, null, allowGeneratedReplies,"
-        errorLine2="                               ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            IconCompat icon = action.getIcon() == null"
-        errorLine2="                                     ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 23; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                    ? null : IconCompat.createFromIconOrNullIfZeroResId(action.getIcon());"
-        errorLine2="                                                                               ~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return new Action(icon, action.title, action.actionIntent, action.getExtras(),"
-        errorLine2="                                                                              ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return new Action(action.icon, action.title, action.actionIntent, action.getExtras(),"
-        errorLine2="                                                                                     ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getGroup();"
-        errorLine2="                                ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 20; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getSortKey();"
-        errorLine2="                                ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getChannelId();"
-        errorLine2="                                ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getTimeoutAfter();"
-        errorLine2="                                ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getBadgeIconType();"
-        errorLine2="                                ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getShortcutId();"
-        errorLine2="                                ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getSettingsText();"
-        errorLine2="                                ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            LocusId locusId = notification.getLocusId();"
-        errorLine2="                                           ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getGroupAlertBehavior();"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 29; however, the containing class androidx.core.app.NotificationCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return notification.getAllowSystemGeneratedContextualActions();"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationCompatBuilder is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="            mBuilder = new Notification.Builder(b.mContext, b.mChannelId);"
         errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -3972,195 +2730,6 @@
 
     <issue
         id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.areNotificationsEnabled();"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 24; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getImportance();"
-        errorLine2="                                        ~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannel(channel);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannelGroup(group);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannels(channels);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannels(platformChannels);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannelGroups(groups);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.createNotificationChannelGroups(platformGroups);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.deleteNotificationChannel(channelId);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            mNotificationManager.deleteNotificationChannelGroup(groupId);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            for (NotificationChannel channel : mNotificationManager.getNotificationChannels()) {"
-        errorLine2="                                                                    ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                if (channelIds.contains(channel.getId())) {"
-        errorLine2="                                                ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                        &amp;&amp; channelIds.contains(channel.getParentChannelId())) {"
-        errorLine2="                                                       ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                mNotificationManager.deleteNotificationChannel(channel.getId());"
-        errorLine2="                                     ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                mNotificationManager.deleteNotificationChannel(channel.getId());"
-        errorLine2="                                                                       ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getNotificationChannel(channelId);"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 30; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getNotificationChannel(channelId, conversationId);"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 28; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getNotificationChannelGroup(channelGroupId);"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="                if (group.getId().equals(channelGroupId)) return group;"
-        errorLine2="                          ~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getNotificationChannels();"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
-        message="This call references a method added in API level 26; however, the containing class androidx.core.app.NotificationManagerCompat is reachable from earlier API levels and will fail run-time class verification."
-        errorLine1="            return mNotificationManager.getNotificationChannelGroups();"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/core/app/NotificationManagerCompat.java"/>
-    </issue>
-
-    <issue
-        id="ClassVerificationFailure"
         message="This call references a method added in API level 28; however, the containing class androidx.core.text.PrecomputedTextCompat.Params is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="                mWrapped = new PrecomputedText.Params.Builder(paint)"
         errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/credentials/credentials-play-services-auth/build.gradle b/credentials/credentials-play-services-auth/build.gradle
index 2125f1d..bf17414 100644
--- a/credentials/credentials-play-services-auth/build.gradle
+++ b/credentials/credentials-play-services-auth/build.gradle
@@ -29,6 +29,10 @@
 
 android {
     namespace "androidx.credentials.play.services.auth"
+
+    defaultConfig {
+        minSdkVersion 19
+    }
 }
 
 androidx {
diff --git a/credentials/credentials-provider/api/current.txt b/credentials/credentials-provider/api/current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/credentials/credentials-provider/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/credentials/credentials-provider/api/public_plus_experimental_current.txt b/credentials/credentials-provider/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/credentials/credentials-provider/api/public_plus_experimental_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/credentials/credentials-provider/api/res-current.txt b/credentials/credentials-provider/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/credentials/credentials-provider/api/res-current.txt
diff --git a/credentials/credentials-provider/api/restricted_current.txt b/credentials/credentials-provider/api/restricted_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/credentials/credentials-provider/api/restricted_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/credentials/credentials-provider/build.gradle b/credentials/credentials-provider/build.gradle
new file mode 100644
index 0000000..f56c18c
--- /dev/null
+++ b/credentials/credentials-provider/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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.LibraryType
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    api(libs.kotlinStdlib)
+    // Add dependencies here
+}
+
+android {
+    namespace "androidx.credentials.provider"
+
+    defaultConfig {
+        minSdkVersion 19
+    }
+}
+
+androidx {
+    name = "Credentials Provider Library"
+    type = LibraryType.PUBLISHED_LIBRARY
+    mavenGroup = LibraryGroups.CREDENTIALS
+    inceptionYear = "2022"
+    description = "use utility APIs to process requests from, and return responses to the android" +
+            "Credential Manager"
+}
diff --git a/credentials/credentials-provider/src/main/androidx/credentials/androidx-credentials-credentials-provider-documentation.md b/credentials/credentials-provider/src/main/androidx/credentials/androidx-credentials-credentials-provider-documentation.md
new file mode 100644
index 0000000..d3a5d02
--- /dev/null
+++ b/credentials/credentials-provider/src/main/androidx/credentials/androidx-credentials-credentials-provider-documentation.md
@@ -0,0 +1,8 @@
+# Module root
+
+CREDENTIALS CREDENTIALS PROVIDER
+
+# Package androidx.credentials.provider
+
+This package provides utility APIs for providers to use as they respond to credential requests 
+from the android Credential Manager.
\ No newline at end of file
diff --git a/credentials/credentials/api/current.txt b/credentials/credentials/api/current.txt
index e6f50d0..014f0be 100644
--- a/credentials/credentials/api/current.txt
+++ b/credentials/credentials/api/current.txt
@@ -1 +1,75 @@
 // Signature format: 4.0
+package androidx.credentials {
+
+  public abstract class CreateCredentialRequest {
+    ctor public CreateCredentialRequest();
+  }
+
+  public abstract class CreateCredentialResponse {
+    ctor public CreateCredentialResponse();
+  }
+
+  public final class CreatePasswordRequest extends androidx.credentials.CreateCredentialRequest {
+    ctor public CreatePasswordRequest(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+  public final class CreatePasswordResponse extends androidx.credentials.CreateCredentialResponse {
+    ctor public CreatePasswordResponse();
+  }
+
+  public abstract class Credential {
+    ctor public Credential();
+  }
+
+  public final class CredentialManager {
+    method public static androidx.credentials.CredentialManager create(android.content.Context context);
+    method public suspend Object? executeCreateCredential(androidx.credentials.CreateCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.CreateCredentialResponse>);
+    method public suspend Object? executeGetCredential(androidx.credentials.GetCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.GetCredentialResponse>);
+    field public static final androidx.credentials.CredentialManager.Companion Companion;
+  }
+
+  public static final class CredentialManager.Companion {
+    method public androidx.credentials.CredentialManager create(android.content.Context context);
+  }
+
+  public abstract class GetCredentialOption {
+    ctor public GetCredentialOption();
+  }
+
+  public final class GetCredentialRequest {
+    ctor public GetCredentialRequest(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+    method public java.util.List<androidx.credentials.GetCredentialOption> getGetCredentialOptions();
+    property public final java.util.List<androidx.credentials.GetCredentialOption> getCredentialOptions;
+  }
+
+  public static final class GetCredentialRequest.Builder {
+    ctor public GetCredentialRequest.Builder();
+    method public androidx.credentials.GetCredentialRequest.Builder addGetCredentialOption(androidx.credentials.GetCredentialOption getCredentialOption);
+    method public androidx.credentials.GetCredentialRequest build();
+    method public androidx.credentials.GetCredentialRequest.Builder setGetCredentialOptions(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+  }
+
+  public final class GetCredentialResponse {
+    ctor public GetCredentialResponse(androidx.credentials.Credential credential);
+    method public androidx.credentials.Credential getCredential();
+    property public final androidx.credentials.Credential credential;
+  }
+
+  public final class GetPasswordOption extends androidx.credentials.GetCredentialOption {
+    ctor public GetPasswordOption();
+  }
+
+  public final class PasswordCredential extends androidx.credentials.Credential {
+    ctor public PasswordCredential(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+}
+
diff --git a/credentials/credentials/api/public_plus_experimental_current.txt b/credentials/credentials/api/public_plus_experimental_current.txt
index e6f50d0..014f0be 100644
--- a/credentials/credentials/api/public_plus_experimental_current.txt
+++ b/credentials/credentials/api/public_plus_experimental_current.txt
@@ -1 +1,75 @@
 // Signature format: 4.0
+package androidx.credentials {
+
+  public abstract class CreateCredentialRequest {
+    ctor public CreateCredentialRequest();
+  }
+
+  public abstract class CreateCredentialResponse {
+    ctor public CreateCredentialResponse();
+  }
+
+  public final class CreatePasswordRequest extends androidx.credentials.CreateCredentialRequest {
+    ctor public CreatePasswordRequest(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+  public final class CreatePasswordResponse extends androidx.credentials.CreateCredentialResponse {
+    ctor public CreatePasswordResponse();
+  }
+
+  public abstract class Credential {
+    ctor public Credential();
+  }
+
+  public final class CredentialManager {
+    method public static androidx.credentials.CredentialManager create(android.content.Context context);
+    method public suspend Object? executeCreateCredential(androidx.credentials.CreateCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.CreateCredentialResponse>);
+    method public suspend Object? executeGetCredential(androidx.credentials.GetCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.GetCredentialResponse>);
+    field public static final androidx.credentials.CredentialManager.Companion Companion;
+  }
+
+  public static final class CredentialManager.Companion {
+    method public androidx.credentials.CredentialManager create(android.content.Context context);
+  }
+
+  public abstract class GetCredentialOption {
+    ctor public GetCredentialOption();
+  }
+
+  public final class GetCredentialRequest {
+    ctor public GetCredentialRequest(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+    method public java.util.List<androidx.credentials.GetCredentialOption> getGetCredentialOptions();
+    property public final java.util.List<androidx.credentials.GetCredentialOption> getCredentialOptions;
+  }
+
+  public static final class GetCredentialRequest.Builder {
+    ctor public GetCredentialRequest.Builder();
+    method public androidx.credentials.GetCredentialRequest.Builder addGetCredentialOption(androidx.credentials.GetCredentialOption getCredentialOption);
+    method public androidx.credentials.GetCredentialRequest build();
+    method public androidx.credentials.GetCredentialRequest.Builder setGetCredentialOptions(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+  }
+
+  public final class GetCredentialResponse {
+    ctor public GetCredentialResponse(androidx.credentials.Credential credential);
+    method public androidx.credentials.Credential getCredential();
+    property public final androidx.credentials.Credential credential;
+  }
+
+  public final class GetPasswordOption extends androidx.credentials.GetCredentialOption {
+    ctor public GetPasswordOption();
+  }
+
+  public final class PasswordCredential extends androidx.credentials.Credential {
+    ctor public PasswordCredential(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+}
+
diff --git a/credentials/credentials/api/restricted_current.txt b/credentials/credentials/api/restricted_current.txt
index e6f50d0..014f0be 100644
--- a/credentials/credentials/api/restricted_current.txt
+++ b/credentials/credentials/api/restricted_current.txt
@@ -1 +1,75 @@
 // Signature format: 4.0
+package androidx.credentials {
+
+  public abstract class CreateCredentialRequest {
+    ctor public CreateCredentialRequest();
+  }
+
+  public abstract class CreateCredentialResponse {
+    ctor public CreateCredentialResponse();
+  }
+
+  public final class CreatePasswordRequest extends androidx.credentials.CreateCredentialRequest {
+    ctor public CreatePasswordRequest(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+  public final class CreatePasswordResponse extends androidx.credentials.CreateCredentialResponse {
+    ctor public CreatePasswordResponse();
+  }
+
+  public abstract class Credential {
+    ctor public Credential();
+  }
+
+  public final class CredentialManager {
+    method public static androidx.credentials.CredentialManager create(android.content.Context context);
+    method public suspend Object? executeCreateCredential(androidx.credentials.CreateCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.CreateCredentialResponse>);
+    method public suspend Object? executeGetCredential(androidx.credentials.GetCredentialRequest request, kotlin.coroutines.Continuation<? super androidx.credentials.GetCredentialResponse>);
+    field public static final androidx.credentials.CredentialManager.Companion Companion;
+  }
+
+  public static final class CredentialManager.Companion {
+    method public androidx.credentials.CredentialManager create(android.content.Context context);
+  }
+
+  public abstract class GetCredentialOption {
+    ctor public GetCredentialOption();
+  }
+
+  public final class GetCredentialRequest {
+    ctor public GetCredentialRequest(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+    method public java.util.List<androidx.credentials.GetCredentialOption> getGetCredentialOptions();
+    property public final java.util.List<androidx.credentials.GetCredentialOption> getCredentialOptions;
+  }
+
+  public static final class GetCredentialRequest.Builder {
+    ctor public GetCredentialRequest.Builder();
+    method public androidx.credentials.GetCredentialRequest.Builder addGetCredentialOption(androidx.credentials.GetCredentialOption getCredentialOption);
+    method public androidx.credentials.GetCredentialRequest build();
+    method public androidx.credentials.GetCredentialRequest.Builder setGetCredentialOptions(java.util.List<? extends androidx.credentials.GetCredentialOption> getCredentialOptions);
+  }
+
+  public final class GetCredentialResponse {
+    ctor public GetCredentialResponse(androidx.credentials.Credential credential);
+    method public androidx.credentials.Credential getCredential();
+    property public final androidx.credentials.Credential credential;
+  }
+
+  public final class GetPasswordOption extends androidx.credentials.GetCredentialOption {
+    ctor public GetPasswordOption();
+  }
+
+  public final class PasswordCredential extends androidx.credentials.Credential {
+    ctor public PasswordCredential(String id, String password);
+    method public String getId();
+    method public String getPassword();
+    property public final String id;
+    property public final String password;
+  }
+
+}
+
diff --git a/credentials/credentials/build.gradle b/credentials/credentials/build.gradle
index 0536e04..e42b992 100644
--- a/credentials/credentials/build.gradle
+++ b/credentials/credentials/build.gradle
@@ -24,11 +24,23 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(project(":internal-testutils-truth"))
+    androidTestImplementation(libs.kotlinCoroutinesAndroid)
 }
 
 android {
     namespace "androidx.credentials"
+
+    defaultConfig {
+        minSdkVersion 19
+    }
 }
 
 androidx {
diff --git a/credentials/credentials/src/androidTest/AndroidManifest.xml b/credentials/credentials/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..4995896
--- /dev/null
+++ b/credentials/credentials/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 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">
+</manifest>
\ No newline at end of file
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialManagerTest.kt b/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialManagerTest.kt
new file mode 100644
index 0000000..81ec28f
--- /dev/null
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/CredentialManagerTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2022 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.credentials
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.testutils.assertThrows
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class CredentialManagerTest {
+    private val context = InstrumentationRegistry.getInstrumentation().context
+
+    private lateinit var credentialManager: CredentialManager
+
+    @Before
+    fun setup() {
+        credentialManager = CredentialManager.create(context)
+    }
+
+    @Test
+    fun testCreateCredential() = runBlocking<Unit> {
+        assertThrows<UnsupportedOperationException> {
+            credentialManager.executeCreateCredential(
+                CreatePasswordRequest("test-user-id", "test-password")
+            )
+        }
+    }
+
+    @Test
+    fun testGetCredential() = runBlocking<Unit> {
+        val request = GetCredentialRequest.Builder()
+            .addGetCredentialOption(GetPasswordOption())
+            .build()
+        assertThrows<UnsupportedOperationException> {
+            credentialManager.executeGetCredential(request)
+        }
+    }
+}
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt
new file mode 100644
index 0000000..d630fa7
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialRequest.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 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.credentials
+
+/**
+ * Base request class for registering a credential.
+ *
+ * An application can construct a subtype request and call [CredentialManager.executeCreateCredential] to
+ * launch framework UI flows to collect consent and any other metadata needed from the user to
+ * register a new user credential.
+ */
+abstract class CreateCredentialRequest
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialResponse.kt b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialResponse.kt
new file mode 100644
index 0000000..192d472
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/CreateCredentialResponse.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 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.credentials
+
+/** Base response class for registering a credential. */
+abstract class CreateCredentialResponse
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordRequest.kt b/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordRequest.kt
new file mode 100644
index 0000000..2fc0116
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordRequest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 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.credentials
+
+/**
+ * A request to save the user password credential with their password provider.
+ *
+ * @property id the user id associated with the password
+ * @property password the password
+ * @throws NullPointerException If [id] is null
+ * @throws NullPointerException If [password] is null
+ * @throws IllegalArgumentException If [password] is empty
+ */
+class CreatePasswordRequest constructor(
+    val id: String,
+    val password: String,
+) : CreateCredentialRequest() {
+
+    init {
+        require(password.isNotEmpty()) { "password should not be empty" }
+    }
+}
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordResponse.kt b/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordResponse.kt
new file mode 100644
index 0000000..d70468c
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/CreatePasswordResponse.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 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.credentials
+
+/** A response of a password saving flow. */
+class CreatePasswordResponse : CreateCredentialResponse()
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/Credential.kt b/credentials/credentials/src/main/java/androidx/credentials/Credential.kt
new file mode 100644
index 0000000..eb19ff8
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/Credential.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 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.credentials
+
+/** Base class for a credential with which the user consented to authenticate to the app. */
+abstract class Credential
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/CredentialManager.kt b/credentials/credentials/src/main/java/androidx/credentials/CredentialManager.kt
new file mode 100644
index 0000000..04e27f1c
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/CredentialManager.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2022 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.credentials
+
+import android.content.Context
+
+/**
+ * Manages user authentication flows.
+ *
+ * An application can call the CredentialManager apis to launch framework UI flows for a user to
+ * register a new credential or to consent to a saved credential from supported credential
+ * providers, which can then be used to authenticate to the app.
+ */
+@Suppress("UNUSED_PARAMETER")
+class CredentialManager private constructor(private val context: Context) {
+    companion object {
+        @JvmStatic
+        fun create(context: Context): CredentialManager = CredentialManager(context)
+    }
+
+    /**
+     * Requests a credential from the user.
+     *
+     * The execution potentially launches framework UI flows for a user to view available
+     * credentials, consent to using one of them, etc.
+     *
+     * @throws UnsupportedOperationException Since the api is unimplemented
+     */
+    // TODO(helenqin): support failure flow.
+    suspend fun executeGetCredential(request: GetCredentialRequest): GetCredentialResponse {
+        throw UnsupportedOperationException("Unimplemented")
+    }
+
+    /**
+     * Registers a user credential that can be used to authenticate the user to
+     * the app in the future.
+     *
+     * The execution potentially launches framework UI flows for a user to view their registration
+     * options, grant consent, etc.
+     *
+     * @throws UnsupportedOperationException Since the api is unimplemented
+     */
+    suspend fun executeCreateCredential(
+        request: CreateCredentialRequest
+    ): CreateCredentialResponse {
+        throw UnsupportedOperationException("Unimplemented")
+    }
+}
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/GetCredentialOption.kt b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialOption.kt
new file mode 100644
index 0000000..2fcd72a
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialOption.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 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.credentials
+
+/** Base request class for getting a registered credential. */
+abstract class GetCredentialOption
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/GetCredentialRequest.kt b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialRequest.kt
new file mode 100644
index 0000000..165198a
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialRequest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2022 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.credentials
+
+/**
+ * Encapsulates a request to get a user credential.
+ *
+ * An application can construct such a request by adding one or more types of [GetCredentialOption],
+ * and then call [CredentialManager.executeGetCredential] to launch framework UI flows to allow the user
+ * to consent to using a previously saved credential for the given application.
+ *
+ * @property getCredentialOptions the list of [GetCredentialOption] from which the user can choose
+ * one to authenticate to the app
+ * @throws IllegalArgumentException If [getCredentialOptions] is empty
+ */
+class GetCredentialRequest constructor(
+    val getCredentialOptions: List<GetCredentialOption>,
+) {
+
+    init {
+        require(getCredentialOptions.isNotEmpty()) { "credentialRequests should not be empty" }
+    }
+
+    /** A builder for [GetCredentialRequest]. */
+    class Builder {
+        private var getCredentialOptions: MutableList<GetCredentialOption> = mutableListOf()
+
+        /** Adds a specific type of [GetCredentialOption]. */
+        fun addGetCredentialOption(getCredentialOption: GetCredentialOption): Builder {
+            getCredentialOptions.add(getCredentialOption)
+            return this
+        }
+
+        /** Sets the list of [GetCredentialOption]. */
+        fun setGetCredentialOptions(getCredentialOptions: List<GetCredentialOption>): Builder {
+            this.getCredentialOptions = getCredentialOptions.toMutableList()
+            return this
+        }
+
+        /**
+         * Builds a [GetCredentialRequest].
+         *
+         * @throws IllegalArgumentException If [getCredentialOptions] is empty
+         */
+        fun build(): GetCredentialRequest {
+            return GetCredentialRequest(getCredentialOptions.toList())
+        }
+    }
+}
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/GetCredentialResponse.kt b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialResponse.kt
new file mode 100644
index 0000000..1a2b624
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/GetCredentialResponse.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 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.credentials
+
+/**
+ * Encapsulates the result of a user credential request.
+ *
+ * @property credential the user credential that can be used to authenticate to your app
+ * @throws NullPointerException If [credential] is null
+ */
+class GetCredentialResponse constructor(val credential: Credential)
diff --git a/credentials/credentials/src/main/java/androidx/credentials/GetPasswordOption.kt b/credentials/credentials/src/main/java/androidx/credentials/GetPasswordOption.kt
new file mode 100644
index 0000000..920cbf2
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/GetPasswordOption.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2022 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.credentials
+
+/** A request to retrieve the user's saved application password from their password provider. */
+class GetPasswordOption : GetCredentialOption()
\ No newline at end of file
diff --git a/credentials/credentials/src/main/java/androidx/credentials/PasswordCredential.kt b/credentials/credentials/src/main/java/androidx/credentials/PasswordCredential.kt
new file mode 100644
index 0000000..252f4a1
--- /dev/null
+++ b/credentials/credentials/src/main/java/androidx/credentials/PasswordCredential.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 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.credentials
+
+/**
+ * Represents the user's password credential granted by the user for app sign-in.
+ *
+ * @property id the user id associated with the password
+ * @property password the password
+ * @throws NullPointerException If [id] is null
+ * @throws NullPointerException If [password] is null
+ * @throws IllegalArgumentException If [password] is empty
+ */
+class PasswordCredential constructor(
+    val id: String,
+    val password: String,
+) : Credential() {
+
+    init {
+        require(password.isNotEmpty()) { "password should not be empty" }
+    }
+}
diff --git a/datastore/datastore-multiprocess/lint-baseline.xml b/datastore/datastore-multiprocess/lint-baseline.xml
deleted file mode 100644
index 7b459a2..0000000
--- a/datastore/datastore-multiprocess/lint-baseline.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="NewApi"
-        message="Implicit cast from `ParcelFileDescriptor` to `Closeable` requires API level 16 (current min is 14)"
-        errorLine1="            ).use {"
-        errorLine2="              ~~~">
-        <location
-            file="src/main/java/androidx/datastore/multiprocess/SharedCounter.kt"/>
-    </issue>
-
-</issues>
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index ce5e0d0..6550261 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -126,6 +126,7 @@
     docs(project(":core:uwb:uwb-rxjava3"))
     docs(project(":credentials:credentials"))
     docs(project(":credentials:credentials-play-services-auth"))
+    docs(project(":credentials:credentials-provider"))
     docs(project(":cursoradapter:cursoradapter"))
     docs(project(":customview:customview"))
     docs(project(":customview:customview-poolingcontainer"))
diff --git a/glance/glance/src/test/kotlin/androidx/glance/color/ColorProvidersTest.kt b/glance/glance/src/test/kotlin/androidx/glance/color/ColorProvidersTest.kt
index 370949f..a8bdf7a 100644
--- a/glance/glance/src/test/kotlin/androidx/glance/color/ColorProvidersTest.kt
+++ b/glance/glance/src/test/kotlin/androidx/glance/color/ColorProvidersTest.kt
@@ -21,7 +21,7 @@
 import androidx.annotation.ColorRes
 import androidx.core.content.ContextCompat
 import androidx.test.core.app.ApplicationProvider
-import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.robolectric.RobolectricTestRunner
@@ -33,6 +33,7 @@
     private val context = ApplicationProvider.getApplicationContext<Context>()
 
     @Test
+    @Config(sdk = [Build.VERSION_CODES.R])
     fun testGlanceMatchMaterial3Colors() {
         val lightColors = mapOf(
             androidx.glance.R.color.glance_colorPrimary to
@@ -94,7 +95,7 @@
     }
 
     @Test
-    @Config(qualifiers = "night")
+    @Config(qualifiers = "night", sdk = [Build.VERSION_CODES.R])
     fun testGlanceMatchMaterial3NightColors() {
         val darkColors = mapOf(
             androidx.glance.R.color.glance_colorPrimary to
@@ -280,8 +281,17 @@
     }
 
     private fun assertColor(@ColorRes source: Int, @ColorRes target: Int) {
-        assertThat(ContextCompat.getColor(context, source)).isEqualTo(
-            ContextCompat.getColor(context, target)
-        )
+        val sourceColor = ContextCompat.getColor(context, source)
+        val targetColor = ContextCompat.getColor(context, target)
+
+        val sourceHex = String.format("0x%08X", sourceColor)
+        val targetHex = String.format("0x%08X", targetColor)
+
+        val sourceName = context.resources.getResourceEntryName(source)
+        val targetName = context.resources.getResourceEntryName(target)
+
+        val message = "$sourceName is $sourceHex but $targetName is $targetHex"
+
+        assertWithMessage(message).that(sourceColor).isEqualTo(targetColor)
     }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/api/current.txt b/graphics/graphics-core/api/current.txt
index 1fe1a05..781c97c 100644
--- a/graphics/graphics-core/api/current.txt
+++ b/graphics/graphics-core/api/current.txt
@@ -28,7 +28,11 @@
     method public boolean awaitForever();
     method public void close();
     method public static androidx.graphics.lowlatency.SyncFenceCompat createNativeSyncFence(androidx.graphics.opengl.egl.EGLSpec egl);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public long getSignalTime();
+    method public boolean isValid();
     field public static final androidx.graphics.lowlatency.SyncFenceCompat.Companion Companion;
+    field public static final long SIGNAL_TIME_INVALID = -1L; // 0xffffffffffffffffL
+    field public static final long SIGNAL_TIME_PENDING = 9223372036854775807L; // 0x7fffffffffffffffL
   }
 
   public static final class SyncFenceCompat.Companion {
diff --git a/graphics/graphics-core/api/public_plus_experimental_current.txt b/graphics/graphics-core/api/public_plus_experimental_current.txt
index 1fe1a05..781c97c 100644
--- a/graphics/graphics-core/api/public_plus_experimental_current.txt
+++ b/graphics/graphics-core/api/public_plus_experimental_current.txt
@@ -28,7 +28,11 @@
     method public boolean awaitForever();
     method public void close();
     method public static androidx.graphics.lowlatency.SyncFenceCompat createNativeSyncFence(androidx.graphics.opengl.egl.EGLSpec egl);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public long getSignalTime();
+    method public boolean isValid();
     field public static final androidx.graphics.lowlatency.SyncFenceCompat.Companion Companion;
+    field public static final long SIGNAL_TIME_INVALID = -1L; // 0xffffffffffffffffL
+    field public static final long SIGNAL_TIME_PENDING = 9223372036854775807L; // 0x7fffffffffffffffL
   }
 
   public static final class SyncFenceCompat.Companion {
diff --git a/graphics/graphics-core/api/restricted_current.txt b/graphics/graphics-core/api/restricted_current.txt
index d2ba87f..141298c 100644
--- a/graphics/graphics-core/api/restricted_current.txt
+++ b/graphics/graphics-core/api/restricted_current.txt
@@ -28,7 +28,11 @@
     method public boolean awaitForever();
     method public void close();
     method public static androidx.graphics.lowlatency.SyncFenceCompat createNativeSyncFence(androidx.graphics.opengl.egl.EGLSpec egl);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public long getSignalTime();
+    method public boolean isValid();
     field public static final androidx.graphics.lowlatency.SyncFenceCompat.Companion Companion;
+    field public static final long SIGNAL_TIME_INVALID = -1L; // 0xffffffffffffffffL
+    field public static final long SIGNAL_TIME_PENDING = 9223372036854775807L; // 0x7fffffffffffffffL
   }
 
   public static final class SyncFenceCompat.Companion {
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
index bb0bd74..246dced 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/GLFrontBufferedRendererTest.kt
@@ -39,7 +39,6 @@
 import org.junit.Assert.assertNotEquals
 import org.junit.Assert.assertTrue
 import org.junit.Assert.fail
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -279,7 +278,6 @@
     }
 
     @Test
-    @Ignore("b/244755709")
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
     fun testRenderFrontBufferSeveralTimes() {
         if (!deviceSupportsNativeAndroidFence()) {
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LineRenderer.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LineRenderer.kt
new file mode 100644
index 0000000..e80f18e
--- /dev/null
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/LineRenderer.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2022 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.graphics.lowlatency
+
+import android.opengl.GLES20
+import java.nio.ByteBuffer
+import java.nio.ByteOrder
+import java.nio.FloatBuffer
+import org.junit.Assert.assertEquals
+
+/**
+ * OpenGL Renderer class responsible for drawing lines
+ */
+class LineRenderer {
+
+    private var mVertexShader: Int = -1
+    private var mFragmentShader: Int = -1
+    private var mGlProgram: Int = -1
+
+    private var mPositionHandle: Int = -1
+    private var mMvpMatrixHandle: Int = -1
+
+    private var mVertexBuffer: FloatBuffer? = null
+    private val mLineCoords = FloatArray(6)
+
+    fun initialize() {
+        release()
+        mVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VertexShaderCode)
+        mFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FragmentShaderCode)
+
+        mGlProgram = GLES20.glCreateProgram()
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+        GLES20.glAttachShader(mGlProgram, mVertexShader)
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+        GLES20.glAttachShader(mGlProgram, mFragmentShader)
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+        GLES20.glLinkProgram(mGlProgram)
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+        val bb: ByteBuffer =
+            ByteBuffer.allocateDirect( // (number of coordinate values * 4 bytes per float)
+                LineCoordsSize * 4
+            )
+        // use the device hardware's native byte order
+        bb.order(ByteOrder.nativeOrder())
+
+        // create a floating point buffer from the ByteBuffer
+        mVertexBuffer = bb.asFloatBuffer().apply {
+            put(mLineCoords)
+            position(0)
+        }
+
+        mPositionHandle = GLES20.glGetAttribLocation(mGlProgram, vPosition)
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+        mMvpMatrixHandle = GLES20.glGetUniformLocation(mGlProgram, uMVPMatrix)
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+    }
+
+    fun release() {
+        if (mVertexShader != -1) {
+            GLES20.glDeleteShader(mVertexShader)
+            mVertexShader = -1
+        }
+
+        if (mFragmentShader != -1) {
+            GLES20.glDeleteShader(mFragmentShader)
+            mFragmentShader = -1
+        }
+
+        if (mGlProgram != -1) {
+            GLES20.glDeleteProgram(mGlProgram)
+            mGlProgram = -1
+        }
+    }
+
+    fun drawLines(mvpMatrix: FloatArray, lines: FloatArray) {
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+        GLES20.glUseProgram(mGlProgram)
+
+        val buff = FloatBuffer.allocate(2)
+        GLES20.glGetFloatv(GLES20.GL_ALIASED_LINE_WIDTH_RANGE, buff)
+        GLES20.glLineWidth(100.0f)
+
+        GLES20.glEnableVertexAttribArray(mPositionHandle)
+
+        GLES20.glUniformMatrix4fv(mMvpMatrixHandle, 1, false, mvpMatrix, 0)
+
+        mVertexBuffer?.let { buffer ->
+            for (i in 0 until lines.size step 4) {
+                mLineCoords[0] = lines[i]
+                mLineCoords[1] = lines[i + 1]
+                mLineCoords[2] = 0f
+                mLineCoords[3] = lines[i + 2]
+                mLineCoords[4] = lines[i + 3]
+                mLineCoords[5] = 0f
+                buffer.put(mLineCoords)
+                buffer.position(0)
+            }
+
+            // Prepare the triangle coordinate data
+            GLES20.glVertexAttribPointer(
+                mPositionHandle, CoordsPerVertex,
+                GLES20.GL_FLOAT, false,
+                VertexStride, buffer
+            )
+            GLES20.glDrawArrays(GLES20.GL_LINES, 0, VertexCount)
+
+            GLES20.glDisableVertexAttribArray(mPositionHandle)
+            assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+        }
+    }
+
+    companion object {
+
+        const val CoordsPerVertex = 3
+        const val LineCoordsSize = 6
+        private val VertexCount: Int = LineCoordsSize / CoordsPerVertex
+        private val VertexStride: Int = CoordsPerVertex * 4 // 4 bytes per vertex
+
+        private const val uMVPMatrix = "uMVPMatrix"
+        private const val vPosition = "vPosition"
+        private const val VertexShaderCode =
+            """
+                uniform mat4 $uMVPMatrix;
+                attribute vec4 $vPosition;
+                void main() { // the matrix must be included as a modifier of gl_Position
+                  gl_Position = $uMVPMatrix * $vPosition;
+                }
+            """
+
+        private const val FragmentShaderCode =
+            """
+                precision highp float;
+
+                void main() {
+                    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+                }
+            """
+
+        fun loadShader(type: Int, shaderCode: String?): Int {
+            val shader = GLES20.glCreateShader(type)
+
+            GLES20.glShaderSource(shader, shaderCode)
+            GLES20.glCompileShader(shader)
+
+            return shader
+        }
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SyncStrategyTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SyncStrategyTest.kt
new file mode 100644
index 0000000..d836469
--- /dev/null
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/SyncStrategyTest.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2022 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.graphics.lowlatency
+
+import android.opengl.EGL14
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.graphics.opengl.egl.EGLConfigAttributes
+import androidx.graphics.opengl.egl.EGLManager
+import androidx.graphics.opengl.egl.EGLSpec
+import androidx.graphics.opengl.egl.EGLVersion
+import androidx.graphics.opengl.egl.supportsNativeAndroidFence
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import org.junit.Assert
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class SyncStrategyTest {
+    @RequiresApi(Build.VERSION_CODES.O)
+    @Test
+    fun testSyncStrategy_Always() {
+        val egl = createAndSetupEGLManager(EGLSpec.V14)
+        if (egl.supportsNativeAndroidFence()) {
+            val strategy = SyncStrategy.ALWAYS
+            val fence = strategy.createSyncFence(egl.eglSpec)
+            assertTrue(fence != null)
+            fence?.close()
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    @Test
+    fun testSyncStrategy_onFirstShow_FrontBufferUsageOff_Invisible() {
+        val egl = createAndSetupEGLManager(EGLSpec.V14)
+        if (egl.supportsNativeAndroidFence()) {
+            val strategy = FrontBufferSyncStrategy(false)
+            val fence = strategy.createSyncFence(EGLSpec.V14)
+            assertTrue(fence != null)
+            fence?.close()
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    @Test
+    fun testSyncStrategy_onFirstShow_FrontBufferUsageOff_Visible() {
+        val egl = createAndSetupEGLManager(EGLSpec.V14)
+        if (egl.supportsNativeAndroidFence()) {
+            val strategy = FrontBufferSyncStrategy(false)
+            strategy.setVisible(true)
+            val fence = strategy.createSyncFence(EGLSpec.V14)
+            assertTrue(fence == null)
+            fence?.close()
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    @Test
+    fun testSyncStrategy_onFirstShow_FrontBufferUsageOn_Invisible() {
+        val egl = createAndSetupEGLManager(EGLSpec.V14)
+        if (egl.supportsNativeAndroidFence()) {
+            val strategy = FrontBufferSyncStrategy(true)
+            val fence = strategy.createSyncFence(egl.eglSpec)
+            assertTrue(fence != null)
+            fence?.close()
+        }
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    @Test
+    fun testSyncStrategy_onFirstShow_FrontBufferUsageOn_Visible() {
+        val egl = createAndSetupEGLManager(EGLSpec.V14)
+        if (egl.supportsNativeAndroidFence()) {
+            val strategy = FrontBufferSyncStrategy(true)
+            strategy.setVisible(true)
+            val fence = strategy.createSyncFence(EGLSpec.V14)
+            assertTrue(fence == null)
+            fence?.close()
+        }
+    }
+
+    // Helper method to create and initialize an EGLManager
+    fun createAndSetupEGLManager(eglSpec: EGLSpec = EGLSpec.V14): EGLManager {
+        val egl = EGLManager(eglSpec)
+        Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
+        Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
+
+        egl.initialize()
+
+        val config = egl.loadConfig(EGLConfigAttributes.RGBA_8888)
+        if (config == null) {
+            Assert.fail("Config 888 should be supported")
+        }
+
+        egl.createContext(config!!)
+        return egl
+    }
+
+    // Helper method to release EGLManager
+    fun releaseEGLManager(egl: EGLManager) {
+        egl.release()
+        Assert.assertEquals(EGLVersion.Unknown, egl.eglVersion)
+        Assert.assertEquals(EGL14.EGL_NO_CONTEXT, egl.eglContext)
+    }
+}
\ No newline at end of file
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
index 7831516..b89bbad0 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLRendererTest.kt
@@ -27,6 +27,7 @@
 import android.opengl.EGL14
 import android.opengl.EGLSurface
 import android.opengl.GLES20
+import android.opengl.Matrix
 import android.os.Build
 import android.os.Handler
 import android.os.HandlerThread
@@ -37,6 +38,7 @@
 import androidx.annotation.RequiresApi
 import androidx.annotation.WorkerThread
 import androidx.graphics.lowlatency.HardwareBufferRenderer
+import androidx.graphics.lowlatency.LineRenderer
 import androidx.graphics.lowlatency.RenderBuffer
 import androidx.graphics.lowlatency.SyncFenceCompat
 import androidx.graphics.opengl.egl.EGLManager
@@ -63,7 +65,6 @@
 @RunWith(AndroidJUnit4::class)
 @SmallTest
 class GLRendererTest {
-
     @Test
     fun testStartAfterStop() {
         with(GLRenderer()) {
@@ -812,6 +813,7 @@
         val teardownLatch = CountDownLatch(1)
         val glRenderer = GLRenderer().apply { start() }
         var renderBuffer: RenderBuffer? = null
+        var status: Boolean? = false
 
         val callbacks = object : HardwareBufferRenderer.RenderCallbacks {
             override fun obtainRenderBuffer(egl: EGLSpec): RenderBuffer =
@@ -832,7 +834,11 @@
                 GLES20.glFlush()
             }
 
-            override fun onDrawComplete(renderBuffer: RenderBuffer) {
+            override fun onDrawComplete(
+                renderBuffer: RenderBuffer,
+                syncFenceCompat: SyncFenceCompat?
+            ) {
+                status = syncFenceCompat?.await(3000)
                 renderLatch.countDown()
             }
         }
@@ -846,6 +852,11 @@
         var hardwareBuffer: HardwareBuffer? = null
         try {
             assertTrue(renderLatch.await(3000, TimeUnit.MILLISECONDS))
+            assert(status != null)
+            status?.let {
+                assertTrue(it)
+            }
+
             hardwareBuffer = renderBuffer?.hardwareBuffer
             if (hardwareBuffer != null) {
                 val colorSpace = ColorSpace.get(ColorSpace.Named.LINEAR_SRGB)
@@ -869,6 +880,114 @@
         }
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    fun testHardwareBufferRendererWithSyncFence() {
+        if (!deviceSupportsNativeAndroidFence()) {
+            // If the Android device does not support the corresponding
+            // EGL Extensions to obtain native Android fence objects from EGLSync
+            // instances then skip this test as we cannot guarantee consistency
+            // for front buffered rendering
+            return
+        }
+
+        val width = 10
+        val height = 10
+        val renderLatch = CountDownLatch(1)
+        val teardownLatch = CountDownLatch(1)
+
+        val glRenderer = GLRenderer().apply { start() }
+        var startTime = Long.MAX_VALUE
+        var signalTime = 0L
+
+        val renderer =
+            object : HardwareBufferRenderer.RenderCallbacks, GLRenderer.EGLContextCallback {
+                private val mMVPMatrix = FloatArray(16)
+                private val mLines = FloatArray(4)
+                private val mLineRenderer = LineRenderer()
+                var mRenderBuffer: RenderBuffer? = null
+
+                @WorkerThread
+                override fun onEGLContextCreated(eglManager: EGLManager) {
+                    mLineRenderer.initialize()
+                }
+
+                @WorkerThread
+                override fun onEGLContextDestroyed(eglManager: EGLManager) {
+                    mLineRenderer.release()
+                }
+
+                @WorkerThread
+                override fun obtainRenderBuffer(egl: EGLSpec): RenderBuffer {
+                    return if (mRenderBuffer != null) {
+                        mRenderBuffer!!
+                    } else {
+                        RenderBuffer(
+                            egl,
+                            HardwareBuffer.create(
+                                width,
+                                height,
+                                HardwareBuffer.RGBA_8888,
+                                1,
+                                HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE
+                            )
+                        ).also { mRenderBuffer = it }
+                    }
+                }
+
+                @WorkerThread
+                override fun onDraw(eglManager: EGLManager) {
+                    startTime = System.nanoTime()
+                    GLES20.glViewport(0, 0, width, height)
+                    assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+                    Matrix.orthoM(mMVPMatrix, 0, 0f, width.toFloat(), 0f, height.toFloat(), -1f, 1f)
+                    mLines[0] = 0f
+                    mLines[1] = 0f
+                    mLines[2] = 5f
+                    mLines[3] = 5f
+                    mLineRenderer.drawLines(mMVPMatrix, mLines)
+                    assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+                }
+
+                @WorkerThread
+                override fun onDrawComplete(
+                    renderBuffer: RenderBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    assertNotNull(syncFenceCompat)
+                    assertTrue(syncFenceCompat!!.isValid())
+
+                    assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+                    assertTrue(syncFenceCompat.await(3000))
+                    signalTime = syncFenceCompat.getSignalTime()
+
+                    renderLatch.countDown()
+                    assertTrue(syncFenceCompat.getSignalTime() < System.nanoTime())
+                    assertTrue(syncFenceCompat.getSignalTime() > startTime)
+                }
+            }
+
+        glRenderer.registerEGLContextCallback(renderer)
+        val hwBufferRenderer = HardwareBufferRenderer(renderer)
+        val renderTarget =
+            glRenderer.createRenderTarget(width, height, hwBufferRenderer)
+
+        renderTarget.requestRender()
+        assertEquals(GLES20.GL_NO_ERROR, GLES20.glGetError())
+
+        try {
+            assertTrue(renderLatch.await(3000, TimeUnit.MILLISECONDS))
+            assertTrue(startTime < signalTime)
+            assertTrue(signalTime < System.nanoTime())
+        } finally {
+            glRenderer.stop(true) {
+                teardownLatch.countDown()
+            }
+            assertTrue(teardownLatch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+
     /**
      * Helper method to create a GLTestActivity instance and progress it through the Activity
      * lifecycle to the resumed state so we can issue rendering commands into the corresponding
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncFenceCompatTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncFenceCompatTest.kt
index cac758d..60c06e7 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncFenceCompatTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SyncFenceCompatTest.kt
@@ -26,7 +26,9 @@
 import androidx.graphics.opengl.egl.EGLSpec
 import androidx.graphics.opengl.egl.EGLVersion
 import androidx.graphics.opengl.egl.supportsNativeAndroidFence
+import androidx.hardware.SyncFence
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertTrue
@@ -36,26 +38,28 @@
 
 @RunWith(AndroidJUnit4::class)
 @SmallTest
-@RequiresApi(Build.VERSION_CODES.KITKAT)
+@RequiresApi(Build.VERSION_CODES.O)
 class SyncFenceCompatTest {
     @Test
-    fun testRenderFenceCreate() {
+    fun testSyncFenceCompat_Create() {
         testEglManager {
             initializeWithDefaultConfig()
             if (supportsNativeAndroidFence()) {
                 val syncFenceCompat = SyncFenceCompat.createNativeSyncFence(this.eglSpec)
+                assert(syncFenceCompat.isValid())
                 syncFenceCompat.close()
             }
         }
     }
 
     @Test
-    fun testRenderFenceAwait() {
+    fun testSyncFenceCompat_Await() {
         testEglManager {
             initializeWithDefaultConfig()
             if (supportsNativeAndroidFence()) {
 
                 val syncFenceCompat = SyncFenceCompat.createNativeSyncFence(this.eglSpec)
+                assert(syncFenceCompat.isValid())
                 GLES20.glFlush()
                 assertTrue(syncFenceCompat.await(1000))
 
@@ -65,13 +69,12 @@
     }
 
     @Test
-    fun testRenderFenceAwaitForever() {
+    fun testSyncFenceCompat_AwaitForever() {
         testEglManager {
             initializeWithDefaultConfig()
             if (supportsNativeAndroidFence()) {
-
                 val syncFenceCompat = SyncFenceCompat.createNativeSyncFence(this.eglSpec)
-                GLES20.glFlush()
+                assert(syncFenceCompat.isValid())
                 assertTrue(syncFenceCompat.awaitForever())
 
                 syncFenceCompat.close()
@@ -79,6 +82,26 @@
         }
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+    fun testSyncFenceCompat_SignalTime() {
+        testEglManager {
+            initializeWithDefaultConfig()
+            if (supportsNativeAndroidFence()) {
+                val start = System.nanoTime()
+                val syncFenceCompat = SyncFenceCompat.createNativeSyncFence(this.eglSpec)
+                assertTrue(syncFenceCompat.isValid())
+                assertTrue(syncFenceCompat.getSignalTime() != SyncFence.SIGNAL_TIME_INVALID)
+                assertTrue(syncFenceCompat.awaitForever())
+
+                assertTrue(syncFenceCompat.getSignalTime() > start)
+                assertTrue(syncFenceCompat.getSignalTime() != SyncFenceCompat.SIGNAL_TIME_PENDING)
+
+                syncFenceCompat.close()
+            }
+        }
+    }
+
     // Helper method used in testing to initialize EGL and default
     // EGLConfig to the ARGB8888 configuration
     private fun EGLManager.initializeWithDefaultConfig() {
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlCompatTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlCompatTest.kt
index 8f7fec9..c4dd258 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlCompatTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlCompatTest.kt
@@ -295,8 +295,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -343,16 +343,16 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
 
                         val buffer2 =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.GREEN
                             )
                         assertNotNull(buffer2)
@@ -387,6 +387,114 @@
     }
 
     @Test
+    fun testTransactionSetBuffer_nullFence() {
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
+            .moveToState(
+                Lifecycle.State.CREATED
+            ).onActivity {
+                val callback = object : SurfaceHolderCallback() {
+                    override fun surfaceCreated(sh: SurfaceHolder) {
+                        val scCompat = SurfaceControlCompat
+                            .Builder()
+                            .setParent(it.getSurfaceView())
+                            .setName("SurfaceControlCompatTest")
+                            .build()
+
+                        // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
+                        val buffer =
+                            SurfaceControlUtils.getSolidBuffer(
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
+                                Color.BLUE
+                            )
+                        assertNotNull(buffer)
+
+                        SurfaceControlCompat.Transaction()
+                            .setBuffer(scCompat, buffer, null)
+                            .setVisibility(
+                                scCompat,
+                                true
+                            ).commit()
+                    }
+                }
+
+                it.addSurface(it.mSurfaceView, callback)
+            }
+
+        scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+            SurfaceControlUtils.validateOutput { bitmap ->
+                val coord = intArrayOf(0, 0)
+                it.mSurfaceView.getLocationOnScreen(coord)
+                Color.RED == bitmap.getPixel(coord[0], coord[1])
+            }
+        }
+    }
+
+    @Test
+    fun testTransactionSetBuffer_simpleFence() {
+        var eglManager: EGLManager? = null
+        val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
+            .moveToState(
+                Lifecycle.State.CREATED
+            ).onActivity {
+                val manager = EGLManager().apply {
+                    initialize()
+                    val config = loadConfig(EGLConfigAttributes.RGBA_8888)
+                    if (config == null) {
+                        fail("Config 8888 should be supported")
+                    }
+                    createContext(config!!)
+                }
+                eglManager = manager
+
+                val callback = object : SurfaceHolderCallback() {
+                    override fun surfaceCreated(sh: SurfaceHolder) {
+                        val scCompat = SurfaceControlCompat
+                            .Builder()
+                            .setParent(it.getSurfaceView())
+                            .setName("SurfaceControlCompatTest")
+                            .build()
+
+                        // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
+                        val buffer =
+                            SurfaceControlUtils.getSolidBuffer(
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
+                                Color.BLUE
+                            )
+                        assertNotNull(buffer)
+
+                        val fence = if (manager.supportsNativeAndroidFence()) {
+                            SyncFenceCompat.createNativeSyncFence(manager.eglSpec)
+                        } else {
+                            null
+                        }
+                        SurfaceControlCompat.Transaction()
+                            .setBuffer(scCompat, buffer, fence)
+                            .setVisibility(
+                                scCompat,
+                                true
+                            ).commit()
+                    }
+                }
+
+                it.addSurface(it.mSurfaceView, callback)
+            }
+
+        scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+            try {
+                SurfaceControlUtils.validateOutput { bitmap ->
+                    val coord = intArrayOf(0, 0)
+                    it.mSurfaceView.getLocationOnScreen(coord)
+                    Color.RED == bitmap.getPixel(coord[0], coord[1])
+                }
+            } finally {
+                eglManager?.release()
+            }
+        }
+    }
+
+    @Test
     fun testTransactionSetBuffer_nullCallback() {
         val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
             .moveToState(
@@ -403,8 +511,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -447,8 +555,8 @@
 
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.GREEN
                             )
                         assertNotNull(buffer)
@@ -456,8 +564,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer2 =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer2)
@@ -506,24 +614,24 @@
 
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.GREEN
                             )
                         assertNotNull(buffer)
 
                         val buffer2 =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.GREEN
                             )
                         assertNotNull(buffer2)
 
                         val buffer3 =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer3)
@@ -562,75 +670,6 @@
     }
 
     @Test
-    fun testTransactionSetBuffer_withSyncFence() {
-        val releaseLatch = CountDownLatch(1)
-        val egl = createAndSetupEGLManager(EGLSpec.V14)
-        if (egl.supportsNativeAndroidFence()) {
-            val syncFenceCompat = SyncFenceCompat.createNativeSyncFence(egl.eglSpec)
-            val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
-                .moveToState(
-                    Lifecycle.State.CREATED
-                ).onActivity {
-                    val callback = object : SurfaceHolderCallback() {
-                        override fun surfaceCreated(sh: SurfaceHolder) {
-                            val scCompat = SurfaceControlCompat
-                                .Builder()
-                                .setParent(it.getSurfaceView())
-                                .setName("SurfaceControlCompatTest")
-                                .build()
-
-                            val buffer =
-                                SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
-                                    Color.GREEN
-                                )
-                            assertNotNull(buffer)
-
-                            // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
-                            val buffer2 =
-                                SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
-                                    Color.BLUE
-                                )
-                            assertNotNull(buffer2)
-
-                            SurfaceControlCompat.Transaction()
-                                .setBuffer(
-                                    scCompat,
-                                    buffer,
-                                    syncFenceCompat,
-                                ) {
-                                    releaseLatch.countDown()
-                                }
-                                .setVisibility(scCompat, true)
-                                .commit()
-                            SurfaceControlCompat.Transaction()
-                                .setBuffer(scCompat, buffer2)
-                                .setVisibility(scCompat, true)
-                                .commit()
-                        }
-                    }
-
-                    it.addSurface(it.mSurfaceView, callback)
-                }
-
-            scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
-                assertTrue(releaseLatch.await(3000, TimeUnit.MILLISECONDS))
-                assertTrue(syncFenceCompat.await(3000))
-                SurfaceControlUtils.validateOutput { bitmap ->
-                    val coord = intArrayOf(0, 0)
-                    it.mSurfaceView.getLocationOnScreen(coord)
-                    Color.RED == bitmap.getPixel(coord[0], coord[1])
-                }
-
-                releaseEGLManager(egl)
-            }
-        }
-    }
-
-    @Test
     fun testTransactionSetVisibility_show() {
         val scenario = ActivityScenario.launch(SurfaceControlWrapperTestActivity::class.java)
             .moveToState(
@@ -647,8 +686,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -691,8 +730,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -743,8 +782,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -753,8 +792,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -800,8 +839,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -810,8 +849,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -857,8 +896,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -867,8 +906,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -907,13 +946,18 @@
                         SurfaceControlCompat.Transaction()
                             .setDamageRegion(
                                 scCompat,
-                                Region(0, 0, it.DEFAULT_WIDTH, it.DEFAULT_HEIGHT)
+                                Region(
+                                    0,
+                                    0,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT
+                                )
                             )
                             .setBuffer(
                                 scCompat,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -957,8 +1001,8 @@
                             .setBuffer(
                                 scCompat,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -995,8 +1039,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
 
@@ -1039,8 +1083,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlCompat.Transaction()
@@ -1082,8 +1126,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlCompat.Transaction()
@@ -1141,8 +1185,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlCompat.Transaction()
@@ -1182,8 +1226,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
 
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
index 2bafbee..80bfb12 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTest.kt
@@ -315,8 +315,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -372,16 +372,16 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
 
                         val buffer2 =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.GREEN
                             )
                         assertNotNull(buffer2)
@@ -433,8 +433,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -480,8 +480,8 @@
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer =
                             SurfaceControlUtils.getSolidBuffer(
-                                it.DEFAULT_WIDTH,
-                                it.DEFAULT_HEIGHT,
+                                SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                 Color.BLUE
                             )
                         assertNotNull(buffer)
@@ -536,8 +536,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -545,8 +545,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -594,8 +594,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -603,8 +603,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -652,8 +652,8 @@
                             .setBuffer(
                                 scCompat1,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -661,8 +661,8 @@
                             .setBuffer(
                                 scCompat2,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.GREEN
                                 )
                             )
@@ -703,13 +703,18 @@
                             .addTransactionCompletedListener(listener)
                             .setDamageRegion(
                                 scCompat,
-                                Region(0, 0, it.DEFAULT_WIDTH, it.DEFAULT_HEIGHT)
+                                Region(
+                                    0,
+                                    0,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT
+                                )
                             )
                             .setBuffer(
                                 scCompat,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -755,8 +760,8 @@
                             .setBuffer(
                                 scCompat,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -798,8 +803,8 @@
                             .setBuffer(
                                 scCompat,
                                 SurfaceControlUtils.getSolidBuffer(
-                                    it.DEFAULT_WIDTH,
-                                    it.DEFAULT_HEIGHT,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                                    SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                                     Color.BLUE
                                 )
                             )
@@ -838,8 +843,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlWrapper.Transaction()
@@ -883,8 +888,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlWrapper.Transaction()
@@ -929,8 +934,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlWrapper.Transaction()
@@ -991,8 +996,8 @@
 
                         // Buffer colorspace is RGBA, so Color.BLUE will be visually Red
                         val buffer = SurfaceControlUtils.getSolidBuffer(
-                            it.DEFAULT_WIDTH,
-                            it.DEFAULT_HEIGHT,
+                            SurfaceControlWrapperTestActivity.DEFAULT_WIDTH,
+                            SurfaceControlWrapperTestActivity.DEFAULT_HEIGHT,
                             Color.BLUE
                         )
                         SurfaceControlWrapper.Transaction()
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTestActivity.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTestActivity.kt
index 962cce7..b99dad2 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTestActivity.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/surface/SurfaceControlWrapperTestActivity.kt
@@ -27,8 +27,10 @@
     lateinit var mSurfaceView: SurfaceView
     lateinit var mFrameLayout: FrameLayout
     lateinit var mLayoutParams: FrameLayout.LayoutParams
-    var DEFAULT_WIDTH = 100
-    var DEFAULT_HEIGHT = 100
+    companion object {
+        val DEFAULT_WIDTH = 100
+        val DEFAULT_HEIGHT = 100
+    }
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
index e623c73..1089720 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/GLFrontBufferedRenderer.kt
@@ -71,7 +71,31 @@
      * be synchronized with the [SurfaceControlCompat.Transaction] to show/hide visibility of the
      * front buffered layer as well as updating double buffered layers
      */
-    private val mCallback = callback
+    private val mCallback = object : Callback<T> by callback {
+        @WorkerThread
+        override fun onDoubleBufferedLayerRenderComplete(
+            frontBufferedLayerSurfaceControl: SurfaceControlCompat,
+            transaction: SurfaceControlCompat.Transaction
+        ) {
+            mFrontBufferSyncStrategy.setVisible(false)
+            callback.onDoubleBufferedLayerRenderComplete(
+                frontBufferedLayerSurfaceControl,
+                transaction
+            )
+        }
+
+        @WorkerThread
+        override fun onFrontBufferedLayerRenderComplete(
+            frontBufferedLayerSurfaceControl: SurfaceControlCompat,
+            transaction: SurfaceControlCompat.Transaction
+        ) {
+            mFrontBufferSyncStrategy.setVisible(true)
+            callback.onFrontBufferedLayerRenderComplete(
+                frontBufferedLayerSurfaceControl,
+                transaction
+            )
+        }
+    }
 
     /**
      * [GLRenderer.EGLContextCallback]s used to release the corresponding [RenderBufferPool]
@@ -157,6 +181,12 @@
     private var mFrontBufferedLayerSurfaceControl: SurfaceControlCompat? = null
 
     /**
+     * [FrontBufferSyncStrategy] used for [HardwareBufferRenderer] to conditionally decide
+     * when to create a [SyncFenceCompat] for transaction calls.
+     */
+    private val mFrontBufferSyncStrategy: FrontBufferSyncStrategy
+
+    /**
      * Width of the layers to render. Only if the size changes to we re-initialize the internal
      * state of the [GLFrontBufferedRenderer]
      */
@@ -200,6 +230,17 @@
      */
     private var mIsReleased = false
 
+    /**
+     * Cached value to store what [HardwareBuffer] usage flags are supported on the device.
+     */
+    private val mHardwareBufferUsageFlags: Long
+
+    /**
+     * Flag to determine if [HardwareBuffer.USAGE_FRONT_BUFFER] is supported or not on
+     * the device
+     */
+    private val mSupportsFrontBufferUsage: Boolean
+
     init {
         mParentRenderLayer.setParentLayerCallbacks(mParentLayerCallback)
         val renderer = if (glRenderer == null) {
@@ -216,6 +257,13 @@
         mDoubleBufferedLayerRenderTarget =
             mParentRenderLayer.createRenderTarget(renderer, mCallback)
         mGLRenderer = renderer
+
+        mHardwareBufferUsageFlags = obtainHardwareBufferUsageFlags()
+
+        mSupportsFrontBufferUsage =
+            (mHardwareBufferUsageFlags and HardwareBuffer.USAGE_FRONT_BUFFER) != 0L
+
+        mFrontBufferSyncStrategy = FrontBufferSyncStrategy(mSupportsFrontBufferUsage)
     }
 
     internal fun update(width: Int, height: Int) {
@@ -233,7 +281,7 @@
                 width,
                 height,
                 format = HardwareBuffer.RGBA_8888,
-                usage = obtainHardwareBufferUsageFlags(),
+                usage = mHardwareBufferUsageFlags,
                 maxPoolSize = 5
             )
 
@@ -289,8 +337,10 @@
             mParentBufferParamQueue.add(param)
             mFrontBufferedRenderTarget?.requestRender()
         } else {
-            Log.w(TAG, "Attempt to render to front buffered layer when " +
-                "GLFrontBufferedRenderer has been released")
+            Log.w(
+                TAG, "Attempt to render to front buffered layer when " +
+                    "GLFrontBufferedRenderer has been released"
+            )
         }
     }
 
@@ -318,8 +368,10 @@
             mDoubleBufferedLayerRenderTarget?.requestRender()
             mFrontBufferedLayerRenderer?.clear()
         } else {
-            Log.w(TAG, "Attempt to render to the double buffered layer when " +
-                "GLFrontBufferedRenderer has been released")
+            Log.w(
+                TAG, "Attempt to render to the double buffered layer when " +
+                    "GLFrontBufferedRenderer has been released"
+            )
         }
     }
 
@@ -393,58 +445,68 @@
 
     private fun createFrontBufferedLayerRenderer(
         frontBufferedLayerSurfaceControl: SurfaceControlCompat
-    ) = HardwareBufferRenderer(
-        object : HardwareBufferRenderer.RenderCallbacks {
+    ): HardwareBufferRenderer {
+        return HardwareBufferRenderer(
+            object : HardwareBufferRenderer.RenderCallbacks {
 
-            @WorkerThread
-            override fun obtainRenderBuffer(egl: EGLSpec): RenderBuffer {
-                var buffer = mFrontLayerBuffer
-                if (buffer == null) {
-                    // Allocate and persist a RenderBuffer instance across frames
-                    buffer = mBufferPool?.obtain(egl).also { mFrontLayerBuffer = it }
-                       ?: throw IllegalArgumentException("Unable to obtain RenderBuffer")
+                @WorkerThread
+                override fun obtainRenderBuffer(egl: EGLSpec): RenderBuffer {
+                    var buffer = mFrontLayerBuffer
+                    if (buffer == null) {
+                        // Allocate and persist a RenderBuffer instance across frames
+                        buffer = mBufferPool?.obtain(egl).also { mFrontLayerBuffer = it }
+                            ?: throw IllegalArgumentException("Unable to obtain RenderBuffer")
+                    }
+                    return buffer
                 }
-                return buffer
-            }
 
-            @WorkerThread
-            override fun onDraw(eglManager: EGLManager) {
-                try {
-                    // Explicitly call remove in order to delineate between scenarios where
-                    // no parameters are provided and the consumer explicitly supports nullable
-                    // parameters.
-                    // If poll was used instead, we would not be able to determine if the nullable
-                    // parameter was because there were no items in the queue or the consumer
-                    // explicitly provided null as a placeholder
-                    mCallback.onDrawFrontBufferedLayer(eglManager, mFrontBufferQueueParams.remove())
-                } catch (_: NoSuchElementException) {
-                    // Skip rendering if we have been told to render but we do not have parameters
-                    // Because the call to render to the front buffer takes in a parameter we should
-                    // not run into this scenario.
+                @WorkerThread
+                override fun onDraw(eglManager: EGLManager) {
+                    try {
+                        // Explicitly call remove in order to delineate between scenarios where
+                        // no parameters are provided and the consumer explicitly supports nullable
+                        // parameters.
+                        // If poll was used instead, we would not be able to determine if the nullable
+                        // parameter was because there were no items in the queue or the consumer
+                        // explicitly provided null as a placeholder
+                        mCallback.onDrawFrontBufferedLayer(
+                            eglManager,
+                            mFrontBufferQueueParams.remove()
+                        )
+                    } catch (_: NoSuchElementException) {
+                        // Skip rendering if we have been told to render but we do not have parameters
+                        // Because the call to render to the front buffer takes in a parameter we should
+                        // not run into this scenario.
+                    }
                 }
-            }
 
-            @WorkerThread
-            override fun onDrawComplete(renderBuffer: RenderBuffer) {
-                val transaction = SurfaceControlCompat.Transaction()
-                    // Make this layer the top most layer
-                    .setLayer(frontBufferedLayerSurfaceControl, Integer.MAX_VALUE)
-                    .setBuffer(
-                        frontBufferedLayerSurfaceControl,
-                        renderBuffer.hardwareBuffer,
-                        null
+                @WorkerThread
+                override fun onDrawComplete(
+                    renderBuffer: RenderBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
+                    val transaction = SurfaceControlCompat.Transaction()
+                        // Make this layer the top most layer
+                        .setLayer(frontBufferedLayerSurfaceControl, Integer.MAX_VALUE)
+                        .setBuffer(
+                            frontBufferedLayerSurfaceControl,
+                            renderBuffer.hardwareBuffer,
+                            syncFenceCompat
+                        )
+                        .setVisibility(frontBufferedLayerSurfaceControl, true)
+                    mParentRenderLayer.buildReparentTransaction(
+                        frontBufferedLayerSurfaceControl, transaction
                     )
-                    .setVisibility(frontBufferedLayerSurfaceControl, true)
-                mParentRenderLayer.buildReparentTransaction(
-                    frontBufferedLayerSurfaceControl, transaction)
-                mCallback.onFrontBufferedLayerRenderComplete(
-                    frontBufferedLayerSurfaceControl,
-                    transaction
-                )
-                transaction.commit()
-            }
-        }
-    )
+                    mCallback.onFrontBufferedLayerRenderComplete(
+                        frontBufferedLayerSurfaceControl,
+                        transaction
+                    )
+                    transaction.commit()
+                }
+            },
+            mFrontBufferSyncStrategy
+        )
+    }
 
     private fun clearParamQueues() {
         mFrontBufferQueueParams.clear()
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/HardwareBufferRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/HardwareBufferRenderer.kt
index 288c3e6..14fb6b9 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/HardwareBufferRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/HardwareBufferRenderer.kt
@@ -34,7 +34,8 @@
  */
 @RequiresApi(Build.VERSION_CODES.O)
 internal class HardwareBufferRenderer(
-    private val hardwareBufferRendererCallbacks: RenderCallbacks
+    private val hardwareBufferRendererCallbacks: RenderCallbacks,
+    private val syncStrategy: SyncStrategy = SyncStrategy.ALWAYS
 ) : GLRenderer.RenderCallback {
 
     private val mClear = AtomicBoolean(false)
@@ -63,13 +64,12 @@
             } else {
                 hardwareBufferRendererCallbacks.onDraw(eglManager)
             }
-            GLES20.glFlush()
-            syncFenceCompat = egl.createNativeSyncFence()
 
-            syncFenceCompat.awaitForever()
+            syncFenceCompat = syncStrategy.createSyncFence(egl)
+
             // At this point the HardwareBuffer has the contents of the GL rendering
             // Create a surface Control transaction to dispatch this request
-            hardwareBufferRendererCallbacks.onDrawComplete(buffer)
+            hardwareBufferRendererCallbacks.onDrawComplete(buffer, syncFenceCompat)
         } finally {
             syncFenceCompat?.close()
         }
@@ -98,6 +98,71 @@
          * Callback when [onDraw] is complete and the contents of the draw
          * are reflected in the corresponding [HardwareBuffer]
          */
-        fun onDrawComplete(renderBuffer: RenderBuffer)
+        fun onDrawComplete(renderBuffer: RenderBuffer, syncFenceCompat: SyncFenceCompat?)
+    }
+}
+
+/**
+ * A strategy class for deciding how to utilize [SyncFenceCompat] within
+ * [HardwareBufferRenderer.RenderCallbacks]. SyncStrategy provides default strategies for
+ * usage:
+ *
+ * [SyncStrategy.ALWAYS] will always create a [SyncFenceCompat] to pass into the render
+ * callbacks for [HardwareBufferRenderer]
+ */
+internal interface SyncStrategy {
+    /**
+     * Conditionally generates a [SyncFenceCompat] based upon implementation.
+     *
+     * @param eglSpec an [EGLSpec] object to dictate the version of EGL and make EGL calls.
+     */
+    fun createSyncFence(eglSpec: EGLSpec): SyncFenceCompat?
+
+    companion object {
+        /**
+         * [SyncStrategy] that will always create a [SyncFenceCompat] object
+         */
+        @JvmField
+        val ALWAYS = object : SyncStrategy {
+            override fun createSyncFence(eglSpec: EGLSpec): SyncFenceCompat? {
+                return eglSpec.createNativeSyncFence()
+            }
+        }
+    }
+}
+
+/**
+ * [SyncStrategy] implementation that optimizes for front buffered rendering use cases.
+ * More specifically this attempts to avoid unnecessary synchronization overhead
+ * wherever possible.
+ *
+ * This will always provide a fence if the corresponding layer transitions from
+ * an invisible to a visible state. If the layer is already visible and front
+ * buffer usage flags are support on the device, then no fence is provided. If this
+ * flag is not supported, then a fence is created and "peeked" to ensure contents
+ * are flushed to the single buffer.
+ */
+internal class FrontBufferSyncStrategy(
+    private val supportsFrontBufferUsage: Boolean
+) : SyncStrategy {
+    private var mFrontBufferVisible: Boolean = false
+
+    fun isVisible(): Boolean = mFrontBufferVisible
+
+    fun setVisible(visibility: Boolean) {
+        mFrontBufferVisible = visibility
+    }
+
+    @RequiresApi(Build.VERSION_CODES.Q)
+    override fun createSyncFence(eglSpec: EGLSpec): SyncFenceCompat? {
+        return if (!isVisible()) {
+            eglSpec.createNativeSyncFence()
+        } else if (supportsFrontBufferUsage) {
+            return null
+        } else {
+            val fence = eglSpec.createNativeSyncFence()
+            fence.close()
+            return null
+        }
     }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
index 460209b..22fd3f29 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SurfaceViewRenderLayer.kt
@@ -81,14 +81,17 @@
                 }
 
                 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
-                override fun onDrawComplete(renderBuffer: RenderBuffer) {
+                override fun onDrawComplete(
+                    renderBuffer: RenderBuffer,
+                    syncFenceCompat: SyncFenceCompat?
+                ) {
                     val frontBufferedLayerSurfaceControl = mLayerCallback
-                            ?.getFrontBufferedLayerSurfaceControl()
+                        ?.getFrontBufferedLayerSurfaceControl()
                     val sc = mParentSurfaceControl
-                        // At this point the parentSurfaceControl should already be created
-                        // in the surfaceChanged callback, however, if for whatever reason this
-                        // was not the case, create the double buffered SurfaceControl now and cache
-                        // it
+                    // At this point the parentSurfaceControl should already be created
+                    // in the surfaceChanged callback, however, if for whatever reason this
+                    // was not the case, create the double buffered SurfaceControl now and cache
+                    // it
                         ?: createDoubleBufferedSurfaceControl().also {
                             mParentSurfaceControl = it
                         }
@@ -96,7 +99,7 @@
                         val transaction = SurfaceControlCompat.Transaction()
                             .setVisibility(frontBufferedLayerSurfaceControl, false)
                             .setVisibility(sc, true)
-                            .setBuffer(sc, renderBuffer.hardwareBuffer) {
+                            .setBuffer(sc, renderBuffer.hardwareBuffer, syncFenceCompat) {
                                 mLayerCallback?.getRenderBufferPool()?.release(renderBuffer)
                             }
 
@@ -106,11 +109,13 @@
                         )
                         transaction.commit()
                     } else {
-                        Log.e(TAG, "Error, no front buffered SurfaceControl available to " +
-                            "synchronize transaction with")
+                        Log.e(
+                            TAG, "Error, no front buffered SurfaceControl available to " +
+                                "synchronize transaction with"
+                        )
                     }
                 }
-        })
+            })
         surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
 
             override fun surfaceCreated(holder: SurfaceHolder) {
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceCompat.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceCompat.kt
index 149888b..a137794 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceCompat.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceCompat.kt
@@ -18,6 +18,7 @@
 
 import android.opengl.EGL14
 import android.opengl.EGL15
+import android.opengl.GLES20
 import android.os.Build
 import androidx.annotation.RequiresApi
 import androidx.graphics.opengl.egl.EGLSpec
@@ -55,12 +56,26 @@
                 val eglSync: EGLSyncKHR =
                     egl.eglCreateSyncKHR(EGLExt.EGL_SYNC_NATIVE_FENCE_ANDROID, null)
                         ?: throw IllegalArgumentException("Unable to create sync object")
+                GLES20.glFlush()
                 val syncFenceCompat = SyncFenceCompat(egl.eglDupNativeFenceFDANDROID(eglSync))
                 egl.eglDestroySyncKHR(eglSync)
 
                 syncFenceCompat
             }
         }
+
+        /**
+         * An invalid signal time. Represents either the signal time for a SyncFence that isn't
+         * valid (that is, [isValid] is `false`), or if an error occurred while attempting to
+         * retrieve the signal time.
+         */
+        const val SIGNAL_TIME_INVALID: Long = -1L
+
+        /**
+         * A pending signal time. This is equivalent to the max value of a long, representing an
+         * infinitely far point in the future.
+         */
+        const val SIGNAL_TIME_PENDING: Long = Long.MAX_VALUE
     }
 
     internal constructor(syncFence: SyncFence) {
@@ -92,6 +107,22 @@
     override fun close() {
         mImpl.close()
     }
+
+    /**
+     * Returns the time that the fence signaled in the [CLOCK_MONOTONIC] time domain.
+     * This returns [SyncFence.SIGNAL_TIME_INVALID] if the SyncFence is invalid.
+     * If the fence hasn't yet signaled, then [SyncFence.SIGNAL_TIME_PENDING] is returned.
+     */
+    @RequiresApi(Build.VERSION_CODES.O)
+    fun getSignalTime(): Long {
+        return mImpl.getSignalTime()
+    }
+
+    /**
+     * Checks if the SyncFence object is valid.
+     * @return `true` if it is valid, `false` otherwise
+     */
+    fun isValid() = mImpl.isValid()
 }
 
 /**
@@ -109,13 +140,15 @@
 @RequiresApi(Build.VERSION_CODES.TIRAMISU)
 internal class SyncFenceCompatVerificationHelper private constructor() {
     companion object {
+        private val mEmptyAttributes = longArrayOf(EGL14.EGL_NONE.toLong())
+
         @RequiresApi(Build.VERSION_CODES.TIRAMISU)
         @androidx.annotation.DoNotInline
         fun createSyncFenceCompatV33(): SyncFenceCompat {
             val display = EGL15.eglGetPlatformDisplay(
                 EGL15.EGL_PLATFORM_ANDROID_KHR,
                 EGL14.EGL_DEFAULT_DISPLAY.toLong(),
-                longArrayOf(EGL14.EGL_NONE.toLong()),
+                mEmptyAttributes,
                 0
             )
             if (display == EGL15.EGL_NO_DISPLAY) {
@@ -129,10 +162,10 @@
             val eglSync = EGL15.eglCreateSync(
                 display,
                 android.opengl.EGLExt.EGL_SYNC_NATIVE_FENCE_ANDROID,
-                longArrayOf(),
+                mEmptyAttributes,
                 0
             )
-
+            GLES20.glFlush()
             val syncFenceCompat = SyncFenceCompat(
                 android.opengl.EGLExt.eglDupNativeFenceFDANDROID(
                     display,
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceImpl.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceImpl.kt
index 66dc871..a0aa066 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceImpl.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceImpl.kt
@@ -16,6 +16,10 @@
 
 package androidx.graphics.lowlatency
 
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.hardware.SyncFence
+
 internal interface SyncFenceImpl {
     /**
      * Waits for a [SyncFenceImpl] to signal for up to the timeout duration
@@ -33,4 +37,18 @@
      * Close the [SyncFenceImpl]
      */
     fun close()
+
+    /**
+     * Returns the time that the fence signaled in the [CLOCK_MONOTONIC] time domain.
+     * This returns [SyncFence.SIGNAL_TIME_INVALID] if the SyncFence is invalid.
+     * If the fence hasn't yet signaled, then [SyncFence.SIGNAL_TIME_PENDING] is returned.
+     */
+    @RequiresApi(Build.VERSION_CODES.O)
+    fun getSignalTime(): Long
+
+    /**
+     * Checks if the SyncFence object is valid.
+     * @return `true` if it is valid, `false` otherwise
+     */
+    fun isValid(): Boolean
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV19.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV19.kt
index 1623412..2e29eb5 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV19.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV19.kt
@@ -44,4 +44,19 @@
     override fun close() {
         mSyncFence.close()
     }
+
+    /**
+     * See [SyncFenceImpl.getSignalTime]
+     */
+    @RequiresApi(Build.VERSION_CODES.O)
+    override fun getSignalTime(): Long {
+        return mSyncFence.getSignalTime()
+    }
+
+    /**
+     * See [SyncFenceImpl.isValid]
+     */
+    override fun isValid(): Boolean {
+        return mSyncFence.isValid()
+    }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV33.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV33.kt
index abcb1a0..1f039a3 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV33.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SyncFenceV33.kt
@@ -45,4 +45,19 @@
     override fun close() {
         mSyncFence.close()
     }
+
+    /**
+     * See [SyncFenceImpl.getSignalTime]
+     */
+    override fun getSignalTime(): Long {
+        return mSyncFence.signalTime
+    }
+
+    /**
+     * Checks if the SyncFence object is valid.
+     * @return `true` if it is valid, `false` otherwise
+     */
+    override fun isValid(): Boolean {
+        return mSyncFence.isValid
+    }
 }
\ No newline at end of file
diff --git a/graphics/graphics-core/src/main/java/androidx/hardware/SyncFence.kt b/graphics/graphics-core/src/main/java/androidx/hardware/SyncFence.kt
index 3977a83..3963976 100644
--- a/graphics/graphics-core/src/main/java/androidx/hardware/SyncFence.kt
+++ b/graphics/graphics-core/src/main/java/androidx/hardware/SyncFence.kt
@@ -14,22 +14,6 @@
  * limitations under the License.
  */
 
-/*
- * Copyright 2022 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.hardware
 
 import android.os.Build
diff --git a/health/connect/connect-client/src/main/java/androidx/health/platform/client/utils/IntentExt.kt b/health/connect/connect-client/src/main/java/androidx/health/platform/client/utils/IntentExt.kt
index fa639aa..21dbe1f 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/platform/client/utils/IntentExt.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/platform/client/utils/IntentExt.kt
@@ -23,11 +23,10 @@
 import androidx.annotation.RestrictTo
 import androidx.health.platform.client.proto.AbstractMessageLite
 
-fun Intent.putProtoMessages(name: String, messages: Collection<AbstractMessageLite<*, *>>) {
+fun Intent.putProtoMessages(name: String, messages: Collection<AbstractMessageLite<*, *>>): Intent =
     putByteArraysExtra(name = name, byteArrays = messages.map { it.toByteArray() })
-}
 
-fun Intent.putByteArraysExtra(name: String, byteArrays: Collection<ByteArray>) {
+fun Intent.putByteArraysExtra(name: String, byteArrays: Collection<ByteArray>): Intent =
     putExtra(
         name,
         Bundle(byteArrays.size).apply {
@@ -36,7 +35,6 @@
             }
         },
     )
-}
 
 fun <T : AbstractMessageLite<*, *>> Intent.getProtoMessages(
     name: String,
diff --git a/health/connect/connect-client/src/test/java/androidx/health/platform/client/utils/IntentExtTest.kt b/health/connect/connect-client/src/test/java/androidx/health/platform/client/utils/IntentExtTest.kt
index 58e95cb..0e117fb 100644
--- a/health/connect/connect-client/src/test/java/androidx/health/platform/client/utils/IntentExtTest.kt
+++ b/health/connect/connect-client/src/test/java/androidx/health/platform/client/utils/IntentExtTest.kt
@@ -18,6 +18,8 @@
 
 import android.content.Intent
 import android.os.Parcel
+import androidx.health.connect.client.impl.converters.records.protoDataType
+import androidx.health.platform.client.proto.DataProto.DataType
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -29,10 +31,12 @@
     @Test
     fun byteArrays_notEmpty() {
         val originalArrays = List(1024) { ByteArray(it, Int::toByte) }
-        var intent = Intent()
-        intent.putByteArraysExtra("key", originalArrays)
-        intent = intent.serializeDeserialize()
-        val deserializedArrays = intent.getByteArraysExtra("key")
+
+        val deserializedArrays =
+            Intent()
+                .putByteArraysExtra("key", originalArrays)
+                .serializeDeserialize()
+                .getByteArraysExtra("key")
 
         assertThat(deserializedArrays?.map(ByteArray::toList))
             .containsExactlyElementsIn(originalArrays.map(ByteArray::toList))
@@ -40,11 +44,11 @@
 
     @Test
     fun byteArrays_empty() {
-        val originalArrays = emptyList<ByteArray>()
-        var intent = Intent()
-        intent.putByteArraysExtra("key", originalArrays)
-        intent = intent.serializeDeserialize()
-        val deserializedArrays = intent.getByteArraysExtra("key")
+        val deserializedArrays =
+            Intent()
+                .putByteArraysExtra("key", emptyList())
+                .serializeDeserialize()
+                .getByteArraysExtra("key")
 
         assertThat(deserializedArrays).isEmpty()
     }
@@ -56,6 +60,37 @@
         assertThat(deserializedArrays).isNull()
     }
 
+    @Test
+    fun protoMessages_notEmpty() {
+        val originalMessages = List(128) { protoDataType("STEPS") }
+
+        val deserializedMessages =
+            Intent()
+                .putProtoMessages("key", originalMessages)
+                .serializeDeserialize()
+                .getProtoMessages("key", DataType::parseFrom)
+
+        assertThat(deserializedMessages).containsExactlyElementsIn(originalMessages)
+    }
+
+    @Test
+    fun protoMessages_empty() {
+        val deserializedMessages =
+            Intent()
+                .putProtoMessages("key", emptyList())
+                .serializeDeserialize()
+                .getProtoMessages("key", DataType::parseFrom)
+
+        assertThat(deserializedMessages).isEmpty()
+    }
+
+    @Test
+    fun protoMessages_null() {
+        val deserializedArrays = Intent().getProtoMessages("key", DataType::parseFrom)
+
+        assertThat(deserializedArrays).isNull()
+    }
+
     private fun Intent.serializeDeserialize(): Intent {
         val parcel = Parcel.obtain()
         writeToParcel(parcel, 0)
diff --git a/libraryversions.toml b/libraryversions.toml
index 34f03d2..44b8c15 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -140,7 +140,7 @@
 WINDOW = "1.1.0-alpha04"
 WINDOW_EXTENSIONS = "1.1.0-alpha02"
 WINDOW_SIDECAR = "1.0.0-rc01"
-WORK = "2.8.0-alpha05"
+WORK = "2.8.0-beta01"
 
 [groups]
 ACTIVITY = { group = "androidx.activity", atomicGroupVersion = "versions.ACTIVITY" }
diff --git a/media/media/src/main/java/android/support/v4/media/session/MediaControllerCompat.java b/media/media/src/main/java/android/support/v4/media/session/MediaControllerCompat.java
index 7f71344..1b5aeef 100644
--- a/media/media/src/main/java/android/support/v4/media/session/MediaControllerCompat.java
+++ b/media/media/src/main/java/android/support/v4/media/session/MediaControllerCompat.java
@@ -222,18 +222,7 @@
      * @param session The session to be controlled.
      */
     public MediaControllerCompat(Context context, @NonNull MediaSessionCompat session) {
-        if (session == null) {
-            throw new IllegalArgumentException("session must not be null");
-        }
-        mToken = session.getSessionToken();
-
-        if (Build.VERSION.SDK_INT >= 29) {
-            mImpl = new MediaControllerImplApi29(context, mToken);
-        } else if (Build.VERSION.SDK_INT >= 21) {
-            mImpl = new MediaControllerImplApi21(context, mToken);
-        } else {
-            mImpl = new MediaControllerImplBase(mToken);
-        }
+        this(context, session.getSessionToken());
     }
 
     /**
@@ -248,7 +237,9 @@
         }
         mToken = sessionToken;
 
-        if (android.os.Build.VERSION.SDK_INT >= 21) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            mImpl = new MediaControllerImplApi29(context, sessionToken);
+        } else if (Build.VERSION.SDK_INT >= 21) {
             mImpl = new MediaControllerImplApi21(context, sessionToken);
         } else {
             mImpl = new MediaControllerImplBase(sessionToken);
diff --git a/media2/media2-common/lint-baseline.xml b/media2/media2-common/lint-baseline.xml
index 37f296f..d4ef3f4 100644
--- a/media2/media2-common/lint-baseline.xml
+++ b/media2/media2-common/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="KotlinPropertyAccess"
diff --git a/navigation/navigation-ui/api/current.txt b/navigation/navigation-ui/api/current.txt
index 9551da2..27e99a9 100644
--- a/navigation/navigation-ui/api/current.txt
+++ b/navigation/navigation-ui/api/current.txt
@@ -11,6 +11,7 @@
     method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
     method public androidx.customview.widget.Openable? getOpenableLayout();
     method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
     property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
     property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
     property public final androidx.customview.widget.Openable? openableLayout;
diff --git a/navigation/navigation-ui/api/public_plus_experimental_current.txt b/navigation/navigation-ui/api/public_plus_experimental_current.txt
index 62b5ce4..7cb97e2 100644
--- a/navigation/navigation-ui/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-ui/api/public_plus_experimental_current.txt
@@ -11,6 +11,7 @@
     method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
     method public androidx.customview.widget.Openable? getOpenableLayout();
     method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
     property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
     property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
     property public final androidx.customview.widget.Openable? openableLayout;
diff --git a/navigation/navigation-ui/api/restricted_current.txt b/navigation/navigation-ui/api/restricted_current.txt
index 9551da2..27e99a9 100644
--- a/navigation/navigation-ui/api/restricted_current.txt
+++ b/navigation/navigation-ui/api/restricted_current.txt
@@ -11,6 +11,7 @@
     method public androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? getFallbackOnNavigateUpListener();
     method public androidx.customview.widget.Openable? getOpenableLayout();
     method public java.util.Set<java.lang.Integer> getTopLevelDestinations();
+    method public boolean isTopLevelDestination(androidx.navigation.NavDestination destination);
     property @Deprecated public final androidx.drawerlayout.widget.DrawerLayout? drawerLayout;
     property public final androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener? fallbackOnNavigateUpListener;
     property public final androidx.customview.widget.Openable? openableLayout;
diff --git a/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/AppBarConfigurationTest.kt b/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/AppBarConfigurationTest.kt
index c2576ae..83c849d 100644
--- a/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/AppBarConfigurationTest.kt
+++ b/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/AppBarConfigurationTest.kt
@@ -17,10 +17,14 @@
 package androidx.navigation.ui
 
 import android.content.Context
+import androidx.appcompat.widget.Toolbar
 import androidx.drawerlayout.widget.DrawerLayout
 import androidx.navigation.NavController
+import androidx.navigation.NavDestinationBuilder
+import androidx.navigation.NavHostController
 import androidx.navigation.createGraph
 import androidx.navigation.plusAssign
+import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.platform.app.InstrumentationRegistry
@@ -90,4 +94,124 @@
         assertThat(appBarConfiguration.fallbackOnNavigateUpListener)
             .isEqualTo(onNavigateUpListener)
     }
+
+    @UiThreadTest
+    @Test
+    fun testIsTopLevelDestination_menuItemAsNestedGraph() {
+        val navController = NavHostController(context)
+        val navigator = TestNavigator()
+        navController.apply {
+            navigatorProvider.addNavigator(navigator)
+            setGraph(R.navigation.simple_graph)
+        }
+
+        val toolbar = Toolbar(context).apply {
+            inflateMenu(R.menu.menu)
+        }
+        val appBarConfig = AppBarConfiguration.Builder(
+            topLevelMenu = toolbar.menu
+        ).build()
+        // start destination of menu_item_graph, a nested graph (and start dest) inside simple_graph
+        assertThat(navController.currentDestination?.id).isEqualTo(
+            R.id.itemHome
+        )
+        // start destination of menu_item_graph which should be a topLevelDestination
+        assertThat(
+            appBarConfig.isTopLevelDestination(
+                navController.currentDestination!!
+            )
+        ).isTrue()
+        // non-starting destination within menu_item_graph
+        assertThat(
+            appBarConfig.isTopLevelDestination(
+                navController.currentDestination!!.parent!!.findNode(R.id.itemSecondDestination)!!
+            )
+        ).isFalse()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testIsTopLevelDestination_menuItemAsIndividualItem() {
+        val navController = NavHostController(context)
+        val navigator = TestNavigator()
+        navController.apply {
+            navigatorProvider.addNavigator(navigator)
+            setGraph(R.navigation.simple_graph)
+        }
+
+        val toolbar = Toolbar(context).apply {
+            inflateMenu(R.menu.menu)
+        }
+        val appBarConfig = AppBarConfiguration.Builder(
+            topLevelMenu = toolbar.menu
+        ).build()
+
+        // menu_item_graph is a NavGraph. The graph id itself should not be a top level destination.
+        assertThat(
+            appBarConfig.isTopLevelDestination(
+                navController.graph.findNode(R.id.menu_item_graph)!!
+            )
+        ).isFalse()
+
+        // menu_item2 which is not a graph. Even though it is not the startDestination of
+        // its parent (simple_graph), it should be added as a topLevelDestination
+        // via AppBarConfig.Builder(menu) constructor.
+        assertThat(
+            appBarConfig.isTopLevelDestination(
+                navController.graph.findNode(R.id.menu_item2)!!
+            )
+        ).isTrue()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testIsTopLevelDestination_simpleGraph() {
+        val navController = NavController(context)
+        val navGraph = navController.apply {
+            navigatorProvider += TestNavigator()
+        }.createGraph(startDestination = "1") {
+            test("1")
+            test("2")
+        }
+        navController.setGraph(navGraph, null)
+        val builder = AppBarConfiguration.Builder(navGraph)
+        val appBarConfiguration = builder.build()
+
+        assertThat(appBarConfiguration.isTopLevelDestination(
+            navController.graph.findNode("1")!!)
+        ).isTrue()
+        assertThat(
+            appBarConfiguration.isTopLevelDestination(navController.graph.findNode("2")!!)
+        ).isFalse()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testIsTopLevelDestination_fromDestinationIds() {
+        val navigator = TestNavigator()
+
+        val dest1 = NavDestinationBuilder(navigator, "1").build()
+        val dest2 = NavDestinationBuilder(navigator, "2").build()
+
+        val builder = AppBarConfiguration.Builder(dest1.id, dest2.id)
+        val appBarConfiguration = builder.build()
+
+        assertThat(appBarConfiguration.isTopLevelDestination(dest1)).isTrue()
+        assertThat(appBarConfiguration.isTopLevelDestination(dest2)).isTrue()
+    }
+
+    @UiThreadTest
+    @Test
+    fun testIsTopLevelDestination_fromSetOfDestinationIds() {
+        val navigator = TestNavigator()
+
+        val dest1 = NavDestinationBuilder(navigator, "1").build()
+        val dest2 = NavDestinationBuilder(navigator, "2").build()
+
+        val builder = AppBarConfiguration.Builder(setOf(dest1.id, dest2.id))
+        val appBarConfiguration = builder.build()
+
+        assertThat(appBarConfiguration.isTopLevelDestination(dest1)).isTrue()
+        assertThat(appBarConfiguration.isTopLevelDestination(dest2)).isTrue()
+    }
 }
diff --git a/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/NavigationUITest.kt b/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/NavigationUITest.kt
index 356161d..0796ff3 100644
--- a/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/NavigationUITest.kt
+++ b/navigation/navigation-ui/src/androidTest/java/androidx/navigation/ui/NavigationUITest.kt
@@ -23,18 +23,14 @@
 import androidx.core.content.res.TypedArrayUtils.getString
 import androidx.navigation.NavController
 import androidx.navigation.NavDestination
-import androidx.navigation.NavGraph
-import androidx.navigation.NavGraphNavigator
 import androidx.navigation.NavHostController
 import androidx.navigation.NavType
 import androidx.navigation.createGraph
-import androidx.navigation.ui.NavigationUI.matchDestinations
 import androidx.test.annotation.UiThreadTest
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import androidx.testutils.TestNavigator
-import androidx.testutils.TestNavigatorProvider
 import androidx.testutils.test
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
@@ -43,15 +39,6 @@
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class NavigationUITest {
-    @Test
-    fun matchDestinationsTest() {
-        val destination = TestNavigator().createDestination().apply {
-            id = 1
-            parent = NavGraph(NavGraphNavigator(TestNavigatorProvider()))
-        }
-
-        assertThat(destination.matchDestinations(setOf(1, 2))).isTrue()
-    }
 
     @UiThreadTest
     @Test
diff --git a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.kt b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.kt
index 9962d7b..3b2c798 100644
--- a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.kt
+++ b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AbstractAppBarOnDestinationChangedListener.kt
@@ -26,7 +26,6 @@
 import androidx.navigation.FloatingWindow
 import androidx.navigation.NavController
 import androidx.navigation.NavDestination
-import androidx.navigation.ui.NavigationUI.matchDestinations
 import java.lang.ref.WeakReference
 
 /**
@@ -36,9 +35,8 @@
  */
 internal abstract class AbstractAppBarOnDestinationChangedListener(
     private val context: Context,
-    configuration: AppBarConfiguration
+    private val configuration: AppBarConfiguration
 ) : NavController.OnDestinationChangedListener {
-    private val topLevelDestinations: Set<Int> = configuration.topLevelDestinations
     private val openableLayoutWeakReference = configuration.openableLayout?.run {
         WeakReference(this)
     }
@@ -68,7 +66,7 @@
             setTitle(label)
         }
 
-        val isTopLevelDestination = destination.matchDestinations(topLevelDestinations)
+        val isTopLevelDestination = configuration.isTopLevelDestination(destination)
         if (openableLayout == null && isTopLevelDestination) {
             setNavigationIcon(null, 0)
         } else {
diff --git a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AppBarConfiguration.kt b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AppBarConfiguration.kt
index 252f385..827a259b 100644
--- a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AppBarConfiguration.kt
+++ b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/AppBarConfiguration.kt
@@ -17,8 +17,11 @@
 
 import android.annotation.SuppressLint
 import android.view.Menu
+import android.view.MenuItem
 import androidx.customview.widget.Openable
 import androidx.drawerlayout.widget.DrawerLayout
+import androidx.navigation.NavDestination
+import androidx.navigation.NavDestination.Companion.hierarchy
 import androidx.navigation.NavGraph
 import androidx.navigation.NavGraph.Companion.findStartDestination
 import androidx.navigation.ui.AppBarConfiguration.OnNavigateUpListener
@@ -80,6 +83,31 @@
         } else null
 
     /**
+     * Determines whether a [NavDestination] is a top level destination in [AppBarConfiguration].
+     *
+     * Returns true if the [NavDestination] was added directly as a top level destination via
+     * [AppBarConfiguration.Builder] constructors such as
+     * `AppBarConfiguration.Builder(topLevelDestinationIds: Set<Int>)`.
+     * If destination was added with a [AppBarConfiguration.Builder] that could take in a graph,
+     * i.e. `AppBarConfiguration.Builder(NavGraph)` or`AppBarConfiguration.Builder(Menu)`, this
+     * helper will return true if the destination is the start destination of a graph
+     * (including nested graphs i.e. [MenuItem] that are also [NavGraph]), or an individual
+     * [MenuItem] within the [Menu].
+     *
+     * @param destination the [NavDestination] to check whether it is a topLevelDestination
+     */
+    public fun isTopLevelDestination(destination: NavDestination): Boolean {
+        return destination.hierarchy.any { parent ->
+            when (parent.id in topLevelDestinations) {
+                true -> if (parent is NavGraph) {
+                            destination.id == parent.findStartDestination().id
+                        } else true
+                else -> false
+            }
+        }
+    }
+
+    /**
      * The Builder class for constructing new [AppBarConfiguration] instances.
      */
     public class Builder {
diff --git a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt
index 920eff2..9a5a17e 100644
--- a/navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt
+++ b/navigation/navigation-ui/src/main/java/androidx/navigation/ui/NavigationUI.kt
@@ -205,9 +205,8 @@
     ): Boolean {
         val openableLayout = configuration.openableLayout
         val currentDestination = navController.currentDestination
-        val topLevelDestinations = configuration.topLevelDestinations
         return if (openableLayout != null && currentDestination != null &&
-            currentDestination.matchDestinations(topLevelDestinations)
+            configuration.isTopLevelDestination(currentDestination)
         ) {
             openableLayout.open()
             true
@@ -708,13 +707,4 @@
     @JvmStatic
     internal fun NavDestination.matchDestination(@IdRes destId: Int): Boolean =
         hierarchy.any { it.id == destId }
-
-    /**
-     * Determines whether the given `destinationIds` match the NavDestination. This
-     * handles both the default case (the destination's id is in the given ids) and the nested
-     * case where the given ids is a parent/grandparent/etc of the destination.
-     */
-    @JvmStatic
-    internal fun NavDestination.matchDestinations(destinationIds: Set<Int?>): Boolean =
-        hierarchy.any { destinationIds.contains(it.id) }
 }
diff --git a/navigation/navigation-ui/src/main/res/menu/menu.xml b/navigation/navigation-ui/src/main/res/menu/menu.xml
new file mode 100644
index 0000000..245cf19
--- /dev/null
+++ b/navigation/navigation-ui/src/main/res/menu/menu.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2019, 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.
+  -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/menu_item_graph"
+        android:title="menu_item1_title" />
+    <item
+        android:id="@+id/menu_item2"
+        android:title="menu_item2_title" />
+</menu>
diff --git a/navigation/navigation-ui/src/main/res/navigation/menu_item_graph.xml b/navigation/navigation-ui/src/main/res/navigation/menu_item_graph.xml
new file mode 100644
index 0000000..4a65edc
--- /dev/null
+++ b/navigation/navigation-ui/src/main/res/navigation/menu_item_graph.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2019, 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.
+  -->
+
+<navigation
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/menu_item_graph"
+    app:startDestination="@+id/itemHome">
+
+    <test
+        android:id="@+id/itemHome"
+        android:name="androidx.navigation.ui.androidTest.EmptyFragment">
+        <action
+            android:id="@+id/itemHome_to_itemSecondDestination"
+            app:destination="@id/itemSecondDestination" />
+    </test>
+    <test
+        android:id="@+id/itemSecondDestination"
+        android:name="androidx.navigation.ui.androidTest.EmptyFragment">
+    </test>
+</navigation>
diff --git a/navigation/navigation-ui/src/main/res/navigation/simple_graph.xml b/navigation/navigation-ui/src/main/res/navigation/simple_graph.xml
new file mode 100644
index 0000000..1fd0cd2
--- /dev/null
+++ b/navigation/navigation-ui/src/main/res/navigation/simple_graph.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2019, 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.
+  -->
+<navigation
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/simple_graph"
+    app:startDestination="@+id/menu_item_graph">
+
+    <test
+        android:id="@+id/menu_item2"
+        android:name="androidx.navigation.ui.androidTest.EmptyFragment">
+    </test>
+
+    <include app:graph="@navigation/menu_item_graph"/>
+</navigation>
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
index 01935b5..4c4aba2 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/GridLayoutManager.java
@@ -964,6 +964,9 @@
         /**
          * Returns the final span index of the provided position.
          * <p>
+         * If {@link #getOrientation()} is {@link #VERTICAL}, this is a column value.
+         * If {@link #getOrientation()} is {@link #HORIZONTAL}, this is a row value.
+         * <p>
          * If you have a faster way to calculate span index for your items, you should override
          * this method. Otherwise, you should enable span index cache
          * ({@link #setSpanIndexCacheEnabled(boolean)}) for better performance. When caching is
@@ -1040,6 +1043,9 @@
         /**
          * Returns the index of the group this position belongs.
          * <p>
+         * If {@link #getOrientation()} is {@link #VERTICAL}, this is a row value.
+         * If {@link #getOrientation()} is {@link #HORIZONTAL}, this is a column value.
+         * <p>
          * For example, if grid has 3 columns and each item occupies 1 span, span group index
          * for item 1 will be 0, item 5 will be 1.
          *
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
index ae1c0fb..83ccfd4 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
@@ -215,7 +215,6 @@
      * @see hasNoteContainingMatch
      */
     fun hasWarningContainingMatch(expectedPattern: String): DiagnosticMessagesSubject {
-        shouldSucceed = false
         return hasDiagnosticWithPattern(
             kind = Diagnostic.Kind.WARNING,
             expectedPattern = expectedPattern,
@@ -262,7 +261,6 @@
      * @see hasWarningContainingMatch
      */
     fun hasNoteContainingMatch(expectedPattern: String): DiagnosticMessagesSubject {
-        shouldSucceed = false
         return hasDiagnosticWithPattern(
             kind = Diagnostic.Kind.NOTE,
             expectedPattern = expectedPattern,
diff --git a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/DiagnosticsTest.kt b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/DiagnosticsTest.kt
index 30e21f1..7ded92a 100644
--- a/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/DiagnosticsTest.kt
+++ b/room/room-compiler-processing-testing/src/test/java/androidx/room/compiler/processing/util/DiagnosticsTest.kt
@@ -39,17 +39,45 @@
             }
             invocation.assertCompilationResult {
                 hasNote("note 1")
-                hasWarning("warn 1")
-                hasError("error 1")
+                assertThat(shouldSucceed).isTrue()
                 hasNoteContaining("ote")
-                hasWarningContaining("arn")
-                hasErrorContaining("rror")
+                assertThat(shouldSucceed).isTrue()
                 hasNoteContainingMatch("ote")
-                hasWarningContainingMatch("arn")
-                hasErrorContainingMatch("rror")
                 hasNoteContainingMatch("^note \\d$")
+                assertThat(shouldSucceed).isTrue()
+
+                hasWarning("warn 1")
+                assertThat(shouldSucceed).isTrue()
+                hasWarningContaining("arn")
+                assertThat(shouldSucceed).isTrue()
+                hasWarningContainingMatch("arn")
                 hasWarningContainingMatch("^warn \\d$")
+                assertThat(shouldSucceed).isTrue()
+
+                hasError("error 1")
+                assertThat(shouldSucceed).isFalse()
+                hasErrorContaining("rror")
+                assertThat(shouldSucceed).isFalse()
+                hasErrorContainingMatch("rror")
                 hasErrorContainingMatch("^error \\d$")
+                assertThat(shouldSucceed).isFalse()
+
+                hasNote("note 1")
+                assertThat(shouldSucceed).isFalse()
+                hasNoteContaining("ote")
+                assertThat(shouldSucceed).isFalse()
+                hasNoteContainingMatch("ote")
+                hasNoteContainingMatch("^note \\d$")
+                assertThat(shouldSucceed).isFalse()
+
+                hasWarning("warn 1")
+                assertThat(shouldSucceed).isFalse()
+                hasWarningContaining("arn")
+                assertThat(shouldSucceed).isFalse()
+                hasWarningContainingMatch("arn")
+                hasWarningContainingMatch("^warn \\d$")
+                assertThat(shouldSucceed).isFalse()
+
                 // these should fail:
                 assertThat(
                     runCatching { hasNote("note") }.isFailure
diff --git a/room/room-migration/src/main/java/androidx/room/migration/bundle/FtsEntityBundle.kt b/room/room-migration/src/main/java/androidx/room/migration/bundle/FtsEntityBundle.kt
index b5e8ed9..ec1c6ed 100644
--- a/room/room-migration/src/main/java/androidx/room/migration/bundle/FtsEntityBundle.kt
+++ b/room/room-migration/src/main/java/androidx/room/migration/bundle/FtsEntityBundle.kt
@@ -60,6 +60,7 @@
         emptyList()
     )
 
+    @Transient
     private val SHADOW_TABLE_NAME_SUFFIXES = listOf(
         "_content",
         "_segdir",
@@ -92,6 +93,7 @@
      * Gets the list of shadow table names corresponding to the FTS virtual table.
      * @return the list of names.
      */
+    @delegate:Transient
     public open val shadowTableNames: List<String> by lazy {
         val currentTable = this@FtsEntityBundle.tableName
         buildList {
diff --git a/room/room-runtime/src/test/java/androidx/room/BuilderTest.java b/room/room-runtime/src/test/java/androidx/room/BuilderTest.java
deleted file mode 100644
index ca73919..0000000
--- a/room/room-runtime/src/test/java/androidx/room/BuilderTest.java
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.instanceOf;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-
-import static java.util.Arrays.asList;
-
-import android.content.Context;
-
-import androidx.annotation.NonNull;
-import androidx.room.migration.Migration;
-import androidx.sqlite.db.SupportSQLiteDatabase;
-import androidx.sqlite.db.SupportSQLiteOpenHelper;
-import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory;
-
-import org.hamcrest.CoreMatchers;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.io.File;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-@SuppressWarnings({"ArraysAsListWithZeroOrOneArgument", "deprecation"})
-@RunWith(JUnit4.class)
-public class BuilderTest {
-    @Test(expected = IllegalArgumentException.class)
-    public void nullName() {
-        //noinspection ConstantConditions
-        Room.databaseBuilder(mock(Context.class), RoomDatabase.class, null).build();
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void emptyName() {
-        Room.databaseBuilder(mock(Context.class), RoomDatabase.class, "  ").build();
-    }
-
-    @Test
-    public void executors_setQueryExecutor() {
-        Executor executor = mock(Executor.class);
-
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .setQueryExecutor(executor)
-                .build();
-
-        assertThat(db.mDatabaseConfiguration.queryExecutor, is(executor));
-        assertThat(db.mDatabaseConfiguration.transactionExecutor, is(executor));
-    }
-
-    @Test
-    public void executors_setTransactionExecutor() {
-        Executor executor = mock(Executor.class);
-
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .setTransactionExecutor(executor)
-                .build();
-
-        assertThat(db.mDatabaseConfiguration.queryExecutor, is(executor));
-        assertThat(db.mDatabaseConfiguration.transactionExecutor, is(executor));
-    }
-
-    @Test
-    public void executors_setBothExecutors() {
-        Executor executor1 = mock(Executor.class);
-        Executor executor2 = mock(Executor.class);
-
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .setQueryExecutor(executor1)
-                .setTransactionExecutor(executor2)
-                .build();
-
-        assertThat(db.mDatabaseConfiguration.queryExecutor, is(executor1));
-        assertThat(db.mDatabaseConfiguration.transactionExecutor, is(executor2));
-    }
-
-    @Test
-    public void migration() {
-        Migration m1 = new EmptyMigration(0, 1);
-        Migration m2 = new EmptyMigration(1, 2);
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .addMigrations(m1, m2).build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
-        assertThat(migrations.findMigrationPath(0, 1), is(asList(m1)));
-        assertThat(migrations.findMigrationPath(1, 2), is(asList(m2)));
-        assertThat(migrations.findMigrationPath(0, 2), is(asList(m1, m2)));
-        assertThat(migrations.findMigrationPath(2, 0), CoreMatchers.<List<Migration>>nullValue());
-        assertThat(migrations.findMigrationPath(0, 3), CoreMatchers.<List<Migration>>nullValue());
-    }
-
-    @Test
-    public void migrationOverride() {
-        Migration m1 = new EmptyMigration(0, 1);
-        Migration m2 = new EmptyMigration(1, 2);
-        Migration m3 = new EmptyMigration(0, 1);
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .addMigrations(m1, m2, m3).build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
-        assertThat(migrations.findMigrationPath(0, 1), is(asList(m3)));
-        assertThat(migrations.findMigrationPath(1, 2), is(asList(m2)));
-        assertThat(migrations.findMigrationPath(0, 3), CoreMatchers.<List<Migration>>nullValue());
-    }
-
-    @Test
-    public void migrationJump() {
-        Migration m1 = new EmptyMigration(0, 1);
-        Migration m2 = new EmptyMigration(1, 2);
-        Migration m3 = new EmptyMigration(2, 3);
-        Migration m4 = new EmptyMigration(0, 3);
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .addMigrations(m1, m2, m3, m4).build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
-        assertThat(migrations.findMigrationPath(0, 3), is(asList(m4)));
-        assertThat(migrations.findMigrationPath(1, 3), is(asList(m2, m3)));
-    }
-
-    @Test
-    public void migrationDowngrade() {
-        Migration m1_2 = new EmptyMigration(1, 2);
-        Migration m2_3 = new EmptyMigration(2, 3);
-        Migration m3_4 = new EmptyMigration(3, 4);
-        Migration m3_2 = new EmptyMigration(3, 2);
-        Migration m2_1 = new EmptyMigration(2, 1);
-        TestDatabase db = Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                .addMigrations(m1_2, m2_3, m3_4, m3_2, m2_1).build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        RoomDatabase.MigrationContainer migrations = config.migrationContainer;
-        assertThat(migrations.findMigrationPath(3, 2), is(asList(m3_2)));
-        assertThat(migrations.findMigrationPath(3, 1), is(asList(m3_2, m2_1)));
-    }
-
-    @Test
-    public void skipMigration() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigration()
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.requireMigration, is(false));
-    }
-
-    @Test
-    public void fallbackToDestructiveMigrationFrom_calledOnce_migrationsNotRequiredForValues() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationFrom(1, 2).build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.isMigrationRequiredFrom(1), is(false));
-        assertThat(config.isMigrationRequiredFrom(2), is(false));
-
-        assertThat(config.isMigrationRequired(1, 2), is(false));
-        assertThat(config.isMigrationRequired(2, 3), is(false));
-    }
-
-    @Test
-    public void fallbackToDestructiveMigrationFrom_calledTwice_migrationsNotRequiredForValues() {
-        Context context = mock(Context.class);
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationFrom(1, 2)
-                .fallbackToDestructiveMigrationFrom(3, 4)
-                .build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-
-        assertThat(config.isMigrationRequiredFrom(1), is(false));
-        assertThat(config.isMigrationRequiredFrom(2), is(false));
-        assertThat(config.isMigrationRequiredFrom(3), is(false));
-        assertThat(config.isMigrationRequiredFrom(4), is(false));
-
-        assertThat(config.isMigrationRequired(1, 2), is(false));
-        assertThat(config.isMigrationRequired(2, 3), is(false));
-        assertThat(config.isMigrationRequired(3, 4), is(false));
-        assertThat(config.isMigrationRequired(4, 5), is(false));
-    }
-
-    @Test
-    public void isMigrationRequiredFrom_fallBackToDestructiveCalled_alwaysReturnsFalse() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigration()
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.isMigrationRequiredFrom(0), is(false));
-        assertThat(config.isMigrationRequiredFrom(1), is(false));
-        assertThat(config.isMigrationRequiredFrom(5), is(false));
-        assertThat(config.isMigrationRequiredFrom(12), is(false));
-        assertThat(config.isMigrationRequiredFrom(132), is(false));
-
-        // Upgrades
-        assertThat(config.isMigrationRequired(0, 1), is(false));
-        assertThat(config.isMigrationRequired(1, 2), is(false));
-        assertThat(config.isMigrationRequired(5, 6), is(false));
-        assertThat(config.isMigrationRequired(7, 12), is(false));
-        assertThat(config.isMigrationRequired(132, 150), is(false));
-
-        // Downgrades
-        assertThat(config.isMigrationRequired(1, 0), is(false));
-        assertThat(config.isMigrationRequired(2, 1), is(false));
-        assertThat(config.isMigrationRequired(6, 5), is(false));
-        assertThat(config.isMigrationRequired(7, 12), is(false));
-        assertThat(config.isMigrationRequired(150, 132), is(false));
-    }
-
-    @Test
-    public void isMigrationRequired_destructiveMigrationOnDowngrade_returnTrueWhenUpgrading() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationOnDowngrade()
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-
-        // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
-        assertThat(config.isMigrationRequiredFrom(0), is(true));
-        assertThat(config.isMigrationRequiredFrom(1), is(true));
-        assertThat(config.isMigrationRequiredFrom(5), is(true));
-        assertThat(config.isMigrationRequiredFrom(12), is(true));
-        assertThat(config.isMigrationRequiredFrom(132), is(true));
-
-        assertThat(config.isMigrationRequired(0, 1), is(true));
-        assertThat(config.isMigrationRequired(1, 2), is(true));
-        assertThat(config.isMigrationRequired(5, 6), is(true));
-        assertThat(config.isMigrationRequired(7, 12), is(true));
-        assertThat(config.isMigrationRequired(132, 150), is(true));
-    }
-
-    @Test
-    public void isMigrationRequired_destructiveMigrationOnDowngrade_returnFalseWhenDowngrading() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationOnDowngrade()
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-
-        // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
-        assertThat(config.isMigrationRequiredFrom(0), is(true));
-        assertThat(config.isMigrationRequiredFrom(1), is(true));
-        assertThat(config.isMigrationRequiredFrom(5), is(true));
-        assertThat(config.isMigrationRequiredFrom(12), is(true));
-        assertThat(config.isMigrationRequiredFrom(132), is(true));
-
-        assertThat(config.isMigrationRequired(1, 0), is(false));
-        assertThat(config.isMigrationRequired(2, 1), is(false));
-        assertThat(config.isMigrationRequired(6 , 5), is(false));
-        assertThat(config.isMigrationRequired(12, 7), is(false));
-        assertThat(config.isMigrationRequired(150, 132), is(false));
-    }
-
-    @Test
-    public void isMigrationRequiredFrom_byDefault_alwaysReturnsTrue() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.isMigrationRequiredFrom(0), is(true));
-        assertThat(config.isMigrationRequiredFrom(1), is(true));
-        assertThat(config.isMigrationRequiredFrom(5), is(true));
-        assertThat(config.isMigrationRequiredFrom(12), is(true));
-        assertThat(config.isMigrationRequiredFrom(132), is(true));
-
-        // Upgrades
-        assertThat(config.isMigrationRequired(0, 1), is(true));
-        assertThat(config.isMigrationRequired(1, 2), is(true));
-        assertThat(config.isMigrationRequired(5, 6), is(true));
-        assertThat(config.isMigrationRequired(7, 12), is(true));
-        assertThat(config.isMigrationRequired(132, 150), is(true));
-
-        // Downgrades
-        assertThat(config.isMigrationRequired(1, 0), is(true));
-        assertThat(config.isMigrationRequired(2, 1), is(true));
-        assertThat(config.isMigrationRequired(6, 5), is(true));
-        assertThat(config.isMigrationRequired(7, 12), is(true));
-        assertThat(config.isMigrationRequired(150, 132), is(true));
-    }
-
-    @Test
-    public void isMigrationRequiredFrom_fallBackToDestFromCalled_falseForProvidedValues() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationFrom(1, 4, 81)
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.isMigrationRequiredFrom(1), is(false));
-        assertThat(config.isMigrationRequiredFrom(4), is(false));
-        assertThat(config.isMigrationRequiredFrom(81), is(false));
-
-        assertThat(config.isMigrationRequired(1, 2), is(false));
-        assertThat(config.isMigrationRequired(4, 8), is(false));
-        assertThat(config.isMigrationRequired(81, 90), is(false));
-    }
-
-    @Test
-    public void isMigrationRequiredFrom_fallBackToDestFromCalled_trueForNonProvidedValues() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationFrom(1, 4, 81)
-                .build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.isMigrationRequiredFrom(2), is(true));
-        assertThat(config.isMigrationRequiredFrom(3), is(true));
-        assertThat(config.isMigrationRequiredFrom(73), is(true));
-
-        assertThat(config.isMigrationRequired(2, 3), is(true));
-        assertThat(config.isMigrationRequired(3, 4), is(true));
-        assertThat(config.isMigrationRequired(73, 80), is(true));
-    }
-
-    @Test
-    public void autoMigrationShouldBeAddedToMigrations_WhenManualDowngradeMigrationIsPresent() {
-        Context context = mock(Context.class);
-
-        BuilderTest_TestDatabase_Impl db =
-                (BuilderTest_TestDatabase_Impl) Room.inMemoryDatabaseBuilder(context,
-                                TestDatabase.class)
-                        .addMigrations(new EmptyMigration(1, 0))
-                        .build();
-
-        DatabaseConfiguration config = db.mDatabaseConfiguration;
-
-        assertThat(config.migrationContainer.findMigrationPath(1, 2), is(db.mAutoMigrations));
-    }
-
-    @Test
-    public void fallbackToDestructiveMigrationOnDowngrade_withProvidedValues_falseForDowngrades() {
-        Context context = mock(Context.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .fallbackToDestructiveMigrationOnDowngrade()
-                .fallbackToDestructiveMigrationFrom(2, 4).build();
-
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-
-        assertThat(config.isMigrationRequired(1, 2), is(true));
-        assertThat(config.isMigrationRequired(2, 3), is(false));
-        assertThat(config.isMigrationRequired(3, 4), is(true));
-        assertThat(config.isMigrationRequired(4, 5), is(false));
-        assertThat(config.isMigrationRequired(5, 6), is(true));
-
-        assertThat(config.isMigrationRequired(2, 1), is(false));
-        assertThat(config.isMigrationRequired(3, 2), is(false));
-        assertThat(config.isMigrationRequired(4, 3), is(false));
-        assertThat(config.isMigrationRequired(5, 4), is(false));
-        assertThat(config.isMigrationRequired(6, 5), is(false));
-    }
-
-    @Test
-    public void createBasic() {
-        Context context = mock(Context.class);
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class).build();
-        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config, notNullValue());
-        assertThat(config.context, is(context));
-        assertThat(config.name, is(nullValue()));
-        assertThat(config.allowMainThreadQueries, is(false));
-        assertThat(config.journalMode, is(RoomDatabase.JournalMode.TRUNCATE));
-        assertThat(config.sqliteOpenHelperFactory,
-                instanceOf(FrameworkSQLiteOpenHelperFactory.class));
-    }
-
-    @Test
-    public void createAllowMainThread() {
-        Context context = mock(Context.class);
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .allowMainThreadQueries()
-                .build();
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.allowMainThreadQueries, is(true));
-    }
-
-    @Test
-    public void createWriteAheadLogging() {
-        Context context = mock(Context.class);
-        TestDatabase db = Room.databaseBuilder(context, TestDatabase.class, "foo")
-                .setJournalMode(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING).build();
-        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config.journalMode, is(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING));
-    }
-
-    @Test
-    public void createWithFactoryAndVersion() {
-        Context context = mock(Context.class);
-        SupportSQLiteOpenHelper.Factory factory = mock(SupportSQLiteOpenHelper.Factory.class);
-
-        TestDatabase db = Room.inMemoryDatabaseBuilder(context, TestDatabase.class)
-                .openHelperFactory(factory)
-                .build();
-        assertThat(db, instanceOf(BuilderTest_TestDatabase_Impl.class));
-        DatabaseConfiguration config = ((BuilderTest_TestDatabase_Impl) db).mConfig;
-        assertThat(config, notNullValue());
-        assertThat(config.sqliteOpenHelperFactory, is(factory));
-    }
-
-    @Test
-    public void createFromAssetAndFromFile() {
-        Exception exception = null;
-        try {
-            Room.databaseBuilder(mock(Context.class), TestDatabase.class, "foo")
-                    .createFromAsset("assets-path")
-                    .createFromFile(new File("not-a--real-file"))
-                    .build();
-            fail("Build should have thrown");
-        } catch (Exception e) {
-            exception = e;
-        }
-        assertThat(exception, instanceOf(IllegalArgumentException.class));
-        assertThat(exception.getMessage(),
-                containsString(
-                        "More than one of createFromAsset(), createFromInputStream(), and "
-                                + "createFromFile() were called on this Builder"));
-    }
-
-    @Test
-    public void createInMemoryFromAsset() {
-        Exception exception = null;
-        try {
-            Room.inMemoryDatabaseBuilder(mock(Context.class), TestDatabase.class)
-                    .createFromAsset("assets-path")
-                    .build();
-            fail("Build should have thrown");
-        } catch (Exception e) {
-            exception = e;
-        }
-        assertThat(exception, instanceOf(IllegalArgumentException.class));
-        assertThat(exception.getMessage(),
-                containsString("Cannot create from asset or file for an in-memory"));
-    }
-
-    @Test
-    public void createInMemoryFromFile() {
-        Exception exception = null;
-        try {
-            Room.inMemoryDatabaseBuilder(mock(Context.class), TestDatabase.class)
-                    .createFromFile(new File("not-a--real-file"))
-                    .build();
-            fail("Build should have thrown");
-        } catch (Exception e) {
-            exception = e;
-        }
-        assertThat(exception, instanceOf(IllegalArgumentException.class));
-        assertThat(exception.getMessage(),
-                containsString("Cannot create from asset or file for an in-memory"));
-    }
-
-    abstract static class TestDatabase extends RoomDatabase {
-
-        DatabaseConfiguration mDatabaseConfiguration;
-
-        @Override
-        public void init(@NonNull DatabaseConfiguration configuration) {
-            super.init(configuration);
-            mDatabaseConfiguration = configuration;
-        }
-    }
-
-    static class EmptyMigration extends Migration {
-        EmptyMigration(int start, int end) {
-            super(start, end);
-        }
-
-        @Override
-        public void migrate(@NonNull SupportSQLiteDatabase database) {
-        }
-    }
-
-}
diff --git a/room/room-runtime/src/test/java/androidx/room/BuilderTest.kt b/room/room-runtime/src/test/java/androidx/room/BuilderTest.kt
new file mode 100644
index 0000000..cd2f9f1
--- /dev/null
+++ b/room/room-runtime/src/test/java/androidx/room/BuilderTest.kt
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2016 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
+
+import android.content.Context
+import androidx.room.Room.databaseBuilder
+import androidx.room.Room.inMemoryDatabaseBuilder
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteDatabase
+import androidx.sqlite.db.SupportSQLiteOpenHelper
+import androidx.sqlite.db.framework.FrameworkSQLiteOpenHelperFactory
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.util.concurrent.Executor
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.kotlin.mock
+
+@RunWith(JUnit4::class)
+class BuilderTest {
+    @Test
+    fun nullName() {
+        try {
+            databaseBuilder(
+                mock(), RoomDatabase::class.java, null
+            ).build()
+        } catch (e: IllegalArgumentException) {
+            assertThat(e.message).isEqualTo(
+                "Cannot build a database with null or empty name. If you are trying to create an " +
+                    "in memory database, use Room.inMemoryDatabaseBuilder"
+            )
+        }
+    }
+
+    @Test
+    fun emptyName() {
+        try {
+            databaseBuilder(
+                mock(), RoomDatabase::class.java, "  "
+            ).build()
+        } catch (e: IllegalArgumentException) {
+            assertThat(e.message).isEqualTo(
+                "Cannot build a database with null or empty name. If you are trying to create an " +
+                    "in memory database, use Room.inMemoryDatabaseBuilder"
+            )
+        }
+    }
+
+    @Test
+    fun executors_setQueryExecutor() {
+        val executor: Executor = mock()
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).setQueryExecutor(executor).build()
+
+        assertThat(db.mDatabaseConfiguration.queryExecutor).isEqualTo(executor)
+        assertThat(db.mDatabaseConfiguration.transactionExecutor).isEqualTo(executor)
+    }
+
+    @Test
+    fun executors_setTransactionExecutor() {
+        val executor: Executor = mock()
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).setTransactionExecutor(executor).build()
+
+        assertThat(db.mDatabaseConfiguration.queryExecutor).isEqualTo(executor)
+        assertThat(db.mDatabaseConfiguration.transactionExecutor).isEqualTo(executor)
+    }
+
+    @Test
+    fun executors_setBothExecutors() {
+        val executor1: Executor = mock()
+        val executor2: Executor = mock()
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).setQueryExecutor(executor1).setTransactionExecutor(executor2).build()
+
+        assertThat(db.mDatabaseConfiguration.queryExecutor).isEqualTo(executor1)
+        assertThat(db.mDatabaseConfiguration.transactionExecutor).isEqualTo(executor2)
+    }
+
+    @Test
+    fun migration() {
+        val m1: Migration = EmptyMigration(0, 1)
+        val m2: Migration = EmptyMigration(1, 2)
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).addMigrations(m1, m2).build()
+
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        val migrations = config.migrationContainer
+
+        assertThat(migrations.findMigrationPath(0, 1)).containsExactlyElementsIn(listOf(m1))
+        assertThat(migrations.findMigrationPath(1, 2)).containsExactlyElementsIn(listOf(m2))
+        assertThat(migrations.findMigrationPath(0, 2))
+            .containsExactlyElementsIn(listOf(m1, m2))
+        assertThat(migrations.findMigrationPath(2, 0)).isNull()
+        assertThat(migrations.findMigrationPath(0, 3)).isNull()
+    }
+
+    @Test
+    fun migrationOverride() {
+        val m1: Migration = EmptyMigration(0, 1)
+        val m2: Migration = EmptyMigration(1, 2)
+        val m3: Migration = EmptyMigration(0, 1)
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).addMigrations(m1, m2, m3).build()
+
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        val migrations = config.migrationContainer
+
+        assertThat(migrations.findMigrationPath(0, 1)).containsExactlyElementsIn(listOf(m3))
+        assertThat(migrations.findMigrationPath(1, 2)).containsExactlyElementsIn(listOf(m2))
+        assertThat(migrations.findMigrationPath(0, 3)).isNull()
+    }
+
+    @Test
+    fun migrationJump() {
+        val m1: Migration = EmptyMigration(0, 1)
+        val m2: Migration = EmptyMigration(1, 2)
+        val m3: Migration = EmptyMigration(2, 3)
+        val m4: Migration = EmptyMigration(0, 3)
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        ).addMigrations(m1, m2, m3, m4).build()
+
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        val migrations = config.migrationContainer
+
+        assertThat(migrations.findMigrationPath(0, 3)).containsExactlyElementsIn(listOf(m4))
+        assertThat(migrations.findMigrationPath(1, 3))
+            .containsExactlyElementsIn(listOf(m2, m3))
+    }
+
+    @Test
+    fun migrationDowngrade() {
+        val m1_2: Migration = EmptyMigration(1, 2)
+        val m2_3: Migration = EmptyMigration(2, 3)
+        val m3_4: Migration = EmptyMigration(3, 4)
+        val m3_2: Migration = EmptyMigration(3, 2)
+        val m2_1: Migration = EmptyMigration(2, 1)
+        val db = databaseBuilder(
+            mock(), TestDatabase::class.java, "foo"
+        )
+            .addMigrations(m1_2, m2_3, m3_4, m3_2, m2_1).build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        val migrations = config.migrationContainer
+        assertThat(migrations.findMigrationPath(3, 2))
+            .containsExactlyElementsIn(listOf(m3_2))
+        assertThat(migrations.findMigrationPath(3, 1))
+            .containsExactlyElementsIn(listOf(m3_2, m2_1))
+    }
+
+    @Test
+    fun skipMigration() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigration()
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.requireMigration).isFalse()
+    }
+
+    @Test
+    fun fallbackToDestructiveMigrationFrom_calledOnce_migrationsNotRequiredForValues() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationFrom(1, 2).build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.isMigrationRequired(1, 2)).isFalse()
+        assertThat(config.isMigrationRequired(2, 3)).isFalse()
+    }
+
+    @Test
+    fun fallbackToDestructiveMigrationFrom_calledTwice_migrationsNotRequiredForValues() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationFrom(1, 2)
+            .fallbackToDestructiveMigrationFrom(3, 4)
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.isMigrationRequired(1, 2)).isFalse()
+        assertThat(config.isMigrationRequired(2, 3)).isFalse()
+        assertThat(config.isMigrationRequired(3, 4)).isFalse()
+        assertThat(config.isMigrationRequired(4, 5)).isFalse()
+    }
+
+    @Test
+    fun isMigrationRequiredFrom_fallBackToDestructiveCalled_alwaysReturnsFalse() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigration()
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+
+        assertThat(config.isMigrationRequired(0, 1)).isFalse()
+        assertThat(config.isMigrationRequired(1, 2)).isFalse()
+        assertThat(config.isMigrationRequired(5, 6)).isFalse()
+        assertThat(config.isMigrationRequired(7, 12)).isFalse()
+        assertThat(config.isMigrationRequired(132, 150)).isFalse()
+
+        assertThat(config.isMigrationRequired(1, 0)).isFalse()
+        assertThat(config.isMigrationRequired(2, 1)).isFalse()
+        assertThat(config.isMigrationRequired(6, 5)).isFalse()
+        assertThat(config.isMigrationRequired(7, 12)).isFalse()
+        assertThat(config.isMigrationRequired(150, 132)).isFalse()
+    }
+
+    // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
+    @Test
+    fun isMigrationRequired_destructiveMigrationOnDowngrade_returnTrueWhenUpgrading() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationOnDowngrade()
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+
+        // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
+        assertThat(config.isMigrationRequired(0, 1)).isTrue()
+        assertThat(config.isMigrationRequired(1, 2)).isTrue()
+        assertThat(config.isMigrationRequired(5, 6)).isTrue()
+        assertThat(config.isMigrationRequired(7, 12)).isTrue()
+        assertThat(config.isMigrationRequired(132, 150)).isTrue()
+    }
+
+    // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
+    @Test
+    fun isMigrationRequired_destructiveMigrationOnDowngrade_returnFalseWhenDowngrading() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationOnDowngrade()
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+
+        // isMigrationRequiredFrom doesn't know about downgrade only so it always returns true
+        assertThat(config.isMigrationRequired(1, 0)).isFalse()
+        assertThat(config.isMigrationRequired(2, 1)).isFalse()
+        assertThat(config.isMigrationRequired(6, 5)).isFalse()
+        assertThat(config.isMigrationRequired(12, 7)).isFalse()
+        assertThat(config.isMigrationRequired(150, 132)).isFalse()
+    }
+
+    @Test
+    fun isMigrationRequiredFrom_byDefault_alwaysReturnsTrue() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+
+        assertThat(config.isMigrationRequired(0, 1)).isTrue()
+        assertThat(config.isMigrationRequired(1, 2)).isTrue()
+        assertThat(config.isMigrationRequired(5, 6)).isTrue()
+        assertThat(config.isMigrationRequired(7, 12)).isTrue()
+        assertThat(config.isMigrationRequired(132, 150)).isTrue()
+
+        assertThat(config.isMigrationRequired(1, 0)).isTrue()
+        assertThat(config.isMigrationRequired(2, 1)).isTrue()
+        assertThat(config.isMigrationRequired(6, 5)).isTrue()
+        assertThat(config.isMigrationRequired(7, 12)).isTrue()
+        assertThat(config.isMigrationRequired(150, 132)).isTrue()
+    }
+
+    @Test
+    fun isMigrationRequiredFrom_fallBackToDestFromCalled_falseForProvidedValues() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationFrom(1, 4, 81)
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.isMigrationRequired(1, 2)).isFalse()
+        assertThat(config.isMigrationRequired(4, 8)).isFalse()
+        assertThat(config.isMigrationRequired(81, 90)).isFalse()
+    }
+
+    @Test
+    fun isMigrationRequiredFrom_fallBackToDestFromCalled_trueForNonProvidedValues() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationFrom(1, 4, 81)
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.isMigrationRequired(2, 3)).isTrue()
+        assertThat(config.isMigrationRequired(3, 4)).isTrue()
+        assertThat(config.isMigrationRequired(73, 80)).isTrue()
+    }
+
+    @Test
+    fun autoMigrationShouldBeAddedToMigrations_WhenManualDowngradeMigrationIsPresent() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(
+            context,
+            TestDatabase::class.java
+        )
+            .addMigrations(EmptyMigration(1, 0))
+            .build() as BuilderTest_TestDatabase_Impl
+        val config: DatabaseConfiguration = db.mDatabaseConfiguration
+        assertThat(
+            config.migrationContainer.findMigrationPath(1, 2)).isEqualTo((db.mAutoMigrations)
+        )
+    }
+
+    @Test
+    fun fallbackToDestructiveMigrationOnDowngrade_withProvidedValues_falseForDowngrades() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .fallbackToDestructiveMigrationOnDowngrade()
+            .fallbackToDestructiveMigrationFrom(2, 4).build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.isMigrationRequired(1, 2)).isTrue()
+        assertThat(config.isMigrationRequired(2, 3)).isFalse()
+        assertThat(config.isMigrationRequired(3, 4)).isTrue()
+        assertThat(config.isMigrationRequired(4, 5)).isFalse()
+        assertThat(config.isMigrationRequired(5, 6)).isTrue()
+        assertThat(config.isMigrationRequired(2, 1)).isFalse()
+        assertThat(config.isMigrationRequired(3, 2)).isFalse()
+        assertThat(config.isMigrationRequired(4, 3)).isFalse()
+        assertThat(config.isMigrationRequired(5, 4)).isFalse()
+        assertThat(config.isMigrationRequired(6, 5)).isFalse()
+    }
+
+    @Test
+    fun createBasic() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java).build()
+        assertThat(db).isInstanceOf(BuilderTest_TestDatabase_Impl::class.java)
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config).isNotNull()
+        assertThat(config.context).isEqualTo(context)
+        assertThat(config.name).isNull()
+        assertThat(config.allowMainThreadQueries).isFalse()
+        assertThat(config.journalMode).isEqualTo(RoomDatabase.JournalMode.TRUNCATE)
+        assertThat(config.sqliteOpenHelperFactory)
+            .isInstanceOf(FrameworkSQLiteOpenHelperFactory::class.java)
+    }
+
+    @Test
+    fun createAllowMainThread() {
+        val context: Context = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .allowMainThreadQueries()
+            .build()
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.allowMainThreadQueries).isTrue()
+    }
+
+    @Test
+    fun createWriteAheadLogging() {
+        val context: Context = mock()
+        val db = databaseBuilder(context, TestDatabase::class.java, "foo")
+            .setJournalMode(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING).build()
+        assertThat(db).isInstanceOf(BuilderTest_TestDatabase_Impl::class.java)
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config.journalMode).isEqualTo(RoomDatabase.JournalMode.WRITE_AHEAD_LOGGING)
+    }
+
+    @Test
+    fun createWithFactoryAndVersion() {
+        val context: Context = mock()
+        val factory: SupportSQLiteOpenHelper.Factory = mock()
+        val db = inMemoryDatabaseBuilder(context, TestDatabase::class.java)
+            .openHelperFactory(factory)
+            .build()
+        assertThat(db).isInstanceOf(BuilderTest_TestDatabase_Impl::class.java)
+        val config: DatabaseConfiguration = (db as BuilderTest_TestDatabase_Impl).mConfig
+        assertThat(config).isNotNull()
+        assertThat(config.sqliteOpenHelperFactory).isEqualTo(factory)
+    }
+
+    @Test
+    fun createFromAssetAndFromFile() {
+        var exception: Exception? = null
+        try {
+            databaseBuilder(
+                mock(),
+                TestDatabase::class.java,
+                "foo"
+            )
+                .createFromAsset("assets-path")
+                .createFromFile(File("not-a--real-file"))
+                .build()
+            Assert.fail("Build should have thrown")
+        } catch (e: Exception) {
+            exception = e
+        }
+        assertThat(exception).isInstanceOf(IllegalArgumentException::class.java)
+        assertThat(exception).hasMessageThat().contains("More than one of createFromAsset(), " +
+            "createFromInputStream(), and createFromFile() were called on this Builder")
+    }
+
+    @Test
+    fun createInMemoryFromAsset() {
+        var exception: Exception? = null
+        try {
+            inMemoryDatabaseBuilder(
+                mock(),
+                TestDatabase::class.java
+            )
+                .createFromAsset("assets-path")
+                .build()
+            Assert.fail("Build should have thrown")
+        } catch (e: Exception) {
+            exception = e
+        }
+        assertThat(exception).isInstanceOf(IllegalArgumentException::class.java)
+        assertThat(exception).hasMessageThat().contains(
+            "Cannot create from asset or file for an in-memory"
+        )
+    }
+
+    @Test
+    fun createInMemoryFromFile() {
+        var exception: Exception? = null
+        try {
+            inMemoryDatabaseBuilder(
+                mock(),
+                TestDatabase::class.java
+            )
+                .createFromFile(File("not-a--real-file"))
+                .build()
+            Assert.fail("Build should have thrown")
+        } catch (e: Exception) {
+            exception = e
+        }
+        assertThat(exception).isInstanceOf(IllegalArgumentException::class.java)
+        assertThat(exception).hasMessageThat().contains(
+            "Cannot create from asset or file for an in-memory"
+        )
+    }
+
+    internal abstract class TestDatabase : RoomDatabase() {
+        lateinit var mDatabaseConfiguration: DatabaseConfiguration
+        override fun init(configuration: DatabaseConfiguration) {
+            super.init(configuration)
+            mDatabaseConfiguration = configuration
+        }
+    }
+
+    internal class EmptyMigration(start: Int, end: Int) : Migration(start, end) {
+        override fun migrate(database: SupportSQLiteDatabase) {}
+    }
+}
diff --git a/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.java b/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.java
deleted file mode 100644
index f475782..0000000
--- a/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import androidx.annotation.NonNull;
-import androidx.room.migration.AutoMigrationSpec;
-import androidx.room.migration.Migration;
-import androidx.sqlite.db.SupportSQLiteOpenHelper;
-
-import org.mockito.Mockito;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-public class BuilderTest_TestDatabase_Impl extends BuilderTest.TestDatabase {
-    DatabaseConfiguration mConfig;
-    List<Migration> mAutoMigrations = Arrays.asList(new BuilderTest.EmptyMigration(1, 2));
-
-    @Override
-    public void init(DatabaseConfiguration configuration) {
-        super.init(configuration);
-        mConfig = configuration;
-    }
-
-    @Override
-    protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration config) {
-        return Mockito.mock(SupportSQLiteOpenHelper.class);
-    }
-
-    @Override
-    protected InvalidationTracker createInvalidationTracker() {
-        return Mockito.mock(InvalidationTracker.class);
-    }
-
-    @Override
-    public void clearAllTables() {
-    }
-
-    @NonNull
-    @Override
-    public List<Migration> getAutoMigrations(
-            @NonNull Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> autoMigrationSpecs
-    ) {
-        return mAutoMigrations;
-    }
-}
\ No newline at end of file
diff --git a/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.kt b/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.kt
new file mode 100644
index 0000000..482b0fa
--- /dev/null
+++ b/room/room-runtime/src/test/java/androidx/room/BuilderTest_TestDatabase_Impl.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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
+
+import androidx.room.migration.AutoMigrationSpec
+import androidx.room.migration.Migration
+import androidx.sqlite.db.SupportSQLiteOpenHelper
+import org.mockito.kotlin.mock
+
+internal class BuilderTest_TestDatabase_Impl : BuilderTest.TestDatabase() {
+    lateinit var mConfig: DatabaseConfiguration
+    var mAutoMigrations = listOf<Migration>(BuilderTest.EmptyMigration(1, 2))
+    override fun init(configuration: DatabaseConfiguration) {
+        super.init(configuration)
+        mConfig = configuration
+    }
+
+    override fun createOpenHelper(config: DatabaseConfiguration): SupportSQLiteOpenHelper {
+        return mock()
+    }
+
+    override fun createInvalidationTracker(): InvalidationTracker {
+        return mock()
+    }
+
+    override fun clearAllTables() {}
+    override fun getAutoMigrations(
+        autoMigrationSpecs: Map<Class<out AutoMigrationSpec>, AutoMigrationSpec>
+    ): List<Migration> {
+        return mAutoMigrations
+    }
+}
\ No newline at end of file
diff --git a/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.java b/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.java
deleted file mode 100644
index 2106fdb..0000000
--- a/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-
-import static androidx.room.InvalidationTracker.ObservedTableTracker.ADD;
-import static androidx.room.InvalidationTracker.ObservedTableTracker.NO_OP;
-import static androidx.room.InvalidationTracker.ObservedTableTracker.REMOVE;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.Arrays;
-
-@RunWith(JUnit4.class)
-public class ObservedTableTrackerTest {
-    private static final int TABLE_COUNT = 5;
-    private InvalidationTracker.ObservedTableTracker mTracker;
-
-    @Before
-    public void setup() {
-        mTracker = new InvalidationTracker.ObservedTableTracker(TABLE_COUNT);
-    }
-
-    @Test
-    public void basicAdd() {
-        mTracker.onAdded(2, 3);
-        assertThat(mTracker.getTablesToSync(), is(createResponse(2, ADD, 3, ADD)));
-    }
-
-    @Test
-    public void basicRemove() {
-        initState(2, 3);
-        mTracker.onRemoved(3);
-        assertThat(mTracker.getTablesToSync(), is(createResponse(3, REMOVE)));
-    }
-
-    @Test
-    public void noChange() {
-        initState(1, 3);
-        mTracker.onAdded(3);
-        assertThat(mTracker.getTablesToSync(), is(nullValue()));
-    }
-
-    @Test
-    public void multipleAdditionsDeletions() {
-        initState(2, 4);
-        mTracker.onAdded(2);
-        assertThat(mTracker.getTablesToSync(), is(nullValue()));
-        mTracker.onAdded(2, 4);
-        assertThat(mTracker.getTablesToSync(), is(nullValue()));
-        mTracker.onRemoved(2);
-        assertThat(mTracker.getTablesToSync(), is(nullValue()));
-        mTracker.onRemoved(2, 4);
-        assertThat(mTracker.getTablesToSync(), is(nullValue()));
-        mTracker.onAdded(1, 3);
-        mTracker.onRemoved(2, 4);
-        assertThat(mTracker.getTablesToSync(), is(
-                createResponse(1, ADD, 2, REMOVE, 3, ADD, 4, REMOVE)));
-    }
-
-    private void initState(int... tableIds) {
-        mTracker.onAdded(tableIds);
-        mTracker.getTablesToSync();
-    }
-
-    private static int[] createResponse(int... tuples) {
-        int[] result = new int[TABLE_COUNT];
-        Arrays.fill(result, NO_OP);
-        for (int i = 0; i < tuples.length; i += 2) {
-            result[tuples[i]] = tuples[i + 1];
-        }
-        return result;
-    }
-}
diff --git a/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.kt b/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.kt
new file mode 100644
index 0000000..10ac217
--- /dev/null
+++ b/room/room-runtime/src/test/java/androidx/room/ObservedTableTrackerTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2017 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
+
+import com.google.common.truth.Truth.assertThat
+import java.util.Arrays
+import kotlin.test.assertNull
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ObservedTableTrackerTest {
+    private lateinit var mTracker: InvalidationTracker.ObservedTableTracker
+    @Before
+    fun setup() {
+        mTracker = InvalidationTracker.ObservedTableTracker(TABLE_COUNT)
+    }
+
+    @Test
+    fun basicAdd() {
+        mTracker.onAdded(2, 3)
+        assertThat(
+            mTracker.getTablesToSync()
+        ).isEqualTo(
+            createResponse(
+                2,
+                InvalidationTracker.ObservedTableTracker.ADD,
+                3,
+                InvalidationTracker.ObservedTableTracker.ADD
+            )
+        )
+    }
+
+    @Test
+    fun basicRemove() {
+        initState(2, 3)
+        mTracker.onRemoved(3)
+        assertThat(
+            mTracker.getTablesToSync()
+        ).isEqualTo(
+            createResponse(3, InvalidationTracker.ObservedTableTracker.REMOVE)
+        )
+    }
+
+    @Test
+    fun noChange() {
+        initState(1, 3)
+        mTracker.onAdded(3)
+        assertNull(
+            mTracker.getTablesToSync()
+        )
+    }
+
+    @Test
+    fun multipleAdditionsDeletions() {
+        initState(2, 4)
+        mTracker.onAdded(2)
+        assertNull(
+            mTracker.getTablesToSync()
+        )
+        mTracker.onAdded(2, 4)
+        assertNull(
+            mTracker.getTablesToSync()
+        )
+        mTracker.onRemoved(2)
+        assertNull(
+            mTracker.getTablesToSync()
+        )
+        mTracker.onRemoved(2, 4)
+        assertNull(
+            mTracker.getTablesToSync()
+        )
+        mTracker.onAdded(1, 3)
+        mTracker.onRemoved(2, 4)
+        assertThat(
+            mTracker.getTablesToSync()
+        ).isEqualTo(
+            createResponse(
+                1,
+                InvalidationTracker.ObservedTableTracker.ADD,
+                2,
+                InvalidationTracker.ObservedTableTracker.REMOVE,
+                3,
+                InvalidationTracker.ObservedTableTracker.ADD,
+                4,
+                InvalidationTracker.ObservedTableTracker.REMOVE
+            )
+        )
+    }
+
+    private fun initState(vararg tableIds: Int) {
+        mTracker.onAdded(*tableIds)
+        mTracker.getTablesToSync()
+    }
+
+    companion object {
+        private const val TABLE_COUNT = 5
+        private fun createResponse(vararg tuples: Int): IntArray {
+            val result = IntArray(TABLE_COUNT)
+            Arrays.fill(result, InvalidationTracker.ObservedTableTracker.NO_OP)
+            var i = 0
+            while (i < tuples.size) {
+                result[tuples[i]] = tuples[i + 1]
+                i += 2
+            }
+            return result
+        }
+    }
+}
\ No newline at end of file
diff --git a/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.java b/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.java
deleted file mode 100644
index 0738a49..0000000
--- a/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright (C) 2017 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;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.sameInstance;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import androidx.sqlite.db.SupportSQLiteProgram;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-@RunWith(JUnit4.class)
-public class RoomSQLiteQueryTest {
-    @Before
-    public void clear() {
-        RoomSQLiteQuery.queryPool.clear();
-    }
-
-    @Test
-    public void acquireBasic() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 3);
-        assertThat(query.getSql(), is("abc"));
-        assertThat(query.getArgCount(), is(3));
-        assertThat(query.blobBindings.length, is(4));
-        assertThat(query.longBindings.length, is(4));
-        assertThat(query.stringBindings.length, is(4));
-        assertThat(query.doubleBindings.length, is(4));
-    }
-
-    @Test
-    public void acquireSameSizeAgain() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 3);
-        query.release();
-        assertThat(RoomSQLiteQuery.acquire("blah", 3), sameInstance(query));
-    }
-
-    @Test
-    public void acquireSameSizeWithoutRelease() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 3);
-        assertThat(RoomSQLiteQuery.acquire("fda", 3), not(sameInstance(query)));
-    }
-
-    @Test
-    public void bindings() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 6);
-        byte[] myBlob = new byte[3];
-        long myLong = 3L;
-        double myDouble = 7.0;
-        String myString = "ss";
-        query.bindBlob(1, myBlob);
-        query.bindLong(2, myLong);
-        query.bindNull(3);
-        query.bindDouble(4, myDouble);
-        query.bindString(5, myString);
-        query.bindNull(6);
-        SupportSQLiteProgram program = mock(SupportSQLiteProgram.class);
-        query.bindTo(program);
-
-        verify(program).bindBlob(1, myBlob);
-        verify(program).bindLong(2, myLong);
-        verify(program).bindNull(3);
-        verify(program).bindDouble(4, myDouble);
-        verify(program).bindString(5, myString);
-        verify(program).bindNull(6);
-    }
-
-    @Test
-    public void dontKeepSameSizeTwice() {
-        RoomSQLiteQuery query1 = RoomSQLiteQuery.acquire("abc", 3);
-        RoomSQLiteQuery query2 = RoomSQLiteQuery.acquire("zx", 3);
-        RoomSQLiteQuery query3 = RoomSQLiteQuery.acquire("qw", 0);
-
-        query1.release();
-        query2.release();
-        assertThat(RoomSQLiteQuery.queryPool.size(), is(1));
-
-        query3.release();
-        assertThat(RoomSQLiteQuery.queryPool.size(), is(2));
-    }
-
-    @Test
-    public void returnExistingForSmallerSize() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 3);
-        query.release();
-        assertThat(RoomSQLiteQuery.acquire("dsa", 2), sameInstance(query));
-    }
-
-    @Test
-    public void returnNewForBigger() {
-        RoomSQLiteQuery query = RoomSQLiteQuery.acquire("abc", 3);
-        query.release();
-        assertThat(RoomSQLiteQuery.acquire("dsa", 4), not(sameInstance(query)));
-    }
-
-    @Test
-    public void pruneCache() {
-        for (int i = 0; i < RoomSQLiteQuery.POOL_LIMIT; i++) {
-            RoomSQLiteQuery.acquire("dsdsa", i).release();
-        }
-        pruneCacheTest();
-    }
-
-    @Test
-    public void pruneCacheReverseInsertion() {
-        List<RoomSQLiteQuery> queries = new ArrayList<>();
-        for (int i = RoomSQLiteQuery.POOL_LIMIT - 1; i >= 0; i--) {
-            queries.add(RoomSQLiteQuery.acquire("dsdsa", i));
-        }
-        for (RoomSQLiteQuery query : queries) {
-            query.release();
-        }
-        pruneCacheTest();
-    }
-
-    private void pruneCacheTest() {
-        assertThat(RoomSQLiteQuery.queryPool.size(), is(RoomSQLiteQuery.POOL_LIMIT));
-        RoomSQLiteQuery.acquire("dsadsa", RoomSQLiteQuery.POOL_LIMIT + 1).release();
-        assertThat(RoomSQLiteQuery.queryPool.size(), is(RoomSQLiteQuery.DESIRED_POOL_SIZE));
-        Iterator<RoomSQLiteQuery> itr = RoomSQLiteQuery.queryPool.values().iterator();
-        for (int i = 0; i < RoomSQLiteQuery.DESIRED_POOL_SIZE; i++) {
-            assertThat(itr.next().getCapacity(), is(i));
-        }
-    }
-}
diff --git a/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.kt b/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.kt
new file mode 100644
index 0000000..669b7f2
--- /dev/null
+++ b/room/room-runtime/src/test/java/androidx/room/RoomSQLiteQueryTest.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2017 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
+
+import androidx.room.RoomSQLiteQuery.Companion.acquire
+import androidx.sqlite.db.SupportSQLiteProgram
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@RunWith(JUnit4::class)
+class RoomSQLiteQueryTest {
+    @Before
+    fun clear() {
+        RoomSQLiteQuery.queryPool.clear()
+    }
+
+    @Test
+    fun acquireBasic() {
+        val query = acquire("abc", 3)
+        assertThat(query.sql).isEqualTo("abc")
+        assertThat(query.argCount).isEqualTo(3)
+        assertThat(query.blobBindings.size).isEqualTo(4)
+        assertThat(query.longBindings.size).isEqualTo(4)
+        assertThat(query.stringBindings.size).isEqualTo(4)
+        assertThat(query.doubleBindings.size).isEqualTo(4)
+    }
+
+    @Test
+    fun acquireSameSizeAgain() {
+        val query = acquire("abc", 3)
+        query.release()
+        assertThat(acquire("blah", 3)).isSameInstanceAs(query)
+    }
+
+    @Test
+    fun acquireSameSizeWithoutRelease() {
+        val query = acquire("abc", 3)
+        assertThat(
+            acquire("fda", 3)
+        ).isNotSameInstanceAs(query)
+    }
+
+    @Test
+    fun bindings() {
+        val query = acquire("abc", 6)
+        val myBlob = ByteArray(3)
+        val myLong = 3L
+        val myDouble = 7.0
+        val myString = "ss"
+        query.bindBlob(1, myBlob)
+        query.bindLong(2, myLong)
+        query.bindNull(3)
+        query.bindDouble(4, myDouble)
+        query.bindString(5, myString)
+        query.bindNull(6)
+        val program: SupportSQLiteProgram = mock()
+        query.bindTo(program)
+        verify(program).bindBlob(1, myBlob)
+        verify(program).bindLong(2, myLong)
+        verify(program).bindNull(3)
+        verify(program).bindDouble(4, myDouble)
+        verify(program).bindString(5, myString)
+        verify(program).bindNull(6)
+    }
+
+    @Test
+    fun dontKeepSameSizeTwice() {
+        val query1 = acquire("abc", 3)
+        val query2 = acquire("zx", 3)
+        val query3 = acquire("qw", 0)
+        query1.release()
+        query2.release()
+        assertThat(RoomSQLiteQuery.queryPool.size).isEqualTo(1)
+        query3.release()
+        assertThat(RoomSQLiteQuery.queryPool.size).isEqualTo(2)
+    }
+
+    @Test
+    fun returnExistingForSmallerSize() {
+        val query = acquire("abc", 3)
+        query.release()
+        assertThat(acquire("dsa", 2)).isSameInstanceAs(query)
+    }
+
+    @Test
+    fun returnNewForBigger() {
+        val query = acquire("abc", 3)
+        query.release()
+        assertThat(
+            acquire("dsa", 4)
+        ).isNotSameInstanceAs(query)
+    }
+
+    @Test
+    fun pruneCache() {
+        for (i in 0 until RoomSQLiteQuery.POOL_LIMIT) {
+            acquire("dsdsa", i).release()
+        }
+        pruneCacheTest()
+    }
+
+    @Test
+    fun pruneCacheReverseInsertion() {
+        val queries: MutableList<RoomSQLiteQuery> = ArrayList()
+        for (i in RoomSQLiteQuery.POOL_LIMIT - 1 downTo 0) {
+            queries.add(acquire("dsdsa", i))
+        }
+        for (query in queries) {
+            query.release()
+        }
+        pruneCacheTest()
+    }
+
+    private fun pruneCacheTest() {
+        assertThat(
+            RoomSQLiteQuery.queryPool.size
+        ).isEqualTo(RoomSQLiteQuery.POOL_LIMIT)
+        acquire("dsadsa", RoomSQLiteQuery.POOL_LIMIT + 1).release()
+        assertThat(
+            RoomSQLiteQuery.queryPool.size
+        ).isEqualTo(RoomSQLiteQuery.DESIRED_POOL_SIZE)
+        val itr: Iterator<RoomSQLiteQuery> = RoomSQLiteQuery.queryPool.values.iterator()
+        for (i in 0 until RoomSQLiteQuery.DESIRED_POOL_SIZE) {
+            assertThat(itr.next().capacity).isEqualTo(i)
+        }
+    }
+}
\ No newline at end of file
diff --git a/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.java b/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.java
deleted file mode 100644
index dde3a3a..0000000
--- a/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.sqlite.db.SupportSQLiteStatement;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.FutureTask;
-
-@RunWith(JUnit4.class)
-public class SharedSQLiteStatementTest {
-    private SharedSQLiteStatement mSharedStmt;
-    RoomDatabase mDb;
-    @Before
-    public void init() {
-        mDb = mock(RoomDatabase.class);
-        when(mDb.compileStatement(anyString())).thenAnswer(new Answer<SupportSQLiteStatement>() {
-
-            @Override
-            public SupportSQLiteStatement answer(InvocationOnMock invocation) throws Throwable {
-                return mock(SupportSQLiteStatement.class);
-            }
-        });
-        when(mDb.getInvalidationTracker()).thenReturn(mock(InvalidationTracker.class));
-        mSharedStmt = new SharedSQLiteStatement(mDb) {
-            @Override
-            protected String createQuery() {
-                return "foo";
-            }
-        };
-    }
-
-    @Test
-    public void checkMainThread() {
-        mSharedStmt.acquire();
-        verify(mDb).assertNotMainThread();
-    }
-
-    @Test
-    public void basic() {
-        assertThat(mSharedStmt.acquire(), notNullValue());
-    }
-
-    @Test
-    public void getTwiceWithoutReleasing() {
-        SupportSQLiteStatement stmt1 = mSharedStmt.acquire();
-        SupportSQLiteStatement stmt2 = mSharedStmt.acquire();
-        assertThat(stmt1, notNullValue());
-        assertThat(stmt2, notNullValue());
-        assertThat(stmt1, is(not(stmt2)));
-    }
-
-    @Test
-    public void getTwiceWithReleasing() {
-        SupportSQLiteStatement stmt1 = mSharedStmt.acquire();
-        mSharedStmt.release(stmt1);
-        SupportSQLiteStatement stmt2 = mSharedStmt.acquire();
-        assertThat(stmt1, notNullValue());
-        assertThat(stmt1, is(stmt2));
-    }
-
-    @Test
-    public void getFromAnotherThreadWhileHolding() throws ExecutionException, InterruptedException {
-        SupportSQLiteStatement stmt1 = mSharedStmt.acquire();
-        FutureTask<SupportSQLiteStatement> task = new FutureTask<>(
-                new Callable<SupportSQLiteStatement>() {
-                    @Override
-                    public SupportSQLiteStatement call() throws Exception {
-                        return mSharedStmt.acquire();
-                    }
-                });
-        new Thread(task).run();
-        SupportSQLiteStatement stmt2 = task.get();
-        assertThat(stmt1, notNullValue());
-        assertThat(stmt2, notNullValue());
-        assertThat(stmt1, is(not(stmt2)));
-    }
-
-    @Test
-    public void getFromAnotherThreadAfterReleasing() throws ExecutionException,
-            InterruptedException {
-        SupportSQLiteStatement stmt1 = mSharedStmt.acquire();
-        mSharedStmt.release(stmt1);
-        FutureTask<SupportSQLiteStatement> task = new FutureTask<>(
-                new Callable<SupportSQLiteStatement>() {
-                    @Override
-                    public SupportSQLiteStatement call() throws Exception {
-                        return mSharedStmt.acquire();
-                    }
-                });
-        new Thread(task).run();
-        SupportSQLiteStatement stmt2 = task.get();
-        assertThat(stmt1, notNullValue());
-        assertThat(stmt1, is(stmt2));
-    }
-}
diff --git a/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.kt b/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.kt
new file mode 100644
index 0000000..c9da445
--- /dev/null
+++ b/room/room-runtime/src/test/java/androidx/room/SharedSQLiteStatementTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 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
+
+import androidx.sqlite.db.SupportSQLiteStatement
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.FutureTask
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@RunWith(JUnit4::class)
+class SharedSQLiteStatementTest {
+    private lateinit var mSharedStmt: SharedSQLiteStatement
+    lateinit var mDb: RoomDatabase
+    @Before
+    fun init() {
+        val mdata: RoomDatabase = mock()
+        whenever(mdata.compileStatement(anyOrNull())).thenAnswer {
+            mock<SupportSQLiteStatement>()
+        }
+        whenever(mdata.invalidationTracker).thenReturn(mock())
+        mDb = mdata
+        mSharedStmt = object : SharedSQLiteStatement(mdata) {
+            override fun createQuery(): String {
+                return "foo"
+            }
+        }
+    }
+
+    @Test
+    fun checkMainThread() {
+        mSharedStmt.acquire()
+        verify(mDb).assertNotMainThread()
+    }
+
+    @Test
+    fun basic() {
+        assertThat(mSharedStmt.acquire()).isNotNull()
+    }
+
+    @Test
+    fun twiceWithoutReleasing() {
+            val stmt1 = mSharedStmt.acquire()
+            val stmt2 = mSharedStmt.acquire()
+            assertThat(stmt1).isNotNull()
+            assertThat(stmt2).isNotNull()
+            assertThat(stmt1).isNotEqualTo(stmt2)
+        }
+
+    @Test
+    fun twiceWithReleasing() {
+            val stmt1 = mSharedStmt.acquire()
+            mSharedStmt.release(stmt1)
+            val stmt2 = mSharedStmt.acquire()
+            assertThat(stmt1).isNotNull()
+            assertThat(stmt1).isEqualTo(stmt2)
+        }
+
+    @Test
+    fun fromAnotherThreadWhileHolding() {
+        val stmt1 = mSharedStmt.acquire()
+        val task = FutureTask { mSharedStmt.acquire() }
+        Thread(task).start()
+        val stmt2 = task.get()
+        assertThat(stmt1).isNotNull()
+        assertThat(stmt2).isNotNull()
+        assertThat(stmt1).isNotEqualTo(stmt2)
+    }
+
+    @Test
+    fun fromAnotherThreadAfterReleasing() {
+        val stmt1 = mSharedStmt.acquire()
+        mSharedStmt.release(stmt1)
+        val task = FutureTask { mSharedStmt.acquire() }
+        Thread(task).start()
+        val stmt2 = task.get()
+        assertThat(stmt1).isNotNull()
+        assertThat(stmt1).isEqualTo(stmt2)
+    }
+}
\ No newline at end of file
diff --git a/samples/AndroidXDemos/lint-baseline.xml b/samples/AndroidXDemos/lint-baseline.xml
index 66b57c7..6748694 100644
--- a/samples/AndroidXDemos/lint-baseline.xml
+++ b/samples/AndroidXDemos/lint-baseline.xml
@@ -215,7 +215,7 @@
         id="NewApi"
         message="`&lt;class>` requires API level 24 (current min is 14)"
         errorLine1="    class=&quot;com.example.androidx.drawable.MyDrawable&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
             file="src/main/res/drawable/my_drawable.xml"/>
     </issue>
@@ -653,6 +653,105 @@
     <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    public void onCreate(Bundle savedInstanceState) {"
+        errorLine2="                         ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected List&lt;Map&lt;String, Object>> getData(String prefix) {"
+        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected List&lt;Map&lt;String, Object>> getData(String prefix) {"
+        errorLine2="                                                ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
+        errorLine2="              ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
+        errorLine2="                                    ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
+        errorLine2="                                                ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected Intent browseIntent(String path) {"
+        errorLine2="              ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected Intent browseIntent(String path) {"
+        errorLine2="                                  ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
+        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
+        errorLine2="                                                           ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
+        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
+        errorLine2="                                                                        ~~~~~~">
+        <location
+            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
+    </issue>
+
+    <issue
+        id="UnknownNullness"
+        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
         errorLine1="    protected void onCreate(Bundle savedInstanceState) {"
         errorLine2="                            ~~~~~~">
         <location
@@ -2984,105 +3083,6 @@
     <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public void onCreate(Bundle savedInstanceState) {"
-        errorLine2="                         ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected List&lt;Map&lt;String, Object>> getData(String prefix) {"
-        errorLine2="              ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected List&lt;Map&lt;String, Object>> getData(String prefix) {"
-        errorLine2="                                                ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
-        errorLine2="                                    ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected Intent activityIntent(String pkg, String componentName) {"
-        errorLine2="                                                ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected Intent browseIntent(String path) {"
-        errorLine2="              ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected Intent browseIntent(String path) {"
-        errorLine2="                                  ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
-        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
-        errorLine2="                                                           ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    protected void addItem(List&lt;Map&lt;String, Object>> data, String name, Intent intent) {"
-        errorLine2="                                                                        ~~~~~~">
-        <location
-            file="src/main/java/com/example/androidx/AndroidXDemos.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
         errorLine1="    public void onBind(ItemTouchViewHolder viewHolder) {"
         errorLine2="                       ~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/samples/SupportPreferenceDemos/lint-baseline.xml b/samples/SupportPreferenceDemos/lint-baseline.xml
index a2a2fdc..a3353c4 100644
--- a/samples/SupportPreferenceDemos/lint-baseline.xml
+++ b/samples/SupportPreferenceDemos/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="MissingTvBanner"
diff --git a/samples/SupportSliceDemos/lint-baseline.xml b/samples/SupportSliceDemos/lint-baseline.xml
index 128542c..1a9fe29 100644
--- a/samples/SupportSliceDemos/lint-baseline.xml
+++ b/samples/SupportSliceDemos/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/samples/SupportWearDemos/lint-baseline.xml b/samples/SupportWearDemos/lint-baseline.xml
index 66e9a6c..cfbc3a4 100644
--- a/samples/SupportWearDemos/lint-baseline.xml
+++ b/samples/SupportWearDemos/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/security/security-crypto/lint-baseline.xml b/security/security-crypto/lint-baseline.xml
index b611da6..e23c350 100644
--- a/security/security-crypto/lint-baseline.xml
+++ b/security/security-crypto/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="BanSynchronizedMethods"
diff --git a/settings.gradle b/settings.gradle
index 8a420cb..130475d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -598,6 +598,7 @@
 includeProject(":core:uwb:uwb-rxjava3", [BuildType.MAIN])
 includeProject(":credentials:credentials", [BuildType.MAIN])
 includeProject(":credentials:credentials-play-services-auth", [BuildType.MAIN])
+includeProject(":credentials:credentials-provider", [BuildType.MAIN])
 includeProject(":cursoradapter:cursoradapter", [BuildType.MAIN])
 includeProject(":customview:customview", [BuildType.MAIN])
 includeProject(":customview:customview-poolingcontainer", [BuildType.MAIN, BuildType.COMPOSE])
@@ -848,7 +849,7 @@
 includeProject(":test:ext:junit-gtest", [BuildType.NATIVE])
 includeProject(":test:integration-tests:junit-gtest-test", [BuildType.NATIVE])
 includeProject(":test:screenshot:screenshot")
-includeProject(":test:screenshot:screenshot-paparazzi", [BuildType.MAIN, BuildType.COMPOSE])
+includeProject(":test:screenshot:screenshot-layoutlib", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":test:screenshot:screenshot-proto")
 includeProject(":test:uiautomator:uiautomator", [BuildType.MAIN])
 includeProject(":test:uiautomator:integration-tests:testapp", [BuildType.MAIN])
diff --git a/slice/slice-builders/lint-baseline.xml b/slice/slice-builders/lint-baseline.xml
index c8166a0..0ff48cb 100644
--- a/slice/slice-builders/lint-baseline.xml
+++ b/slice/slice-builders/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="WrongConstant"
diff --git a/slice/slice-core/lint-baseline.xml b/slice/slice-core/lint-baseline.xml
index 90d930b..d036494 100644
--- a/slice/slice-core/lint-baseline.xml
+++ b/slice/slice-core/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="BanUncheckedReflection"
diff --git a/slice/slice-view/lint-baseline.xml b/slice/slice-view/lint-baseline.xml
index 2a146f2..d5a0743 100644
--- a/slice/slice-view/lint-baseline.xml
+++ b/slice/slice-view/lint-baseline.xml
@@ -74,60 +74,6 @@
     </issue>
 
     <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_min&quot; formatted=&quot;false&quot; msgid=&quot;7664017844210142826&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_min&quot; formatted=&quot;false&quot; msgid=&quot;7664017844210142826&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_years&quot; formatted=&quot;false&quot; msgid=&quot;2628491538787454021&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_years&quot; formatted=&quot;false&quot; msgid=&quot;2628491538787454021&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_days&quot; formatted=&quot;false&quot; msgid=&quot;8356547162075064530&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;abc_slice_duration_days&quot; formatted=&quot;false&quot; msgid=&quot;8356547162075064530&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/strings.xml"/>
-    </issue>
-
-    <issue
         id="UnknownNullness"
         message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
         errorLine1="    public ActionRow(Context context, boolean fullActions) {"
diff --git a/sqlite/integration-tests/inspection-room-testapp/lint-baseline.xml b/sqlite/integration-tests/inspection-room-testapp/lint-baseline.xml
index 719e8ec..ce89072 100644
--- a/sqlite/integration-tests/inspection-room-testapp/lint-baseline.xml
+++ b/sqlite/integration-tests/inspection-room-testapp/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="MissingTestSizeAnnotation"
diff --git a/sqlite/sqlite/lint-baseline.xml b/sqlite/sqlite/lint-baseline.xml
deleted file mode 100644
index 58c8b41..0000000
--- a/sqlite/sqlite/lint-baseline.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public static SupportSQLiteQueryBuilder builder(String tableName) {"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public static SupportSQLiteQueryBuilder builder(String tableName) {"
-        errorLine2="                                                    ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder distinct() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder columns(String[] columns) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder columns(String[] columns) {"
-        errorLine2="                                             ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder selection(String selection, Object[] bindArgs) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder selection(String selection, Object[] bindArgs) {"
-        errorLine2="                                               ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder selection(String selection, Object[] bindArgs) {"
-        errorLine2="                                                                 ~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder groupBy(String groupBy) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder groupBy(String groupBy) {"
-        errorLine2="                                             ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder having(String having) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder having(String having) {"
-        errorLine2="                                            ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder orderBy(String orderBy) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder orderBy(String orderBy) {"
-        errorLine2="                                             ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder limit(String limit) {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQueryBuilder limit(String limit) {"
-        errorLine2="                                           ~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-    <issue
-        id="UnknownNullness"
-        message="Unknown nullability; explicitly declare as `@Nullable` or `@NonNull` to improve Kotlin interoperability; see https://developer.android.com/kotlin/interop#nullability_annotations"
-        errorLine1="    public SupportSQLiteQuery create() {"
-        errorLine2="           ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/sqlite/db/SupportSQLiteQueryBuilder.java"/>
-    </issue>
-
-</issues>
diff --git a/test/screenshot/screenshot-paparazzi/build.gradle b/test/screenshot/screenshot-layoutlib/build.gradle
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/build.gradle
rename to test/screenshot/screenshot-layoutlib/build.gradle
diff --git a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/AndroidXPaparazziTestRule.kt b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/AndroidXLayoutlibTestRule.kt
similarity index 91%
rename from test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/AndroidXPaparazziTestRule.kt
rename to test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/AndroidXLayoutlibTestRule.kt
index aa727e0..3ae6ebf 100644
--- a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/AndroidXPaparazziTestRule.kt
+++ b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/AndroidXLayoutlibTestRule.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.test.screenshot.paparazzi
+package androidx.test.screenshot.layoutlib
 
 import app.cash.paparazzi.DeviceConfig
 import app.cash.paparazzi.Environment
@@ -25,7 +25,7 @@
 /**
  * Creates a [Paparazzi] test rule configured from system properties for AndroidX tests.
  */
-fun AndroidXPaparazziTestRule(
+fun AndroidXLayoutlibTestRule(
     deviceConfig: DeviceConfig = DeviceConfig.NEXUS_5.copy(softButtons = false),
     theme: String = "android:Theme.Material.NoActionBar.Fullscreen",
     renderingMode: RenderingMode = RenderingMode.NORMAL,
@@ -51,13 +51,13 @@
 )
 
 /** Package name used for resolving system properties */
-private const val PACKAGE_NAME = "androidx.test.screenshot.paparazzi"
+private const val PACKAGE_NAME = "androidx.test.screenshot.layoutlib"
 
 /** Read a system property with [PACKAGE_NAME] prefix, throwing an exception if missing */
 private fun systemProperty(name: String) =
     requireNotNull(System.getProperty("$PACKAGE_NAME.$name")) {
         "System property $PACKAGE_NAME.$name is not set. You may need to apply " +
-            "AndroidXPaparazziPlugin to your Gradle build."
+            "AndroidXLayoutlibPlugin to your Gradle build."
     }
 
 /** Little helper to convert string path to [File] to improve readability */
diff --git a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifier.kt b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/GoldenVerifier.kt
similarity index 99%
rename from test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifier.kt
rename to test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/GoldenVerifier.kt
index 1e58c90..f58a421 100644
--- a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifier.kt
+++ b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/GoldenVerifier.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package androidx.test.screenshot.paparazzi
+package androidx.test.screenshot.layoutlib
 
 import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult
 import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult.Status
diff --git a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/ImageDiffer.kt b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/ImageDiffer.kt
similarity index 97%
rename from test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/ImageDiffer.kt
rename to test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/ImageDiffer.kt
index 72e9e99..d82adce 100644
--- a/test/screenshot/screenshot-paparazzi/src/main/kotlin/androidx/test/screenshot/paparazzi/ImageDiffer.kt
+++ b/test/screenshot/screenshot-layoutlib/src/main/kotlin/androidx/test/screenshot/layoutlib/ImageDiffer.kt
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package androidx.test.screenshot.paparazzi
+package androidx.test.screenshot.layoutlib
 
-import androidx.test.screenshot.paparazzi.ImageDiffer.DiffResult.Similar
+import androidx.test.screenshot.layoutlib.ImageDiffer.DiffResult.Similar
 import java.awt.image.BufferedImage
 
 /**
diff --git a/test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt b/test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt
similarity index 98%
rename from test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt
rename to test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt
index cbaa845..1200d53 100644
--- a/test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt
+++ b/test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/GoldenVerifierTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.test.screenshot.paparazzi
 
+import androidx.test.screenshot.layoutlib.GoldenVerifier
+import androidx.test.screenshot.layoutlib.ImageDiffer
 import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult
 import androidx.test.screenshot.proto.ScreenshotResultProto.ScreenshotResult.Status
 import app.cash.paparazzi.Snapshot
diff --git a/test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt b/test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt
similarity index 89%
rename from test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt
rename to test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt
index 341d454..092a5c9 100644
--- a/test/screenshot/screenshot-paparazzi/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt
+++ b/test/screenshot/screenshot-layoutlib/src/test/kotlin/androidx/test/screenshot/paparazzi/ImageDifferTest.kt
@@ -16,9 +16,9 @@
 
 package androidx.test.screenshot.paparazzi
 
-import androidx.test.screenshot.paparazzi.ImageDiffer.DiffResult.Different
-import androidx.test.screenshot.paparazzi.ImageDiffer.DiffResult.Similar
-import androidx.test.screenshot.paparazzi.ImageDiffer.PixelPerfect
+import androidx.test.screenshot.layoutlib.ImageDiffer.DiffResult.Different
+import androidx.test.screenshot.layoutlib.ImageDiffer.DiffResult.Similar
+import androidx.test.screenshot.layoutlib.ImageDiffer.PixelPerfect
 import javax.imageio.ImageIO
 import kotlin.test.Test
 import kotlin.test.assertEquals
diff --git a/test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/PixelPerfect_diff.png b/test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/PixelPerfect_diff.png
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/PixelPerfect_diff.png
rename to test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/PixelPerfect_diff.png
Binary files differ
diff --git a/test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/circle.png b/test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/circle.png
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/circle.png
rename to test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/circle.png
Binary files differ
diff --git a/test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/horizontal_rectangle.png b/test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/horizontal_rectangle.png
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/horizontal_rectangle.png
rename to test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/horizontal_rectangle.png
Binary files differ
diff --git a/test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/star.png b/test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/star.png
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/star.png
rename to test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/star.png
Binary files differ
diff --git a/test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/vertical_rectangle.png b/test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/vertical_rectangle.png
similarity index 100%
rename from test/screenshot/screenshot-paparazzi/src/test/resources/androidx/test/screenshot/paparazzi/vertical_rectangle.png
rename to test/screenshot/screenshot-layoutlib/src/test/resources/androidx/test/screenshot/paparazzi/vertical_rectangle.png
Binary files differ
diff --git a/testutils/testutils-runtime/lint-baseline.xml b/testutils/testutils-runtime/lint-baseline.xml
index 2d2a7d3..8f6f992 100644
--- a/testutils/testutils-runtime/lint-baseline.xml
+++ b/testutils/testutils-runtime/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="BanUncheckedReflection"
diff --git a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
index a2d095d..914a8d7 100644
--- a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/grid/LazyGridPrefetcherTest.kt
@@ -32,6 +32,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.LargeTest
 import androidx.tv.foundation.lazy.AutoTestFrameClock
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -59,7 +60,7 @@
 
     @Test
     fun notPrefetchingForwardInitially() {
-        composeList()
+        composeGrid()
 
         rule.onNodeWithTag("4")
             .assertDoesNotExist()
@@ -67,7 +68,7 @@
 
     @Test
     fun notPrefetchingBackwardInitially() {
-        composeList(firstItem = 4)
+        composeGrid(firstItem = 4)
 
         rule.onNodeWithTag("0")
             .assertDoesNotExist()
@@ -75,7 +76,7 @@
 
     @Test
     fun prefetchingForwardAfterSmallScroll() {
-        composeList()
+        composeGrid()
 
         rule.runOnIdle {
             runBlocking {
@@ -95,7 +96,7 @@
 
     @Test
     fun prefetchingBackwardAfterSmallScroll() {
-        composeList(firstItem = 4, itemOffset = 10)
+        composeGrid(firstItem = 4, itemOffset = 10)
 
         rule.runOnIdle {
             runBlocking {
@@ -115,7 +116,7 @@
 
     @Test
     fun prefetchingForwardAndBackward() {
-        composeList(firstItem = 2)
+        composeGrid(firstItem = 2)
 
         rule.runOnIdle {
             runBlocking {
@@ -151,7 +152,7 @@
 
     @Test
     fun prefetchingForwardTwice() {
-        composeList()
+        composeGrid()
 
         rule.runOnIdle {
             runBlocking {
@@ -180,7 +181,7 @@
 
     @Test
     fun prefetchingBackwardTwice() {
-        composeList(firstItem = 8)
+        composeGrid(firstItem = 8)
 
         rule.runOnIdle {
             runBlocking {
@@ -211,7 +212,7 @@
 
     @Test
     fun prefetchingForwardAndBackwardReverseLayout() {
-        composeList(firstItem = 2, reverseLayout = true)
+        composeGrid(firstItem = 2, reverseLayout = true)
 
         rule.runOnIdle {
             runBlocking {
@@ -252,7 +253,7 @@
     @Test
     fun prefetchingForwardAndBackwardWithContentPadding() {
         val halfItemSize = itemsSizeDp / 2f
-        composeList(
+        composeGrid(
             firstItem = 4,
             itemOffset = 5,
             contentPadding = PaddingValues(mainAxis = halfItemSize)
@@ -343,6 +344,40 @@
         rule.runOnIdle { }
     }
 
+    @Test
+    fun scrollingByListSizeCancelsPreviousPrefetch() {
+        composeGrid()
+
+        // now we have items 0-3 visible
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 2-5 are visible
+                // and schedule a prefetching for 6-7
+                state.scrollBy(itemsSizePx.toFloat())
+
+                // move viewport by screen size to items 8-11, so item 6 is just behind
+                // the first visible item
+                state.scrollBy(itemsSizePx * 3f)
+
+                // move scroll further to items 10-13, so item 6 is reused
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(13)
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // scroll again to ensure item 6 was dropped
+                state.scrollBy(itemsSizePx * 100f)
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(activeNodes).doesNotContain(6)
+        }
+    }
+
     private fun waitForPrefetch(index: Int) {
         rule.waitUntil {
             activeNodes.contains(index) && activeMeasuredNodes.contains(index)
@@ -352,7 +387,7 @@
     private val activeNodes = mutableSetOf<Int>()
     private val activeMeasuredNodes = mutableSetOf<Int>()
 
-    private fun composeList(
+    private fun composeGrid(
         firstItem: Int = 0,
         itemOffset: Int = 0,
         reverseLayout: Boolean = false,
diff --git a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
index 14401a4..13f31cf 100644
--- a/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
+++ b/tv/tv-foundation/src/androidTest/java/androidx/tv/foundation/lazy/list/LazyListPrefetcherTest.kt
@@ -32,6 +32,7 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.dp
 import androidx.test.filters.LargeTest
+import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -326,6 +327,40 @@
         rule.runOnIdle { }
     }
 
+    @Test
+    fun scrollingByListSizeCancelsPreviousPrefetch() {
+        composeList()
+
+        // now we have items 0-1 visible
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // this will move the viewport so items 1-2 are visible
+                // and schedule a prefetching for 3
+                state.scrollBy(itemsSizePx.toFloat())
+
+                // move viewport by screen size to items 4-5, so item 3 is just behind
+                // the first visible item
+                state.scrollBy(itemsSizePx * 3f)
+
+                // move scroll further to items 5-6, so item 3 is reused
+                state.scrollBy(itemsSizePx.toFloat())
+            }
+        }
+
+        waitForPrefetch(7)
+
+        rule.runOnIdle {
+            runBlocking(AutoTestFrameClock()) {
+                // scroll again to ensure item 3 was dropped
+                state.scrollBy(itemsSizePx * 100f)
+            }
+        }
+
+        rule.runOnIdle {
+            assertThat(activeNodes).doesNotContain(3)
+        }
+    }
+
     private fun waitForPrefetch(index: Int) {
         rule.waitUntil {
             activeNodes.contains(index) && activeMeasuredNodes.contains(index)
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/TvLazyGridState.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/TvLazyGridState.kt
index df4e4c2..42f4e83 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/TvLazyGridState.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/grid/TvLazyGridState.kt
@@ -343,6 +343,25 @@
         }
     }
 
+    private fun cancelPrefetchIfVisibleItemsChanged(info: TvLazyGridLayoutInfo) {
+        if (lineToPrefetch != -1 && info.visibleItemsInfo.isNotEmpty()) {
+            val expectedLineToPrefetch = if (wasScrollingForward) {
+                info.visibleItemsInfo.last().let {
+                    if (isVertical) it.row else it.column
+                } + 1
+            } else {
+                info.visibleItemsInfo.first().let {
+                    if (isVertical) it.row else it.column
+                } - 1
+            }
+            if (lineToPrefetch != expectedLineToPrefetch) {
+                lineToPrefetch = -1
+                currentLinePrefetchHandles.forEach { it.cancel() }
+                currentLinePrefetchHandles.clear()
+            }
+        }
+    }
+
     internal val prefetchState = LazyLayoutPrefetchState()
 
     /**
@@ -374,6 +393,8 @@
             result.firstVisibleLineScrollOffset != 0
 
         numMeasurePasses++
+
+        cancelPrefetchIfVisibleItemsChanged(result)
     }
 
     /**
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyListState.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyListState.kt
index 3328e28..6330923 100644
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyListState.kt
+++ b/tv/tv-foundation/src/main/java/androidx/tv/foundation/lazy/list/LazyListState.kt
@@ -365,6 +365,23 @@
             result.firstVisibleItemScrollOffset != 0
 
         numMeasurePasses++
+
+        cancelPrefetchIfVisibleItemsChanged(result)
+    }
+
+    private fun cancelPrefetchIfVisibleItemsChanged(info: TvLazyListLayoutInfo) {
+        if (indexToPrefetch != -1 && info.visibleItemsInfo.isNotEmpty()) {
+            val expectedPrefetchIndex = if (wasScrollingForward) {
+                info.visibleItemsInfo.last().index + 1
+            } else {
+                info.visibleItemsInfo.first().index - 1
+            }
+            if (indexToPrefetch != expectedPrefetchIndex) {
+                indexToPrefetch = -1
+                currentPrefetchHandle?.cancel()
+                currentPrefetchHandle = null
+            }
+        }
     }
 
     /**
diff --git a/vectordrawable/vectordrawable/lint-baseline.xml b/vectordrawable/vectordrawable/lint-baseline.xml
index a918dbd..f647f1f 100644
--- a/vectordrawable/vectordrawable/lint-baseline.xml
+++ b/vectordrawable/vectordrawable/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/viewpager/viewpager/lint-baseline.xml b/viewpager/viewpager/lint-baseline.xml
index c9974a1..a252977 100644
--- a/viewpager/viewpager/lint-baseline.xml
+++ b/viewpager/viewpager/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="UnknownNullness"
diff --git a/wear/watchface/watchface-complications-data/lint-baseline.xml b/wear/watchface/watchface-complications-data/lint-baseline.xml
deleted file mode 100644
index af4f75c..0000000
--- a/wear/watchface/watchface-complications-data/lint-baseline.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_days&quot; formatted=&quot;false&quot; msgid=&quot;3878057769320887026&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_days&quot; formatted=&quot;false&quot; msgid=&quot;3878057769320887026&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_hours&quot; formatted=&quot;false&quot; msgid=&quot;6016687406802669982&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_hours&quot; formatted=&quot;false&quot; msgid=&quot;6016687406802669982&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_minutes&quot; formatted=&quot;false&quot; msgid=&quot;6752732458902810711&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_short_minutes&quot; formatted=&quot;false&quot; msgid=&quot;6752732458902810711&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_days&quot; formatted=&quot;false&quot; msgid=&quot;5109682345086392533&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_days&quot; formatted=&quot;false&quot; msgid=&quot;5109682345086392533&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_hours&quot; formatted=&quot;false&quot; msgid=&quot;3172220157267000186&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_hours&quot; formatted=&quot;false&quot; msgid=&quot;3172220157267000186&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_minutes&quot; formatted=&quot;false&quot; msgid=&quot;529404827937478243&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr-rCA/complication_strings.xml"/>
-    </issue>
-
-    <issue
-        id="MissingQuantity"
-        message="For locale &quot;fr&quot; (French) the following quantity should also be defined: `many` (e.g. &quot;1000000 de jours&quot;)"
-        errorLine1="    &lt;plurals name=&quot;time_difference_words_minutes&quot; formatted=&quot;false&quot; msgid=&quot;529404827937478243&quot;>"
-        errorLine2="    ^">
-        <location
-            file="src/main/res/values-fr/complication_strings.xml"/>
-    </issue>
-
-</issues>
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
index 18896d4..18c41fe 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlot.kt
@@ -422,6 +422,8 @@
         )
     }
 
+    private var lastComplicationUpdate = Instant.EPOCH
+
     private class ComplicationDataHistoryEntry(
         val complicationData: ComplicationData,
         val time: Instant
@@ -986,6 +988,7 @@
         loadDrawablesAsynchronous: Boolean,
         instant: Instant
     ) {
+        lastComplicationUpdate = instant
         complicationHistory?.push(ComplicationDataHistoryEntry(complicationData, instant))
         timelineComplicationData = complicationData
         timelineEntries = complicationData.asWireComplicationData().timelineEntries?.map {
@@ -1210,6 +1213,7 @@
         @OptIn(ComplicationExperimental::class)
         writer.println("boundingArc=$boundingArc")
         writer.println("complicationSlotBounds=$complicationSlotBounds")
+        writer.println("lastComplicationUpdate=$lastComplicationUpdate")
         writer.println("data history")
         complicationHistory?.let {
             writer.increaseIndent()
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 51d8a7d..9fdf2f5 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -1926,7 +1926,6 @@
             mutableWatchState.watchFaceInstanceId.value = sanitizeWatchFaceId(params.instanceId)
             val watchState = mutableWatchState.asWatchState()
 
-            interactiveInstanceId = mutableWatchState.watchFaceInstanceId.value
             createWatchFaceInternal(
                 watchState,
                 fakeSurfaceHolder,
@@ -1968,7 +1967,6 @@
                 pendingInitialComplications = readComplicationDataCache(_context, params.instanceId)
             }
 
-            interactiveInstanceId = params.instanceId
             createWatchFaceInternal(
                 watchState,
                 getWallpaperSurfaceHolderOverride(),
@@ -1977,6 +1975,7 @@
 
             val instance = InteractiveWatchFaceImpl(this, params.instanceId)
             InteractiveInstanceManager.addInstance(instance)
+            interactiveInstanceId = params.instanceId
             return instance
         }
 
@@ -2397,10 +2396,18 @@
 
         override fun sendPreviewImageNeedsUpdateRequest() {
             synchronized(lock) {
-                lastPreviewImageNeedsUpdateRequest = interactiveInstanceId
+                if (this::interactiveInstanceId.isInitialized) {
+                    lastPreviewImageNeedsUpdateRequest = interactiveInstanceId
 
-                forEachListener("sendPreviewImageNeedsUpdateRequest") {
-                    it.onPreviewImageUpdateRequested(interactiveInstanceId)
+                    forEachListener("sendPreviewImageNeedsUpdateRequest") {
+                        it.onPreviewImageUpdateRequested(interactiveInstanceId)
+                    }
+                } else {
+                    Log.w(
+                        TAG,
+                        "Ignoring sendPreviewImageNeedsUpdateRequest because " +
+                            "interactiveInstanceId not initialized"
+                    )
                 }
             }
         }
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/MainActivity.java b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/MainActivity.java
index d86f336..ddc135e 100644
--- a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/MainActivity.java
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/MainActivity.java
@@ -569,6 +569,17 @@
             }
         });
 
+        findViewById(R.id.enqueue_infinite_work_charging).setOnClickListener(
+                new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        StressTest.queueLotsOfWorkers(
+                                WorkManager.getInstance(MainActivity.this)
+                        );
+                    }
+                });
+
+
         Button hundredJobExceptionButton = findViewById(R.id.create_hundred_job_exception);
         // 100 Job limits are only enforced on API 24+.
         if (Build.VERSION.SDK_INT >= 24) {
diff --git a/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/StressTest.kt b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/StressTest.kt
new file mode 100644
index 0000000..48389e2
--- /dev/null
+++ b/work/integration-tests/testapp/src/main/java/androidx/work/integration/testapp/StressTest.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 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.
+ */
+@file:JvmName("StressTest")
+package androidx.work.integration.testapp
+
+import android.util.Log
+import androidx.work.Constraints
+import androidx.work.ExistingWorkPolicy
+import androidx.work.NetworkType
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
+
+fun queueLotsOfWorkers(workManager: WorkManager) {
+    for (i in 1..1000) {
+        Log.i("TestWM", "Queueing $i worker")
+        val constraint = Constraints.Builder()
+            .setRequiredNetworkType(NetworkType.CONNECTED)
+            .build()
+        val uniqueName = "Worker-$i"
+
+        val worker = OneTimeWorkRequestBuilder<TestWorker>()
+            .setConstraints(constraint)
+            .build()
+
+        val worker2 = OneTimeWorkRequestBuilder<TestWorker>()
+            .setConstraints(constraint)
+            .build()
+
+        val worker3 = OneTimeWorkRequestBuilder<TestWorker>()
+            .setConstraints(constraint)
+            .build()
+
+        workManager.beginUniqueWork(uniqueName, ExistingWorkPolicy.KEEP, worker)
+            .then(worker2)
+            .then(worker3)
+            .enqueue()
+    }
+}
diff --git a/work/integration-tests/testapp/src/main/res/layout/activity_main.xml b/work/integration-tests/testapp/src/main/res/layout/activity_main.xml
index ced7f94..789d68f 100644
--- a/work/integration-tests/testapp/src/main/res/layout/activity_main.xml
+++ b/work/integration-tests/testapp/src/main/res/layout/activity_main.xml
@@ -343,5 +343,13 @@
             android:layout_marginLeft="16dp"
             android:layout_marginStart="16dp"/>
 
+        <Button android:text="@string/stress_test"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/stress_test"
+            android:layout_marginTop="12dp"
+            android:layout_marginLeft="16dp"
+            android:layout_marginStart="16dp"/>
+
     </LinearLayout>
 </ScrollView>
diff --git a/work/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml b/work/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
index f56d600..91c735f 100644
--- a/work/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
+++ b/work/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
@@ -50,4 +50,5 @@
     <integer name="notification_id">1</integer>
     <string name="notification_title">Working</string>
     <string name="cancel_constraint_tracking_worker">Cancel Constraint Tracking Worker</string>
+    <string name="stress_test">Stress Test</string>
 </resources>
\ No newline at end of file
diff --git a/work/work-gcm/api/2.8.0-beta01.txt b/work/work-gcm/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-gcm/api/2.8.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-gcm/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-gcm/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-gcm/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-gcm/api/res-2.8.0-beta01.txt b/work/work-gcm/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-gcm/api/res-2.8.0-beta01.txt
diff --git a/work/work-gcm/api/restricted_2.8.0-beta01.txt b/work/work-gcm/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-gcm/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-inspection/lint-baseline.xml b/work/work-inspection/lint-baseline.xml
index 677478e..2ddb484 100644
--- a/work/work-inspection/lint-baseline.xml
+++ b/work/work-inspection/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="cli" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
+<issues format="6" by="lint 7.4.0-alpha08" type="baseline" client="gradle" dependencies="false" name="AGP (7.4.0-alpha08)" variant="all" version="7.4.0-alpha08">
 
     <issue
         id="RemoveWorkManagerInitializer"
diff --git a/work/work-multiprocess/api/2.8.0-beta01.txt b/work/work-multiprocess/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..bd27cfb
--- /dev/null
+++ b/work/work-multiprocess/api/2.8.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/work-multiprocess/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-multiprocess/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..bd27cfb
--- /dev/null
+++ b/work/work-multiprocess/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/work-multiprocess/api/res-2.8.0-beta01.txt b/work/work-multiprocess/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-multiprocess/api/res-2.8.0-beta01.txt
diff --git a/work/work-multiprocess/api/restricted_2.8.0-beta01.txt b/work/work-multiprocess/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..bd27cfb
--- /dev/null
+++ b/work/work-multiprocess/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,26 @@
+// Signature format: 4.0
+package androidx.work.multiprocess {
+
+  public abstract class RemoteCoroutineWorker extends androidx.work.multiprocess.RemoteListenableWorker {
+    ctor public RemoteCoroutineWorker(android.content.Context context, androidx.work.WorkerParameters parameters);
+    method public abstract suspend Object? doRemoteWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method public final void onStopped();
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startRemoteWork();
+  }
+
+  public abstract class RemoteListenableWorker extends androidx.work.ListenableWorker {
+    ctor public RemoteListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startRemoteWork();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+    field public static final String ARGUMENT_CLASS_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_CLASS_NAME";
+    field public static final String ARGUMENT_PACKAGE_NAME = "androidx.work.impl.workers.RemoteListenableWorker.ARGUMENT_PACKAGE_NAME";
+  }
+
+  public class RemoteWorkerService extends android.app.Service {
+    ctor public RemoteWorkerService();
+    method public android.os.IBinder? onBind(android.content.Intent);
+  }
+
+}
+
diff --git a/work/work-runtime-ktx/api/2.8.0-beta01.txt b/work/work-runtime-ktx/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..efdea4c
--- /dev/null
+++ b/work/work-runtime-ktx/api/2.8.0-beta01.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public suspend Object? getForegroundInfo(kotlin.coroutines.Continuation<? super androidx.work.ForegroundInfo>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo> getForegroundInfoAsync();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS>);
+  }
+
+}
+
diff --git a/work/work-runtime-ktx/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-runtime-ktx/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..efdea4c
--- /dev/null
+++ b/work/work-runtime-ktx/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public suspend Object? getForegroundInfo(kotlin.coroutines.Continuation<? super androidx.work.ForegroundInfo>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo> getForegroundInfoAsync();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS>);
+  }
+
+}
+
diff --git a/work/work-runtime-ktx/api/res-2.8.0-beta01.txt b/work/work-runtime-ktx/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-runtime-ktx/api/res-2.8.0-beta01.txt
diff --git a/work/work-runtime-ktx/api/restricted_2.8.0-beta01.txt b/work/work-runtime-ktx/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..efdea4c
--- /dev/null
+++ b/work/work-runtime-ktx/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,30 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class CoroutineWorker extends androidx.work.ListenableWorker {
+    ctor public CoroutineWorker(android.content.Context appContext, androidx.work.WorkerParameters params);
+    method public abstract suspend Object? doWork(kotlin.coroutines.Continuation<? super androidx.work.ListenableWorker.Result>);
+    method @Deprecated public kotlinx.coroutines.CoroutineDispatcher getCoroutineContext();
+    method public suspend Object? getForegroundInfo(kotlin.coroutines.Continuation<? super androidx.work.ForegroundInfo>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo> getForegroundInfoAsync();
+    method public final void onStopped();
+    method public final suspend Object? setForeground(androidx.work.ForegroundInfo foregroundInfo, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final suspend Object? setProgress(androidx.work.Data data, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result> startWork();
+    property @Deprecated public kotlinx.coroutines.CoroutineDispatcher coroutineContext;
+  }
+
+  public final class DataKt {
+    method public static inline <reified T> boolean hasKeyWithValueOfType(androidx.work.Data, String key);
+    method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
+  }
+
+  public final class ListenableFutureKt {
+  }
+
+  public final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS>);
+  }
+
+}
+
diff --git a/work/work-runtime/api/2.8.0-beta01.txt b/work/work-runtime/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..4519d02
--- /dev/null
+++ b/work/work-runtime/api/2.8.0-beta01.txt
@@ -0,0 +1,499 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data> inputs);
+  }
+
+  public enum BackoffPolicy {
+    method public static androidx.work.BackoffPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.BackoffPolicy[] values();
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InitializationExceptionHandler? getInitializationExceptionHandler();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public androidx.work.SchedulingExceptionHandler? getSchedulingExceptionHandler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInitializationExceptionHandler(androidx.work.InitializationExceptionHandler);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setSchedulingExceptionHandler(androidx.work.SchedulingExceptionHandler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(optional @androidx.room.ColumnInfo(name="required_network_type") androidx.work.NetworkType requiredNetworkType, optional @androidx.room.ColumnInfo(name="requires_charging") boolean requiresCharging, optional @androidx.room.ColumnInfo(name="requires_device_idle") boolean requiresDeviceIdle, optional @androidx.room.ColumnInfo(name="requires_battery_not_low") boolean requiresBatteryNotLow, optional @androidx.room.ColumnInfo(name="requires_storage_not_low") boolean requiresStorageNotLow, optional @androidx.room.ColumnInfo(name="trigger_content_update_delay") long contentTriggerUpdateDelayMillis, optional @androidx.room.ColumnInfo(name="trigger_max_content_delay") long contentTriggerMaxDelayMillis, optional @androidx.room.ColumnInfo(name="content_uri_triggers") java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers);
+    ctor public Constraints(androidx.work.Constraints other);
+    method public long getContentTriggerMaxDelayMillis();
+    method public long getContentTriggerUpdateDelayMillis();
+    method public java.util.Set<androidx.work.Constraints.ContentUriTrigger> getContentUriTriggers();
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    property public final long contentTriggerMaxDelayMillis;
+    property public final long contentTriggerUpdateDelayMillis;
+    property public final java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers;
+    property public final androidx.work.NetworkType requiredNetworkType;
+    field public static final androidx.work.Constraints.Companion Companion;
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri uri, boolean triggerForDescendants);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType networkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean requiresBatteryNotLow);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean requiresCharging);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean requiresDeviceIdle);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean requiresStorageNotLow);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration duration);
+  }
+
+  public static final class Constraints.Companion {
+  }
+
+  public static final class Constraints.ContentUriTrigger {
+    ctor public Constraints.ContentUriTrigger(android.net.Uri uri, boolean isTriggeredForDescendants);
+    method public android.net.Uri getUri();
+    method public boolean isTriggeredForDescendants();
+    property public final boolean isTriggeredForDescendants;
+    property public final android.net.Uri uri;
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    method public static androidx.work.ExistingPeriodicWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingPeriodicWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy CANCEL_AND_REENQUEUE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant @Deprecated public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy UPDATE;
+  }
+
+  public enum ExistingWorkPolicy {
+    method public static androidx.work.ExistingWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public interface InitializationExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo!> getForegroundInfoAsync();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    method public static androidx.work.NetworkType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.NetworkType[] values();
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+    field public static final androidx.work.OneTimeWorkRequest.Companion Companion;
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public static final class OneTimeWorkRequest.Companion {
+    method public androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public enum OutOfQuotaPolicy {
+    method public static androidx.work.OutOfQuotaPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.OutOfQuotaPolicy[] values();
+    enum_constant public static final androidx.work.OutOfQuotaPolicy DROP_WORK_REQUEST;
+    enum_constant public static final androidx.work.OutOfQuotaPolicy RUN_AS_NON_EXPEDITED_WORK_REQUEST;
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final androidx.work.PeriodicWorkRequest.Companion Companion;
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexInterval, java.util.concurrent.TimeUnit flexIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval, java.time.Duration flexInterval);
+  }
+
+  public static final class PeriodicWorkRequest.Companion {
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public interface SchedulingExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Configuration getConfiguration();
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public static boolean isInitialized();
+    method public abstract androidx.work.Operation pruneWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkManager.UpdateResult!> updateWork(androidx.work.WorkRequest);
+  }
+
+  public enum WorkManager.UpdateResult {
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_FOR_NEXT_RUN;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_IMMEDIATELY;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult NOT_APPLIED;
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public static androidx.work.WorkQuery fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery fromIds(java.util.UUID!...);
+    method public static androidx.work.WorkQuery fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery fromStates(androidx.work.WorkInfo.State!...);
+    method public static androidx.work.WorkQuery fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery fromTags(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    property public java.util.UUID id;
+    field public static final androidx.work.WorkRequest.Companion Companion;
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<B, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String tag);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, long backoffDelay, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, java.time.Duration duration);
+    method public final B setConstraints(androidx.work.Constraints constraints);
+    method public B setExpedited(androidx.work.OutOfQuotaPolicy policy);
+    method public final B setId(java.util.UUID id);
+    method public B setInitialDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration duration);
+    method public final B setInputData(androidx.work.Data inputData);
+  }
+
+  public static final class WorkRequest.Companion {
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method @WorkerThread public androidx.work.ForegroundInfo getForegroundInfo();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method @IntRange(from=0) public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+
diff --git a/work/work-runtime/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-runtime/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..4519d02
--- /dev/null
+++ b/work/work-runtime/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,499 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data> inputs);
+  }
+
+  public enum BackoffPolicy {
+    method public static androidx.work.BackoffPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.BackoffPolicy[] values();
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InitializationExceptionHandler? getInitializationExceptionHandler();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public androidx.work.SchedulingExceptionHandler? getSchedulingExceptionHandler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInitializationExceptionHandler(androidx.work.InitializationExceptionHandler);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setSchedulingExceptionHandler(androidx.work.SchedulingExceptionHandler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(optional @androidx.room.ColumnInfo(name="required_network_type") androidx.work.NetworkType requiredNetworkType, optional @androidx.room.ColumnInfo(name="requires_charging") boolean requiresCharging, optional @androidx.room.ColumnInfo(name="requires_device_idle") boolean requiresDeviceIdle, optional @androidx.room.ColumnInfo(name="requires_battery_not_low") boolean requiresBatteryNotLow, optional @androidx.room.ColumnInfo(name="requires_storage_not_low") boolean requiresStorageNotLow, optional @androidx.room.ColumnInfo(name="trigger_content_update_delay") long contentTriggerUpdateDelayMillis, optional @androidx.room.ColumnInfo(name="trigger_max_content_delay") long contentTriggerMaxDelayMillis, optional @androidx.room.ColumnInfo(name="content_uri_triggers") java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers);
+    ctor public Constraints(androidx.work.Constraints other);
+    method public long getContentTriggerMaxDelayMillis();
+    method public long getContentTriggerUpdateDelayMillis();
+    method public java.util.Set<androidx.work.Constraints.ContentUriTrigger> getContentUriTriggers();
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    property public final long contentTriggerMaxDelayMillis;
+    property public final long contentTriggerUpdateDelayMillis;
+    property public final java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers;
+    property public final androidx.work.NetworkType requiredNetworkType;
+    field public static final androidx.work.Constraints.Companion Companion;
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri uri, boolean triggerForDescendants);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType networkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean requiresBatteryNotLow);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean requiresCharging);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean requiresDeviceIdle);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean requiresStorageNotLow);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration duration);
+  }
+
+  public static final class Constraints.Companion {
+  }
+
+  public static final class Constraints.ContentUriTrigger {
+    ctor public Constraints.ContentUriTrigger(android.net.Uri uri, boolean isTriggeredForDescendants);
+    method public android.net.Uri getUri();
+    method public boolean isTriggeredForDescendants();
+    property public final boolean isTriggeredForDescendants;
+    property public final android.net.Uri uri;
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    method public static androidx.work.ExistingPeriodicWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingPeriodicWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy CANCEL_AND_REENQUEUE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant @Deprecated public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy UPDATE;
+  }
+
+  public enum ExistingWorkPolicy {
+    method public static androidx.work.ExistingWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public interface InitializationExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo!> getForegroundInfoAsync();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    method public static androidx.work.NetworkType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.NetworkType[] values();
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+    field public static final androidx.work.OneTimeWorkRequest.Companion Companion;
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public static final class OneTimeWorkRequest.Companion {
+    method public androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public enum OutOfQuotaPolicy {
+    method public static androidx.work.OutOfQuotaPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.OutOfQuotaPolicy[] values();
+    enum_constant public static final androidx.work.OutOfQuotaPolicy DROP_WORK_REQUEST;
+    enum_constant public static final androidx.work.OutOfQuotaPolicy RUN_AS_NON_EXPEDITED_WORK_REQUEST;
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final androidx.work.PeriodicWorkRequest.Companion Companion;
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexInterval, java.util.concurrent.TimeUnit flexIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval, java.time.Duration flexInterval);
+  }
+
+  public static final class PeriodicWorkRequest.Companion {
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public interface SchedulingExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Configuration getConfiguration();
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public static boolean isInitialized();
+    method public abstract androidx.work.Operation pruneWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkManager.UpdateResult!> updateWork(androidx.work.WorkRequest);
+  }
+
+  public enum WorkManager.UpdateResult {
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_FOR_NEXT_RUN;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_IMMEDIATELY;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult NOT_APPLIED;
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public static androidx.work.WorkQuery fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery fromIds(java.util.UUID!...);
+    method public static androidx.work.WorkQuery fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery fromStates(androidx.work.WorkInfo.State!...);
+    method public static androidx.work.WorkQuery fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery fromTags(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    property public java.util.UUID id;
+    field public static final androidx.work.WorkRequest.Companion Companion;
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<B, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String tag);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, long backoffDelay, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, java.time.Duration duration);
+    method public final B setConstraints(androidx.work.Constraints constraints);
+    method public B setExpedited(androidx.work.OutOfQuotaPolicy policy);
+    method public final B setId(java.util.UUID id);
+    method public B setInitialDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration duration);
+    method public final B setInputData(androidx.work.Data inputData);
+  }
+
+  public static final class WorkRequest.Companion {
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method @WorkerThread public androidx.work.ForegroundInfo getForegroundInfo();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method @IntRange(from=0) public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+
diff --git a/work/work-runtime/api/res-2.8.0-beta01.txt b/work/work-runtime/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-runtime/api/res-2.8.0-beta01.txt
diff --git a/work/work-runtime/api/restricted_2.8.0-beta01.txt b/work/work-runtime/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..4519d02
--- /dev/null
+++ b/work/work-runtime/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,499 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public final class ArrayCreatingInputMerger extends androidx.work.InputMerger {
+    ctor public ArrayCreatingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data> inputs);
+  }
+
+  public enum BackoffPolicy {
+    method public static androidx.work.BackoffPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.BackoffPolicy[] values();
+    enum_constant public static final androidx.work.BackoffPolicy EXPONENTIAL;
+    enum_constant public static final androidx.work.BackoffPolicy LINEAR;
+  }
+
+  public final class Configuration {
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.work.InitializationExceptionHandler? getInitializationExceptionHandler();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public androidx.work.SchedulingExceptionHandler? getSchedulingExceptionHandler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    field public static final int MIN_SCHEDULER_LIMIT = 20; // 0x14
+  }
+
+  public static final class Configuration.Builder {
+    ctor public Configuration.Builder();
+    method public androidx.work.Configuration build();
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setInitializationExceptionHandler(androidx.work.InitializationExceptionHandler);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int, int);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler);
+    method public androidx.work.Configuration.Builder setSchedulingExceptionHandler(androidx.work.SchedulingExceptionHandler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+  }
+
+  public final class Constraints {
+    ctor public Constraints(optional @androidx.room.ColumnInfo(name="required_network_type") androidx.work.NetworkType requiredNetworkType, optional @androidx.room.ColumnInfo(name="requires_charging") boolean requiresCharging, optional @androidx.room.ColumnInfo(name="requires_device_idle") boolean requiresDeviceIdle, optional @androidx.room.ColumnInfo(name="requires_battery_not_low") boolean requiresBatteryNotLow, optional @androidx.room.ColumnInfo(name="requires_storage_not_low") boolean requiresStorageNotLow, optional @androidx.room.ColumnInfo(name="trigger_content_update_delay") long contentTriggerUpdateDelayMillis, optional @androidx.room.ColumnInfo(name="trigger_max_content_delay") long contentTriggerMaxDelayMillis, optional @androidx.room.ColumnInfo(name="content_uri_triggers") java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers);
+    ctor public Constraints(androidx.work.Constraints other);
+    method public long getContentTriggerMaxDelayMillis();
+    method public long getContentTriggerUpdateDelayMillis();
+    method public java.util.Set<androidx.work.Constraints.ContentUriTrigger> getContentUriTriggers();
+    method public androidx.work.NetworkType getRequiredNetworkType();
+    method public boolean requiresBatteryNotLow();
+    method public boolean requiresCharging();
+    method @RequiresApi(23) public boolean requiresDeviceIdle();
+    method public boolean requiresStorageNotLow();
+    property public final long contentTriggerMaxDelayMillis;
+    property public final long contentTriggerUpdateDelayMillis;
+    property public final java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers;
+    property public final androidx.work.NetworkType requiredNetworkType;
+    field public static final androidx.work.Constraints.Companion Companion;
+    field public static final androidx.work.Constraints NONE;
+  }
+
+  public static final class Constraints.Builder {
+    ctor public Constraints.Builder();
+    method @RequiresApi(24) public androidx.work.Constraints.Builder addContentUriTrigger(android.net.Uri uri, boolean triggerForDescendants);
+    method public androidx.work.Constraints build();
+    method public androidx.work.Constraints.Builder setRequiredNetworkType(androidx.work.NetworkType networkType);
+    method public androidx.work.Constraints.Builder setRequiresBatteryNotLow(boolean requiresBatteryNotLow);
+    method public androidx.work.Constraints.Builder setRequiresCharging(boolean requiresCharging);
+    method @RequiresApi(23) public androidx.work.Constraints.Builder setRequiresDeviceIdle(boolean requiresDeviceIdle);
+    method public androidx.work.Constraints.Builder setRequiresStorageNotLow(boolean requiresStorageNotLow);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration duration);
+  }
+
+  public static final class Constraints.Companion {
+  }
+
+  public static final class Constraints.ContentUriTrigger {
+    ctor public Constraints.ContentUriTrigger(android.net.Uri uri, boolean isTriggeredForDescendants);
+    method public android.net.Uri getUri();
+    method public boolean isTriggeredForDescendants();
+    property public final boolean isTriggeredForDescendants;
+    property public final android.net.Uri uri;
+  }
+
+  public final class Data {
+    ctor public Data(androidx.work.Data);
+    method @androidx.room.TypeConverter public static androidx.work.Data fromByteArray(byte[]);
+    method public boolean getBoolean(String, boolean);
+    method public boolean[]? getBooleanArray(String);
+    method public byte getByte(String, byte);
+    method public byte[]? getByteArray(String);
+    method public double getDouble(String, double);
+    method public double[]? getDoubleArray(String);
+    method public float getFloat(String, float);
+    method public float[]? getFloatArray(String);
+    method public int getInt(String, int);
+    method public int[]? getIntArray(String);
+    method public java.util.Map<java.lang.String!,java.lang.Object!> getKeyValueMap();
+    method public long getLong(String, long);
+    method public long[]? getLongArray(String);
+    method public String? getString(String);
+    method public String![]? getStringArray(String);
+    method public <T> boolean hasKeyWithValueOfType(String, Class<T!>);
+    method public byte[] toByteArray();
+    field public static final androidx.work.Data EMPTY;
+    field public static final int MAX_DATA_BYTES = 10240; // 0x2800
+  }
+
+  public static final class Data.Builder {
+    ctor public Data.Builder();
+    method public androidx.work.Data build();
+    method public androidx.work.Data.Builder putAll(androidx.work.Data);
+    method public androidx.work.Data.Builder putAll(java.util.Map<java.lang.String!,java.lang.Object!>);
+    method public androidx.work.Data.Builder putBoolean(String, boolean);
+    method public androidx.work.Data.Builder putBooleanArray(String, boolean[]);
+    method public androidx.work.Data.Builder putByte(String, byte);
+    method public androidx.work.Data.Builder putByteArray(String, byte[]);
+    method public androidx.work.Data.Builder putDouble(String, double);
+    method public androidx.work.Data.Builder putDoubleArray(String, double[]);
+    method public androidx.work.Data.Builder putFloat(String, float);
+    method public androidx.work.Data.Builder putFloatArray(String, float[]);
+    method public androidx.work.Data.Builder putInt(String, int);
+    method public androidx.work.Data.Builder putIntArray(String, int[]);
+    method public androidx.work.Data.Builder putLong(String, long);
+    method public androidx.work.Data.Builder putLongArray(String, long[]);
+    method public androidx.work.Data.Builder putString(String, String?);
+    method public androidx.work.Data.Builder putStringArray(String, String![]);
+  }
+
+  public class DelegatingWorkerFactory extends androidx.work.WorkerFactory {
+    ctor public DelegatingWorkerFactory();
+    method public final void addFactory(androidx.work.WorkerFactory);
+    method public final androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public enum ExistingPeriodicWorkPolicy {
+    method public static androidx.work.ExistingPeriodicWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingPeriodicWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy CANCEL_AND_REENQUEUE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy KEEP;
+    enum_constant @Deprecated public static final androidx.work.ExistingPeriodicWorkPolicy REPLACE;
+    enum_constant public static final androidx.work.ExistingPeriodicWorkPolicy UPDATE;
+  }
+
+  public enum ExistingWorkPolicy {
+    method public static androidx.work.ExistingWorkPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.ExistingWorkPolicy[] values();
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND;
+    enum_constant public static final androidx.work.ExistingWorkPolicy APPEND_OR_REPLACE;
+    enum_constant public static final androidx.work.ExistingWorkPolicy KEEP;
+    enum_constant public static final androidx.work.ExistingWorkPolicy REPLACE;
+  }
+
+  public final class ForegroundInfo {
+    ctor public ForegroundInfo(int, android.app.Notification);
+    ctor public ForegroundInfo(int, android.app.Notification, int);
+    method public int getForegroundServiceType();
+    method public android.app.Notification getNotification();
+    method public int getNotificationId();
+  }
+
+  public interface ForegroundUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(android.content.Context, java.util.UUID, androidx.work.ForegroundInfo);
+  }
+
+  public interface InitializationExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String);
+  }
+
+  public abstract class ListenableWorker {
+    ctor public ListenableWorker(android.content.Context, androidx.work.WorkerParameters);
+    method public final android.content.Context getApplicationContext();
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ForegroundInfo!> getForegroundInfoAsync();
+    method public final java.util.UUID getId();
+    method public final androidx.work.Data getInputData();
+    method @RequiresApi(28) public final android.net.Network? getNetwork();
+    method @IntRange(from=0) public final int getRunAttemptCount();
+    method public final java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public final java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public final java.util.List<android.net.Uri!> getTriggeredContentUris();
+    method public final boolean isStopped();
+    method public void onStopped();
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setForegroundAsync(androidx.work.ForegroundInfo);
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> setProgressAsync(androidx.work.Data);
+    method @MainThread public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract static class ListenableWorker.Result {
+    method public static androidx.work.ListenableWorker.Result failure();
+    method public static androidx.work.ListenableWorker.Result failure(androidx.work.Data);
+    method public abstract androidx.work.Data getOutputData();
+    method public static androidx.work.ListenableWorker.Result retry();
+    method public static androidx.work.ListenableWorker.Result success();
+    method public static androidx.work.ListenableWorker.Result success(androidx.work.Data);
+  }
+
+  public enum NetworkType {
+    method public static androidx.work.NetworkType valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.NetworkType[] values();
+    enum_constant public static final androidx.work.NetworkType CONNECTED;
+    enum_constant public static final androidx.work.NetworkType METERED;
+    enum_constant public static final androidx.work.NetworkType NOT_REQUIRED;
+    enum_constant public static final androidx.work.NetworkType NOT_ROAMING;
+    enum_constant @RequiresApi(30) public static final androidx.work.NetworkType TEMPORARILY_UNMETERED;
+    enum_constant public static final androidx.work.NetworkType UNMETERED;
+  }
+
+  public final class OneTimeWorkRequest extends androidx.work.WorkRequest {
+    method public static androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public static java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+    field public static final androidx.work.OneTimeWorkRequest.Companion Companion;
+  }
+
+  public static final class OneTimeWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.OneTimeWorkRequest.Builder,androidx.work.OneTimeWorkRequest> {
+    ctor public OneTimeWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public androidx.work.OneTimeWorkRequest.Builder setInputMerger(Class<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public static final class OneTimeWorkRequest.Companion {
+    method public androidx.work.OneTimeWorkRequest from(Class<? extends androidx.work.ListenableWorker> workerClass);
+    method public java.util.List<androidx.work.OneTimeWorkRequest> from(java.util.List<? extends java.lang.Class<? extends androidx.work.ListenableWorker>> workerClasses);
+  }
+
+  public final class OneTimeWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder! OneTimeWorkRequestBuilder();
+    method public static inline androidx.work.OneTimeWorkRequest.Builder setInputMerger(androidx.work.OneTimeWorkRequest.Builder, kotlin.reflect.KClass<? extends androidx.work.InputMerger> inputMerger);
+  }
+
+  public interface Operation {
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.Operation.State.SUCCESS!> getResult();
+    method public androidx.lifecycle.LiveData<androidx.work.Operation.State!> getState();
+  }
+
+  public abstract static class Operation.State {
+  }
+
+  public static final class Operation.State.FAILURE extends androidx.work.Operation.State {
+    ctor public Operation.State.FAILURE(Throwable);
+    method public Throwable getThrowable();
+  }
+
+  public static final class Operation.State.IN_PROGRESS extends androidx.work.Operation.State {
+  }
+
+  public static final class Operation.State.SUCCESS extends androidx.work.Operation.State {
+  }
+
+  public enum OutOfQuotaPolicy {
+    method public static androidx.work.OutOfQuotaPolicy valueOf(String name) throws java.lang.IllegalArgumentException;
+    method public static androidx.work.OutOfQuotaPolicy[] values();
+    enum_constant public static final androidx.work.OutOfQuotaPolicy DROP_WORK_REQUEST;
+    enum_constant public static final androidx.work.OutOfQuotaPolicy RUN_AS_NON_EXPEDITED_WORK_REQUEST;
+  }
+
+  public final class OverwritingInputMerger extends androidx.work.InputMerger {
+    ctor public OverwritingInputMerger();
+    method public androidx.work.Data merge(java.util.List<androidx.work.Data!>);
+  }
+
+  public final class PeriodicWorkRequest extends androidx.work.WorkRequest {
+    field public static final androidx.work.PeriodicWorkRequest.Companion Companion;
+    field public static final long MIN_PERIODIC_FLEX_MILLIS = 300000L; // 0x493e0L
+    field public static final long MIN_PERIODIC_INTERVAL_MILLIS = 900000L; // 0xdbba0L
+  }
+
+  public static final class PeriodicWorkRequest.Builder extends androidx.work.WorkRequest.Builder<androidx.work.PeriodicWorkRequest.Builder,androidx.work.PeriodicWorkRequest> {
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexInterval, java.util.concurrent.TimeUnit flexIntervalTimeUnit);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval, java.time.Duration flexInterval);
+  }
+
+  public static final class PeriodicWorkRequest.Companion {
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexTimeInterval, java.util.concurrent.TimeUnit flexTimeIntervalUnit);
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder! PeriodicWorkRequestBuilder(java.time.Duration repeatInterval, java.time.Duration flexTimeInterval);
+  }
+
+  public interface ProgressUpdater {
+    method public com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> updateProgress(android.content.Context, java.util.UUID, androidx.work.Data);
+  }
+
+  public interface RunnableScheduler {
+    method public void cancel(Runnable);
+    method public void scheduleWithDelay(@IntRange(from=0) long, Runnable);
+  }
+
+  public interface SchedulingExceptionHandler {
+    method public void handleException(Throwable);
+  }
+
+  public abstract class WorkContinuation {
+    ctor public WorkContinuation();
+    method public static androidx.work.WorkContinuation combine(java.util.List<androidx.work.WorkContinuation!>);
+    method public abstract androidx.work.Operation enqueue();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos();
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData();
+    method public final androidx.work.WorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public final class WorkInfo {
+    method public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method public java.util.Set<java.lang.String!> getTags();
+  }
+
+  public enum WorkInfo.State {
+    method public boolean isFinished();
+    enum_constant public static final androidx.work.WorkInfo.State BLOCKED;
+    enum_constant public static final androidx.work.WorkInfo.State CANCELLED;
+    enum_constant public static final androidx.work.WorkInfo.State ENQUEUED;
+    enum_constant public static final androidx.work.WorkInfo.State FAILED;
+    enum_constant public static final androidx.work.WorkInfo.State RUNNING;
+    enum_constant public static final androidx.work.WorkInfo.State SUCCEEDED;
+  }
+
+  public abstract class WorkManager {
+    method public final androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.WorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.WorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Operation cancelAllWork();
+    method public abstract androidx.work.Operation cancelAllWorkByTag(String);
+    method public abstract androidx.work.Operation cancelUniqueWork(String);
+    method public abstract androidx.work.Operation cancelWorkById(java.util.UUID);
+    method public abstract android.app.PendingIntent createCancelPendingIntent(java.util.UUID);
+    method public final androidx.work.Operation enqueue(androidx.work.WorkRequest);
+    method public abstract androidx.work.Operation enqueue(java.util.List<? extends androidx.work.WorkRequest>);
+    method public abstract androidx.work.Operation enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.Operation enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract androidx.work.Configuration getConfiguration();
+    method @Deprecated public static androidx.work.WorkManager getInstance();
+    method public static androidx.work.WorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Long!> getLastCancelAllTimeMillis();
+    method public abstract androidx.lifecycle.LiveData<java.lang.Long!> getLastCancelAllTimeMillisLiveData();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkInfo!> getWorkInfoById(java.util.UUID);
+    method public abstract androidx.lifecycle.LiveData<androidx.work.WorkInfo!> getWorkInfoByIdLiveData(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTag(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkLiveData(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosLiveData(androidx.work.WorkQuery);
+    method public static void initialize(android.content.Context, androidx.work.Configuration);
+    method public static boolean isInitialized();
+    method public abstract androidx.work.Operation pruneWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<androidx.work.WorkManager.UpdateResult!> updateWork(androidx.work.WorkRequest);
+  }
+
+  public enum WorkManager.UpdateResult {
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_FOR_NEXT_RUN;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult APPLIED_IMMEDIATELY;
+    enum_constant public static final androidx.work.WorkManager.UpdateResult NOT_APPLIED;
+  }
+
+  public final class WorkManagerInitializer implements androidx.startup.Initializer<androidx.work.WorkManager> {
+    ctor public WorkManagerInitializer();
+    method public androidx.work.WorkManager create(android.content.Context);
+    method public java.util.List<java.lang.Class<? extends androidx.startup.Initializer<?>>!> dependencies();
+  }
+
+  public final class WorkQuery {
+    method public static androidx.work.WorkQuery fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery fromIds(java.util.UUID!...);
+    method public static androidx.work.WorkQuery fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery fromStates(androidx.work.WorkInfo.State!...);
+    method public static androidx.work.WorkQuery fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery fromTags(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public java.util.List<java.util.UUID!> getIds();
+    method public java.util.List<androidx.work.WorkInfo.State!> getStates();
+    method public java.util.List<java.lang.String!> getTags();
+    method public java.util.List<java.lang.String!> getUniqueWorkNames();
+  }
+
+  public static final class WorkQuery.Builder {
+    method public androidx.work.WorkQuery.Builder addIds(java.util.List<java.util.UUID!>);
+    method public androidx.work.WorkQuery.Builder addStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public androidx.work.WorkQuery.Builder addTags(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery.Builder addUniqueWorkNames(java.util.List<java.lang.String!>);
+    method public androidx.work.WorkQuery build();
+    method public static androidx.work.WorkQuery.Builder fromIds(java.util.List<java.util.UUID!>);
+    method public static androidx.work.WorkQuery.Builder fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery.Builder fromTags(java.util.List<java.lang.String!>);
+    method public static androidx.work.WorkQuery.Builder fromUniqueWorkNames(java.util.List<java.lang.String!>);
+  }
+
+  public abstract class WorkRequest {
+    method public java.util.UUID getId();
+    property public java.util.UUID id;
+    field public static final androidx.work.WorkRequest.Companion Companion;
+    field public static final long DEFAULT_BACKOFF_DELAY_MILLIS = 30000L; // 0x7530L
+    field public static final long MAX_BACKOFF_MILLIS = 18000000L; // 0x112a880L
+    field public static final long MIN_BACKOFF_MILLIS = 10000L; // 0x2710L
+  }
+
+  public abstract static class WorkRequest.Builder<B extends androidx.work.WorkRequest.Builder<B, ?>, W extends androidx.work.WorkRequest> {
+    method public final B addTag(String tag);
+    method public final W build();
+    method public final B keepResultsForAtLeast(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, long backoffDelay, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, java.time.Duration duration);
+    method public final B setConstraints(androidx.work.Constraints constraints);
+    method public B setExpedited(androidx.work.OutOfQuotaPolicy policy);
+    method public final B setId(java.util.UUID id);
+    method public B setInitialDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public B setInitialDelay(java.time.Duration duration);
+    method public final B setInputData(androidx.work.Data inputData);
+  }
+
+  public static final class WorkRequest.Companion {
+  }
+
+  public abstract class Worker extends androidx.work.ListenableWorker {
+    ctor public Worker(android.content.Context, androidx.work.WorkerParameters);
+    method @WorkerThread public abstract androidx.work.ListenableWorker.Result doWork();
+    method @WorkerThread public androidx.work.ForegroundInfo getForegroundInfo();
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+  public abstract class WorkerFactory {
+    ctor public WorkerFactory();
+    method public abstract androidx.work.ListenableWorker? createWorker(android.content.Context, String, androidx.work.WorkerParameters);
+  }
+
+  public final class WorkerParameters {
+    method @IntRange(from=0) public int getGeneration();
+    method public java.util.UUID getId();
+    method public androidx.work.Data getInputData();
+    method @RequiresApi(28) public android.net.Network? getNetwork();
+    method @IntRange(from=0) public int getRunAttemptCount();
+    method public java.util.Set<java.lang.String!> getTags();
+    method @RequiresApi(24) public java.util.List<java.lang.String!> getTriggeredContentAuthorities();
+    method @RequiresApi(24) public java.util.List<android.net.Uri!> getTriggeredContentUris();
+  }
+
+}
+
+package androidx.work.multiprocess {
+
+  public abstract class RemoteWorkContinuation {
+    method public static androidx.work.multiprocess.RemoteWorkContinuation combine(java.util.List<androidx.work.multiprocess.RemoteWorkContinuation!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue();
+    method public final androidx.work.multiprocess.RemoteWorkContinuation then(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation then(java.util.List<androidx.work.OneTimeWorkRequest!>);
+  }
+
+  public abstract class RemoteWorkManager {
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public final androidx.work.multiprocess.RemoteWorkContinuation beginWith(androidx.work.OneTimeWorkRequest);
+    method public abstract androidx.work.multiprocess.RemoteWorkContinuation beginWith(java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWork();
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelAllWorkByTag(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelUniqueWork(String);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> cancelWorkById(java.util.UUID);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(androidx.work.WorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueue(java.util.List<androidx.work.WorkRequest!>);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniquePeriodicWork(String, androidx.work.ExistingPeriodicWorkPolicy, androidx.work.PeriodicWorkRequest);
+    method public final com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, androidx.work.OneTimeWorkRequest);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.lang.Void!> enqueueUniqueWork(String, androidx.work.ExistingWorkPolicy, java.util.List<androidx.work.OneTimeWorkRequest!>);
+    method public static androidx.work.multiprocess.RemoteWorkManager getInstance(android.content.Context);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfos(androidx.work.WorkQuery);
+  }
+
+}
+
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/StartStopToken.kt b/work/work-runtime/src/main/java/androidx/work/impl/StartStopToken.kt
index 034a5a45..f9c4245 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/StartStopToken.kt
+++ b/work/work-runtime/src/main/java/androidx/work/impl/StartStopToken.kt
@@ -37,8 +37,7 @@
 
     fun tokenFor(id: WorkGenerationalId): StartStopToken {
         return synchronized(lock) {
-            val startStopToken = StartStopToken(id)
-            runs.getOrPut(id) { startStopToken }
+            runs.getOrPut(id) { StartStopToken(id) }
         }
     }
 
@@ -56,6 +55,10 @@
         }
     }
 
+    fun contains(id: WorkGenerationalId): Boolean {
+        return synchronized(lock) { runs.contains(id) }
+    }
+
     fun tokenFor(spec: WorkSpec) = tokenFor(spec.generationalId())
     fun remove(spec: WorkSpec) = remove(spec.generationalId())
 }
\ No newline at end of file
diff --git a/work/work-runtime/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java b/work/work-runtime/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
index e1c9c42..656f129 100644
--- a/work/work-runtime/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
+++ b/work/work-runtime/src/main/java/androidx/work/impl/background/greedy/GreedyScheduler.java
@@ -124,6 +124,11 @@
         Set<String> constrainedWorkSpecIds = new HashSet<>();
 
         for (WorkSpec workSpec : workSpecs) {
+            // it doesn't help against races, but reduces useless load in the system
+            WorkGenerationalId id = generationalId(workSpec);
+            if (mStartStopTokens.contains(id)) {
+                continue;
+            }
             long nextRunTime = workSpec.calculateNextRunTime();
             long now = System.currentTimeMillis();
             if (workSpec.state == WorkInfo.State.ENQUEUED) {
@@ -146,8 +151,11 @@
                         constrainedWorkSpecIds.add(workSpec.id);
                     }
                 } else {
-                    Logger.get().debug(TAG, "Starting work for " + workSpec.id);
-                    mWorkManagerImpl.startWork(mStartStopTokens.tokenFor(workSpec));
+                    // it doesn't help against races, but reduces useless load in the system
+                    if (!mStartStopTokens.contains(generationalId(workSpec))) {
+                        Logger.get().debug(TAG, "Starting work for " + workSpec.id);
+                        mWorkManagerImpl.startWork(mStartStopTokens.tokenFor(workSpec));
+                    }
                 }
             }
         }
@@ -195,8 +203,11 @@
     public void onAllConstraintsMet(@NonNull List<WorkSpec> workSpecs) {
         for (WorkSpec workSpec : workSpecs) {
             WorkGenerationalId id = generationalId(workSpec);
-            Logger.get().debug(TAG, "Constraints met: Scheduling work ID " + id);
-            mWorkManagerImpl.startWork(mStartStopTokens.tokenFor(id));
+            // it doesn't help against races, but reduces useless load in the system
+            if (!mStartStopTokens.contains(id)) {
+                Logger.get().debug(TAG, "Constraints met: Scheduling work ID " + id);
+                mWorkManagerImpl.startWork(mStartStopTokens.tokenFor(id));
+            }
         }
     }
 
diff --git a/work/work-rxjava2/api/2.8.0-beta01.txt b/work/work-rxjava2/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..1cca40e
--- /dev/null
+++ b/work/work-rxjava2/api/2.8.0-beta01.txt
@@ -0,0 +1,16 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public io.reactivex.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.Completable setForeground(androidx.work.ForegroundInfo);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-rxjava2/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-rxjava2/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..1cca40e
--- /dev/null
+++ b/work/work-rxjava2/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,16 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public io.reactivex.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.Completable setForeground(androidx.work.ForegroundInfo);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-rxjava2/api/res-2.8.0-beta01.txt b/work/work-rxjava2/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-rxjava2/api/res-2.8.0-beta01.txt
diff --git a/work/work-rxjava2/api/restricted_2.8.0-beta01.txt b/work/work-rxjava2/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..1cca40e
--- /dev/null
+++ b/work/work-rxjava2/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,16 @@
+// Signature format: 4.0
+package androidx.work {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.Scheduler getBackgroundScheduler();
+    method public io.reactivex.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.Completable setForeground(androidx.work.ForegroundInfo);
+    method @Deprecated public final io.reactivex.Single<java.lang.Void!> setProgress(androidx.work.Data);
+    method public com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-rxjava3/api/2.8.0-beta01.txt b/work/work-rxjava3/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..0983052
--- /dev/null
+++ b/work/work-rxjava3/api/2.8.0-beta01.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.rxjava3.core.Completable setForeground(androidx.work.ForegroundInfo);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-rxjava3/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-rxjava3/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..0983052
--- /dev/null
+++ b/work/work-rxjava3/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.rxjava3.core.Completable setForeground(androidx.work.ForegroundInfo);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-rxjava3/api/res-2.8.0-beta01.txt b/work/work-rxjava3/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-rxjava3/api/res-2.8.0-beta01.txt
diff --git a/work/work-rxjava3/api/restricted_2.8.0-beta01.txt b/work/work-rxjava3/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..0983052
--- /dev/null
+++ b/work/work-rxjava3/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,15 @@
+// Signature format: 4.0
+package androidx.work.rxjava3 {
+
+  public abstract class RxWorker extends androidx.work.ListenableWorker {
+    ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
+    method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
+    method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
+    method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
+    method public final io.reactivex.rxjava3.core.Completable setForeground(androidx.work.ForegroundInfo);
+    method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
+  }
+
+}
+
diff --git a/work/work-testing/api/2.8.0-beta01.txt b/work/work-testing/api/2.8.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/work-testing/api/2.8.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+
diff --git a/work/work-testing/api/public_plus_experimental_2.8.0-beta01.txt b/work/work-testing/api/public_plus_experimental_2.8.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/work-testing/api/public_plus_experimental_2.8.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+
diff --git a/work/work-testing/api/res-2.8.0-beta01.txt b/work/work-testing/api/res-2.8.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-testing/api/res-2.8.0-beta01.txt
diff --git a/work/work-testing/api/restricted_2.8.0-beta01.txt b/work/work-testing/api/restricted_2.8.0-beta01.txt
new file mode 100644
index 0000000..f3f3fe2
--- /dev/null
+++ b/work/work-testing/api/restricted_2.8.0-beta01.txt
@@ -0,0 +1,52 @@
+// Signature format: 4.0
+package androidx.work.testing {
+
+  public class SynchronousExecutor implements java.util.concurrent.Executor {
+    ctor public SynchronousExecutor();
+    method public void execute(Runnable);
+  }
+
+  public interface TestDriver {
+    method public void setAllConstraintsMet(java.util.UUID);
+    method public void setInitialDelayMet(java.util.UUID);
+    method public void setPeriodDelayMet(java.util.UUID);
+  }
+
+  public class TestListenableWorkerBuilder<W extends androidx.work.ListenableWorker> {
+    method public W build();
+    method public static androidx.work.testing.TestListenableWorkerBuilder<? extends androidx.work.ListenableWorker> from(android.content.Context, androidx.work.WorkRequest);
+    method public static <W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W!> from(android.content.Context, Class<W!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setForegroundUpdater(androidx.work.ForegroundUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setId(java.util.UUID);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setInputData(androidx.work.Data);
+    method @RequiresApi(28) public androidx.work.testing.TestListenableWorkerBuilder<W!> setNetwork(android.net.Network);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setProgressUpdater(androidx.work.ProgressUpdater);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setRunAttemptCount(int);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setTags(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentAuthorities(java.util.List<java.lang.String!>);
+    method @RequiresApi(24) public androidx.work.testing.TestListenableWorkerBuilder<W!> setTriggeredContentUris(java.util.List<android.net.Uri!>);
+    method public androidx.work.testing.TestListenableWorkerBuilder<W!> setWorkerFactory(androidx.work.WorkerFactory);
+  }
+
+  public final class TestListenableWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.testing.TestListenableWorkerBuilder<W>! TestListenableWorkerBuilder(android.content.Context context, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public class TestWorkerBuilder<W extends androidx.work.Worker> extends androidx.work.testing.TestListenableWorkerBuilder<W> {
+    method public static androidx.work.testing.TestWorkerBuilder<? extends androidx.work.Worker> from(android.content.Context, androidx.work.WorkRequest, java.util.concurrent.Executor);
+    method public static <W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W!> from(android.content.Context, Class<W!>, java.util.concurrent.Executor);
+  }
+
+  public final class TestWorkerBuilderKt {
+    method public static inline <reified W extends androidx.work.Worker> androidx.work.testing.TestWorkerBuilder<W>! TestWorkerBuilder(android.content.Context context, java.util.concurrent.Executor executor, optional androidx.work.Data inputData, optional java.util.List<? extends java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<? extends java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method @Deprecated public static androidx.work.testing.TestDriver? getTestDriver();
+    method public static androidx.work.testing.TestDriver? getTestDriver(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration);
+  }
+
+}
+