Merge changes I45cb9710,I8a591b4a,I8ac43baa into androidx-main

* changes:
  Opt-in Metalava w/ K2 UAST (R3)
  Opt-in Metalava w/ K2 UAST (R2)
  Opt-in Metalava w/ K2 UAST (R1)
diff --git a/activity/activity/api/current.txt b/activity/activity/api/current.txt
index c241ac8..f55a193 100644
--- a/activity/activity/api/current.txt
+++ b/activity/activity/api/current.txt
@@ -3,7 +3,7 @@
 
   public final class BackEventCompat {
     ctor @RequiresApi(34) public BackEventCompat(android.window.BackEvent backEvent);
-    ctor @VisibleForTesting public BackEventCompat(float touchX, float touchY, float progress, int swipeEdge);
+    ctor @VisibleForTesting public BackEventCompat(float touchX, float touchY, @FloatRange(from=0.0, to=1.0) float progress, int swipeEdge);
     method public float getProgress();
     method public int getSwipeEdge();
     method public float getTouchX();
diff --git a/activity/activity/api/restricted_current.txt b/activity/activity/api/restricted_current.txt
index 9d7924a..0348b24 100644
--- a/activity/activity/api/restricted_current.txt
+++ b/activity/activity/api/restricted_current.txt
@@ -3,7 +3,7 @@
 
   public final class BackEventCompat {
     ctor @RequiresApi(34) public BackEventCompat(android.window.BackEvent backEvent);
-    ctor @VisibleForTesting public BackEventCompat(float touchX, float touchY, float progress, int swipeEdge);
+    ctor @VisibleForTesting public BackEventCompat(float touchX, float touchY, @FloatRange(from=0.0, to=1.0) float progress, int swipeEdge);
     method public float getProgress();
     method public int getSwipeEdge();
     method public float getTouchX();
diff --git a/activity/activity/src/main/java/androidx/activity/BackEventCompat.kt b/activity/activity/src/main/java/androidx/activity/BackEventCompat.kt
index b850269..a53c63d 100644
--- a/activity/activity/src/main/java/androidx/activity/BackEventCompat.kt
+++ b/activity/activity/src/main/java/androidx/activity/BackEventCompat.kt
@@ -19,6 +19,7 @@
 import android.os.Build
 import android.window.BackEvent
 import androidx.annotation.DoNotInline
+import androidx.annotation.FloatRange
 import androidx.annotation.IntDef
 import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
@@ -29,16 +30,19 @@
  */
 class BackEventCompat @VisibleForTesting constructor(
     /**
-     * Absolute X location of the touch point of this event.
+     * Absolute X location of the touch point of this event in the coordinate space of the view that
+     *      * received this back event.
      */
     val touchX: Float,
     /**
-     * Absolute Y location of the touch point of this event.
+     * Absolute Y location of the touch point of this event in the coordinate space of the view that
+     * received this back event.
      */
     val touchY: Float,
     /**
      * Value between 0 and 1 on how far along the back gesture is.
      */
+    @FloatRange(from = 0.0, to = 1.0)
     val progress: Float,
     /**
      * Indicates which edge the swipe starts from.
diff --git a/appactions/builtintypes/builtintypes/api/current.txt b/appactions/builtintypes/builtintypes/api/current.txt
index 2a8f29a..f20b3ad 100644
--- a/appactions/builtintypes/builtintypes/api/current.txt
+++ b/appactions/builtintypes/builtintypes/api/current.txt
@@ -4,10 +4,10 @@
   @androidx.appsearch.annotation.Document(name="bitprop:ByDay") public final class ByDay {
     ctor public ByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
     ctor public ByDay(String text);
-    method public androidx.appactions.builtintypes.types.DayOfWeek? getAsDayOfWeek();
+    method @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public androidx.appactions.builtintypes.types.DayOfWeek? getAsDayOfWeek();
     method @androidx.appsearch.annotation.Document.StringProperty public String? getAsText();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ByDay.Mapper<R> mapper);
-    property public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
+    property @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
     property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
   }
 
@@ -42,13 +42,13 @@
     ctor public EndDate(java.time.Instant instant);
     ctor public EndDate(java.time.LocalDate date);
     ctor public EndDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.EndDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface EndDate.Mapper<R> {
@@ -62,13 +62,13 @@
     ctor public EndTime(java.time.Instant instant);
     ctor public EndTime(java.time.LocalDateTime localDateTime);
     ctor public EndTime(java.time.LocalTime time);
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
-    method public java.time.LocalTime? getAsTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? getAsTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.EndTime.Mapper<R> mapper);
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
-    property public final java.time.LocalTime? asTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
   }
 
   public static interface EndTime.Mapper<R> {
@@ -82,13 +82,13 @@
     ctor public ExceptDate(java.time.Instant instant);
     ctor public ExceptDate(java.time.LocalDate date);
     ctor public ExceptDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ExceptDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface ExceptDate.Mapper<R> {
@@ -107,10 +107,10 @@
   @androidx.appsearch.annotation.Document(name="bitprop:RepeatFrequency") public final class RepeatFrequency {
     ctor public RepeatFrequency(String text);
     ctor public RepeatFrequency(java.time.Duration duration);
-    method public java.time.Duration? getAsDuration();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public java.time.Duration? getAsDuration();
     method @androidx.appsearch.annotation.Document.StringProperty public String? getAsText();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.RepeatFrequency.Mapper<R> mapper);
-    property public final java.time.Duration? asDuration;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public final java.time.Duration? asDuration;
     property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
   }
 
@@ -124,13 +124,13 @@
     ctor public StartDate(java.time.Instant instant);
     ctor public StartDate(java.time.LocalDate date);
     ctor public StartDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.StartDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface StartDate.Mapper<R> {
@@ -144,13 +144,13 @@
     ctor public StartTime(java.time.Instant instant);
     ctor public StartTime(java.time.LocalDateTime localDateTime);
     ctor public StartTime(java.time.LocalTime time);
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
-    method public java.time.LocalTime? getAsTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? getAsTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.StartTime.Mapper<R> mapper);
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
-    property public final java.time.LocalTime? asTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
   }
 
   public static interface StartTime.Mapper<R> {
@@ -162,6 +162,46 @@
 
 }
 
+package androidx.appactions.builtintypes.serializers {
+
+  public final class DayOfWeekAsCanonicalUrlSerializer implements androidx.appsearch.app.StringSerializer<androidx.appactions.builtintypes.types.DayOfWeek> {
+    ctor public DayOfWeekAsCanonicalUrlSerializer();
+    method public androidx.appactions.builtintypes.types.DayOfWeek? deserialize(String value);
+    method public String serialize(androidx.appactions.builtintypes.types.DayOfWeek instance);
+  }
+
+  public final class DurationAsNanosSerializer implements androidx.appsearch.app.LongSerializer<java.time.Duration> {
+    ctor public DurationAsNanosSerializer();
+    method public java.time.Duration deserialize(long value);
+    method public long serialize(java.time.Duration instance);
+  }
+
+  public final class InstantAsEpochMilliSerializer implements androidx.appsearch.app.LongSerializer<java.time.Instant> {
+    ctor public InstantAsEpochMilliSerializer();
+    method public java.time.Instant deserialize(long value);
+    method public long serialize(java.time.Instant instance);
+  }
+
+  public final class LocalDateAsEpochDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDate> {
+    ctor public LocalDateAsEpochDaySerializer();
+    method public java.time.LocalDate deserialize(long value);
+    method public long serialize(java.time.LocalDate instance);
+  }
+
+  public final class LocalDateTimeAsUtcEpochSecondSerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDateTime> {
+    ctor public LocalDateTimeAsUtcEpochSecondSerializer();
+    method public java.time.LocalDateTime deserialize(long value);
+    method public long serialize(java.time.LocalDateTime instance);
+  }
+
+  public final class LocalTimeAsNanoOfDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalTime> {
+    ctor public LocalTimeAsNanoOfDaySerializer();
+    method public java.time.LocalTime deserialize(long value);
+    method public long serialize(java.time.LocalTime instance);
+  }
+
+}
+
 package androidx.appactions.builtintypes.types {
 
   public abstract class AbstractAlarm<Self extends androidx.appactions.builtintypes.types.AbstractAlarm<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Alarm {
@@ -725,6 +765,7 @@
   public final class DayOfWeek {
     method public String getCanonicalUrl();
     method public <R> R mapWhen(androidx.appactions.builtintypes.types.DayOfWeek.Mapper<R> mapper);
+    method public static java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
     property public final String canonicalUrl;
     field public static final androidx.appactions.builtintypes.types.DayOfWeek.Companion Companion;
     field public static final androidx.appactions.builtintypes.types.DayOfWeek FRIDAY;
@@ -738,6 +779,7 @@
   }
 
   public static final class DayOfWeek.Companion {
+    method public java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
   }
 
   public static interface DayOfWeek.Mapper<R> {
diff --git a/appactions/builtintypes/builtintypes/api/restricted_current.txt b/appactions/builtintypes/builtintypes/api/restricted_current.txt
index 2a8f29a..f20b3ad 100644
--- a/appactions/builtintypes/builtintypes/api/restricted_current.txt
+++ b/appactions/builtintypes/builtintypes/api/restricted_current.txt
@@ -4,10 +4,10 @@
   @androidx.appsearch.annotation.Document(name="bitprop:ByDay") public final class ByDay {
     ctor public ByDay(androidx.appactions.builtintypes.types.DayOfWeek dayOfWeek);
     ctor public ByDay(String text);
-    method public androidx.appactions.builtintypes.types.DayOfWeek? getAsDayOfWeek();
+    method @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public androidx.appactions.builtintypes.types.DayOfWeek? getAsDayOfWeek();
     method @androidx.appsearch.annotation.Document.StringProperty public String? getAsText();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ByDay.Mapper<R> mapper);
-    property public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
+    property @androidx.appsearch.annotation.Document.StringProperty(serializer=DayOfWeekAsCanonicalUrlSerializer::class) public final androidx.appactions.builtintypes.types.DayOfWeek? asDayOfWeek;
     property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
   }
 
@@ -42,13 +42,13 @@
     ctor public EndDate(java.time.Instant instant);
     ctor public EndDate(java.time.LocalDate date);
     ctor public EndDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.EndDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface EndDate.Mapper<R> {
@@ -62,13 +62,13 @@
     ctor public EndTime(java.time.Instant instant);
     ctor public EndTime(java.time.LocalDateTime localDateTime);
     ctor public EndTime(java.time.LocalTime time);
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
-    method public java.time.LocalTime? getAsTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? getAsTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.EndTime.Mapper<R> mapper);
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
-    property public final java.time.LocalTime? asTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
   }
 
   public static interface EndTime.Mapper<R> {
@@ -82,13 +82,13 @@
     ctor public ExceptDate(java.time.Instant instant);
     ctor public ExceptDate(java.time.LocalDate date);
     ctor public ExceptDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.ExceptDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface ExceptDate.Mapper<R> {
@@ -107,10 +107,10 @@
   @androidx.appsearch.annotation.Document(name="bitprop:RepeatFrequency") public final class RepeatFrequency {
     ctor public RepeatFrequency(String text);
     ctor public RepeatFrequency(java.time.Duration duration);
-    method public java.time.Duration? getAsDuration();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public java.time.Duration? getAsDuration();
     method @androidx.appsearch.annotation.Document.StringProperty public String? getAsText();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.RepeatFrequency.Mapper<R> mapper);
-    property public final java.time.Duration? asDuration;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=DurationAsNanosSerializer::class) public final java.time.Duration? asDuration;
     property @androidx.appsearch.annotation.Document.StringProperty public final String? asText;
   }
 
@@ -124,13 +124,13 @@
     ctor public StartDate(java.time.Instant instant);
     ctor public StartDate(java.time.LocalDate date);
     ctor public StartDate(java.time.LocalDateTime localDateTime);
-    method public java.time.LocalDate? getAsDate();
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public java.time.LocalDate? getAsDate();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.StartDate.Mapper<R> mapper);
-    property public final java.time.LocalDate? asDate;
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateAsEpochDaySerializer::class) public final java.time.LocalDate? asDate;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
   }
 
   public static interface StartDate.Mapper<R> {
@@ -144,13 +144,13 @@
     ctor public StartTime(java.time.Instant instant);
     ctor public StartTime(java.time.LocalDateTime localDateTime);
     ctor public StartTime(java.time.LocalTime time);
-    method public java.time.Instant? getAsInstant();
-    method public java.time.LocalDateTime? getAsLocalDateTime();
-    method public java.time.LocalTime? getAsTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public java.time.Instant? getAsInstant();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public java.time.LocalDateTime? getAsLocalDateTime();
+    method @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public java.time.LocalTime? getAsTime();
     method public <R> R mapWhen(androidx.appactions.builtintypes.properties.StartTime.Mapper<R> mapper);
-    property public final java.time.Instant? asInstant;
-    property public final java.time.LocalDateTime? asLocalDateTime;
-    property public final java.time.LocalTime? asTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=InstantAsEpochMilliSerializer::class) public final java.time.Instant? asInstant;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalDateTimeAsUtcEpochSecondSerializer::class) public final java.time.LocalDateTime? asLocalDateTime;
+    property @androidx.appsearch.annotation.Document.LongProperty(serializer=LocalTimeAsNanoOfDaySerializer::class) public final java.time.LocalTime? asTime;
   }
 
   public static interface StartTime.Mapper<R> {
@@ -162,6 +162,46 @@
 
 }
 
+package androidx.appactions.builtintypes.serializers {
+
+  public final class DayOfWeekAsCanonicalUrlSerializer implements androidx.appsearch.app.StringSerializer<androidx.appactions.builtintypes.types.DayOfWeek> {
+    ctor public DayOfWeekAsCanonicalUrlSerializer();
+    method public androidx.appactions.builtintypes.types.DayOfWeek? deserialize(String value);
+    method public String serialize(androidx.appactions.builtintypes.types.DayOfWeek instance);
+  }
+
+  public final class DurationAsNanosSerializer implements androidx.appsearch.app.LongSerializer<java.time.Duration> {
+    ctor public DurationAsNanosSerializer();
+    method public java.time.Duration deserialize(long value);
+    method public long serialize(java.time.Duration instance);
+  }
+
+  public final class InstantAsEpochMilliSerializer implements androidx.appsearch.app.LongSerializer<java.time.Instant> {
+    ctor public InstantAsEpochMilliSerializer();
+    method public java.time.Instant deserialize(long value);
+    method public long serialize(java.time.Instant instance);
+  }
+
+  public final class LocalDateAsEpochDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDate> {
+    ctor public LocalDateAsEpochDaySerializer();
+    method public java.time.LocalDate deserialize(long value);
+    method public long serialize(java.time.LocalDate instance);
+  }
+
+  public final class LocalDateTimeAsUtcEpochSecondSerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalDateTime> {
+    ctor public LocalDateTimeAsUtcEpochSecondSerializer();
+    method public java.time.LocalDateTime deserialize(long value);
+    method public long serialize(java.time.LocalDateTime instance);
+  }
+
+  public final class LocalTimeAsNanoOfDaySerializer implements androidx.appsearch.app.LongSerializer<java.time.LocalTime> {
+    ctor public LocalTimeAsNanoOfDaySerializer();
+    method public java.time.LocalTime deserialize(long value);
+    method public long serialize(java.time.LocalTime instance);
+  }
+
+}
+
 package androidx.appactions.builtintypes.types {
 
   public abstract class AbstractAlarm<Self extends androidx.appactions.builtintypes.types.AbstractAlarm<Self, Builder>, Builder extends androidx.appactions.builtintypes.types.AbstractAlarm.Builder<Builder, Self>> implements androidx.appactions.builtintypes.types.Alarm {
@@ -725,6 +765,7 @@
   public final class DayOfWeek {
     method public String getCanonicalUrl();
     method public <R> R mapWhen(androidx.appactions.builtintypes.types.DayOfWeek.Mapper<R> mapper);
+    method public static java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
     property public final String canonicalUrl;
     field public static final androidx.appactions.builtintypes.types.DayOfWeek.Companion Companion;
     field public static final androidx.appactions.builtintypes.types.DayOfWeek FRIDAY;
@@ -738,6 +779,7 @@
   }
 
   public static final class DayOfWeek.Companion {
+    method public java.util.List<androidx.appactions.builtintypes.types.DayOfWeek> values();
   }
 
   public static interface DayOfWeek.Mapper<R> {
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt
index 8457bc1..a8e3dba 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ByDay.kt
@@ -13,6 +13,7 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.DayOfWeekAsCanonicalUrlSerializer
 import androidx.appactions.builtintypes.types.DayOfWeek
 import androidx.appsearch.`annotation`.Document
 import java.util.Objects
@@ -20,7 +21,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -41,22 +41,14 @@
   /** The [String] variant, or null if constructed using a different variant. */
   @get:JvmName("asText") @get:Document.StringProperty public val asText: String? = null,
   /** The [DayOfWeek] variant, or null if constructed using a different variant. */
-  @get:JvmName("asDayOfWeek") public val asDayOfWeek: DayOfWeek? = null,
+  @get:JvmName("asDayOfWeek")
+  @get:Document.StringProperty(serializer = DayOfWeekAsCanonicalUrlSerializer::class)
+  public val asDayOfWeek: DayOfWeek? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [String] variant. */
   public constructor(text: String) : this(asText = text)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/DisambiguatingDescription.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/DisambiguatingDescription.kt
index b442650..66fed6a 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/DisambiguatingDescription.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/DisambiguatingDescription.kt
@@ -21,7 +21,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -48,20 +47,10 @@
   @get:Document.DocumentProperty
   public val asCanonicalValue: CanonicalValue? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [String] variant. */
   public constructor(text: String) : this(asText = text)
 
@@ -139,12 +128,12 @@
   ) {
     @get:RestrictTo(LIBRARY_GROUP)
     @set:RestrictTo(LIBRARY_GROUP)
-    @Document.Id
+    @get:Document.Id
     public var identifier: String = ""
 
     @get:RestrictTo(LIBRARY_GROUP)
     @set:RestrictTo(LIBRARY_GROUP)
-    @Document.Namespace
+    @get:Document.Namespace
     public var namespace: String = ""
 
     public override fun equals(other: Any?): Boolean {
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt
index e7ece00..c2df08a 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndDate.kt
@@ -13,6 +13,9 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
+import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
+import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Instant
 import java.time.LocalDate
@@ -22,7 +25,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -42,26 +44,22 @@
 public class EndDate
 internal constructor(
   /** The [LocalDate] variant, or null if constructed using a different variant. */
-  @get:JvmName("asDate") public val asDate: LocalDate? = null,
+  @get:JvmName("asDate")
+  @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
+  public val asDate: LocalDate? = null,
   /** The [LocalDateTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asLocalDateTime") public val asLocalDateTime: LocalDateTime? = null,
+  @get:JvmName("asLocalDateTime")
+  @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
+  public val asLocalDateTime: LocalDateTime? = null,
   /** The [Instant] variant, or null if constructed using a different variant. */
-  @get:JvmName("asInstant") public val asInstant: Instant? = null,
+  @get:JvmName("asInstant")
+  @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
+  public val asInstant: Instant? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [LocalDate] variant. */
   public constructor(date: LocalDate) : this(asDate = date)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt
index cf12cc8..ad35fc5 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/EndTime.kt
@@ -13,6 +13,9 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
+import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
+import androidx.appactions.builtintypes.serializers.LocalTimeAsNanoOfDaySerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Instant
 import java.time.LocalDateTime
@@ -22,7 +25,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -47,26 +49,22 @@
 public class EndTime
 internal constructor(
   /** The [LocalTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asTime") public val asTime: LocalTime? = null,
+  @get:JvmName("asTime")
+  @get:Document.LongProperty(serializer = LocalTimeAsNanoOfDaySerializer::class)
+  public val asTime: LocalTime? = null,
   /** The [LocalDateTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asLocalDateTime") public val asLocalDateTime: LocalDateTime? = null,
+  @get:JvmName("asLocalDateTime")
+  @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
+  public val asLocalDateTime: LocalDateTime? = null,
   /** The [Instant] variant, or null if constructed using a different variant. */
-  @get:JvmName("asInstant") public val asInstant: Instant? = null,
+  @get:JvmName("asInstant")
+  @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
+  public val asInstant: Instant? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [LocalTime] variant. */
   public constructor(time: LocalTime) : this(asTime = time)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt
index 394af47..9821724 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/ExceptDate.kt
@@ -13,6 +13,9 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
+import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
+import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Instant
 import java.time.LocalDate
@@ -22,7 +25,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -47,26 +49,22 @@
 public class ExceptDate
 internal constructor(
   /** The [LocalDate] variant, or null if constructed using a different variant. */
-  @get:JvmName("asDate") public val asDate: LocalDate? = null,
+  @get:JvmName("asDate")
+  @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
+  public val asDate: LocalDate? = null,
   /** The [LocalDateTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asLocalDateTime") public val asLocalDateTime: LocalDateTime? = null,
+  @get:JvmName("asLocalDateTime")
+  @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
+  public val asLocalDateTime: LocalDateTime? = null,
   /** The [Instant] variant, or null if constructed using a different variant. */
-  @get:JvmName("asInstant") public val asInstant: Instant? = null,
+  @get:JvmName("asInstant")
+  @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
+  public val asInstant: Instant? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [LocalDate] variant. */
   public constructor(date: LocalDate) : this(asDate = date)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt
index 133e294..6806b49 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/Name.kt
@@ -19,7 +19,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -39,20 +38,10 @@
   /** The [String] variant, or null if constructed using a different variant. */
   @get:JvmName("asText") @get:Document.StringProperty public val asText: String? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [String] variant. */
   public constructor(text: String) : this(asText = text)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt
index 4e795f0..75d6357 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/RepeatFrequency.kt
@@ -13,6 +13,7 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.DurationAsNanosSerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Duration
 import java.util.Objects
@@ -20,7 +21,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -40,24 +40,16 @@
 public class RepeatFrequency
 internal constructor(
   /** The [Duration] variant, or null if constructed using a different variant. */
-  @get:JvmName("asDuration") public val asDuration: Duration? = null,
+  @get:JvmName("asDuration")
+  @get:Document.LongProperty(serializer = DurationAsNanosSerializer::class)
+  public val asDuration: Duration? = null,
   /** The [String] variant, or null if constructed using a different variant. */
   @get:JvmName("asText") @get:Document.StringProperty public val asText: String? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [Duration] variant. */
   public constructor(duration: Duration) : this(asDuration = duration)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt
index 72f94e4..d6c4e94 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartDate.kt
@@ -13,6 +13,9 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
+import androidx.appactions.builtintypes.serializers.LocalDateAsEpochDaySerializer
+import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Instant
 import java.time.LocalDate
@@ -22,7 +25,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -42,26 +44,22 @@
 public class StartDate
 internal constructor(
   /** The [LocalDate] variant, or null if constructed using a different variant. */
-  @get:JvmName("asDate") public val asDate: LocalDate? = null,
+  @get:JvmName("asDate")
+  @get:Document.LongProperty(serializer = LocalDateAsEpochDaySerializer::class)
+  public val asDate: LocalDate? = null,
   /** The [LocalDateTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asLocalDateTime") public val asLocalDateTime: LocalDateTime? = null,
+  @get:JvmName("asLocalDateTime")
+  @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
+  public val asLocalDateTime: LocalDateTime? = null,
   /** The [Instant] variant, or null if constructed using a different variant. */
-  @get:JvmName("asInstant") public val asInstant: Instant? = null,
+  @get:JvmName("asInstant")
+  @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
+  public val asInstant: Instant? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [LocalDate] variant. */
   public constructor(date: LocalDate) : this(asDate = date)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt
index 54dcdce..19ea317 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/properties/StartTime.kt
@@ -13,6 +13,9 @@
 // limitations under the License.
 package androidx.appactions.builtintypes.properties
 
+import androidx.appactions.builtintypes.serializers.InstantAsEpochMilliSerializer
+import androidx.appactions.builtintypes.serializers.LocalDateTimeAsUtcEpochSecondSerializer
+import androidx.appactions.builtintypes.serializers.LocalTimeAsNanoOfDaySerializer
 import androidx.appsearch.`annotation`.Document
 import java.time.Instant
 import java.time.LocalDateTime
@@ -22,7 +25,6 @@
 import kotlin.Boolean
 import kotlin.Int
 import kotlin.String
-import kotlin.Suppress
 import kotlin.error
 import kotlin.jvm.JvmName
 
@@ -47,26 +49,22 @@
 public class StartTime
 internal constructor(
   /** The [LocalTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asTime") public val asTime: LocalTime? = null,
+  @get:JvmName("asTime")
+  @get:Document.LongProperty(serializer = LocalTimeAsNanoOfDaySerializer::class)
+  public val asTime: LocalTime? = null,
   /** The [LocalDateTime] variant, or null if constructed using a different variant. */
-  @get:JvmName("asLocalDateTime") public val asLocalDateTime: LocalDateTime? = null,
+  @get:JvmName("asLocalDateTime")
+  @get:Document.LongProperty(serializer = LocalDateTimeAsUtcEpochSecondSerializer::class)
+  public val asLocalDateTime: LocalDateTime? = null,
   /** The [Instant] variant, or null if constructed using a different variant. */
-  @get:JvmName("asInstant") public val asInstant: Instant? = null,
+  @get:JvmName("asInstant")
+  @get:Document.LongProperty(serializer = InstantAsEpochMilliSerializer::class)
+  public val asInstant: Instant? = null,
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") identifier: String = "",
+  @get:Document.Id @get:JvmName("getIdentifier") internal val identifier: String = "",
   /** Required ctor param for the AppSearch compiler. */
-  @Suppress("UNUSED_PARAMETER") namespace: String = "",
+  @get:Document.Namespace @get:JvmName("getNamespace") internal val namespace: String = "",
 ) {
-  @get:Document.Id
-  @get:JvmName("getIdentifier")
-  internal val identifier: String
-    get() = ""
-
-  @get:Document.Namespace
-  @get:JvmName("getNamespace")
-  internal val namespace: String
-    get() = ""
-
   /** Constructor for the [LocalTime] variant. */
   public constructor(time: LocalTime) : this(asTime = time)
 
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt
new file mode 100644
index 0000000..5dfdb1e
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DayOfWeekAsCanonicalUrlSerializer.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appactions.builtintypes.types.DayOfWeek
+import androidx.appsearch.app.StringSerializer
+import kotlin.String
+import kotlin.collections.firstOrNull
+
+/**
+ * Serializes [DayOfWeek] as its canonical url String so it may be stored as a
+ * `@Document.StringProperty`.
+ *
+ * @see DayOfWeek.canonicalUrl
+ */
+public class DayOfWeekAsCanonicalUrlSerializer : StringSerializer<DayOfWeek> {
+  public override fun serialize(instance: DayOfWeek): String = instance.canonicalUrl
+
+  public override fun deserialize(`value`: String): DayOfWeek? =
+    DayOfWeek.values().firstOrNull { it.canonicalUrl == value }
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt
new file mode 100644
index 0000000..8645db9
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/DurationAsNanosSerializer.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appsearch.app.LongSerializer
+import java.time.Duration
+
+/**
+ * Serializes a [Duration] to nanos so it may be stored as a `@Document.LongProperty`.
+ *
+ * @see Duration.toNanos
+ */
+class DurationAsNanosSerializer : LongSerializer<Duration> {
+  override fun serialize(instance: Duration): Long = instance.toNanos()
+
+  override fun deserialize(value: Long): Duration = Duration.ofNanos(value)
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt
new file mode 100644
index 0000000..72c3fec
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/InstantAsEpochMilliSerializer.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appsearch.app.LongSerializer
+import java.time.Instant
+
+/**
+ * Serializes an [Instant] to epoch millis so it may be stored as a `@Document.LongProperty`.
+ *
+ * @see Instant.toEpochMilli
+ */
+class InstantAsEpochMilliSerializer : LongSerializer<Instant> {
+  override fun serialize(instance: Instant): Long = instance.toEpochMilli()
+
+  override fun deserialize(value: Long): Instant = Instant.ofEpochMilli(value)
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt
new file mode 100644
index 0000000..765cfba
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateAsEpochDaySerializer.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appsearch.app.LongSerializer
+import java.time.LocalDate
+
+/**
+ * Serializes a [LocalDate] to an epoch day so it may be stored as a `@Document.LongProperty`.
+ *
+ * @see LocalDate.toEpochDay
+ */
+class LocalDateAsEpochDaySerializer : LongSerializer<LocalDate> {
+  override fun serialize(instance: LocalDate): Long = instance.toEpochDay()
+
+  override fun deserialize(value: Long): LocalDate = LocalDate.ofEpochDay(value)
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt
new file mode 100644
index 0000000..14eb7e31
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalDateTimeAsUtcEpochSecondSerializer.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appsearch.app.LongSerializer
+import java.time.LocalDateTime
+import java.time.ZoneOffset
+
+/**
+ * Serializes a [LocalDateTime] as epoch seconds assuming the UTC timezone so it may be stored as a
+ * `@Document.LongProperty`.
+ *
+ * For example, 2023-08-14T18:30 is serialized as seconds(2023-08-14T18:30+00:00).
+ *
+ * @see LocalDateTime.toEpochSecond
+ * @see ZoneOffset.UTC
+ */
+class LocalDateTimeAsUtcEpochSecondSerializer : LongSerializer<LocalDateTime> {
+  override fun serialize(instance: LocalDateTime): Long = instance.toEpochSecond(ZoneOffset.UTC)
+
+  override fun deserialize(value: Long): LocalDateTime =
+    LocalDateTime.ofEpochSecond(value, /* nanoOfSecond= */ 0, ZoneOffset.UTC)
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt
new file mode 100644
index 0000000..1394afb
--- /dev/null
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/serializers/LocalTimeAsNanoOfDaySerializer.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.appactions.builtintypes.serializers
+
+import androidx.appsearch.app.LongSerializer
+import java.time.LocalTime
+
+/**
+ * Serializes a [LocalTime] to nanos so it may be stored as a `@Document.LongProperty`.
+ *
+ * @see LocalTime.toNanoOfDay
+ */
+class LocalTimeAsNanoOfDaySerializer : LongSerializer<LocalTime> {
+  override fun serialize(instance: LocalTime): Long = instance.toNanoOfDay()
+
+  override fun deserialize(value: Long): LocalTime = LocalTime.ofNanoOfDay(value)
+}
diff --git a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt
index 6f17b6e..4abefc7 100644
--- a/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt
+++ b/appactions/builtintypes/builtintypes/src/main/java/androidx/appactions/builtintypes/types/DayOfWeek.kt
@@ -14,7 +14,10 @@
 package androidx.appactions.builtintypes.types
 
 import kotlin.String
+import kotlin.collections.List
+import kotlin.collections.listOf
 import kotlin.jvm.JvmField
+import kotlin.jvm.JvmStatic
 
 /**
  * The day of the week.
@@ -86,6 +89,10 @@
     /** The day of the week between Tuesday and Thursday. */
     @JvmField
     public val WEDNESDAY: DayOfWeek = DayOfWeek(canonicalUrl = "http://schema.org/Wednesday")
+
+    @JvmStatic
+    public fun values(): List<DayOfWeek> =
+      listOf(FRIDAY, MONDAY, PUBLIC_HOLIDAYS, SATURDAY, SUNDAY, THURSDAY, TUESDAY, WEDNESDAY)
   }
 
   /** Maps each of the possible variants of [DayOfWeek] to some [R]. */
diff --git a/appactions/interaction/interaction-service-proto/build.gradle b/appactions/interaction/interaction-service-proto/build.gradle
index b2ab25e..7662e1a 100644
--- a/appactions/interaction/interaction-service-proto/build.gradle
+++ b/appactions/interaction/interaction-service-proto/build.gradle
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 import androidx.build.Publish
 import androidx.build.RunApiTasks
 
@@ -46,10 +47,6 @@
     compileOnly("androidx.annotation:annotation:1.1.0")
 }
 
-jar {
-    exclude "**/*.proto"
-}
-
 protobuf {
     protoc {
         artifact = libs.protobufCompiler.get()
@@ -61,9 +58,6 @@
         }
     }
 
-    // Generates the java proto-lite code for the protos in this project. See
-    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
-    // for more information.
     generateProtoTasks {
         // Add any additional directories specified in the "main" source set to the Java
         // source directories of the main source set.
diff --git a/appactions/interaction/interaction-service/build.gradle b/appactions/interaction/interaction-service/build.gradle
index d667215..dc3aa0a 100644
--- a/appactions/interaction/interaction-service/build.gradle
+++ b/appactions/interaction/interaction-service/build.gradle
@@ -31,7 +31,10 @@
             new BundleInsideHelper.Relocation(
                 /* from = */ "com.google.protobuf",
                 /* to =   */ "androidx.appactions.interaction.protobuf")
-        ]
+        ],
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
diff --git a/appsearch/appsearch-local-storage/build.gradle b/appsearch/appsearch-local-storage/build.gradle
index 35485ad..df4e5b0 100644
--- a/appsearch/appsearch-local-storage/build.gradle
+++ b/appsearch/appsearch-local-storage/build.gradle
@@ -62,11 +62,14 @@
 BundleInsideHelper.forInsideAar(
     project,
     /* from = */ "com.google.protobuf",
-    /* to =   */ "com.google.android.icing.protobuf"
+    /* to =   */ "com.google.android.icing.protobuf",
+    // proto-lite dependency includes .proto files, which are not used and would clash if
+    // users also use proto library directly
+    /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
-    bundleInside(project(path: ":icing", configuration: "exportRelease"))
+    bundleInside(project(":icing"))
 
     api("androidx.annotation:annotation:1.1.0")
 
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
index ac9027a..4c432b6 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Profiler.kt
@@ -30,6 +30,7 @@
 import androidx.benchmark.simpleperf.RecordOptions
 import androidx.benchmark.vmtrace.ArtTrace
 import java.io.File
+import java.io.FileOutputStream
 
 /**
  * Profiler abstraction used for the timing stage.
@@ -199,11 +200,9 @@
     override val requiresSingleMeasurementIteration: Boolean = true
 
     override fun embedInPerfettoTrace(profilerTrace: File, perfettoTrace: File) {
-        perfettoTrace.appendBytes(
-            ArtTrace(profilerTrace)
-                .toPerfettoTrace()
-                .encode()
-        )
+        ArtTrace(profilerTrace)
+            .toPerfettoTrace()
+            .encode(FileOutputStream(perfettoTrace, /* append = */ true))
     }
 }
 @SuppressLint("BanThreadSleep") // needed for connected profiling
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Shell.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Shell.kt
index 6811685..fed5b64 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Shell.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Shell.kt
@@ -612,8 +612,12 @@
 
     @RequiresApi(21)
     fun disablePackages(appPackages: List<String>) {
+        // Additionally use `am force-stop` to force JobScheduler to drop all jobs.
         val command = appPackages.joinToString(separator = "\n") { appPackage ->
-            "pm disable-user $appPackage"
+            """
+                am force-stop $appPackage
+                pm disable-user $appPackage
+            """".trimIndent()
         }
         executeScriptCaptureStdoutStderr(command)
     }
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/SideEffects.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/SideEffects.kt
index 4310393..cbc700e 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/SideEffects.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/SideEffects.kt
@@ -46,13 +46,20 @@
     }
 
     companion object {
-        // A list of packages to disable + "com.google.android.gms"
+        // A list of packages to disable
+        // google3/configs/wireless/android/testing/atp/prod/android-crystalball-eng/health/microbench/power/modifications.gcl
         // https://source.corp.google.com/piper///depot/google3/java/com/google/android/libraries/swpower/fixture/DisableModule.java
         internal val DEFAULT_PACKAGES_TO_DISABLE = listOf(
             "com.android.chrome",
-            "com.android.phone",
+            "com.android.dialer",
+            "com.android.dreams.basic",
+            "com.android.mms.service",
+            // b/247058855
+            // "com.android.phone",
             "com.android.ramdump",
+            "com.android.server.telecom",
             "com.android.vending",
+            "com.google.android.GoogleCamera",
             "com.google.android.apps.docs",
             "com.google.android.apps.gcs",
             "com.google.android.apps.internal.betterbug",
@@ -60,10 +67,14 @@
             "com.google.android.apps.messaging",
             "com.google.android.apps.nbu.files",
             "com.google.android.apps.photos",
+            "com.google.android.apps.pixelmigrate",
             "com.google.android.apps.scone",
+            "com.google.android.apps.speechservices",
+            "com.google.android.apps.tachyon",
             "com.google.android.apps.tips",
             "com.google.android.apps.turbo",
             "com.google.android.apps.tycho",
+            "com.google.android.apps.wellbeing",
             "com.google.android.apps.work.clouddpc",
             "com.google.android.apps.youtube.music",
             "com.google.android.as",
@@ -74,10 +85,9 @@
             "com.google.android.contacts",
             "com.google.android.deskclock",
             "com.google.android.dialer",
-            "com.google.android.googlequicksearchbox",
             "com.google.android.gm",
             "com.google.android.gms",
-            "com.google.android.GoogleCamera",
+            "com.google.android.googlequicksearchbox",
             "com.google.android.ims",
             "com.google.android.inputmethod.latin",
             "com.google.android.marvin.talkback",
@@ -85,9 +95,8 @@
             "com.google.android.settings.intelligence",
             "com.google.android.tts",
             "com.google.android.videos",
-            "com.google.android.youtube",
-            "com.google.android.videos",
-            "com.google.android.volta"
+            "com.google.android.volta",
+            "com.google.android.youtube"
         )
     }
 }
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
index c823e02..5eaa17c 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/perfetto/PerfettoCaptureWrapper.kt
@@ -27,7 +27,7 @@
 import androidx.benchmark.Shell
 import androidx.benchmark.perfetto.PerfettoHelper.Companion.LOG_TAG
 import androidx.benchmark.perfetto.PerfettoHelper.Companion.isAbiSupported
-import java.io.File
+import java.io.FileOutputStream
 
 /**
  * Wrapper for [PerfettoCapture] which does nothing below API 23.
@@ -137,7 +137,7 @@
 
                 if (inMemoryTracingLabel != null) {
                     val inMemoryTrace = InMemoryTracing.commitToTrace(inMemoryTracingLabel)
-                    File(path).appendBytes(inMemoryTrace.encode())
+                    inMemoryTrace.encode(FileOutputStream(path, /* append = */ true))
                 }
                 traceCallback?.invoke(path)
             }
diff --git a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/SideEffectRunListener.kt b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/SideEffectRunListener.kt
new file mode 100644
index 0000000..3aaa557
--- /dev/null
+++ b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/SideEffectRunListener.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 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.benchmark.macro.junit4
+
+import androidx.annotation.RestrictTo
+import androidx.benchmark.DisableDexOpt
+import androidx.benchmark.DisablePackages
+import androidx.benchmark.RunListenerDelegate
+import org.junit.runner.Description
+import org.junit.runner.Result
+import org.junit.runner.notification.RunListener
+
+/**
+ * Enables the use of side-effects that reduce the noise during a macro benchmark run.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+class SideEffectRunListener : RunListener() {
+    private val delegate: RunListenerDelegate = RunListenerDelegate(
+        sideEffects = listOf(
+            DisablePackages(),
+            DisableDexOpt(),
+        )
+    )
+
+    override fun testRunStarted(description: Description) {
+        super.testRunStarted(description)
+        delegate.onTestRunStarted()
+    }
+
+    override fun testRunFinished(result: Result) {
+        super.testRunFinished(result)
+        delegate.onTestRunFinished()
+    }
+}
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
index 2ce63cd..5bde073 100644
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
+++ b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/MacrobenchmarkScopeTest.kt
@@ -216,6 +216,8 @@
         )
         // Turn on method tracing
         scope.launchWithMethodTracing = true
+        // Force Method Tracing
+        scope.methodTracingForTests = true
         // Launch first activity, and validate it is displayed
         scope.startActivityAndWait(ConfigurableActivity.createIntent("InitialText"))
         assertTrue(device.hasObject(By.text("InitialText")))
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
index df00a1a..217cf5d 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/Macrobenchmark.kt
@@ -290,13 +290,14 @@
                             metrics.forEach {
                                 it.stop()
                             }
-                            if (launchWithMethodTracing) {
+                            if (launchWithMethodTracing && scope.isMethodTracing) {
                                 val (label, tracePath) = scope.stopMethodTracing()
                                 val resultFile = Profiler.ResultFile(
                                     label = label,
                                     absolutePath = tracePath
                                 )
                                 resultFiles += resultFile
+                                scope.isMethodTracing = false
                             }
                         }
                     }
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
index 12c949c..9b141c6 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/MacrobenchmarkScope.kt
@@ -22,6 +22,7 @@
 import android.os.Build
 import android.util.Log
 import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
 import androidx.benchmark.DeviceInfo
 import androidx.benchmark.Outputs
 import androidx.benchmark.Shell
@@ -62,6 +63,18 @@
     internal var launchWithMethodTracing: Boolean = false
 
     /**
+     * Only use this for testing. This forces `--start-profiler` without the check for process
+     * live ness.
+     */
+    @VisibleForTesting
+    internal var methodTracingForTests: Boolean = false
+
+    /**
+     * This is `true` iff method tracing is currently active.
+     */
+    internal var isMethodTracing: Boolean = false
+
+    /**
      * Current Macrobenchmark measurement iteration, or null if measurement is not yet enabled.
      *
      * Non-measurement iterations can occur due to warmup a [CompilationMode], or prior to the first
@@ -133,9 +146,16 @@
             getFrameStats().map { it.uniqueName }
         }
         val preLaunchTimestampNs = System.nanoTime()
-        val profileArgs = if (launchWithMethodTracing) {
+        // Only use --start-profiler is the package is not alive. Otherwise re-use the existing
+        // profiling session.
+        val profileArgs =
+            if (launchWithMethodTracing && (methodTracingForTests || !Shell.isPackageAlive(
+                    packageName
+                ))
+            ) {
+            isMethodTracing = true
             val tracePath = methodTracePath(packageName, iteration ?: 0)
-            "--start-profiler \"$tracePath\""
+            "--start-profiler \"$tracePath\" --streaming"
         } else {
             ""
         }
diff --git a/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattClientTest.kt b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattClientTest.kt
index 79560e5..7bab0cd 100644
--- a/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattClientTest.kt
+++ b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattClientTest.kt
@@ -31,7 +31,6 @@
 import androidx.bluetooth.BluetoothDevice
 import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.GattClient
-import java.nio.ByteBuffer
 import java.util.UUID
 import java.util.concurrent.atomic.AtomicInteger
 import junit.framework.TestCase.fail
@@ -476,12 +475,4 @@
             )
         }
     }
-
-    private fun Int.toByteArray(): ByteArray {
-        return ByteBuffer.allocate(Int.SIZE_BYTES).putInt(this).array()
-    }
-
-    private fun ByteArray.toInt(): Int {
-        return ByteBuffer.wrap(this).int
-    }
 }
diff --git a/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattServerTest.kt b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattServerTest.kt
index c7027b3..fea074b 100644
--- a/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattServerTest.kt
+++ b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/RobolectricGattServerTest.kt
@@ -32,7 +32,6 @@
 import androidx.bluetooth.GattServer
 import androidx.bluetooth.GattServerRequest
 import androidx.bluetooth.GattService
-import java.nio.ByteBuffer
 import java.util.UUID
 import junit.framework.TestCase.fail
 import kotlinx.coroutines.CompletableDeferred
@@ -72,23 +71,20 @@
 
         private val cccdUuid = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
 
-        private val readCharacteristic = GattCharacteristic.of(
-            readCharUuid,
-            PROPERTY_READ
-        )
-        private val writeCharacteristic = GattCharacteristic.of(
+        private val readCharacteristic = GattCharacteristic(readCharUuid, PROPERTY_READ)
+        private val writeCharacteristic = GattCharacteristic(
             writeCharUuid, PROPERTY_READ or PROPERTY_WRITE
         )
-        private val notifyCharacteristic = GattCharacteristic.of(
+        private val notifyCharacteristic = GattCharacteristic(
             notifyCharUuid, PROPERTY_READ or PROPERTY_NOTIFY
         )
-        private val unknownCharacteristic = GattCharacteristic.of(unknownCharUuid, 0)
+        private val unknownCharacteristic = GattCharacteristic(unknownCharUuid, 0)
 
-        private val service1 = GattService.of(
+        private val service1 = GattService(
             serviceUuid1,
             listOf(readCharacteristic, writeCharacteristic, notifyCharacteristic)
         )
-        private val service2 = GattService.of(serviceUuid2, listOf())
+        private val service2 = GattService(serviceUuid2, listOf())
     }
 
     @Before
@@ -113,7 +109,8 @@
                 closed.complete(Unit)
             }
 
-        bluetoothLe.openGattServer(listOf()).first().accept {
+        bluetoothLe.openGattServer(listOf()) {
+            connectRequest.first().accept {}
         }
 
         Assert.assertTrue(opened.isCompleted)
@@ -138,16 +135,16 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.reject()
-                Assert.assertThrows(
-                    IllegalStateException::class.java
-                ) {
-                    runBlocking {
-                        it.accept {}
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.reject()
+                    Assert.assertThrows(IllegalStateException::class.java) {
+                        runBlocking {
+                            it.accept {}
+                        }
                     }
+                    this@launch.cancel()
                 }
-                this@launch.cancel()
             }
         }.join()
 
@@ -173,16 +170,14 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.accept {}
-                Assert.assertThrows(
-                    IllegalStateException::class.java
-                ) {
-                    runBlocking {
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.accept {}
+                    Assert.assertThrows(IllegalStateException::class.java) {
                         it.reject()
                     }
+                    this@launch.cancel()
                 }
-                this@launch.cancel()
             }
         }.join()
 
@@ -209,16 +204,18 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.accept {
-                    when (val request = requests.first()) {
-                        is GattServerRequest.ReadCharacteristicRequest -> {
-                            request.sendResponse(true, valueToRead.toByteArray())
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.accept {
+                        when (val request = requests.first()) {
+                            is GattServerRequest.ReadCharacteristicRequest -> {
+                                request.sendResponse(true, valueToRead.toByteArray())
+                            }
+                            else -> fail("unexpected request")
                         }
-                        else -> fail("unexpected request")
+                        // Close the server
+                        this@launch.cancel()
                     }
-                    // Close the server
-                    this@launch.cancel()
                 }
             }
         }.join()
@@ -250,17 +247,20 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.accept {
-                    when (val request = requests.first()) {
-                        is GattServerRequest.ReadCharacteristicRequest -> {
-                            Assert.assertEquals(readCharacteristic, request.characteristic)
-                            request.sendResponse(true, valueToRead.toByteArray())
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.accept {
+                        when (val request = requests.first()) {
+                            is GattServerRequest.ReadCharacteristicRequest -> {
+                                Assert.assertEquals(readCharacteristic, request.characteristic)
+                                request.sendResponse(true, valueToRead.toByteArray())
+                            }
+
+                            else -> fail("unexpected request")
                         }
-                        else -> fail("unexpected request")
+                        // Close the server
+                        this@launch.cancel()
                     }
-                    // Close the server
-                    this@launch.cancel()
                 }
             }
         }.join()
@@ -288,17 +288,20 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.accept {
-                    when (val request = requests.first()) {
-                        is GattServerRequest.WriteCharacteristicRequest -> {
-                            Assert.assertEquals(valueToWrite, request.value?.toInt())
-                            request.sendResponse(true)
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.accept {
+                        when (val request = requests.first()) {
+                            is GattServerRequest.WriteCharacteristicRequest -> {
+                                Assert.assertEquals(valueToWrite, request.value?.toInt())
+                                request.sendResponse(true, request.value)
+                            }
+
+                            else -> fail("unexpected request")
                         }
-                        else -> fail("unexpected request")
+                        // Close the server
+                        this@launch.cancel()
                     }
-                    // Close the server
-                    this@launch.cancel()
                 }
             }
         }.join()
@@ -333,11 +336,13 @@
             }
 
         launch {
-            bluetoothLe.openGattServer(services).collect {
-                it.accept {
-                    notify(notifyCharacteristic, valueToNotify.toByteArray())
-                    // Close the server
-                    this@launch.cancel()
+            bluetoothLe.openGattServer(services) {
+                connectRequest.collect {
+                    it.accept {
+                        notify(notifyCharacteristic, valueToNotify.toByteArray())
+                        // Close the server
+                        this@launch.cancel()
+                    }
                 }
             }
         }.join()
@@ -363,11 +368,9 @@
             }
 
         launch {
-            opened.await()
-            bluetoothLe.updateServices(listOf(service2))
-        }
-        launch {
-            bluetoothLe.openGattServer(listOf(service1)).first().accept {
+            bluetoothLe.openGattServer(listOf(service1)) {
+                updateServices(listOf(service2))
+                connectRequest.first().accept {}
             }
         }.join()
 
@@ -470,11 +473,3 @@
         }
     }
 }
-
-private fun Int.toByteArray(): ByteArray {
-    return ByteBuffer.allocate(Int.SIZE_BYTES).putInt(this).array()
-}
-
-private fun ByteArray.toInt(): Int {
-    return ByteBuffer.wrap(this).int
-}
diff --git a/compose/material/material-icons-extended-filled/build.gradle b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/TestUtils.kt
similarity index 64%
copy from compose/material/material-icons-extended-filled/build.gradle
copy to bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/TestUtils.kt
index 5933def..d3872cf 100644
--- a/compose/material/material-icons-extended-filled/build.gradle
+++ b/bluetooth/bluetooth-testing/src/test/kotlin/androidx/bluetooth/testing/TestUtils.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2023 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.
@@ -14,8 +14,14 @@
  * limitations under the License.
  */
 
-apply from: "../material-icons-extended/generate.gradle"
+package androidx.bluetooth.testing
 
-android {
-    namespace "androidx.compose.material.icons.extended"
+import java.nio.ByteBuffer
+
+internal fun Int.toByteArray(): ByteArray {
+    return ByteBuffer.allocate(Int.SIZE_BYTES).putInt(this).array()
+}
+
+internal fun ByteArray.toInt(): Int {
+    return ByteBuffer.wrap(this).int
 }
diff --git a/bluetooth/bluetooth/api/current.txt b/bluetooth/bluetooth/api/current.txt
index b8ff05b..2bfa8e7 100644
--- a/bluetooth/bluetooth/api/current.txt
+++ b/bluetooth/bluetooth/api/current.txt
@@ -65,6 +65,7 @@
     ctor public BluetoothLe(android.content.Context context);
     method @RequiresPermission("android.permission.BLUETOOTH_ADVERTISE") public kotlinx.coroutines.flow.Flow<java.lang.Integer> advertise(androidx.bluetooth.AdvertiseParams advertiseParams);
     method @RequiresPermission("android.permission.BLUETOOTH_CONNECT") public suspend <R> Object? connectGatt(androidx.bluetooth.BluetoothDevice device, kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattClientScope,? super kotlin.coroutines.Continuation<? super R>,?> block, kotlin.coroutines.Continuation<? super kotlin.Result<? extends R>>);
+    method public suspend <R> Object? openGattServer(java.util.List<androidx.bluetooth.GattService> services, kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattServerConnectScope,? super kotlin.coroutines.Continuation<? super R>,?> block, kotlin.coroutines.Continuation<? super kotlin.Result<? extends R>>);
     method @RequiresPermission("android.permission.BLUETOOTH_SCAN") public kotlinx.coroutines.flow.Flow<androidx.bluetooth.ScanResult> scan(optional java.util.List<androidx.bluetooth.ScanFilter> filters);
   }
 
@@ -77,15 +78,36 @@
     method public suspend Object? writeCharacteristic(androidx.bluetooth.GattCharacteristic characteristic, byte[] value, kotlin.coroutines.Continuation<? super kotlin.Result<? extends kotlin.Unit>>);
   }
 
+  public static final class BluetoothLe.GattServerConnectRequest {
+    method public suspend Object? accept(kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattServerSessionScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.bluetooth.BluetoothDevice getDevice();
+    method public void reject();
+    property public final androidx.bluetooth.BluetoothDevice device;
+  }
+
+  public static interface BluetoothLe.GattServerConnectScope {
+    method public kotlinx.coroutines.flow.Flow<androidx.bluetooth.BluetoothLe.GattServerConnectRequest> getConnectRequest();
+    method public void updateServices(java.util.List<androidx.bluetooth.GattService> services);
+    property public abstract kotlinx.coroutines.flow.Flow<androidx.bluetooth.BluetoothLe.GattServerConnectRequest> connectRequest;
+  }
+
+  public static interface BluetoothLe.GattServerSessionScope {
+    method public androidx.bluetooth.BluetoothDevice getDevice();
+    method public kotlinx.coroutines.flow.Flow<androidx.bluetooth.GattServerRequest> getRequests();
+    method public void notify(androidx.bluetooth.GattCharacteristic characteristic, byte[] value);
+    property public abstract androidx.bluetooth.BluetoothDevice device;
+    property public abstract kotlinx.coroutines.flow.Flow<androidx.bluetooth.GattServerRequest> requests;
+  }
+
   public final class GattCharacteristic {
+    ctor public GattCharacteristic(java.util.UUID uuid, int properties);
     method public int getProperties();
     method public java.util.UUID getUuid();
-    method public static androidx.bluetooth.GattCharacteristic of(java.util.UUID uuid, int properties);
     property public final int properties;
     property public final java.util.UUID uuid;
     field public static final androidx.bluetooth.GattCharacteristic.Companion Companion;
     field public static final int PROPERTY_BROADCAST = 1; // 0x1
-    field public static final int PROPERTY_EXTENDS_PROP = 128; // 0x80
+    field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
     field public static final int PROPERTY_INDICATE = 32; // 0x20
     field public static final int PROPERTY_NOTIFY = 16; // 0x10
     field public static final int PROPERTY_READ = 2; // 0x2
@@ -95,21 +117,32 @@
   }
 
   public static final class GattCharacteristic.Companion {
-    method public androidx.bluetooth.GattCharacteristic of(java.util.UUID uuid, int properties);
+  }
+
+  public interface GattServerRequest {
+  }
+
+  public static final class GattServerRequest.ReadCharacteristicRequest implements androidx.bluetooth.GattServerRequest {
+    method public androidx.bluetooth.GattCharacteristic getCharacteristic();
+    method public void sendResponse(boolean success, byte[]? value);
+    property public final androidx.bluetooth.GattCharacteristic characteristic;
+  }
+
+  public static final class GattServerRequest.WriteCharacteristicRequest implements androidx.bluetooth.GattServerRequest {
+    method public androidx.bluetooth.GattCharacteristic getCharacteristic();
+    method public byte[]? getValue();
+    method public void sendResponse(boolean success, byte[]? value);
+    property public final androidx.bluetooth.GattCharacteristic characteristic;
+    property public final byte[]? value;
   }
 
   public final class GattService {
+    ctor public GattService(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
     method public androidx.bluetooth.GattCharacteristic? getCharacteristic(java.util.UUID uuid);
     method public java.util.List<androidx.bluetooth.GattCharacteristic> getCharacteristics();
     method public java.util.UUID getUuid();
-    method public static androidx.bluetooth.GattService of(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
     property public final java.util.List<androidx.bluetooth.GattCharacteristic> characteristics;
     property public final java.util.UUID uuid;
-    field public static final androidx.bluetooth.GattService.Companion Companion;
-  }
-
-  public static final class GattService.Companion {
-    method public androidx.bluetooth.GattService of(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
   }
 
   public final class ScanFilter {
diff --git a/bluetooth/bluetooth/api/restricted_current.txt b/bluetooth/bluetooth/api/restricted_current.txt
index b8ff05b..2bfa8e7 100644
--- a/bluetooth/bluetooth/api/restricted_current.txt
+++ b/bluetooth/bluetooth/api/restricted_current.txt
@@ -65,6 +65,7 @@
     ctor public BluetoothLe(android.content.Context context);
     method @RequiresPermission("android.permission.BLUETOOTH_ADVERTISE") public kotlinx.coroutines.flow.Flow<java.lang.Integer> advertise(androidx.bluetooth.AdvertiseParams advertiseParams);
     method @RequiresPermission("android.permission.BLUETOOTH_CONNECT") public suspend <R> Object? connectGatt(androidx.bluetooth.BluetoothDevice device, kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattClientScope,? super kotlin.coroutines.Continuation<? super R>,?> block, kotlin.coroutines.Continuation<? super kotlin.Result<? extends R>>);
+    method public suspend <R> Object? openGattServer(java.util.List<androidx.bluetooth.GattService> services, kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattServerConnectScope,? super kotlin.coroutines.Continuation<? super R>,?> block, kotlin.coroutines.Continuation<? super kotlin.Result<? extends R>>);
     method @RequiresPermission("android.permission.BLUETOOTH_SCAN") public kotlinx.coroutines.flow.Flow<androidx.bluetooth.ScanResult> scan(optional java.util.List<androidx.bluetooth.ScanFilter> filters);
   }
 
@@ -77,15 +78,36 @@
     method public suspend Object? writeCharacteristic(androidx.bluetooth.GattCharacteristic characteristic, byte[] value, kotlin.coroutines.Continuation<? super kotlin.Result<? extends kotlin.Unit>>);
   }
 
+  public static final class BluetoothLe.GattServerConnectRequest {
+    method public suspend Object? accept(kotlin.jvm.functions.Function2<? super androidx.bluetooth.BluetoothLe.GattServerSessionScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public androidx.bluetooth.BluetoothDevice getDevice();
+    method public void reject();
+    property public final androidx.bluetooth.BluetoothDevice device;
+  }
+
+  public static interface BluetoothLe.GattServerConnectScope {
+    method public kotlinx.coroutines.flow.Flow<androidx.bluetooth.BluetoothLe.GattServerConnectRequest> getConnectRequest();
+    method public void updateServices(java.util.List<androidx.bluetooth.GattService> services);
+    property public abstract kotlinx.coroutines.flow.Flow<androidx.bluetooth.BluetoothLe.GattServerConnectRequest> connectRequest;
+  }
+
+  public static interface BluetoothLe.GattServerSessionScope {
+    method public androidx.bluetooth.BluetoothDevice getDevice();
+    method public kotlinx.coroutines.flow.Flow<androidx.bluetooth.GattServerRequest> getRequests();
+    method public void notify(androidx.bluetooth.GattCharacteristic characteristic, byte[] value);
+    property public abstract androidx.bluetooth.BluetoothDevice device;
+    property public abstract kotlinx.coroutines.flow.Flow<androidx.bluetooth.GattServerRequest> requests;
+  }
+
   public final class GattCharacteristic {
+    ctor public GattCharacteristic(java.util.UUID uuid, int properties);
     method public int getProperties();
     method public java.util.UUID getUuid();
-    method public static androidx.bluetooth.GattCharacteristic of(java.util.UUID uuid, int properties);
     property public final int properties;
     property public final java.util.UUID uuid;
     field public static final androidx.bluetooth.GattCharacteristic.Companion Companion;
     field public static final int PROPERTY_BROADCAST = 1; // 0x1
-    field public static final int PROPERTY_EXTENDS_PROP = 128; // 0x80
+    field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
     field public static final int PROPERTY_INDICATE = 32; // 0x20
     field public static final int PROPERTY_NOTIFY = 16; // 0x10
     field public static final int PROPERTY_READ = 2; // 0x2
@@ -95,21 +117,32 @@
   }
 
   public static final class GattCharacteristic.Companion {
-    method public androidx.bluetooth.GattCharacteristic of(java.util.UUID uuid, int properties);
+  }
+
+  public interface GattServerRequest {
+  }
+
+  public static final class GattServerRequest.ReadCharacteristicRequest implements androidx.bluetooth.GattServerRequest {
+    method public androidx.bluetooth.GattCharacteristic getCharacteristic();
+    method public void sendResponse(boolean success, byte[]? value);
+    property public final androidx.bluetooth.GattCharacteristic characteristic;
+  }
+
+  public static final class GattServerRequest.WriteCharacteristicRequest implements androidx.bluetooth.GattServerRequest {
+    method public androidx.bluetooth.GattCharacteristic getCharacteristic();
+    method public byte[]? getValue();
+    method public void sendResponse(boolean success, byte[]? value);
+    property public final androidx.bluetooth.GattCharacteristic characteristic;
+    property public final byte[]? value;
   }
 
   public final class GattService {
+    ctor public GattService(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
     method public androidx.bluetooth.GattCharacteristic? getCharacteristic(java.util.UUID uuid);
     method public java.util.List<androidx.bluetooth.GattCharacteristic> getCharacteristics();
     method public java.util.UUID getUuid();
-    method public static androidx.bluetooth.GattService of(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
     property public final java.util.List<androidx.bluetooth.GattCharacteristic> characteristics;
     property public final java.util.UUID uuid;
-    field public static final androidx.bluetooth.GattService.Companion Companion;
-  }
-
-  public static final class GattService.Companion {
-    method public androidx.bluetooth.GattService of(java.util.UUID uuid, java.util.List<androidx.bluetooth.GattCharacteristic> characteristics);
   }
 
   public final class ScanFilter {
diff --git a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattCharacteristicTest.kt b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattCharacteristicTest.kt
index 048cf65..04daa45 100644
--- a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattCharacteristicTest.kt
+++ b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattCharacteristicTest.kt
@@ -31,7 +31,7 @@
             FwkCharacteristic.PROPERTY_BROADCAST to
                 GattCharacteristic.PROPERTY_BROADCAST,
             FwkCharacteristic.PROPERTY_EXTENDED_PROPS to
-                GattCharacteristic.PROPERTY_EXTENDS_PROP,
+                GattCharacteristic.PROPERTY_EXTENDED_PROPS,
             FwkCharacteristic.PROPERTY_INDICATE to
                 GattCharacteristic.PROPERTY_INDICATE,
             FwkCharacteristic.PROPERTY_NOTIFY
@@ -63,7 +63,7 @@
 
         val properties = GattCharacteristic.PROPERTY_READ
 
-        val characteristic = GattCharacteristic.of(uuid, properties)
+        val characteristic = GattCharacteristic(uuid, properties)
 
         Assert.assertEquals(uuid, characteristic.uuid)
         Assert.assertEquals(properties, characteristic.properties)
diff --git a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattServiceTest.kt b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattServiceTest.kt
index babeb61e..b32eab9 100644
--- a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattServiceTest.kt
+++ b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/GattServiceTest.kt
@@ -58,13 +58,13 @@
         val charUuid2 = UUID.randomUUID()
         val charUuid3 = UUID.randomUUID()
 
-        val char1 = GattCharacteristic.of(charUuid1, /*properties=*/0)
-        val char2 = GattCharacteristic.of(charUuid2, /*properties=*/0)
-        val char3 = GattCharacteristic.of(charUuid3, /*properties=*/0)
+        val char1 = GattCharacteristic(charUuid1, /*properties=*/0)
+        val char2 = GattCharacteristic(charUuid2, /*properties=*/0)
+        val char3 = GattCharacteristic(charUuid3, /*properties=*/0)
 
         val characteristics = mutableListOf(char1, char2)
 
-        val gattService = GattService.of(serviceUuid, characteristics)
+        val gattService = GattService(serviceUuid, characteristics)
 
         assertEquals(serviceUuid, gattService.uuid)
         assertEquals(2, gattService.characteristics.size)
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothLe.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothLe.kt
index 06074cb..e59357f 100644
--- a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothLe.kt
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/BluetoothLe.kt
@@ -243,46 +243,36 @@
     }
 
     /**
-     * Represents a client connection request from a remote device.
+     * A scope for handling connect requests from remote devices.
      *
-     * @property device the remote device connecting to the server
+     * @property connectRequest connect requests from remote devices.
+     *
+     * @see BluetoothLe#openGattServer
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    class GattServerConnectionRequest internal constructor(
-        val device: BluetoothDevice,
-        private val server: GattServer,
-        internal val session: GattServer.Session,
-    ) {
+    interface GattServerConnectScope {
         /**
-         * Accepts the connection request and handles incoming requests after that.
-         *
-         * Requests from the client before calling this should be saved.
-         *
-         * @see GattServerScope
+         * A _hot_ flow of [GattServerConnectRequest].
          */
-        suspend fun accept(block: suspend GattServerScope.() -> Unit) {
-            return server.acceptConnection(this, block)
-        }
+        val connectRequest: Flow<GattServerConnectRequest>
 
         /**
-         * Rejects the connection request.
+         * Updates the services of the opened GATT server.
          *
-         * All the requests from the client will be rejected.
+         * @param services the new services that will be notified to the clients.
          */
-        fun reject() {
-            return server.rejectConnection(this)
-        }
+        fun updateServices(services: List<GattService>)
     }
 
     /**
      * A scope for operations as a GATT server role.
      *
+     * A scope is created for each remote device.
+     *
      * Collect [requests] to respond with requests from the client.
      *
-     * @see GattServerConnectionRequest#accept()
+     * @see GattServerConnectRequest#accept()
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    interface GattServerScope {
+    interface GattServerSessionScope {
         /**
          * A client device connected to the server.
          */
@@ -306,31 +296,54 @@
     }
 
     /**
-     * Opens a GATT server.
+     * Represents a connect request from a remote device.
      *
-     * It returns a _cold_ [Flow] of connection requests.
-     * If the flow is cancelled, the server will be closed.
-     *
-     * Only one server at a time can be opened.
-     *
-     * @param services the services that will be exposed to the clients.
-     *
-     * @see GattServerConnectionRequest
+     * @property device the remote device connecting to the server
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    fun openGattServer(services: List<GattService>): Flow<GattServerConnectionRequest> {
-        return server.open(services)
+    class GattServerConnectRequest internal constructor(
+        private val session: GattServer.Session,
+    ) {
+        val device: BluetoothDevice
+            get() = session.device
+        /**
+         * Accepts the connect request and handles incoming requests after that.
+         *
+         * Requests from the client before calling this should be saved.
+         *
+         * @param block a block of code that is invoked after the connection is made.
+         *
+         * @see GattServerSessionScope
+         */
+        suspend fun accept(block: suspend GattServerSessionScope.() -> Unit) {
+            return session.acceptConnection(block)
+        }
+
+        /**
+         * Rejects the connect request.
+         *
+         * All the requests from the client will be rejected.
+         */
+        fun reject() {
+            return session.rejectConnection()
+        }
     }
 
     /**
-     * Updates the services of the opened GATT server.
-     * It will be ignored if there is no opened server.
+     * Opens a GATT server.
      *
-     * @param services the new services that will be notified to the clients
+     *
+     * Only one server at a time can be opened.
+     *
+     * @param services the services that will be exposed to the clients
+     * @param block a block of code that is invoked after the server is opened
+     *
+     * @see GattServerConnectRequest
      */
-    @RestrictTo(RestrictTo.Scope.LIBRARY)
-    fun updateServices(services: List<GattService>) {
-        server.updateServices(services)
+    suspend fun <R> openGattServer(
+        services: List<GattService>,
+        block: suspend GattServerConnectScope.() -> R
+    ): Result<R> {
+        return server.open(services, block)
     }
 
     @VisibleForTesting
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattCharacteristic.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattCharacteristic.kt
index c567f8e..986be1f 100644
--- a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattCharacteristic.kt
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattCharacteristic.kt
@@ -17,6 +17,7 @@
 package androidx.bluetooth
 
 import android.bluetooth.BluetoothGattCharacteristic as FwkCharacteristic
+import androidx.annotation.IntDef
 import androidx.annotation.RestrictTo
 import java.util.UUID
 
@@ -28,6 +29,21 @@
     @set:RestrictTo(RestrictTo.Scope.LIBRARY)
     var fwkCharacteristic: FwkCharacteristic
 ) {
+    @Target(AnnotationTarget.TYPE)
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @Retention(AnnotationRetention.SOURCE)
+    @IntDef(flag = true, value = [
+        PROPERTY_BROADCAST,
+        PROPERTY_READ,
+        PROPERTY_WRITE_NO_RESPONSE,
+        PROPERTY_WRITE,
+        PROPERTY_NOTIFY,
+        PROPERTY_INDICATE,
+        PROPERTY_SIGNED_WRITE,
+        PROPERTY_EXTENDED_PROPS
+    ])
+    annotation class Property
+
     companion object {
         /**
          * It permits broadcasts of the characteristic.
@@ -67,13 +83,10 @@
         /**
          * Additional characteristic properties are defined.
          */
-        const val PROPERTY_EXTENDS_PROP = FwkCharacteristic.PROPERTY_EXTENDED_PROPS
+        const val PROPERTY_EXTENDED_PROPS = FwkCharacteristic.PROPERTY_EXTENDED_PROPS
 
-        /**
-         * Creates a [GattCharacteristic] instance for a GATT server.
-         */
         @JvmStatic
-        fun of(uuid: UUID, properties: Int): GattCharacteristic {
+        private fun getPermissionsWithProperties(properties: @Property Int): Int {
             var permissions = 0
             if ((properties and PROPERTY_READ) != 0) {
                 permissions = permissions or FwkCharacteristic.PERMISSION_READ
@@ -84,11 +97,14 @@
             if ((properties and PROPERTY_SIGNED_WRITE) != 0) {
                 permissions = permissions or FwkCharacteristic.PERMISSION_WRITE_SIGNED
             }
-            val fwkCharacteristic = FwkCharacteristic(uuid, properties, permissions)
-            return GattCharacteristic(fwkCharacteristic)
+            return permissions
         }
     }
 
+    constructor(uuid: UUID, properties: @Property Int) :
+        this(FwkCharacteristic(uuid, properties, getPermissionsWithProperties(properties))) {
+    }
+
     /**
      * The UUID of the characteristic.
      */
@@ -98,7 +114,7 @@
     /**
      * The properties of the characteristic.
      */
-    val properties: Int
+    val properties: @Property Int
         get() = fwkCharacteristic.properties
 
     /**
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServer.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServer.kt
index 61186f0..6d2edf4 100644
--- a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServer.kt
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServer.kt
@@ -32,11 +32,9 @@
 import androidx.annotation.RestrictTo
 import androidx.annotation.VisibleForTesting
 import java.util.concurrent.atomic.AtomicBoolean
-import java.util.concurrent.atomic.AtomicReference
+import java.util.concurrent.atomic.AtomicInteger
 import kotlinx.coroutines.channels.Channel
 import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.receiveAsFlow
 
@@ -66,25 +64,25 @@
         )
     }
 
+    internal interface Session {
+        companion object {
+            const val STATE_DISCONNECTED = 0
+            const val STATE_CONNECTING = 1
+            const val STATE_CONNECTED = 2
+        }
+
+        val device: BluetoothDevice
+
+        suspend fun acceptConnection(block: suspend BluetoothLe.GattServerSessionScope.() -> Unit)
+        fun rejectConnection()
+
+        fun sendResponse(requestId: Int, status: Int, offset: Int, value: ByteArray?)
+    }
+
     private companion object {
         private const val TAG = "GattServer"
     }
 
-    internal class Session {
-        enum class State {
-            DISCONNECTED,
-            CONNECTING,
-            CONNECTED,
-        }
-
-        var state: AtomicReference<State> = AtomicReference(State.CONNECTING)
-        val requestChannel = Channel<GattServerRequest>(Channel.UNLIMITED)
-    }
-
-    // Should be accessed only from the callback thread
-    private val sessions: MutableMap<FwkDevice, Session> = mutableMapOf()
-    private val attributeMap = AttributeMap()
-
     @SuppressLint("ObsoleteSdkInt")
     @VisibleForTesting
     @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -92,144 +90,176 @@
         if (Build.VERSION.SDK_INT >= 33) FrameworkAdapterApi33()
         else FrameworkAdapterBase()
 
-    fun open(services: List<GattService>):
-        Flow<BluetoothLe.GattServerConnectionRequest> = callbackFlow {
-        attributeMap.updateWithServices(services)
-        val callback = object : BluetoothGattServerCallback() {
-            override fun onConnectionStateChange(
-                device: FwkDevice,
-                status: Int,
-                newState: Int
-            ) {
-                when (newState) {
-                    BluetoothProfile.STATE_CONNECTED -> {
-                        trySend(
-                            BluetoothLe.GattServerConnectionRequest(
-                                BluetoothDevice(device),
-                                this@GattServer,
-                                addSession(device)
-                            )
-                        )
+    suspend fun <R> open(
+        services: List<GattService>,
+        block: suspend BluetoothLe.GattServerConnectScope.() -> R
+    ): Result<R> {
+        return Result.success(createServerScope(services).block())
+    }
+
+    private fun createServerScope(services: List<GattService>): BluetoothLe.GattServerConnectScope {
+        return object : BluetoothLe.GattServerConnectScope {
+            private val attributeMap = AttributeMap()
+            // Should be accessed only from the callback thread
+            private val sessions: MutableMap<FwkDevice, Session> = mutableMapOf()
+
+            override val connectRequest = callbackFlow {
+                    attributeMap.updateWithServices(services)
+                    val callback = object : BluetoothGattServerCallback() {
+                        override fun onConnectionStateChange(
+                            device: FwkDevice,
+                            status: Int,
+                            newState: Int
+                        ) {
+                            when (newState) {
+                                BluetoothProfile.STATE_CONNECTED -> {
+                                    trySend(
+                                        BluetoothLe.GattServerConnectRequest(
+                                            addSession(device)
+                                        )
+                                    )
+                                }
+
+                                BluetoothProfile.STATE_DISCONNECTED -> removeSession(device)
+                            }
+                        }
+
+                        override fun onCharacteristicReadRequest(
+                            device: FwkDevice,
+                            requestId: Int,
+                            offset: Int,
+                            characteristic: FwkCharacteristic
+                        ) {
+                            attributeMap.fromFwkCharacteristic(characteristic)?.let { char ->
+                                findActiveSessionWithDevice(device)?.run {
+                                    requestChannel.trySend(
+                                        GattServerRequest.ReadCharacteristicRequest(
+                                            this, requestId, offset, char
+                                        )
+                                    )
+                                }
+                            } ?: run {
+                                fwkAdapter.sendResponse(
+                                    device, requestId, BluetoothGatt.GATT_READ_NOT_PERMITTED,
+                                    offset, /*value=*/null
+                                )
+                            }
+                        }
+
+                        override fun onCharacteristicWriteRequest(
+                            device: FwkDevice,
+                            requestId: Int,
+                            characteristic: FwkCharacteristic,
+                            preparedWrite: Boolean,
+                            responseNeeded: Boolean,
+                            offset: Int,
+                            value: ByteArray?
+                        ) {
+                            // TODO(b/296505524): handle preparedWrite == true
+                            attributeMap.fromFwkCharacteristic(characteristic)?.let {
+                                findActiveSessionWithDevice(device)?.run {
+                                    requestChannel.trySend(
+                                        GattServerRequest.WriteCharacteristicRequest(
+                                            this,
+                                            requestId,
+                                            it,
+                                            value
+                                        )
+                                    )
+                                }
+                            } ?: run {
+                                fwkAdapter.sendResponse(
+                                    device, requestId, BluetoothGatt.GATT_WRITE_NOT_PERMITTED,
+                                    offset, /*value=*/null
+                                )
+                            }
+                        }
                     }
-                    BluetoothProfile.STATE_DISCONNECTED -> removeSession(device)
+                    fwkAdapter.openGattServer(context, callback)
+                    services.forEach { fwkAdapter.addService(it.fwkService) }
+
+                    awaitClose {
+                        fwkAdapter.closeGattServer()
+                    }
+                }
+
+            override fun updateServices(services: List<GattService>) {
+                fwkAdapter.clearServices()
+                services.forEach { fwkAdapter.addService(it.fwkService) }
+            }
+
+            fun addSession(device: FwkDevice): Session {
+                return Session(BluetoothDevice(device)).apply {
+                    sessions[device] = this
                 }
             }
 
-            override fun onCharacteristicReadRequest(
-                device: FwkDevice,
-                requestId: Int,
-                offset: Int,
-                characteristic: FwkCharacteristic
-            ) {
-                attributeMap.fromFwkCharacteristic(characteristic)?.let {
-                    findActiveSessionWithDevice(device)?.requestChannel?.trySend(
-                        GattServerRequest.ReadCharacteristicRequest(
-                            this@GattServer, device, requestId, offset, it
+            fun removeSession(device: FwkDevice) {
+                sessions.remove(device)
+            }
+
+            fun findActiveSessionWithDevice(device: FwkDevice): Session? {
+                return sessions[device]?.takeIf {
+                    it.state.get() != GattServer.Session.STATE_DISCONNECTED
+                }
+            }
+
+            inner class Session(override val device: BluetoothDevice) : GattServer.Session {
+
+                val state: AtomicInteger = AtomicInteger(GattServer.Session.STATE_CONNECTING)
+                val requestChannel = Channel<GattServerRequest>(Channel.UNLIMITED)
+
+                override suspend fun acceptConnection(
+                    block: suspend BluetoothLe.GattServerSessionScope.() -> Unit
+                ) {
+                    if (!state.compareAndSet(
+                            GattServer.Session.STATE_CONNECTING,
+                            GattServer.Session.STATE_CONNECTED
                         )
-                    )
-                } ?: run {
-                    sendResponse(device, requestId, BluetoothGatt.GATT_READ_NOT_PERMITTED, offset,
-                        /*value=*/null)
-                }
-            }
+                    ) {
+                        throw IllegalStateException("the request is already handled")
+                    }
 
-            override fun onCharacteristicWriteRequest(
-                device: FwkDevice,
-                requestId: Int,
-                characteristic: FwkCharacteristic,
-                preparedWrite: Boolean,
-                responseNeeded: Boolean,
-                offset: Int,
-                value: ByteArray?
-            ) {
-                attributeMap.fromFwkCharacteristic(characteristic)?.let {
-                    findActiveSessionWithDevice(device)?.requestChannel?.trySend(
-                        GattServerRequest.WriteCharacteristicRequest(
-                            this@GattServer,
-                            device,
-                            requestId,
-                            it,
-                            preparedWrite,
-                            responseNeeded,
-                            offset,
-                            value
+                    val scope = object : BluetoothLe.GattServerSessionScope {
+                        override val device: BluetoothDevice
+                            get() = this@Session.device
+                        override val requests = requestChannel.receiveAsFlow()
+
+                        override fun notify(
+                            characteristic: GattCharacteristic,
+                            value: ByteArray
+                        ) {
+                            fwkAdapter.notifyCharacteristicChanged(
+                                device.fwkDevice,
+                                characteristic.fwkCharacteristic,
+                                false,
+                                value
+                            )
+                        }
+                    }
+                    scope.block()
+                }
+
+                override fun rejectConnection() {
+                    if (!state.compareAndSet(
+                            GattServer.Session.STATE_CONNECTING,
+                            GattServer.Session.STATE_DISCONNECTED
                         )
-                    )
-                } ?: run {
-                    sendResponse(device, requestId, BluetoothGatt.GATT_WRITE_NOT_PERMITTED,
-                        offset, /*value=*/null)
+                    ) {
+                        throw IllegalStateException("the request is already handled")
+                    }
+                }
+
+                override fun sendResponse(
+                    requestId: Int,
+                    status: Int,
+                    offset: Int,
+                    value: ByteArray?
+                ) {
+                    fwkAdapter.sendResponse(device.fwkDevice, requestId, status, offset, value)
                 }
             }
         }
-        fwkAdapter.openGattServer(context, callback)
-        services.forEach { fwkAdapter.addService(it.fwkService) }
-
-        awaitClose {
-            fwkAdapter.closeGattServer()
-        }
-    }
-
-    fun updateServices(services: List<GattService>) {
-        fwkAdapter.clearServices()
-        services.forEach { fwkAdapter.addService(it.fwkService) }
-    }
-
-    suspend fun<R> acceptConnection(
-        request: BluetoothLe.GattServerConnectionRequest,
-        block: suspend BluetoothLe.GattServerScope.() -> R
-    ) = coroutineScope {
-        val session = request.session
-        if (!session.state.compareAndSet(Session.State.CONNECTING, Session.State.CONNECTED)) {
-            throw IllegalStateException("the request is already handled")
-        }
-        val scope = object : BluetoothLe.GattServerScope {
-            override val device: BluetoothDevice
-                get() = request.device
-            override val requests = session.requestChannel.receiveAsFlow()
-
-            override fun notify(
-                characteristic: GattCharacteristic,
-                value: ByteArray
-            ) {
-                fwkAdapter.notifyCharacteristicChanged(
-                    request.device.fwkDevice, characteristic.fwkCharacteristic, false, value)
-            }
-        }
-        scope.block()
-    }
-
-    @SuppressLint("MissingPermission")
-    fun rejectConnection(request: BluetoothLe.GattServerConnectionRequest) {
-        if (!request.session.state.compareAndSet(
-                Session.State.CONNECTING, Session.State.DISCONNECTED)) {
-            throw IllegalStateException("the request is already handled")
-        }
-    }
-
-    internal fun findActiveSessionWithDevice(device: FwkDevice): Session? {
-        return sessions[device]?.takeIf {
-            it.state.get() != Session.State.DISCONNECTED
-        }
-    }
-
-    internal fun addSession(device: FwkDevice): Session {
-        return Session().apply {
-            sessions[device] = this
-        }
-    }
-
-    internal fun removeSession(device: FwkDevice) {
-        sessions.remove(device)
-    }
-
-    internal fun sendResponse(
-        device: FwkDevice,
-        requestId: Int,
-        status: Int,
-        offset: Int,
-        value: ByteArray?
-    ) {
-        fwkAdapter.sendResponse(device, requestId, status, offset, value)
     }
 
     private open class FrameworkAdapterBase : FrameworkAdapter {
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServerRequest.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServerRequest.kt
index a386bc8..8dd6554 100644
--- a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServerRequest.kt
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattServerRequest.kt
@@ -16,48 +16,69 @@
 
 package androidx.bluetooth
 
-import android.bluetooth.BluetoothDevice as FwkDevice
 import android.bluetooth.BluetoothGatt.GATT_READ_NOT_PERMITTED
 import android.bluetooth.BluetoothGatt.GATT_SUCCESS
 import android.bluetooth.BluetoothGatt.GATT_WRITE_NOT_PERMITTED
-import androidx.annotation.RestrictTo
 
-@RestrictTo(RestrictTo.Scope.LIBRARY)
+/**
+ * Represents a request to be handled as a GATT server role.
+ *
+ * @see BluetoothLe.GattServerConnectRequest.accept
+ */
 interface GattServerRequest {
+    /**
+     * Represents a read characteristic request.
+     *
+     * @property characteristic a characteristic to read
+     */
     class ReadCharacteristicRequest internal constructor(
-        private val server: GattServer,
-        internal val device: FwkDevice,
+        private val session: GattServer.Session,
         private val requestId: Int,
-        val offset: Int,
+        private val offset: Int,
         val characteristic: GattCharacteristic
     ) : GattServerRequest {
+        /**
+         * Sends the result for the read request.
+         *
+         * @param success true if the request was successful
+         * @param value a value of the characteristic or `null` if it failed.
+         */
         fun sendResponse(success: Boolean, value: ByteArray?) {
-            server.sendResponse(
-                device,
+            val resValue: ByteArray? = if (offset == 0 || value == null) value
+            else if (value.size > offset) value.copyOfRange(offset, value.size - 1)
+            else ByteArray(0)
+            session.sendResponse(
                 requestId,
                 if (success) GATT_SUCCESS else GATT_READ_NOT_PERMITTED,
                 offset,
-                value
+                resValue
             )
         }
     }
 
+    /**
+     * Represents a write characteristic request.
+     *
+     * @property characteristic a characteristic to write
+     * @property value a value to write
+     */
     class WriteCharacteristicRequest internal constructor(
-        private val server: GattServer,
-        internal val device: FwkDevice,
+        private val session: GattServer.Session,
         private val requestId: Int,
         val characteristic: GattCharacteristic,
-        val isPreparedWrite: Boolean,
-        val shouldResponse: Boolean,
-        val offset: Int,
         val value: ByteArray?
     ) : GattServerRequest {
-        fun sendResponse(success: Boolean) {
-            server.sendResponse(
-                device,
+        /**
+         * Sends the result for the write request.
+         *
+         * @param success true if the request was successful
+         * @param value an optional value that is written
+         */
+        fun sendResponse(success: Boolean, value: ByteArray?) {
+            session.sendResponse(
                 requestId,
                 if (success) GATT_SUCCESS else GATT_WRITE_NOT_PERMITTED,
-                offset,
+                0,
                 value
             )
         }
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattService.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattService.kt
index be68d9c..1372c32 100644
--- a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattService.kt
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/GattService.kt
@@ -26,28 +26,28 @@
     internal val fwkService: FwkService,
     characteristics: List<GattCharacteristic>? = null
 ) {
+    /**
+     * the UUID of the service
+     */
     val uuid: UUID
         get() = fwkService.uuid
+
+    /**
+     * a list of characteristics included in the service
+     */
     val characteristics: List<GattCharacteristic>
 
+    constructor(uuid: UUID, characteristics: List<GattCharacteristic>) :
+        this(FwkService(uuid, FwkService.SERVICE_TYPE_PRIMARY), characteristics) {
+        characteristics.forEach { fwkService.addCharacteristic(it.fwkCharacteristic) }
+    }
+
     init {
         this.characteristics = characteristics?.toList()
             ?: fwkService.characteristics.map { GattCharacteristic(it) }
         this.characteristics.forEach { it.service = this }
     }
 
-    companion object {
-        /**
-         * Creates a [GattService] instance for a GATT server.
-         */
-        @JvmStatic
-        fun of(uuid: UUID, characteristics: List<GattCharacteristic>): GattService {
-            val fwkService = FwkService(uuid, FwkService.SERVICE_TYPE_PRIMARY)
-            characteristics.forEach { fwkService.addCharacteristic(it.fwkCharacteristic) }
-            return GattService(fwkService, characteristics)
-        }
-    }
-
     /**
      * Gets a [GattCharacteristic] in the service with the given UUID.
      *
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
index fa4374f..89a87ca 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
@@ -33,7 +33,6 @@
 import androidx.bluetooth.AdvertiseResult
 import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.GattCharacteristic
-import androidx.bluetooth.GattCharacteristic.Companion.PROPERTY_READ
 import androidx.bluetooth.GattServerRequest
 import androidx.bluetooth.GattService
 import androidx.bluetooth.integration.testapp.R
@@ -372,7 +371,7 @@
                             else -> editTextInput
                         }
                     )
-                    val service = GattService.of(uuid, listOf())
+                    val service = GattService(uuid, listOf())
                     viewModel.addGattService(service)
                     gattServerServicesAdapter
                         ?.notifyItemInserted(viewModel.gattServerServices.size - 1)
@@ -439,7 +438,7 @@
                             else -> uuidText
                         }
                     )
-                    val sampleCharacteristic = GattCharacteristic.of(uuid, properties)
+                    val sampleCharacteristic = GattCharacteristic(uuid, properties)
 
                     val index = viewModel.gattServerServices.indexOf(bluetoothGattService)
                     viewModel.addGattCharacteristic(bluetoothGattService, sampleCharacteristic)
@@ -460,18 +459,20 @@
         gattServerJob = gattServerScope.launch {
             isGattServerOpen = true
 
-            bluetoothLe.openGattServer(viewModel.gattServerServices).collect {
-                launch {
-                    it.accept {
-                        launch {
+            bluetoothLe.openGattServer(viewModel.gattServerServices) {
+                connectRequest.collect {
+                    launch {
+                        it.accept {
                             requests.collect {
                                 when (it) {
                                     is GattServerRequest.ReadCharacteristicRequest ->
                                         it.sendResponse(/*success=*/true,
-                                            ByteBuffer.allocate(Int.SIZE_BYTES).putInt(1).array())
+                                            ByteBuffer.allocate(Int.SIZE_BYTES).putInt(1)
+                                                .array()
+                                        )
 
                                     is GattServerRequest.WriteCharacteristicRequest ->
-                                        it.sendResponse(/*success=*/true)
+                                        it.sendResponse(/*success=*/true, null)
 
                                     else -> throw NotImplementedError("unknown request")
                                 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
index c303c0d..ba55df3 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserViewModel.kt
@@ -85,7 +85,7 @@
     fun addGattCharacteristic(service: GattService, characteristic: GattCharacteristic) {
         val index = _gattServerServices.indexOf(service)
         if (index < 0) return;
-        _gattServerServices[index] = GattService.of(service.uuid,
+        _gattServerServices[index] = GattService(service.uuid,
             service.characteristics.toMutableList().apply {
                 add(characteristic)
             }
diff --git a/browser/browser/api/api_lint.ignore b/browser/browser/api/api_lint.ignore
index 68c85ec..bec6b20 100644
--- a/browser/browser/api/api_lint.ignore
+++ b/browser/browser/api/api_lint.ignore
@@ -157,6 +157,8 @@
     androidx.browser.customtabs.CustomTabsIntent does not declare a `getSecondaryToolbarViews()` method matching method androidx.browser.customtabs.CustomTabsIntent.Builder.setSecondaryToolbarViews(android.widget.RemoteViews,int[],android.app.PendingIntent)
 MissingGetterMatchingBuilder: androidx.browser.customtabs.CustomTabsIntent.Builder#setSession(androidx.browser.customtabs.CustomTabsSession):
     androidx.browser.customtabs.CustomTabsIntent does not declare a `getSession()` method matching method androidx.browser.customtabs.CustomTabsIntent.Builder.setSession(androidx.browser.customtabs.CustomTabsSession)
+MissingGetterMatchingBuilder: androidx.browser.customtabs.CustomTabsIntent.Builder#setShareIdentityEnabled(boolean):
+    androidx.browser.customtabs.CustomTabsIntent does not declare a `isShareIdentityEnabled()` method matching method androidx.browser.customtabs.CustomTabsIntent.Builder.setShareIdentityEnabled(boolean)
 MissingGetterMatchingBuilder: androidx.browser.customtabs.CustomTabsIntent.Builder#setShareState(int):
     androidx.browser.customtabs.CustomTabsIntent does not declare a `getShareState()` method matching method androidx.browser.customtabs.CustomTabsIntent.Builder.setShareState(int)
 MissingGetterMatchingBuilder: androidx.browser.customtabs.CustomTabsIntent.Builder#setShowTitle(boolean):
diff --git a/browser/browser/api/current.txt b/browser/browser/api/current.txt
index 4878f05..28f6ded 100644
--- a/browser/browser/api/current.txt
+++ b/browser/browser/api/current.txt
@@ -104,8 +104,9 @@
     method public static androidx.browser.customtabs.CustomTabColorSchemeParams getColorSchemeParams(android.content.Intent, int);
     method @Dimension(unit=androidx.annotation.Dimension.PX) public static int getInitialActivityHeightPx(android.content.Intent);
     method public static int getMaxToolbarItems();
+    method public android.app.PendingIntent? getSecondaryToolbarSwipeUpGesture(android.content.Intent);
     method @Dimension(unit=androidx.annotation.Dimension.DP) public static int getToolbarCornerRadiusDp(android.content.Intent);
-    method public static String? getTranslateLanguage(android.content.Intent);
+    method public static java.util.Locale? getTranslateLocale(android.content.Intent);
     method public static boolean isBackgroundInteractionEnabled(android.content.Intent);
     method public static boolean isBookmarksButtonEnabled(android.content.Intent);
     method public static boolean isDownloadButtonEnabled(android.content.Intent);
@@ -145,6 +146,7 @@
     field public static final String EXTRA_REMOTEVIEWS_PENDINGINTENT = "android.support.customtabs.extra.EXTRA_REMOTEVIEWS_PENDINGINTENT";
     field public static final String EXTRA_REMOTEVIEWS_VIEW_IDS = "android.support.customtabs.extra.EXTRA_REMOTEVIEWS_VIEW_IDS";
     field public static final String EXTRA_SECONDARY_TOOLBAR_COLOR = "android.support.customtabs.extra.SECONDARY_TOOLBAR_COLOR";
+    field public static final String EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE = "androidx.browser.customtabs.extra.SECONDARY_TOOLBAR_SWIPE_UP_GESTURE";
     field public static final String EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER = "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER";
     field public static final String EXTRA_SESSION = "android.support.customtabs.extra.SESSION";
     field public static final String EXTRA_SHARE_STATE = "androidx.browser.customtabs.extra.SHARE_STATE";
@@ -154,7 +156,7 @@
     field public static final String EXTRA_TOOLBAR_COLOR = "android.support.customtabs.extra.TOOLBAR_COLOR";
     field public static final String EXTRA_TOOLBAR_CORNER_RADIUS_DP = "androidx.browser.customtabs.extra.TOOLBAR_CORNER_RADIUS_DP";
     field public static final String EXTRA_TOOLBAR_ITEMS = "android.support.customtabs.extra.TOOLBAR_ITEMS";
-    field public static final String EXTRA_TRANSLATE_LANGUAGE = "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE";
+    field public static final String EXTRA_TRANSLATE_LANGUAGE_TAG = "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE_TAG";
     field public static final String KEY_DESCRIPTION = "android.support.customtabs.customaction.DESCRIPTION";
     field public static final String KEY_ICON = "android.support.customtabs.customaction.ICON";
     field public static final String KEY_ID = "android.support.customtabs.customaction.ID";
@@ -196,16 +198,18 @@
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setNavigationBarColor(@ColorInt int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setNavigationBarDividerColor(@ColorInt int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarColor(@ColorInt int);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarSwipeUpGesture(android.app.PendingIntent?);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarViews(android.widget.RemoteViews, int[]?, android.app.PendingIntent?);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSendToExternalDefaultHandlerEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSession(androidx.browser.customtabs.CustomTabsSession);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setShareIdentityEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShareState(int);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShowOnToolbarEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShowTitle(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setStartAnimations(android.content.Context, @AnimRes int, @AnimRes int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setToolbarColor(@ColorInt int);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setToolbarCornerRadiusDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
-    method public androidx.browser.customtabs.CustomTabsIntent.Builder setTranslateLanguage(String);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setTranslateLocale(java.util.Locale);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setUrlBarHidingEnabled(boolean);
   }
 
@@ -265,6 +269,7 @@
     method public boolean setActionButton(android.graphics.Bitmap, String);
     method @RequiresFeature(name=androidx.browser.customtabs.CustomTabsFeatures.ENGAGEMENT_SIGNALS, enforcement="androidx.browser.customtabs.CustomTabsSession#isEngagementSignalsApiAvailable") public boolean setEngagementSignalsCallback(androidx.browser.customtabs.EngagementSignalsCallback, android.os.Bundle) throws android.os.RemoteException;
     method @RequiresFeature(name=androidx.browser.customtabs.CustomTabsFeatures.ENGAGEMENT_SIGNALS, enforcement="androidx.browser.customtabs.CustomTabsSession#isEngagementSignalsApiAvailable") public boolean setEngagementSignalsCallback(java.util.concurrent.Executor, androidx.browser.customtabs.EngagementSignalsCallback, android.os.Bundle) throws android.os.RemoteException;
+    method public boolean setSecondaryToolbarSwipeUpGesture(android.app.PendingIntent?);
     method public boolean setSecondaryToolbarViews(android.widget.RemoteViews?, int[]?, android.app.PendingIntent?);
     method @Deprecated public boolean setToolbarItem(int, android.graphics.Bitmap, String);
     method public boolean validateRelationship(@androidx.browser.customtabs.CustomTabsService.Relation int, android.net.Uri, android.os.Bundle?);
diff --git a/browser/browser/api/restricted_current.txt b/browser/browser/api/restricted_current.txt
index 2eab941..4c1585e 100644
--- a/browser/browser/api/restricted_current.txt
+++ b/browser/browser/api/restricted_current.txt
@@ -115,8 +115,9 @@
     method public static androidx.browser.customtabs.CustomTabColorSchemeParams getColorSchemeParams(android.content.Intent, int);
     method @Dimension(unit=androidx.annotation.Dimension.PX) public static int getInitialActivityHeightPx(android.content.Intent);
     method public static int getMaxToolbarItems();
+    method public android.app.PendingIntent? getSecondaryToolbarSwipeUpGesture(android.content.Intent);
     method @Dimension(unit=androidx.annotation.Dimension.DP) public static int getToolbarCornerRadiusDp(android.content.Intent);
-    method public static String? getTranslateLanguage(android.content.Intent);
+    method public static java.util.Locale? getTranslateLocale(android.content.Intent);
     method public static boolean isBackgroundInteractionEnabled(android.content.Intent);
     method public static boolean isBookmarksButtonEnabled(android.content.Intent);
     method public static boolean isDownloadButtonEnabled(android.content.Intent);
@@ -156,6 +157,7 @@
     field public static final String EXTRA_REMOTEVIEWS_PENDINGINTENT = "android.support.customtabs.extra.EXTRA_REMOTEVIEWS_PENDINGINTENT";
     field public static final String EXTRA_REMOTEVIEWS_VIEW_IDS = "android.support.customtabs.extra.EXTRA_REMOTEVIEWS_VIEW_IDS";
     field public static final String EXTRA_SECONDARY_TOOLBAR_COLOR = "android.support.customtabs.extra.SECONDARY_TOOLBAR_COLOR";
+    field public static final String EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE = "androidx.browser.customtabs.extra.SECONDARY_TOOLBAR_SWIPE_UP_GESTURE";
     field public static final String EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER = "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER";
     field public static final String EXTRA_SESSION = "android.support.customtabs.extra.SESSION";
     field public static final String EXTRA_SHARE_STATE = "androidx.browser.customtabs.extra.SHARE_STATE";
@@ -165,7 +167,7 @@
     field public static final String EXTRA_TOOLBAR_COLOR = "android.support.customtabs.extra.TOOLBAR_COLOR";
     field public static final String EXTRA_TOOLBAR_CORNER_RADIUS_DP = "androidx.browser.customtabs.extra.TOOLBAR_CORNER_RADIUS_DP";
     field public static final String EXTRA_TOOLBAR_ITEMS = "android.support.customtabs.extra.TOOLBAR_ITEMS";
-    field public static final String EXTRA_TRANSLATE_LANGUAGE = "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE";
+    field public static final String EXTRA_TRANSLATE_LANGUAGE_TAG = "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE_TAG";
     field public static final String KEY_DESCRIPTION = "android.support.customtabs.customaction.DESCRIPTION";
     field public static final String KEY_ICON = "android.support.customtabs.customaction.ICON";
     field public static final String KEY_ID = "android.support.customtabs.customaction.ID";
@@ -207,16 +209,18 @@
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setNavigationBarColor(@ColorInt int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setNavigationBarDividerColor(@ColorInt int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarColor(@ColorInt int);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarSwipeUpGesture(android.app.PendingIntent?);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSecondaryToolbarViews(android.widget.RemoteViews, int[]?, android.app.PendingIntent?);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSendToExternalDefaultHandlerEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setSession(androidx.browser.customtabs.CustomTabsSession);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setShareIdentityEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShareState(int);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShowOnToolbarEnabled(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setShowTitle(boolean);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setStartAnimations(android.content.Context, @AnimRes int, @AnimRes int);
     method @Deprecated public androidx.browser.customtabs.CustomTabsIntent.Builder setToolbarColor(@ColorInt int);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setToolbarCornerRadiusDp(@Dimension(unit=androidx.annotation.Dimension.DP) int);
-    method public androidx.browser.customtabs.CustomTabsIntent.Builder setTranslateLanguage(String);
+    method public androidx.browser.customtabs.CustomTabsIntent.Builder setTranslateLocale(java.util.Locale);
     method public androidx.browser.customtabs.CustomTabsIntent.Builder setUrlBarHidingEnabled(boolean);
   }
 
@@ -276,6 +280,7 @@
     method public boolean setActionButton(android.graphics.Bitmap, String);
     method @RequiresFeature(name=androidx.browser.customtabs.CustomTabsFeatures.ENGAGEMENT_SIGNALS, enforcement="androidx.browser.customtabs.CustomTabsSession#isEngagementSignalsApiAvailable") public boolean setEngagementSignalsCallback(androidx.browser.customtabs.EngagementSignalsCallback, android.os.Bundle) throws android.os.RemoteException;
     method @RequiresFeature(name=androidx.browser.customtabs.CustomTabsFeatures.ENGAGEMENT_SIGNALS, enforcement="androidx.browser.customtabs.CustomTabsSession#isEngagementSignalsApiAvailable") public boolean setEngagementSignalsCallback(java.util.concurrent.Executor, androidx.browser.customtabs.EngagementSignalsCallback, android.os.Bundle) throws android.os.RemoteException;
+    method public boolean setSecondaryToolbarSwipeUpGesture(android.app.PendingIntent?);
     method public boolean setSecondaryToolbarViews(android.widget.RemoteViews?, int[]?, android.app.PendingIntent?);
     method @Deprecated public boolean setToolbarItem(int, android.graphics.Bitmap, String);
     method public boolean validateRelationship(@androidx.browser.customtabs.CustomTabsService.Relation int, android.net.Uri, android.os.Bundle?);
diff --git a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java
index d19d42f..73ece64 100644
--- a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java
+++ b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsIntent.java
@@ -20,6 +20,7 @@
 import static androidx.annotation.Dimension.PX;
 
 import android.app.Activity;
+import android.app.ActivityOptions;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -52,6 +53,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Locale;
 
 /**
  * Class holding the {@link Intent} and start bundle for a Custom Tabs Activity.
@@ -176,10 +178,11 @@
             "android.support.customtabs.extra.SEND_TO_EXTERNAL_HANDLER";
 
     /**
-     * Extra that specifies the target language the Translate UI should be triggered with.
+     * Extra that specifies the target locale the Translate UI should be triggered with.
+     * The locale is represented as a well-formed IETF BCP 47 language tag.
      */
-    public static final String EXTRA_TRANSLATE_LANGUAGE =
-            "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE";
+    public static final String EXTRA_TRANSLATE_LANGUAGE_TAG =
+            "androidx.browser.customtabs.extra.TRANSLATE_LANGUAGE_TAG";
 
     /**
      * Extra that, when set to false, disables interactions with the background app
@@ -197,6 +200,13 @@
             "android.support.customtabs.customaction.SHOW_ON_TOOLBAR";
 
     /**
+     * Extra that specifies the {@link PendingIntent} to be sent when the user swipes up from
+     * the secondary (bottom) toolbar.
+     */
+    public static final String EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE =
+            "androidx.browser.customtabs.extra.SECONDARY_TOOLBAR_SWIPE_UP_GESTURE";
+
+    /**
      * Don't show any title. Shows only the domain.
      */
     public static final int NO_TITLE = 0;
@@ -535,12 +545,13 @@
         private final CustomTabColorSchemeParams.Builder mDefaultColorSchemeBuilder =
                 new CustomTabColorSchemeParams.Builder();
         @Nullable private ArrayList<Bundle> mMenuItems;
-        @Nullable private Bundle mStartAnimationBundle;
+        @Nullable private ActivityOptions mActivityOptions;
         @Nullable private ArrayList<Bundle> mActionButtons;
         @Nullable private SparseArray<Bundle> mColorSchemeParamBundles;
         @Nullable private Bundle mDefaultColorSchemeBundle;
         @ShareState private int mShareState = SHARE_STATE_DEFAULT;
         private boolean mInstantAppsEnabled = true;
+        private boolean mShareIdentity;
 
         /**
          * Creates a {@link CustomTabsIntent.Builder} object associated with no
@@ -892,6 +903,18 @@
         }
 
         /**
+         * Sets the {@link PendingIntent} to be sent when the user swipes up from
+         * the secondary (bottom) toolbar.
+         * @param pendingIntent The {@link PendingIntent} that will be sent when
+         *                      the user swipes up from the secondary toolbar.
+         */
+        @NonNull
+        public Builder setSecondaryToolbarSwipeUpGesture(@Nullable PendingIntent pendingIntent) {
+            mIntent.putExtra(EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE, pendingIntent);
+            return this;
+        }
+
+        /**
          * Sets whether Instant Apps is enabled for this Custom Tab.
 
          * @param enabled Whether Instant Apps should be enabled.
@@ -913,8 +936,13 @@
         @SuppressWarnings("NullAway") // TODO: b/141869399
         public Builder setStartAnimations(
                 @NonNull Context context, @AnimRes int enterResId, @AnimRes int exitResId) {
-            mStartAnimationBundle = ActivityOptionsCompat.makeCustomAnimation(
-                    context, enterResId, exitResId).toBundle();
+            // We use ActivityOptions, not ActivityOptionsCompat, to build the start activity
+            // options, since we might set another option (share identity, which is not
+            // available yet via ActivityOptionsCompat) before turning it to a Bundle.
+            // TODO(b/296463161): Update androidx.core.core lib to support the new option via
+            // ActivityOptionsCompat and use it here instead of ActivityOptions.
+            mActivityOptions = ActivityOptions.makeCustomAnimation(
+                    context, enterResId, exitResId);
             return this;
         }
 
@@ -1092,6 +1120,7 @@
          * is enabled by default.
          *
          * @param enabled Whether the start button is enabled.
+         * @see CustomTabsIntent#EXTRA_DISABLE_BOOKMARKS_BUTTON
          */
         @NonNull
         public Builder setBookmarksButtonEnabled(boolean enabled) {
@@ -1104,6 +1133,7 @@
          * is enabled by default.
          *
          * @param enabled Whether the download button is enabled.
+         * @see CustomTabsIntent#EXTRA_DISABLE_DOWNLOAD_BUTTON
          */
         @NonNull
         public Builder setDownloadButtonEnabled(boolean enabled) {
@@ -1115,6 +1145,7 @@
          * Enables sending initial urls to external handler apps, if possible.
          *
          * @param enabled Whether to send urls to external handler.
+         * @see CustomTabsIntent#EXTRA_SEND_TO_EXTERNAL_DEFAULT_HANDLER
          */
         @NonNull
         public Builder setSendToExternalDefaultHandlerEnabled(boolean enabled) {
@@ -1123,14 +1154,16 @@
         }
 
         /**
-         * Specifies the target language the Translate UI should be triggered with.
+         * Specifies the target locale the Translate UI should be triggered with.
          *
-         * @param lang Language code for the translate UI. Should be in the format of
-         *        ISO 639 language code.
+         * @param locale {@link Locale} object that represents the target locale.
+         * @see CustomTabsIntent#EXTRA_TRANSLATE_LANGUAGE_TAG
          */
         @NonNull
-        public Builder setTranslateLanguage(@NonNull String lang) {
-            mIntent.putExtra(EXTRA_TRANSLATE_LANGUAGE, lang);
+        public Builder setTranslateLocale(@NonNull Locale locale) {
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                setLanguageTag(locale);
+            }
             return this;
         }
 
@@ -1140,6 +1173,7 @@
          * Enables the interactions with the background app when a Partial Custom Tab is launched.
          *
          * @param enabled Whether the background interaction is enabled.
+         * @see CustomTabsIntent#EXTRA_ENABLE_BACKGROUND_INTERACTION
          */
         @NonNull
         public Builder setBackgroundInteractionEnabled(boolean enabled) {
@@ -1153,6 +1187,7 @@
          * toolbar.
          *
          * @param enabled Whether the additional actions can be added to the toolbar.
+         * @see CustomTabsIntent#EXTRA_SHOW_ON_TOOLBAR
          */
         @NonNull
         public Builder setShowOnToolbarEnabled(boolean enabled) {
@@ -1161,6 +1196,16 @@
         }
 
         /**
+         * Allow Custom Tabs to obtain the caller's identity i.e. package name.
+         * @param enabled Whether the identity sharing is enabled.
+         */
+        @NonNull
+        public Builder setShareIdentityEnabled(boolean enabled) {
+            mShareIdentity = enabled;
+            return this;
+        }
+
+        /**
          * Combines all the options that have been set and returns a new {@link CustomTabsIntent}
          * object.
          */
@@ -1195,7 +1240,14 @@
                 setCurrentLocaleAsDefaultAcceptLanguage();
             }
 
-            return new CustomTabsIntent(mIntent, mStartAnimationBundle);
+            Bundle bundle = null;
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+                setShareIdentityEnabled();
+            }
+            if (mActivityOptions != null) {
+                bundle = mActivityOptions.toBundle();
+            }
+            return new CustomTabsIntent(mIntent, bundle);
         }
 
         /**
@@ -1214,6 +1266,19 @@
                 }
             }
         }
+
+        @RequiresApi(api = Build.VERSION_CODES.N)
+        private void setLanguageTag(@NonNull Locale locale) {
+            Api21Impl.setLanguageTag(mIntent, locale);
+        }
+
+        @RequiresApi(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+        private void setShareIdentityEnabled() {
+            if (mActivityOptions == null) {
+                mActivityOptions = Api23Impl.makeBasicActivityOptions();
+            }
+            Api34Impl.setShareIdentityEnabled(mActivityOptions, mShareIdentity);
+        }
     }
 
     /**
@@ -1369,14 +1434,24 @@
     }
 
     /**
-     * Gets the target language for the Translate UI.
+     * Gets the target locale for the Translate UI.
      *
-     * @return The target language the Translate UI should be triggered with.
-     * @see CustomTabsIntent#EXTRA_TRANSLATE_LANGUAGE
+     * @return The target locale the Translate UI should be triggered with.
+     * @see CustomTabsIntent#EXTRA_TRANSLATE_LANGUAGE_TAG
      */
     @Nullable
-    public static String getTranslateLanguage(@NonNull Intent intent) {
-        return intent.getStringExtra(EXTRA_TRANSLATE_LANGUAGE);
+    public static Locale getTranslateLocale(@NonNull Intent intent) {
+        Locale locale = null;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            locale = getLocaleForLanguageTag(intent);
+        }
+        return locale;
+    }
+
+    @RequiresApi(api = Build.VERSION_CODES.N)
+    @Nullable
+    private static Locale getLocaleForLanguageTag(Intent intent) {
+        return Api21Impl.getLocaleForLanguageTag(intent);
     }
 
     /**
@@ -1395,6 +1470,40 @@
         return intent.getBooleanExtra(EXTRA_SHOW_ON_TOOLBAR, false);
     }
 
+    /**
+     * @return The {@link PendingIntent} that will be sent when the user swipes up
+     *     from the secondary toolbar.
+     * @see CustomTabsIntent#EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE
+     */
+    @SuppressWarnings("deprecation")
+    @Nullable
+    public PendingIntent getSecondaryToolbarSwipeUpGesture(@NonNull Intent intent) {
+        return intent.getParcelableExtra(EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE);
+    }
+
+    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+    private static class Api21Impl {
+        @DoNotInline
+        static void setLanguageTag(Intent intent, Locale locale) {
+            intent.putExtra(EXTRA_TRANSLATE_LANGUAGE_TAG, locale.toLanguageTag());
+        }
+
+        @DoNotInline
+        @Nullable
+        static Locale getLocaleForLanguageTag(Intent intent) {
+            String languageTag = intent.getStringExtra(EXTRA_TRANSLATE_LANGUAGE_TAG);
+            return languageTag != null ? Locale.forLanguageTag(languageTag) : null;
+        }
+    }
+
+    @RequiresApi(api = Build.VERSION_CODES.M)
+    private static class Api23Impl {
+        @DoNotInline
+        static ActivityOptions makeBasicActivityOptions() {
+            return ActivityOptions.makeBasic();
+        }
+    }
+
     @RequiresApi(api = Build.VERSION_CODES.N)
     private static class Api24Impl {
         @DoNotInline
@@ -1404,4 +1513,12 @@
             return (defaultLocaleList.size() > 0) ? defaultLocaleList.get(0).toLanguageTag(): null;
         }
     }
+
+    @RequiresApi(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+    private static class Api34Impl {
+        @DoNotInline
+        static void setShareIdentityEnabled(ActivityOptions activityOptions, boolean enabled) {
+            activityOptions.setShareIdentityEnabled(enabled);
+        }
+    }
 }
diff --git a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
index 8f4f865..76a35e9 100644
--- a/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
+++ b/browser/browser/src/main/java/androidx/browser/customtabs/CustomTabsSession.java
@@ -166,6 +166,25 @@
     }
 
     /**
+     * Sets a {@link PendingIntent} object to be sent when the user swipes up from the secondary
+     * (bottom) toolbar.
+     *
+     * @param pendingIntent {@link PendingIntent} to send.
+     * @return Whether the update succeeded.
+     */
+    public boolean setSecondaryToolbarSwipeUpGesture(@Nullable PendingIntent pendingIntent) {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(CustomTabsIntent.EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE,
+                pendingIntent);
+        addIdToBundle(bundle);
+        try {
+            return mService.updateVisuals(mCallback, bundle);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * Updates the visuals for toolbar items. Will only succeed if a custom tab created using this
      * session is in the foreground in browser and the given id is valid.
      *
diff --git a/browser/browser/src/test/java/androidx/browser/customtabs/CustomTabsIntentTest.java b/browser/browser/src/test/java/androidx/browser/customtabs/CustomTabsIntentTest.java
index 9997f73..267d5a0 100644
--- a/browser/browser/src/test/java/androidx/browser/customtabs/CustomTabsIntentTest.java
+++ b/browser/browser/src/test/java/androidx/browser/customtabs/CustomTabsIntentTest.java
@@ -25,6 +25,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.graphics.Color;
 import android.os.Build;
@@ -42,6 +43,8 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.internal.DoNotInstrument;
 
+import java.util.Locale;
+
 /**
  * Tests for CustomTabsIntent.
  */
@@ -608,13 +611,27 @@
         assertTrue(CustomTabsIntent.isShowOnToolbarEnabled(intent));
     }
 
+    @Config(minSdk = Build.VERSION_CODES.N)
     @Test
-    public void testTranslateLanguage() {
+    public void testTranslateLocale() {
         Intent intent = new CustomTabsIntent.Builder().build().intent;
-        assertNull(CustomTabsIntent.getTranslateLanguage(intent));
+        assertNull(CustomTabsIntent.getTranslateLocale(intent));
 
-        intent = new CustomTabsIntent.Builder().setTranslateLanguage("fr").build().intent;
-        assertEquals("fr", CustomTabsIntent.getTranslateLanguage(intent));
+        intent = new CustomTabsIntent.Builder().setTranslateLocale(Locale.FRANCE).build().intent;
+        Locale locale = CustomTabsIntent.getTranslateLocale(intent);
+        assertEquals(locale.toLanguageTag(), Locale.FRANCE.toLanguageTag());
+    }
+
+    @Config(minSdk = Build.VERSION_CODES.N)
+    @Test
+    public void testSecondaryToolbarSwipeUpGesture() {
+        PendingIntent pendingIntent = TestUtil.makeMockPendingIntent();
+        Intent intent = new CustomTabsIntent.Builder()
+                .setSecondaryToolbarSwipeUpGesture(pendingIntent)
+                .build()
+                .intent;
+        assertEquals(pendingIntent, intent.getParcelableExtra(
+                        CustomTabsIntent.EXTRA_SECONDARY_TOOLBAR_SWIPE_UP_GESTURE));
     }
 
     private void assertNullSessionInExtras(Intent intent) {
diff --git a/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java b/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
index fa0c171..79e40a0 100644
--- a/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
+++ b/browser/browser/src/test/java/androidx/browser/customtabs/TestUtil.java
@@ -51,7 +51,7 @@
     }
 
     @NonNull
-    private static PendingIntent makeMockPendingIntent() {
+    public static PendingIntent makeMockPendingIntent() {
         return PendingIntent.getBroadcast(mock(Context.class), 0, new Intent(), 0);
     }
 
diff --git a/buildSrc-tests/src/test/java/androidx/build/testConfiguration/AndroidTestConfigBuilderTest.kt b/buildSrc-tests/src/test/java/androidx/build/testConfiguration/AndroidTestConfigBuilderTest.kt
index 05105a0..4efa132 100644
--- a/buildSrc-tests/src/test/java/androidx/build/testConfiguration/AndroidTestConfigBuilderTest.kt
+++ b/buildSrc-tests/src/test/java/androidx/build/testConfiguration/AndroidTestConfigBuilderTest.kt
@@ -58,7 +58,7 @@
     }
 
     @Test
-    fun testXmlAgainstGoldenDefaultBenchmark() {
+    fun testXmlAgainstGoldenMicrobenchmark() {
         builder.isMicrobenchmark(true)
         MatcherAssert.assertThat(
             builder.buildXml(),
@@ -67,6 +67,15 @@
     }
 
     @Test
+    fun testXmlAgainstGoldenMacroBenchmark() {
+        builder.isMacrobenchmark(true)
+        MatcherAssert.assertThat(
+            builder.buildXml(),
+            CoreMatchers.`is`(goldenDefaultConfigMacroBenchmark)
+        )
+    }
+
+    @Test
     fun testJsonAgainstGoldenDefault() {
         MatcherAssert.assertThat(
             builder.buildJson(),
@@ -368,3 +377,38 @@
     </test>
     </configuration>
 """.trimIndent()
+
+private val goldenDefaultConfigMacroBenchmark = """
+    <?xml version="1.0" encoding="utf-8"?>
+    <!-- Copyright (C) 2020 The Android Open Source Project
+    Licensed under the Apache License, Version 2.0 (the "License")
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+    http://www.apache.org/licenses/LICENSE-2.0
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions
+    and limitations under the License.-->
+    <configuration description="Runs tests for the module">
+    <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MinApiLevelModuleController">
+    <option name="min-api-level" value="15" />
+    </object>
+    <option name="test-suite-tag" value="placeholder_tag" />
+    <option name="config-descriptor:metadata" key="applicationId" value="com.androidx.placeholder.Placeholder" />
+    <option name="wifi:disable" value="true" />
+    <option name="instrumentation-arg" key="notAnnotation" value="androidx.test.filters.FlakyTest" />
+    <option name="instrumentation-arg" key="listener" value="androidx.benchmark.junit4.InstrumentationResultsRunListener" />
+    <option name="instrumentation-arg" key="listener" value="androidx.benchmark.macro.junit4.SideEffectRunListener" />
+    <include name="google/unbundled/common/setup" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+    <option name="cleanup-apks" value="true" />
+    <option name="install-arg" value="-t" />
+    <option name="test-file-name" value="placeholder.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+    <option name="runner" value="com.example.Runner"/>
+    <option name="package" value="com.androidx.placeholder.Placeholder" />
+    </test>
+    </configuration>
+""".trimIndent()
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
index 8cb0a3d..2d1760f 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXComposeImplPlugin.kt
@@ -93,27 +93,24 @@
                     disable.add("UnknownIssueId")
                     error.addAll(ComposeLintWarningIdsToTreatAsErrors)
 
-                    // Paths we want to enable ListIterator checks for - for higher level
-                    // libraries it won't have a noticeable performance impact, and we don't want
-                    // developers reading high level library code to worry about this.
-                    val listIteratorPaths =
-                        listOf("compose:foundation", "compose:runtime", "compose:ui", "text")
-
-                    // Paths we want to disable ListIteratorChecks for - these are not runtime
-                    // libraries and so Iterator allocation is not relevant.
+                    // Paths we want to disable ListIteratorChecks for
                     val ignoreListIteratorFilter =
                         listOf(
+                            // These are not runtime libraries and so Iterator allocation is not
+                            // relevant.
                             "compose:ui:ui-test",
                             "compose:ui:ui-tooling",
                             "compose:ui:ui-inspection",
+                            // Navigation libraries are not in performance critical paths, so we can
+                            // ignore them.
+                            "navigation:navigation-compose",
+                            "wear:compose:compose-navigation"
                         )
 
                     // Disable ListIterator if we are not in a matching path, or we are in an
                     // unpublished project
                     if (
-                        listIteratorPaths.none { path.contains(it) } ||
-                            ignoreListIteratorFilter.any { path.contains(it) } ||
-                            !isPublished
+                        ignoreListIteratorFilter.any { path.contains(it) } || !isPublished
                     ) {
                         disable.add("ListIterator")
                     }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
index bd42717..73b8580 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXImplPlugin.kt
@@ -936,7 +936,7 @@
         taskConfigurator: (TaskProvider<VerifyDependencyVersionsTask>) -> Unit
     ) {
         afterEvaluate {
-            if (extension.type != LibraryType.SAMPLES) {
+            if (extension.type != LibraryType.UNSET && extension.type != LibraryType.SAMPLES) {
                 val verifyDependencyVersionsTask = project.createVerifyDependencyVersionsTask()
                 if (verifyDependencyVersionsTask != null) {
                     taskConfigurator(verifyDependencyVersionsTask)
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
index 07d5c42..a19f9a0 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/ListTaskOutputsTask.kt
@@ -106,10 +106,8 @@
 // TODO(149103692): remove all elements of this set
 val taskNamesKnownToDuplicateOutputs =
     setOf(
-        "kotlinSourcesJar",
-        "releaseSourcesJar",
-        "sourceJarRelease",
-        "sourceJar",
+        // Instead of adding new elements to this set, prefer to disable unused tasks when possible
+
         // The following tests intentionally have the same output of golden images
         "updateGoldenDesktopTest",
         "updateGoldenDebugUnitTest"
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
index e98648a..1e6ed89 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/SourceJarTaskHelper.kt
@@ -97,6 +97,11 @@
             }
         }
     }
+
+    val disableNames = setOf(
+        "releaseSourcesJar",
+    )
+    disableUnusedSourceJarTasks(disableNames)
 }
 
 /** Sets up a source jar task for a Java library project. */
@@ -128,6 +133,11 @@
             }
         }
     registerSourcesVariant(sourceJar)
+
+    val disableNames = setOf(
+        "kotlinSourcesJar",
+    )
+    disableUnusedSourceJarTasks(disableNames)
 }
 
 fun Project.configureSourceJarForMultiplatform() {
@@ -161,6 +171,18 @@
             task.metaInf.from(metadataFile)
         }
     registerMultiplatformSourcesVariant(sourceJar)
+    val disableNames = setOf(
+        "kotlinSourcesJar",
+    )
+    disableUnusedSourceJarTasks(disableNames)
+}
+
+fun Project.disableUnusedSourceJarTasks(disableNames: Set<String>) {
+    project.tasks.configureEach({ task ->
+        if (disableNames.contains(task.name)) {
+            task.enabled = false
+        }
+    })
 }
 
 internal val Project.multiplatformUsage
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/dackka/DackkaTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/dackka/DackkaTask.kt
index 59b5d8f..c7006f8 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/dackka/DackkaTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/dackka/DackkaTask.kt
@@ -97,6 +97,8 @@
 
     @Input lateinit var annotationsNotToDisplayKotlin: List<String>
 
+    @Input lateinit var hidingAnnotations: List<String>
+
     @InputFiles
     @PathSensitive(PathSensitivity.NONE)
     lateinit var versionMetadataFiles: Provider<List<File>>
@@ -209,6 +211,7 @@
                                             annotationsNotToDisplayJava,
                                         "annotationsNotToDisplayKotlin" to
                                             annotationsNotToDisplayKotlin,
+                                        "hidingAnnotations" to hidingAnnotations,
                                         "versionMetadataFilenames" to checkVersionMetadataFiles()
                                     )
                                 )
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
index 66eb173..e39904c2 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/docs/AndroidXDocsImplPlugin.kt
@@ -519,6 +519,7 @@
                     annotationsNotToDisplay = hiddenAnnotations
                     annotationsNotToDisplayJava = hiddenAnnotationsJava
                     annotationsNotToDisplayKotlin = hiddenAnnotationsKotlin
+                    hidingAnnotations = annotationsToHideApis
                     versionMetadataFiles =
                         versionMetadataConfiguration.incoming.artifacts.resolvedArtifacts.map {
                             it.map { it.file }
@@ -700,6 +701,9 @@
 // Annotations which should not be displayed in the Java docs, in addition to hiddenAnnotations
 private val hiddenAnnotationsJava: List<String> = emptyList()
 
+// Annotations which mean the elements they are applied to should be hidden from the docs
+private val annotationsToHideApis: List<String> = listOf("androidx.annotation.RestrictTo")
+
 /** Data class that matches JSON structure of kotlin source set metadata */
 data class ProjectStructureMetadata(var sourceSets: List<SourceSetMetadata>)
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/AndroidTestConfigBuilder.kt b/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/AndroidTestConfigBuilder.kt
index 159d0c3..3a3226e 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/AndroidTestConfigBuilder.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/AndroidTestConfigBuilder.kt
@@ -24,6 +24,7 @@
     var appApkSha256: String? = null
     lateinit var applicationId: String
     var isMicrobenchmark: Boolean = false
+    var isMacrobenchmark: Boolean = false
     var isPostsubmit: Boolean = true
     lateinit var minSdk: String
     val tags = mutableListOf<String>()
@@ -42,6 +43,8 @@
 
     fun isMicrobenchmark(isMicrobenchmark: Boolean) =
         apply { this.isMicrobenchmark = isMicrobenchmark }
+    fun isMacrobenchmark(isMacrobenchmark: Boolean) =
+        apply { this.isMacrobenchmark = isMacrobenchmark }
 
     fun isPostsubmit(isPostsubmit: Boolean) = apply { this.isPostsubmit = isPostsubmit }
 
@@ -99,6 +102,9 @@
                 sb.append(MICROBENCHMARK_PRESUBMIT_OPTION)
             }
         }
+        if (isMacrobenchmark) {
+            sb.append(MACROBENCHMARK_POSTSUBMIT_OPTIONS)
+        }
         sb.append(SETUP_INCLUDE)
             .append(TARGET_PREPARER_OPEN.replace("CLEANUP_APKS", "true"))
             .append(APK_INSTALL_OPTION.replace("APK_NAME", testApkName))
@@ -330,6 +336,14 @@
 """
         .trimIndent()
 
+private val MACROBENCHMARK_POSTSUBMIT_OPTIONS =
+    """
+    <option name="instrumentation-arg" key="listener" value="androidx.benchmark.junit4.InstrumentationResultsRunListener" />
+    <option name="instrumentation-arg" key="listener" value="androidx.benchmark.macro.junit4.SideEffectRunListener" />
+
+"""
+        .trimIndent()
+
 private val FLAKY_TEST_OPTION =
     """
     <option name="instrumentation-arg" key="notAnnotation" value="androidx.test.filters.FlakyTest" />
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
index d428c0f..2cc0b51 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/testConfiguration/GenerateTestConfigurationTask.kt
@@ -148,6 +148,7 @@
             }
         } else if (testProjectPath.get().endsWith("macrobenchmark")) {
             // macro benchmarks do not have a dryRunMode, so we don't run them in presubmit
+            configBuilder.isMacrobenchmark(true)
             configBuilder.tag("macrobenchmarks")
         } else {
             configBuilder.tag("androidx_unit_tests")
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/BundleInsideHelper.kt b/buildSrc/public/src/main/kotlin/androidx/build/BundleInsideHelper.kt
index e928e54..78efaed 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/BundleInsideHelper.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/BundleInsideHelper.kt
@@ -17,9 +17,14 @@
 package androidx.build
 
 import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
+import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
+import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
 import org.gradle.api.Project
 import org.gradle.api.Task
 import org.gradle.api.artifacts.Configuration
+import org.gradle.api.file.FileTreeElement
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.TaskProvider
 import org.gradle.jvm.tasks.Jar
 import org.gradle.kotlin.dsl.findByType
@@ -27,6 +32,7 @@
 import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
+import shadow.org.apache.tools.zip.ZipOutputStream
 
 /** Allow java and Android libraries to bundle other projects inside the project jar/aar. */
 object BundleInsideHelper {
@@ -45,13 +51,15 @@
      * Used project are expected
      *
      * @param relocations a list of package relocations to apply
+     * @param dropResourcesWithSuffix used to drop Java resources if they match this suffix,
+     *        null means no filtering
      * @receiver the project that should bundle jars specified by this configuration
      * @see forInsideAar(String, String)
      */
     @JvmStatic
-    fun Project.forInsideAar(relocations: List<Relocation>) {
+    fun Project.forInsideAar(relocations: List<Relocation>, dropResourcesWithSuffix: String?) {
         val bundle = configurations.create(CONFIGURATION_NAME)
-        val repackage = configureRepackageTaskForType(relocations, bundle)
+        val repackage = configureRepackageTaskForType(relocations, bundle, dropResourcesWithSuffix)
         // Add to AGP's configuration so this jar get packaged inside of the aar.
         dependencies.add("implementation", files(repackage.flatMap { it.archiveFile }))
     }
@@ -69,11 +77,13 @@
      *
      * @param from specifies from which package the rename should happen
      * @param to specifies to which package to put the renamed classes
+     * @param dropResourcesWithSuffix used to drop Java resources if they match this suffix,
+     *        null means no filtering
      * @receiver the project that should bundle jars specified by these configurations
      */
     @JvmStatic
-    fun Project.forInsideAar(from: String, to: String) {
-        forInsideAar(listOf(Relocation(from, to)))
+    fun Project.forInsideAar(from: String, to: String, dropResourcesWithSuffix: String?) {
+        forInsideAar(listOf(Relocation(from, to)), dropResourcesWithSuffix)
     }
 
     /**
@@ -90,12 +100,18 @@
      *
      * @param from specifies from which package the rename should happen
      * @param to specifies to which package to put the renamed classes
+     * @param dropResourcesWithSuffix used to drop Java resources if they match this suffix,
+     * null means no filtering
      * @receiver the project that should bundle jars specified by these configurations
      */
     @JvmStatic
-    fun Project.forInsideJar(from: String, to: String) {
+    fun Project.forInsideJar(from: String, to: String, dropResourcesWithSuffix: String?) {
         val bundle = configurations.create(CONFIGURATION_NAME)
-        val repackage = configureRepackageTaskForType(listOf(Relocation(from, to)), bundle)
+        val repackage = configureRepackageTaskForType(
+            relocations = listOf(Relocation(from, to)),
+            configuration = bundle,
+            dropResourcesWithSuffix = dropResourcesWithSuffix
+        )
         dependencies.add("compileOnly", files(repackage.flatMap { it.archiveFile }))
         dependencies.add("testImplementation", files(repackage.flatMap { it.archiveFile }))
 
@@ -126,15 +142,21 @@
     /**
      * KMP Version of [Project.forInsideJar]. See those docs for details.
      *
+     * @param dropResourcesWithSuffix used to drop Java resources if they match this suffix,
+     *      * null means no filtering
      * TODO(b/237104605): bundleInside is a global configuration. Should figure out how to make it
      *   work properly with kmp and source sets so it can reside inside a sourceSet dependency.
      */
     @JvmStatic
-    fun Project.forInsideJarKmp(from: String, to: String) {
+    fun Project.forInsideJarKmp(from: String, to: String, dropResourcesWithSuffix: String?) {
         val kmpExtension =
             extensions.findByType<KotlinMultiplatformExtension>() ?: error("kmp only")
         val bundle = configurations.create(CONFIGURATION_NAME)
-        val repackage = configureRepackageTaskForType(listOf(Relocation(from, to)), bundle)
+        val repackage = configureRepackageTaskForType(
+            relocations = listOf(Relocation(from, to)),
+            configuration = bundle,
+            dropResourcesWithSuffix = dropResourcesWithSuffix
+        )
 
         // To account for KMP structure we need to find the jvm specific target
         // and add the repackaged archive files to only their compilations.
@@ -210,18 +232,50 @@
 
     private fun Project.configureRepackageTaskForType(
         relocations: List<Relocation>,
-        configuration: Configuration
-    ): TaskProvider<ShadowJar> {
+        configuration: Configuration,
+        dropResourcesWithSuffix: String?
+        ): TaskProvider<ShadowJar> {
         return tasks.register(REPACKAGE_TASK_NAME, ShadowJar::class.java) { task ->
             task.apply {
                 configurations = listOf(configuration)
                 for (relocation in relocations) {
                     relocate(relocation.from, relocation.to)
                 }
+                val dontIncludeResourceTransformer = DontIncludeResourceTransformer()
+                dontIncludeResourceTransformer.dropResourcesWithSuffix = dropResourcesWithSuffix
+                transformers.add(dontIncludeResourceTransformer)
                 archiveBaseName.set("repackaged")
                 archiveVersion.set("")
                 destinationDirectory.set(layout.buildDirectory.dir("repackaged"))
             }
         }
     }
+
+    internal class DontIncludeResourceTransformer : Transformer {
+        @Optional
+        @Input
+        var dropResourcesWithSuffix: String? = null
+
+        override fun getName(): String {
+            return "DontIncludeResourceTransformer"
+        }
+
+        override fun canTransformResource(element: FileTreeElement?): Boolean {
+            val path = element?.relativePath?.pathString
+            return dropResourcesWithSuffix != null &&
+                (path?.endsWith(dropResourcesWithSuffix!!) == true)
+        }
+
+        override fun transform(context: TransformerContext?) {
+            // no op
+        }
+
+        override fun hasTransformedResource(): Boolean {
+            return true
+        }
+
+        override fun modifyOutputStream(zipOutputStream: ZipOutputStream?, b: Boolean) {
+            // no op
+        }
+    }
 }
diff --git a/busytown/androidx_compose_multiplatform.sh b/busytown/androidx_compose_multiplatform.sh
index d14184c..cd3cca9 100755
--- a/busytown/androidx_compose_multiplatform.sh
+++ b/busytown/androidx_compose_multiplatform.sh
@@ -13,7 +13,6 @@
       -Pandroidx.enableComposeCompilerMetrics=true \
       -Pandroidx.enableComposeCompilerReports=true \
       -Pandroidx.constraints=true \
-      --no-daemon \
       --profile \
       compileDebugAndroidTestSources \
       compileDebugSources \
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapter.kt
index 06d84bf..bfb2ddb 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapter.kt
@@ -20,7 +20,7 @@
 import androidx.annotation.VisibleForTesting
 import androidx.camera.camera2.pipe.CameraDevices
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.integration.internal.CameraGraphCreator
+import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraInfo
 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop
 import androidx.camera.core.CameraInfo
@@ -32,15 +32,26 @@
 
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class CameraCoordinatorAdapter(
+    private var cameraPipe: CameraPipe?,
     cameraDevices: CameraDevices,
-    private val cameraGraphCreator: CameraGraphCreator
 ) : CameraCoordinator {
-    @VisibleForTesting val cameraInternalMap = mutableMapOf<CameraId, CameraInternalAdapter>()
-    @VisibleForTesting var concurrentCameraIdsSet = mutableSetOf<Set<CameraId>>()
-    @VisibleForTesting var concurrentCameraIdMap = mutableMapOf<String, MutableList<String>>()
-    @VisibleForTesting var activeConcurrentCameraInfosList = mutableListOf<CameraInfo>()
-    @VisibleForTesting var concurrentMode: Int = CAMERA_OPERATING_MODE_UNSPECIFIED
-    @VisibleForTesting var concurrentModeOn = false
+    @VisibleForTesting
+    val cameraInternalMap = mutableMapOf<CameraId, CameraInternalAdapter>()
+
+    @VisibleForTesting
+    var concurrentCameraIdsSet = mutableSetOf<Set<CameraId>>()
+
+    @VisibleForTesting
+    var concurrentCameraIdMap = mutableMapOf<String, MutableList<String>>()
+
+    @VisibleForTesting
+    var activeConcurrentCameraInfosList = mutableListOf<CameraInfo>()
+
+    @VisibleForTesting
+    var concurrentMode: Int = CAMERA_OPERATING_MODE_UNSPECIFIED
+
+    @VisibleForTesting
+    var concurrentModeOn = false
 
     init {
         concurrentCameraIdsSet = cameraDevices.awaitConcurrentCameraIds()!!.toMutableSet()
@@ -85,8 +96,16 @@
 
     override fun setActiveConcurrentCameraInfos(cameraInfos: MutableList<CameraInfo>) {
         activeConcurrentCameraInfosList = cameraInfos
-        for (cameraInternalAdapter in cameraInternalMap.values) {
-            cameraInternalAdapter.resumeRefresh()
+        val graphConfigs = cameraInternalMap.values.map {
+            checkNotNull(it.getDeferredCameraGraphConfig()) {
+                "Every CameraInternal instance is expected to have a deferred CameraGraph config " +
+                    "when the active concurrent CameraInfos are set!"
+            }
+        }
+        val cameraGraphs = checkNotNull(cameraPipe).createCameraGraphs(graphConfigs)
+        check(cameraGraphs.size == cameraInternalMap.size)
+        for ((cameraInternalAdapter, cameraGraph) in cameraInternalMap.values.zip(cameraGraphs)) {
+            cameraInternalAdapter.resumeDeferredCameraGraphCreation(cameraGraph)
         }
     }
 
@@ -114,12 +133,11 @@
     override fun setCameraOperatingMode(@CameraOperatingMode cameraOperatingMode: Int) {
         concurrentMode = cameraOperatingMode
         concurrentModeOn = cameraOperatingMode == CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT
-        cameraGraphCreator.setConcurrentModeOn(concurrentModeOn)
         for (cameraInternalAdapter in cameraInternalMap.values) {
             if (cameraOperatingMode == CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT) {
-                cameraInternalAdapter.pauseRefresh()
+                cameraInternalAdapter.setCameraGraphCreationMode(createImmediately = false)
             } else if (cameraOperatingMode == CameraCoordinator.CAMERA_OPERATING_MODE_SINGLE) {
-                cameraInternalAdapter.resumeRefresh()
+                cameraInternalAdapter.setCameraGraphCreationMode(createImmediately = true)
             }
         }
     }
@@ -131,6 +149,7 @@
     }
 
     override fun shutdown() {
+        cameraPipe = null
         cameraInternalMap.clear()
         concurrentCameraIdsSet.clear()
         concurrentCameraIdMap.clear()
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
index 1c3dc2c..a22309f 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraFactoryAdapter.kt
@@ -72,7 +72,9 @@
     private var mAvailableCamerasSelector: CameraSelector? = availableCamerasSelector
     private var mAvailableCameraIds: List<String>
     private val cameraCoordinator: CameraCoordinatorAdapter = CameraCoordinatorAdapter(
-        appComponent.getCameraDevices(), appComponent.getCameraGraphCreator())
+        appComponent.getCameraPipe(),
+        appComponent.getCameraDevices(),
+    )
 
     init {
         debug { "Created CameraFactoryAdapter" }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
index 5b39179..5020ead 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraInternalAdapter.kt
@@ -19,6 +19,7 @@
 package androidx.camera.camera2.pipe.integration.adapter
 
 import androidx.annotation.RequiresApi
+import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.core.Log.debug
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
@@ -60,11 +61,15 @@
         // TODO: Consider preloading the list of camera ids and metadata.
     }
 
-    fun pauseRefresh() = threads.scope.launch(threads.backgroundDispatcher) {
-        useCaseManager.pauseRefresh()
+    internal fun setCameraGraphCreationMode(createImmediately: Boolean) {
+        useCaseManager.setCameraGraphCreationMode(createImmediately)
     }
-    fun resumeRefresh() = threads.scope.launch(threads.backgroundDispatcher) {
-        useCaseManager.resumeRefresh()
+
+    internal fun getDeferredCameraGraphConfig(): CameraGraph.Config? =
+        useCaseManager.getDeferredCameraGraphConfig()
+
+    internal fun resumeDeferredCameraGraphCreation(cameraGraph: CameraGraph) {
+        useCaseManager.resumeDeferredComponentCreation(cameraGraph)
     }
 
     // Load / unload methods
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraUseCaseAdapter.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraUseCaseAdapter.kt
index 4d083da..8361fb3 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraUseCaseAdapter.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/adapter/CameraUseCaseAdapter.kt
@@ -248,8 +248,6 @@
                 builder.addCameraCaptureCallback(CaptureCallbackContainer.create(it))
             }
 
-            // TODO: Copy CameraEventCallback (used for extension)
-
             // Copy extended Camera2 configurations
             val extendedConfig = MutableOptionsBundle.create().apply {
                 camera2Config.getPhysicalCameraId()?.let { physicalCameraId ->
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
index 31d67ce..2ba8e67 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/config/CameraAppConfig.kt
@@ -23,7 +23,6 @@
 import androidx.camera.camera2.pipe.CameraDevices
 import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.integration.impl.CameraInteropStateCallbackRepository
-import androidx.camera.camera2.pipe.integration.internal.CameraGraphCreator
 import androidx.camera.core.impl.CameraFactory
 import androidx.camera.core.impl.CameraThreadConfig
 import dagger.Component
@@ -79,8 +78,6 @@
     fun getCameraPipe(): CameraPipe
     fun getCameraDevices(): CameraDevices
 
-    fun getCameraGraphCreator(): CameraGraphCreator
-
     @Component.Builder
     interface Builder {
         fun config(config: CameraAppConfig): Builder
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfig.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfig.kt
index ab6853b..58c49d6 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfig.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfig.kt
@@ -66,7 +66,6 @@
 internal val SESSION_PHYSICAL_CAMERA_ID_OPTION: Config.Option<String> = Config.Option.create(
     "camera2.cameraCaptureSession.physicalCameraId", String::class.java
 )
-// TODO: Porting the CameraEventCallback option constant.
 
 /**
  * Internal shared implementation details for camera 2 interop.
@@ -170,8 +169,6 @@
         return config.retrieveOption(SESSION_CAPTURE_CALLBACK_OPTION, valueIfMissing)
     }
 
-    // TODO: Prepare a getter for CameraEventCallbacks
-
     /**
      * Returns the capture request tag.
      *
@@ -275,8 +272,6 @@
             return Camera2ImplConfig(OptionsBundle.from(mutableOptionsBundle))
         }
     }
-
-    // TODO: Prepare a setter for CameraEventCallbacks, ex: setCameraEventCallback
 }
 
 internal fun CaptureRequest.Key<*>.createCaptureRequestOption(): Config.Option<Any> {
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
index aa17277..84bd53e 100644
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
+++ b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManager.kt
@@ -41,7 +41,6 @@
 import androidx.camera.camera2.pipe.integration.config.CameraScope
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraComponent
 import androidx.camera.camera2.pipe.integration.config.UseCaseCameraConfig
-import androidx.camera.camera2.pipe.integration.internal.CameraGraphCreator
 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraControl
 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop
 import androidx.camera.core.UseCase
@@ -54,7 +53,6 @@
 import javax.inject.Provider
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.joinAll
-import kotlinx.coroutines.runBlocking
 
 /**
  * This class keeps track of the currently attached and active [UseCase]'s for a specific camera.
@@ -87,7 +85,6 @@
 @CameraScope
 class UseCaseManager @Inject constructor(
     private val cameraPipe: CameraPipe,
-    private val cameraGraphCreator: CameraGraphCreator,
     private val callbackMap: CameraCallbackMap,
     private val requestListener: ComboRequestListener,
     private val cameraConfig: CameraConfig,
@@ -115,7 +112,10 @@
     private var activeResumeEnabled = false
 
     @GuardedBy("lock")
-    private var refreshAttached = true
+    private var shouldCreateCameraGraphImmediately = true
+
+    @GuardedBy("lock")
+    private var deferredUseCaseManagerConfig: UseCaseManagerConfig? = null
 
     private val meteringRepeating by lazy {
         MeteringRepeating.Builder(
@@ -141,13 +141,17 @@
 
     private val allControls = controls.toMutableSet().apply { add(camera2CameraControl) }
 
-    fun pauseRefresh() = synchronized(lock) {
-        refreshAttached = false
+    internal fun setCameraGraphCreationMode(createImmediately: Boolean) = synchronized(lock) {
+        shouldCreateCameraGraphImmediately = createImmediately
+        if (shouldCreateCameraGraphImmediately) {
+            // Clear the UseCaseManager configuration that haven't been "resumed" when we return
+            // to single camera operating mode early.
+            deferredUseCaseManagerConfig = null
+        }
     }
 
-    fun resumeRefresh() = synchronized(lock) {
-        refreshAttached = true
-        refreshAttachedUseCases(attachedUseCases)
+    internal fun getDeferredCameraGraphConfig() = synchronized(lock) {
+        deferredUseCaseManagerConfig?.cameraGraphConfig
     }
 
     /**
@@ -283,9 +287,6 @@
 
     @GuardedBy("lock")
     private fun refreshAttachedUseCases(newUseCases: Set<UseCase>) {
-        if (!refreshAttached) {
-            return
-        }
         val useCases = newUseCases.toList()
 
         // Close prior camera graph
@@ -315,28 +316,53 @@
 
         val graphConfig = createCameraGraphConfig(
             sessionConfigAdapter, streamConfigMap, callbackMap,
-            requestListener, cameraConfig, cameraQuirks, cameraGraphFlags)
-        val cameraGraph =
-            runBlocking { cameraGraphCreator.createCameraGraph(cameraPipe, graphConfig) }
+            requestListener, cameraConfig, cameraQuirks, cameraGraphFlags
+        )
 
-        // Create and configure the new camera component.
-        _activeComponent =
-            builder.config(
-                UseCaseCameraConfig(
-                    useCases,
-                    sessionConfigAdapter,
-                    cameraStateAdapter,
-                    cameraGraph,
-                    streamConfigMap
-                )
-            )
-                .build()
-        for (control in allControls) {
-            control.useCaseCamera = camera
+        val useCaseManagerConfig = UseCaseManagerConfig(
+            useCases,
+            sessionConfigAdapter,
+            graphConfig,
+            streamConfigMap
+        )
+        if (!shouldCreateCameraGraphImmediately) {
+            deferredUseCaseManagerConfig = useCaseManagerConfig
+            return
         }
-        camera?.setActiveResumeMode(activeResumeEnabled)
+        val cameraGraph = cameraPipe.create(useCaseManagerConfig.cameraGraphConfig)
+        beginComponentCreation(useCaseManagerConfig, cameraGraph)
+    }
 
-        refreshRunningUseCases()
+    internal fun resumeDeferredComponentCreation(cameraGraph: CameraGraph) {
+        val config = synchronized(lock) { deferredUseCaseManagerConfig }
+        checkNotNull(config)
+        beginComponentCreation(config, cameraGraph)
+    }
+
+    private fun beginComponentCreation(
+        useCaseManagerConfig: UseCaseManagerConfig,
+        cameraGraph: CameraGraph
+    ) {
+        with(useCaseManagerConfig) {
+            // Create and configure the new camera component.
+            _activeComponent =
+                builder.config(
+                    UseCaseCameraConfig(
+                        useCases,
+                        sessionConfigAdapter,
+                        cameraStateAdapter,
+                        cameraGraph,
+                        streamConfigMap
+                    )
+                )
+                    .build()
+            for (control in allControls) {
+                control.useCaseCamera = camera
+            }
+            camera?.setActiveResumeMode(activeResumeEnabled)
+
+            refreshRunningUseCases()
+        }
     }
 
     @GuardedBy("lock")
@@ -464,6 +490,13 @@
     }
 
     companion object {
+        internal data class UseCaseManagerConfig(
+            val useCases: List<UseCase>,
+            val sessionConfigAdapter: SessionConfigAdapter,
+            val cameraGraphConfig: CameraGraph.Config,
+            val streamConfigMap: MutableMap<CameraStream.Config, DeferrableSurface>
+        )
+
         fun SessionConfig.toCamera2ImplConfig(): Camera2ImplConfig {
             return Camera2ImplConfig(implementationOptions)
         }
diff --git a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreator.kt b/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreator.kt
deleted file mode 100644
index f0aabe8..0000000
--- a/camera/camera-camera2-pipe-integration/src/main/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreator.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2023 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.camera.camera2.pipe.integration.internal
-
-import androidx.annotation.GuardedBy
-import androidx.annotation.RequiresApi
-import androidx.camera.camera2.pipe.CameraGraph
-import androidx.camera.camera2.pipe.CameraPipe
-import javax.inject.Inject
-import javax.inject.Singleton
-import kotlinx.coroutines.CompletableDeferred
-
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-@Singleton
-class CameraGraphCreator @Inject constructor() {
-    private val lock = Any()
-
-    @GuardedBy("lock")
-    var currentExpectedConfigs = 1
-
-    @GuardedBy("lock")
-    val currentConfigs = mutableListOf<CameraGraph.Config>()
-
-    private var pendingDeferred: CompletableDeferred<CameraGraph>? = null
-
-    fun setConcurrentModeOn(on: Boolean) = synchronized(lock) {
-        currentExpectedConfigs = if (on) {
-            2
-        } else {
-            1
-        }
-    }
-
-    suspend fun createCameraGraph(cameraPipe: CameraPipe, config: CameraGraph.Config): CameraGraph {
-        var deferred: CompletableDeferred<CameraGraph>? = null
-        synchronized(lock) {
-            currentConfigs.add(config)
-            if (currentConfigs.size != currentExpectedConfigs) {
-                deferred = CompletableDeferred()
-                pendingDeferred = deferred
-            }
-        }
-        if (deferred != null) {
-            return deferred!!.await()
-        }
-        synchronized(lock) {
-            if (currentExpectedConfigs == 1) {
-                val cameraGraph = cameraPipe.create(config)
-                currentConfigs.clear()
-                return cameraGraph
-            } else {
-                val cameraGraphs = cameraPipe.createCameraGraphs(currentConfigs)
-                pendingDeferred?.complete(cameraGraphs.first())
-                currentConfigs.clear()
-                return cameraGraphs[1]
-            }
-        }
-    }
-}
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapterTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapterTest.kt
index 4e9619b..442f7b1 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapterTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/adapter/CameraCoordinatorAdapterTest.kt
@@ -16,25 +16,31 @@
 
 package androidx.camera.camera2.pipe.integration.adapter
 
+import android.content.Context
 import android.os.Build
 import androidx.camera.camera2.pipe.CameraBackendId
+import androidx.camera.camera2.pipe.CameraGraph
 import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.integration.internal.CameraGraphCreator
+import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.integration.testing.FakeCameraInfoAdapterCreator
+import androidx.camera.camera2.pipe.testing.FakeCameraBackend
 import androidx.camera.camera2.pipe.testing.FakeCameraDevices
 import androidx.camera.camera2.pipe.testing.FakeCameraMetadata
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_CONCURRENT
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_SINGLE
 import androidx.camera.core.concurrent.CameraCoordinator.CAMERA_OPERATING_MODE_UNSPECIFIED
 import androidx.camera.core.impl.CameraInfoInternal
+import androidx.test.core.app.ApplicationProvider
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.never
 import org.mockito.kotlin.reset
 import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
 import org.robolectric.annotation.Config
 import org.robolectric.annotation.internal.DoNotInstrument
 
@@ -43,7 +49,9 @@
 @Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
 class CameraCoordinatorAdapterTest {
 
-    private val cameraMetadata = FakeCameraMetadata()
+    private val cameraMetadata0 = FakeCameraMetadata(cameraId = CameraId("0"))
+    private val cameraMetadata1 = FakeCameraMetadata(cameraId = CameraId("1"))
+    private val cameraMetadata2 = FakeCameraMetadata(cameraId = CameraId("2"))
 
     private val cameraDevices = FakeCameraDevices(
         defaultCameraBackendId = CameraBackendId("0"),
@@ -51,16 +59,46 @@
             setOf(CameraBackendId("0"), CameraBackendId("1")),
             setOf(CameraBackendId("0"), CameraBackendId("2"))
         ),
-        cameraMetadataMap = mapOf(CameraBackendId("0") to listOf(cameraMetadata))
+        cameraMetadataMap = mapOf(
+            CameraBackendId("0") to listOf(
+                cameraMetadata0,
+                cameraMetadata1,
+                cameraMetadata2
+            )
+        )
     )
 
-    private val mockCameraGraphCreator: CameraGraphCreator = mock()
     private val mockCameraInternalAdapter0: CameraInternalAdapter = mock()
     private val mockCameraInternalAdapter1: CameraInternalAdapter = mock()
     private val mockCameraInternalAdapter2: CameraInternalAdapter = mock()
 
-    private val cameraCoordinatorAdapter = CameraCoordinatorAdapter(
-        cameraDevices, mockCameraGraphCreator)
+    private val mockCameraGraphConfig0 = CameraGraph.Config(
+        camera = CameraId("0"), streams = emptyList()
+    )
+    private val mockCameraGraphConfig1 = CameraGraph.Config(
+        camera = CameraId("1"), streams = emptyList()
+    )
+    private val mockCameraGraphConfig2 = CameraGraph.Config(
+        camera = CameraId("2"), streams = emptyList()
+    )
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val fakeCameraBackend = FakeCameraBackend(
+        fakeCameras = mapOf(
+            cameraMetadata0.camera to cameraMetadata0,
+            cameraMetadata1.camera to cameraMetadata1,
+            cameraMetadata2.camera to cameraMetadata2
+        )
+    )
+    private val cameraPipe = CameraPipe(
+        CameraPipe.Config(
+            context,
+            cameraBackendConfig = CameraPipe.CameraBackendConfig(
+                internalBackend = fakeCameraBackend
+            ),
+        )
+    )
+    private val cameraCoordinatorAdapter = CameraCoordinatorAdapter(cameraPipe, cameraDevices)
 
     @Before
     fun setUp() {
@@ -79,9 +117,17 @@
 
     @Test
     fun setAndGetActiveConcurrentCameraInfos() {
+        whenever(mockCameraInternalAdapter0.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig0)
+        whenever(mockCameraInternalAdapter1.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig1)
+        whenever(mockCameraInternalAdapter2.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig2)
+
         cameraCoordinatorAdapter.activeConcurrentCameraInfos = mutableListOf(
             FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("0")),
-            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1")))
+            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1"))
+        )
 
         assertThat(cameraCoordinatorAdapter.activeConcurrentCameraInfos.size).isEqualTo(2)
         val cameraInfo0 = cameraCoordinatorAdapter.activeConcurrentCameraInfos[0]
@@ -90,17 +136,25 @@
         val cameraInfo1 = cameraCoordinatorAdapter.activeConcurrentCameraInfos[1]
             as CameraInfoInternal
         assertThat(cameraInfo1.cameraId).isEqualTo("1")
-        verify(mockCameraInternalAdapter0).resumeRefresh()
-        verify(mockCameraInternalAdapter1).resumeRefresh()
+        verify(mockCameraInternalAdapter0).resumeDeferredCameraGraphCreation(any())
+        verify(mockCameraInternalAdapter1).resumeDeferredCameraGraphCreation(any())
     }
 
     @Test
     fun getPairedConcurrentCameraId() {
+        whenever(mockCameraInternalAdapter0.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig0)
+        whenever(mockCameraInternalAdapter1.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig1)
+        whenever(mockCameraInternalAdapter2.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig2)
+
         assertThat(cameraCoordinatorAdapter.getPairedConcurrentCameraId("0")).isNull()
 
         cameraCoordinatorAdapter.activeConcurrentCameraInfos = mutableListOf(
             FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("0")),
-            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1")))
+            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1"))
+        )
 
         assertThat(cameraCoordinatorAdapter.getPairedConcurrentCameraId("0")).isEqualTo("1")
     }
@@ -109,11 +163,10 @@
     fun setAndGetCameraOperatingMode() {
         cameraCoordinatorAdapter.cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
 
-        verify(mockCameraInternalAdapter0).pauseRefresh()
-        verify(mockCameraInternalAdapter0, never()).resumeRefresh()
-        verify(mockCameraInternalAdapter1).pauseRefresh()
-        verify(mockCameraInternalAdapter1, never()).resumeRefresh()
-        verify(mockCameraGraphCreator).setConcurrentModeOn(true)
+        verify(mockCameraInternalAdapter0).setCameraGraphCreationMode(createImmediately = false)
+        verify(mockCameraInternalAdapter0, never()).resumeDeferredCameraGraphCreation(any())
+        verify(mockCameraInternalAdapter1).setCameraGraphCreationMode(createImmediately = false)
+        verify(mockCameraInternalAdapter1, never()).resumeDeferredCameraGraphCreation(any())
         assertThat(cameraCoordinatorAdapter.cameraOperatingMode)
             .isEqualTo(CAMERA_OPERATING_MODE_CONCURRENT)
 
@@ -121,25 +174,32 @@
         reset(mockCameraInternalAdapter1)
         cameraCoordinatorAdapter.cameraOperatingMode = CAMERA_OPERATING_MODE_SINGLE
 
-        verify(mockCameraInternalAdapter0).resumeRefresh()
-        verify(mockCameraInternalAdapter1).resumeRefresh()
-        verify(mockCameraGraphCreator).setConcurrentModeOn(false)
+        verify(mockCameraInternalAdapter0).setCameraGraphCreationMode(createImmediately = true)
+        verify(mockCameraInternalAdapter1).setCameraGraphCreationMode(createImmediately = true)
         assertThat(cameraCoordinatorAdapter.cameraOperatingMode)
             .isEqualTo(CAMERA_OPERATING_MODE_SINGLE)
 
         reset(mockCameraInternalAdapter0)
         reset(mockCameraInternalAdapter1)
         cameraCoordinatorAdapter.cameraOperatingMode = CAMERA_OPERATING_MODE_UNSPECIFIED
-        verify(mockCameraInternalAdapter0, never()).resumeRefresh()
-        verify(mockCameraInternalAdapter1, never()).resumeRefresh()
+        verify(mockCameraInternalAdapter0, never()).resumeDeferredCameraGraphCreation(any())
+        verify(mockCameraInternalAdapter1, never()).resumeDeferredCameraGraphCreation(any())
     }
 
     @Test
     fun shutdown() {
+        whenever(mockCameraInternalAdapter0.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig0)
+        whenever(mockCameraInternalAdapter1.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig1)
+        whenever(mockCameraInternalAdapter2.getDeferredCameraGraphConfig())
+            .thenReturn(mockCameraGraphConfig2)
+
         cameraCoordinatorAdapter.cameraOperatingMode = CAMERA_OPERATING_MODE_CONCURRENT
         cameraCoordinatorAdapter.activeConcurrentCameraInfos = mutableListOf(
             FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("0")),
-            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1")))
+            FakeCameraInfoAdapterCreator.createCameraInfoAdapter(cameraId = CameraId("1"))
+        )
 
         cameraCoordinatorAdapter.shutdown()
 
@@ -148,7 +208,8 @@
         assertThat(cameraCoordinatorAdapter.concurrentCameraIdMap).isEmpty()
         assertThat(cameraCoordinatorAdapter.concurrentCameraIdsSet).isEmpty()
         assertThat(cameraCoordinatorAdapter.cameraOperatingMode).isEqualTo(
-            CAMERA_OPERATING_MODE_UNSPECIFIED)
+            CAMERA_OPERATING_MODE_UNSPECIFIED
+        )
         assertThat(cameraCoordinatorAdapter.concurrentModeOn).isFalse()
     }
 }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfigTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfigTest.kt
index 2e37850..a99cf92 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfigTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/Camera2ImplConfigTest.kt
@@ -163,7 +163,4 @@
             true
         }
     }
-
-    // TODO: After porting CameraEventCallback (used for extension) to CameraUseCaseAdapter,
-    //  also porting canExtendWithCameraEventCallback
 }
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
index f06d683..9a1df6c35 100644
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
+++ b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/impl/UseCaseManagerTest.kt
@@ -30,7 +30,6 @@
 import androidx.camera.camera2.pipe.integration.compat.workaround.OutputSizesCorrector
 import androidx.camera.camera2.pipe.integration.config.CameraConfig
 import androidx.camera.camera2.pipe.integration.impl.UseCaseCamera.RunningUseCasesChangeListener
-import androidx.camera.camera2.pipe.integration.internal.CameraGraphCreator
 import androidx.camera.camera2.pipe.integration.interop.Camera2CameraControl
 import androidx.camera.camera2.pipe.integration.interop.ExperimentalCamera2Interop
 import androidx.camera.camera2.pipe.integration.testing.FakeCamera2CameraControlCompat
@@ -345,7 +344,6 @@
         val fakeCamera = FakeCamera()
         return UseCaseManager(
             cameraPipe = CameraPipe(CameraPipe.Config(ApplicationProvider.getApplicationContext())),
-            cameraGraphCreator = CameraGraphCreator(),
             cameraConfig = CameraConfig(cameraId),
             callbackMap = CameraCallbackMap(),
             requestListener = ComboRequestListener(),
diff --git a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreatorTest.kt b/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreatorTest.kt
deleted file mode 100644
index 02100cc..0000000
--- a/camera/camera-camera2-pipe-integration/src/test/java/androidx/camera/camera2/pipe/integration/internal/CameraGraphCreatorTest.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright 2023 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.camera.camera2.pipe.integration.internal
-
-import android.content.Context
-import android.graphics.Rect
-import android.hardware.camera2.CameraCharacteristics
-import android.hardware.camera2.CameraMetadata
-import android.os.Build
-import android.util.Size
-import androidx.camera.camera2.pipe.CameraGraph
-import androidx.camera.camera2.pipe.CameraId
-import androidx.camera.camera2.pipe.CameraPipe
-import androidx.camera.camera2.pipe.CameraStream
-import androidx.camera.camera2.pipe.StreamFormat
-import androidx.camera.camera2.pipe.integration.adapter.RobolectricCameraPipeTestRunner
-import androidx.test.core.app.ApplicationProvider
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.async
-import kotlinx.coroutines.test.advanceUntilIdle
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.internal.DoNotInstrument
-import org.robolectric.shadow.api.Shadow
-import org.robolectric.shadows.ShadowCameraCharacteristics
-import org.robolectric.shadows.ShadowCameraManager
-import org.robolectric.shadows.StreamConfigurationMapBuilder
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@RunWith(RobolectricCameraPipeTestRunner::class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
-class CameraGraphCreatorTest {
-
-    private val cameraGraphCreator: CameraGraphCreator = CameraGraphCreator()
-    private val context = ApplicationProvider.getApplicationContext() as Context
-    private val cameraPipe = CameraPipe(CameraPipe.Config(context))
-
-    private val stream1Config = CameraStream.Config.create(
-        Size(640, 480), StreamFormat.YUV_420_888)
-    private val stream2Config = CameraStream.Config.create(
-        Size(1280, 720), StreamFormat.YUV_420_888)
-    private val cameraGraph1Config = CameraGraph.Config(CameraId("0"), listOf(stream1Config))
-    private val cameraGraph2Config = CameraGraph.Config(CameraId("1"), listOf(stream2Config))
-
-    @Before
-    fun setUp() {
-        setupCameras()
-    }
-
-    @Test
-    fun createCameraGraph_singleMode() = runTest {
-        cameraGraphCreator.setConcurrentModeOn(false)
-        val cameraGraph = cameraGraphCreator.createCameraGraph(cameraPipe, cameraGraph1Config)
-
-        advanceUntilIdle()
-        assertThat(cameraGraph).isNotNull()
-    }
-
-    @Test
-    fun createCameraGraph_concurrentMode() = runTest {
-        cameraGraphCreator.setConcurrentModeOn(true)
-
-        val cameraGraph0 = async {
-            cameraGraphCreator.createCameraGraph(cameraPipe, cameraGraph1Config)
-        }
-        advanceUntilIdle()
-        assertThat(cameraGraph0.isCompleted).isFalse()
-
-        val cameraGraph1 = async {
-            cameraGraphCreator.createCameraGraph(cameraPipe, cameraGraph2Config)
-        }
-        advanceUntilIdle()
-
-        assertThat(cameraGraph0.isCompleted).isTrue()
-        assertThat(cameraGraph1.isCompleted).isTrue()
-        assertThat(cameraGraph0.await()).isNotNull()
-        assertThat(cameraGraph1.await()).isNotNull()
-    }
-
-    private fun setupCameras() {
-        val capabilities =
-            intArrayOf(CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE)
-
-        initCharacteristics("0", CameraCharacteristics.LENS_FACING_BACK, capabilities)
-        initCharacteristics("1", CameraCharacteristics.LENS_FACING_FRONT, capabilities)
-    }
-
-    private fun initCharacteristics(cameraId: String, lensFacing: Int, capabilities: IntArray?) {
-        val sensorWidth = 640
-        val sensorHeight = 480
-
-        val characteristics = ShadowCameraCharacteristics.newCameraCharacteristics()
-        val shadowCharacteristics =
-            Shadow.extract<ShadowCameraCharacteristics>(characteristics).apply {
-
-                set(CameraCharacteristics.LENS_FACING, lensFacing)
-
-                set(
-                    CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE,
-                    Rect(0, 0, sensorWidth, sensorHeight)
-                )
-
-                set(
-                    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL,
-                    CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
-                )
-
-                set(
-                    CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP,
-                    StreamConfigurationMapBuilder.newBuilder().build()
-                )
-            }
-
-        capabilities?.let {
-            shadowCharacteristics.set(
-                CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES, capabilities
-            )
-        }
-
-        // Add the camera to the camera service
-        (Shadow.extract<Any>(
-            ApplicationProvider.getApplicationContext<Context>()
-                .getSystemService(Context.CAMERA_SERVICE)
-        ) as ShadowCameraManager).addCamera(cameraId, characteristics)
-    }
-}
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2RequestProcessorTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2RequestProcessorTest.kt
index 747aa69..fb74085 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2RequestProcessorTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2RequestProcessorTest.kt
@@ -81,7 +81,7 @@
     private lateinit var cameraDeviceHolder: CameraUtil.CameraDeviceHolder
     private lateinit var captureSessionRepository: CaptureSessionRepository
     private lateinit var dynamicRangesCompat: DynamicRangesCompat
-    private lateinit var captureSessionOpenerBuilder: SynchronizedCaptureSessionOpener.Builder
+    private lateinit var captureSessionOpenerBuilder: SynchronizedCaptureSession.OpenerBuilder
     private lateinit var mainThreadExecutor: Executor
     private lateinit var previewSurface: SessionProcessorSurface
     private lateinit var captureSurface: SessionProcessorSurface
@@ -107,7 +107,7 @@
         captureSessionRepository = CaptureSessionRepository(mainThreadExecutor)
         val cameraCharacteristics = getCameraCharacteristic(CAMERA_ID)
         dynamicRangesCompat = DynamicRangesCompat.fromCameraCharacteristics(cameraCharacteristics)
-        captureSessionOpenerBuilder = SynchronizedCaptureSessionOpener.Builder(
+        captureSessionOpenerBuilder = SynchronizedCaptureSession.OpenerBuilder(
             mainThreadExecutor,
             mainThreadExecutor as ScheduledExecutorService,
             handler,
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
index ba71d6e..4f491d0 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
@@ -38,14 +38,11 @@
 import static org.junit.Assume.assumeTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 
 import android.content.Context;
 import android.graphics.ImageFormat;
@@ -74,8 +71,6 @@
 import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.Camera2Config;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.camera2.impl.CameraEventCallback;
-import androidx.camera.camera2.impl.CameraEventCallbacks;
 import androidx.camera.camera2.internal.CaptureSession.State;
 import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
 import androidx.camera.camera2.internal.compat.CameraCharacteristicsCompat;
@@ -93,7 +88,6 @@
 import androidx.camera.core.impl.CaptureConfig;
 import androidx.camera.core.impl.DeferrableSurface;
 import androidx.camera.core.impl.ImmediateSurface;
-import androidx.camera.core.impl.MutableOptionsBundle;
 import androidx.camera.core.impl.Quirks;
 import androidx.camera.core.impl.SessionConfig;
 import androidx.camera.core.impl.utils.executor.CameraXExecutors;
@@ -123,7 +117,6 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.model.Statement;
 import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
 import org.mockito.Mockito;
 
 import java.util.ArrayList;
@@ -184,7 +177,7 @@
     private CameraUtil.CameraDeviceHolder mCameraDeviceHolder;
 
     private CaptureSessionRepository mCaptureSessionRepository;
-    private SynchronizedCaptureSessionOpener.Builder mCaptureSessionOpenerBuilder;
+    private SynchronizedCaptureSession.OpenerBuilder mCaptureSessionOpenerBuilder;
 
     private final List<CaptureSession> mCaptureSessions = new ArrayList<>();
     private final List<DeferrableSurface> mDeferrableSurfaces = new ArrayList<>();
@@ -240,7 +233,7 @@
 
         mCaptureSessionRepository = new CaptureSessionRepository(mExecutor);
 
-        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSessionOpener.Builder(mExecutor,
+        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSession.OpenerBuilder(mExecutor,
                 mScheduledExecutor, mHandler, mCaptureSessionRepository,
                 new Quirks(new ArrayList<>()), DeviceQuirks.getAll());
 
@@ -684,14 +677,12 @@
         CaptureResult captureResult =
                 ((Camera2CameraCaptureResult) cameraCaptureResult).getCaptureResult();
 
-        // From CameraEventCallbacks option
+        // From SessionConfig option
         assertThat(captureResult.getRequest().get(CaptureRequest.CONTROL_AF_MODE)).isEqualTo(
-                CaptureRequest.CONTROL_AF_MODE_MACRO);
+                CaptureRequest.CONTROL_AF_MODE_AUTO);
         assertThat(captureResult.getRequest().get(
                 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION)).isEqualTo(
-                mTestParameters0.mEvRange.getLower());
-
-        // From SessionConfig option
+                mTestParameters0.mEvRange.getUpper());
         assertThat(captureResult.getRequest().get(CaptureRequest.CONTROL_AE_MODE)).isEqualTo(
                 CaptureRequest.CONTROL_AE_MODE_ON);
     }
@@ -857,12 +848,10 @@
         assertThat(captureResult.getRequest().get(CaptureRequest.CONTROL_AF_MODE)).isEqualTo(
                 CaptureRequest.CONTROL_AF_MODE_OFF);
 
-        // From CameraEventCallbacks option
+        // From SessionConfig option
         assertThat(captureResult.getRequest().get(
                 CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION)).isEqualTo(
-                mTestParameters0.mEvRange.getLower());
-
-        // From SessionConfig option
+                mTestParameters0.mEvRange.getUpper());
         assertThat(captureResult.getRequest().get(CaptureRequest.CONTROL_AE_MODE)).isEqualTo(
                 CaptureRequest.CONTROL_AE_MODE_ON);
     }
@@ -948,7 +937,7 @@
 
     @Test
     public void surfaceTerminationFutureIsCalledWhenSessionIsClose() throws InterruptedException {
-        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSessionOpener.Builder(mExecutor,
+        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSession.OpenerBuilder(mExecutor,
                 mScheduledExecutor, mHandler, mCaptureSessionRepository,
                 new Quirks(Arrays.asList(new PreviewOrientationIncorrectQuirk())),
                 DeviceQuirks.getAll());
@@ -971,101 +960,9 @@
     }
 
     @Test
-    public void cameraEventCallbackInvokedInOrder() {
-        CaptureSession captureSession = createCaptureSession();
-        captureSession.setSessionConfig(mTestParameters0.mSessionConfig);
-
-        captureSession.open(mTestParameters0.mSessionConfig, mCameraDeviceHolder.get(),
-                mCaptureSessionOpenerBuilder.build());
-        InOrder inOrder = inOrder(mTestParameters0.mMockCameraEventCallback);
-
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onInitSession();
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onEnableSession();
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onRepeating();
-        verify(mTestParameters0.mMockCameraEventCallback, never()).onDisableSession();
-
-        verifyNoMoreInteractions(mTestParameters0.mMockCameraEventCallback);
-
-        captureSession.close();
-        verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onDisableSession();
-        captureSession.release(false);
-        verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onDeInitSession();
-
-        verifyNoMoreInteractions(mTestParameters0.mMockCameraEventCallback);
-    }
-
-    @Test
-    public void cameraEventCallbackInvoked_assignDifferentSessionConfig() {
-        CaptureSession captureSession = createCaptureSession();
-        captureSession.setSessionConfig(new SessionConfig.Builder().build());
-        captureSession.open(mTestParameters0.mSessionConfig, mCameraDeviceHolder.get(),
-                mCaptureSessionOpenerBuilder.build());
-
-        InOrder inOrder = inOrder(mTestParameters0.mMockCameraEventCallback);
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onInitSession();
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onEnableSession();
-        // Should not trigger repeating since the repeating SessionConfig is empty.
-        verify(mTestParameters0.mMockCameraEventCallback, never()).onRepeating();
-
-        captureSession.close();
-        inOrder.verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onDisableSession();
-        captureSession.release(false);
-        verify(mTestParameters0.mMockCameraEventCallback, timeout(3000)).onDeInitSession();
-
-        verifyNoMoreInteractions(mTestParameters0.mMockCameraEventCallback);
-    }
-
-    @Test
-    public void cameraEventCallback_requestKeysIssuedSuccessfully() {
-        ArgumentCaptor<CameraCaptureResult> captureResultCaptor = ArgumentCaptor.forClass(
-                CameraCaptureResult.class);
-
-        CaptureSession captureSession = createCaptureSession();
-        captureSession.setSessionConfig(mTestParameters0.mSessionConfig);
-
-        // Open the capture session and verify the onEnableSession callback would be invoked
-        // but onDisableSession callback not.
-        captureSession.open(mTestParameters0.mSessionConfig, mCameraDeviceHolder.get(),
-                mCaptureSessionOpenerBuilder.build());
-
-        // Verify the request options in onEnableSession.
-        verify(mTestParameters0.mTestCameraEventCallback.mEnableCallback,
-                timeout(3000)).onCaptureCompleted(captureResultCaptor.capture());
-        CameraCaptureResult result1 = captureResultCaptor.getValue();
-        assertThat(result1).isInstanceOf(Camera2CameraCaptureResult.class);
-        CaptureResult captureResult1 = ((Camera2CameraCaptureResult) result1).getCaptureResult();
-        assertThat(captureResult1.getRequest().get(
-                CaptureRequest.CONTROL_SCENE_MODE)).isEqualTo(
-                mTestParameters0.mTestCameraEventCallback.mAvailableSceneMode);
-        // The onDisableSession should not been invoked.
-        verify(mTestParameters0.mTestCameraEventCallback.mDisableCallback,
-                never()).onCaptureCompleted(any(CameraCaptureResult.class));
-
-        reset(mTestParameters0.mTestCameraEventCallback.mEnableCallback);
-        reset(mTestParameters0.mTestCameraEventCallback.mDisableCallback);
-
-        // Close the capture session and verify the onDisableSession callback would be invoked
-        // but onEnableSession callback not.
-        captureSession.close();
-
-        // Verify the request options in onDisableSession.
-        verify(mTestParameters0.mTestCameraEventCallback.mDisableCallback,
-                timeout(3000)).onCaptureCompleted(captureResultCaptor.capture());
-        CameraCaptureResult result2 = captureResultCaptor.getValue();
-        assertThat(result2).isInstanceOf(Camera2CameraCaptureResult.class);
-        CaptureResult captureResult2 = ((Camera2CameraCaptureResult) result2).getCaptureResult();
-        assertThat(captureResult2.getRequest().get(
-                CaptureRequest.CONTROL_SCENE_MODE)).isEqualTo(
-                mTestParameters0.mTestCameraEventCallback.mAvailableSceneMode);
-        // The onEnableSession should not been invoked in close().
-        verify(mTestParameters0.mTestCameraEventCallback.mEnableCallback,
-                never()).onCaptureCompleted(any(CameraCaptureResult.class));
-    }
-
-    @Test
     public void closingCaptureSessionClosesDeferrableSurface()
             throws ExecutionException, InterruptedException {
-        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSessionOpener.Builder(mExecutor,
+        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSession.OpenerBuilder(mExecutor,
                 mScheduledExecutor, mHandler, mCaptureSessionRepository,
                 new Quirks(Arrays.asList(new ConfigureSurfaceToSecondarySessionFailQuirk())),
                 DeviceQuirks.getAll());
@@ -1213,22 +1110,41 @@
     public void cameraDisconnected_whenOpeningCaptureSessions_onClosedShouldBeCalled()
             throws CameraAccessException, InterruptedException, ExecutionException,
             TimeoutException {
+        assumeFalse("Known device issue, b/255461164", "cph1931".equalsIgnoreCase(Build.MODEL));
+
         List<OutputConfigurationCompat> outputConfigList = new LinkedList<>();
         outputConfigList.add(
                 new OutputConfigurationCompat(mTestParameters0.mImageReader.getSurface()));
 
-        SynchronizedCaptureSessionOpener synchronizedCaptureSessionOpener =
-                mCaptureSessionOpenerBuilder.build();
+        CountDownLatch endedCountDown = new CountDownLatch(1);
+        CameraCaptureSession.StateCallback testStateCallback =
+                new CameraCaptureSession.StateCallback() {
 
-        SessionConfigurationCompat sessionConfigCompat =
-                synchronizedCaptureSessionOpener.createSessionConfigurationCompat(
-                        SessionConfigurationCompat.SESSION_REGULAR,
-                        outputConfigList,
-                        new SynchronizedCaptureSessionStateCallbacks.Adapter(
-                                mTestParameters0.mSessionStateCallback));
+                    @Override
+                    public void onClosed(@NonNull CameraCaptureSession session) {
+                        endedCountDown.countDown();
+                    }
+
+                    @Override
+                    public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
+
+                    }
+
+                    @Override
+                    public void onConfigureFailed(
+                            @NonNull CameraCaptureSession cameraCaptureSession) {
+                        endedCountDown.countDown();
+                    }
+                };
+
+        SynchronizedCaptureSession.Opener opener = mCaptureSessionOpenerBuilder.build();
+        SessionConfigurationCompat sessionConfigCompat = opener.createSessionConfigurationCompat(
+                SessionConfigurationCompat.SESSION_REGULAR,
+                outputConfigList,
+                new SynchronizedCaptureSessionStateCallbacks.Adapter(testStateCallback));
 
         // Open the CameraCaptureSession without waiting for the onConfigured() callback.
-        synchronizedCaptureSessionOpener.openCaptureSession(mCameraDeviceHolder.get(),
+        opener.openCaptureSession(mCameraDeviceHolder.get(),
                 sessionConfigCompat, mTestParameters0.mSessionConfig.getSurfaces());
 
         // Open the camera again to simulate the cameraDevice is disconnected
@@ -1251,11 +1167,10 @@
                     }
                 });
         // Only verify the result when the camera can open successfully.
-        assumeTrue(countDownLatch.await(3000, TimeUnit.MILLISECONDS));
+        assumeTrue(countDownLatch.await(3, TimeUnit.SECONDS));
 
         // The opened CaptureSession should be closed after the CameraDevice is disconnected.
-        verify(mTestParameters0.mSessionStateCallback, timeout(5000)).onClosed(
-                any(CameraCaptureSession.class));
+        assumeTrue(endedCountDown.await(3, TimeUnit.SECONDS));
         assertThat(mCaptureSessionRepository.getCaptureSessions().size()).isEqualTo(0);
 
         CameraUtil.releaseCameraDevice(holder);
@@ -1266,6 +1181,8 @@
     public void cameraDisconnected_captureSessionsOnClosedShouldBeCalled_repeatingStarted()
             throws ExecutionException, InterruptedException, TimeoutException,
             CameraAccessException {
+        assumeFalse("Known device issue, b/255461164", "cph1931".equalsIgnoreCase(Build.MODEL));
+
         CaptureSession captureSession = createCaptureSession();
         captureSession.setSessionConfig(mTestParameters0.mSessionConfig);
         captureSession.open(mTestParameters0.mSessionConfig, mCameraDeviceHolder.get(),
@@ -1316,6 +1233,8 @@
     public void cameraDisconnected_captureSessionsOnClosedShouldBeCalled_withoutRepeating()
             throws CameraAccessException, InterruptedException, ExecutionException,
             TimeoutException {
+        assumeFalse("Known device issue, b/255461164", "cph1931".equalsIgnoreCase(Build.MODEL));
+
         // The CameraCaptureSession will call close() automatically when CameraDevice is
         // disconnected, and the CameraCaptureSession should receive the onClosed() callback if
         // the CameraDevice status is idling.
@@ -1367,7 +1286,7 @@
         outputConfigList.add(
                 new OutputConfigurationCompat(mTestParameters0.mImageReader.getSurface()));
 
-        SynchronizedCaptureSessionOpener synchronizedCaptureSessionOpener =
+        SynchronizedCaptureSession.Opener synchronizedCaptureSessionOpener =
                 mCaptureSessionOpenerBuilder.build();
 
         SessionConfigurationCompat sessionConfigCompat =
@@ -1433,12 +1352,11 @@
             sessionConfigBuilder.addSurface(deferrableSurface);
         }
 
-        FakeOpenerImpl fakeOpener = new FakeOpenerImpl();
-        SynchronizedCaptureSessionOpener opener = new SynchronizedCaptureSessionOpener(fakeOpener);
+        FakeOpener fakeOpener = new FakeOpener();
         // Don't use #createCaptureSession since FakeOpenerImpl won't create CameraCaptureSession
         // so no need to be released.
         CaptureSession captureSession = new CaptureSession(mDynamicRangesCompat);
-        captureSession.open(sessionConfigBuilder.build(), mCameraDeviceHolder.get(), opener);
+        captureSession.open(sessionConfigBuilder.build(), mCameraDeviceHolder.get(), fakeOpener);
 
         ArgumentCaptor<SessionConfigurationCompat> captor =
                 ArgumentCaptor.forClass(SessionConfigurationCompat.class);
@@ -1673,55 +1591,6 @@
         }
     }
 
-    /**
-     * A implementation to test {@link CameraEventCallback} on CaptureSession.f
-     */
-    private static class TestCameraEventCallback extends CameraEventCallback {
-
-        TestCameraEventCallback(CameraCharacteristicsCompat characteristics) {
-            if (characteristics != null) {
-                int[] availableSceneModes =
-                        characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES);
-                if (availableSceneModes != null && availableSceneModes.length > 0) {
-                    mAvailableSceneMode = availableSceneModes[0];
-                } else {
-                    mAvailableSceneMode = CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
-                }
-            } else {
-                mAvailableSceneMode = CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED;
-            }
-        }
-
-        private final CameraCaptureCallback mEnableCallback = Mockito.mock(
-                CameraCaptureCallback.class);
-        private final CameraCaptureCallback mDisableCallback = Mockito.mock(
-                CameraCaptureCallback.class);
-
-        private final int mAvailableSceneMode;
-
-        @Override
-        public CaptureConfig onInitSession() {
-            return getCaptureConfig(CaptureRequest.CONTROL_SCENE_MODE, mAvailableSceneMode, null);
-        }
-
-        @Override
-        public CaptureConfig onEnableSession() {
-            return getCaptureConfig(CaptureRequest.CONTROL_SCENE_MODE, mAvailableSceneMode,
-                    mEnableCallback);
-        }
-
-        @Override
-        public CaptureConfig onRepeating() {
-            return getCaptureConfig(CaptureRequest.CONTROL_SCENE_MODE, mAvailableSceneMode, null);
-        }
-
-        @Override
-        public CaptureConfig onDisableSession() {
-            return getCaptureConfig(CaptureRequest.CONTROL_SCENE_MODE, mAvailableSceneMode,
-                    mDisableCallback);
-        }
-    }
-
     private static <T> CaptureConfig getCaptureConfig(CaptureRequest.Key<T> key, T effectValue,
             CameraCaptureCallback callback) {
         CaptureConfig.Builder captureConfigBuilder = new CaptureConfig.Builder();
@@ -1733,10 +1602,10 @@
         return captureConfigBuilder.build();
     }
 
-    private static class FakeOpenerImpl implements SynchronizedCaptureSessionOpener.OpenerImpl {
+    private static class FakeOpener implements SynchronizedCaptureSession.Opener {
 
-        final SynchronizedCaptureSessionOpener.OpenerImpl mMock = mock(
-                SynchronizedCaptureSessionOpener.OpenerImpl.class);
+        final SynchronizedCaptureSession.Opener mMock = mock(
+                SynchronizedCaptureSession.Opener.class);
 
         @NonNull
         @Override
@@ -1816,10 +1685,6 @@
         private final SessionConfig mSessionConfig;
         private final CaptureConfig mCaptureConfig;
 
-        private final TestCameraEventCallback mTestCameraEventCallback;
-        private final CameraEventCallback mMockCameraEventCallback = Mockito.mock(
-                CameraEventCallback.class);
-
         private final CameraCaptureSession.StateCallback mSessionStateCallback =
                 Mockito.mock(CameraCaptureSession.StateCallback.class);
         private final CameraCaptureCallback mSessionCameraCaptureCallback =
@@ -1864,27 +1729,13 @@
             builder.addRepeatingCameraCaptureCallback(
                     CaptureCallbackContainer.create(mCamera2CaptureCallback));
 
-            mTestCameraEventCallback = new TestCameraEventCallback(characteristics);
-            MutableOptionsBundle testCallbackConfig = MutableOptionsBundle.create();
-            testCallbackConfig.insertOption(Camera2ImplConfig.CAMERA_EVENT_CALLBACK_OPTION,
-                    new CameraEventCallbacks(mTestCameraEventCallback));
-            builder.addImplementationOptions(testCallbackConfig);
-
-            MutableOptionsBundle mockCameraEventCallbackConfig = MutableOptionsBundle.create();
-            mockCameraEventCallbackConfig.insertOption(
-                    Camera2ImplConfig.CAMERA_EVENT_CALLBACK_OPTION,
-                    new CameraEventCallbacks(mMockCameraEventCallback));
-            builder.addImplementationOptions(mockCameraEventCallbackConfig);
-
             // Set capture request options
             // ==================================================================================
             // Priority | Component        | AF_MODE       | EV MODE            | AE_MODE
             // ----------------------------------------------------------------------------------
             // P1 | CaptureConfig          | AF_MODE_OFF  |                     |
             // ----------------------------------------------------------------------------------
-            // P2 | CameraEventCallbacks   | AF_MODE_MACRO | Min EV             |
-            // ----------------------------------------------------------------------------------
-            // P3 | SessionConfig          | AF_MODE_AUTO  | Max EV             | AE_MODE_ON
+            // P2 | SessionConfig          | AF_MODE_AUTO  | Max EV             | AE_MODE_ON
             // ==================================================================================
 
             mEvRange = characteristics != null
@@ -1893,27 +1744,6 @@
 
             Camera2ImplConfig.Builder camera2ConfigBuilder = new Camera2ImplConfig.Builder();
 
-            // Add capture request options for CameraEventCallbacks
-            CameraEventCallback cameraEventCallback = new CameraEventCallback() {
-                @Override
-                public CaptureConfig onRepeating() {
-                    CaptureConfig.Builder builder = new CaptureConfig.Builder();
-                    builder.addImplementationOptions(
-                            new Camera2ImplConfig.Builder()
-                                    .setCaptureRequestOption(
-                                            CaptureRequest.CONTROL_AF_MODE,
-                                            CaptureRequest.CONTROL_AF_MODE_MACRO)
-                                    .setCaptureRequestOption(
-                                            CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION,
-                                            mEvRange.getLower())
-                                    .build());
-                    return builder.build();
-                }
-            };
-            new Camera2ImplConfig.Extender<>(camera2ConfigBuilder)
-                    .setCameraEventCallback(
-                            new CameraEventCallbacks(cameraEventCallback));
-
             // Add capture request options for SessionConfig
             camera2ConfigBuilder
                     .setCaptureRequestOption(
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
index 6752ba2..63460d1 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
@@ -133,7 +133,7 @@
 
     private lateinit var cameraDeviceHolder: CameraDeviceHolder
     private lateinit var captureSessionRepository: CaptureSessionRepository
-    private lateinit var captureSessionOpenerBuilder: SynchronizedCaptureSessionOpener.Builder
+    private lateinit var captureSessionOpenerBuilder: SynchronizedCaptureSession.OpenerBuilder
     private lateinit var sessionProcessor: FakeSessionProcessor
     private lateinit var executor: Executor
     private lateinit var handler: Handler
@@ -160,7 +160,7 @@
         val cameraId = CameraUtil.getCameraIdWithLensFacing(lensFacing)!!
         camera2CameraInfo = Camera2CameraInfoImpl(cameraId, cameraManagerCompat)
         captureSessionRepository = CaptureSessionRepository(executor)
-        captureSessionOpenerBuilder = SynchronizedCaptureSessionOpener.Builder(
+        captureSessionOpenerBuilder = SynchronizedCaptureSession.OpenerBuilder(
             executor,
             executor as ScheduledExecutorService,
             handler,
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
index 39e937f..aed6d4e 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/Camera2ImplConfig.java
@@ -66,11 +66,6 @@
             SESSION_CAPTURE_CALLBACK_OPTION =
             Option.create("camera2.cameraCaptureSession.captureCallback",
                     CameraCaptureSession.CaptureCallback.class);
-
-    @RestrictTo(Scope.LIBRARY)
-    public static final Option<CameraEventCallbacks> CAMERA_EVENT_CALLBACK_OPTION =
-            Option.create("camera2.cameraEvent.callback", CameraEventCallbacks.class);
-
     @RestrictTo(Scope.LIBRARY)
     public static final Option<Object> CAPTURE_REQUEST_TAG_OPTION = Option.create(
             "camera2.captureRequest.tag", Object.class);
@@ -180,19 +175,6 @@
     }
 
     /**
-     * Returns the stored CameraEventCallbacks instance.
-     *
-     * @param valueIfMissing The value to return if this configuration option has not been set.
-     * @return The stored value or <code>valueIfMissing</code> if the value does not exist in this
-     * configuration.
-     */
-    @Nullable
-    public CameraEventCallbacks getCameraEventCallback(
-            @Nullable CameraEventCallbacks valueIfMissing) {
-        return getConfig().retrieveOption(CAMERA_EVENT_CALLBACK_OPTION, valueIfMissing);
-    }
-
-    /**
      * Returns the capture request tag.
      *
      * @param valueIfMissing The value to return if this configuration option has not been set.
@@ -281,38 +263,4 @@
             return new Camera2ImplConfig(OptionsBundle.from(mMutableOptionsBundle));
         }
     }
-
-    /**
-     * Extends a {@link ExtendableBuilder} to add Camera2 implementation options.
-     *
-     * @param <T> the type being built by the extendable builder.
-     */
-    public static final class Extender<T> {
-
-        ExtendableBuilder<T> mBaseBuilder;
-
-        /**
-         * Creates an Extender that can be used to add Camera2 implementation options to another
-         * Builder.
-         *
-         * @param baseBuilder The builder being extended.
-         */
-        public Extender(@NonNull ExtendableBuilder<T> baseBuilder) {
-            mBaseBuilder = baseBuilder;
-        }
-
-        /**
-         * Sets a CameraEventCallbacks instance.
-         *
-         * @param cameraEventCallbacks The CameraEventCallbacks.
-         * @return The current Extender.
-         */
-        @NonNull
-        public Extender<T> setCameraEventCallback(
-                @NonNull CameraEventCallbacks cameraEventCallbacks) {
-            mBaseBuilder.getMutableConfig().insertOption(CAMERA_EVENT_CALLBACK_OPTION,
-                    cameraEventCallbacks);
-            return this;
-        }
-    }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallback.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallback.java
deleted file mode 100644
index 1a2d805..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallback.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.
- */
-
-package androidx.camera.camera2.impl;
-
-import android.hardware.camera2.CameraCaptureSession;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CaptureConfig;
-
-/**
- * A callback object for tracking the camera capture session event and get request data.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public abstract class CameraEventCallback {
-
-    /**
-     * This will be invoked before creating a {@link CameraCaptureSession} for initializing the
-     * session.
-     *
-     * <p>The returned parameter in CaptureConfig will be passed to the camera device as part of
-     * the capture session initialization via setSessionParameters(). The valid parameter is a
-     * subset of the available capture request parameters.
-     *
-     * @return CaptureConfig The request information to customize the session.
-     */
-    @Nullable
-    public CaptureConfig onInitSession() {
-        return null;
-    }
-
-    /**
-     * This will be invoked once after a {@link CameraCaptureSession} is created. The returned
-     * parameter in CaptureConfig will be used to generate a single request to the current
-     * configured camera device. The generated request would be submitted to camera before process
-     * other single request.
-     *
-     * @return CaptureConfig The request information to customize the session.
-     */
-    @Nullable
-    public CaptureConfig onEnableSession() {
-        return null;
-    }
-
-    /**
-     * This callback will be invoked before starting the repeating request in the
-     * {@link CameraCaptureSession}. The returned CaptureConfig will be used to generate a
-     * capture request, and would be used in setRepeatingRequest().
-     *
-     * @return CaptureConfig The request information to customize the session.
-     */
-    @Nullable
-    public CaptureConfig onRepeating() {
-        return null;
-    }
-
-    /**
-     * This will be invoked once before the {@link CameraCaptureSession} is closed. The
-     * returned parameter in CaptureConfig will be used to generate a single request to the current
-     * configured camera device. The generated request would be submitted to camera before the
-     * capture session was closed.
-     *
-     * @return CaptureConfig The request information to customize the session.
-     */
-    @Nullable
-    public CaptureConfig onDisableSession() {
-        return null;
-    }
-
-    /**
-     * This will be invoked after the {@link CameraCaptureSession} is closed.
-     */
-    public void onDeInitSession() {}
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallbacks.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallbacks.java
deleted file mode 100644
index f0badc3..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/impl/CameraEventCallbacks.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.
- */
-
-package androidx.camera.camera2.impl;
-
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.MultiValueSet;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Different implementations of {@link CameraEventCallback}.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-public final class CameraEventCallbacks extends MultiValueSet<CameraEventCallback> {
-
-    public CameraEventCallbacks(@NonNull CameraEventCallback... callbacks) {
-        addAll(Arrays.asList(callbacks));
-    }
-
-    /** Returns a camera event callback which calls a list of other callbacks. */
-    @NonNull
-    public ComboCameraEventCallback createComboCallback() {
-        return new ComboCameraEventCallback(getAllItems());
-    }
-
-    /** Returns a camera event callback which does nothing. */
-    @NonNull
-    public static CameraEventCallbacks createEmptyCallback() {
-        return new CameraEventCallbacks();
-    }
-
-    @NonNull
-    @Override
-    public MultiValueSet<CameraEventCallback> clone() {
-        CameraEventCallbacks ret = createEmptyCallback();
-        ret.addAll(getAllItems());
-        return ret;
-    }
-
-    /**
-     * A CameraEventCallback which contains a list of CameraEventCallback and will
-     * propagate received callback to the list.
-     */
-    public static final class ComboCameraEventCallback {
-        private final List<CameraEventCallback> mCallbacks = new ArrayList<>();
-
-        ComboCameraEventCallback(List<CameraEventCallback> callbacks) {
-            for (CameraEventCallback callback : callbacks) {
-                mCallbacks.add(callback);
-            }
-        }
-
-        /**
-         * Invokes {@link CameraEventCallback#onInitSession()} on all registered callbacks and
-         * returns a {@link CaptureConfig} list that aggregates all the results for setting the
-         * session parameters.
-         *
-         * @return a {@link List<CaptureConfig>} that contains session parameters to be configured
-         * upon creating {@link android.hardware.camera2.CameraCaptureSession}
-         */
-        @NonNull
-        public List<CaptureConfig> onInitSession() {
-            List<CaptureConfig> ret = new ArrayList<>();
-            for (CameraEventCallback callback : mCallbacks) {
-                CaptureConfig presetCaptureStage = callback.onInitSession();
-                if (presetCaptureStage != null) {
-                    ret.add(presetCaptureStage);
-                }
-            }
-            return ret;
-        }
-
-        /**
-         * Invokes {@link CameraEventCallback#onEnableSession()} on all registered callbacks and
-         * returns a {@link CaptureConfig} list that aggregates all the results. The returned
-         * list contains capture request parameters to be set on a single request that will be
-         * triggered right after {@link android.hardware.camera2.CameraCaptureSession} is
-         * configured.
-         *
-         * @return a {@link List<CaptureConfig>} that contains capture request parameters to be
-         * set on a single request that will be triggered after
-         * {@link android.hardware.camera2.CameraCaptureSession} is configured.
-         */
-        @NonNull
-        public List<CaptureConfig> onEnableSession() {
-            List<CaptureConfig> ret = new ArrayList<>();
-            for (CameraEventCallback callback : mCallbacks) {
-                CaptureConfig enableCaptureStage = callback.onEnableSession();
-                if (enableCaptureStage != null) {
-                    ret.add(enableCaptureStage);
-                }
-            }
-            return ret;
-        }
-
-        /**
-         * Invokes {@link CameraEventCallback#onRepeating()} on all registered callbacks and
-         * returns a {@link CaptureConfig} list that aggregates all the results. The returned
-         * list contains capture request parameters to be set on the repeating request.
-         *
-         * @return a {@link List<CaptureConfig>} that contains capture request parameters to be
-         * set on the repeating request.
-         */
-        @NonNull
-        public List<CaptureConfig> onRepeating() {
-            List<CaptureConfig> ret = new ArrayList<>();
-            for (CameraEventCallback callback : mCallbacks) {
-                CaptureConfig repeatingCaptureStage = callback.onRepeating();
-                if (repeatingCaptureStage != null) {
-                    ret.add(repeatingCaptureStage);
-                }
-            }
-            return ret;
-        }
-
-        /**
-         * Invokes {@link CameraEventCallback#onDisableSession()} on all registered callbacks and
-         * returns a {@link CaptureConfig} list that aggregates all the results. The returned
-         * list contains capture request parameters to be set on a single request that will be
-         * triggered right before {@link android.hardware.camera2.CameraCaptureSession} is closed.
-         *
-         * @return a {@link List<CaptureConfig>} that contains capture request parameters to be
-         * set on a single request that will be triggered right before
-         * {@link android.hardware.camera2.CameraCaptureSession} is closed.
-         */
-        @NonNull
-        public List<CaptureConfig> onDisableSession() {
-            List<CaptureConfig> ret = new ArrayList<>();
-            for (CameraEventCallback callback : mCallbacks) {
-                CaptureConfig disableCaptureStage = callback.onDisableSession();
-                if (disableCaptureStage != null) {
-                    ret.add(disableCaptureStage);
-                }
-            }
-            return ret;
-        }
-
-        /**
-         * Invokes {@link CameraEventCallback#onDeInitSession()} on all registered callbacks.
-         */
-        public void onDeInitSession() {
-            for (CameraEventCallback callback : mCallbacks) {
-                callback.onDeInitSession();
-            }
-        }
-
-        @NonNull
-        public List<CameraEventCallback> getCallbacks() {
-            return mCallbacks;
-        }
-    }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 1f4e430..c049a71 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -183,7 +183,7 @@
     @NonNull
     private final CaptureSessionRepository mCaptureSessionRepository;
     @NonNull
-    private final SynchronizedCaptureSessionOpener.Builder mCaptureSessionOpenerBuilder;
+    private final SynchronizedCaptureSession.OpenerBuilder mCaptureSessionOpenerBuilder;
     private final Set<String> mNotifyStateAttachedSet = new HashSet<>();
 
     @NonNull
@@ -257,7 +257,7 @@
                 DynamicRangesCompat.fromCameraCharacteristics(mCameraCharacteristicsCompat);
         mCaptureSession = newCaptureSession();
 
-        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSessionOpener.Builder(mExecutor,
+        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSession.OpenerBuilder(mExecutor,
                 mScheduledExecutorService, schedulerHandler, mCaptureSessionRepository,
                 cameraInfoImpl.getCameraQuirks(), DeviceQuirks.getAll());
 
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpacker.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpacker.java
index 17ca148..e64c90c 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpacker.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpacker.java
@@ -22,7 +22,6 @@
 import androidx.annotation.OptIn;
 import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.camera2.impl.CameraEventCallbacks;
 import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
 import androidx.camera.camera2.internal.compat.workaround.PreviewPixelHDRnet;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
@@ -92,8 +91,6 @@
 
         // Copy extended Camera2 configurations
         MutableOptionsBundle extendedConfig = MutableOptionsBundle.create();
-        extendedConfig.insertOption(Camera2ImplConfig.CAMERA_EVENT_CALLBACK_OPTION,
-                camera2Config.getCameraEventCallback(CameraEventCallbacks.createEmptyCallback()));
         extendedConfig.insertOption(Camera2ImplConfig.SESSION_PHYSICAL_CAMERA_ID_OPTION,
                 camera2Config.getPhysicalCameraId(null));
         extendedConfig.insertOption(Camera2ImplConfig.STREAM_USE_CASE_OPTION,
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
index 1030126..78f66c1 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
@@ -32,7 +32,6 @@
 import androidx.annotation.OptIn;
 import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.camera2.impl.CameraEventCallbacks;
 import androidx.camera.camera2.internal.compat.params.DynamicRangeConversions;
 import androidx.camera.camera2.internal.compat.params.DynamicRangesCompat;
 import androidx.camera.camera2.internal.compat.params.InputConfigurationCompat;
@@ -45,10 +44,7 @@
 import androidx.camera.core.Logger;
 import androidx.camera.core.impl.CameraCaptureCallback;
 import androidx.camera.core.impl.CaptureConfig;
-import androidx.camera.core.impl.Config;
 import androidx.camera.core.impl.DeferrableSurface;
-import androidx.camera.core.impl.MutableOptionsBundle;
-import androidx.camera.core.impl.OptionsBundle;
 import androidx.camera.core.impl.SessionConfig;
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.FutureChain;
@@ -63,7 +59,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.concurrent.CancellationException;
 
 /**
@@ -96,7 +91,7 @@
     /** The Opener to help on creating the SynchronizedCaptureSession. */
     @Nullable
     @GuardedBy("mSessionLock")
-    SynchronizedCaptureSessionOpener mSynchronizedCaptureSessionOpener;
+    SynchronizedCaptureSession.Opener mSessionOpener;
     /** The framework camera capture session held by this session. */
     @Nullable
     @GuardedBy("mSessionLock")
@@ -105,15 +100,6 @@
     @Nullable
     @GuardedBy("mSessionLock")
     SessionConfig mSessionConfig;
-    /** The capture options from CameraEventCallback.onRepeating(). */
-    @NonNull
-    @GuardedBy("mSessionLock")
-    Config mCameraEventOnRepeatingOptions = OptionsBundle.emptyBundle();
-    /** The CameraEventCallbacks for this capture session. */
-    @SuppressWarnings("WeakerAccess") /* synthetic accessor */
-    @GuardedBy("mSessionLock")
-    @NonNull
-    CameraEventCallbacks mCameraEventCallbacks = CameraEventCallbacks.createEmptyCallback();
     /**
      * The map of DeferrableSurface to Surface. It is both for restoring the surfaces used to
      * configure the current capture session and for getting the configured surface from a
@@ -215,22 +201,19 @@
     @Override
     public ListenableFuture<Void> open(@NonNull SessionConfig sessionConfig,
             @NonNull CameraDevice cameraDevice,
-            @NonNull SynchronizedCaptureSessionOpener opener) {
+            @NonNull SynchronizedCaptureSession.Opener opener) {
         synchronized (mSessionLock) {
             switch (mState) {
                 case INITIALIZED:
                     mState = State.GET_SURFACE;
-                    List<DeferrableSurface> surfaces = sessionConfig.getSurfaces();
-                    mConfiguredDeferrableSurfaces = new ArrayList<>(surfaces);
-                    mSynchronizedCaptureSessionOpener = opener;
+                    mConfiguredDeferrableSurfaces = new ArrayList<>(sessionConfig.getSurfaces());
+                    mSessionOpener = opener;
                     ListenableFuture<Void> openFuture = FutureChain.from(
-                                    mSynchronizedCaptureSessionOpener.startWithDeferrableSurface(
-                                            mConfiguredDeferrableSurfaces,
-                                            TIMEOUT_GET_SURFACE_IN_MS))
-                            .transformAsync(
-                                    surfaceList -> openCaptureSession(surfaceList, sessionConfig,
-                                            cameraDevice),
-                                    mSynchronizedCaptureSessionOpener.getExecutor());
+                            mSessionOpener.startWithDeferrableSurface(
+                                    mConfiguredDeferrableSurfaces, TIMEOUT_GET_SURFACE_IN_MS)
+                    ).transformAsync(
+                            surfaces -> openCaptureSession(surfaces, sessionConfig, cameraDevice),
+                            mSessionOpener.getExecutor());
 
                     Futures.addCallback(openFuture, new FutureCallback<Void>() {
                         @Override
@@ -242,7 +225,7 @@
                         public void onFailure(@NonNull Throwable t) {
                             synchronized (mSessionLock) {
                                 // Stop the Opener if we get any failure during opening.
-                                mSynchronizedCaptureSessionOpener.stop();
+                                mSessionOpener.stop();
                                 switch (mState) {
                                     case OPENING:
                                     case CLOSED:
@@ -256,7 +239,7 @@
                                 }
                             }
                         }
-                    }, mSynchronizedCaptureSessionOpener.getExecutor());
+                    }, mSessionOpener.getExecutor());
 
                     // The cancellation of the external ListenableFuture cannot actually stop
                     // the open session since we can't cancel the camera2 flow. The underlying
@@ -305,23 +288,12 @@
 
                     Camera2ImplConfig camera2Config =
                             new Camera2ImplConfig(sessionConfig.getImplementationOptions());
-                    // Start check preset CaptureStage information.
-                    mCameraEventCallbacks = camera2Config
-                            .getCameraEventCallback(CameraEventCallbacks.createEmptyCallback());
-                    List<CaptureConfig> presetList =
-                            mCameraEventCallbacks.createComboCallback().onInitSession();
-
                     // Generate the CaptureRequest builder from repeating request since Android
                     // recommend use the same template type as the initial capture request. The
                     // tag and output targets would be ignored by default.
-                    CaptureConfig.Builder captureConfigBuilder =
+                    CaptureConfig.Builder sessionParameterConfigBuilder =
                             CaptureConfig.Builder.from(sessionConfig.getRepeatingCaptureConfig());
 
-                    for (CaptureConfig config : presetList) {
-                        captureConfigBuilder.addImplementationOptions(
-                                config.getImplementationOptions());
-                    }
-
                     List<OutputConfigurationCompat> outputConfigList = new ArrayList<>();
                     String physicalCameraIdForAllStreams =
                             camera2Config.getPhysicalCameraId(null);
@@ -346,7 +318,7 @@
                     outputConfigList = getUniqueOutputConfigurations(outputConfigList);
 
                     SessionConfigurationCompat sessionConfigCompat =
-                            mSynchronizedCaptureSessionOpener.createSessionConfigurationCompat(
+                            mSessionOpener.createSessionConfigurationCompat(
                                     SessionConfigurationCompat.SESSION_REGULAR, outputConfigList,
                                     callbacks);
 
@@ -360,7 +332,7 @@
                     try {
                         CaptureRequest captureRequest =
                                 Camera2CaptureRequestBuilder.buildWithoutTarget(
-                                        captureConfigBuilder.build(), cameraDevice);
+                                        sessionParameterConfigBuilder.build(), cameraDevice);
                         if (captureRequest != null) {
                             sessionConfigCompat.setSessionParameters(captureRequest);
                         }
@@ -368,7 +340,7 @@
                         return Futures.immediateFailedFuture(e);
                     }
 
-                    return mSynchronizedCaptureSessionOpener.openCaptureSession(cameraDevice,
+                    return mSessionOpener.openCaptureSession(cameraDevice,
                             sessionConfigCompat, mConfiguredDeferrableSurfaces);
                 default:
                     return Futures.immediateFailedFuture(new CancellationException(
@@ -459,34 +431,19 @@
                     throw new IllegalStateException(
                             "close() should not be possible in state: " + mState);
                 case GET_SURFACE:
-                    Preconditions.checkNotNull(mSynchronizedCaptureSessionOpener, "The "
-                            + "Opener shouldn't null in state:" + mState);
-                    mSynchronizedCaptureSessionOpener.stop();
+                    Preconditions.checkNotNull(mSessionOpener,
+                            "The Opener shouldn't null in state:" + mState);
+                    mSessionOpener.stop();
                     // Fall through
                 case INITIALIZED:
                     mState = State.RELEASED;
                     break;
                 case OPENED:
-                    // Only issue onDisableSession requests at OPENED state.
-                    if (mSessionConfig != null) {
-                        List<CaptureConfig> configList =
-                                mCameraEventCallbacks.createComboCallback().onDisableSession();
-                        if (!configList.isEmpty()) {
-                            try {
-                                issueCaptureRequests(setupConfiguredSurface(configList));
-                            } catch (IllegalStateException e) {
-                                // We couldn't issue the request before close the capture session,
-                                // but we should continue the close flow.
-                                Logger.e(TAG, "Unable to issue the request before close the "
-                                        + "capture session", e);
-                            }
-                        }
-                    }
                     // Not break close flow. Fall through
                 case OPENING:
-                    Preconditions.checkNotNull(mSynchronizedCaptureSessionOpener, "The "
-                            + "Opener shouldn't null in state:" + mState);
-                    mSynchronizedCaptureSessionOpener.stop();
+                    Preconditions.checkNotNull(mSessionOpener,
+                            "The Opener shouldn't null in state:" + mState);
+                    mSessionOpener.stop();
                     mState = State.CLOSED;
                     mSessionConfig = null;
 
@@ -527,11 +484,10 @@
                     }
                     // Fall through
                 case OPENING:
-                    mCameraEventCallbacks.createComboCallback().onDeInitSession();
                     mState = State.RELEASING;
-                    Preconditions.checkNotNull(mSynchronizedCaptureSessionOpener, "The "
-                            + "Opener shouldn't null in state:" + mState);
-                    if (mSynchronizedCaptureSessionOpener.stop()) {
+                    Preconditions.checkNotNull(mSessionOpener,
+                            "The Opener shouldn't null in state:" + mState);
+                    if (mSessionOpener.stop()) {
                         // The CameraCaptureSession doesn't created finish the release flow
                         // directly.
                         finishClose();
@@ -553,9 +509,9 @@
 
                     return mReleaseFuture;
                 case GET_SURFACE:
-                    Preconditions.checkNotNull(mSynchronizedCaptureSessionOpener, "The "
-                            + "Opener shouldn't null in state:" + mState);
-                    mSynchronizedCaptureSessionOpener.stop();
+                    Preconditions.checkNotNull(mSessionOpener,
+                            "The Opener shouldn't null in state:" + mState);
+                    mSessionOpener.stop();
                     // Fall through
                 case INITIALIZED:
                     mState = State.RELEASED;
@@ -668,19 +624,8 @@
 
             try {
                 Logger.d(TAG, "Issuing request for session.");
-
-                // The override priority for implementation options
-                // P1 CameraEventCallback onRepeating options
-                // P2 SessionConfig options
-                CaptureConfig.Builder captureConfigBuilder = CaptureConfig.Builder.from(
-                        captureConfig);
-
-                mCameraEventOnRepeatingOptions = mergeOptions(
-                        mCameraEventCallbacks.createComboCallback().onRepeating());
-                captureConfigBuilder.addImplementationOptions(mCameraEventOnRepeatingOptions);
-
                 CaptureRequest captureRequest = Camera2CaptureRequestBuilder.build(
-                        captureConfigBuilder.build(), mSynchronizedCaptureSession.getDevice(),
+                        captureConfig, mSynchronizedCaptureSession.getDevice(),
                         mConfiguredSurfaceMap);
                 if (captureRequest == null) {
                     Logger.d(TAG, "Skipping issuing empty request for session.");
@@ -775,16 +720,13 @@
 
                     // The override priority for implementation options
                     // P1 Single capture options
-                    // P2 CameraEventCallback onRepeating options
-                    // P3 SessionConfig options
+                    // P2 SessionConfig options
                     if (mSessionConfig != null) {
                         captureConfigBuilder.addImplementationOptions(
                                 mSessionConfig.getRepeatingCaptureConfig()
                                         .getImplementationOptions());
                     }
 
-                    captureConfigBuilder.addImplementationOptions(mCameraEventOnRepeatingOptions);
-
                     // Need to override again since single capture options has highest priority.
                     captureConfigBuilder.addImplementationOptions(
                             captureConfig.getImplementationOptions());
@@ -930,42 +872,6 @@
         return Camera2CaptureCallbacks.createComboCallback(camera2Callbacks);
     }
 
-
-    /**
-     * Merges the implementation options from the input {@link CaptureConfig} list.
-     *
-     * <p>It will retain the first option if a conflict is detected.
-     *
-     * @param captureConfigList CaptureConfig list to be merged.
-     * @return merged options.
-     */
-    @NonNull
-    private static Config mergeOptions(List<CaptureConfig> captureConfigList) {
-        MutableOptionsBundle options = MutableOptionsBundle.create();
-        for (CaptureConfig captureConfig : captureConfigList) {
-            Config newOptions = captureConfig.getImplementationOptions();
-            for (Config.Option<?> option : newOptions.listOptions()) {
-                @SuppressWarnings("unchecked") // Options/values are being copied directly
-                Config.Option<Object> objectOpt = (Config.Option<Object>) option;
-                Object newValue = newOptions.retrieveOption(objectOpt, null);
-                if (options.containsOption(option)) {
-                    Object oldValue = options.retrieveOption(objectOpt, null);
-                    if (!Objects.equals(oldValue, newValue)) {
-                        Logger.d(TAG, "Detect conflicting option "
-                                + objectOpt.getId()
-                                + " : "
-                                + newValue
-                                + " != "
-                                + oldValue);
-                    }
-                } else {
-                    options.insertOption(objectOpt, newValue);
-                }
-            }
-        }
-        return options;
-    }
-
     enum State {
         /** The default state of the session before construction. */
         UNINITIALIZED,
@@ -1033,16 +939,6 @@
                     case OPENING:
                         mState = State.OPENED;
                         mSynchronizedCaptureSession = session;
-
-                        // Issue capture request of enableSession if exists.
-                        if (mSessionConfig != null) {
-                            List<CaptureConfig> list =
-                                    mCameraEventCallbacks.createComboCallback().onEnableSession();
-                            if (!list.isEmpty()) {
-                                issueBurstCaptureRequest(setupConfiguredSurface(list));
-                            }
-                        }
-
                         Logger.d(TAG, "Attempting to send capture request onConfigured");
                         issueRepeatingCaptureRequests(mSessionConfig);
                         issuePendingCaptureRequest();
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
index 351c8f5..4e745ce 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
@@ -62,7 +62,7 @@
     @NonNull
     ListenableFuture<Void> open(@NonNull SessionConfig sessionConfig,
             @NonNull CameraDevice cameraDevice,
-            @NonNull SynchronizedCaptureSessionOpener opener);
+            @NonNull SynchronizedCaptureSession.Opener opener);
 
 
     /**
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
index 5c9eb4b..01357dc 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
@@ -142,7 +142,7 @@
     @NonNull
     @Override
     public ListenableFuture<Void> open(@NonNull SessionConfig sessionConfig,
-            @NonNull CameraDevice cameraDevice, @NonNull SynchronizedCaptureSessionOpener opener) {
+            @NonNull CameraDevice cameraDevice, @NonNull SynchronizedCaptureSession.Opener opener) {
         Preconditions.checkArgument(mProcessorState == ProcessorState.UNINITIALIZED,
                 "Invalid state state:" + mProcessorState);
         Preconditions.checkArgument(!sessionConfig.getSurfaces().isEmpty(),
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSession.java
index 2c1a74b..e5e07ac 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSession.java
@@ -20,18 +20,26 @@
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.params.SessionConfiguration;
 import android.os.Build;
+import android.os.Handler;
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.annotation.CameraExecutor;
 import androidx.camera.camera2.internal.compat.CameraCaptureSessionCompat;
+import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
+import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
+import androidx.camera.core.impl.DeferrableSurface;
+import androidx.camera.core.impl.Quirks;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
 import java.util.List;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ScheduledExecutorService;
 
 /**
  * The interface for accessing features in {@link CameraCaptureSession}.
@@ -47,10 +55,10 @@
  * if it need to use a Executor. Most use cases should attempt to call the overloaded method
  * instead.
  *
- * <p>The {@link SynchronizedCaptureSessionOpener} can help to create the
+ * <p>The {@link SynchronizedCaptureSession.Opener} can help to create the
  * {@link SynchronizedCaptureSession} object.
  *
- * @see SynchronizedCaptureSessionOpener
+ * @see SynchronizedCaptureSession.Opener
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 public interface SynchronizedCaptureSession {
@@ -363,4 +371,157 @@
 
         }
     }
+
+    /**
+     * Opener interface to open the {@link SynchronizedCaptureSession}.
+     *
+     * <p>The {@link #openCaptureSession} method can be used to open a new
+     * {@link SynchronizedCaptureSession}, and the {@link SessionConfigurationCompat} object is
+     * needed by the {@link #openCaptureSession} should be created via the
+     * {@link #createSessionConfigurationCompat}. It will send the ready-to-use
+     * {@link SynchronizedCaptureSession} to the provided listener's
+     * {@link SynchronizedCaptureSession.StateCallback#onConfigured} callback.
+     *
+     * <p>An Opener should only be used to open one SynchronizedCaptureSession. The Opener cannot be
+     * reused to open the second SynchronizedCaptureSession. The {@link #openCaptureSession} can't
+     * be called more than once in the same Opener.
+     *
+     * @see #openCaptureSession(CameraDevice, SessionConfigurationCompat, List)
+     * @see #createSessionConfigurationCompat(int, List, SynchronizedCaptureSession.StateCallback)
+     * @see SynchronizedCaptureSession.StateCallback
+     *
+     * <p>The {@link #stop} method should be invoked when the SynchronizedCaptureSession opening
+     * flow is interrupted.
+     * @see #startWithDeferrableSurface
+     * @see #stop()
+     */
+    interface Opener {
+
+        /**
+         * Opens the SynchronizedCaptureSession.
+         *
+         * <p>The behavior of this method similar to the
+         * {@link CameraDevice#createCaptureSession(SessionConfiguration)}. It will use the
+         * input cameraDevice to create the SynchronizedCaptureSession.
+         *
+         * <p>The {@link SessionConfigurationCompat} object that is needed in this method should be
+         * created via the {@link #createSessionConfigurationCompat}.
+         *
+         * <p>The use count of the input DeferrableSurfaces will be increased. It will be
+         * automatically decreased when the surface is not used by the camera. For instance, when
+         * the opened SynchronizedCaptureSession is closed completely or when the configuration of
+         * the session is failed.
+         *
+         * <p>Cancellation of the returned future is a no-op. The opening task can only be
+         * cancelled by the {@link #stop()}. The {@link #stop()} only effective when the
+         * CameraDevice#createCaptureSession() hasn't been invoked. If the {@link #stop()} is called
+         * before the CameraDevice#createCaptureSession(), it will stop the
+         * SynchronizedCaptureSession creation.
+         * Otherwise, the SynchronizedCaptureSession will be created and the
+         * {@link SynchronizedCaptureSession.StateCallback#onConfigured} or
+         * {@link SynchronizedCaptureSession.StateCallback#onConfigureFailed} callback will be
+         * invoked.
+         *
+         * @param cameraDevice               the camera with which to generate the
+         *                                   SynchronizedCaptureSession
+         * @param sessionConfigurationCompat A {@link SessionConfigurationCompat} that is created
+         *                                   via the {@link #createSessionConfigurationCompat}.
+         * @param deferrableSurfaces         the list of the DeferrableSurface that be used to
+         *                                   configure the session.
+         * @return a ListenableFuture object which completes when the SynchronizedCaptureSession is
+         * configured.
+         * @see #createSessionConfigurationCompat
+         * @see #stop()
+         */
+        @NonNull
+        ListenableFuture<Void> openCaptureSession(@NonNull CameraDevice cameraDevice,
+                @NonNull SessionConfigurationCompat sessionConfigurationCompat,
+                @NonNull List<DeferrableSurface> deferrableSurfaces);
+
+        /**
+         * Create the SessionConfigurationCompat for {@link #openCaptureSession} used.
+         *
+         * This method will add necessary information into the created SessionConfigurationCompat
+         * instance for SynchronizedCaptureSession.
+         *
+         * @param sessionType   The session type.
+         * @param outputsCompat A list of output configurations for the SynchronizedCaptureSession.
+         * @param stateCallback A state callback interface implementation.
+         */
+        @NonNull
+        SessionConfigurationCompat createSessionConfigurationCompat(int sessionType,
+                @NonNull List<OutputConfigurationCompat> outputsCompat,
+                @NonNull SynchronizedCaptureSession.StateCallback stateCallback);
+
+        /**
+         * Get the surface from the DeferrableSurfaces.
+         *
+         * <p>The {@link #startWithDeferrableSurface} method will return a Surface list that
+         * is held in the List<DeferrableSurface>. The Opener helps in maintaining the timing to
+         * close the returned DeferrableSurface list. Most use case should attempt to use the
+         * {@link #startWithDeferrableSurface} method to get the Surface for creating the
+         * SynchronizedCaptureSession.
+         *
+         * @param deferrableSurfaces The deferrable surfaces to open.
+         * @param timeout            the timeout to get surfaces from the deferrable surface list.
+         * @return the Future which will contain the surface list, Cancellation of this
+         * future is a no-op. The returned Surface list can be used to create the
+         * SynchronizedCaptureSession.
+         * @see #openCaptureSession
+         * @see #stop
+         */
+        @NonNull
+        ListenableFuture<List<Surface>> startWithDeferrableSurface(
+                @NonNull List<DeferrableSurface> deferrableSurfaces, long timeout);
+
+        @NonNull
+        @CameraExecutor
+        Executor getExecutor();
+
+        /**
+         * Disable the startWithDeferrableSurface() and openCaptureSession() ability, and stop the
+         * startWithDeferrableSurface() and openCaptureSession() if
+         * CameraDevice#createCaptureSession() hasn't been invoked. Once the
+         * CameraDevice#createCaptureSession() already been invoked, the task of
+         * openCaptureSession() will keep going.
+         *
+         * @return true if the CameraCaptureSession creation has not been started yet. Otherwise
+         * return false.
+         */
+        boolean stop();
+    }
+
+    /**
+     * A builder to create new {@link SynchronizedCaptureSession.Opener}
+     */
+    class OpenerBuilder {
+
+        private final Executor mExecutor;
+        private final ScheduledExecutorService mScheduledExecutorService;
+        private final Handler mCompatHandler;
+        private final CaptureSessionRepository mCaptureSessionRepository;
+        private final Quirks mCameraQuirks;
+        private final Quirks mDeviceQuirks;
+
+        OpenerBuilder(@NonNull @CameraExecutor Executor executor,
+                @NonNull ScheduledExecutorService scheduledExecutorService,
+                @NonNull Handler compatHandler,
+                @NonNull CaptureSessionRepository captureSessionRepository,
+                @NonNull Quirks cameraQuirks,
+                @NonNull Quirks deviceQuirks) {
+            mExecutor = executor;
+            mScheduledExecutorService = scheduledExecutorService;
+            mCompatHandler = compatHandler;
+            mCaptureSessionRepository = captureSessionRepository;
+            mCameraQuirks = cameraQuirks;
+            mDeviceQuirks = deviceQuirks;
+        }
+
+        @NonNull
+        Opener build() {
+            return new SynchronizedCaptureSessionImpl(mCameraQuirks, mDeviceQuirks,
+                    mCaptureSessionRepository, mExecutor, mScheduledExecutorService,
+                    mCompatHandler);
+        }
+    }
 }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionBaseImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionBaseImpl.java
index cea447a..9ed6659 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionBaseImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionBaseImpl.java
@@ -54,17 +54,19 @@
 import java.util.concurrent.ScheduledExecutorService;
 
 /**
- * The basic implementation of {@link SynchronizedCaptureSession} to forward the feature calls
- * into the {@link CameraCaptureSession}. It will not synchronize methods with the other
- * SynchronizedCaptureSessions.
+ * The implementation of {@link SynchronizedCaptureSession} to forward the feature calls
+ * into the {@link CameraCaptureSession}.
  *
- * The {@link StateCallback} to receives the state callbacks from the
- * {@link CameraCaptureSession.StateCallback} and convert the {@link CameraCaptureSession} to the
- * SynchronizedCaptureSession object.
+ * The implementation of {@link SynchronizedCaptureSession.StateCallback} and
+ * {@link SynchronizedCaptureSession.Opener} will be able to track the creation and close of the
+ * SynchronizedCaptureSession in {@link CaptureSessionRepository}.
+ * Some Quirks may be required to take some action before opening/closing other sessions, with the
+ * SynchronizedCaptureSessionBaseImpl, it would be useful when implementing the workaround of
+ * Quirks.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class SynchronizedCaptureSessionBaseImpl extends SynchronizedCaptureSession.StateCallback implements
-        SynchronizedCaptureSession, SynchronizedCaptureSessionOpener.OpenerImpl {
+        SynchronizedCaptureSession, SynchronizedCaptureSession.Opener {
 
     private static final String TAG = "SyncCaptureSessionBase";
 
@@ -144,22 +146,21 @@
             mCaptureSessionRepository.onCreateCaptureSession(this);
             CameraDeviceCompat cameraDeviceCompat =
                     CameraDeviceCompat.toCameraDeviceCompat(cameraDevice, mCompatHandler);
-            mOpenCaptureSessionFuture = CallbackToFutureAdapter.getFuture(
-                    completer -> {
-                        synchronized (mLock) {
-                            // Attempt to set all the configured deferrable surfaces is in used
-                            // before adding them to the session.
-                            holdDeferrableSurfaces(deferrableSurfaces);
+            mOpenCaptureSessionFuture = CallbackToFutureAdapter.getFuture(completer -> {
+                synchronized (mLock) {
+                    // Attempt to set all the configured deferrable surfaces is in used
+                    // before adding them to the session.
+                    holdDeferrableSurfaces(deferrableSurfaces);
 
-                            Preconditions.checkState(mOpenCaptureSessionCompleter == null,
-                                    "The openCaptureSessionCompleter can only set once!");
+                    Preconditions.checkState(mOpenCaptureSessionCompleter == null,
+                            "The openCaptureSessionCompleter can only set once!");
 
-                            mOpenCaptureSessionCompleter = completer;
-                            cameraDeviceCompat.createCaptureSession(sessionConfigurationCompat);
-                            return "openCaptureSession[session="
-                                    + SynchronizedCaptureSessionBaseImpl.this + "]";
-                        }
-                    });
+                    mOpenCaptureSessionCompleter = completer;
+                    cameraDeviceCompat.createCaptureSession(sessionConfigurationCompat);
+                    return "openCaptureSession[session="
+                            + SynchronizedCaptureSessionBaseImpl.this + "]";
+                }
+            });
 
             Futures.addCallback(mOpenCaptureSessionFuture, new FutureCallback<Void>() {
                 @Override
@@ -169,7 +170,7 @@
 
                 @Override
                 public void onFailure(@NonNull Throwable t) {
-                    SynchronizedCaptureSessionBaseImpl.this.finishClose();
+                    finishClose();
                     mCaptureSessionRepository.onCaptureSessionConfigureFail(
                             SynchronizedCaptureSessionBaseImpl.this);
                 }
@@ -299,34 +300,31 @@
                         new CancellationException("Opener is disabled"));
             }
 
-            mStartingSurface = FutureChain.from(
-                    DeferrableSurfaces.surfaceListWithTimeout(deferrableSurfaces, false, timeout,
-                            getExecutor(), mScheduledExecutorService)).transformAsync(surfaces -> {
-                                Logger.d(TAG,
-                                        "[" + SynchronizedCaptureSessionBaseImpl.this
-                                                + "] getSurface...done");
-                                // If a Surface in configuredSurfaces is null it means the
-                                // Surface was not retrieved from the ListenableFuture. Only
-                                // handle the first failed Surface since subsequent calls to
-                                // CaptureSession.open() will handle the other failed Surfaces if
-                                // there are any.
-                                if (surfaces.contains(null)) {
-                                    DeferrableSurface deferrableSurface = deferrableSurfaces.get(
-                                            surfaces.indexOf(null));
-                                    return Futures.immediateFailedFuture(
-                                            new DeferrableSurface.SurfaceClosedException(
-                                                    "Surface closed", deferrableSurface));
-                                }
+            ListenableFuture<List<Surface>> future = DeferrableSurfaces.surfaceListWithTimeout(
+                    deferrableSurfaces, false, timeout, getExecutor(), mScheduledExecutorService);
 
-                                if (surfaces.isEmpty()) {
-                                    return Futures.immediateFailedFuture(
-                                            new IllegalArgumentException(
-                                                    "Unable to open capture session without "
-                                                            + "surfaces"));
-                                }
-
-                                return Futures.immediateFuture(surfaces);
-                            }, getExecutor());
+            mStartingSurface = FutureChain.from(future).transformAsync(surfaces -> {
+                Logger.d(TAG, "[" + SynchronizedCaptureSessionBaseImpl.this + "] getSurface done "
+                        + "with results: " + surfaces);
+                // If a Surface in configuredSurfaces is null it means the
+                // Surface was not retrieved from the ListenableFuture. Only
+                // handle the first failed Surface since subsequent calls to
+                // CaptureSession.open() will handle the other failed Surfaces if
+                // there are any.
+                if (surfaces.isEmpty()) {
+                    return Futures.immediateFailedFuture(new IllegalArgumentException(
+                            "Unable to open capture session without surfaces")
+                    );
+                }
+                if (surfaces.contains(null)) {
+                    return Futures.immediateFailedFuture(
+                            new DeferrableSurface.SurfaceClosedException(
+                                    "Surface closed", deferrableSurfaces.get(surfaces.indexOf(null))
+                            )
+                    );
+                }
+                return Futures.immediateFuture(surfaces);
+            }, getExecutor());
 
             return Futures.nonCancellationPropagating(mStartingSurface);
         }
@@ -554,8 +552,15 @@
                 // the onClosed callback, we can treat this session is already in closed state.
                 onSessionFinished(session);
 
-                Objects.requireNonNull(mCaptureSessionStateCallback);
-                mCaptureSessionStateCallback.onClosed(session);
+                if (mCameraCaptureSessionCompat != null) {
+                    // Only call onClosed() if we have the instance of CameraCaptureSession.
+                    Objects.requireNonNull(mCaptureSessionStateCallback);
+                    mCaptureSessionStateCallback.onClosed(session);
+                } else {
+                    Logger.w(TAG, "[" + SynchronizedCaptureSessionBaseImpl.this + "] Cannot call "
+                            + "onClosed() when the CameraCaptureSession is not correctly "
+                            + "configured.");
+                }
             }, CameraXExecutors.directExecutor());
         }
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionImpl.java
index 10ab59b..de4b4b8c 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionImpl.java
@@ -31,33 +31,24 @@
 import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
 import androidx.camera.camera2.internal.compat.workaround.ForceCloseCaptureSession;
 import androidx.camera.camera2.internal.compat.workaround.ForceCloseDeferrableSurface;
+import androidx.camera.camera2.internal.compat.workaround.SessionResetPolicy;
 import androidx.camera.camera2.internal.compat.workaround.WaitForRepeatingRequestStart;
 import androidx.camera.core.Logger;
 import androidx.camera.core.impl.DeferrableSurface;
 import androidx.camera.core.impl.Quirks;
+import androidx.camera.core.impl.utils.futures.FutureChain;
 import androidx.camera.core.impl.utils.futures.Futures;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
- * <p>The SynchronizedCaptureSessionImpl synchronizing methods between the other
- * SynchronizedCaptureSessions to fix b/135050586, b/145725334, b/144817309, b/146773463. The
- * SynchronizedCaptureSessionBaseImpl would be a non-synchronizing version.
- *
- * <p>In b/144817309, the onClosed() callback on
- * {@link android.hardware.camera2.CameraCaptureSession.StateCallback}
- * might not be invoked if the capture session is not the latest one. To align the fixed
- * framework behavior, we manually call the onClosed() when a new CameraCaptureSession is created.
- *
- * <p>The b/135050586, b/145725334 need to close the {@link DeferrableSurface} to force the
- * {@link DeferrableSurface} recreate in the new CaptureSession.
- *
- * <p>b/146773463: It needs to check all the releasing capture sessions are ready for opening
- * next capture session.
+ * The SynchronizedCaptureSessionImpl applies a few workarounds for Quirks.
  */
 @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
 class SynchronizedCaptureSessionImpl extends SynchronizedCaptureSessionBaseImpl {
@@ -72,11 +63,13 @@
     private List<DeferrableSurface> mDeferrableSurfaces;
     @Nullable
     @GuardedBy("mObjectLock")
-    ListenableFuture<Void> mOpeningCaptureSession;
+    ListenableFuture<List<Void>> mOpenSessionBlockerFuture;
 
     private final ForceCloseDeferrableSurface mCloseSurfaceQuirk;
     private final WaitForRepeatingRequestStart mWaitForOtherSessionCompleteQuirk;
     private final ForceCloseCaptureSession mForceCloseSessionQuirk;
+    private final SessionResetPolicy mSessionResetPolicy;
+    private final AtomicBoolean mClosed = new AtomicBoolean(false);
 
     SynchronizedCaptureSessionImpl(
             @NonNull Quirks cameraQuirks,
@@ -89,6 +82,7 @@
         mCloseSurfaceQuirk = new ForceCloseDeferrableSurface(cameraQuirks, deviceQuirks);
         mWaitForOtherSessionCompleteQuirk = new WaitForRepeatingRequestStart(cameraQuirks);
         mForceCloseSessionQuirk = new ForceCloseCaptureSession(deviceQuirks);
+        mSessionResetPolicy = new SessionResetPolicy(deviceQuirks);
     }
 
     @NonNull
@@ -97,11 +91,32 @@
             @NonNull SessionConfigurationCompat sessionConfigurationCompat,
             @NonNull List<DeferrableSurface> deferrableSurfaces) {
         synchronized (mObjectLock) {
-            mOpeningCaptureSession = mWaitForOtherSessionCompleteQuirk.openCaptureSession(
-                    cameraDevice, sessionConfigurationCompat, deferrableSurfaces,
-                    mCaptureSessionRepository.getClosingCaptureSession(),
-                    super::openCaptureSession);
-            return Futures.nonCancellationPropagating(mOpeningCaptureSession);
+            // For b/146773463: It needs to check all the releasing capture sessions are ready for
+            // opening next capture session.
+            List<SynchronizedCaptureSession>
+                    closingSessions = mCaptureSessionRepository.getClosingCaptureSession();
+            List<ListenableFuture<Void>> futureList = new ArrayList<>();
+            for (SynchronizedCaptureSession session : closingSessions) {
+                futureList.add(session.getOpeningBlocker());
+            }
+            mOpenSessionBlockerFuture = Futures.successfulAsList(futureList);
+
+            return Futures.nonCancellationPropagating(
+                    FutureChain.from(mOpenSessionBlockerFuture).transformAsync(v -> {
+                        if (mSessionResetPolicy.needAbortCapture()) {
+                            closeCreatedSession();
+                        }
+                        debugLog("start openCaptureSession");
+                        return super.openCaptureSession(cameraDevice, sessionConfigurationCompat,
+                                deferrableSurfaces);
+                    }, getExecutor()));
+        }
+    }
+
+    private void closeCreatedSession() {
+        List<SynchronizedCaptureSession> sessions = mCaptureSessionRepository.getCaptureSessions();
+        for (SynchronizedCaptureSession session : sessions) {
+            session.close();
         }
     }
 
@@ -126,8 +141,10 @@
         synchronized (mObjectLock) {
             if (isCameraCaptureSessionOpen()) {
                 mCloseSurfaceQuirk.onSessionEnd(mDeferrableSurfaces);
-            } else if (mOpeningCaptureSession != null) {
-                mOpeningCaptureSession.cancel(true);
+            } else {
+                if (mOpenSessionBlockerFuture != null) {
+                    mOpenSessionBlockerFuture.cancel(true);
+                }
             }
             return super.stop();
         }
@@ -151,6 +168,20 @@
 
     @Override
     public void close() {
+        if (!mClosed.compareAndSet(false, true)) {
+            debugLog("close() has been called. Skip this invocation.");
+            return;
+        }
+
+        if (mSessionResetPolicy.needAbortCapture()) {
+            try {
+                debugLog("Call abortCaptures() before closing session.");
+                abortCaptures();
+            } catch (Exception e) {
+                debugLog("Exception when calling abortCaptures()" + e);
+            }
+        }
+
         debugLog("Session call close()");
         mWaitForOtherSessionCompleteQuirk.onSessionEnd();
         mWaitForOtherSessionCompleteQuirk.getStartStreamFuture().addListener(() -> {
@@ -169,6 +200,12 @@
         super.onClosed(session);
     }
 
+    @Override
+    public void finishClose() {
+        super.finishClose();
+        mWaitForOtherSessionCompleteQuirk.onFinishClosed();
+    }
+
     void debugLog(String message) {
         Logger.d(TAG, "[" + SynchronizedCaptureSessionImpl.this + "] " + message);
     }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionOpener.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionOpener.java
deleted file mode 100644
index 7e28273..0000000
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionOpener.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.camera2.internal;
-
-import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.params.SessionConfiguration;
-import android.os.Handler;
-import android.view.Surface;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.RequiresApi;
-import androidx.camera.camera2.internal.annotation.CameraExecutor;
-import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
-import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
-import androidx.camera.camera2.internal.compat.workaround.ForceCloseCaptureSession;
-import androidx.camera.camera2.internal.compat.workaround.ForceCloseDeferrableSurface;
-import androidx.camera.camera2.internal.compat.workaround.WaitForRepeatingRequestStart;
-import androidx.camera.core.impl.DeferrableSurface;
-import androidx.camera.core.impl.Quirks;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-import java.util.List;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * The Opener to open the {@link SynchronizedCaptureSession}.
- *
- * <p>The {@link #openCaptureSession} method can be used to open a new
- * {@link SynchronizedCaptureSession}, and the {@link SessionConfigurationCompat} object that
- * needed by the {@link #openCaptureSession} should be created via the
- * {@link #createSessionConfigurationCompat}. It will send the ready-to-use
- * {@link SynchronizedCaptureSession} to the provided listener's
- * {@link SynchronizedCaptureSession.StateCallback#onConfigured} callback.
- *
- * <p>An Opener should only be used to open one SynchronizedCaptureSession. The Opener cannot be
- * reused to open the second SynchronizedCaptureSession. The {@link #openCaptureSession} can't
- * be called more than once in the same Opener.
- *
- * @see #openCaptureSession(CameraDevice, SessionConfigurationCompat, List)
- * @see #createSessionConfigurationCompat(int, List, SynchronizedCaptureSession.StateCallback)
- * @see SynchronizedCaptureSession.StateCallback
- *
- * <p>The {@link #stop} method should be invoked when the SynchronizedCaptureSession opening flow
- * is interropted.
- * @see #startWithDeferrableSurface
- * @see #stop()
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-final class SynchronizedCaptureSessionOpener {
-
-    @NonNull
-    private final OpenerImpl mImpl;
-
-    SynchronizedCaptureSessionOpener(@NonNull OpenerImpl impl) {
-        mImpl = impl;
-    }
-
-    /**
-     * Opens the SynchronizedCaptureSession.
-     *
-     * <p>The behavior of this method similar to the
-     * {@link CameraDevice#createCaptureSession(SessionConfiguration)}. It will use the
-     * input cameraDevice to create the SynchronizedCaptureSession.
-     *
-     * <p>The {@link SessionConfigurationCompat} object that is needed in this method should be
-     * created via the {@link #createSessionConfigurationCompat}.
-     *
-     * <p>The use count of the input DeferrableSurfaces will be increased. It will be
-     * automatically decreased when the surface is not used by the camera. For instance, when the
-     * opened SynchronizedCaptureSession is closed completely or when the configuration of the
-     * session is failed.
-     *
-     * <p>Cancellation of the returned future is a no-op. The opening task can only be
-     * cancelled by the {@link #stop()}. The {@link #stop()} only effective when the
-     * CameraDevice#createCaptureSession() hasn't been invoked. If the {@link #stop()} is called
-     * before the CameraDevice#createCaptureSession(), it will stop the
-     * SynchronizedCaptureSession creation.
-     * Otherwise, the SynchronizedCaptureSession will be created and the
-     * {@link SynchronizedCaptureSession.StateCallback#onConfigured} or
-     * {@link SynchronizedCaptureSession.StateCallback#onConfigureFailed} callback will be invoked.
-     *
-     * @param cameraDevice               the camera with which to generate the
-     *                                   SynchronizedCaptureSession
-     * @param sessionConfigurationCompat A {@link SessionConfigurationCompat} that is created via
-     *                                   the {@link #createSessionConfigurationCompat}.
-     * @param deferrableSurfaces         the list of the DeferrableSurface that be used to
-     *                                   configure the session.
-     * @return a ListenableFuture object which completes when the SynchronizedCaptureSession is
-     * configured.
-     * @see #createSessionConfigurationCompat(int, List, SynchronizedCaptureSession.StateCallback)
-     * @see #stop()
-     */
-    @NonNull
-    ListenableFuture<Void> openCaptureSession(@NonNull CameraDevice cameraDevice,
-            @NonNull SessionConfigurationCompat sessionConfigurationCompat,
-            @NonNull List<DeferrableSurface> deferrableSurfaces) {
-        return mImpl.openCaptureSession(cameraDevice, sessionConfigurationCompat,
-                deferrableSurfaces);
-    }
-
-    /**
-     * Create the SessionConfigurationCompat for {@link #openCaptureSession} used.
-     *
-     * This method will add necessary information into the created SessionConfigurationCompat
-     * instance for SynchronizedCaptureSession.
-     *
-     * @param sessionType   The session type.
-     * @param outputsCompat A list of output configurations for the SynchronizedCaptureSession.
-     * @param stateCallback A state callback interface implementation.
-     */
-    @NonNull
-    SessionConfigurationCompat createSessionConfigurationCompat(int sessionType,
-            @NonNull List<OutputConfigurationCompat> outputsCompat,
-            @NonNull SynchronizedCaptureSession.StateCallback stateCallback) {
-        return mImpl.createSessionConfigurationCompat(sessionType, outputsCompat,
-                stateCallback);
-    }
-
-    /**
-     * Get the surface from the DeferrableSurfaces.
-     *
-     * <p>The {@link #startWithDeferrableSurface} method will return a Surface list that
-     * is held in the List<DeferrableSurface>. The Opener helps in maintaining the timing to
-     * close the returned DeferrableSurface list. Most use case should attempt to use the
-     * {@link #startWithDeferrableSurface} method to get the Surface for creating the
-     * SynchronizedCaptureSession.
-     *
-     * @param deferrableSurfaces The deferrable surfaces to open.
-     * @param timeout            the timeout to get surfaces from the deferrable surface list.
-     * @return the Future which will contain the surface list, Cancellation of this
-     * future is a no-op. The returned Surface list can be used to create the
-     * SynchronizedCaptureSession.
-     * @see #openCaptureSession
-     * @see #stop
-     */
-    @NonNull
-    ListenableFuture<List<Surface>> startWithDeferrableSurface(
-            @NonNull List<DeferrableSurface> deferrableSurfaces, long timeout) {
-        return mImpl.startWithDeferrableSurface(deferrableSurfaces, timeout);
-    }
-
-    /**
-     * Disable the startWithDeferrableSurface() and openCaptureSession() ability, and stop the
-     * startWithDeferrableSurface() and openCaptureSession() if CameraDevice#createCaptureSession()
-     * hasn't been invoked. Once the CameraDevice#createCaptureSession() already been invoked, the
-     * task of openCaptureSession() will keep going.
-     *
-     * @return true if the CameraCaptureSession creation has not been started yet. Otherwise true
-     * false.
-     */
-    boolean stop() {
-        return mImpl.stop();
-    }
-
-    @NonNull
-    @CameraExecutor
-    public Executor getExecutor() {
-        return mImpl.getExecutor();
-    }
-
-    static class Builder {
-        private final Executor mExecutor;
-        private final ScheduledExecutorService mScheduledExecutorService;
-        private final Handler mCompatHandler;
-        private final CaptureSessionRepository mCaptureSessionRepository;
-        private final Quirks mCameraQuirks;
-        private final Quirks mDeviceQuirks;
-        private final boolean mQuirkExist;
-
-        Builder(@NonNull @CameraExecutor Executor executor,
-                @NonNull ScheduledExecutorService scheduledExecutorService,
-                @NonNull Handler compatHandler,
-                @NonNull CaptureSessionRepository captureSessionRepository,
-                @NonNull Quirks cameraQuirks,
-                @NonNull Quirks deviceQuirks) {
-            mExecutor = executor;
-            mScheduledExecutorService = scheduledExecutorService;
-            mCompatHandler = compatHandler;
-            mCaptureSessionRepository = captureSessionRepository;
-            mCameraQuirks = cameraQuirks;
-            mDeviceQuirks = deviceQuirks;
-            mQuirkExist = new ForceCloseDeferrableSurface(mCameraQuirks,
-                    mDeviceQuirks).shouldForceClose() || new WaitForRepeatingRequestStart(
-                    mCameraQuirks).shouldWaitRepeatingSubmit() || new ForceCloseCaptureSession(
-                    mDeviceQuirks).shouldForceClose();
-        }
-
-        @NonNull
-        SynchronizedCaptureSessionOpener build() {
-            return new SynchronizedCaptureSessionOpener(
-                    mQuirkExist ? new SynchronizedCaptureSessionImpl(mCameraQuirks, mDeviceQuirks,
-                            mCaptureSessionRepository, mExecutor, mScheduledExecutorService,
-                            mCompatHandler)
-                            : new SynchronizedCaptureSessionBaseImpl(mCaptureSessionRepository,
-                                    mExecutor, mScheduledExecutorService, mCompatHandler));
-        }
-    }
-
-    interface OpenerImpl {
-
-        @NonNull
-        ListenableFuture<Void> openCaptureSession(@NonNull CameraDevice cameraDevice, @NonNull
-                SessionConfigurationCompat sessionConfigurationCompat,
-                @NonNull List<DeferrableSurface> deferrableSurfaces);
-
-        @NonNull
-        SessionConfigurationCompat createSessionConfigurationCompat(int sessionType,
-                @NonNull List<OutputConfigurationCompat> outputsCompat,
-                @NonNull SynchronizedCaptureSession.StateCallback stateCallback);
-
-        @NonNull
-        @CameraExecutor
-        Executor getExecutor();
-
-        @NonNull
-        ListenableFuture<List<Surface>> startWithDeferrableSurface(
-                @NonNull List<DeferrableSurface> deferrableSurfaces, long timeout);
-
-        boolean stop();
-    }
-}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
index 695c99d..f3fdd6d 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/DeviceQuirksLoader.java
@@ -89,6 +89,9 @@
         if (InvalidVideoProfilesQuirk.load()) {
             quirks.add(new InvalidVideoProfilesQuirk());
         }
+        if (Preview3AThreadCrash.load()) {
+            quirks.add(new Preview3AThreadCrash());
+        }
         if (SmallDisplaySizeQuirk.load()) {
             quirks.add(new SmallDisplaySizeQuirk());
         }
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Preview3AThreadCrash.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Preview3AThreadCrash.java
new file mode 100644
index 0000000..dedf839
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/quirk/Preview3AThreadCrash.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 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.camera.camera2.internal.compat.quirk;
+
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.Quirk;
+
+/**
+ * Camera service crashes after submitting a request by a newly created CameraCaptureSession.
+ *
+ * <p>QuirkSummary
+ *     Bug Id: 290861504
+ *     Description: The camera service may crash once a newly created CameraCaptureSession submit
+ *     a repeating request.
+ *     Device(s): Samsung device with samsungexynos7870 hardware
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class Preview3AThreadCrash implements Quirk {
+
+    static boolean load() {
+        return "samsungexynos7870".equalsIgnoreCase(Build.HARDWARE);
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/SessionResetPolicy.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/SessionResetPolicy.java
new file mode 100644
index 0000000..f04af77
--- /dev/null
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/SessionResetPolicy.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2023 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.camera.camera2.internal.compat.workaround;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.internal.compat.quirk.Preview3AThreadCrash;
+import androidx.camera.core.impl.Quirks;
+
+/**
+ * Indicate the required actions when going to switch CameraCaptureSession.
+ *
+ * @see Preview3AThreadCrash
+ */
+@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
+public class SessionResetPolicy {
+
+    private final boolean mNeedAbortCapture;
+
+    public SessionResetPolicy(@NonNull Quirks deviceQuirks) {
+        mNeedAbortCapture = deviceQuirks.contains(Preview3AThreadCrash.class);
+    }
+
+    /**
+     * @return true if it needs to call abortCapture before the CameraCaptureSession is closed.
+     */
+    public boolean needAbortCapture() {
+        return mNeedAbortCapture;
+    }
+}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/WaitForRepeatingRequestStart.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/WaitForRepeatingRequestStart.java
index 8da55f2..e1a91a1 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/WaitForRepeatingRequestStart.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/workaround/WaitForRepeatingRequestStart.java
@@ -18,27 +18,18 @@
 
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraCaptureSession;
-import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CaptureRequest;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.camera.camera2.internal.Camera2CaptureCallbacks;
-import androidx.camera.camera2.internal.SynchronizedCaptureSession;
-import androidx.camera.camera2.internal.compat.params.SessionConfigurationCompat;
 import androidx.camera.camera2.internal.compat.quirk.CaptureSessionStuckQuirk;
-import androidx.camera.core.impl.DeferrableSurface;
 import androidx.camera.core.impl.Quirks;
-import androidx.camera.core.impl.utils.executor.CameraXExecutors;
-import androidx.camera.core.impl.utils.futures.FutureChain;
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * The workaround is used to wait for the other CameraCaptureSessions to complete their in-flight
  * capture sequences before opening the current session.
@@ -87,27 +78,6 @@
         return Futures.nonCancellationPropagating(mStartStreamingFuture);
     }
 
-    /**
-     * For b/146773463: It needs to check all the releasing capture sessions are ready for
-     * opening next capture session.
-     */
-    @NonNull
-    public ListenableFuture<Void> openCaptureSession(
-            @NonNull CameraDevice cameraDevice,
-            @NonNull SessionConfigurationCompat sessionConfigurationCompat,
-            @NonNull List<DeferrableSurface> deferrableSurfaces,
-            @NonNull List<SynchronizedCaptureSession> closingSessions,
-            @NonNull OpenCaptureSession openCaptureSession) {
-        List<ListenableFuture<Void>> futureList = new ArrayList<>();
-        for (SynchronizedCaptureSession session : closingSessions) {
-            futureList.add(session.getOpeningBlocker());
-        }
-
-        return FutureChain.from(Futures.successfulAsList(futureList)).transformAsync(
-                v -> openCaptureSession.run(cameraDevice, sessionConfigurationCompat,
-                        deferrableSurfaces), CameraXExecutors.directExecutor());
-    }
-
     /** Hook the setSingleRepeatingRequest() to know if it has started a repeating request. */
     public int setSingleRepeatingRequest(
             @NonNull CaptureRequest request,
@@ -134,6 +104,13 @@
         }
     }
 
+    /**
+     * This should be called when SynchronizedCaptureSession#finishClose is called.
+     */
+    public void onFinishClosed() {
+        mStartStreamingFuture.cancel(true);
+    }
+
     private final CameraCaptureSession.CaptureCallback mCaptureCallback =
             new CameraCaptureSession.CaptureCallback() {
                 @Override
@@ -163,14 +140,4 @@
                 @NonNull CameraCaptureSession.CaptureCallback listener)
                 throws CameraAccessException;
     }
-
-    /** Interface to forward call of the openCaptureSession() method. */
-    @FunctionalInterface
-    public interface OpenCaptureSession {
-        /** Run the openCaptureSession() method. */
-        @NonNull
-        ListenableFuture<Void> run(@NonNull CameraDevice cameraDevice,
-                @NonNull SessionConfigurationCompat sessionConfigurationCompat,
-                @NonNull List<DeferrableSurface> deferrableSurfaces);
-    }
 }
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2ImplConfigTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2ImplConfigTest.java
index c3d9873..bff78ef 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2ImplConfigTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/impl/Camera2ImplConfigTest.java
@@ -37,8 +37,6 @@
 public class Camera2ImplConfigTest {
     private static final int INVALID_TEMPLATE_TYPE = -1;
     private static final int INVALID_COLOR_CORRECTION_MODE = -1;
-    private static final CameraEventCallbacks CAMERA_EVENT_CALLBACKS =
-            CameraEventCallbacks.createEmptyCallback();
 
     @Test
     public void emptyConfigurationDoesNotContainTemplateType() {
@@ -50,17 +48,6 @@
     }
 
     @Test
-    public void canExtendWithCameraEventCallback() {
-        FakeConfig.Builder builder = new FakeConfig.Builder();
-
-        new Camera2ImplConfig.Extender<>(builder).setCameraEventCallback(CAMERA_EVENT_CALLBACKS);
-        Camera2ImplConfig config = new Camera2ImplConfig(builder.build());
-
-        assertThat(config.getCameraEventCallback(/*valueIfMissing=*/ null))
-                .isSameInstanceAs(CAMERA_EVENT_CALLBACKS);
-    }
-
-    @Test
     public void canSetAndRetrieveCaptureRequestKeys_byBuilder() {
         Range<Integer> fakeRange = new Range<>(0, 30);
         Camera2ImplConfig.Builder builder =
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpackerTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpackerTest.java
index bc4a710..76be504 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpackerTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2SessionOptionUnpackerTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import android.hardware.camera2.CameraCaptureSession;
 import android.hardware.camera2.CameraCaptureSession.CaptureCallback;
@@ -30,7 +29,6 @@
 
 import androidx.annotation.OptIn;
 import androidx.camera.camera2.impl.Camera2ImplConfig;
-import androidx.camera.camera2.impl.CameraEventCallbacks;
 import androidx.camera.camera2.interop.Camera2Interop;
 import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
 import androidx.camera.core.ImageCapture;
@@ -73,16 +71,10 @@
         CameraDevice.StateCallback deviceCallback = mock(CameraDevice.StateCallback.class);
         CameraCaptureSession.StateCallback sessionStateCallback =
                 mock(CameraCaptureSession.StateCallback.class);
-        CameraEventCallbacks cameraEventCallbacks = mock(CameraEventCallbacks.class);
-        when(cameraEventCallbacks.clone()).thenReturn(cameraEventCallbacks);
-
         new Camera2Interop.Extender<>(imageCaptureBuilder)
                 .setSessionCaptureCallback(captureCallback)
                 .setDeviceStateCallback(deviceCallback)
                 .setSessionStateCallback(sessionStateCallback);
-        new Camera2ImplConfig.Extender<>(imageCaptureBuilder)
-                .setCameraEventCallback(cameraEventCallbacks);
-
         SessionConfig.Builder sessionBuilder = new SessionConfig.Builder();
         mUnpacker.unpack(RESOLUTION_VGA, imageCaptureBuilder.getUseCaseConfig(), sessionBuilder);
         SessionConfig sessionConfig = sessionBuilder.build();
@@ -98,10 +90,6 @@
         assertThat(sessionConfig.getDeviceStateCallbacks()).containsExactly(deviceCallback);
         assertThat(sessionConfig.getSessionStateCallbacks())
                 .containsExactly(sessionStateCallback);
-        assertThat(
-                new Camera2ImplConfig(
-                        sessionConfig.getImplementationOptions()).getCameraEventCallback(
-                        null)).isEqualTo(cameraEventCallbacks);
     }
 
     @Test
diff --git a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionTest.java b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionTest.java
index 03cdf81..d539e15 100644
--- a/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionTest.java
+++ b/camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SynchronizedCaptureSessionTest.java
@@ -36,6 +36,7 @@
 import androidx.camera.core.impl.DeferrableSurface;
 import androidx.camera.core.impl.ImmediateSurface;
 import androidx.camera.core.impl.Quirks;
+import androidx.camera.core.impl.utils.executor.CameraXExecutors;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -61,8 +62,8 @@
     private SynchronizedCaptureSession.StateCallback mMockStateCallback;
     private List<OutputConfigurationCompat> mOutputs;
     private CaptureSessionRepository mCaptureSessionRepository;
-    private SynchronizedCaptureSessionOpener mSynchronizedCaptureSessionOpener;
-    private SynchronizedCaptureSessionOpener.Builder mCaptureSessionOpenerBuilder;
+    private SynchronizedCaptureSession.Opener mSynchronizedCaptureSessionOpener;
+    private SynchronizedCaptureSession.OpenerBuilder mCaptureSessionOpenerBuilder;
     private ScheduledExecutorService mScheduledExecutorService =
             Executors.newSingleThreadScheduledExecutor();
 
@@ -83,8 +84,8 @@
         mFakeDeferrableSurfaces.add(mDeferrableSurface1);
         mFakeDeferrableSurfaces.add(mDeferrableSurface2);
 
-        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSessionOpener.Builder(
-                android.os.AsyncTask.SERIAL_EXECUTOR, mScheduledExecutorService,
+        mCaptureSessionOpenerBuilder = new SynchronizedCaptureSession.OpenerBuilder(
+                CameraXExecutors.directExecutor(), mScheduledExecutorService,
                 mock(Handler.class), mCaptureSessionRepository,
                 new Quirks(Arrays.asList(new PreviewOrientationIncorrectQuirk(),
                         new ConfigureSurfaceToSecondarySessionFailQuirk())),
@@ -122,7 +123,7 @@
         CameraCaptureSession mockCaptureSession1 = mock(CameraCaptureSession.class);
         SynchronizedCaptureSession.StateCallback mockStateCallback1 = mock(
                 SynchronizedCaptureSession.StateCallback.class);
-        SynchronizedCaptureSessionOpener captureSessionUtil1 =
+        SynchronizedCaptureSession.Opener captureSessionUtil1 =
                 mCaptureSessionOpenerBuilder.build();
         SessionConfigurationCompat sessionConfigurationCompat1 =
                 captureSessionUtil1.createSessionConfigurationCompat(
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java b/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java
deleted file mode 100644
index 5037730..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ImageSaverTest.java
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package androidx.camera.core;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeFalse;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-import android.provider.MediaStore;
-import android.util.Base64;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.camera.core.ImageSaver.OnImageSavedCallback;
-import androidx.camera.core.ImageSaver.SaveError;
-import androidx.exifinterface.media.ExifInterface;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.MediumTest;
-import androidx.test.filters.SdkSuppress;
-import androidx.test.rule.GrantPermissionRule;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-import java.util.Objects;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-
-/**
- * Instrument tests for {@link ImageSaver}.
- */
-@MediumTest
-@RunWith(AndroidJUnit4.class)
-@SdkSuppress(minSdkVersion = 21)
-public class ImageSaverTest {
-
-    private static final int WIDTH = 160;
-    private static final int HEIGHT = 120;
-    private static final int CROP_WIDTH = 100;
-    private static final int CROP_HEIGHT = 100;
-    private static final int Y_PIXEL_STRIDE = 1;
-    private static final int Y_ROW_STRIDE = WIDTH;
-    private static final int UV_PIXEL_STRIDE = 1;
-    private static final int UV_ROW_STRIDE = WIDTH / 2;
-    private static final int DEFAULT_JPEG_QUALITY = 100;
-    private static final String JPEG_IMAGE_DATA_BASE_64 =
-            "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB"
-                    + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB"
-                    + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAB4AKADASIA"
-                    + "AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA"
-                    + "AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3"
-                    + "ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm"
-                    + "p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA"
-                    + "AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx"
-                    + "BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK"
-                    + "U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3"
-                    + "uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD/AD/6"
-                    + "KKK/8/8AP/P/AAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii"
-                    + "gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKA"
-                    + "CiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK"
-                    + "KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoo"
-                    + "ooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiii"
-                    + "gAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=";
-    // The image used here has a YUV_420_888 format.
-
-    private static final String TAG = "ImageSaverTest";
-    private static final String INVALID_DATA_PATH = "/invalid_path";
-
-    private static final String TAG_TO_IGNORE = ExifInterface.TAG_COMPRESSION;
-    private static final String TAG_TO_IGNORE_VALUE = "6";
-    private static final String TAG_TO_COPY = ExifInterface.TAG_MAKE;
-    private static final String TAG_TO_COPY_VALUE = "make";
-
-    @Rule
-    public GrantPermissionRule mStoragePermissionRule =
-            GrantPermissionRule.grant(Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                    Manifest.permission.READ_EXTERNAL_STORAGE);
-
-    @Mock
-    private final ImageProxy mMockYuvImage = mock(ImageProxy.class);
-    @Mock
-    private final ImageProxy.PlaneProxy mYPlane = mock(ImageProxy.PlaneProxy.class);
-    @Mock
-    private final ImageProxy.PlaneProxy mUPlane = mock(ImageProxy.PlaneProxy.class);
-    @Mock
-    private final ImageProxy.PlaneProxy mVPlane = mock(ImageProxy.PlaneProxy.class);
-    private final ByteBuffer mYBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT);
-    private final ByteBuffer mUBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT / 4);
-    private final ByteBuffer mVBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT / 4);
-    @Mock
-    private final ImageProxy mMockJpegImage = mock(ImageProxy.class);
-    @Mock
-    private final ImageProxy.PlaneProxy mJpegDataPlane = mock(ImageProxy.PlaneProxy.class);
-    private ByteBuffer mJpegDataBuffer;
-
-    private final Semaphore mSemaphore = new Semaphore(0);
-    private final ImageSaver.OnImageSavedCallback mMockCallback =
-            mock(ImageSaver.OnImageSavedCallback.class);
-    private final ImageSaver.OnImageSavedCallback mSyncCallback =
-            new OnImageSavedCallback() {
-                @Override
-                public void onImageSaved(
-                        @NonNull ImageCapture.OutputFileResults outputFileResults) {
-                    mMockCallback.onImageSaved(outputFileResults);
-                    mSemaphore.release();
-                }
-
-                @Override
-                public void onError(@NonNull SaveError saveError, @NonNull String message,
-                        @Nullable Throwable cause) {
-                    Logger.d(TAG, message, cause);
-                    mMockCallback.onError(saveError, message, cause);
-                    mSemaphore.release();
-                }
-            };
-
-    private ExecutorService mBackgroundExecutor;
-    private ContentResolver mContentResolver;
-
-    @Before
-    public void setup() throws IOException {
-        assumeFalse("Skip for Cuttlefish.", Build.MODEL.contains("Cuttlefish"));
-        createDefaultPictureFolderIfNotExist();
-        mJpegDataBuffer = createJpegBufferWithExif();
-        // The YUV image's behavior.
-        when(mMockYuvImage.getFormat()).thenReturn(ImageFormat.YUV_420_888);
-        when(mMockYuvImage.getWidth()).thenReturn(WIDTH);
-        when(mMockYuvImage.getHeight()).thenReturn(HEIGHT);
-
-        when(mYPlane.getBuffer()).thenReturn(mYBuffer);
-        when(mYPlane.getPixelStride()).thenReturn(Y_PIXEL_STRIDE);
-        when(mYPlane.getRowStride()).thenReturn(Y_ROW_STRIDE);
-
-        when(mUPlane.getBuffer()).thenReturn(mUBuffer);
-        when(mUPlane.getPixelStride()).thenReturn(UV_PIXEL_STRIDE);
-        when(mUPlane.getRowStride()).thenReturn(UV_ROW_STRIDE);
-
-        when(mVPlane.getBuffer()).thenReturn(mVBuffer);
-        when(mVPlane.getPixelStride()).thenReturn(UV_PIXEL_STRIDE);
-        when(mVPlane.getRowStride()).thenReturn(UV_ROW_STRIDE);
-        when(mMockYuvImage.getPlanes())
-                .thenReturn(new ImageProxy.PlaneProxy[]{mYPlane, mUPlane, mVPlane});
-        when(mMockYuvImage.getCropRect()).thenReturn(new Rect(0, 0, CROP_WIDTH, CROP_HEIGHT));
-
-        // The JPEG image's behavior
-        when(mMockJpegImage.getFormat()).thenReturn(ImageFormat.JPEG);
-        when(mMockJpegImage.getWidth()).thenReturn(WIDTH);
-        when(mMockJpegImage.getHeight()).thenReturn(HEIGHT);
-        when(mMockJpegImage.getCropRect()).thenReturn(new Rect(0, 0, CROP_WIDTH, CROP_HEIGHT));
-
-        when(mJpegDataPlane.getBuffer()).thenReturn(mJpegDataBuffer);
-        when(mMockJpegImage.getPlanes()).thenReturn(new ImageProxy.PlaneProxy[]{mJpegDataPlane});
-
-        // Set up a background executor for callbacks
-        mBackgroundExecutor = Executors.newSingleThreadExecutor();
-
-        mContentResolver = ApplicationProvider.getApplicationContext().getContentResolver();
-    }
-
-    @After
-    public void tearDown() {
-        if (mBackgroundExecutor != null) {
-            mBackgroundExecutor.shutdown();
-        }
-    }
-
-    private ByteBuffer createJpegBufferWithExif() throws IOException {
-        // Create a jpeg file with the test data.
-        File tempFile = File.createTempFile("jpeg_with_exif", ".jpg");
-        tempFile.deleteOnExit();
-        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
-            fos.write(Base64.decode(JPEG_IMAGE_DATA_BASE_64, Base64.DEFAULT));
-        }
-
-        // Add exif tag to the jpeg file and save.
-        ExifInterface saveExif = new ExifInterface(tempFile.toString());
-        saveExif.setAttribute(TAG_TO_IGNORE, TAG_TO_IGNORE_VALUE);
-        saveExif.setAttribute(TAG_TO_COPY, TAG_TO_COPY_VALUE);
-        saveExif.saveAttributes();
-
-        // Verify that the tags are saved correctly.
-        ExifInterface verifyExif = new ExifInterface(tempFile.getPath());
-        assertThat(verifyExif.getAttribute(TAG_TO_IGNORE)).isEqualTo(TAG_TO_IGNORE_VALUE);
-        assertThat(verifyExif.getAttribute(TAG_TO_COPY)).isEqualTo(TAG_TO_COPY_VALUE);
-
-        // Read the jpeg file and return it as a ByteBuffer.
-        byte[] buffer = new byte[1024];
-        try (FileInputStream in = new FileInputStream(tempFile);
-             ByteArrayOutputStream out = new ByteArrayOutputStream(1024)) {
-            int read;
-            while (true) {
-                read = in.read(buffer);
-                if (read == -1) break;
-                out.write(buffer, 0, read);
-            }
-            return ByteBuffer.wrap(out.toByteArray());
-        }
-    }
-
-    @SuppressWarnings("deprecation")
-    private void createDefaultPictureFolderIfNotExist() {
-        File pictureFolder = Environment.getExternalStoragePublicDirectory(
-                Environment.DIRECTORY_PICTURES);
-        if (!pictureFolder.exists()) {
-            pictureFolder.mkdir();
-        }
-    }
-
-    private ImageSaver getDefaultImageSaver(ImageProxy image, File file) {
-        return getDefaultImageSaver(image,
-                new ImageCapture.OutputFileOptions.Builder(file).build());
-    }
-
-    private ImageSaver getDefaultImageSaver(@NonNull ImageProxy image) {
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
-        return getDefaultImageSaver(image,
-                new ImageCapture.OutputFileOptions.Builder(mContentResolver,
-                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
-                        contentValues).build());
-    }
-
-    private ImageSaver getDefaultImageSaver(ImageProxy image, OutputStream outputStream) {
-        return getDefaultImageSaver(image,
-                new ImageCapture.OutputFileOptions.Builder(outputStream).build());
-    }
-
-    private ImageSaver getDefaultImageSaver(ImageProxy image,
-            ImageCapture.OutputFileOptions outputFileOptions) {
-        return new ImageSaver(
-                image,
-                outputFileOptions,
-                /*orientation=*/ 0,
-                DEFAULT_JPEG_QUALITY,
-                mBackgroundExecutor,
-                mBackgroundExecutor,
-                mSyncCallback);
-    }
-
-    @Test
-    public void savedImage_exifIsCopiedToCroppedImage() throws IOException, InterruptedException {
-        // Arrange.
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-
-        // Act.
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-        mSemaphore.acquire();
-        verify(mMockCallback).onImageSaved(any());
-
-        // Assert.
-        ExifInterface exifInterface = new ExifInterface(saveLocation.getPath());
-        assertThat(exifInterface.getAttribute(TAG_TO_IGNORE)).isNotEqualTo(TAG_TO_IGNORE_VALUE);
-        assertThat(exifInterface.getAttribute(TAG_TO_COPY)).isEqualTo(TAG_TO_COPY_VALUE);
-    }
-
-    @Test
-    public void canSaveYuvImage_withNonExistingFile() throws InterruptedException {
-        File saveLocation = new File(ApplicationProvider.getApplicationContext().getCacheDir(),
-                "test" + System.currentTimeMillis() + ".jpg");
-        saveLocation.deleteOnExit();
-        // make sure file does not exist
-        if (saveLocation.exists()) {
-            saveLocation.delete();
-        }
-        assertThat(!saveLocation.exists());
-
-        getDefaultImageSaver(mMockYuvImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        verify(mMockCallback).onImageSaved(any());
-    }
-
-    @Test
-    public void canSaveYuvImage_withExistingFile() throws InterruptedException, IOException {
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-        assertThat(saveLocation.exists());
-
-        getDefaultImageSaver(mMockYuvImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        verify(mMockCallback).onImageSaved(any());
-    }
-
-    @Test
-    public void saveToUri() throws InterruptedException, FileNotFoundException {
-        // Act.
-        getDefaultImageSaver(mMockYuvImage).run();
-        mSemaphore.acquire();
-
-        // Assert.
-        // Verify success callback is called.
-        ArgumentCaptor<ImageCapture.OutputFileResults> outputFileResultsArgumentCaptor =
-                ArgumentCaptor.forClass(ImageCapture.OutputFileResults.class);
-        verify(mMockCallback).onImageSaved(outputFileResultsArgumentCaptor.capture());
-
-        // Verify save location Uri is available.
-        Uri saveLocationUri = outputFileResultsArgumentCaptor.getValue().getSavedUri();
-        assertThat(saveLocationUri).isNotNull();
-
-        // Loads image and verify width and height.
-        ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(saveLocationUri, "r");
-        Bitmap bitmap = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
-        assertThat(bitmap.getWidth()).isEqualTo(CROP_WIDTH);
-        assertThat(bitmap.getHeight()).isEqualTo(CROP_HEIGHT);
-
-        // Clean up.
-        mContentResolver.delete(saveLocationUri, null, null);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Test
-    public void saveToUriWithEmptyCollection_onErrorCalled() throws InterruptedException {
-        // Arrange.
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
-        contentValues.put(MediaStore.MediaColumns.DATA, INVALID_DATA_PATH);
-        ImageSaver imageSaver = getDefaultImageSaver(mMockYuvImage,
-                new ImageCapture.OutputFileOptions.Builder(mContentResolver,
-                        Uri.EMPTY,
-                        contentValues).build());
-
-        // Act.
-        imageSaver.run();
-        mSemaphore.acquire();
-
-        // Assert.
-        verify(mMockCallback).onError(eq(SaveError.FILE_IO_FAILED), any(), any());
-    }
-
-    @Test
-    public void saveToOutputStream() throws InterruptedException, IOException {
-        // Arrange.
-        File file = File.createTempFile("test", ".jpg");
-        file.deleteOnExit();
-
-        // Act.
-        try (OutputStream outputStream = new FileOutputStream(file)) {
-            getDefaultImageSaver(mMockYuvImage, outputStream).run();
-            mSemaphore.acquire();
-        }
-
-        // Assert.
-        verify(mMockCallback).onImageSaved(any());
-        // Loads image and verify width and height.
-        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
-        assertThat(bitmap.getWidth()).isEqualTo(CROP_WIDTH);
-        assertThat(bitmap.getHeight()).isEqualTo(CROP_HEIGHT);
-    }
-
-    @Test
-    public void saveToClosedOutputStream_onErrorCalled() throws InterruptedException,
-            IOException {
-        // Arrange.
-        File file = File.createTempFile("test", ".jpg");
-        file.deleteOnExit();
-        OutputStream outputStream = new FileOutputStream(file);
-        outputStream.close();
-
-        // Act.
-        getDefaultImageSaver(mMockYuvImage, outputStream).run();
-        mSemaphore.acquire();
-
-        // Assert.
-        verify(mMockCallback).onError(eq(SaveError.FILE_IO_FAILED), anyString(),
-                any(Throwable.class));
-    }
-
-    @Test
-    public void canSaveJpegImage() throws InterruptedException, IOException {
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        verify(mMockCallback).onImageSaved(any());
-    }
-
-    @Test
-    public void saveToFile_uriIsSet() throws InterruptedException, IOException {
-        // Arrange.
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-
-        // Act.
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        // Assert.
-        ArgumentCaptor<ImageCapture.OutputFileResults> argumentCaptor =
-                ArgumentCaptor.forClass(ImageCapture.OutputFileResults.class);
-        verify(mMockCallback).onImageSaved(argumentCaptor.capture());
-        String savedPath = Objects.requireNonNull(
-                argumentCaptor.getValue().getSavedUri()).getPath();
-        assertThat(savedPath).isEqualTo(saveLocation.getPath());
-    }
-
-    @Test
-    public void errorCallbackWillBeCalledOnInvalidPath() throws InterruptedException {
-        // Invalid filename should cause error
-        File saveLocation = new File("/not/a/real/path.jpg");
-
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        verify(mMockCallback).onError(eq(SaveError.FILE_IO_FAILED), anyString(),
-                any(Throwable.class));
-    }
-
-    @Test
-    public void imageIsClosedOnSuccess() throws InterruptedException, IOException {
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-
-        mSemaphore.acquire();
-
-        verify(mMockJpegImage).close();
-    }
-
-    @Test
-    public void imageIsClosedOnError() throws InterruptedException {
-        // Invalid filename should cause error
-        File saveLocation = new File("/not/a/real/path.jpg");
-
-        getDefaultImageSaver(mMockJpegImage, saveLocation).run();
-        mSemaphore.acquire();
-
-        verify(mMockJpegImage).close();
-    }
-
-    private void imageCanBeCropped(ImageProxy image) throws InterruptedException, IOException {
-        File saveLocation = File.createTempFile("test", ".jpg");
-        saveLocation.deleteOnExit();
-
-        getDefaultImageSaver(image, saveLocation).run();
-        mSemaphore.acquire();
-
-        Bitmap bitmap = BitmapFactory.decodeFile(saveLocation.getPath());
-        assertThat(bitmap.getWidth()).isEqualTo(CROP_WIDTH);
-        assertThat(bitmap.getHeight()).isEqualTo(CROP_HEIGHT);
-    }
-
-    @Test
-    public void jpegImageCanBeCropped() throws InterruptedException, IOException {
-        imageCanBeCropped(mMockJpegImage);
-    }
-
-    @Test
-    public void yuvImageCanBeCropped() throws InterruptedException, IOException {
-        imageCanBeCropped(mMockYuvImage);
-    }
-}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapDeviceTest.kt
similarity index 88%
rename from camera/camera-core/src/test/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapTest.kt
rename to camera/camera-core/src/androidTest/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapDeviceTest.kt
index a3e433ec..8d4030b 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapTest.kt
+++ b/camera/camera-core/src/androidTest/java/androidx/camera/core/imagecapture/JpegBytes2CroppedBitmapDeviceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright 2023 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.
@@ -21,7 +21,6 @@
 import android.graphics.ImageFormat
 import android.graphics.Matrix
 import android.graphics.Rect
-import android.os.Build
 import android.util.Size
 import androidx.camera.core.imagecapture.Utils.CAMERA_CAPTURE_RESULT
 import androidx.camera.core.imagecapture.Utils.HEIGHT
@@ -30,19 +29,19 @@
 import androidx.camera.testing.impl.ExifUtil.createExif
 import androidx.camera.testing.impl.TestImageUtil.createJpegBytes
 import androidx.camera.testing.impl.TestImageUtil.getAverageDiff
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.internal.DoNotInstrument
 
 /**
  * Unit tests for [JpegBytes2CroppedBitmap].
  */
-@RunWith(RobolectricTestRunner::class)
-@DoNotInstrument
-@Config(minSdk = Build.VERSION_CODES.LOLLIPOP)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = 21)
 class JpegBytes2CroppedBitmapTest {
 
     private val operation = JpegBytes2CroppedBitmap()
@@ -69,8 +68,8 @@
         val output = operation.apply(input)
 
         // Assert: only the yellow and blue blocks exist after the cropping.
-        assertThat(getAverageDiff(output.data, Rect(0, 0, 320, 240), YELLOW)).isEqualTo(0)
-        assertThat(getAverageDiff(output.data, Rect(321, 0, WIDTH, 240), BLUE)).isEqualTo(0)
+        assertThat(getAverageDiff(output.data, Rect(0, 0, 320, 240), BLUE)).isEqualTo(0)
+        assertThat(getAverageDiff(output.data, Rect(321, 0, WIDTH, 240), YELLOW)).isEqualTo(0)
         // Assert: the packet info is correct.
         assertThat(output.cropRect).isEqualTo(Rect(0, 0, cropRect.width(), cropRect.height()))
         assertThat(output.exif).isEqualTo(input.exif)
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Camera.java b/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
index 583094a..5616fc8 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Camera.java
@@ -110,13 +110,43 @@
     void setExtendedConfig(@Nullable CameraConfig cameraConfig);
 
     /**
-     * Checks whether the use cases combination is supported by the camera.
+     * Checks whether the use cases combination is supported.
      *
      * @param useCases to be checked whether can be supported.
-     * @return whether the use cases combination is supported by the camera
+     * @return whether the use cases combination is supported by the camera.
      */
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     default boolean isUseCasesCombinationSupported(@NonNull UseCase... useCases) {
+        return isUseCasesCombinationSupported(true, useCases);
+    }
+
+    /**
+     * Checks whether the use cases combination is supported by camera framework.
+     *
+     * <p>This method verify whether the given use cases can be supported solely by the surface
+     * configurations they require. It doesn't consider the optimization done by CameraX such as
+     * {@link androidx.camera.core.streamsharing.StreamSharing}.
+     *
+     * @param useCases to be checked whether can be supported.
+     * @return whether the use cases combination is supported by the camera.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    default boolean isUseCasesCombinationSupportedByFramework(@NonNull UseCase... useCases) {
+        return isUseCasesCombinationSupported(false, useCases);
+    }
+
+    /**
+     * Checks whether the use cases combination is supported.
+     *
+     * @param withStreamSharing {@code true} if
+     * {@link androidx.camera.core.streamsharing.StreamSharing} feature is considered, otherwise
+     * {@code false}.
+     * @param useCases to be checked whether can be supported.
+     * @return whether the use cases combination is supported by the camera.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    default boolean isUseCasesCombinationSupported(boolean withStreamSharing,
+            @NonNull UseCase... useCases) {
         return true;
     }
 }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
deleted file mode 100644
index e1f0dbc..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package androidx.camera.core;
-
-import android.content.ContentValues;
-import android.graphics.ImageFormat;
-import android.net.Uri;
-import android.os.Build;
-import android.provider.MediaStore;
-
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.utils.Exif;
-import androidx.camera.core.internal.compat.workaround.ExifRotationAvailability;
-import androidx.camera.core.internal.utils.ImageUtil;
-import androidx.camera.core.internal.utils.ImageUtil.CodecFailedException;
-import androidx.core.util.Preconditions;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.UUID;
-import java.util.concurrent.Executor;
-import java.util.concurrent.RejectedExecutionException;
-
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-final class ImageSaver implements Runnable {
-    private static final String TAG = "ImageSaver";
-
-    private static final String TEMP_FILE_PREFIX = "CameraX";
-    private static final String TEMP_FILE_SUFFIX = ".tmp";
-    private static final int COPY_BUFFER_SIZE = 1024;
-    private static final int PENDING = 1;
-    private static final int NOT_PENDING = 0;
-
-    // The image that was captured
-    private final ImageProxy mImage;
-    // The orientation of the image
-    private final int mOrientation;
-    // The compression quality level of the output JPEG image
-    private final int mJpegQuality;
-    // The target location to save the image to.
-    @NonNull
-    private final ImageCapture.OutputFileOptions mOutputFileOptions;
-    // The executor to call back on
-    @NonNull
-    private final Executor mUserCallbackExecutor;
-    // The callback to call on completion
-    @NonNull
-    private final OnImageSavedCallback mCallback;
-    // The executor to handle the I/O operations
-    @NonNull
-    private final Executor mSequentialIoExecutor;
-
-    ImageSaver(
-            @NonNull ImageProxy image,
-            @NonNull ImageCapture.OutputFileOptions outputFileOptions,
-            int orientation,
-            @IntRange(from = 1, to = 100) int jpegQuality,
-            @NonNull Executor userCallbackExecutor,
-            @NonNull Executor sequentialIoExecutor,
-            @NonNull OnImageSavedCallback callback) {
-        mImage = image;
-        mOutputFileOptions = outputFileOptions;
-        mOrientation = orientation;
-        mJpegQuality = jpegQuality;
-        mCallback = callback;
-        mUserCallbackExecutor = userCallbackExecutor;
-        mSequentialIoExecutor = sequentialIoExecutor;
-    }
-
-    @Override
-    public void run() {
-        // Save the image to a temp file first. This is necessary because ExifInterface only
-        // supports saving to File.
-        File tempFile = saveImageToTempFile();
-        if (tempFile != null) {
-            // Post copying on a sequential executor. If the user provided saving destination maps
-            // to a specific file on disk, accessing the file from multiple threads is not safe.
-            mSequentialIoExecutor.execute(() -> copyTempFileToDestination(tempFile));
-        }
-    }
-
-    /**
-     * Saves the {@link #mImage} to a temp file.
-     *
-     * <p> It also crops the image and update Exif if necessary. Returns null if saving failed.
-     */
-    @Nullable
-    private File saveImageToTempFile() {
-        File tempFile;
-        try {
-            if (isSaveToFile()) {
-                // For saving to file, write to the target folder and rename for better performance.
-                // The file extensions must be the same as app provided to avoid the directory
-                // access problem.
-                tempFile = new File(mOutputFileOptions.getFile().getParent(),
-                        TEMP_FILE_PREFIX + UUID.randomUUID().toString()
-                                + getFileExtensionWithDot(mOutputFileOptions.getFile()));
-            } else {
-                tempFile = File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
-            }
-        } catch (IOException e) {
-            postError(SaveError.FILE_IO_FAILED, "Failed to create temp file", e);
-            return null;
-        }
-
-        SaveError saveError = null;
-        String errorMessage = null;
-        Throwable throwable = null;
-        try (ImageProxy imageToClose = mImage;
-             FileOutputStream output = new FileOutputStream(tempFile)) {
-            byte[] bytes = imageToJpegByteArray(mImage, mJpegQuality);
-            output.write(bytes);
-
-            // Create new exif based on the original exif.
-            Exif exif = Exif.createFromFile(tempFile);
-            Exif.createFromImageProxy(mImage).copyToCroppedImage(exif);
-
-            // Overwrite the original orientation if the quirk exists.
-            if (!new ExifRotationAvailability().shouldUseExifOrientation(mImage)) {
-                exif.rotate(mOrientation);
-            }
-
-            // Overwrite exif based on metadata.
-            ImageCapture.Metadata metadata = mOutputFileOptions.getMetadata();
-            if (metadata.isReversedHorizontal()) {
-                exif.flipHorizontally();
-            }
-            if (metadata.isReversedVertical()) {
-                exif.flipVertically();
-            }
-            if (metadata.getLocation() != null) {
-                exif.attachLocation(mOutputFileOptions.getMetadata().getLocation());
-            }
-
-            exif.save();
-        } catch (OutOfMemoryError e) {
-            saveError = SaveError.UNKNOWN;
-            errorMessage = "Processing failed due to low memory.";
-            throwable = e;
-        } catch (IOException | IllegalArgumentException e) {
-            saveError = SaveError.FILE_IO_FAILED;
-            errorMessage = "Failed to write temp file";
-            throwable = e;
-        } catch (CodecFailedException e) {
-            switch (e.getFailureType()) {
-                case ENCODE_FAILED:
-                    saveError = SaveError.ENCODE_FAILED;
-                    errorMessage = "Failed to encode mImage";
-                    break;
-                case DECODE_FAILED:
-                    saveError = SaveError.CROP_FAILED;
-                    errorMessage = "Failed to crop mImage";
-                    break;
-                case UNKNOWN:
-                default:
-                    saveError = SaveError.UNKNOWN;
-                    errorMessage = "Failed to transcode mImage";
-                    break;
-            }
-            throwable = e;
-        }
-        if (saveError != null) {
-            postError(saveError, errorMessage, throwable);
-            tempFile.delete();
-            return null;
-        }
-        return tempFile;
-    }
-
-    private static String getFileExtensionWithDot(File file) {
-        String fileName = file.getName();
-        int dotIndex = fileName.lastIndexOf('.');
-        if (dotIndex >= 0) {
-            return fileName.substring(dotIndex);
-        } else {
-            return "";
-        }
-    }
-
-    @NonNull
-    private byte[] imageToJpegByteArray(@NonNull ImageProxy image, @IntRange(from = 1,
-            to = 100) int jpegQuality) throws CodecFailedException {
-        boolean shouldCropImage = ImageUtil.shouldCropImage(image);
-        int imageFormat = image.getFormat();
-
-        if (imageFormat == ImageFormat.JPEG) {
-            if (!shouldCropImage) {
-                // When cropping is unnecessary, the byte array doesn't need to be decoded and
-                // re-encoded again. Therefore, jpegQuality is unnecessary in this case.
-                return ImageUtil.jpegImageToJpegByteArray(image);
-            } else {
-                return ImageUtil.jpegImageToJpegByteArray(image, image.getCropRect(), jpegQuality);
-            }
-        } else if (imageFormat == ImageFormat.YUV_420_888) {
-            return ImageUtil.yuvImageToJpegByteArray(image, shouldCropImage ? image.getCropRect() :
-                    null, jpegQuality, 0 /* rotationDegrees */);
-        } else {
-            Logger.w(TAG, "Unrecognized image format: " + imageFormat);
-        }
-
-        return null;
-    }
-
-    /**
-     * Copy the temp file to user specified destination.
-     *
-     * <p> The temp file will be deleted afterwards.
-     */
-    void copyTempFileToDestination(@NonNull File tempFile) {
-        Preconditions.checkNotNull(tempFile);
-        SaveError saveError = null;
-        String errorMessage = null;
-        Exception exception = null;
-        Uri outputUri = null;
-        try {
-            if (isSaveToMediaStore()) {
-                ContentValues values = mOutputFileOptions.getContentValues() != null
-                        ? new ContentValues(mOutputFileOptions.getContentValues())
-                        : new ContentValues();
-                setContentValuePending(values, PENDING);
-                outputUri = mOutputFileOptions.getContentResolver().insert(
-                        mOutputFileOptions.getSaveCollection(),
-                        values);
-                if (outputUri == null) {
-                    saveError = SaveError.FILE_IO_FAILED;
-                    errorMessage = "Failed to insert URI.";
-                } else {
-                    if (!copyTempFileToUri(tempFile, outputUri)) {
-                        saveError = SaveError.FILE_IO_FAILED;
-                        errorMessage = "Failed to save to URI.";
-                    }
-                    setUriNotPending(outputUri);
-                }
-            } else if (isSaveToOutputStream()) {
-                copyTempFileToOutputStream(tempFile, mOutputFileOptions.getOutputStream());
-            } else if (isSaveToFile()) {
-                File targetFile = mOutputFileOptions.getFile();
-                // Normally File#renameTo will overwrite the targetFile even if it already exists.
-                // Just in case of unexpected behavior on certain platforms or devices, delete the
-                // target file before renaming.
-                if (targetFile.exists()) {
-                    targetFile.delete();
-                }
-                if (!tempFile.renameTo(targetFile)) {
-                    saveError = SaveError.FILE_IO_FAILED;
-                    errorMessage = "Failed to rename file.";
-                }
-                outputUri = Uri.fromFile(targetFile);
-            }
-        } catch (IOException | IllegalArgumentException | SecurityException e) {
-            saveError = SaveError.FILE_IO_FAILED;
-            errorMessage = "Failed to write destination file.";
-            exception = e;
-        } finally {
-            tempFile.delete();
-        }
-        if (saveError != null) {
-            postError(saveError, errorMessage, exception);
-        } else {
-            postSuccess(outputUri);
-        }
-    }
-
-    private boolean isSaveToMediaStore() {
-        return mOutputFileOptions.getSaveCollection() != null
-                && mOutputFileOptions.getContentResolver() != null
-                && mOutputFileOptions.getContentValues() != null;
-    }
-
-    private boolean isSaveToFile() {
-        return mOutputFileOptions.getFile() != null;
-    }
-
-    private boolean isSaveToOutputStream() {
-        return mOutputFileOptions.getOutputStream() != null;
-    }
-
-    /**
-     * Removes IS_PENDING flag during the writing to {@link Uri}.
-     */
-    private void setUriNotPending(@NonNull Uri outputUri) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            ContentValues values = new ContentValues();
-            setContentValuePending(values, NOT_PENDING);
-            mOutputFileOptions.getContentResolver().update(outputUri, values, null, null);
-        }
-    }
-
-    /** Set IS_PENDING flag to {@link ContentValues}. */
-    private void setContentValuePending(@NonNull ContentValues values, int isPending) {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
-            values.put(MediaStore.Images.Media.IS_PENDING, isPending);
-        }
-    }
-
-    /**
-     * Copies temp file to {@link Uri}.
-     *
-     * @return false if the {@link Uri} is not writable.
-     */
-    private boolean copyTempFileToUri(@NonNull File tempFile, @NonNull Uri uri) throws IOException {
-        try (OutputStream outputStream =
-                     mOutputFileOptions.getContentResolver().openOutputStream(uri)) {
-            if (outputStream == null) {
-                // The URI is not writable.
-                return false;
-            }
-            copyTempFileToOutputStream(tempFile, outputStream);
-        }
-        return true;
-    }
-
-    private void copyTempFileToOutputStream(@NonNull File tempFile,
-            @NonNull OutputStream outputStream) throws IOException {
-        try (InputStream in = new FileInputStream(tempFile)) {
-            byte[] buf = new byte[COPY_BUFFER_SIZE];
-            int len;
-            while ((len = in.read(buf)) > 0) {
-                outputStream.write(buf, 0, len);
-            }
-        }
-    }
-
-    private void postSuccess(@Nullable Uri outputUri) {
-        try {
-            mUserCallbackExecutor.execute(
-                    () -> mCallback.onImageSaved(new ImageCapture.OutputFileResults(outputUri)));
-        } catch (RejectedExecutionException e) {
-            Logger.e(TAG,
-                    "Application executor rejected executing OnImageSavedCallback.onImageSaved "
-                            + "callback. Skipping.");
-        }
-    }
-
-    private void postError(SaveError saveError, final String message,
-            @Nullable final Throwable cause) {
-        try {
-            mUserCallbackExecutor.execute(() -> mCallback.onError(saveError, message, cause));
-        } catch (RejectedExecutionException e) {
-            Logger.e(TAG, "Application executor rejected executing OnImageSavedCallback.onError "
-                    + "callback. Skipping.");
-        }
-    }
-
-    /** Type of error that occurred during save */
-    public enum SaveError {
-        /** Failed to write to or close the file */
-        FILE_IO_FAILED,
-        /** Failure when attempting to encode image */
-        ENCODE_FAILED,
-        /** Failure when attempting to crop image */
-        CROP_FAILED,
-        UNKNOWN
-    }
-
-    public interface OnImageSavedCallback {
-
-        void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults);
-
-        void onError(@NonNull SaveError saveError, @NonNull String message,
-                @Nullable Throwable cause);
-    }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
index 3422289..67162d5 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/DeferrableSurfaces.java
@@ -24,6 +24,7 @@
 import androidx.camera.core.impl.utils.futures.FutureCallback;
 import androidx.camera.core.impl.utils.futures.Futures;
 import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.core.util.Preconditions;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -33,8 +34,6 @@
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -51,65 +50,51 @@
      * {@link DeferrableSurface} collection.
      *
      * @param removeNullSurfaces       If true remove all Surfaces that were not retrieved.
-     * @param timeout                  The task timeout value in milliseconds.
+     * @param timeoutMillis            The task timeout value in milliseconds.
      * @param executor                 The executor service to run the task.
      * @param scheduledExecutorService The executor service to schedule the timeout event.
      */
     @NonNull
     public static ListenableFuture<List<Surface>> surfaceListWithTimeout(
             @NonNull Collection<DeferrableSurface> deferrableSurfaces,
-            boolean removeNullSurfaces, long timeout, @NonNull Executor executor,
+            boolean removeNullSurfaces, long timeoutMillis, @NonNull Executor executor,
             @NonNull ScheduledExecutorService scheduledExecutorService) {
-        List<ListenableFuture<Surface>> listenableFutureSurfaces = new ArrayList<>();
-
-        for (DeferrableSurface deferrableSurface : deferrableSurfaces) {
-            listenableFutureSurfaces.add(
-                    Futures.nonCancellationPropagating(deferrableSurface.getSurface()));
+        List<ListenableFuture<Surface>> list = new ArrayList<>();
+        for (DeferrableSurface surface : deferrableSurfaces) {
+            list.add(Futures.nonCancellationPropagating(surface.getSurface()));
         }
+        ListenableFuture<List<Surface>> listenableFuture = Futures.makeTimeoutFuture(
+                timeoutMillis, scheduledExecutorService, Futures.successfulAsList(list)
+        );
 
-        return CallbackToFutureAdapter.getFuture(
-                completer -> {
-                    ListenableFuture<List<Surface>> listenableFuture = Futures.successfulAsList(
-                            listenableFutureSurfaces);
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            // Cancel the listenableFuture if the outer task was cancelled, and the
+            // listenableFuture will cancel the scheduledFuture on its complete callback.
+            completer.addCancellationListener(() -> listenableFuture.cancel(true), executor);
 
-                    ScheduledFuture<?> scheduledFuture = scheduledExecutorService.schedule(() -> {
-                        executor.execute(() -> {
-                            if (!listenableFuture.isDone()) {
-                                completer.setException(
-                                        new TimeoutException(
-                                                "Cannot complete surfaceList within " + timeout));
-                                listenableFuture.cancel(true);
-                            }
-                        });
-                    }, timeout, TimeUnit.MILLISECONDS);
+            Futures.addCallback(listenableFuture, new FutureCallback<List<Surface>>() {
+                @Override
+                public void onSuccess(@Nullable List<Surface> result) {
+                    Preconditions.checkNotNull(result);
+                    List<Surface> surfaces = new ArrayList<>(result);
+                    if (removeNullSurfaces) {
+                        surfaces.removeAll(Collections.singleton(null));
+                    }
+                    completer.set(surfaces);
+                }
 
-                    // Cancel the listenableFuture if the outer task was cancelled, and the
-                    // listenableFuture will cancel the scheduledFuture on its complete callback.
-                    completer.addCancellationListener(() -> listenableFuture.cancel(true),
-                            executor);
+                @Override
+                public void onFailure(@NonNull Throwable t) {
+                    if (t instanceof TimeoutException) {
+                        completer.setException(t);
+                    } else {
+                        completer.set(Collections.emptyList());
+                    }
+                }
+            }, executor);
 
-                    Futures.addCallback(listenableFuture,
-                            new FutureCallback<List<Surface>>() {
-                                @Override
-                                public void onSuccess(@Nullable List<Surface> result) {
-                                    List<Surface> surfaces = new ArrayList<>(result);
-                                    if (removeNullSurfaces) {
-                                        surfaces.removeAll(Collections.singleton(null));
-                                    }
-                                    completer.set(surfaces);
-                                    scheduledFuture.cancel(true);
-                                }
-
-                                @Override
-                                public void onFailure(@NonNull Throwable t) {
-                                    completer.set(
-                                            Collections.unmodifiableList(Collections.emptyList()));
-                                    scheduledFuture.cancel(true);
-                                }
-                            }, executor);
-
-                    return "surfaceList";
-                });
+            return "surfaceList[" + deferrableSurfaces + "]";
+        });
     }
 
     /**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/futures/Futures.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/futures/Futures.java
index c26b0b1..dde1276 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/futures/Futures.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/utils/futures/Futures.java
@@ -35,7 +35,10 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Utility class for generating specific implementations of {@link ListenableFuture}.
@@ -411,6 +414,30 @@
     }
 
     /**
+     * Returns a future that delegates to the supplied future but will finish early
+     * (via a TimeoutException) if the specified duration expires.
+     *
+     * @param timeoutMillis     When to time out the future in milliseconds.
+     * @param scheduledExecutor The executor service to enforce the timeout.
+     * @param input             The future to delegate to.
+     */
+    @NonNull
+    public static <V> ListenableFuture<V> makeTimeoutFuture(
+            long timeoutMillis,
+            @NonNull ScheduledExecutorService scheduledExecutor,
+            @NonNull ListenableFuture<V> input) {
+        return CallbackToFutureAdapter.getFuture(completer -> {
+            propagate(input, completer);
+            ScheduledFuture<?> timeoutFuture = scheduledExecutor.schedule(
+                    () -> completer.setException(new TimeoutException("Future[" + input + "] is "
+                            + "not done within " + timeoutMillis + " ms.")),
+                    timeoutMillis, TimeUnit.MILLISECONDS);
+            input.addListener(() -> timeoutFuture.cancel(true), CameraXExecutors.directExecutor());
+            return "TimeoutFuture[" + input + "]";
+        });
+    }
+
+    /**
      * Should not be instantiated.
      */
     private Futures() {}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
index 7d284bd..22f51ec 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/internal/CameraUseCaseAdapter.java
@@ -945,16 +945,22 @@
     }
 
     @Override
-    public boolean isUseCasesCombinationSupported(@NonNull UseCase... useCases) {
+    public boolean isUseCasesCombinationSupported(boolean withStreamSharing,
+            @NonNull UseCase... useCases) {
+        Collection<UseCase> useCasesToVerify = Arrays.asList(useCases);
+        if (withStreamSharing) {
+            StreamSharing streamSharing = createOrReuseStreamSharing(useCasesToVerify, true);
+            useCasesToVerify = calculateCameraUseCases(useCasesToVerify, null, streamSharing);
+        }
         synchronized (mLock) {
             // If the UseCases exceed the resolutions then it will throw an exception
             try {
-                Map<UseCase, ConfigPair> configs = getConfigs(Arrays.asList(useCases),
+                Map<UseCase, ConfigPair> configs = getConfigs(useCasesToVerify,
                         mCameraConfig.getUseCaseConfigFactory(), mUseCaseConfigFactory);
                 calculateSuggestedStreamSpecs(
                         getCameraMode(),
                         mCameraInternal.getCameraInfoInternal(),
-                        Arrays.asList(useCases), emptyList(), configs);
+                        useCasesToVerify, emptyList(), configs);
             } catch (IllegalArgumentException e) {
                 return false;
             }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
index e52b102..9d40fa6 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/processing/SurfaceEdge.java
@@ -646,9 +646,11 @@
                     + "provider, call SurfaceEdge#invalidate before calling "
                     + "SurfaceEdge#setProvider");
             checkArgument(getPrescribedSize().equals(provider.getPrescribedSize()),
-                    "The provider's size must match the parent");
+                    String.format("The provider's size(%s) must match the parent(%s)",
+                            getPrescribedSize(), provider.getPrescribedSize()));
             checkArgument(getPrescribedStreamFormat() == provider.getPrescribedStreamFormat(),
-                    "The provider's format must match the parent");
+                    String.format("The provider's format(%s) must match the parent(%s)",
+                            getPrescribedStreamFormat(), provider.getPrescribedStreamFormat()));
             checkState(!isClosed(), "The parent is closed. Call SurfaceEdge#invalidate() before "
                     + "setting a new provider.");
             mProvider = provider;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/DynamicRangeUtils.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/DynamicRangeUtils.java
new file mode 100644
index 0000000..98f25c4
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/DynamicRangeUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2023 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.camera.core.streamsharing;
+
+import static androidx.camera.core.DynamicRange.BIT_DEPTH_UNSPECIFIED;
+import static androidx.camera.core.DynamicRange.ENCODING_HDR_UNSPECIFIED;
+import static androidx.camera.core.DynamicRange.ENCODING_SDR;
+import static androidx.camera.core.DynamicRange.ENCODING_UNSPECIFIED;
+
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.DynamicRange;
+import androidx.camera.core.impl.UseCaseConfig;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Utility methods for handling dynamic range.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+public class DynamicRangeUtils {
+
+    private DynamicRangeUtils() {
+    }
+
+    /**
+     * Resolves dynamic ranges from use case configs.
+     *
+     * <p>If there is no dynamic range that satisfies all requirements, a null will be returned.
+     */
+    @Nullable
+    public static DynamicRange resolveDynamicRange(@NonNull Set<UseCaseConfig<?>> useCaseConfigs) {
+        List<DynamicRange> dynamicRanges = new ArrayList<>();
+        for (UseCaseConfig<?> useCaseConfig : useCaseConfigs) {
+            dynamicRanges.add(useCaseConfig.getDynamicRange());
+        }
+
+        return intersectDynamicRange(dynamicRanges);
+    }
+
+    /**
+     * Finds the intersection of the input dynamic ranges.
+     *
+     * <p>Returns the intersection if found, or null if no intersection.
+     */
+    @Nullable
+    private static DynamicRange intersectDynamicRange(@NonNull List<DynamicRange> dynamicRanges) {
+        if (dynamicRanges.isEmpty()) {
+            return null;
+        }
+
+        DynamicRange firstDynamicRange = dynamicRanges.get(0);
+        Integer resultEncoding = firstDynamicRange.getEncoding();
+        Integer resultBitDepth = firstDynamicRange.getBitDepth();
+        for (int i = 1; i < dynamicRanges.size(); i++) {
+            DynamicRange childDynamicRange = dynamicRanges.get(i);
+            resultEncoding = intersectDynamicRangeEncoding(resultEncoding,
+                    childDynamicRange.getEncoding());
+            resultBitDepth = intersectDynamicRangeBitDepth(resultBitDepth,
+                    childDynamicRange.getBitDepth());
+
+            if (resultEncoding == null || resultBitDepth == null) {
+                return null;
+            }
+        }
+
+        return new DynamicRange(resultEncoding, resultBitDepth);
+    }
+
+    @Nullable
+    private static Integer intersectDynamicRangeEncoding(@NonNull Integer encoding1,
+            @NonNull Integer encoding2) {
+        // Handle unspecified.
+        if (encoding1.equals(ENCODING_UNSPECIFIED)) {
+            return encoding2;
+        }
+        if (encoding2.equals(ENCODING_UNSPECIFIED)) {
+            return encoding1;
+        }
+
+        // Handle HDR unspecified.
+        if (encoding1.equals(ENCODING_HDR_UNSPECIFIED) && !encoding2.equals(ENCODING_SDR)) {
+            return encoding2;
+        }
+        if (encoding2.equals(ENCODING_HDR_UNSPECIFIED) && !encoding1.equals(ENCODING_SDR)) {
+            return encoding1;
+        }
+
+        return encoding1.equals(encoding2) ? encoding1 : null;
+    }
+
+    @Nullable
+    private static Integer intersectDynamicRangeBitDepth(@NonNull Integer bitDepth1,
+            @NonNull Integer bitDepth2) {
+        // Handle unspecified.
+        if (bitDepth1.equals(BIT_DEPTH_UNSPECIFIED)) {
+            return bitDepth2;
+        }
+        if (bitDepth2.equals(BIT_DEPTH_UNSPECIFIED)) {
+            return bitDepth1;
+        }
+
+        return bitDepth1.equals(bitDepth2) ? bitDepth1 : null;
+    }
+}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
index da98cf3..33a2a1e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCamera.java
@@ -19,11 +19,13 @@
 import static androidx.camera.core.CameraEffect.PREVIEW;
 import static androidx.camera.core.CameraEffect.VIDEO_CAPTURE;
 import static androidx.camera.core.impl.ImageFormatConstants.INTERNAL_DEFINED_IMAGE_FORMAT_PRIVATE;
+import static androidx.camera.core.impl.ImageInputConfig.OPTION_INPUT_DYNAMIC_RANGE;
 import static androidx.camera.core.impl.ImageOutputConfig.OPTION_CUSTOM_ORDERED_RESOLUTIONS;
 import static androidx.camera.core.impl.UseCaseConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
 import static androidx.camera.core.impl.utils.Threads.checkMainThread;
 import static androidx.camera.core.impl.utils.TransformUtils.getRotatedSize;
 import static androidx.camera.core.impl.utils.TransformUtils.rectToSize;
+import static androidx.camera.core.streamsharing.DynamicRangeUtils.resolveDynamicRange;
 import static androidx.camera.core.streamsharing.ResolutionUtils.getMergedResolutions;
 import static androidx.core.util.Preconditions.checkState;
 
@@ -40,6 +42,7 @@
 import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 import androidx.camera.core.CameraEffect;
+import androidx.camera.core.DynamicRange;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.Preview;
 import androidx.camera.core.UseCase;
@@ -96,6 +99,8 @@
     private final CameraCaptureCallback mParentMetadataCallback = createCameraCaptureCallback();
     @NonNull
     private final VirtualCameraControl mVirtualCameraControl;
+    @NonNull
+    private final VirtualCameraInfo mVirtualCameraInfo;
 
     /**
      * @param parentCamera         the parent {@link CameraInternal} instance. For example, the
@@ -112,6 +117,7 @@
         mChildren = children;
         mVirtualCameraControl = new VirtualCameraControl(parentCamera.getCameraControlInternal(),
                 streamSharingControl);
+        mVirtualCameraInfo = new VirtualCameraInfo(parentCamera.getCameraInfoInternal());
         // Set children state to inactive by default.
         for (UseCase child : children) {
             mChildrenActiveState.put(child, false);
@@ -139,6 +145,19 @@
         // Merge Surface occupancy priority.
         mutableConfig.insertOption(OPTION_SURFACE_OCCUPANCY_PRIORITY,
                 getHighestSurfacePriority(childrenConfigs));
+
+        // Merge dynamic range configs. Try to find a dynamic range that can match all child
+        // requirements, or throw an exception if no matching dynamic range.
+        //  TODO: This approach works for the current code base, where only VideoCapture can be
+        //   configured (Preview follows the settings, ImageCapture is fixed as SDR). When
+        //   dynamic range APIs opened on other use cases, we might want a more advanced approach
+        //   that allows conflicts, e.g. converting HDR stream to SDR stream.
+        DynamicRange dynamicRange = resolveDynamicRange(childrenConfigs);
+        if (dynamicRange == null) {
+            throw new IllegalArgumentException("Failed to merge child dynamic ranges, can not find"
+                    + " a dynamic range that satisfies all children.");
+        }
+        mutableConfig.insertOption(OPTION_INPUT_DYNAMIC_RANGE, dynamicRange);
     }
 
     void bindChildren() {
@@ -306,9 +325,7 @@
     @NonNull
     @Override
     public CameraInfoInternal getCameraInfoInternal() {
-        // TODO(b/265818567): replace this with a virtual camera info that returns a updated sensor
-        //  rotation degrees based on buffer transformation applied in StreamSharing.
-        return mParentCamera.getCameraInfoInternal();
+        return mVirtualCameraInfo;
     }
 
     @NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraInfo.java b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraInfo.java
new file mode 100644
index 0000000..cdd2e3e
--- /dev/null
+++ b/camera/camera-core/src/main/java/androidx/camera/core/streamsharing/VirtualCameraInfo.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2023 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.camera.core.streamsharing;
+
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.camera.core.impl.CameraInfoInternal;
+import androidx.camera.core.impl.ForwardingCameraInfo;
+
+import java.util.UUID;
+
+/**
+ * A {@link CameraInfoInternal} that returns info of the virtual camera.
+ */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+public class VirtualCameraInfo extends ForwardingCameraInfo {
+
+    private final String mVirtualCameraId;
+
+    VirtualCameraInfo(@NonNull CameraInfoInternal cameraInfoInternal) {
+        super(cameraInfoInternal);
+        // Generate a unique ID for the virtual camera.
+        mVirtualCameraId =
+                "virtual-" + cameraInfoInternal.getCameraId() + "-" + UUID.randomUUID().toString();
+    }
+
+    /**
+     * Override the parent camera ID.
+     */
+    @NonNull
+    @Override
+    public String getCameraId() {
+        return mVirtualCameraId;
+    }
+}
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
index e023a9f..c59ee46 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/internal/CameraUseCaseAdapterTest.kt
@@ -224,6 +224,66 @@
         )
     }
 
+    @Test
+    fun isUseCasesCombinationSupported_returnTrueWhenSupported() {
+        // Assert
+        assertThat(adapter.isUseCasesCombinationSupported(preview, image)).isTrue()
+    }
+
+    @Test
+    fun isUseCasesCombinationSupported_returnFalseWhenNotSupported() {
+        // Arrange
+        val preview2 = Preview.Builder().build()
+        // Assert: double preview use cases should not be supported even with stream sharing.
+        assertThat(
+            adapter.isUseCasesCombinationSupported(
+                preview,
+                preview2,
+                video,
+                image
+            )
+        ).isFalse()
+    }
+
+    @Test
+    fun isUseCasesCombinationSupportedByFramework_returnTrueWhenSupported() {
+        // Assert
+        assertThat(adapter.isUseCasesCombinationSupportedByFramework(preview, image)).isTrue()
+    }
+
+    @Test
+    fun isUseCasesCombinationSupportedByFramework_returnFalseWhenNotSupported() {
+        // Assert
+        assertThat(
+            adapter.isUseCasesCombinationSupportedByFramework(
+                preview,
+                video,
+                image
+            )
+        ).isFalse()
+    }
+
+    @Test
+    fun isUseCasesCombinationSupported_withStreamSharing() {
+        // preview, video, image should not be supported if stream sharing is not enabled.
+        assertThat(
+            adapter.isUseCasesCombinationSupported( /*withStreamSharing=*/ false,
+                preview,
+                video,
+                image
+            )
+        ).isFalse()
+
+        // preview, video, image should be supported if stream sharing is enabled.
+        assertThat(
+            adapter.isUseCasesCombinationSupported( /*withStreamSharing=*/ true,
+                preview,
+                video,
+                image
+            )
+        ).isTrue()
+    }
+
     @Test(expected = CameraException::class)
     fun invalidUseCaseComboCantBeFixedByStreamSharing_throwsException() {
         // Arrange: create a camera that only support one JPEG stream.
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
index de16acd..3b5c6ea 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/StreamSharingTest.kt
@@ -27,6 +27,7 @@
 import androidx.camera.core.CameraEffect.PREVIEW
 import androidx.camera.core.CameraEffect.VIDEO_CAPTURE
 import androidx.camera.core.CameraSelector.LENS_FACING_FRONT
+import androidx.camera.core.DynamicRange
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY
 import androidx.camera.core.ImageProxy
@@ -154,6 +155,41 @@
     }
 
     @Test
+    fun getParentDynamicRange_isIntersectionOfChildrenDynamicRanges() {
+        val unspecifiedChild = FakeUseCase(
+            FakeUseCaseConfig.Builder().setSurfaceOccupancyPriority(1)
+                .setDynamicRange(DynamicRange.UNSPECIFIED).useCaseConfig
+        )
+        val hdrChild = FakeUseCase(
+            FakeUseCaseConfig.Builder().setSurfaceOccupancyPriority(2)
+                .setDynamicRange(DynamicRange.HLG_10_BIT).useCaseConfig
+        )
+        streamSharing =
+            StreamSharing(camera, setOf(unspecifiedChild, hdrChild), useCaseConfigFactory)
+        assertThat(
+            streamSharing.mergeConfigs(
+                camera.cameraInfoInternal, /*extendedConfig*/null, /*cameraDefaultConfig*/null
+            ).dynamicRange
+        ).isEqualTo(DynamicRange.HLG_10_BIT)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun getParentDynamicRange_exception_whenChildrenDynamicRangesConflict() {
+        val sdrChild = FakeUseCase(
+            FakeUseCaseConfig.Builder().setSurfaceOccupancyPriority(1)
+                .setDynamicRange(DynamicRange.SDR).useCaseConfig
+        )
+        val hdrChild = FakeUseCase(
+            FakeUseCaseConfig.Builder().setSurfaceOccupancyPriority(2)
+                .setDynamicRange(DynamicRange.HLG_10_BIT).useCaseConfig
+        )
+        streamSharing = StreamSharing(camera, setOf(sdrChild, hdrChild), useCaseConfigFactory)
+        streamSharing.mergeConfigs(
+            camera.cameraInfoInternal, /*extendedConfig*/null, /*cameraDefaultConfig*/null
+        )
+    }
+
+    @Test
     fun verifySupportedEffects() {
         assertThat(streamSharing.isEffectTargetsSupported(PREVIEW or VIDEO_CAPTURE)).isTrue()
         assertThat(
diff --git a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraTest.kt b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraTest.kt
index 8fe319e..4681fbb 100644
--- a/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraTest.kt
+++ b/camera/camera-core/src/test/java/androidx/camera/core/streamsharing/VirtualCameraTest.kt
@@ -116,6 +116,12 @@
     }
 
     @Test
+    fun getCameraId_returnsVirtualCameraId() {
+        assertThat(virtualCamera.cameraInfoInternal.cameraId)
+            .startsWith("virtual-" + parentCamera.cameraInfoInternal.cameraId)
+    }
+
+    @Test
     fun submitStillCaptureRequests_triggersSnapshot() {
         // Arrange.
         virtualCamera.bindChildren()
@@ -249,7 +255,8 @@
     @Test
     fun virtualCameraInheritsParentProperties() {
         assertThat(virtualCamera.cameraState).isEqualTo(parentCamera.cameraState)
-        assertThat(virtualCamera.cameraInfo).isEqualTo(parentCamera.cameraInfo)
+        assertThat(virtualCamera.cameraInfoInternal.implementation)
+            .isEqualTo(virtualCamera.cameraInfoInternal.implementation)
     }
 
     @Test
diff --git a/camera/camera-effects/build.gradle b/camera/camera-effects/build.gradle
index d1c307f..ae6d569 100644
--- a/camera/camera-effects/build.gradle
+++ b/camera/camera-effects/build.gradle
@@ -23,10 +23,23 @@
 }
 dependencies {
     api(project(":camera:camera-core"))
-
     implementation(libs.autoValueAnnotations)
 
     annotationProcessor(libs.autoValue)
+
+    androidTestImplementation(libs.multidex)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(project(":camera:camera-testing")) {
+        // Ensure camera-testing does not pull in androidx.test dependencies
+        exclude(group:"androidx.test")
+    }
+    androidTestImplementation(libs.kotlinStdlib)
+    androidTestImplementation(libs.kotlinCoroutinesAndroid)
+    androidTestImplementation("androidx.concurrent:concurrent-futures-ktx:1.1.0")
 }
 android {
     defaultConfig {
diff --git a/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlContextDeviceTest.kt b/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlContextDeviceTest.kt
new file mode 100644
index 0000000..2ea329a
--- /dev/null
+++ b/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlContextDeviceTest.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 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.camera.effects.opengl
+
+import android.graphics.SurfaceTexture
+import android.view.Surface
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumentation tests for [GlContext].
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = 21)
+class GlContextDeviceTest {
+
+    companion object {
+        private const val TIMESTAMP_NS = 0L
+    }
+
+    private val glContext = GlContext()
+
+    private lateinit var surface: Surface
+    private lateinit var surfaceTexture: SurfaceTexture
+
+    @Before
+    fun setUp() {
+        surfaceTexture = SurfaceTexture(0)
+        surface = Surface(surfaceTexture)
+        glContext.init()
+    }
+
+    @After
+    fun tearDown() {
+        glContext.release()
+        surfaceTexture.release()
+        surface.release()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun drawUnregisteredSurface_throwsException() {
+        glContext.drawAndSwap(surface, TIMESTAMP_NS)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun unregisterSurfaceAndDraw_throwsException() {
+        glContext.registerSurface(surface)
+        glContext.unregisterSurface(surface)
+        glContext.drawAndSwap(surface, TIMESTAMP_NS)
+    }
+
+    @Test
+    fun drawRegisteredSurface_noException() {
+        glContext.registerSurface(surface)
+        glContext.drawAndSwap(surface, TIMESTAMP_NS)
+    }
+
+    @Test
+    fun registerSurfaceWithoutDrawingOrReleasing_noException() {
+        glContext.registerSurface(surface)
+    }
+}
diff --git a/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlRendererDeviceTest.kt b/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlRendererDeviceTest.kt
new file mode 100644
index 0000000..73a5942
--- /dev/null
+++ b/camera/camera-effects/src/androidTest/java/androidx/camera/effects/opengl/GlRendererDeviceTest.kt
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2023 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.camera.effects.opengl
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.PorterDuff
+import android.graphics.Rect
+import android.graphics.SurfaceTexture
+import android.opengl.Matrix
+import android.os.Handler
+import android.os.Looper
+import android.util.Size
+import android.view.Surface
+import androidx.camera.testing.impl.TestImageUtil.createBitmap
+import androidx.camera.testing.impl.TestImageUtil.getAverageDiff
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Executors
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.asCoroutineDispatcher
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.withTimeoutOrNull
+import org.junit.After
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Instrumentation tests for [GlRenderer].
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = 21)
+class GlRendererDeviceTest {
+
+    companion object {
+        private const val WIDTH = 640
+        private const val HEIGHT = 480
+        private const val TIMESTAMP_NS = 0L
+    }
+
+    private val input = createBitmap(WIDTH, HEIGHT)
+    private val overlay = createOverlayBitmap()
+    private val transparentOverlay = createTransparentOverlay()
+
+    private val glRenderer = GlRenderer()
+    private lateinit var inputSurface: Surface
+    private lateinit var inputTexture: SurfaceTexture
+    private lateinit var inputExecutor: ExecutorService
+
+    private lateinit var outputSurface: Surface
+    private lateinit var outputTexture: SurfaceTexture
+
+    private val identityMatrix = FloatArray(16).apply {
+        Matrix.setIdentityM(this, 0)
+    }
+
+    @Before
+    fun setUp() = runBlocking {
+        inputExecutor = Executors.newSingleThreadExecutor()
+        withContext(inputExecutor.asCoroutineDispatcher()) {
+            glRenderer.init()
+            inputTexture = SurfaceTexture(glRenderer.inputTextureId).apply {
+                setDefaultBufferSize(WIDTH, HEIGHT)
+            }
+            inputSurface = Surface(inputTexture)
+        }
+        outputTexture = SurfaceTexture(0).apply {
+            setDefaultBufferSize(WIDTH, HEIGHT)
+        }
+        outputSurface = Surface(outputTexture)
+    }
+
+    @After
+    fun tearDown() {
+        inputExecutor.execute {
+            glRenderer.release()
+            inputTexture.release()
+            inputSurface.release()
+        }
+        outputTexture.release()
+        outputSurface.release()
+        inputExecutor.shutdown()
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun renderInputWhenUninitialized_throwsException() {
+        val glRenderer = GlRenderer()
+        try {
+            glRenderer.renderInputToSurface(TIMESTAMP_NS, identityMatrix, outputSurface)
+        } finally {
+            glRenderer.release()
+        }
+    }
+
+    @Test
+    fun drawInputToQueue_snapshot() = runBlocking(inputExecutor.asCoroutineDispatcher()) {
+        // Arrange: upload a overlay and create a texture queue.
+        glRenderer.uploadOverlay(overlay)
+        drawInputSurface(input)
+        val queue = glRenderer.createBufferTextureIds(1, Size(WIDTH, HEIGHT))
+        // Act: draw input to the queue and then to the output.
+        glRenderer.renderInputToQueueTexture(queue[0])
+        val bitmap =
+            glRenderer.renderQueueTextureToBitmap(queue[0], WIDTH, HEIGHT, identityMatrix)
+        // Assert: the output is the input with overlay.
+        assertOverlayColor(bitmap)
+    }
+
+    @Test
+    fun drawInputWithoutOverlay_snapshot() = runBlocking(inputExecutor.asCoroutineDispatcher()) {
+        // Arrange: upload a transparent overlay.
+        glRenderer.uploadOverlay(transparentOverlay)
+        drawInputSurface(input)
+        // Act.
+        val output = glRenderer.renderInputToBitmap(WIDTH, HEIGHT, identityMatrix)
+        // Assert: the output is the same as the input.
+        assertThat(getAverageDiff(output, input)).isEqualTo(0)
+    }
+
+    /**
+     * Tests that the input is rendered to the output surface with the overlay.
+     */
+    private fun assertOverlayColor(bitmap: Bitmap) {
+        // Top left quadrant is white.
+        assertThat(
+            getAverageDiff(
+                bitmap,
+                Rect(0, 0, WIDTH / 2, HEIGHT / 2),
+                Color.WHITE
+            )
+        ).isEqualTo(0)
+        assertThat(
+            getAverageDiff(
+                bitmap,
+                Rect(WIDTH / 2, 0, WIDTH, HEIGHT / 2),
+                Color.GREEN
+            )
+        ).isEqualTo(0)
+        assertThat(
+            getAverageDiff(
+                bitmap,
+                Rect(WIDTH / 2, HEIGHT / 2, WIDTH, HEIGHT),
+                Color.YELLOW
+            )
+        ).isEqualTo(0)
+        assertThat(
+            getAverageDiff(
+                bitmap,
+                Rect(0, HEIGHT / 2, WIDTH / 2, HEIGHT),
+                Color.BLUE
+            )
+        ).isEqualTo(0)
+    }
+
+    /**
+     * Draws the bitmap to the input surface and waits for the frame to be available.
+     */
+    private suspend fun drawInputSurface(bitmap: Bitmap) {
+        val deferredOnFrameAvailable = CompletableDeferred<Unit>()
+        inputTexture.setOnFrameAvailableListener({
+            deferredOnFrameAvailable.complete(Unit)
+        }, Handler(Looper.getMainLooper()))
+
+        // Draw bitmap to inputSurface.
+        val canvas = inputSurface.lockCanvas(null)
+        canvas.drawBitmap(bitmap, 0f, 0f, null)
+        inputSurface.unlockCanvasAndPost(canvas)
+
+        // Wait for frame available and update texture.
+        withTimeoutOrNull(5_000) {
+            deferredOnFrameAvailable.await()
+        } ?: Assert.fail("Timed out waiting for SurfaceTexture frame available.")
+        inputTexture.updateTexImage()
+    }
+
+    /**
+     * Creates a bitmap with a white top-left quadrant.
+     */
+    private fun createOverlayBitmap(): Bitmap {
+        val bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
+        val centerX = (WIDTH / 2).toFloat()
+        val centerY = (HEIGHT / 2).toFloat()
+
+        val canvas = Canvas(bitmap)
+        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
+
+        val paint = Paint()
+        paint.style = Paint.Style.FILL
+        paint.color = Color.WHITE
+        canvas.drawRect(0f, 0f, centerX, centerY, paint)
+        return bitmap
+    }
+
+    /**
+     * Creates a transparent bitmap.
+     */
+    private fun createTransparentOverlay(): Bitmap {
+        val bitmap = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bitmap)
+        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
+        return bitmap
+    }
+}
diff --git a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlContext.java b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlContext.java
index bc9b244..56919d0 100644
--- a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlContext.java
+++ b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlContext.java
@@ -16,9 +16,13 @@
 
 package androidx.camera.effects.opengl;
 
+import static androidx.camera.effects.opengl.Utils.checkEglErrorOrLog;
 import static androidx.camera.effects.opengl.Utils.checkEglErrorOrThrow;
+import static androidx.camera.effects.opengl.Utils.drawArrays;
 import static androidx.core.util.Preconditions.checkState;
 
+import static java.util.Objects.requireNonNull;
+
 import android.opengl.EGL14;
 import android.opengl.EGLConfig;
 import android.opengl.EGLContext;
@@ -32,6 +36,8 @@
 import androidx.annotation.RequiresApi;
 import androidx.camera.core.Logger;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -55,22 +61,23 @@
 
     // Current output Surface being drawn to.
     @Nullable
-    @SuppressWarnings("UnusedVariable")
     private EglSurface mCurrentSurface = null;
     // A temporary output Surface. This is used when no Surface has been registered yet.
     @Nullable
     private EglSurface mTempSurface = null;
+    @NonNull
+    private final Map<Surface, EglSurface> mRegisteredSurfaces = new HashMap<>();
 
     void init() {
-        // TODO(b/295407763): make sure EGLDisplay, EGLConfig, and EGLContext are released when
-        //  there is exception.
+        checkState(Objects.equals(mEglDisplay, EGL14.EGL_NO_DISPLAY), "Already initialized");
+
         // Create EGLDisplay.
-        EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
-        if (Objects.equals(eglDisplay, EGL14.EGL_NO_DISPLAY)) {
+        mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+        if (Objects.equals(mEglDisplay, EGL14.EGL_NO_DISPLAY)) {
             throw new IllegalStateException("Unable to get EGL14 display");
         }
         int[] version = new int[2];
-        if (!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) {
+        if (!EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)) {
             throw new IllegalStateException("Unable to initialize EGL14");
         }
 
@@ -94,35 +101,28 @@
         EGLConfig[] configs = new EGLConfig[1];
         int[] numConfigs = new int[1];
         if (!EGL14.eglChooseConfig(
-                eglDisplay, attribToChooseConfig, 0, configs, 0, configs.length,
-                numConfigs, 0
+                mEglDisplay, attribToChooseConfig, 0, configs, 0, configs.length, numConfigs, 0
         )) {
             throw new IllegalStateException("Unable to find a suitable EGLConfig");
         }
-        EGLConfig eglConfig = configs[0];
+        mEglConfig = configs[0];
         int[] attribToCreateContext = {
                 EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
                 EGL14.EGL_NONE
         };
 
         // Create EGLContext.
-        EGLContext eglContext = EGL14.eglCreateContext(
-                eglDisplay, eglConfig, EGL14.EGL_NO_CONTEXT,
+        mEglContext = EGL14.eglCreateContext(
+                mEglDisplay, mEglConfig, EGL14.EGL_NO_CONTEXT,
                 attribToCreateContext, 0
         );
         checkEglErrorOrThrow("eglCreateContext");
         int[] values = new int[1];
         EGL14.eglQueryContext(
-                eglDisplay, eglContext, EGL14.EGL_CONTEXT_CLIENT_VERSION, values,
-                0
+                mEglDisplay, mEglContext, EGL14.EGL_CONTEXT_CLIENT_VERSION, values, 0
         );
         Logger.d(TAG, "EGLContext created, client version " + values[0]);
 
-        // All successful. Track the created objects.
-        mEglDisplay = eglDisplay;
-        mEglConfig = eglConfig;
-        mEglContext = eglContext;
-
         // Create a temporary surface to make it current.
         mTempSurface = create1x1PBufferSurface();
         makeCurrent(mTempSurface);
@@ -135,7 +135,10 @@
      * {@link #drawAndSwap}.
      */
     void registerSurface(@NonNull Surface surface) {
-        throw new UnsupportedOperationException("Not implemented yet");
+        checkInitialized();
+        if (!mRegisteredSurfaces.containsKey(surface)) {
+            mRegisteredSurfaces.put(surface, null);
+        }
     }
 
     /**
@@ -144,7 +147,16 @@
      * <p>Once unregistered, calling {@link #drawAndSwap} will no longer be effective.
      */
     void unregisterSurface(@NonNull Surface surface) {
-        throw new UnsupportedOperationException("Not implemented yet");
+        checkInitialized();
+        if (requireNonNull(mCurrentSurface).getSurface() == surface) {
+            // If the current surface is being unregistered, switch to the temporary surface.
+            makeCurrent(requireNonNull(mTempSurface));
+        }
+        // Destroy the EGLSurface.
+        EglSurface removedSurface = mRegisteredSurfaces.remove(surface);
+        if (removedSurface != null) {
+            destroyEglSurface(removedSurface);
+        }
     }
 
     /**
@@ -155,42 +167,108 @@
      * @param timestampNs The timestamp of the frame in nanoseconds.
      */
     void drawAndSwap(@NonNull Surface surface, long timestampNs) {
-        throw new UnsupportedOperationException("Not implemented yet");
+        checkInitialized();
+        checkState(mRegisteredSurfaces.containsKey(surface), "The Surface is not registered.");
+
+        // Get or create the EGLSurface.
+        EglSurface eglSurface = mRegisteredSurfaces.get(surface);
+        // Workaround for when the output Surface is failed to create or needs to be recreated.
+        if (eglSurface == null) {
+            eglSurface = createEglSurface(surface);
+            if (eglSurface == null) {
+                Logger.w(TAG, "Failed to create EGLSurface. Skip drawing.");
+                return;
+            }
+            mRegisteredSurfaces.put(surface, eglSurface);
+        }
+
+        // Draw.
+        makeCurrent(eglSurface);
+        drawArrays(eglSurface.getWidth(), eglSurface.getHeight());
+        EGLExt.eglPresentationTimeANDROID(mEglDisplay, eglSurface.getEglSurface(), timestampNs);
+
+        // Swap buffer
+        if (!EGL14.eglSwapBuffers(mEglDisplay, eglSurface.getEglSurface())) {
+            // If swap buffer failed, destroy the invalid EGL Surface.
+            Logger.w(TAG, "Failed to swap buffers with EGL error: 0x" + Integer.toHexString(
+                    EGL14.eglGetError()));
+            unregisterSurface(surface);
+            // Add the surface back since it's still registered.
+            mRegisteredSurfaces.put(surface, null);
+        }
     }
 
-    boolean release() {
-        if (!isInitialized()) {
-            return false;
+    void release() {
+        if (!Objects.equals(mEglDisplay, EGL14.EGL_NO_DISPLAY)) {
+            EGL14.eglMakeCurrent(
+                    mEglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
+                    EGL14.EGL_NO_CONTEXT
+            );
         }
-        EGL14.eglMakeCurrent(
-                mEglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
-                EGL14.EGL_NO_CONTEXT
-        );
 
-        // TODO: Destroy registered EGL surfaces.
+        // Destroy EGLSurfaces
+        for (EglSurface eglSurface : mRegisteredSurfaces.values()) {
+            if (eglSurface != null) {
+                destroyEglSurface(eglSurface);
+            }
+        }
+        mRegisteredSurfaces.clear();
 
         // Destroy the temporary surface.
         if (mTempSurface != null) {
-            EGL14.eglDestroySurface(mEglDisplay, mTempSurface.getEglSurface());
+            destroyEglSurface(mTempSurface);
             mTempSurface = null;
         }
         mCurrentSurface = null;
 
         // Destroy EGLContext and terminate display.
-        EGL14.eglDestroyContext(mEglDisplay, mEglContext);
-        EGL14.eglTerminate(mEglDisplay);
-        EGL14.eglReleaseThread();
+        if (!Objects.equals(mEglContext, EGL14.EGL_NO_CONTEXT)) {
+            EGL14.eglDestroyContext(mEglDisplay, mEglContext);
+            mEglContext = EGL14.EGL_NO_CONTEXT;
+        }
+        if (!Objects.equals(mEglDisplay, EGL14.EGL_NO_DISPLAY)) {
+            EGL14.eglTerminate(mEglDisplay);
+            mEglDisplay = EGL14.EGL_NO_DISPLAY;
+        }
 
-        // Clear the created configurations.
-        mEglDisplay = EGL14.EGL_NO_DISPLAY;
-        mEglContext = EGL14.EGL_NO_CONTEXT;
+        EGL14.eglReleaseThread();
         mEglConfig = null;
-        return true;
     }
 
     // --- Private methods ---
 
-    private void makeCurrent(EglSurface eglSurface) {
+    private void destroyEglSurface(@NonNull EglSurface eglSurface) {
+        if (!EGL14.eglDestroySurface(mEglDisplay, eglSurface.getEglSurface())) {
+            checkEglErrorOrLog("eglDestroySurface");
+        }
+    }
+
+    @Nullable
+    private EglSurface createEglSurface(@NonNull Surface surface) {
+        EGLSurface eglSurface;
+        try {
+            int[] surfaceAttrib = {
+                    EGL14.EGL_NONE
+            };
+            eglSurface = EGL14.eglCreateWindowSurface(
+                    mEglDisplay, mEglConfig, surface, surfaceAttrib, 0);
+            checkEglErrorOrThrow("eglCreateWindowSurface");
+        } catch (IllegalStateException | IllegalArgumentException e) {
+            Logger.w(TAG, "Failed to create EGL surface: " + e.getMessage(), e);
+            return null;
+        }
+        int width = querySurface(eglSurface, EGL14.EGL_WIDTH);
+        int height = querySurface(eglSurface, EGL14.EGL_HEIGHT);
+        return EglSurface.of(eglSurface, surface, width, height);
+    }
+
+    private int querySurface(@NonNull EGLSurface eglSurface, int what) {
+        int[] value = new int[1];
+        EGL14.eglQuerySurface(mEglDisplay, eglSurface, what, value, 0);
+        return value[0];
+    }
+
+    private void makeCurrent(@NonNull EglSurface eglSurface) {
         checkInitialized();
         if (!EGL14.eglMakeCurrent(mEglDisplay, eglSurface.getEglSurface(),
                 eglSurface.getEglSurface(),
diff --git a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramCopy.java b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramCopy.java
index 9a10090..2336fa3 100644
--- a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramCopy.java
+++ b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramCopy.java
@@ -17,6 +17,7 @@
 package androidx.camera.effects.opengl;
 
 import static androidx.camera.effects.opengl.Utils.checkGlErrorOrThrow;
+import static androidx.camera.effects.opengl.Utils.createFbo;
 import static androidx.camera.effects.opengl.Utils.drawArrays;
 
 import android.opengl.GLES11Ext;
@@ -51,7 +52,7 @@
             + "}";
 
     // A FBO object for attaching the output texture.
-    private int mFbo;
+    private int mFbo = -1;
 
     GlProgramCopy() {
         super(VERTEX_SHADER, FRAGMENT_SHADER);
@@ -61,10 +62,7 @@
     protected void configure() {
         super.configure();
         // Create a FBO for attaching the output texture.
-        int[] fbos = new int[1];
-        GLES20.glGenFramebuffers(1, fbos, 0);
-        checkGlErrorOrThrow("glGenFramebuffers");
-        mFbo = fbos[0];
+        mFbo = createFbo();
     }
 
     @Override
diff --git a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramOverlay.java b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramOverlay.java
index 2b0fe6b..61a1a9f 100644
--- a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramOverlay.java
+++ b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlProgramOverlay.java
@@ -16,14 +16,24 @@
 
 package androidx.camera.effects.opengl;
 
+import static androidx.camera.core.ImageProcessingUtil.copyByteBufferToBitmap;
 import static androidx.camera.effects.opengl.Utils.checkGlErrorOrThrow;
 import static androidx.camera.effects.opengl.Utils.checkLocationOrThrow;
+import static androidx.camera.effects.opengl.Utils.configureTexture2D;
+import static androidx.camera.effects.opengl.Utils.createFbo;
+import static androidx.camera.effects.opengl.Utils.createTextureId;
+import static androidx.camera.effects.opengl.Utils.drawArrays;
+import static androidx.core.util.Preconditions.checkArgument;
 
+import android.graphics.Bitmap;
 import android.opengl.GLES20;
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
+
+import java.nio.ByteBuffer;
 
 /**
  * A GL program that copies the source while overlaying a texture on top of it.
@@ -31,6 +41,10 @@
 @RequiresApi(21)
 class GlProgramOverlay extends GlProgram {
 
+    private static final String TAG = "GlProgramOverlay";
+
+    private static final int SNAPSHOT_PIXEL_STRIDE = 4;
+
     static final String TEXTURE_MATRIX = "uTexMatrix";
     static final String OVERLAY_SAMPLER = "samplerOverlayTexture";
 
@@ -106,7 +120,91 @@
             @NonNull float[] matrix, @NonNull GlContext glContext, @NonNull Surface surface,
             long timestampNs) {
         use();
+        uploadParameters(inputTextureTarget, inputTextureId, overlayTextureId, matrix);
+        try {
+            glContext.drawAndSwap(surface, timestampNs);
+        } catch (IllegalStateException e) {
+            Logger.w(TAG, "Failed to draw the frame", e);
+        }
+    }
 
+    /**
+     * Draws the input texture and overlay to a Bitmap.
+     *
+     * @param inputTextureTarget the texture target of the input texture. This could be either
+     *                           GLES11Ext.GL_TEXTURE_EXTERNAL_OES or GLES20.GL_TEXTURE_2D,
+     *                           depending if copying from an external texture or a 2D texture.
+     * @param inputTextureId     the texture id of the input texture. This could be either an
+     *                           external texture or a 2D texture.
+     * @param overlayTextureId   the texture id of the overlay texture. This must be a 2D texture.
+     * @param width              the width of the output bitmap.
+     * @param height             the height of the output bitmap.
+     * @param matrix             the texture transformation matrix.
+     */
+    @NonNull
+    Bitmap snapshot(int inputTextureTarget, int inputTextureId, int overlayTextureId, int width,
+            int height, @NonNull float[] matrix) {
+        use();
+        // Allocate buffer.
+        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(width * height * SNAPSHOT_PIXEL_STRIDE);
+        // Take a snapshot.
+        snapshot(inputTextureTarget, inputTextureId, overlayTextureId, width, height,
+                matrix, byteBuffer);
+        // Create a Bitmap and copy the bytes over.
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        byteBuffer.rewind();
+        copyByteBufferToBitmap(bitmap, byteBuffer, width * SNAPSHOT_PIXEL_STRIDE);
+        return bitmap;
+    }
+
+    /**
+     * Draws the input texture and overlay to a FBO and download the bytes to the given ByteBuffer.
+     */
+    private void snapshot(int inputTextureTarget,
+            int inputTextureId, int overlayTextureId, int width,
+            int height, @NonNull float[] textureTransform, @NonNull ByteBuffer byteBuffer) {
+        checkArgument(byteBuffer.capacity() == width * height * 4,
+                "ByteBuffer capacity is not equal to width * height * 4.");
+        checkArgument(byteBuffer.isDirect(), "ByteBuffer is not direct.");
+
+        // Create a FBO as the drawing target.
+        int fbo = createFbo();
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo);
+        checkGlErrorOrThrow("glBindFramebuffer");
+        // Create the texture behind the FBO
+        int textureId = createTextureId();
+        configureTexture2D(textureId);
+        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, width,
+                height, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
+        checkGlErrorOrThrow("glTexImage2D");
+        // Attach the texture to the FBO
+        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
+                GLES20.GL_TEXTURE_2D, textureId, 0);
+        checkGlErrorOrThrow("glFramebufferTexture2D");
+
+        // Draw
+        uploadParameters(inputTextureTarget, inputTextureId, overlayTextureId, textureTransform);
+        drawArrays(width, height);
+
+        // Download the pixels from the FBO
+        GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
+                byteBuffer);
+        checkGlErrorOrThrow("glReadPixels");
+
+        // Clean up
+        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
+        checkGlErrorOrThrow("glBindFramebuffer");
+        GLES20.glDeleteTextures(1, new int[]{textureId}, 0);
+        checkGlErrorOrThrow("glDeleteTextures");
+        GLES20.glDeleteFramebuffers(1, new int[]{fbo}, 0);
+        checkGlErrorOrThrow("glDeleteFramebuffers");
+    }
+
+    /**
+     * Uploads the parameters to the shader.
+     */
+    private void uploadParameters(int inputTextureTarget, int inputTextureId, int overlayTextureId,
+            @NonNull float[] matrix) {
         // Uploads the texture transformation matrix.
         GLES20.glUniformMatrix4fv(mTextureMatrixLoc, 1, false, matrix, 0);
         checkGlErrorOrThrow("glUniformMatrix4fv");
@@ -120,7 +218,5 @@
         GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
         GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, overlayTextureId);
         checkGlErrorOrThrow("glBindTexture");
-
-        glContext.drawAndSwap(surface, timestampNs);
     }
 }
diff --git a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlRenderer.java b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlRenderer.java
index 984a25a..8046e43 100644
--- a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlRenderer.java
+++ b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/GlRenderer.java
@@ -16,12 +16,22 @@
 
 package androidx.camera.effects.opengl;
 
+import static androidx.camera.effects.opengl.Utils.checkGlErrorOrThrow;
+import static androidx.camera.effects.opengl.Utils.configureExternalTexture;
+import static androidx.camera.effects.opengl.Utils.configureTexture2D;
+import static androidx.camera.effects.opengl.Utils.createTextureId;
+import static androidx.core.util.Preconditions.checkState;
+
 import android.graphics.Bitmap;
+import android.opengl.GLES11Ext;
 import android.opengl.GLES20;
+import android.opengl.GLUtils;
+import android.os.Build;
 import android.util.Size;
 import android.view.Surface;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 
 /**
@@ -36,9 +46,27 @@
  *
  * <p>It also allows the caller to upload a bitmap and overlay it when rendering to Surface.
  */
+@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public final class GlRenderer {
 
+    private static final String TAG = "GlRenderer";
+
+    private boolean mInitialized = false;
+
+    private Thread mGlThread = null;
+    private final GlContext mGlContext = new GlContext();
+    private final GlProgramOverlay mGlProgramOverlay = new GlProgramOverlay();
+    private final GlProgramCopy mGlProgramCopy = new GlProgramCopy();
+
+    // Texture IDs.
+    private int mInputTextureId = -1;
+    private int mOverlayTextureId = -1;
+    @NonNull
+    private int[] mQueueTextureIds = new int[0];
+    private int mQueueTextureWidth = -1;
+    private int mQueueTextureHeight = -1;
+
     // --- Public methods ---
 
     /**
@@ -46,8 +74,22 @@
      *
      * <p>Must be called before any other methods.
      */
-    void init() {
-        throw new UnsupportedOperationException("TODO: implement this");
+    public void init() {
+        checkState(!mInitialized, "Already initialized");
+        mInitialized = true;
+        mGlThread = Thread.currentThread();
+        try {
+            mGlContext.init();
+            mGlProgramCopy.init();
+            mGlProgramOverlay.init();
+            mInputTextureId = createTextureId();
+            configureExternalTexture(mInputTextureId);
+            mOverlayTextureId = createTextureId();
+            configureTexture2D(mOverlayTextureId);
+        } catch (IllegalStateException | IllegalArgumentException e) {
+            release();
+            throw e;
+        }
     }
 
     /**
@@ -55,15 +97,41 @@
      *
      * <p>Once released, it can never be accessed again.
      */
-    void release() {
-        throw new UnsupportedOperationException("TODO: implement this");
+    public void release() {
+        checkGlThreadAndInitialized();
+
+        mInitialized = false;
+        mGlThread = null;
+        mQueueTextureWidth = -1;
+        mQueueTextureHeight = -1;
+
+        mGlContext.release();
+        mGlProgramOverlay.release();
+        mGlProgramCopy.release();
+
+        if (mInputTextureId != -1) {
+            GLES20.glDeleteTextures(1, new int[]{mInputTextureId}, 0);
+            checkGlErrorOrThrow("glDeleteTextures");
+            mInputTextureId = -1;
+        }
+        if (mOverlayTextureId != -1) {
+            GLES20.glDeleteTextures(1, new int[]{mOverlayTextureId}, 0);
+            checkGlErrorOrThrow("glDeleteTextures");
+            mOverlayTextureId = -1;
+        }
+        if (mQueueTextureIds.length > 0) {
+            GLES20.glDeleteTextures(mQueueTextureIds.length, mQueueTextureIds, 0);
+            checkGlErrorOrThrow("glDeleteTextures");
+            mQueueTextureIds = new int[0];
+        }
     }
 
     /**
      * Gets the external input texture ID created during initialization.
      */
     public int getInputTextureId() {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        return mInputTextureId;
     }
 
     /**
@@ -79,14 +147,48 @@
      */
     @NonNull
     public int[] createBufferTextureIds(int queueDepth, @NonNull Size size) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        // Delete the current buffer if it exists.
+        if (mQueueTextureIds.length > 0) {
+            GLES20.glDeleteTextures(mQueueTextureIds.length, mQueueTextureIds, 0);
+            checkGlErrorOrThrow("glDeleteTextures");
+        }
+
+        mQueueTextureIds = new int[queueDepth];
+        // If the queue depth is 0, return an empty array. There is no need to create textures.
+        if (queueDepth == 0) {
+            return mQueueTextureIds;
+        }
+
+        // Create the textures.
+        GLES20.glGenTextures(queueDepth, mQueueTextureIds, 0);
+        checkGlErrorOrThrow("glGenTextures");
+        mQueueTextureWidth = size.getWidth();
+        mQueueTextureHeight = size.getHeight();
+        for (int textureId : mQueueTextureIds) {
+            configureTexture2D(textureId);
+            GLES20.glTexImage2D(
+                    GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, size.getWidth(), size.getHeight(), 0,
+                    GLES20.GL_RGB,
+                    GLES20.GL_UNSIGNED_BYTE,
+                    null
+            );
+        }
+        return mQueueTextureIds;
     }
 
     /**
      * Uploads the {@link Bitmap} to the overlay texture.
      */
     public void uploadOverlay(@NonNull Bitmap overlay) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mOverlayTextureId);
+        checkGlErrorOrThrow("glBindTexture");
+
+        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, overlay, 0);
+        checkGlErrorOrThrow("texImage2D");
     }
 
     /**
@@ -96,7 +198,8 @@
      * {@link #renderQueueTextureToSurface}.
      */
     public void registerOutputSurface(@NonNull Surface surface) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        mGlContext.registerSurface(surface);
     }
 
     /**
@@ -106,7 +209,8 @@
      * {@link #renderQueueTextureToSurface} with the {@link Surface} throws an exception.
      */
     public void unregisterOutputSurface(@NonNull Surface surface) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        mGlContext.unregisterSurface(surface);
     }
 
     /**
@@ -117,7 +221,9 @@
      */
     public void renderInputToSurface(long timestampNs, @NonNull float[] textureTransform,
             @NonNull Surface surface) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        mGlProgramOverlay.draw(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mInputTextureId,
+                mOverlayTextureId, textureTransform, mGlContext, surface, timestampNs);
     }
 
     /**
@@ -128,9 +234,10 @@
      * {@link #createBufferTextureIds}.
      */
     public void renderQueueTextureToSurface(int textureId, long timestampNs,
-            @NonNull float[] textureTransform,
-            @NonNull Surface surface) {
-        throw new UnsupportedOperationException("TODO: implement this");
+            @NonNull float[] textureTransform, @NonNull Surface surface) {
+        checkGlThreadAndInitialized();
+        mGlProgramOverlay.draw(GLES20.GL_TEXTURE_2D, textureId, mOverlayTextureId,
+                textureTransform, mGlContext, surface, timestampNs);
     }
 
     /**
@@ -139,8 +246,36 @@
      * <p>The texture ID must be from the latest return value of{@link #createBufferTextureIds}.
      */
     public void renderInputToQueueTexture(int textureId) {
-        throw new UnsupportedOperationException("TODO: implement this");
+        checkGlThreadAndInitialized();
+        mGlProgramCopy.draw(mInputTextureId, textureId, mQueueTextureWidth, mQueueTextureHeight);
+    }
+
+    /**
+     * Renders a queued texture to a Bitmap and returns.
+     */
+    @NonNull
+    public Bitmap renderQueueTextureToBitmap(int textureId, int width, int height,
+            @NonNull float[] textureTransform) {
+        checkGlThreadAndInitialized();
+        return mGlProgramOverlay.snapshot(GLES20.GL_TEXTURE_2D, textureId, mOverlayTextureId,
+                width, height, textureTransform);
+    }
+
+    /**
+     * Renders the input texture to a Bitmap and returns.
+     */
+    @NonNull
+    public Bitmap renderInputToBitmap(int width, int height, @NonNull float[] textureTransform) {
+        checkGlThreadAndInitialized();
+        return mGlProgramOverlay.snapshot(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mInputTextureId,
+                mOverlayTextureId, width, height, textureTransform);
     }
 
     // --- Private methods ---
+
+    private void checkGlThreadAndInitialized() {
+        checkState(mInitialized, "OpenGlRenderer is not initialized");
+        checkState(mGlThread == Thread.currentThread(),
+                "Method call must be called on the GL thread.");
+    }
 }
diff --git a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/Utils.java b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/Utils.java
index 9712b41..7c28bb1 100644
--- a/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/Utils.java
+++ b/camera/camera-effects/src/main/java/androidx/camera/effects/opengl/Utils.java
@@ -19,10 +19,12 @@
 import static androidx.camera.effects.opengl.GlProgram.VERTEX_SIZE;
 
 import android.opengl.EGL14;
+import android.opengl.GLES11Ext;
 import android.opengl.GLES20;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.camera.core.Logger;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -41,6 +43,14 @@
     private Utils() {
     }
 
+    static void checkEglErrorOrLog(@NonNull String op) {
+        try {
+            checkEglErrorOrThrow(op);
+        } catch (IllegalStateException e) {
+            Logger.e(TAG, e.toString(), e);
+        }
+    }
+
     static void drawArrays(int width, int height) {
         GLES20.glViewport(0, 0, width, height);
         GLES20.glScissor(0, 0, width, height);
@@ -78,4 +88,57 @@
             throw new IllegalStateException("Unable to locate '" + label + "' in program");
         }
     }
+
+    /**
+     * Creates a single texture ID.
+     */
+    static int createTextureId() {
+        int[] textureIds = new int[1];
+        GLES20.glGenTextures(1, textureIds, 0);
+        checkGlErrorOrThrow("glGenTextures");
+        return textureIds[0];
+    }
+
+    /**
+     * Creates a single FBO.
+     */
+    static int createFbo() {
+        int[] fbos = new int[1];
+        GLES20.glGenFramebuffers(1, fbos, 0);
+        checkGlErrorOrThrow("glGenFramebuffers");
+        return fbos[0];
+    }
+
+    /**
+     * Configures the texture as a 2D texture.
+     */
+    static void configureTexture2D(int textureId) {
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
+        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_LINEAR);
+        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
+                GLES20.GL_CLAMP_TO_EDGE);
+        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
+                GLES20.GL_CLAMP_TO_EDGE);
+    }
+
+    /**
+     * Configures the texture as an external texture.
+     */
+    static void configureExternalTexture(int textureId) {
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
+        checkGlErrorOrThrow("glBindTexture " + textureId);
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_NEAREST);
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
+                GLES20.GL_CLAMP_TO_EDGE);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
+                GLES20.GL_CLAMP_TO_EDGE);
+        checkGlErrorOrThrow("glTexParameter");
+    }
 }
diff --git a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
index f3f56b7..056e784 100644
--- a/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
+++ b/camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/LifecycleCamera.java
@@ -281,7 +281,8 @@
     }
 
     @Override
-    public boolean isUseCasesCombinationSupported(@NonNull UseCase... useCases) {
-        return mCameraUseCaseAdapter.isUseCasesCombinationSupported(useCases);
+    public boolean isUseCasesCombinationSupported(boolean withStreamSharing,
+            @NonNull UseCase... useCases) {
+        return mCameraUseCaseAdapter.isUseCasesCombinationSupported(withStreamSharing, useCases);
     }
 }
diff --git a/camera/camera-testing/src/androidTest/java/androidx/camera/testing/TestImageUtilDeviceTest.kt b/camera/camera-testing/src/androidTest/java/androidx/camera/testing/TestImageUtilDeviceTest.kt
index a54aa93..450f4cd 100644
--- a/camera/camera-testing/src/androidTest/java/androidx/camera/testing/TestImageUtilDeviceTest.kt
+++ b/camera/camera-testing/src/androidTest/java/androidx/camera/testing/TestImageUtilDeviceTest.kt
@@ -14,13 +14,16 @@
  * limitations under the License.
  */
 package androidx.camera.testing
+
 import android.graphics.BitmapFactory.decodeByteArray
+import android.graphics.Color
 import android.graphics.Color.BLUE
 import android.graphics.Color.GREEN
 import android.graphics.Color.RED
 import android.graphics.Color.YELLOW
 import android.graphics.Rect
 import androidx.camera.core.internal.utils.ImageUtil.jpegImageToJpegByteArray
+import androidx.camera.testing.impl.TestImageUtil.createBitmap
 import androidx.camera.testing.impl.TestImageUtil.createJpegBytes
 import androidx.camera.testing.impl.TestImageUtil.createJpegFakeImageProxy
 import androidx.camera.testing.impl.TestImageUtil.getAverageDiff
@@ -30,6 +33,7 @@
 import com.google.common.truth.Truth.assertThat
 import org.junit.Test
 import org.junit.runner.RunWith
+
 /**
  * Unit tests for [TestImageUtil]
  */
@@ -57,6 +61,18 @@
     }
 
     @Test
+    fun createBitmap_verifyWithIncorrectColor() {
+        // The color is supposed to be RED.
+        assertThat(
+            getAverageDiff(
+                createBitmap(WIDTH, HEIGHT),
+                Rect(0, 0, 320, 240),
+                Color.CYAN
+            )
+        ).isEqualTo(255)
+    }
+
+    @Test
     fun createJpegImageProxy_verifyContent() {
         // Arrange: create JPEG bytes.
         val jpegBytes = createJpegBytes(WIDTH, HEIGHT)
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/TestImageUtil.java b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/TestImageUtil.java
index 06f1e21..8bcd510 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/TestImageUtil.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/TestImageUtil.java
@@ -188,7 +188,7 @@
     private static int calculateColorDiff(int color1, int color2) {
         int diff = 0;
         for (int shift = 0; shift <= 16; shift += 8) {
-            diff += Math.abs((color1 >> shift) & 0xFF - (color2 >> shift) & 0xFF);
+            diff += Math.abs(((color1 >> shift) & 0xFF) - ((color2 >> shift) & 0xFF));
         }
         return diff / 3;
     }
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCaseConfig.java b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCaseConfig.java
index b8f0e05..1d9801a1 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCaseConfig.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/impl/fakes/FakeUseCaseConfig.java
@@ -24,10 +24,12 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
 import androidx.camera.core.CameraSelector;
+import androidx.camera.core.DynamicRange;
 import androidx.camera.core.MirrorMode;
 import androidx.camera.core.UseCase;
 import androidx.camera.core.impl.CaptureConfig;
 import androidx.camera.core.impl.Config;
+import androidx.camera.core.impl.ImageInputConfig;
 import androidx.camera.core.impl.ImageOutputConfig;
 import androidx.camera.core.impl.MutableConfig;
 import androidx.camera.core.impl.MutableOptionsBundle;
@@ -72,7 +74,8 @@
     @RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
     public static final class Builder implements
             UseCaseConfig.Builder<FakeUseCase, FakeUseCaseConfig, FakeUseCaseConfig.Builder>,
-            ImageOutputConfig.Builder<FakeUseCaseConfig.Builder> {
+            ImageOutputConfig.Builder<FakeUseCaseConfig.Builder>,
+            ImageInputConfig.Builder<FakeUseCaseConfig.Builder> {
 
         private final MutableOptionsBundle mOptionsBundle;
 
@@ -166,6 +169,14 @@
 
         @Override
         @NonNull
+        public Builder setDynamicRange(
+                @NonNull DynamicRange dynamicRange) {
+            getMutableConfig().insertOption(OPTION_INPUT_DYNAMIC_RANGE, dynamicRange);
+            return this;
+        }
+
+        @Override
+        @NonNull
         public Builder setCaptureOptionUnpacker(
                 @NonNull CaptureConfig.OptionUnpacker optionUnpacker) {
             getMutableConfig().insertOption(OPTION_CAPTURE_CONFIG_UNPACKER, optionUnpacker);
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
index 4cf082c..06f118d 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/DeviceCompatibilityTest.kt
@@ -26,7 +26,6 @@
 import androidx.camera.core.CameraSelector.DEFAULT_BACK_CAMERA
 import androidx.camera.core.CameraSelector.DEFAULT_FRONT_CAMERA
 import androidx.camera.core.CameraXConfig
-import androidx.camera.core.DynamicRange
 import androidx.camera.core.impl.EncoderProfilesProxy.VideoProfileProxy
 import androidx.camera.testing.impl.CameraPipeConfigTestRule
 import androidx.camera.testing.impl.CameraUtil
@@ -66,8 +65,6 @@
 ) {
 
     private val context: Context = ApplicationProvider.getApplicationContext()
-    // TODO(b/278168212): Only SDR is checked by now. Need to extend to HDR dynamic ranges.
-    private val dynamicRange = DynamicRange.SDR
     private val zeroRange by lazy { android.util.Range.create(0, 0) }
 
     @get:Rule
@@ -149,10 +146,14 @@
         if (!CameraUtil.hasCameraWithLensFacing(cameraSelector.lensFacing!!)) {
             return emptyList()
         }
+
         val cameraInfo = CameraUtil.createCameraUseCaseAdapter(context, cameraSelector).cameraInfo
         val videoCapabilities = Recorder.getVideoCapabilities(cameraInfo)
-        return videoCapabilities.getSupportedQualities(dynamicRange).mapNotNull { quality ->
-            videoCapabilities.getProfiles(quality, dynamicRange)
+
+        return videoCapabilities.supportedDynamicRanges.flatMap { dynamicRange ->
+            videoCapabilities.getSupportedQualities(dynamicRange).map { quality ->
+                videoCapabilities.getProfiles(quality, dynamicRange)!!
+            }
         }
     }
 
diff --git a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProviderTest.kt b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProviderTest.kt
index ba20e24..8c2fee1 100644
--- a/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProviderTest.kt
+++ b/camera/camera-video/src/androidTest/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProviderTest.kt
@@ -35,6 +35,8 @@
 import androidx.camera.testing.impl.CameraXUtil
 import androidx.camera.testing.impl.LabTestRule
 import androidx.camera.video.internal.BackupHdrProfileEncoderProfilesProvider.DEFAULT_VALIDATOR
+import androidx.camera.video.internal.compat.quirk.DeviceQuirks
+import androidx.camera.video.internal.compat.quirk.MediaCodecInfoReportIncorrectInfoQuirk
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.filters.SdkSuppress
 import androidx.test.filters.SmallTest
@@ -42,6 +44,7 @@
 import com.google.common.truth.Truth.assertWithMessage
 import java.util.concurrent.TimeUnit
 import org.junit.After
+import org.junit.Assume.assumeFalse
 import org.junit.Assume.assumeTrue
 import org.junit.Before
 import org.junit.Rule
@@ -71,21 +74,14 @@
     val labTest: LabTestRule = LabTestRule()
 
     companion object {
+
+        // Reference to the available values listed in Quality.
         @JvmStatic
         private val qualities = arrayOf(
-            CamcorderProfile.QUALITY_LOW,
-            CamcorderProfile.QUALITY_HIGH,
-            CamcorderProfile.QUALITY_QCIF,
-            CamcorderProfile.QUALITY_CIF,
             CamcorderProfile.QUALITY_480P,
             CamcorderProfile.QUALITY_720P,
             CamcorderProfile.QUALITY_1080P,
-            CamcorderProfile.QUALITY_QVGA,
             CamcorderProfile.QUALITY_2160P,
-            CamcorderProfile.QUALITY_VGA,
-            CamcorderProfile.QUALITY_4KDCI,
-            CamcorderProfile.QUALITY_QHD,
-            CamcorderProfile.QUALITY_2K,
         )
 
         @JvmStatic
@@ -115,6 +111,10 @@
                 }
             }
         }
+
+        private fun hasMediaCodecIncorrectInfoQuirk(): Boolean {
+            return DeviceQuirks.get(MediaCodecInfoReportIncorrectInfoQuirk::class.java) != null
+        }
     }
 
     private val context: Context = ApplicationProvider.getApplicationContext()
@@ -151,6 +151,7 @@
     @Test
     fun defaultValidator_returnNonNull_whenProfileIsFromCamcorder() {
         // Arrange.
+        assumeFalse(hasMediaCodecIncorrectInfoQuirk())
         assumeTrue(baseProvider.hasProfile(quality))
         val encoderProfiles = baseProvider.getAll(quality)
         val baseVideoProfile = encoderProfiles!!.videoProfiles[0]
@@ -170,6 +171,7 @@
         assumeTrue(cameraInfo.supportedDynamicRanges.containsAll(setOf(SDR, HLG_10_BIT)))
 
         // Arrange.
+        assumeFalse(hasMediaCodecIncorrectInfoQuirk())
         assumeTrue(baseProvider.hasProfile(quality))
         val baseVideoProfilesSize = baseProvider.getAll(quality)!!.videoProfiles.size
 
diff --git a/camera/camera-video/src/main/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProvider.java b/camera/camera-video/src/main/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProvider.java
index 0d86c40..8f28109 100644
--- a/camera/camera-video/src/main/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProvider.java
+++ b/camera/camera-video/src/main/java/androidx/camera/video/internal/BackupHdrProfileEncoderProfilesProvider.java
@@ -269,6 +269,10 @@
         VideoEncoderConfig videoEncoderConfig = toVideoEncoderConfig(profile);
         try {
             VideoEncoderInfo videoEncoderInfo = VideoEncoderInfoImpl.from(videoEncoderConfig);
+            if (!videoEncoderInfo.isSizeSupported(profile.getWidth(), profile.getHeight())) {
+                return null;
+            }
+
             int baseBitrate = videoEncoderConfig.getBitrate();
             int newBitrate = videoEncoderInfo.getSupportedBitrateRange().clamp(baseBitrate);
             return newBitrate == baseBitrate ? profile : modifyBitrate(profile, newBitrate);
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/OpenCloseCaptureSessionStressTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/OpenCloseCaptureSessionStressTest.kt
index 9633b80..cd7c3c9 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/OpenCloseCaptureSessionStressTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/OpenCloseCaptureSessionStressTest.kt
@@ -111,7 +111,7 @@
         }
 
         // Creates the Preview with the CameraCaptureSessionStateMonitor to monitor whether the
-        // event callbacks are called.
+        // session callbacks are called.
         preview = createPreviewWithSessionStateMonitor(implName, sessionStateMonitor)
 
         withContext(Dispatchers.Main) {
@@ -133,7 +133,7 @@
     @Test
     @RepeatRule.Repeat(times = STRESS_TEST_REPEAT_COUNT)
     fun openCloseCaptureSessionStressTest_withPreviewImageCapture(): Unit = runBlocking {
-        bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(preview, imageCapture)
+        bindUseCase_unbindAll_toCheckCameraSession_repeatedly(preview, imageCapture)
     }
 
     @LabTestRule.LabTestOnly
@@ -143,7 +143,7 @@
         runBlocking {
             val imageAnalysis = ImageAnalysis.Builder().build()
             assumeTrue(camera.isUseCasesCombinationSupported(preview, imageCapture, imageAnalysis))
-            bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+            bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
                 preview,
                 imageCapture,
                 imageAnalysis = imageAnalysis
@@ -156,7 +156,7 @@
     fun openCloseCaptureSessionStressTest_withPreviewVideoCapture(): Unit =
         runBlocking {
             val videoCapture = VideoCapture.withOutput(Recorder.Builder().build())
-            bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+            bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
                 preview,
                 videoCapture = videoCapture
             )
@@ -169,7 +169,7 @@
         runBlocking {
             val videoCapture = VideoCapture.withOutput(Recorder.Builder().build())
             assumeTrue(camera.isUseCasesCombinationSupported(preview, videoCapture, imageCapture))
-            bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+            bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
                 preview,
                 videoCapture = videoCapture,
                 imageCapture = imageCapture
@@ -184,7 +184,7 @@
             val videoCapture = VideoCapture.withOutput(Recorder.Builder().build())
             val imageAnalysis = ImageAnalysis.Builder().build()
             assumeTrue(camera.isUseCasesCombinationSupported(preview, videoCapture, imageAnalysis))
-            bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+            bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
                 preview,
                 videoCapture = videoCapture,
                 imageAnalysis = imageAnalysis
@@ -193,12 +193,12 @@
 
     /**
      * Repeatedly binds use cases, unbind all to check whether the capture session can be opened
-     * and closed successfully by monitoring the CameraEvent callbacks.
+     * and closed successfully by monitoring the camera session callbacks.
      *
      * <p>This function checks the nullabilities of the input ImageCapture, VideoCapture and
      * ImageAnalysis to determine whether the use cases will be bound together to run the test.
      */
-    private fun bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+    private fun bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
         preview: Preview,
         imageCapture: ImageCapture? = null,
         videoCapture: VideoCapture<Recorder>? = null,
@@ -206,7 +206,7 @@
         repeatCount: Int = STRESS_TEST_OPERATION_REPEAT_COUNT
     ): Unit = runBlocking {
         for (i in 1..repeatCount) {
-            // Arrange: resets the camera event monitor
+            // Arrange: resets the camera monitor
             sessionStateMonitor.reset()
 
             withContext(Dispatchers.Main) {
@@ -268,7 +268,7 @@
     }
 
     /**
-     * An implementation of CameraCaptureSession.StateCallback to monitor whether the event
+     * An implementation of CameraCaptureSession.StateCallback to monitor whether the session
      * callbacks are called properly or not.
      */
     private class CameraCaptureSessionStateMonitor : StateCallback() {
diff --git a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
index 4ee8dc0..52db202 100644
--- a/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
+++ b/camera/integration-tests/extensionstestapp/src/androidTest/java/androidx/camera/integration/extensions/OpenCloseCaptureSessionStressTest.kt
@@ -28,7 +28,6 @@
 import androidx.camera.core.ImageCapture
 import androidx.camera.core.Preview
 import androidx.camera.core.UseCase
-import androidx.camera.extensions.ExtensionMode
 import androidx.camera.extensions.ExtensionsManager
 import androidx.camera.integration.extensions.util.CameraXExtensionsTestUtil
 import androidx.camera.integration.extensions.utils.CameraIdExtensionModePair
@@ -177,7 +176,7 @@
 
     @Test
     fun openCloseCaptureSessionStressTest_withPreviewImageCapture(): Unit = runBlocking {
-        bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(preview, imageCapture)
+        bindUseCase_unbindAll_toCheckCameraSession_repeatedly(preview, imageCapture)
     }
 
     @Test
@@ -185,7 +184,7 @@
         runBlocking {
             val imageAnalysis = ImageAnalysis.Builder().build()
             assumeTrue(camera.isUseCasesCombinationSupported(preview, imageCapture, imageAnalysis))
-            bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+            bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
                 preview,
                 imageCapture,
                 imageAnalysis
@@ -196,12 +195,12 @@
      * Repeatedly binds use cases, unbind all to check whether the capture session can be opened
      * and closed successfully by monitoring the camera session state.
      */
-    private fun bindUseCase_unbindAll_toCheckCameraEvent_repeatedly(
+    private fun bindUseCase_unbindAll_toCheckCameraSession_repeatedly(
         vararg useCases: UseCase,
         repeatCount: Int = CameraXExtensionsTestUtil.getStressTestRepeatingCount()
     ): Unit = runBlocking {
         for (i in 1..repeatCount) {
-            // Arrange: resets the camera event monitor
+            // Arrange: resets the camera session monitor
             cameraSessionMonitor.reset()
 
             withContext(Dispatchers.Main) {
@@ -234,32 +233,10 @@
         @get:Parameterized.Parameters(name = "config = {0}")
         val parameters: Collection<CameraIdExtensionModePair>
             get() = CameraXExtensionsTestUtil.getAllCameraIdExtensionModeCombinations()
-
-        /**
-         * Retrieves the default extended camera config provider id string
-         */
-        private fun getExtendedCameraConfigProviderId(@ExtensionMode.Mode mode: Int): String =
-            when (mode) {
-                ExtensionMode.BOKEH -> "EXTENSION_MODE_BOKEH"
-                ExtensionMode.HDR -> "EXTENSION_MODE_HDR"
-                ExtensionMode.NIGHT -> "EXTENSION_MODE_NIGHT"
-                ExtensionMode.FACE_RETOUCH -> "EXTENSION_MODE_FACE_RETOUCH"
-                ExtensionMode.AUTO -> "EXTENSION_MODE_AUTO"
-                else -> throw IllegalArgumentException("Invalid extension mode!")
-            }.let {
-                return ":camera:camera-extensions-$it"
-            }
-
-        /**
-         * Retrieves the camera event monitor extended camera config provider id string
-         */
-        private fun getCameraEventMonitorCameraConfigProviderId(
-            @ExtensionMode.Mode mode: Int
-        ): String = "${getExtendedCameraConfigProviderId(mode)}-camera-event-monitor"
     }
 
     /**
-     * An implementation of CameraEventCallback to monitor whether the camera is closed or opened.
+     * To monitor whether the camera is closed or opened.
      */
     private class CameraSessionMonitor {
         private var sessionEnabledLatch = CountDownLatch(1)
diff --git a/camera/integration-tests/viewtestapp/build.gradle b/camera/integration-tests/viewtestapp/build.gradle
index d8b1deb..1c44751 100644
--- a/camera/integration-tests/viewtestapp/build.gradle
+++ b/camera/integration-tests/viewtestapp/build.gradle
@@ -70,6 +70,7 @@
     // Outside of androidx this is resolved via constraint added to lifecycle-common,
     // but it doesn't work in androidx.
     implementation("androidx.lifecycle:lifecycle-common-java8:2.5.1")
+    api(libs.constraintLayout)
     compileOnly(libs.kotlinCompiler)
 
     // Lifecycle and LiveData
diff --git a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/StreamSharingActivity.kt b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/StreamSharingActivity.kt
index 2b0d6f6..a593ec0 100644
--- a/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/StreamSharingActivity.kt
+++ b/camera/integration-tests/viewtestapp/src/main/java/androidx/camera/integration/view/StreamSharingActivity.kt
@@ -77,6 +77,7 @@
     private var cameraSelector: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
     private var camera: Camera? = null
     private var previewViewMode: ImplementationMode = ImplementationMode.PERFORMANCE
+    private var previewViewScaleType = PreviewView.ScaleType.FILL_CENTER;
     private var activeRecording: Recording? = null
     private var isUseCasesBound: Boolean = false
     private var deviceOrientation: Int = -1
@@ -102,6 +103,7 @@
 
         // Initial view objects.
         previewView = findViewById(R.id.preview_view)
+        previewView.scaleType = previewViewScaleType
         previewView.implementationMode = previewViewMode
         exportButton = findViewById(R.id.export_button)
         exportButton.setOnClickListener {
@@ -212,9 +214,10 @@
         return null
     }
 
+    @SuppressLint("RestrictedApi")
     private fun isStreamSharingEnabled(): Boolean {
         val isCombinationSupported =
-            camera != null && camera!!.isUseCasesCombinationSupported(*useCases)
+            camera != null && camera!!.isUseCasesCombinationSupportedByFramework(*useCases)
         return !isCombinationSupported && isUseCasesBound
     }
 
diff --git a/camera/integration-tests/viewtestapp/src/main/res/layout/activity_stream_sharing.xml b/camera/integration-tests/viewtestapp/src/main/res/layout/activity_stream_sharing.xml
index d97b32a..8a2037d 100644
--- a/camera/integration-tests/viewtestapp/src/main/res/layout/activity_stream_sharing.xml
+++ b/camera/integration-tests/viewtestapp/src/main/res/layout/activity_stream_sharing.xml
@@ -14,46 +14,46 @@
   limitations under the License.
   -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/layout_camera"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    app:layout_constraintBottom_toBottomOf="parent"
+    app:layout_constraintEnd_toEndOf="parent"
+    app:layout_constraintStart_toStartOf="parent"
+    app:layout_constraintTop_toTopOf="parent">
 
-    <FrameLayout
-        android:id="@+id/container"
+    <androidx.camera.view.PreviewView
+        android:id="@+id/preview_view"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1">
-
-        <androidx.camera.view.PreviewView
-            android:id="@+id/preview_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent" />
-    </FrameLayout>
+        android:layout_height="match_parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
     <LinearLayout
+        android:id="@+id/controller"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent">
 
-        <LinearLayout
-            android:id="@+id/controller"
-            android:layout_width="wrap_content"
+        <Button
+            android:id="@+id/export_button"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal">
+            android:text="@string/btn_export" />
 
-            <Button
-                android:id="@+id/export_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/btn_export" />
-
-            <Button
-                android:id="@+id/record_button"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:enabled="false"
-                android:text="@string/btn_video_record" />
-        </LinearLayout>
+        <Button
+            android:id="@+id/record_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:enabled="false"
+            android:text="@string/btn_video_record" />
     </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/tabtemplates/TabTemplateLoadingDemoScreen.java b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/tabtemplates/TabTemplateLoadingDemoScreen.java
index e695b2e..ab66eb3 100644
--- a/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/tabtemplates/TabTemplateLoadingDemoScreen.java
+++ b/car/app/app-samples/showcase/common/src/main/java/androidx/car/app/sample/showcase/common/screens/templatelayouts/tabtemplates/TabTemplateLoadingDemoScreen.java
@@ -18,14 +18,13 @@
 
 import static androidx.car.app.model.Action.APP_ICON;
 
-import android.text.TextUtils;
-
 import androidx.annotation.NonNull;
 import androidx.car.app.CarContext;
 import androidx.car.app.CarToast;
 import androidx.car.app.Screen;
 import androidx.car.app.model.CarIcon;
 import androidx.car.app.model.ItemList;
+import androidx.car.app.model.ListTemplate;
 import androidx.car.app.model.Row;
 import androidx.car.app.model.SearchTemplate;
 import androidx.car.app.model.Tab;
@@ -43,14 +42,8 @@
  * state.
  */
 public final class TabTemplateLoadingDemoScreen extends Screen {
-    private static final int[] sTitleResIds = new int[]{
-            R.string.tab_title_message, R.string.tab_title_search
-    };
-
-    private static final int[] sIconResIds = new int[]{
-            R.drawable.ic_explore_white_24dp,
-            R.drawable.ic_face_24px
-    };
+    private static final String LOADING_ID = "Loading";
+    private static final String SEARCH_ID = "Search";
 
     private final Map<String, Tab> mTabs;
     private TabTemplate.Builder mTabTemplateBuilder;
@@ -75,34 +68,46 @@
 
         mTabs.clear();
 
-        for (int i = 0; i < 2; i++) {
-            String contentId = String.valueOf(i);
+        Tab loadingTab =
+                new Tab.Builder()
+                        .setTitle(getCarContext().getString(R.string.tab_title_loading))
+                        .setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(),
+                                R.drawable.ic_explore_white_24dp)).build())
+                        .setContentId(LOADING_ID)
+                        .build();
+        mTabTemplateBuilder.addTab(loadingTab);
 
-            Tab.Builder tabBuilder = new Tab.Builder()
-                    .setTitle(getCarContext().getString(sTitleResIds[i]))
-                    .setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(),
-                            sIconResIds[i])).build())
-                    .setContentId(contentId);
-            if (TextUtils.isEmpty(mActiveContentId) && i == 0) {
-                mActiveContentId = contentId;
-            }
+        Tab otherTab =
+                new Tab.Builder()
+                        .setTitle(getCarContext().getString(R.string.tab_title_search))
+                        .setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(),
+                                R.drawable.ic_face_24px)).build())
+                        .setContentId(SEARCH_ID)
+                        .build();
+        mTabTemplateBuilder.addTab(otherTab);
 
-            Tab tab = tabBuilder.build();
-            mTabs.put(tab.getContentId(), tab);
-            mTabTemplateBuilder.addTab(tab);
-
-            if (TextUtils.equals(mActiveContentId, contentId)) {
-                if (i == 0) {
-                    mTabTemplateBuilder.setLoading(true);
-                } else {
-                    mTabTemplateBuilder.setTabContents(createSearchTab());
-                }
-            }
+        if (mActiveContentId == null) {
+            mActiveContentId = LOADING_ID;
         }
-        return mTabTemplateBuilder.setActiveTabContentId(mActiveContentId).build();
+
+        Template contentTemplate;
+        switch (mActiveContentId) {
+            case LOADING_ID:
+                contentTemplate = new ListTemplate.Builder().setLoading(true).build();
+                break;
+            case SEARCH_ID:
+                contentTemplate = createSearchTemplate();
+                break;
+            default:
+                throw new IllegalStateException("What happened?!");
+        }
+
+        return mTabTemplateBuilder.setTabContents(
+                new TabContents.Builder(contentTemplate).build()).setActiveTabContentId(
+                mActiveContentId).build();
     }
 
-    private TabContents createSearchTab() {
+    private Template createSearchTemplate() {
         ItemList.Builder listBuilder = new ItemList.Builder();
         for (int i = 1; i <= 6; ++i) {
             listBuilder.addItem(
@@ -125,7 +130,7 @@
                 .setItemList(listBuilder.build())
                 .setShowKeyboardByDefault(true)
                 .build();
-        return new TabContents.Builder(searchTemplate).build();
+        return searchTemplate;
     }
 
 }
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
index 3bb95c8..287b25c 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-am/strings.xml
@@ -171,7 +171,7 @@
     <string name="continue_route" msgid="5172258139245088080">"ወደ አቅጣጫ ቀጥል"</string>
     <string name="routes_title" msgid="7799772149932075357">"መንገዶች"</string>
     <string name="place_list_nav_template_demo_title" msgid="8019588508812955290">"የዝርዝር አሰሳ ቅንብር ደንብ ቅንጭብ ማሳያን ይመድቡ"</string>
-    <string name="route_preview_template_demo_title" msgid="7878704357953167555">"የመንገድ ቅድመ እይታ ቅንብር ደንብ ቅንጭብ ማሳያ"</string>
+    <string name="route_preview_template_demo_title" msgid="7878704357953167555">"የመንገድ ቅድመ ዕይታ ቅንብር ደንብ ቅንጭብ ማሳያ"</string>
     <string name="notification_template_demo_title" msgid="5076051497316030274">"የማሳወቂያ ቅንብር ደንብ ቅንጭብ ማሳያ"</string>
     <string name="nav_map_template_demo_title" msgid="344985380763975398">"የአሰሳ ቅንብር ደንብ በካርታ ብቻ ማሳያ"</string>
     <string name="nav_demos_title" msgid="72781206086461004">"የአሰሳ ቅንጭብ ማሳያዎች"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
index e2bd7a7..18b72b9 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values-da/strings.xml
@@ -67,7 +67,7 @@
     <string name="parked_toast_msg" msgid="2532422265890824446">"Handlingen Parkeret"</string>
     <string name="more_toast_msg" msgid="5938288138225509885">"Der blev klikket på Mere"</string>
     <string name="commute_toast_msg" msgid="4112684360647638688">"Der blev trykket på knappen Pendling"</string>
-    <string name="grant_location_permission_toast_msg" msgid="268046297444808010">"Giv adgangstilladelse til lokation for at se den aktuelle lokation"</string>
+    <string name="grant_location_permission_toast_msg" msgid="268046297444808010">"Giv lokationstilladelse for at se den aktuelle lokation"</string>
     <string name="sign_in_with_google_toast_msg" msgid="5720947549233124775">"Log ind med Google starter her"</string>
     <string name="changes_selection_to_index_toast_msg_prefix" msgid="957766225794389167">"Markeringen blev ændret til indeks"</string>
     <string name="yes_action_toast_msg" msgid="6216215197177241247">"Der blev trykket på knappen Ja."</string>
@@ -126,7 +126,7 @@
     <string name="permissions_granted_msg" msgid="2348556088141992714">"Alle tilladelser er tildelt. Tilbagekald tilladelser via Indstillinger."</string>
     <string name="needs_access_msg_prefix" msgid="2204136858798832382">"Appen skal have adgang til følgende tilladelser:\n"</string>
     <string name="phone_screen_permission_msg" msgid="3599815596923367256">"Giv tilladelse på telefonskærmen"</string>
-    <string name="enable_location_permission_on_device_msg" msgid="472752487966156897">"Aktivér adgangstilladelse til lokation på enheden"</string>
+    <string name="enable_location_permission_on_device_msg" msgid="472752487966156897">"Aktivér lokationstilladelse på enheden"</string>
     <string name="enable_location_permission_on_phone_msg" msgid="5082615523959139121">"Aktivér lokation på telefonens skærm"</string>
     <string name="required_permissions_title" msgid="5351791879153568211">"Påkrævede tilladelser"</string>
     <string name="request_permissions_title" msgid="7456426341142412300">"Demonstration af Anmod om tilladelse"</string>
diff --git a/car/app/app-samples/showcase/common/src/main/res/values/strings.xml b/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
index 81a7dbd..f0623a2 100644
--- a/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
+++ b/car/app/app-samples/showcase/common/src/main/res/values/strings.xml
@@ -335,6 +335,7 @@
   <string name="tab_title_list">List Tab</string>
   <string name="tab_title_grid">Grid Tab with Long Tab Title</string>
   <string name="tab_title_search">Search Tab</string>
+  <string name="tab_title_loading">Loading Tab</string>
   <string name="tab_template_loading_demo_title">Tab Template Loading Demo</string>
   <string name="tab_template_no_tabs_demo_title">Tab Template No Tabs Demo</string>
 
diff --git a/collection/collection/api/current.txt b/collection/collection/api/current.txt
index 4261c54..5bcab89 100644
--- a/collection/collection/api/current.txt
+++ b/collection/collection/api/current.txt
@@ -133,7 +133,16 @@
   }
 
   public final class FloatListKt {
+    method public static androidx.collection.FloatList emptyFloatList();
+    method public static androidx.collection.FloatList floatListOf();
+    method public static androidx.collection.FloatList floatListOf(float element1);
+    method public static androidx.collection.FloatList floatListOf(float element1, float element2);
+    method public static androidx.collection.FloatList floatListOf(float element1, float element2, float element3);
+    method public static androidx.collection.FloatList floatListOf(float... elements);
     method public static inline androidx.collection.MutableFloatList mutableFloatListOf();
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1);
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1, float element2);
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1, float element2, float element3);
     method public static inline androidx.collection.MutableFloatList mutableFloatListOf(float... elements);
   }
 
@@ -158,7 +167,15 @@
 
   public final class FloatSetKt {
     method public static androidx.collection.FloatSet emptyFloatSet();
+    method public static androidx.collection.FloatSet floatSetOf();
+    method public static androidx.collection.FloatSet floatSetOf(float element1);
+    method public static androidx.collection.FloatSet floatSetOf(float element1, float element2);
+    method public static androidx.collection.FloatSet floatSetOf(float element1, float element2, float element3);
+    method public static androidx.collection.FloatSet floatSetOf(float... elements);
     method public static androidx.collection.MutableFloatSet mutableFloatSetOf();
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1);
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1, float element2);
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1, float element2, float element3);
     method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float... elements);
   }
 
@@ -201,7 +218,16 @@
   }
 
   public final class IntListKt {
+    method public static androidx.collection.IntList emptyIntList();
+    method public static androidx.collection.IntList intListOf();
+    method public static androidx.collection.IntList intListOf(int element1);
+    method public static androidx.collection.IntList intListOf(int element1, int element2);
+    method public static androidx.collection.IntList intListOf(int element1, int element2, int element3);
+    method public static androidx.collection.IntList intListOf(int... elements);
     method public static inline androidx.collection.MutableIntList mutableIntListOf();
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1);
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1, int element2);
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1, int element2, int element3);
     method public static inline androidx.collection.MutableIntList mutableIntListOf(int... elements);
   }
 
@@ -226,7 +252,15 @@
 
   public final class IntSetKt {
     method public static androidx.collection.IntSet emptyIntSet();
+    method public static androidx.collection.IntSet intSetOf();
+    method public static androidx.collection.IntSet intSetOf(int element1);
+    method public static androidx.collection.IntSet intSetOf(int element1, int element2);
+    method public static androidx.collection.IntSet intSetOf(int element1, int element2, int element3);
+    method public static androidx.collection.IntSet intSetOf(int... elements);
     method public static androidx.collection.MutableIntSet mutableIntSetOf();
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1);
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1, int element2);
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1, int element2, int element3);
     method public static androidx.collection.MutableIntSet mutableIntSetOf(int... elements);
   }
 
@@ -269,7 +303,16 @@
   }
 
   public final class LongListKt {
+    method public static androidx.collection.LongList emptyLongList();
+    method public static androidx.collection.LongList longListOf();
+    method public static androidx.collection.LongList longListOf(long element1);
+    method public static androidx.collection.LongList longListOf(long element1, long element2);
+    method public static androidx.collection.LongList longListOf(long element1, long element2, long element3);
+    method public static androidx.collection.LongList longListOf(long... elements);
     method public static inline androidx.collection.MutableLongList mutableLongListOf();
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1);
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1, long element2);
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1, long element2, long element3);
     method public static inline androidx.collection.MutableLongList mutableLongListOf(long... elements);
   }
 
@@ -294,7 +337,15 @@
 
   public final class LongSetKt {
     method public static androidx.collection.LongSet emptyLongSet();
+    method public static androidx.collection.LongSet longSetOf();
+    method public static androidx.collection.LongSet longSetOf(long element1);
+    method public static androidx.collection.LongSet longSetOf(long element1, long element2);
+    method public static androidx.collection.LongSet longSetOf(long element1, long element2, long element3);
+    method public static androidx.collection.LongSet longSetOf(long... elements);
     method public static androidx.collection.MutableLongSet mutableLongSetOf();
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1);
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1, long element2);
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1, long element2, long element3);
     method public static androidx.collection.MutableLongSet mutableLongSetOf(long... elements);
   }
 
@@ -564,6 +615,7 @@
     method public boolean removeAll(E![] elements);
     method public boolean removeAll(Iterable<? extends E> elements);
     method public boolean removeAll(kotlin.sequences.Sequence<? extends E> elements);
+    method public inline void removeIf(kotlin.jvm.functions.Function1<? super E,java.lang.Boolean> predicate);
     method @IntRange(from=0L) public int trim();
   }
 
@@ -652,7 +704,15 @@
   public final class ScatterSetKt {
     method public static <E> androidx.collection.ScatterSet<E> emptyScatterSet();
     method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf();
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1);
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1, E element2);
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1, E element2, E element3);
     method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E?... elements);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf();
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1, E element2);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1, E element2, E element3);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E?... elements);
   }
 
   public class SimpleArrayMap<K, V> {
diff --git a/collection/collection/api/restricted_current.txt b/collection/collection/api/restricted_current.txt
index 7759811..a46df5c 100644
--- a/collection/collection/api/restricted_current.txt
+++ b/collection/collection/api/restricted_current.txt
@@ -135,7 +135,16 @@
   }
 
   public final class FloatListKt {
+    method public static androidx.collection.FloatList emptyFloatList();
+    method public static androidx.collection.FloatList floatListOf();
+    method public static androidx.collection.FloatList floatListOf(float element1);
+    method public static androidx.collection.FloatList floatListOf(float element1, float element2);
+    method public static androidx.collection.FloatList floatListOf(float element1, float element2, float element3);
+    method public static androidx.collection.FloatList floatListOf(float... elements);
     method public static inline androidx.collection.MutableFloatList mutableFloatListOf();
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1);
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1, float element2);
+    method public static androidx.collection.MutableFloatList mutableFloatListOf(float element1, float element2, float element3);
     method public static inline androidx.collection.MutableFloatList mutableFloatListOf(float... elements);
   }
 
@@ -163,7 +172,15 @@
 
   public final class FloatSetKt {
     method public static androidx.collection.FloatSet emptyFloatSet();
+    method public static androidx.collection.FloatSet floatSetOf();
+    method public static androidx.collection.FloatSet floatSetOf(float element1);
+    method public static androidx.collection.FloatSet floatSetOf(float element1, float element2);
+    method public static androidx.collection.FloatSet floatSetOf(float element1, float element2, float element3);
+    method public static androidx.collection.FloatSet floatSetOf(float... elements);
     method public static androidx.collection.MutableFloatSet mutableFloatSetOf();
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1);
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1, float element2);
+    method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float element1, float element2, float element3);
     method public static androidx.collection.MutableFloatSet mutableFloatSetOf(float... elements);
   }
 
@@ -208,7 +225,16 @@
   }
 
   public final class IntListKt {
+    method public static androidx.collection.IntList emptyIntList();
+    method public static androidx.collection.IntList intListOf();
+    method public static androidx.collection.IntList intListOf(int element1);
+    method public static androidx.collection.IntList intListOf(int element1, int element2);
+    method public static androidx.collection.IntList intListOf(int element1, int element2, int element3);
+    method public static androidx.collection.IntList intListOf(int... elements);
     method public static inline androidx.collection.MutableIntList mutableIntListOf();
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1);
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1, int element2);
+    method public static androidx.collection.MutableIntList mutableIntListOf(int element1, int element2, int element3);
     method public static inline androidx.collection.MutableIntList mutableIntListOf(int... elements);
   }
 
@@ -236,7 +262,15 @@
 
   public final class IntSetKt {
     method public static androidx.collection.IntSet emptyIntSet();
+    method public static androidx.collection.IntSet intSetOf();
+    method public static androidx.collection.IntSet intSetOf(int element1);
+    method public static androidx.collection.IntSet intSetOf(int element1, int element2);
+    method public static androidx.collection.IntSet intSetOf(int element1, int element2, int element3);
+    method public static androidx.collection.IntSet intSetOf(int... elements);
     method public static androidx.collection.MutableIntSet mutableIntSetOf();
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1);
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1, int element2);
+    method public static androidx.collection.MutableIntSet mutableIntSetOf(int element1, int element2, int element3);
     method public static androidx.collection.MutableIntSet mutableIntSetOf(int... elements);
   }
 
@@ -281,7 +315,16 @@
   }
 
   public final class LongListKt {
+    method public static androidx.collection.LongList emptyLongList();
+    method public static androidx.collection.LongList longListOf();
+    method public static androidx.collection.LongList longListOf(long element1);
+    method public static androidx.collection.LongList longListOf(long element1, long element2);
+    method public static androidx.collection.LongList longListOf(long element1, long element2, long element3);
+    method public static androidx.collection.LongList longListOf(long... elements);
     method public static inline androidx.collection.MutableLongList mutableLongListOf();
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1);
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1, long element2);
+    method public static androidx.collection.MutableLongList mutableLongListOf(long element1, long element2, long element3);
     method public static inline androidx.collection.MutableLongList mutableLongListOf(long... elements);
   }
 
@@ -309,7 +352,15 @@
 
   public final class LongSetKt {
     method public static androidx.collection.LongSet emptyLongSet();
+    method public static androidx.collection.LongSet longSetOf();
+    method public static androidx.collection.LongSet longSetOf(long element1);
+    method public static androidx.collection.LongSet longSetOf(long element1, long element2);
+    method public static androidx.collection.LongSet longSetOf(long element1, long element2, long element3);
+    method public static androidx.collection.LongSet longSetOf(long... elements);
     method public static androidx.collection.MutableLongSet mutableLongSetOf();
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1);
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1, long element2);
+    method public static androidx.collection.MutableLongSet mutableLongSetOf(long element1, long element2, long element3);
     method public static androidx.collection.MutableLongSet mutableLongSetOf(long... elements);
   }
 
@@ -579,6 +630,8 @@
     method public boolean removeAll(E![] elements);
     method public boolean removeAll(Iterable<? extends E> elements);
     method public boolean removeAll(kotlin.sequences.Sequence<? extends E> elements);
+    method @kotlin.PublishedApi internal void removeElementAt(int index);
+    method public inline void removeIf(kotlin.jvm.functions.Function1<? super E,java.lang.Boolean> predicate);
     method @IntRange(from=0L) public int trim();
   }
 
@@ -682,7 +735,15 @@
   public final class ScatterSetKt {
     method public static <E> androidx.collection.ScatterSet<E> emptyScatterSet();
     method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf();
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1);
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1, E element2);
+    method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E element1, E element2, E element3);
     method public static <E> androidx.collection.MutableScatterSet<E> mutableScatterSetOf(E?... elements);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf();
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1, E element2);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E element1, E element2, E element3);
+    method public static <E> androidx.collection.ScatterSet<E> scatterSetOf(E?... elements);
   }
 
   public class SimpleArrayMap<K, V> {
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatList.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatList.kt
index 5aa24f6..cf0c648 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatList.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatList.kt
@@ -839,13 +839,80 @@
 @Suppress("PrivatePropertyName")
 private val EmptyFloatArray = FloatArray(0)
 
+private val EmptyFloatList: FloatList = MutableFloatList(0)
+
 /**
- * Creates and returns an empty [MutableFloatList] with the default capacity.
+ * @return a read-only [FloatList] with nothing in it.
+ */
+public fun emptyFloatList(): FloatList = EmptyFloatList
+
+/**
+ * @return a read-only [FloatList] with nothing in it.
+ */
+public fun floatListOf(): FloatList = EmptyFloatList
+
+/**
+ * @return a new read-only [FloatList] with [element1] as the only item in the list.
+ */
+public fun floatListOf(element1: Float): FloatList = mutableFloatListOf(element1)
+
+/**
+ * @return a new read-only [FloatList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun floatListOf(element1: Float, element2: Float): FloatList =
+    mutableFloatListOf(element1, element2)
+
+/**
+ * @return a new read-only [FloatList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun floatListOf(element1: Float, element2: Float, element3: Float): FloatList =
+    mutableFloatListOf(element1, element2, element3)
+
+/**
+ * @return a new read-only [FloatList] with [elements] in order.
+ */
+public fun floatListOf(vararg elements: Float): FloatList =
+    MutableFloatList(elements.size).apply { plusAssign(elements) }
+
+/**
+ * @return a new empty [MutableFloatList] with the default capacity.
  */
 public inline fun mutableFloatListOf(): MutableFloatList = MutableFloatList()
 
 /**
- * Creates and returns a [MutableFloatList] with the given values.
+ * @return a new [MutableFloatList] with [element1] as the only item in the list.
+ */
+public fun mutableFloatListOf(element1: Float): MutableFloatList {
+    val list = MutableFloatList(1)
+    list += element1
+    return list
+}
+
+/**
+ * @return a new [MutableFloatList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun mutableFloatListOf(element1: Float, element2: Float): MutableFloatList {
+    val list = MutableFloatList(2)
+    list += element1
+    list += element2
+    return list
+}
+
+/**
+ * @return a new [MutableFloatList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun mutableFloatListOf(element1: Float, element2: Float, element3: Float): MutableFloatList {
+    val list = MutableFloatList(3)
+    list += element1
+    list += element2
+    list += element3
+    return list
+}
+
+/**
+ * @return a new [MutableFloatList] with the given elements, in order.
  */
 public inline fun mutableFloatListOf(vararg elements: Float): MutableFloatList =
-    MutableFloatList(elements.size).also { it.addAll(elements) }
+    MutableFloatList(elements.size).apply { plusAssign(elements) }
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
index ec17dcb..278902c4 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/FloatSet.kt
@@ -43,17 +43,75 @@
 public fun emptyFloatSet(): FloatSet = EmptyFloatSet
 
 /**
+ * Returns an empty, read-only [ScatterSet].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun floatSetOf(): FloatSet = EmptyFloatSet
+
+/**
+ * Returns a new read-only [FloatSet] with only [element1] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun floatSetOf(element1: Float): FloatSet = mutableFloatSetOf(element1)
+
+/**
+ * Returns a new read-only [FloatSet] with only [element1] and [element2] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun floatSetOf(element1: Float, element2: Float): FloatSet =
+    mutableFloatSetOf(element1, element2)
+
+/**
+ * Returns a new read-only [FloatSet] with only [element1], [element2], and [element3] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun floatSetOf(element1: Float, element2: Float, element3: Float): FloatSet =
+    mutableFloatSetOf(element1, element2, element3)
+
+/**
+ * Returns a new read-only [FloatSet] with only [elements] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun floatSetOf(vararg elements: Float): FloatSet =
+    MutableFloatSet(elements.size).apply { plusAssign(elements) }
+
+/**
  * Returns a new [MutableFloatSet].
  */
 public fun mutableFloatSetOf(): MutableFloatSet = MutableFloatSet()
 
 /**
+ * Returns a new [MutableFloatSet] with only [element1] in it.
+ */
+public fun mutableFloatSetOf(element1: Float): MutableFloatSet =
+    MutableFloatSet(1).apply {
+        plusAssign(element1)
+    }
+
+/**
+ * Returns a new [MutableFloatSet] with only [element1] and [element2] in it.
+ */
+public fun mutableFloatSetOf(element1: Float, element2: Float): MutableFloatSet =
+    MutableFloatSet(2).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+    }
+
+/**
+ * Returns a new [MutableFloatSet] with only [element1], [element2], and [element3] in it.
+ */
+public fun mutableFloatSetOf(element1: Float, element2: Float, element3: Float): MutableFloatSet =
+    MutableFloatSet(3).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+        plusAssign(element3)
+    }
+
+/**
  * Returns a new [MutableFloatSet] with the specified elements.
  */
 public fun mutableFloatSetOf(vararg elements: Float): MutableFloatSet =
-    MutableFloatSet(elements.size).apply {
-        addAll(elements)
-    }
+    MutableFloatSet(elements.size).apply { plusAssign(elements) }
 
 /**
  * [FloatSet] is a container with a [Set]-like interface designed to avoid
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntList.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntList.kt
index dbeb31b..8c6122db 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntList.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntList.kt
@@ -483,7 +483,7 @@
  * @constructor Creates a [MutableIntList] with a [capacity] of `initialCapacity`.
  */
 public class MutableIntList(
-    initialCapacity: Int = DefaultCapacity
+    initialCapacity: Int = 16
 ) : IntList(initialCapacity) {
     /**
      * Returns the total number of elements that can be held before the [MutableIntList] must
@@ -835,20 +835,84 @@
     }
 }
 
-@Suppress("ConstPropertyName")
-private const val DefaultCapacity = 16
-
 // Empty array used when nothing is allocated
 @Suppress("PrivatePropertyName")
 private val EmptyIntArray = IntArray(0)
 
+private val EmptyIntList: IntList = MutableIntList(0)
+
 /**
- * Creates and returns an empty [MutableIntList] with the default capacity.
+ * @return a read-only [IntList] with nothing in it.
+ */
+public fun emptyIntList(): IntList = EmptyIntList
+
+/**
+ * @return a read-only [IntList] with nothing in it.
+ */
+public fun intListOf(): IntList = EmptyIntList
+
+/**
+ * @return a new read-only [IntList] with [element1] as the only item in the list.
+ */
+public fun intListOf(element1: Int): IntList = mutableIntListOf(element1)
+
+/**
+ * @return a new read-only [IntList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun intListOf(element1: Int, element2: Int): IntList =
+    mutableIntListOf(element1, element2)
+
+/**
+ * @return a new read-only [IntList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun intListOf(element1: Int, element2: Int, element3: Int): IntList =
+    mutableIntListOf(element1, element2, element3)
+
+/**
+ * @return a new read-only [IntList] with [elements] in order.
+ */
+public fun intListOf(vararg elements: Int): IntList =
+    MutableIntList(elements.size).apply { plusAssign(elements) }
+
+/**
+ * @return a new empty [MutableIntList] with the default capacity.
  */
 public inline fun mutableIntListOf(): MutableIntList = MutableIntList()
 
 /**
- * Creates and returns a [MutableIntList] with the given values.
+ * @return a new [MutableIntList] with [element1] as the only item in the list.
+ */
+public fun mutableIntListOf(element1: Int): MutableIntList {
+    val list = MutableIntList(1)
+    list += element1
+    return list
+}
+
+/**
+ * @return a new [MutableIntList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun mutableIntListOf(element1: Int, element2: Int): MutableIntList {
+    val list = MutableIntList(2)
+    list += element1
+    list += element2
+    return list
+}
+
+/**
+ * @return a new [MutableIntList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun mutableIntListOf(element1: Int, element2: Int, element3: Int): MutableIntList {
+    val list = MutableIntList(3)
+    list += element1
+    list += element2
+    list += element3
+    return list
+}
+
+/**
+ * @return a new [MutableIntList] with the given elements, in order.
  */
 public inline fun mutableIntListOf(vararg elements: Int): MutableIntList =
-    MutableIntList(elements.size).also { it.addAll(elements) }
+    MutableIntList(elements.size).apply { plusAssign(elements) }
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
index fc29782..2db0f7f 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/IntSet.kt
@@ -34,7 +34,7 @@
 // Default empty set to avoid allocations
 private val EmptyIntSet = MutableIntSet(0)
 
-// An empty array of Ints
+// An empty array of ints
 private val EmptyIntArray = IntArray(0)
 
 /**
@@ -43,17 +43,75 @@
 public fun emptyIntSet(): IntSet = EmptyIntSet
 
 /**
+ * Returns an empty, read-only [ScatterSet].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun intSetOf(): IntSet = EmptyIntSet
+
+/**
+ * Returns a new read-only [IntSet] with only [element1] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun intSetOf(element1: Int): IntSet = mutableIntSetOf(element1)
+
+/**
+ * Returns a new read-only [IntSet] with only [element1] and [element2] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun intSetOf(element1: Int, element2: Int): IntSet =
+    mutableIntSetOf(element1, element2)
+
+/**
+ * Returns a new read-only [IntSet] with only [element1], [element2], and [element3] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun intSetOf(element1: Int, element2: Int, element3: Int): IntSet =
+    mutableIntSetOf(element1, element2, element3)
+
+/**
+ * Returns a new read-only [IntSet] with only [elements] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun intSetOf(vararg elements: Int): IntSet =
+    MutableIntSet(elements.size).apply { plusAssign(elements) }
+
+/**
  * Returns a new [MutableIntSet].
  */
 public fun mutableIntSetOf(): MutableIntSet = MutableIntSet()
 
 /**
+ * Returns a new [MutableIntSet] with only [element1] in it.
+ */
+public fun mutableIntSetOf(element1: Int): MutableIntSet =
+    MutableIntSet(1).apply {
+        plusAssign(element1)
+    }
+
+/**
+ * Returns a new [MutableIntSet] with only [element1] and [element2] in it.
+ */
+public fun mutableIntSetOf(element1: Int, element2: Int): MutableIntSet =
+    MutableIntSet(2).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+    }
+
+/**
+ * Returns a new [MutableIntSet] with only [element1], [element2], and [element3] in it.
+ */
+public fun mutableIntSetOf(element1: Int, element2: Int, element3: Int): MutableIntSet =
+    MutableIntSet(3).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+        plusAssign(element3)
+    }
+
+/**
  * Returns a new [MutableIntSet] with the specified elements.
  */
 public fun mutableIntSetOf(vararg elements: Int): MutableIntSet =
-    MutableIntSet(elements.size).apply {
-        addAll(elements)
-    }
+    MutableIntSet(elements.size).apply { plusAssign(elements) }
 
 /**
  * [IntSet] is a container with a [Set]-like interface designed to avoid
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongList.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongList.kt
index 85679d4..94dfd82 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongList.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongList.kt
@@ -483,7 +483,7 @@
  * @constructor Creates a [MutableLongList] with a [capacity] of `initialCapacity`.
  */
 public class MutableLongList(
-    initialCapacity: Int = DefaultCapacity
+    initialCapacity: Int = 16
 ) : LongList(initialCapacity) {
     /**
      * Returns the total number of elements that can be held before the [MutableLongList] must
@@ -835,20 +835,84 @@
     }
 }
 
-@Suppress("ConstPropertyName")
-private const val DefaultCapacity = 16
-
 // Empty array used when nothing is allocated
 @Suppress("PrivatePropertyName")
 private val EmptyLongArray = LongArray(0)
 
+private val EmptyLongList: LongList = MutableLongList(0)
+
 /**
- * Creates and returns an empty [MutableLongList] with the default capacity.
+ * @return a read-only [LongList] with nothing in it.
+ */
+public fun emptyLongList(): LongList = EmptyLongList
+
+/**
+ * @return a read-only [LongList] with nothing in it.
+ */
+public fun longListOf(): LongList = EmptyLongList
+
+/**
+ * @return a new read-only [LongList] with [element1] as the only item in the list.
+ */
+public fun longListOf(element1: Long): LongList = mutableLongListOf(element1)
+
+/**
+ * @return a new read-only [LongList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun longListOf(element1: Long, element2: Long): LongList =
+    mutableLongListOf(element1, element2)
+
+/**
+ * @return a new read-only [LongList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun longListOf(element1: Long, element2: Long, element3: Long): LongList =
+    mutableLongListOf(element1, element2, element3)
+
+/**
+ * @return a new read-only [LongList] with [elements] in order.
+ */
+public fun longListOf(vararg elements: Long): LongList =
+    MutableLongList(elements.size).apply { plusAssign(elements) }
+
+/**
+ * @return a new empty [MutableLongList] with the default capacity.
  */
 public inline fun mutableLongListOf(): MutableLongList = MutableLongList()
 
 /**
- * Creates and returns a [MutableLongList] with the given values.
+ * @return a new [MutableLongList] with [element1] as the only item in the list.
+ */
+public fun mutableLongListOf(element1: Long): MutableLongList {
+    val list = MutableLongList(1)
+    list += element1
+    return list
+}
+
+/**
+ * @return a new [MutableLongList] with 2 elements, [element1] and [element2], in order.
+ */
+public fun mutableLongListOf(element1: Long, element2: Long): MutableLongList {
+    val list = MutableLongList(2)
+    list += element1
+    list += element2
+    return list
+}
+
+/**
+ * @return a new [MutableLongList] with 3 elements, [element1], [element2], and [element3],
+ * in order.
+ */
+public fun mutableLongListOf(element1: Long, element2: Long, element3: Long): MutableLongList {
+    val list = MutableLongList(3)
+    list += element1
+    list += element2
+    list += element3
+    return list
+}
+
+/**
+ * @return a new [MutableLongList] with the given elements, in order.
  */
 public inline fun mutableLongListOf(vararg elements: Long): MutableLongList =
-    MutableLongList(elements.size).also { it.addAll(elements) }
+    MutableLongList(elements.size).apply { plusAssign(elements) }
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
index 4cfe132..f292716 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/LongSet.kt
@@ -34,7 +34,7 @@
 // Default empty set to avoid allocations
 private val EmptyLongSet = MutableLongSet(0)
 
-// An empty array of Longs
+// An empty array of longs
 private val EmptyLongArray = LongArray(0)
 
 /**
@@ -43,17 +43,75 @@
 public fun emptyLongSet(): LongSet = EmptyLongSet
 
 /**
+ * Returns an empty, read-only [ScatterSet].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun longSetOf(): LongSet = EmptyLongSet
+
+/**
+ * Returns a new read-only [LongSet] with only [element1] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun longSetOf(element1: Long): LongSet = mutableLongSetOf(element1)
+
+/**
+ * Returns a new read-only [LongSet] with only [element1] and [element2] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun longSetOf(element1: Long, element2: Long): LongSet =
+    mutableLongSetOf(element1, element2)
+
+/**
+ * Returns a new read-only [LongSet] with only [element1], [element2], and [element3] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun longSetOf(element1: Long, element2: Long, element3: Long): LongSet =
+    mutableLongSetOf(element1, element2, element3)
+
+/**
+ * Returns a new read-only [LongSet] with only [elements] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun longSetOf(vararg elements: Long): LongSet =
+    MutableLongSet(elements.size).apply { plusAssign(elements) }
+
+/**
  * Returns a new [MutableLongSet].
  */
 public fun mutableLongSetOf(): MutableLongSet = MutableLongSet()
 
 /**
+ * Returns a new [MutableLongSet] with only [element1] in it.
+ */
+public fun mutableLongSetOf(element1: Long): MutableLongSet =
+    MutableLongSet(1).apply {
+        plusAssign(element1)
+    }
+
+/**
+ * Returns a new [MutableLongSet] with only [element1] and [element2] in it.
+ */
+public fun mutableLongSetOf(element1: Long, element2: Long): MutableLongSet =
+    MutableLongSet(2).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+    }
+
+/**
+ * Returns a new [MutableLongSet] with only [element1], [element2], and [element3] in it.
+ */
+public fun mutableLongSetOf(element1: Long, element2: Long, element3: Long): MutableLongSet =
+    MutableLongSet(3).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+        plusAssign(element3)
+    }
+
+/**
  * Returns a new [MutableLongSet] with the specified elements.
  */
 public fun mutableLongSetOf(vararg elements: Long): MutableLongSet =
-    MutableLongSet(elements.size).apply {
-        addAll(elements)
-    }
+    MutableLongSet(elements.size).apply { plusAssign(elements) }
 
 /**
  * [LongSet] is a container with a [Set]-like interface designed to avoid
diff --git a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
index 3b13f66..fe0cfd4 100644
--- a/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
+++ b/collection/collection/src/commonMain/kotlin/androidx/collection/ScatterSet.kt
@@ -42,17 +42,75 @@
 public fun <E> emptyScatterSet(): ScatterSet<E> = EmptyScatterSet as ScatterSet<E>
 
 /**
+ * Returns an empty, read-only [ScatterSet].
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <E> scatterSetOf(): ScatterSet<E> = EmptyScatterSet as ScatterSet<E>
+
+/**
+ * Returns a new read-only [ScatterSet] with only [element1] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <E> scatterSetOf(element1: E): ScatterSet<E> = mutableScatterSetOf(element1)
+
+/**
+ * Returns a new read-only [ScatterSet] with only [element1] and [element2] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <E> scatterSetOf(element1: E, element2: E): ScatterSet<E> =
+    mutableScatterSetOf(element1, element2)
+
+/**
+ * Returns a new read-only [ScatterSet] with only [element1], [element2], and [element3] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <E> scatterSetOf(element1: E, element2: E, element3: E): ScatterSet<E> =
+    mutableScatterSetOf(element1, element2, element3)
+
+/**
+ * Returns a new read-only [ScatterSet] with only [elements] in it.
+ */
+@Suppress("UNCHECKED_CAST")
+public fun <E> scatterSetOf(vararg elements: E): ScatterSet<E> =
+    MutableScatterSet<E>(elements.size).apply { plusAssign(elements) }
+
+/**
  * Returns a new [MutableScatterSet].
  */
 public fun <E> mutableScatterSetOf(): MutableScatterSet<E> = MutableScatterSet()
 
 /**
+ * Returns a new [MutableScatterSet] with only [element1] in it.
+ */
+public fun <E> mutableScatterSetOf(element1: E): MutableScatterSet<E> =
+    MutableScatterSet<E>(1).apply {
+        plusAssign(element1)
+    }
+
+/**
+ * Returns a new [MutableScatterSet] with only [element1] and [element2] in it.
+ */
+public fun <E> mutableScatterSetOf(element1: E, element2: E): MutableScatterSet<E> =
+    MutableScatterSet<E>(2).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+    }
+
+/**
+ * Returns a new [MutableScatterSet] with only [element1], [element2], and [element3] in it.
+ */
+public fun <E> mutableScatterSetOf(element1: E, element2: E, element3: E): MutableScatterSet<E> =
+    MutableScatterSet<E>(3).apply {
+        plusAssign(element1)
+        plusAssign(element2)
+        plusAssign(element3)
+    }
+
+/**
  * Returns a new [MutableScatterSet] with the specified contents.
  */
 public fun <E> mutableScatterSetOf(vararg elements: E): MutableScatterSet<E> =
-    MutableScatterSet<E>(elements.size).apply {
-        addAll(elements)
-    }
+    MutableScatterSet<E>(elements.size).apply { plusAssign(elements) }
 
 /**
  * [ScatterSet] is a container with a [Set]-like interface based on a flat
@@ -704,7 +762,21 @@
         }
     }
 
-    private fun removeElementAt(index: Int) {
+    /**
+     * Removes any values for which the specified [predicate] returns true.
+     */
+    public inline fun removeIf(predicate: (E) -> Boolean) {
+        val elements = elements
+        forEachIndex { index ->
+            @Suppress("UNCHECKED_CAST")
+            if (predicate(elements[index] as E)) {
+                removeElementAt(index)
+            }
+        }
+    }
+
+    @PublishedApi
+    internal fun removeElementAt(index: Int) {
         _size -= 1
 
         // TODO: We could just mark the element as empty if there's a group
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatListTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatListTest.kt
index 63d4ce6..b4e501b 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatListTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatListTest.kt
@@ -629,4 +629,88 @@
         l.sortDescending()
         assertEquals(mutableFloatListOf(5f, 4f, 3f, 2f, 1f), l)
     }
+
+    @Test
+    fun testEmptyFloatList() {
+        val l = emptyFloatList()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun floatListOfEmpty() {
+        val l = floatListOf()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun floatListOfOneValue() {
+        val l = floatListOf(2f)
+        assertEquals(1, l.size)
+        assertEquals(2f, l[0])
+    }
+
+    @Test
+    fun floatListOfTwoValues() {
+        val l = floatListOf(2f, 1f)
+        assertEquals(2, l.size)
+        assertEquals(2f, l[0])
+        assertEquals(1f, l[1])
+    }
+
+    @Test
+    fun floatListOfThreeValues() {
+        val l = floatListOf(2f, 10f, -1f)
+        assertEquals(3, l.size)
+        assertEquals(2f, l[0])
+        assertEquals(10f, l[1])
+        assertEquals(-1f, l[2])
+    }
+
+    @Test
+    fun floatListOfFourValues() {
+        val l = floatListOf(2f, 10f, -1f, 10f)
+        assertEquals(4, l.size)
+        assertEquals(2f, l[0])
+        assertEquals(10f, l[1])
+        assertEquals(-1f, l[2])
+        assertEquals(10f, l[3])
+    }
+
+    @Test
+    fun mutableFloatListOfOneValue() {
+        val l = mutableFloatListOf(2f)
+        assertEquals(1, l.size)
+        assertEquals(1, l.capacity)
+        assertEquals(2f, l[0])
+    }
+
+    @Test
+    fun mutableFloatListOfTwoValues() {
+        val l = mutableFloatListOf(2f, 1f)
+        assertEquals(2, l.size)
+        assertEquals(2, l.capacity)
+        assertEquals(2f, l[0])
+        assertEquals(1f, l[1])
+    }
+
+    @Test
+    fun mutableFloatListOfThreeValues() {
+        val l = mutableFloatListOf(2f, 10f, -1f)
+        assertEquals(3, l.size)
+        assertEquals(3, l.capacity)
+        assertEquals(2f, l[0])
+        assertEquals(10f, l[1])
+        assertEquals(-1f, l[2])
+    }
+
+    @Test
+    fun mutableFloatListOfFourValues() {
+        val l = mutableFloatListOf(2f, 10f, -1f, 10f)
+        assertEquals(4, l.size)
+        assertEquals(4, l.capacity)
+        assertEquals(2f, l[0])
+        assertEquals(10f, l[1])
+        assertEquals(-1f, l[2])
+        assertEquals(10f, l[3])
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
index df1c181..98f7b59 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/FloatSetTest.kt
@@ -20,6 +20,7 @@
 import kotlin.test.assertFailsWith
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
+import kotlin.test.assertSame
 import kotlin.test.assertTrue
 
 class FloatSetTest {
@@ -442,4 +443,84 @@
         assertTrue(set.trim() > 0)
         assertEquals(capacity, set.capacity)
     }
+
+    @Test
+    fun floatSetOfEmpty() {
+        assertSame(emptyFloatSet(), floatSetOf())
+        assertEquals(0, floatSetOf().size)
+    }
+
+    @Test
+    fun floatSetOfOne() {
+        val set = floatSetOf(1f)
+        assertEquals(1, set.size)
+        assertEquals(1f, set.first())
+    }
+
+    @Test
+    fun floatSetOfTwo() {
+        val set = floatSetOf(1f, 2f)
+        assertEquals(2, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertFalse(5f in set)
+    }
+
+    @Test
+    fun floatSetOfThree() {
+        val set = floatSetOf(1f, 2f, 3f)
+        assertEquals(3, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertTrue(3f in set)
+        assertFalse(5f in set)
+    }
+
+    @Test
+    fun floatSetOfFour() {
+        val set = floatSetOf(1f, 2f, 3f, 4f)
+        assertEquals(4, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertTrue(3f in set)
+        assertTrue(4f in set)
+        assertFalse(5f in set)
+    }
+
+    @Test
+    fun mutableFloatSetOfOne() {
+        val set = mutableFloatSetOf(1f)
+        assertEquals(1, set.size)
+        assertEquals(1f, set.first())
+    }
+
+    @Test
+    fun mutableFloatSetOfTwo() {
+        val set = mutableFloatSetOf(1f, 2f)
+        assertEquals(2, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertFalse(5f in set)
+    }
+
+    @Test
+    fun mutableFloatSetOfThree() {
+        val set = mutableFloatSetOf(1f, 2f, 3f)
+        assertEquals(3, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertTrue(3f in set)
+        assertFalse(5f in set)
+    }
+
+    @Test
+    fun mutableFloatSetOfFour() {
+        val set = mutableFloatSetOf(1f, 2f, 3f, 4f)
+        assertEquals(4, set.size)
+        assertTrue(1f in set)
+        assertTrue(2f in set)
+        assertTrue(3f in set)
+        assertTrue(4f in set)
+        assertFalse(5f in set)
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntListTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntListTest.kt
index 068527c..66d89af 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntListTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntListTest.kt
@@ -628,4 +628,88 @@
         l.sortDescending()
         assertEquals(mutableIntListOf(5, 4, 3, 2, 1), l)
     }
+
+    @Test
+    fun testEmptyIntList() {
+        val l = emptyIntList()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun intListOfEmpty() {
+        val l = intListOf()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun intListOfOneValue() {
+        val l = intListOf(2)
+        assertEquals(1, l.size)
+        assertEquals(2, l[0])
+    }
+
+    @Test
+    fun intListOfTwoValues() {
+        val l = intListOf(2, 1)
+        assertEquals(2, l.size)
+        assertEquals(2, l[0])
+        assertEquals(1, l[1])
+    }
+
+    @Test
+    fun intListOfThreeValues() {
+        val l = intListOf(2, 10, -1)
+        assertEquals(3, l.size)
+        assertEquals(2, l[0])
+        assertEquals(10, l[1])
+        assertEquals(-1, l[2])
+    }
+
+    @Test
+    fun intListOfFourValues() {
+        val l = intListOf(2, 10, -1, 10)
+        assertEquals(4, l.size)
+        assertEquals(2, l[0])
+        assertEquals(10, l[1])
+        assertEquals(-1, l[2])
+        assertEquals(10, l[3])
+    }
+
+    @Test
+    fun mutableIntListOfOneValue() {
+        val l = mutableIntListOf(2)
+        assertEquals(1, l.size)
+        assertEquals(1, l.capacity)
+        assertEquals(2, l[0])
+    }
+
+    @Test
+    fun mutableIntListOfTwoValues() {
+        val l = mutableIntListOf(2, 1)
+        assertEquals(2, l.size)
+        assertEquals(2, l.capacity)
+        assertEquals(2, l[0])
+        assertEquals(1, l[1])
+    }
+
+    @Test
+    fun mutableIntListOfThreeValues() {
+        val l = mutableIntListOf(2, 10, -1)
+        assertEquals(3, l.size)
+        assertEquals(3, l.capacity)
+        assertEquals(2, l[0])
+        assertEquals(10, l[1])
+        assertEquals(-1, l[2])
+    }
+
+    @Test
+    fun mutableIntListOfFourValues() {
+        val l = mutableIntListOf(2, 10, -1, 10)
+        assertEquals(4, l.size)
+        assertEquals(4, l.capacity)
+        assertEquals(2, l[0])
+        assertEquals(10, l[1])
+        assertEquals(-1, l[2])
+        assertEquals(10, l[3])
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
index 121b0a6..9d326e1 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/IntSetTest.kt
@@ -20,6 +20,7 @@
 import kotlin.test.assertFailsWith
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
+import kotlin.test.assertSame
 import kotlin.test.assertTrue
 
 class IntSetTest {
@@ -442,4 +443,84 @@
         assertTrue(set.trim() > 0)
         assertEquals(capacity, set.capacity)
     }
+
+    @Test
+    fun intSetOfEmpty() {
+        assertSame(emptyIntSet(), intSetOf())
+        assertEquals(0, intSetOf().size)
+    }
+
+    @Test
+    fun intSetOfOne() {
+        val set = intSetOf(1)
+        assertEquals(1, set.size)
+        assertEquals(1, set.first())
+    }
+
+    @Test
+    fun intSetOfTwo() {
+        val set = intSetOf(1, 2)
+        assertEquals(2, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertFalse(5 in set)
+    }
+
+    @Test
+    fun intSetOfThree() {
+        val set = intSetOf(1, 2, 3)
+        assertEquals(3, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertTrue(3 in set)
+        assertFalse(5 in set)
+    }
+
+    @Test
+    fun intSetOfFour() {
+        val set = intSetOf(1, 2, 3, 4)
+        assertEquals(4, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertTrue(3 in set)
+        assertTrue(4 in set)
+        assertFalse(5 in set)
+    }
+
+    @Test
+    fun mutableIntSetOfOne() {
+        val set = mutableIntSetOf(1)
+        assertEquals(1, set.size)
+        assertEquals(1, set.first())
+    }
+
+    @Test
+    fun mutableIntSetOfTwo() {
+        val set = mutableIntSetOf(1, 2)
+        assertEquals(2, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertFalse(5 in set)
+    }
+
+    @Test
+    fun mutableIntSetOfThree() {
+        val set = mutableIntSetOf(1, 2, 3)
+        assertEquals(3, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertTrue(3 in set)
+        assertFalse(5 in set)
+    }
+
+    @Test
+    fun mutableIntSetOfFour() {
+        val set = mutableIntSetOf(1, 2, 3, 4)
+        assertEquals(4, set.size)
+        assertTrue(1 in set)
+        assertTrue(2 in set)
+        assertTrue(3 in set)
+        assertTrue(4 in set)
+        assertFalse(5 in set)
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongListTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongListTest.kt
index e9893fa..45aa039 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongListTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongListTest.kt
@@ -628,4 +628,88 @@
         l.sortDescending()
         assertEquals(mutableLongListOf(5L, 4L, 3L, 2L, 1L), l)
     }
+
+    @Test
+    fun testEmptyLongList() {
+        val l = emptyLongList()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun longListOfEmpty() {
+        val l = longListOf()
+        assertEquals(0, l.size)
+    }
+
+    @Test
+    fun longListOfOneValue() {
+        val l = longListOf(2L)
+        assertEquals(1, l.size)
+        assertEquals(2L, l[0])
+    }
+
+    @Test
+    fun longListOfTwoValues() {
+        val l = longListOf(2L, 1L)
+        assertEquals(2, l.size)
+        assertEquals(2L, l[0])
+        assertEquals(1L, l[1])
+    }
+
+    @Test
+    fun longListOfThreeValues() {
+        val l = longListOf(2L, 10L, -1L)
+        assertEquals(3, l.size)
+        assertEquals(2L, l[0])
+        assertEquals(10L, l[1])
+        assertEquals(-1L, l[2])
+    }
+
+    @Test
+    fun longListOfFourValues() {
+        val l = longListOf(2L, 10L, -1L, 10L)
+        assertEquals(4, l.size)
+        assertEquals(2L, l[0])
+        assertEquals(10L, l[1])
+        assertEquals(-1L, l[2])
+        assertEquals(10L, l[3])
+    }
+
+    @Test
+    fun mutableLongListOfOneValue() {
+        val l = mutableLongListOf(2L)
+        assertEquals(1, l.size)
+        assertEquals(1, l.capacity)
+        assertEquals(2L, l[0])
+    }
+
+    @Test
+    fun mutableLongListOfTwoValues() {
+        val l = mutableLongListOf(2L, 1L)
+        assertEquals(2, l.size)
+        assertEquals(2, l.capacity)
+        assertEquals(2L, l[0])
+        assertEquals(1L, l[1])
+    }
+
+    @Test
+    fun mutableLongListOfThreeValues() {
+        val l = mutableLongListOf(2L, 10L, -1L)
+        assertEquals(3, l.size)
+        assertEquals(3, l.capacity)
+        assertEquals(2L, l[0])
+        assertEquals(10L, l[1])
+        assertEquals(-1L, l[2])
+    }
+
+    @Test
+    fun mutableLongListOfFourValues() {
+        val l = mutableLongListOf(2L, 10L, -1L, 10L)
+        assertEquals(4, l.size)
+        assertEquals(4, l.capacity)
+        assertEquals(2L, l[0])
+        assertEquals(10L, l[1])
+        assertEquals(-1L, l[2])
+        assertEquals(10L, l[3])
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
index de7549d..1278fcf 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/LongSetTest.kt
@@ -20,6 +20,7 @@
 import kotlin.test.assertFailsWith
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
+import kotlin.test.assertSame
 import kotlin.test.assertTrue
 
 class LongSetTest {
@@ -442,4 +443,84 @@
         assertTrue(set.trim() > 0)
         assertEquals(capacity, set.capacity)
     }
+
+    @Test
+    fun longSetOfEmpty() {
+        assertSame(emptyLongSet(), longSetOf())
+        assertEquals(0, longSetOf().size)
+    }
+
+    @Test
+    fun longSetOfOne() {
+        val set = longSetOf(1L)
+        assertEquals(1, set.size)
+        assertEquals(1L, set.first())
+    }
+
+    @Test
+    fun longSetOfTwo() {
+        val set = longSetOf(1L, 2L)
+        assertEquals(2, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertFalse(5L in set)
+    }
+
+    @Test
+    fun longSetOfThree() {
+        val set = longSetOf(1L, 2L, 3L)
+        assertEquals(3, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertTrue(3L in set)
+        assertFalse(5L in set)
+    }
+
+    @Test
+    fun longSetOfFour() {
+        val set = longSetOf(1L, 2L, 3L, 4L)
+        assertEquals(4, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertTrue(3L in set)
+        assertTrue(4L in set)
+        assertFalse(5L in set)
+    }
+
+    @Test
+    fun mutableLongSetOfOne() {
+        val set = mutableLongSetOf(1L)
+        assertEquals(1, set.size)
+        assertEquals(1L, set.first())
+    }
+
+    @Test
+    fun mutableLongSetOfTwo() {
+        val set = mutableLongSetOf(1L, 2L)
+        assertEquals(2, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertFalse(5L in set)
+    }
+
+    @Test
+    fun mutableLongSetOfThree() {
+        val set = mutableLongSetOf(1L, 2L, 3L)
+        assertEquals(3, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertTrue(3L in set)
+        assertFalse(5L in set)
+    }
+
+    @Test
+    fun mutableLongSetOfFour() {
+        val set = mutableLongSetOf(1L, 2L, 3L, 4L)
+        assertEquals(4, set.size)
+        assertTrue(1L in set)
+        assertTrue(2L in set)
+        assertTrue(3L in set)
+        assertTrue(4L in set)
+        assertFalse(5L in set)
+    }
 }
diff --git a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
index 201b2ef..5a4ba52 100644
--- a/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
+++ b/collection/collection/src/commonTest/kotlin/androidx/collection/ScatterSetTest.kt
@@ -21,6 +21,7 @@
 import kotlin.test.assertFalse
 import kotlin.test.assertNotEquals
 import kotlin.test.assertNull
+import kotlin.test.assertSame
 import kotlin.test.assertTrue
 
 class ScatterSetTest {
@@ -648,4 +649,103 @@
         assertTrue(set.trim() > 0)
         assertEquals(capacity, set.capacity)
     }
+
+    @Test
+    fun scatterSetOfEmpty() {
+        assertSame(emptyScatterSet<String>(), scatterSetOf<String>())
+        assertEquals(0, scatterSetOf<String>().size)
+    }
+
+    @Test
+    fun scatterSetOfOne() {
+        val set = scatterSetOf("Hello")
+        assertEquals(1, set.size)
+        assertEquals("Hello", set.first())
+    }
+
+    @Test
+    fun scatterSetOfTwo() {
+        val set = scatterSetOf("Hello", "World")
+        assertEquals(2, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun scatterSetOfThree() {
+        val set = scatterSetOf("Hello", "World", "Hola")
+        assertEquals(3, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertTrue("Hola" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun scatterSetOfFour() {
+        val set = scatterSetOf("Hello", "World", "Hola", "Mundo")
+        assertEquals(4, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertTrue("Hola" in set)
+        assertTrue("Mundo" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun mutableScatterSetOfOne() {
+        val set = mutableScatterSetOf("Hello")
+        assertEquals(1, set.size)
+        assertEquals("Hello", set.first())
+    }
+
+    @Test
+    fun mutableScatterSetOfTwo() {
+        val set = mutableScatterSetOf("Hello", "World")
+        assertEquals(2, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun mutableScatterSetOfThree() {
+        val set = mutableScatterSetOf("Hello", "World", "Hola")
+        assertEquals(3, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertTrue("Hola" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun mutableScatterSetOfFour() {
+        val set = mutableScatterSetOf("Hello", "World", "Hola", "Mundo")
+        assertEquals(4, set.size)
+        assertTrue("Hello" in set)
+        assertTrue("World" in set)
+        assertTrue("Hola" in set)
+        assertTrue("Mundo" in set)
+        assertFalse("Bonjour" in set)
+    }
+
+    @Test
+    fun removeIf() {
+        val set = MutableScatterSet<String>()
+        set.add("Hello")
+        set.add("Bonjour")
+        set.add("Hallo")
+        set.add("Konnichiwa")
+        set.add("Ciao")
+        set.add("Annyeong")
+
+        set.removeIf { value -> value.startsWith('H') }
+
+        assertEquals(4, set.size)
+        assertTrue(set.contains("Bonjour"))
+        assertTrue(set.contains("Konnichiwa"))
+        assertTrue(set.contains("Ciao"))
+        assertTrue(set.contains("Annyeong"))
+    }
 }
diff --git a/compose/animation/animation-core/api/current.txt b/compose/animation/animation-core/api/current.txt
index a08aaa1..9f05c54 100644
--- a/compose/animation/animation-core/api/current.txt
+++ b/compose/animation/animation-core/api/current.txt
@@ -472,6 +472,11 @@
     property public S targetState;
   }
 
+  @androidx.compose.runtime.Immutable public final class PathEasing implements androidx.compose.animation.core.Easing {
+    ctor public PathEasing(androidx.compose.ui.graphics.Path path);
+    method public float transform(float fraction);
+  }
+
   public enum RepeatMode {
     method public static androidx.compose.animation.core.RepeatMode valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
     method public static androidx.compose.animation.core.RepeatMode[] values();
diff --git a/compose/animation/animation-core/api/restricted_current.txt b/compose/animation/animation-core/api/restricted_current.txt
index 04f1097..73e9ff3 100644
--- a/compose/animation/animation-core/api/restricted_current.txt
+++ b/compose/animation/animation-core/api/restricted_current.txt
@@ -472,6 +472,11 @@
     property public S targetState;
   }
 
+  @androidx.compose.runtime.Immutable public final class PathEasing implements androidx.compose.animation.core.Easing {
+    ctor public PathEasing(androidx.compose.ui.graphics.Path path);
+    method public float transform(float fraction);
+  }
+
   public enum RepeatMode {
     method public static androidx.compose.animation.core.RepeatMode valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
     method public static androidx.compose.animation.core.RepeatMode[] values();
diff --git a/compose/animation/animation-core/lint-baseline.xml b/compose/animation/animation-core/lint-baseline.xml
index 6302da6..8e853fd 100644
--- a/compose/animation/animation-core/lint-baseline.xml
+++ b/compose/animation/animation-core/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanSuppressTag"
@@ -83,6 +83,87 @@
     </issue>
 
     <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _animations.forEach {"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _transitions.forEach {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _animations.forEach {"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _transitions.forEach {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _transitions.forEach {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        _animations.forEach {"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                _animations.forEach { it.resetAnimation() }"
+        errorLine2="                            ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        return animations.fold(&quot;Transition animation values: &quot;) { acc, anim -> &quot;$acc$anim, &quot; }"
+        errorLine2="                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            _animations.forEach {"
+        errorLine2="                        ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/core/Transition.kt"/>
+    </issue>
+
+    <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method animateFloatAsState has parameter &apos;finishedListener&apos; with type Function1&lt;? super Float, Unit>."
         errorLine1="    finishedListener: ((Float) -> Unit)? = null"
diff --git a/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/PathEasingSamples.kt b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/PathEasingSamples.kt
new file mode 100644
index 0000000..5333694
--- /dev/null
+++ b/compose/animation/animation-core/samples/src/main/java/androidx/compose/animation/core/samples/PathEasingSamples.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation.core.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.animation.core.PathEasing
+import androidx.compose.animation.core.animateIntOffsetAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.dp
+
+@Sampled
+@Composable
+fun PathEasingSample() {
+    // Creates a custom PathEasing curve and applies it to an animation
+    var toggled by remember {
+        mutableStateOf(true)
+    }
+    val pathForAnimation = remember {
+        Path().apply {
+            moveTo(0f, 0f)
+            cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f)
+            cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f)
+        }
+    }
+    val offset by animateIntOffsetAsState(
+        targetValue =
+        if (toggled) IntOffset.Zero else IntOffset(300, 300),
+        label = "offset",
+        animationSpec = tween(durationMillis = 1000, easing = PathEasing(pathForAnimation))
+    )
+    Box(modifier = Modifier
+        .fillMaxSize()
+        .clickable {
+            toggled = !toggled
+        }) {
+        Box(modifier = Modifier
+            .offset {
+                offset
+            }
+            .size(100.dp)
+            .background(Color.Blue))
+    }
+}
diff --git a/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/PathEasingTest.kt b/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/PathEasingTest.kt
new file mode 100644
index 0000000..a5e8472
--- /dev/null
+++ b/compose/animation/animation-core/src/androidAndroidTest/kotlin/androidx/compose/animation/core/PathEasingTest.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation.core
+
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.Path
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class PathEasingTest {
+    @Test
+    fun pathEasing_Emphasized_BoundsCheck() {
+        val path = Path()
+        path.moveTo(0f, 0f)
+        path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f)
+        path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f)
+
+        val easing = PathEasing(path)
+        assertThat(easing.transform(0f)).isZero()
+        assertThat(easing.transform(1f)).isEqualTo(1f)
+
+        assertEquals(0.77283f, easing.transform(0.25f), 0.0001f)
+        assertEquals(0.95061f, easing.transform(0.5f), 0.0001f)
+        assertEquals(0.99139f, easing.transform(0.75f), 0.0001f)
+    }
+
+    @Test
+    fun pathEasing_CheckIncreasingXOverTime() {
+        val path = Path()
+        path.moveTo(0f, 0f)
+        path.quadraticBezierTo(0f, 1.65f, 1f, -0.6f)
+
+        val easing = PathEasing(path)
+        assertThat(easing.transform(0f)).isZero()
+        assertThat(easing.transform(1f)).isEqualTo(1f)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun pathEasing_CheckIncreasingXOverTime_InvalidPath() {
+        val path = Path()
+        path.addOval(Rect(0f, 0f, 1f, 1f))
+
+        PathEasing(path)
+    }
+
+    @Test(expected = IllegalArgumentException::class)
+    fun pathEasing_NoPathProvided_ThrowsIllegalArgument() {
+        val emptyPath = Path()
+        PathEasing(emptyPath)
+    }
+}
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/PathEasing.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/PathEasing.kt
new file mode 100644
index 0000000..a704e39
--- /dev/null
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/PathEasing.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.animation.core
+
+import androidx.compose.runtime.Immutable
+import androidx.compose.ui.graphics.Path
+import androidx.compose.ui.graphics.PathMeasure
+import kotlin.math.absoluteValue
+
+/**
+ * An easing function for an arbitrary [Path].
+ *
+ * The [Path] must begin at `(0, 0)` and end at `(1, 1)`. The x-coordinate along the
+ * [Path] is the input value and the output is the y coordinate of the line at that
+ * point. This means that the Path must conform to a function `y = f(x)`.
+ *
+ * The [Path] must not have gaps in the x direction and must not
+ * loop back on itself such that there can be two points sharing the same x coordinate.
+ *
+ * This is equivalent to the Android `PathInterpolator`.
+ *
+ * [CubicBezierEasing] should be used if a bezier curve is required as it performs less allocations.
+ * [PathEasing] should be used when creating an arbitrary path.
+ *
+ * @sample androidx.compose.animation.core.samples.PathEasingSample
+ *
+ * @param path The path to use to make the line representing the Easing Curve.
+ *
+ */
+@Immutable
+class PathEasing(path: Path) : Easing {
+
+    private val offsetX: FloatArray
+    private val offsetY: FloatArray
+
+    init {
+        val pathMeasure = PathMeasure()
+        pathMeasure.setPath(path, false)
+
+        val pathLength: Float = pathMeasure.length
+        require(pathLength > 0) {
+            "Path cannot be zero in length. " +
+                "Ensure that supplied Path starts at [0,0] and ends at [1,1]"
+        }
+        val numPoints: Int =
+            (pathLength / Precision).toInt() + 1
+
+        offsetX = FloatArray(numPoints) { 0f }
+        offsetY = FloatArray(numPoints) { 0f }
+
+        for (i in 0 until numPoints) {
+            val distance = i * pathLength / (numPoints - 1)
+            val offset = pathMeasure.getPosition(distance)
+            offsetX[i] = offset.x
+            offsetY[i] = offset.y
+            if (i > 0 && offsetX[i] < offsetX[i - 1]) {
+                throw IllegalArgumentException("Path needs to be continuously increasing")
+            }
+        }
+    }
+
+    override fun transform(fraction: Float): Float {
+        if (fraction <= 0.0f) {
+            return 0.0f
+        } else if (fraction >= 1.0f) {
+            return 1.0f
+        }
+
+        // Do a binary search for the correct x to interpolate between.
+        val startIndex = offsetX.binarySearch(fraction)
+        // the index will be negative if an exact match is not found,
+        // so return the exact item if the index is positive.
+        if (startIndex > 0) {
+            return offsetY[startIndex]
+        }
+        val insertionStartIndex = startIndex.absoluteValue
+        if (insertionStartIndex >= offsetX.size - 1) {
+            return offsetY.last()
+        }
+        val endIndex: Int = insertionStartIndex + 1
+
+        val xRange: Float = offsetX[endIndex] - offsetX[insertionStartIndex]
+
+        val tInRange: Float = fraction - offsetX[insertionStartIndex]
+        val newFraction = tInRange / xRange
+
+        val startY: Float = offsetY[insertionStartIndex]
+        val endY: Float = offsetY[endIndex]
+
+        return startY + newFraction * (endY - startY)
+    }
+}
+
+/**
+ * Governs the accuracy of the approximation of [PathEasing].
+ */
+private const val Precision = 0.002f
diff --git a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt
index bc21855..0053e36 100644
--- a/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt
+++ b/compose/animation/animation-core/src/commonMain/kotlin/androidx/compose/animation/core/VectorizedAnimationSpec.kt
@@ -413,7 +413,12 @@
     ): V = if (playTimeNanos + initialOffsetNanos > durationNanos) {
         // Start velocity of the 2nd and subsequent iteration will be the velocity at the end
         // of the first iteration, instead of the initial velocity.
-        getVelocityFromNanos(durationNanos - initialOffsetNanos, start, startVelocity, end)
+        animation.getVelocityFromNanos(
+            playTimeNanos = durationNanos - initialOffsetNanos,
+            initialValue = start,
+            targetValue = end,
+            initialVelocity = startVelocity
+        )
     } else {
         startVelocity
     }
diff --git a/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/AnimationTest.kt b/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/AnimationTest.kt
index a632f65..a9f239f 100644
--- a/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/AnimationTest.kt
+++ b/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/AnimationTest.kt
@@ -335,6 +335,53 @@
         )
     }
 
+    @Test
+    fun testVectorizedInfiniteRepeatableSpec_velocityOnRepetitions() {
+        val repeatableSpec = VectorizedInfiniteRepeatableSpec(
+            animation = VectorizedAverageVelocitySpec(durationMillis = 1000),
+            repeatMode = RepeatMode.Restart,
+        )
+        val playTimeNanosA = 0L
+        val playTimeNanosB = 1_000L * 1_000_000 - 1
+        val playTimeNanosC = 1_000L * 1_000_000 + 1
+
+        val vectorStart = AnimationVector(0f)
+        val vectorEnd = AnimationVector(3f)
+        val vectorV0 = AnimationVector(0f)
+
+        val velocityAtA = repeatableSpec.getVelocityFromNanos(
+            playTimeNanos = playTimeNanosA,
+            initialValue = vectorStart,
+            targetValue = vectorEnd,
+            initialVelocity = vectorV0
+        )
+
+        val velocityAtB = repeatableSpec.getVelocityFromNanos(
+            playTimeNanos = playTimeNanosB,
+            initialValue = vectorStart,
+            targetValue = vectorEnd,
+            initialVelocity = vectorV0
+        )
+
+        val velocityAC = repeatableSpec.getVelocityFromNanos(
+            playTimeNanos = playTimeNanosC,
+            initialValue = vectorStart,
+            targetValue = vectorEnd,
+            initialVelocity = vectorV0
+        )
+
+        assertEquals(vectorV0, velocityAtA)
+
+        // Final velocity will be the final velocity from the average of: [0, X] = 3 pixels/second
+        // In other words: 6 pixels/second, or `vectorEnd[0] * 2f`
+        // There will be a minor difference since we are measuring one nanosecond before the end
+        assertEquals(vectorEnd[0] * 2f, velocityAtB[0], 0.01f)
+
+        // Final velocity of "B" carries over to initial velocity of "C"
+        // There will be a minor difference since we are measuring 2 nanoseconds between each other
+        assertEquals(velocityAtB[0], velocityAC[0], 0.01f)
+    }
+
     private fun verifyAnimation(
         anim: VectorizedAnimationSpec<AnimationVector4D>,
         start: AnimationVector4D,
@@ -364,4 +411,64 @@
             fixedAnim.durationMillis
         )
     }
+
+    /**
+     * [VectorizedDurationBasedAnimationSpec] that promises to maintain the same average velocity
+     * based on target/initial value and duration.
+     *
+     * This means that the instantaneous velocity will also depend on the initial velocity.
+     */
+    private class VectorizedAverageVelocitySpec<V : AnimationVector>(
+        override val durationMillis: Int
+    ) : VectorizedDurationBasedAnimationSpec<V> {
+        private val durationSeconds = durationMillis.toFloat() / 1_000
+        override val delayMillis: Int = 0
+
+        override fun getValueFromNanos(
+            playTimeNanos: Long,
+            initialValue: V,
+            targetValue: V,
+            initialVelocity: V
+        ): V {
+            val playTimeSeconds = (playTimeNanos / 1_000_000).toFloat() / 1_000
+            val velocity = getVelocityFromNanos(
+                playTimeNanos = playTimeNanos,
+                initialValue = initialValue,
+                targetValue = targetValue,
+                initialVelocity = initialVelocity
+            )
+            val valueVector = initialValue.newInstance()
+            for (i in 0 until velocity.size) {
+                valueVector[i] = velocity[i] * playTimeSeconds
+            }
+            return valueVector
+        }
+
+        override fun getVelocityFromNanos(
+            playTimeNanos: Long,
+            initialValue: V,
+            targetValue: V,
+            initialVelocity: V
+        ): V {
+            val playTimeSeconds = (playTimeNanos / 1_000_000).toFloat() / 1_000
+            val averageVelocity = initialVelocity.newInstance()
+            for (i in 0 until averageVelocity.size) {
+                averageVelocity[i] = (targetValue[i] - initialValue[i]) / durationSeconds
+            }
+            val finalVelocity = initialVelocity.newInstance()
+            for (i in 0 until averageVelocity.size) {
+                finalVelocity[i] = averageVelocity[i] * 2 - initialVelocity[i]
+            }
+            val velocityVector = initialVelocity.newInstance()
+
+            for (i in 0 until averageVelocity.size) {
+                velocityVector[i] = lerp(
+                    start = initialVelocity[i],
+                    stop = finalVelocity[i],
+                    fraction = playTimeSeconds / durationSeconds
+                )
+            }
+            return velocityVector
+        }
+    }
 }
diff --git a/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/EasingTest.kt b/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/EasingTest.kt
index 7f22ced..4aff192 100644
--- a/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/EasingTest.kt
+++ b/compose/animation/animation-core/src/test/java/androidx/compose/animation/core/EasingTest.kt
@@ -35,7 +35,7 @@
     @Test
     fun cubicBezierEndsAt1() {
         val easing = FastOutLinearInEasing
-        assertThat(easing.transform(0f)).isZero()
+        assertThat(easing.transform(1f) == 1f)
     }
 
     @Test
diff --git a/compose/animation/animation-graphics/lint-baseline.xml b/compose/animation/animation-graphics/lint-baseline.xml
index f4264ea..6f66ed4 100644
--- a/compose/animation/animation-graphics/lint-baseline.xml
+++ b/compose/animation/animation-graphics/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="RestrictedApi"
@@ -10,4 +10,58 @@
             file="src/androidMain/kotlin/androidx/compose/animation/graphics/vector/compat/XmlAnimatorParser.android.kt"/>
     </issue>
 
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (target in animatedImageVector.targets) {"
+        errorLine2="                    ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/compose/animation/graphics/res/AnimatedVectorPainterResources.android.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val spec = combined(timestamps.map { timestamp ->"
+        errorLine2="                                           ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/graphics/vector/Animator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            for (keyframe in animatorKeyframes) {"
+        errorLine2="                          ~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/graphics/vector/Animator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            for (keyframe in animatorKeyframes) {"
+        errorLine2="                          ~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/graphics/vector/Animator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    return start.zip(stop) { a, b -> lerp(a, b, fraction) }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/graphics/vector/Animator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            specs.map { (timeMillis, spec) ->"
+        errorLine2="                  ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/graphics/vector/AnimatorAnimationSpecs.kt"/>
+    </issue>
+
 </issues>
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimationDemos.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimationDemos.kt
index 0906082..0c0bbbc 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimationDemos.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/AnimationDemos.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.animation.demos
 
+import androidx.compose.animation.core.samples.PathEasingSample
 import androidx.compose.animation.core.samples.SeekingAnimationSample
 import androidx.compose.animation.demos.fancy.AnimatedClockDemo
 import androidx.compose.animation.demos.fancy.AnimatedDotsDemo
@@ -190,6 +191,7 @@
                 ComposableDemo("Column Arrangements Demo") { ColumnConfigurationDemo() },
                 ComposableDemo("Row Arrangements Demo (Landscape)") { RowConfigurationDemo() },
                 ComposableDemo("Easing Functions Demo") { EasingInfoDemo() },
+                ComposableDemo("Path Easing Function Demo") { PathEasingSample() },
             )
         ),
 
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingFunctionDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingFunctionDemo.kt
index bef78a5..de22e70 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingFunctionDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingFunctionDemo.kt
@@ -85,7 +85,9 @@
     Column(modifier = modifier.padding(16.dp)) {
         Text(easing.description)
         Spacer(modifier = Modifier.height(16.dp))
-        EasingGraph(easing = easing.function, coroutineScope = coroutineScope)
+        Box {
+            EasingGraph(easing = easing.function, coroutineScope = coroutineScope)
+        }
     }
 }
 
diff --git a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingItemDemo.kt b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingItemDemo.kt
index 1f7b53f..45ea8d9 100644
--- a/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingItemDemo.kt
+++ b/compose/animation/animation/integration-tests/animation-demos/src/main/java/androidx/compose/animation/demos/visualaid/EasingItemDemo.kt
@@ -17,6 +17,8 @@
 package androidx.compose.animation.demos.visualaid
 
 import androidx.compose.animation.core.Easing
+import androidx.compose.animation.core.PathEasing
+import androidx.compose.ui.graphics.Path
 
 enum class EasingItemDemo(val description: String, val function: Easing) {
 
@@ -139,4 +141,15 @@
     ),
 
     Linear("Linear", function = androidx.compose.animation.core.LinearEasing),
+
+    EmphasizedEasing("EmphasizedEasing", function = EmphasizedEasingCurve),
 }
+
+/**
+ * Emphasized Easing Curve (Material Spec)
+ */
+private val EmphasizedEasingCurve: Easing = PathEasing(Path().apply {
+    moveTo(0f, 0f)
+    cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f)
+    cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f)
+})
diff --git a/compose/animation/animation/lint-baseline.xml b/compose/animation/animation/lint-baseline.xml
index 76c606a..d6cc720 100644
--- a/compose/animation/animation/lint-baseline.xml
+++ b/compose/animation/animation/lint-baseline.xml
@@ -1,5 +1,95 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                currentlyVisible.forEach {"
+        errorLine2="                                 ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedContent.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.minIntrinsicWidth(height) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedContent.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.minIntrinsicHeight(width) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedContent.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.maxIntrinsicWidth(height) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedContent.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.maxIntrinsicHeight(width) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedContent.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeables = measurables.map { it.measure(constraints) }"
+        errorLine2="                                     ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedVisibility.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.minIntrinsicWidth(height) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedVisibility.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.minIntrinsicHeight(width) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedVisibility.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.maxIntrinsicWidth(height) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedVisibility.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = measurables.asSequence().map { it.maxIntrinsicHeight(width) }.maxOrNull() ?: 0"
+        errorLine2="                    ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/animation/AnimatedVisibility.kt"/>
+    </issue>
 
     <issue
         id="PrimitiveInLambda"
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
index aafa9e2..5210b23 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposePlugin.kt
@@ -220,7 +220,7 @@
     companion object {
         fun checkCompilerVersion(configuration: CompilerConfiguration): Boolean {
             try {
-                val KOTLIN_VERSION_EXPECTATION = "1.9.0"
+                val KOTLIN_VERSION_EXPECTATION = "1.9.10"
                 KotlinCompilerVersion.getVersion()?.let { version ->
                     val msgCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
                     val suppressKotlinVersionCheck = configuration.get(
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
index 6fc6792..0a54200 100644
--- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
+++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/VersionChecker.kt
@@ -127,7 +127,7 @@
          * The maven version string of this compiler. This string should be updated before/after every
          * release.
          */
-        const val compilerVersion: String = "1.5.2"
+        const val compilerVersion: String = "1.5.3"
         private val minimumRuntimeVersion: String
             get() = runtimeVersionToMavenVersionTable[minimumRuntimeVersionInt] ?: "unknown"
     }
diff --git a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
index 91c442b..b51df0e 100644
--- a/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
+++ b/compose/foundation/foundation-layout/src/androidAndroidTest/kotlin/androidx/compose/foundation/layout/RowColumnTest.kt
@@ -1944,6 +1944,34 @@
     }
 
     @Test
+    fun testRow_protectsAgainstOverflow() = with(density) {
+        val rowMinWidth = 0.toDp()
+        val latch = CountDownLatch(3)
+        show {
+            WithInfiniteConstraints {
+                ConstrainedBox(DpConstraints(minWidth = rowMinWidth)) {
+                    Row(horizontalArrangement = Arrangement.spacedBy((0.5).dp)) {
+                        Layout { _, constraints ->
+                            assertEquals(Constraints(), constraints)
+                            layout(Constraints.Infinity, 100) {
+                                latch.countDown()
+                            }
+                        }
+                        Box(modifier = Modifier.weight(1f, true)) {
+                            latch.countDown()
+                        }
+
+                        Box(modifier = Modifier.weight(.00000001f, true)) {
+                            latch.countDown()
+                        }
+                    }
+                }
+            }
+        }
+        assertTrue(latch.await(1, TimeUnit.SECONDS))
+    }
+
+    @Test
     fun testRow_measuresNoWeightChildrenCorrectly() = with(density) {
         val availableWidth = 100.toDp()
         val childWidth = 50.toDp()
diff --git a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnMeasurementHelper.kt b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnMeasurementHelper.kt
index 7483575..15bac06 100644
--- a/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnMeasurementHelper.kt
+++ b/compose/foundation/foundation-layout/src/commonMain/kotlin/androidx/compose/foundation/layout/RowColumnMeasurementHelper.kt
@@ -86,11 +86,11 @@
         @Suppress("NAME_SHADOWING")
         val constraints = OrientationIndependentConstraints(constraints, orientation)
         val arrangementSpacingPx = with(measureScope) {
-            arrangementSpacing.roundToPx()
+            arrangementSpacing.roundToPx().toLong()
         }
 
         var totalWeight = 0f
-        var fixedSpace = 0
+        var fixedSpace = 0L
         var crossAxisSpace = 0
         var weightChildrenCount = 0
 
@@ -116,14 +116,15 @@
                         mainAxisMax = if (mainAxisMax == Constraints.Infinity) {
                             Constraints.Infinity
                         } else {
-                            mainAxisMax - fixedSpace
+                            (mainAxisMax - fixedSpace).coerceAtLeast(0).toInt()
                         },
                         crossAxisMin = 0
                     ).toBoxConstraints(orientation)
                 )
                 spaceAfterLastNoWeight = min(
-                    arrangementSpacingPx,
-                    mainAxisMax - fixedSpace - placeable.mainAxisSize()
+                    arrangementSpacingPx.toInt(),
+                    (mainAxisMax - fixedSpace - placeable.mainAxisSize())
+                        .coerceAtLeast(0).toInt()
                 )
                 fixedSpace += placeable.mainAxisSize() + spaceAfterLastNoWeight
                 crossAxisSpace = max(crossAxisSpace, placeable.crossAxisSize())
@@ -144,8 +145,9 @@
                 } else {
                     constraints.mainAxisMin
                 }
+            val arrangementSpacingTotal = arrangementSpacingPx * (weightChildrenCount - 1)
             val remainingToTarget =
-                targetSpace - fixedSpace - arrangementSpacingPx * (weightChildrenCount - 1)
+                (targetSpace - fixedSpace - arrangementSpacingTotal).coerceAtLeast(0)
 
             val weightUnitSpace = if (totalWeight > 0) remainingToTarget / totalWeight else 0f
             var remainder = remainingToTarget - (startIndex until endIndex).sumOf {
@@ -185,8 +187,9 @@
                     placeables[i] = placeable
                 }
             }
-            weightedSpace = (weightedSpace + arrangementSpacingPx * (weightChildrenCount - 1))
-                .coerceAtMost(constraints.mainAxisMax - fixedSpace)
+            weightedSpace = (weightedSpace + arrangementSpacingTotal)
+                .coerceIn(0, constraints.mainAxisMax - fixedSpace)
+                .toInt()
         }
 
         var beforeCrossAxisAlignmentLine = 0
@@ -222,7 +225,10 @@
         }
 
         // Compute the Row or Column size and position the children.
-        val mainAxisLayoutSize = max(fixedSpace + weightedSpace, constraints.mainAxisMin)
+        val mainAxisLayoutSize = max(
+            (fixedSpace + weightedSpace).coerceAtLeast(0).toInt(),
+            constraints.mainAxisMin
+        )
         val crossAxisLayoutSize = if (constraints.crossAxisMax != Constraints.Infinity &&
             crossAxisSize == SizeMode.Expand
         ) {
@@ -248,11 +254,11 @@
             endIndex = endIndex,
             beforeCrossAxisAlignmentLine = beforeCrossAxisAlignmentLine,
             mainAxisPositions = mainAxisPositions(
-                    mainAxisLayoutSize,
-                    childrenMainAxisSize,
-                    mainAxisPositions,
-                    measureScope
-                ))
+                mainAxisLayoutSize,
+                childrenMainAxisSize,
+                mainAxisPositions,
+                measureScope
+            ))
     }
 
     private fun mainAxisPositions(
diff --git a/compose/foundation/foundation/api/current.txt b/compose/foundation/foundation/api/current.txt
index 01ff795..26a8e15 100644
--- a/compose/foundation/foundation/api/current.txt
+++ b/compose/foundation/foundation/api/current.txt
@@ -19,6 +19,33 @@
     property @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public static final float DefaultMarqueeVelocity;
   }
 
+  public final class BasicTooltipDefaults {
+    method public androidx.compose.foundation.MutatorMutex getGlobalMutatorMutex();
+    property public final androidx.compose.foundation.MutatorMutex GlobalMutatorMutex;
+    field public static final androidx.compose.foundation.BasicTooltipDefaults INSTANCE;
+    field public static final long TooltipDuration = 1500L; // 0x5dcL
+  }
+
+  public final class BasicTooltipKt {
+    method @androidx.compose.runtime.Composable public static void BasicTooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.foundation.BasicTooltipState state, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.foundation.BasicTooltipState BasicTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @androidx.compose.runtime.Composable public static androidx.compose.foundation.BasicTooltipState rememberBasicTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+  }
+
+  @androidx.compose.runtime.Stable public interface BasicTooltipState {
+    method public void dismiss();
+    method public boolean isPersistent();
+    method public boolean isVisible();
+    method public void onDispose();
+    method public suspend Object? show(optional androidx.compose.foundation.MutatePriority mutatePriority, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public abstract boolean isPersistent;
+    property public abstract boolean isVisible;
+  }
+
+  public final class BasicTooltip_androidKt {
+    method @androidx.compose.runtime.Composable public static void BasicTooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.foundation.BasicTooltipState state, androidx.compose.ui.Modifier modifier, boolean focusable, boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
   public final class BorderKt {
     method public static androidx.compose.ui.Modifier border(androidx.compose.ui.Modifier, androidx.compose.foundation.BorderStroke border, optional androidx.compose.ui.graphics.Shape shape);
     method public static androidx.compose.ui.Modifier border(androidx.compose.ui.Modifier, float width, androidx.compose.ui.graphics.Brush brush, androidx.compose.ui.graphics.Shape shape);
@@ -1090,9 +1117,7 @@
 
   public final class PagerKt {
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
   }
 
   @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public sealed interface PagerLayoutInfo {
@@ -1166,7 +1191,6 @@
   }
 
   public final class PagerStateKt {
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction);
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction, kotlin.jvm.functions.Function0<java.lang.Integer> pageCount);
   }
 
diff --git a/compose/foundation/foundation/api/restricted_current.txt b/compose/foundation/foundation/api/restricted_current.txt
index 4924e60..e7d0f2a 100644
--- a/compose/foundation/foundation/api/restricted_current.txt
+++ b/compose/foundation/foundation/api/restricted_current.txt
@@ -19,6 +19,33 @@
     property @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public static final float DefaultMarqueeVelocity;
   }
 
+  public final class BasicTooltipDefaults {
+    method public androidx.compose.foundation.MutatorMutex getGlobalMutatorMutex();
+    property public final androidx.compose.foundation.MutatorMutex GlobalMutatorMutex;
+    field public static final androidx.compose.foundation.BasicTooltipDefaults INSTANCE;
+    field public static final long TooltipDuration = 1500L; // 0x5dcL
+  }
+
+  public final class BasicTooltipKt {
+    method @androidx.compose.runtime.Composable public static void BasicTooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.foundation.BasicTooltipState state, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.foundation.BasicTooltipState BasicTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @androidx.compose.runtime.Composable public static androidx.compose.foundation.BasicTooltipState rememberBasicTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+  }
+
+  @androidx.compose.runtime.Stable public interface BasicTooltipState {
+    method public void dismiss();
+    method public boolean isPersistent();
+    method public boolean isVisible();
+    method public void onDispose();
+    method public suspend Object? show(optional androidx.compose.foundation.MutatePriority mutatePriority, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    property public abstract boolean isPersistent;
+    property public abstract boolean isVisible;
+  }
+
+  public final class BasicTooltip_androidKt {
+    method @androidx.compose.runtime.Composable public static void BasicTooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.foundation.BasicTooltipState state, androidx.compose.ui.Modifier modifier, boolean focusable, boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+  }
+
   public final class BorderKt {
     method public static androidx.compose.ui.Modifier border(androidx.compose.ui.Modifier, androidx.compose.foundation.BorderStroke border, optional androidx.compose.ui.graphics.Shape shape);
     method public static androidx.compose.ui.Modifier border(androidx.compose.ui.Modifier, float width, androidx.compose.ui.graphics.Brush brush, androidx.compose.ui.graphics.Shape shape);
@@ -1092,9 +1119,7 @@
 
   public final class PagerKt {
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.pager.PagerScope,? super java.lang.Integer,kotlin.Unit> pageContent);
   }
 
   @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi public sealed interface PagerLayoutInfo {
@@ -1168,7 +1193,6 @@
   }
 
   public final class PagerStateKt {
-    method @Deprecated @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction);
     method @SuppressCompatibility @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction, kotlin.jvm.functions.Function0<java.lang.Integer> pageCount);
   }
 
diff --git a/compose/foundation/foundation/lint-baseline.xml b/compose/foundation/foundation/lint-baseline.xml
index 21f098b..4fa6762 100644
--- a/compose/foundation/foundation/lint-baseline.xml
+++ b/compose/foundation/foundation/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="NewApi"
@@ -1470,42 +1470,6 @@
 
     <issue
         id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method HorizontalPager has parameter &apos;key&apos; with type Function1&lt;? super Integer, ? extends Object>."
-        errorLine1="    key: ((index: Int) -> Any)? = null,"
-        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method HorizontalPager has parameter &apos;pageContent&apos; with type Function2&lt;? super PagerScope, ? super Integer, Unit>."
-        errorLine1="    pageContent: @Composable PagerScope.(page: Int) -> Unit"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method VerticalPager has parameter &apos;key&apos; with type Function1&lt;? super Integer, ? extends Object>."
-        errorLine1="    key: ((index: Int) -> Any)? = null,"
-        errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method VerticalPager has parameter &apos;pageContent&apos; with type Function2&lt;? super PagerScope, ? super Integer, Unit>."
-        errorLine1="    pageContent: @Composable PagerScope.(page: Int) -> Unit"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method VerticalPager has parameter &apos;key&apos; with type Function1&lt;? super Integer, ? extends Object>."
         errorLine1="    key: ((index: Int) -> Any)? = null,"
         errorLine2="         ~~~~~~~~~~~~~~~~~~~~~~">
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/BasicTooltipTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/BasicTooltipTest.kt
new file mode 100644
index 0000000..416f193
--- /dev/null
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/BasicTooltipTest.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2023 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.foundation
+
+import android.os.Build
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.requiredSize
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.longClick
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performMouseInput
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntRect
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.window.PopupPositionProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
+@RunWith(AndroidJUnit4::class)
+class BasicTooltipTest {
+    @get:Rule
+    val rule = createComposeRule()
+
+    @OptIn(ExperimentalTestApi::class)
+    @Test
+    fun tooltip_handleDefaultGestures_enabled() {
+        lateinit var state: BasicTooltipState
+        lateinit var scope: CoroutineScope
+        rule.setContent {
+            state = rememberBasicTooltipState(initialIsVisible = false)
+            scope = rememberCoroutineScope()
+            BasicTooltipBox(
+                positionProvider = EmptyPositionProvider(),
+                tooltip = {},
+                state = state,
+                modifier = Modifier.testTag(TOOLTIP_ANCHOR)
+            ) { Box(modifier = Modifier.requiredSize(1.dp)) {} }
+        }
+
+        // Stop auto advance for test consistency
+        rule.mainClock.autoAdvance = false
+
+        // The tooltip should not be showing at first
+        Truth.assertThat(state.isVisible).isFalse()
+
+        // Long press the anchor
+        rule.onNodeWithTag(TOOLTIP_ANCHOR, true)
+            .performTouchInput {
+                longClick()
+            }
+
+        // Check that the tooltip is now showing
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isTrue()
+
+        // Dismiss the tooltip and check that it dismissed
+        scope.launch {
+            state.dismiss()
+        }
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isFalse()
+
+        // Hover over the anchor with mouse input
+        rule.onNodeWithTag(TOOLTIP_ANCHOR)
+            .performMouseInput {
+                enter()
+            }
+
+        // Check that the tooltip is now showing
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isTrue()
+
+        // Hover away from the anchor
+        rule.onNodeWithTag(TOOLTIP_ANCHOR)
+            .performMouseInput {
+                exit()
+            }
+
+        // Check that the tooltip is now dismissed
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isFalse()
+    }
+
+    @OptIn(ExperimentalTestApi::class)
+    @Test
+    fun tooltip_handleDefaultGestures_disabled() {
+        lateinit var state: BasicTooltipState
+        rule.setContent {
+            state = rememberBasicTooltipState(initialIsVisible = false)
+            BasicTooltipBox(
+                positionProvider = EmptyPositionProvider(),
+                tooltip = {},
+                enableUserInput = false,
+                state = state,
+                modifier = Modifier.testTag(TOOLTIP_ANCHOR)
+            ) { Box(modifier = Modifier.requiredSize(1.dp)) {} }
+        }
+
+        // Stop auto advance for test consistency
+        rule.mainClock.autoAdvance = false
+
+        // The tooltip should not be showing at first
+        Truth.assertThat(state.isVisible).isFalse()
+
+        // Long press the anchor
+        rule.onNodeWithTag(TOOLTIP_ANCHOR)
+            .performTouchInput {
+                longClick()
+            }
+
+        // Check that the tooltip is still not showing
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isFalse()
+
+        // Hover over the anchor with mouse input
+        rule.onNodeWithTag(TOOLTIP_ANCHOR)
+            .performMouseInput {
+                enter()
+            }
+
+        // Check that the tooltip is still not showing
+        rule.waitForIdle()
+        Truth.assertThat(state.isVisible).isFalse()
+    }
+}
+
+private class EmptyPositionProvider : PopupPositionProvider {
+    override fun calculatePosition(
+        anchorBounds: IntRect,
+        windowSize: IntSize,
+        layoutDirection: LayoutDirection,
+        popupContentSize: IntSize
+    ): IntOffset { return IntOffset(0, 0) }
+}
+
+private const val TOOLTIP_ANCHOR = "anchor"
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
index 684016b..1ec698c 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/DraggableTest.kt
@@ -26,6 +26,7 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.size
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.rememberCoroutineScope
@@ -36,6 +37,7 @@
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.platform.InspectableValue
 import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.isDebugInspectorInfoEnabled
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.ExperimentalTestApi
@@ -800,6 +802,43 @@
     }
 
     @Test
+    fun draggable_velocityIsLimitedByViewConfiguration() {
+        var latestVelocity = 0f
+        val maxVelocity = 1000f
+
+        rule.setContent {
+            val viewConfig = LocalViewConfiguration.current
+            val newConfig = object : ViewConfiguration by viewConfig {
+                override val maximumFlingVelocity: Int
+                    get() = maxVelocity.toInt()
+            }
+            CompositionLocalProvider(LocalViewConfiguration provides newConfig) {
+                Box {
+                    Box(
+                        modifier = Modifier
+                            .testTag(draggableBoxTag)
+                            .size(100.dp)
+                            .draggable(orientation = Orientation.Horizontal, onDragStopped = {
+                                latestVelocity = it
+                            }, onDrag = {})
+                    )
+                }
+            }
+        }
+
+        rule.onNodeWithTag(draggableBoxTag).performTouchInput {
+            this.swipeWithVelocity(
+                start = this.centerLeft,
+                end = this.centerRight,
+                endVelocity = 2000f
+            )
+        }
+        rule.runOnIdle {
+            assertThat(latestVelocity).isEqualTo(maxVelocity)
+        }
+    }
+
+    @Test
     fun draggable_interactionSource_resetWhenInteractionSourceChanged() {
         val interactionSource1 = MutableInteractionSource()
         val interactionSource2 = MutableInteractionSource()
@@ -952,9 +991,9 @@
             enabled.value = false // cancels pointer input scope
         }
 
-       rule.runOnIdle {
-           assertTrue { runningJob.isActive } // check if scope is still active
-       }
+        rule.runOnIdle {
+            assertTrue { runningJob.isActive } // check if scope is still active
+        }
     }
 
     @Test
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollTest.kt
index 805bc22..a828f4b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/ScrollTest.kt
@@ -60,6 +60,7 @@
 import androidx.compose.ui.layout.MeasurePolicy
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
+import androidx.compose.ui.layout.OnRemeasuredModifier
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.InspectableValue
 import androidx.compose.ui.platform.LocalDensity
@@ -462,6 +463,7 @@
                         content()
                     }
                 }
+
                 Horizontal -> {
                     CompositionLocalProvider(LocalLayoutDirection provides config.layoutDirection) {
                         Row(Modifier.horizontalScroll(actualState)) {
@@ -590,6 +592,7 @@
                                 )
                             }
                         }
+
                         Horizontal -> {
                             CompositionLocalProvider(
                                 LocalLayoutDirection provides config.layoutDirection
@@ -673,6 +676,7 @@
                             content()
                         }
                     }
+
                     Horizontal -> {
                         CompositionLocalProvider(
                             LocalLayoutDirection provides config.layoutDirection
@@ -1066,6 +1070,69 @@
         assertThat(state.viewportSize).isEqualTo(scrollerSize)
     }
 
+    @Test
+    fun onMaxValueUpdate_shouldNotGenerateExtraMeasurements() {
+        var measurements = 0
+        lateinit var scrollState: ScrollState
+
+        val sizeModifiers = if (config.orientation == Horizontal) {
+            Modifier
+                .fillMaxWidth()
+                .height(100.dp)
+        } else {
+            Modifier
+                .width(100.dp)
+                .fillMaxHeight()
+        }
+
+        val wrapperModifiers = Modifier
+            .testTag(scrollerTag)
+            .then(sizeModifiers)
+            .then(CountMeasureModifier { measurements++ })
+
+        val content: @Composable () -> Unit = {
+            repeat(25) {
+                Box(modifier = Modifier.size(100.dp)
+                    .padding(2.dp)
+                    .background(Color.Red))
+            }
+        }
+
+        rule.setContent {
+            scrollState = rememberScrollState()
+
+            CompositionLocalProvider(LocalLayoutDirection provides config.layoutDirection) {
+                if (config.orientation == Horizontal) {
+                    Row(
+                        Modifier
+                            .horizontalScroll(scrollState)
+                            .then(wrapperModifiers),
+                        content = { content() }
+                    )
+                } else {
+                    Column(
+                        Modifier
+                            .verticalScroll(scrollState)
+                            .then(wrapperModifiers),
+                        content = { content() }
+                    )
+                }
+            }
+        }
+
+        val previousMeasurement = measurements
+
+        rule.onNodeWithTag(scrollerTag)
+            .performTouchInput {
+                configAwareSwipe()
+            }
+
+        rule.runOnIdle {
+            assertThat(scrollState.value).isNotEqualTo(0) // check we scrolled
+            assertThat(measurements).isEqualTo(previousMeasurement) // no extra measurements
+        }
+    }
+
     private fun Modifier.intrinsicMainAxisSize(size: IntrinsicSize): Modifier =
         if (config.orientation == Horizontal) {
             width(size)
@@ -1116,6 +1183,7 @@
                 height = mainAxisSize,
                 rowHeight = cellSize
             )
+
             Horizontal -> composeHorizontalScroller(
                 scrollState = scrollState,
                 isReversed = isReversed,
@@ -1213,6 +1281,7 @@
                 height = mainAxis,
                 rowHeight = cellSize
             )
+
             Horizontal -> validateHorizontalScroller(
                 offset = offset,
                 width = mainAxis,
@@ -1374,4 +1443,10 @@
             Size(size.width + inflate * 2, size.height + inflate * 2)
         )
     }
+
+    private class CountMeasureModifier(val onRemeasure: () -> Unit) : OnRemeasuredModifier {
+        override fun onRemeasured(size: IntSize) {
+            onRemeasure.invoke()
+        }
+    }
 }
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateNonGestureScrollingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateNonGestureScrollingTest.kt
index 58fcbec..722fb27 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateNonGestureScrollingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateNonGestureScrollingTest.kt
@@ -18,9 +18,11 @@
 
 import androidx.compose.foundation.AutoTestFrameClock
 import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.layout.onSizeChanged
@@ -147,6 +149,49 @@
     }
 
     @Test
+    fun currentPage_pagerWithKeys_shouldBeTheSameAfterDatasetUpdate() {
+        // Arrange
+        class Data(val id: Int, val item: String)
+
+        val data = mutableListOf(
+            Data(3, "A"),
+            Data(4, "B"),
+            Data(5, "C")
+        )
+
+        val extraData = mutableListOf(
+            Data(0, "D"),
+            Data(1, "E"),
+            Data(2, "F")
+        )
+
+        val dataset = mutableStateOf<List<Data>>(data)
+
+        createPager(
+            modifier = Modifier.fillMaxSize(),
+            initialPage = 1,
+            key = { dataset.value[it].id },
+            pageCount = {
+                dataset.value.size
+            }, pageContent = {
+                val item = dataset.value[it]
+                Box(modifier = Modifier.fillMaxSize().testTag(item.item))
+            })
+
+        Truth.assertThat(dataset.value[pagerState.currentPage].item).isEqualTo("B")
+
+        rule.runOnIdle {
+            dataset.value = extraData + data // add new data
+        }
+
+        rule.waitForIdle()
+        Truth.assertThat(pagerState.pageCount).isEqualTo(6) // all data is present
+        rule.onNodeWithTag("B").assertIsDisplayed() // scroll kept
+        Truth.assertThat(pagerState.currentPage).isEqualTo(4)
+        Truth.assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f)
+    }
+
+    @Test
     fun calculatePageCountOffset_shouldBeBasedOnCurrentPage() {
         val pageToOffsetCalculations = mutableMapOf<Int, Float>()
         createPager(modifier = Modifier.fillMaxSize(), pageSize = { PageSize.Fixed(20.dp) }) {
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/BasicTooltip.android.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/BasicTooltip.android.kt
new file mode 100644
index 0000000..56551fc
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/BasicTooltip.android.kt
@@ -0,0 +1,216 @@
+/*
+ * Copyright 2023 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.foundation
+
+import androidx.compose.foundation.gestures.awaitEachGesture
+import androidx.compose.foundation.gestures.awaitFirstDown
+import androidx.compose.foundation.gestures.waitForUpOrCancellation
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.PointerEventTimeoutCancellationException
+import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.PointerType
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.LiveRegionMode
+import androidx.compose.ui.semantics.liveRegion
+import androidx.compose.ui.semantics.onLongClick
+import androidx.compose.ui.semantics.paneTitle
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.window.Popup
+import androidx.compose.ui.window.PopupPositionProvider
+import androidx.compose.ui.window.PopupProperties
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * BasicTooltipBox that wraps a composable with a tooltip.
+ *
+ * Tooltip that provides a descriptive message for an anchor.
+ * It can be used to call the users attention to the anchor.
+ *
+ * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip
+ * relative to the anchor content.
+ * @param tooltip the composable that will be used to populate the tooltip's content.
+ * @param state handles the state of the tooltip's visibility.
+ * @param modifier the [Modifier] to be applied to this BasicTooltipBox.
+ * @param focusable [Boolean] that determines if the tooltip is focusable. When true,
+ * the tooltip will consume touch events while it's shown and will have accessibility
+ * focus move to the first element of the component. When false, the tooltip
+ * won't consume touch events while it's shown but assistive-tech users will need
+ * to swipe or drag to get to the first element of the component.
+ * @param enableUserInput [Boolean] which determines if this BasicTooltipBox will handle
+ * long press and mouse hover to trigger the tooltip through the state provided.
+ * @param content the composable that the tooltip will anchor to.
+ */
+@Composable
+actual fun BasicTooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: BasicTooltipState,
+    modifier: Modifier,
+    focusable: Boolean,
+    enableUserInput: Boolean,
+    content: @Composable () -> Unit
+) {
+    val scope = rememberCoroutineScope()
+    Box {
+        if (state.isVisible) {
+            TooltipPopup(
+                positionProvider = positionProvider,
+                state = state,
+                scope = scope,
+                focusable = focusable,
+                content = tooltip
+            )
+        }
+
+        WrappedAnchor(
+            enableUserInput = enableUserInput,
+            state = state,
+            modifier = modifier,
+            content = content
+        )
+    }
+
+    DisposableEffect(state) {
+        onDispose { state.onDispose() }
+    }
+}
+
+@Composable
+private fun WrappedAnchor(
+    enableUserInput: Boolean,
+    state: BasicTooltipState,
+    modifier: Modifier = Modifier,
+    content: @Composable () -> Unit
+) {
+    val scope = rememberCoroutineScope()
+    val longPressLabel = stringResource(R.string.tooltip_label)
+    Box(modifier = modifier
+            .handleGestures(enableUserInput, state)
+            .anchorSemantics(longPressLabel, enableUserInput, state, scope)
+    ) { content() }
+}
+
+@Composable
+private fun TooltipPopup(
+    positionProvider: PopupPositionProvider,
+    state: BasicTooltipState,
+    scope: CoroutineScope,
+    focusable: Boolean,
+    content: @Composable () -> Unit
+) {
+    val tooltipDescription = stringResource(R.string.tooltip_description)
+    Popup(
+        popupPositionProvider = positionProvider,
+        onDismissRequest = {
+            if (state.isVisible) {
+                scope.launch { state.dismiss() }
+            }
+        },
+        properties = PopupProperties(focusable = focusable)
+    ) {
+        Box(
+            modifier = Modifier.semantics {
+                liveRegion = LiveRegionMode.Assertive
+                paneTitle = tooltipDescription
+            }
+        ) { content() }
+    }
+}
+
+private fun Modifier.handleGestures(
+    enabled: Boolean,
+    state: BasicTooltipState
+): Modifier =
+    if (enabled) {
+        this.pointerInput(state) {
+                coroutineScope {
+                    awaitEachGesture {
+                        val longPressTimeout = viewConfiguration.longPressTimeoutMillis
+                        val pass = PointerEventPass.Initial
+
+                        // wait for the first down press
+                        val inputType = awaitFirstDown(pass = pass).type
+
+                        if (inputType == PointerType.Touch || inputType == PointerType.Stylus) {
+                            try {
+                                // listen to if there is up gesture
+                                // within the longPressTimeout limit
+                                withTimeout(longPressTimeout) {
+                                    waitForUpOrCancellation(pass = pass)
+                                }
+                            } catch (_: PointerEventTimeoutCancellationException) {
+                                // handle long press - Show the tooltip
+                                launch { state.show(MutatePriority.UserInput) }
+
+                                // consume the children's click handling
+                                val changes = awaitPointerEvent(pass = pass).changes
+                                for (i in 0 until changes.size) { changes[i].consume() }
+                            }
+                        }
+                    }
+                }
+            }
+            .pointerInput(state) {
+                coroutineScope {
+                    awaitPointerEventScope {
+                        val pass = PointerEventPass.Main
+
+                        while (true) {
+                            val event = awaitPointerEvent(pass)
+                            val inputType = event.changes[0].type
+                            if (inputType == PointerType.Mouse) {
+                                when (event.type) {
+                                    PointerEventType.Enter -> {
+                                        launch { state.show(MutatePriority.UserInput) }
+                                    }
+
+                                    PointerEventType.Exit -> {
+                                        state.dismiss()
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+    } else this
+
+private fun Modifier.anchorSemantics(
+    label: String,
+    enabled: Boolean,
+    state: BasicTooltipState,
+    scope: CoroutineScope
+): Modifier =
+    if (enabled) {
+        this.semantics(mergeDescendants = true) {
+                onLongClick(
+                    label = label,
+                    action = {
+                        scope.launch { state.show() }
+                        true
+                    }
+                )
+            }
+    } else this
diff --git a/compose/foundation/foundation/src/androidMain/res/values/strings.xml b/compose/foundation/foundation/src/androidMain/res/values/strings.xml
new file mode 100644
index 0000000..cb6255c
--- /dev/null
+++ b/compose/foundation/foundation/src/androidMain/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2023 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.
+  -->
+
+<resources>
+    <string name="tooltip_description">tooltip</string>
+    <string name="tooltip_label">show tooltip</string>
+</resources>
\ No newline at end of file
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BasicTooltip.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BasicTooltip.kt
new file mode 100644
index 0000000..26deed4
--- /dev/null
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/BasicTooltip.kt
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2023 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.foundation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.window.PopupPositionProvider
+import kotlinx.coroutines.CancellableContinuation
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withTimeout
+
+/**
+ * BasicTooltipBox that wraps a composable with a tooltip.
+ *
+ * Tooltip that provides a descriptive message for an anchor.
+ * It can be used to call the users attention to the anchor.
+ *
+ * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip
+ * relative to the anchor content.
+ * @param tooltip the composable that will be used to populate the tooltip's content.
+ * @param state handles the state of the tooltip's visibility.
+ * @param modifier the [Modifier] to be applied to this BasicTooltipBox.
+ * @param focusable [Boolean] that determines if the tooltip is focusable. When true,
+ * the tooltip will consume touch events while it's shown and will have accessibility
+ * focus move to the first element of the component. When false, the tooltip
+ * won't consume touch events while it's shown but assistive-tech users will need
+ * to swipe or drag to get to the first element of the component.
+ * @param enableUserInput [Boolean] which determines if this BasicTooltipBox will handle
+ * long press and mouse hover to trigger the tooltip through the state provided.
+ * @param content the composable that the tooltip will anchor to.
+ */
+@Composable
+expect fun BasicTooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: BasicTooltipState,
+    modifier: Modifier = Modifier,
+    focusable: Boolean = true,
+    enableUserInput: Boolean = true,
+    content: @Composable () -> Unit
+)
+
+/**
+ * Create and remember the default [BasicTooltipState].
+ *
+ * @param initialIsVisible the initial value for the tooltip's visibility when drawn.
+ * @param isPersistent [Boolean] that determines if the tooltip associated with this
+ * will be persistent or not. If isPersistent is true, then the tooltip will
+ * only be dismissed when the user clicks outside the bounds of the tooltip or if
+ * [BasicTooltipState.dismiss] is called. When isPersistent is false, the tooltip will dismiss after
+ * a short duration. Ideally, this should be set to true when there is actionable content
+ * being displayed within a tooltip.
+ * @param mutatorMutex [MutatorMutex] used to ensure that for all of the tooltips associated
+ * with the mutator mutex, only one will be shown on the screen at any time.
+ */
+@Composable
+fun rememberBasicTooltipState(
+    initialIsVisible: Boolean = false,
+    isPersistent: Boolean = true,
+    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
+): BasicTooltipState =
+    rememberSaveable(
+        isPersistent,
+        mutatorMutex,
+        saver = BasicTooltipStateImpl.Saver
+    ) {
+        BasicTooltipStateImpl(
+            initialIsVisible = initialIsVisible,
+            isPersistent = isPersistent,
+            mutatorMutex = mutatorMutex
+        )
+    }
+
+/**
+ * Constructor extension function for [BasicTooltipState]
+ *
+ * @param initialIsVisible the initial value for the tooltip's visibility when drawn.
+ * @param isPersistent [Boolean] that determines if the tooltip associated with this
+ * will be persistent or not. If isPersistent is true, then the tooltip will
+ * only be dismissed when the user clicks outside the bounds of the tooltip or if
+ * [BasicTooltipState.dismiss] is called. When isPersistent is false, the tooltip will dismiss after
+ * a short duration. Ideally, this should be set to true when there is actionable content
+ * being displayed within a tooltip.
+ * @param mutatorMutex [MutatorMutex] used to ensure that for all of the tooltips associated
+ * with the mutator mutex, only one will be shown on the screen at any time.
+ */
+fun BasicTooltipState(
+    initialIsVisible: Boolean = false,
+    isPersistent: Boolean = true,
+    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
+): BasicTooltipState =
+    BasicTooltipStateImpl(
+        initialIsVisible = initialIsVisible,
+        isPersistent = isPersistent,
+        mutatorMutex = mutatorMutex
+    )
+
+@Stable
+private class BasicTooltipStateImpl(
+    initialIsVisible: Boolean,
+    override val isPersistent: Boolean,
+    private val mutatorMutex: MutatorMutex
+) : BasicTooltipState {
+    override var isVisible by mutableStateOf(initialIsVisible)
+
+    /**
+     * continuation used to clean up
+     */
+    private var job: (CancellableContinuation<Unit>)? = null
+
+    /**
+     * Show the tooltip associated with the current [BasicTooltipState].
+     * When this method is called, all of the other tooltips associated
+     * with [mutatorMutex] will be dismissed.
+     *
+     * @param mutatePriority [MutatePriority] to be used with [mutatorMutex].
+     */
+    override suspend fun show(
+        mutatePriority: MutatePriority
+    ) {
+        val cancellableShow: suspend () -> Unit = {
+            suspendCancellableCoroutine { continuation ->
+                isVisible = true
+                job = continuation
+            }
+        }
+
+        // Show associated tooltip for [TooltipDuration] amount of time
+        // or until tooltip is explicitly dismissed depending on [isPersistent].
+        mutatorMutex.mutate(mutatePriority) {
+            try {
+                if (isPersistent) {
+                    cancellableShow()
+                } else {
+                    withTimeout(BasicTooltipDefaults.TooltipDuration) {
+                        cancellableShow()
+                    }
+                }
+            } finally {
+                // timeout or cancellation has occurred
+                // and we close out the current tooltip.
+                isVisible = false
+            }
+        }
+    }
+
+    /**
+     * Dismiss the tooltip associated with
+     * this [BasicTooltipState] if it's currently being shown.
+     */
+    override fun dismiss() {
+        isVisible = false
+    }
+
+    /**
+     * Cleans up [mutatorMutex] when the tooltip associated
+     * with this state leaves Composition.
+     */
+    override fun onDispose() {
+        job?.cancel()
+    }
+
+    companion object {
+        /**
+         * The default [Saver] implementation for [BasicTooltipStateImpl].
+         */
+        val Saver = Saver<BasicTooltipStateImpl, Any>(
+            save = {
+                   listOf(
+                       it.isVisible,
+                       it.isPersistent,
+                       it.mutatorMutex
+                   )
+            },
+            restore = {
+                val (isVisible, isPersistent, mutatorMutex) = it as List<*>
+                BasicTooltipStateImpl(
+                    initialIsVisible = isVisible as Boolean,
+                    isPersistent = isPersistent as Boolean,
+                    mutatorMutex = mutatorMutex as MutatorMutex,
+                )
+            }
+        )
+    }
+}
+
+/**
+ * The state that is associated with an instance of a tooltip.
+ * Each instance of tooltips should have its own [BasicTooltipState].
+ */
+@Stable
+interface BasicTooltipState {
+    /**
+     * [Boolean] that indicates if the tooltip is currently being shown or not.
+     */
+    val isVisible: Boolean
+
+    /**
+     * [Boolean] that determines if the tooltip associated with this
+     * will be persistent or not. If isPersistent is true, then the tooltip will
+     * only be dismissed when the user clicks outside the bounds of the tooltip or if
+     * [BasicTooltipState.dismiss] is called. When isPersistent is false, the tooltip will
+     * dismiss after a short duration. Ideally, this should be set to true when there
+     * is actionable content being displayed within a tooltip.
+     */
+    val isPersistent: Boolean
+
+    /**
+     * Show the tooltip associated with the current [BasicTooltipState].
+     * When this method is called all of the other tooltips currently
+     * being shown will dismiss.
+     *
+     * @param mutatePriority [MutatePriority] to be used.
+     */
+    suspend fun show(mutatePriority: MutatePriority = MutatePriority.Default)
+
+    /**
+     * Dismiss the tooltip associated with
+     * this [BasicTooltipState] if it's currently being shown.
+     */
+    fun dismiss()
+
+    /**
+     * Clean up when the this state leaves Composition.
+     */
+    fun onDispose()
+}
+
+/**
+ * BasicTooltip defaults that contain default values for tooltips created.
+ */
+object BasicTooltipDefaults {
+    /**
+     * The global/default [MutatorMutex] used to sync Tooltips.
+     */
+    val GlobalMutatorMutex: MutatorMutex = MutatorMutex()
+
+    /**
+     * The default duration, in milliseconds, that non-persistent tooltips
+     * will show on the screen before dismissing.
+     */
+    const val TooltipDuration = 1500L
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
index e14ccc1..f4825f2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/Scroll.kt
@@ -38,6 +38,7 @@
 import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.layout.IntrinsicMeasurable
@@ -105,8 +106,10 @@
         get() = _maxValueState.intValue
         internal set(newMax) {
             _maxValueState.intValue = newMax
-            if (value > newMax) {
-                value = newMax
+            Snapshot.withoutReadObservation {
+                if (value > newMax) {
+                    value = newMax
+                }
             }
         }
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
index 7a08add..4b6c4856 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/gestures/Draggable.kt
@@ -42,10 +42,13 @@
 import androidx.compose.ui.input.pointer.positionChangeIgnoreConsumed
 import androidx.compose.ui.input.pointer.util.VelocityTracker
 import androidx.compose.ui.input.pointer.util.addPointerInputChange
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
 import androidx.compose.ui.node.DelegatingNode
 import androidx.compose.ui.node.ModifierNodeElement
 import androidx.compose.ui.node.PointerInputModifierNode
+import androidx.compose.ui.node.currentValueOf
 import androidx.compose.ui.platform.InspectorInfo
+import androidx.compose.ui.platform.LocalViewConfiguration
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.Velocity
 import kotlin.coroutines.cancellation.CancellationException
@@ -294,7 +297,7 @@
     private var onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
     private var onDragStopped: suspend CoroutineScope.(velocity: Velocity) -> Unit,
     private var reverseDirection: Boolean
-) : DelegatingNode(), PointerInputModifierNode {
+) : DelegatingNode(), PointerInputModifierNode, CompositionLocalConsumerModifierNode {
     // Use wrapper lambdas here to make sure that if these properties are updated while we suspend,
     // we point to the new reference when we invoke them.
     private val _canDrag: (PointerInputChange) -> Boolean = { canDrag(it) }
@@ -360,8 +363,12 @@
                                 isDragSuccessful = false
                                 if (!isActive) throw cancellation
                             } finally {
+                                val maximumVelocity = currentValueOf(LocalViewConfiguration)
+                                    .maximumFlingVelocity.toFloat()
                                 val event = if (isDragSuccessful) {
-                                    val velocity = velocityTracker.calculateVelocity()
+                                    val velocity = velocityTracker.calculateVelocity(
+                                        Velocity(maximumVelocity, maximumVelocity)
+                                    )
                                     velocityTracker.resetTracking()
                                     DragStopped(velocity * if (reverseDirection) -1f else 1f)
                                 } else {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
index a9a34f3..30d025e 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
@@ -96,7 +96,8 @@
  * @param reverseLayout reverse the direction of scrolling and layout.
  * @param key a stable and unique key representing the item. When you specify the key the scroll
  * position will be maintained based on the key, which means if you add/remove items before the
- * current visible item the item with the given key will be kept as the first visible one.
+ * current visible item the item with the given key will be kept as the first visible one. If null
+ * is passed the position in the list will represent the key.
  * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager]
  * behaves with nested lists. The default behavior will see [Pager] to consume all nested deltas.
  * @param pageContent This Pager's page Composable.
@@ -140,115 +141,6 @@
 }
 
 /**
- * A Pager that scrolls horizontally. Pages are lazily placed in accordance to the available
- * viewport size. By definition, pages in a [Pager] have the same size, defined by [pageSize] and
- * use a snap animation (provided by [flingBehavior] to scroll pages into a specific position). You
- * can use [beyondBoundsPageCount] to place more pages before and after the visible pages.
- *
- * If you need snapping with pages of different size, you can use a [SnapFlingBehavior] with a
- * [SnapLayoutInfoProvider] adapted to a LazyList.
- * @see androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider for the implementation
- * of a [SnapLayoutInfoProvider] that uses [androidx.compose.foundation.lazy.LazyListState].
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.SimpleHorizontalPagerSample
- *
- * @param pageCount The number of pages this Pager will contain
- * @param modifier A modifier instance to be applied to this Pager outer layout
- * @param state The state to control this pager
- * @param contentPadding a padding around the whole content. This will add padding for the
- * content after it has been clipped, which is not possible via [modifier] param. You can use it
- * to add a padding before the first page or after the last one. Use [pageSpacing] to add spacing
- * between the pages.
- * @param pageSize Use this to change how the pages will look like inside this pager.
- * @param beyondBoundsPageCount Pages to compose and layout before and after the list of visible
- * pages. Note: Be aware that using a large value for [beyondBoundsPageCount] will cause a lot of
- * pages to be composed, measured and placed which will defeat the purpose of using lazy loading.
- * This should be used as an optimization to pre-load a couple of pages before and after the visible
- * ones. This does not include the pages automatically composed and laid out by the pre-fetcher in
- *  * the direction of the scroll during scroll events.
- * @param pageSpacing The amount of space to be used to separate the pages in this Pager
- * @param verticalAlignment How pages are aligned vertically in this Pager.
- * @param flingBehavior The [FlingBehavior] to be used for post scroll gestures.
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using [PagerState.scroll] even when it is
- * disabled.
- * @param reverseLayout reverse the direction of scrolling and layout.
- * @param key a stable and unique key representing the page. When you specify the key the scroll
- * position will be maintained based on the key, which means if you add/remove pages before the
- * current visible page the page with the given key will be kept as the first visible one.
- * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager]
- * behaves with nested lists. The default behavior will see [Pager] to consume all nested deltas.
- * @param pageContent This Pager's page Composable.
- */
-@Deprecated(
-    "Please use the overload without pageCount. pageCount should be provided " +
-        "through PagerState.",
-    ReplaceWith(
-        """HorizontalPager(
-            modifier = modifier,
-            state = state,
-            pageSpacing = pageSpacing,
-            horizontalAlignment = horizontalAlignment,
-            userScrollEnabled = userScrollEnabled,
-            reverseLayout = reverseLayout,
-            contentPadding = contentPadding,
-            beyondBoundsPageCount = beyondBoundsPageCount,
-            pageSize = pageSize,
-            flingBehavior = flingBehavior,
-            key = key,
-            pageNestedScrollConnection = pageNestedScrollConnection,
-            pageContent = pageContent
-        )""",
-        imports = arrayOf(
-            "androidx.compose.foundation.gestures.Orientation",
-            "androidx.compose.foundation.layout.PaddingValues",
-            "androidx.compose.foundation.pager.PageSize",
-            "androidx.compose.foundation.pager.PagerDefaults"
-        ),
-    ),
-    level = DeprecationLevel.ERROR
-)
-@Composable
-@ExperimentalFoundationApi
-fun HorizontalPager(
-    pageCount: Int,
-    modifier: Modifier = Modifier,
-    state: PagerState = rememberPagerState { pageCount },
-    contentPadding: PaddingValues = PaddingValues(0.dp),
-    pageSize: PageSize = PageSize.Fill,
-    beyondBoundsPageCount: Int = PagerDefaults.BeyondBoundsPageCount,
-    pageSpacing: Dp = 0.dp,
-    verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
-    flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state),
-    userScrollEnabled: Boolean = true,
-    reverseLayout: Boolean = false,
-    key: ((index: Int) -> Any)? = null,
-    pageNestedScrollConnection: NestedScrollConnection = remember(state) {
-        PagerDefaults.pageNestedScrollConnection(state, Orientation.Horizontal)
-    },
-    pageContent: @Composable PagerScope.(page: Int) -> Unit
-) {
-    Pager(
-        state = state,
-        modifier = modifier,
-        contentPadding = contentPadding,
-        pageSize = pageSize,
-        beyondBoundsPageCount = beyondBoundsPageCount,
-        pageSpacing = pageSpacing,
-        orientation = Orientation.Horizontal,
-        verticalAlignment = verticalAlignment,
-        horizontalAlignment = Alignment.CenterHorizontally,
-        flingBehavior = flingBehavior,
-        userScrollEnabled = userScrollEnabled,
-        reverseLayout = reverseLayout,
-        key = key,
-        pageNestedScrollConnection = pageNestedScrollConnection,
-        pageContent = pageContent
-    )
-}
-
-/**
  * A Pager that scrolls vertically. Pages are lazily placed in accordance to the available
  * viewport size. By definition, pages in a [Pager] have the same size, defined by [pageSize] and
  * use a snap animation (provided by [flingBehavior] to scroll pages into a specific position). You
@@ -284,7 +176,8 @@
  * @param reverseLayout reverse the direction of scrolling and layout.
  * @param key a stable and unique key representing the item. When you specify the key the scroll
  * position will be maintained based on the key, which means if you add/remove items before the
- * current visible item the item with the given key will be kept as the first visible one.
+ * current visible item the item with the given key will be kept as the first visible one. If null
+ * is passed the position in the list will represent the key.
  * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager] behaves
  * with nested lists. The default behavior will see [Pager] to consume all nested deltas.
  * @param pageContent This Pager's page Composable.
@@ -328,114 +221,6 @@
 }
 
 /**
- * A Pager that scrolls vertically. Pages are lazily placed in accordance to the available
- * viewport size. By definition, pages in a [Pager] have the same size, defined by [pageSize] and
- * use a snap animation (provided by [flingBehavior] to scroll pages into a specific position). You
- * can use [beyondBoundsPageCount] to place more pages before and after the visible pages.
- *
- * If you need snapping with pages of different size, you can use a [SnapFlingBehavior] with a
- * [SnapLayoutInfoProvider] adapted to a LazyList.
- * @see androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider for the implementation
- * of a [SnapLayoutInfoProvider] that uses [androidx.compose.foundation.lazy.LazyListState].
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.SimpleVerticalPagerSample
- *
- * @param pageCount The number of pages this Pager will contain
- * @param modifier A modifier instance to be apply to this Pager outer layout
- * @param state The state to control this pager
- * @param contentPadding a padding around the whole content. This will add padding for the
- * content after it has been clipped, which is not possible via [modifier] param. You can use it
- * to add a padding before the first page or after the last one. Use [pageSpacing] to add spacing
- * between the pages.
- * @param pageSize Use this to change how the pages will look like inside this pager.
- * @param beyondBoundsPageCount Pages to compose and layout before and after the list of visible
- * pages. Note: Be aware that using a large value for [beyondBoundsPageCount] will cause a lot of
- * pages to be composed, measured and placed which will defeat the purpose of using lazy loading.
- * This should be used as an optimization to pre-load a couple of pages before and after the visible
- * ones. This does not include the pages automatically composed and laid out by the pre-fetcher in
- *  * the direction of the scroll during scroll events.
- * @param pageSpacing The amount of space to be used to separate the pages in this Pager
- * @param horizontalAlignment How pages are aligned horizontally in this Pager.
- * @param flingBehavior The [FlingBehavior] to be used for post scroll gestures.
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using [PagerState.scroll] even when it is
- * disabled.
- * @param reverseLayout reverse the direction of scrolling and layout.
- * @param key a stable and unique key representing the page. When you specify the key the scroll
- * position will be maintained based on the key, which means if you add/remove pages before the
- * current visible page the page with the given key will be kept as the first visible one.
- * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager] behaves
- * with nested lists. The default behavior will see [Pager] to consume all nested deltas.
- * @param pageContent This Pager's page Composable.
- */
-@Deprecated(
-    "Please use the overload without pageCount. pageCount should be provided " +
-        "through PagerState.", ReplaceWith(
-        """VerticalPager(
-            modifier = modifier,
-            state = state,
-            pageSpacing = pageSpacing,
-            horizontalAlignment = horizontalAlignment,
-            userScrollEnabled = userScrollEnabled,
-            reverseLayout = reverseLayout,
-            contentPadding = contentPadding,
-            beyondBoundsPageCount = beyondBoundsPageCount,
-            pageSize = pageSize,
-            flingBehavior = flingBehavior,
-            key = key,
-            pageNestedScrollConnection = pageNestedScrollConnection,
-            pageContent = pageContent
-        )""",
-        imports = arrayOf(
-            "androidx.compose.foundation.gestures.Orientation",
-            "androidx.compose.foundation.layout.PaddingValues",
-            "androidx.compose.foundation.pager.PageSize",
-            "androidx.compose.foundation.pager.PagerDefaults"
-        )
-    ),
-    level = DeprecationLevel.ERROR
-)
-@Composable
-@ExperimentalFoundationApi
-fun VerticalPager(
-    pageCount: Int,
-    modifier: Modifier = Modifier,
-    state: PagerState = rememberPagerState { pageCount },
-    contentPadding: PaddingValues = PaddingValues(0.dp),
-    pageSize: PageSize = PageSize.Fill,
-    beyondBoundsPageCount: Int = PagerDefaults.BeyondBoundsPageCount,
-    pageSpacing: Dp = 0.dp,
-    horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
-    flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state),
-    userScrollEnabled: Boolean = true,
-    reverseLayout: Boolean = false,
-    key: ((index: Int) -> Any)? = null,
-    pageNestedScrollConnection: NestedScrollConnection = remember(state) {
-        PagerDefaults.pageNestedScrollConnection(state, Orientation.Vertical)
-    },
-    pageContent: @Composable PagerScope.(page: Int) -> Unit
-) {
-    Pager(
-        state = state,
-        modifier = modifier,
-        contentPadding = contentPadding,
-        pageSize = pageSize,
-        beyondBoundsPageCount = beyondBoundsPageCount,
-        pageSpacing = pageSpacing,
-        orientation = Orientation.Vertical,
-        verticalAlignment = Alignment.CenterVertically,
-        horizontalAlignment = horizontalAlignment,
-        flingBehavior = flingBehavior,
-        userScrollEnabled = userScrollEnabled,
-        reverseLayout = reverseLayout,
-        key = key,
-        pageNestedScrollConnection = pageNestedScrollConnection,
-        pageContent = pageContent
-    )
-}
-
-/**
  * This is used to determine how Pages are laid out in [Pager]. By changing the size of the pages
  * one can change how many pages are shown.
  *
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
index b8e31dc..1c8676f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
@@ -138,11 +138,13 @@
                 pageAvailableSize
             }
         )
+        val itemProvider = itemProviderLambda()
 
         val firstVisiblePage: Int
         val firstVisiblePageOffset: Int
         Snapshot.withoutReadObservation {
-            firstVisiblePage = state.firstVisiblePage
+            firstVisiblePage =
+                state.matchScrollPositionWithKey(itemProvider, state.firstVisiblePage)
             firstVisiblePageOffset = if (state.layoutInfo == EmptyLayoutInfo) {
                 (state.initialPageOffsetFraction * pageAvailableSize).roundToInt()
             } else {
@@ -150,7 +152,6 @@
             }
         }
 
-        val itemProvider = itemProviderLambda()
         val pinnedPages = itemProvider.calculateLazyLayoutPinnedIndices(
             pinnedItemList = state.pinnedPages,
             beyondBoundsInfo = state.beyondBoundsInfo
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
index 03395ab..d5abf73 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerScrollPosition.kt
@@ -20,6 +20,7 @@
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.snapping.calculateDistanceToDesiredSnapPosition
 import androidx.compose.foundation.lazy.layout.LazyLayoutNearestRangeState
+import androidx.compose.foundation.lazy.layout.findIndexByKey
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.setValue
@@ -115,6 +116,18 @@
         lastKnownFirstPageKey = null
     }
 
+    fun matchPageWithKey(
+        itemProvider: PagerLazyLayoutItemProvider,
+        index: Int
+    ): Int {
+        val newIndex = itemProvider.findIndexByKey(lastKnownFirstPageKey, index)
+        if (index != newIndex) {
+            this.firstVisiblePage = newIndex
+            nearestRangeState.update(index)
+        }
+        return newIndex
+    }
+
     private fun update(index: Int, scrollOffset: Int) {
         require(index >= 0f) { "Index should be non-negative ($index)" }
         this.firstVisiblePage = index
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
index 58431d0..8efdab9 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
@@ -43,6 +43,7 @@
 import androidx.compose.runtime.saveable.listSaver
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.runtime.structuralEqualityPolicy
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.layout.Remeasurement
@@ -86,42 +87,6 @@
     }
 }
 
-/**
- * Creates and remember a [PagerState] to be used with a [Pager]
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.PagerWithStateSample
- *
- * @param initialPage The pager that should be shown first.
- * @param initialPageOffsetFraction The offset of the initial page as a fraction of the page size.
- * This should vary between -0.5 and 0.5 and indicates how to offset the initial page from the
- * snapped position.
- */
-@Deprecated(
-    "Please use the overload where you can provide a source of truth for the pageCount.",
-    ReplaceWith(
-        """rememberPagerState(
-                initialPage = initialPage,
-                initialPageOffsetFraction = initialPageOffsetFraction
-            ){
-                // provide pageCount
-            }"""
-    ), level = DeprecationLevel.ERROR
-)
-@ExperimentalFoundationApi
-@Composable
-fun rememberPagerState(
-    initialPage: Int = 0,
-    initialPageOffsetFraction: Float = 0f
-): PagerState {
-    return rememberSaveable(saver = PagerStateImpl.Saver) {
-        PagerStateImpl(
-            initialPage = initialPage,
-            initialPageOffsetFraction = initialPageOffsetFraction
-        ) { 0 }
-    }
-}
-
 @ExperimentalFoundationApi
 internal class PagerStateImpl(
     initialPage: Int,
@@ -638,6 +603,16 @@
         }
         return (currentPage - page) + currentPageOffsetFraction
     }
+
+    /**
+     * When the user provided custom keys for the pages we can try to detect when there were
+     * pages added or removed before our current page and keep this page as the current one
+     * given that its index has been changed.
+     */
+    internal fun matchScrollPositionWithKey(
+        itemProvider: PagerLazyLayoutItemProvider,
+        firstPageIndex: Int = Snapshot.withoutReadObservation { scrollPosition.firstVisiblePage }
+    ): Int = scrollPosition.matchPageWithKey(itemProvider, firstPageIndex)
 }
 
 @OptIn(ExperimentalFoundationApi::class)
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt
index 41c7433..4ec59e2 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/BasicTextField2.kt
@@ -452,7 +452,7 @@
         TextFieldSelectionState(
             textFieldState = state,
             textLayoutState = textLayoutState,
-            textEditFilter = inputTransformation,
+            inputTransformation = inputTransformation,
             density = density,
             editable = enabled && !readOnly,
             isFocused = isFocused
@@ -464,12 +464,14 @@
     SideEffect {
         // These properties are not backed by snapshot state, so they can't be updated directly in
         // composition.
-        textFieldSelectionState.hapticFeedBack = currentHapticFeedback
-        textFieldSelectionState.clipboardManager = currentClipboardManager
-        textFieldSelectionState.textToolbar = currentTextToolbar
-        textFieldSelectionState.textEditFilter = inputTransformation
-        textFieldSelectionState.density = density
-        textFieldSelectionState.editable = enabled && !readOnly
+        textFieldSelectionState.update(
+            hapticFeedBack = currentHapticFeedback,
+            clipboardManager = currentClipboardManager,
+            textToolbar = currentTextToolbar,
+            inputTransformation = inputTransformation,
+            density = density,
+            editable = enabled && !readOnly,
+        )
     }
 
     DisposableEffect(textFieldSelectionState) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/input/internal/selection/TextFieldSelectionState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/input/internal/selection/TextFieldSelectionState.kt
index 02b783d..7e75fa5 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/input/internal/selection/TextFieldSelectionState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/text2/input/internal/selection/TextFieldSelectionState.kt
@@ -71,30 +71,31 @@
 internal class TextFieldSelectionState(
     private val textFieldState: TextFieldState,
     private val textLayoutState: TextLayoutState,
-    var textEditFilter: InputTransformation?,
-    var density: Density,
-    var editable: Boolean,
+    private var inputTransformation: InputTransformation?,
+    private var density: Density,
+    private var editable: Boolean,
     var isFocused: Boolean
 ) {
     /**
      * [HapticFeedback] handle to perform haptic feedback.
      */
-    var hapticFeedBack: HapticFeedback? = null
+    private var hapticFeedBack: HapticFeedback? = null
 
     /**
      * [TextToolbar] to show floating toolbar(post-M) or primary toolbar(pre-M).
      */
-    var textToolbar: TextToolbar? = null
+    private var textToolbar: TextToolbar? = null
 
     /**
      * [ClipboardManager] to perform clipboard features.
      */
-    var clipboardManager: ClipboardManager? = null
+    private var clipboardManager: ClipboardManager? = null
 
     /**
      * Whether user is interacting with the UI in touch mode.
      */
     var isInTouchMode: Boolean by mutableStateOf(true)
+        private set
 
     /**
      * The offset of visible bounds when dragging is started by a cursor or a selection handle.
@@ -251,6 +252,22 @@
         getSelectionHandleState(isStartHandle = false)
     }
 
+    fun update(
+        hapticFeedBack: HapticFeedback,
+        clipboardManager: ClipboardManager,
+        textToolbar: TextToolbar,
+        inputTransformation: InputTransformation?,
+        density: Density,
+        editable: Boolean,
+    ) {
+        this.hapticFeedBack = hapticFeedBack
+        this.clipboardManager = clipboardManager
+        this.textToolbar = textToolbar
+        this.inputTransformation = inputTransformation
+        this.density = density
+        this.editable = editable
+    }
+
     /**
      * Implements the complete set of gestures supported by the cursor handle.
      */
@@ -1047,7 +1064,7 @@
      * Edits the TextFieldState content with a filter applied if available.
      */
     private fun editAsUser(block: EditingBuffer.() -> Unit) {
-        textFieldState.editAsUser(textEditFilter, block = block)
+        textFieldState.editAsUser(inputTransformation, block = block)
     }
 
     private fun hideTextToolbar() {
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt
new file mode 100644
index 0000000..b09eeba
--- /dev/null
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/BasicTooltip.desktop.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 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.foundation
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.window.Popup
+import androidx.compose.ui.window.PopupPositionProvider
+
+/**
+ * BasicTooltipBox that wraps a composable with a tooltip.
+ *
+ * Tooltip that provides a descriptive message for an anchor.
+ * It can be used to call the users attention to the anchor.
+ *
+ * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip
+ * relative to the anchor content.
+ * @param tooltip the composable that will be used to populate the tooltip's content.
+ * @param state handles the state of the tooltip's visibility.
+ * @param modifier the [Modifier] to be applied to this BasicTooltipBox.
+ * @param focusable [Boolean] that determines if the tooltip is focusable. When true,
+ * the tooltip will consume touch events while it's shown and will have accessibility
+ * focus move to the first element of the component. When false, the tooltip
+ * won't consume touch events while it's shown but assistive-tech users will need
+ * to swipe or drag to get to the first element of the component.
+ * @param enableUserInput [Boolean] which determines if this BasicTooltipBox will handle
+ * long press and mouse hover to trigger the tooltip through the state provided.
+ * @param content the composable that the tooltip will anchor to.
+ */
+@Composable
+actual fun BasicTooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: BasicTooltipState,
+    modifier: Modifier,
+    focusable: Boolean,
+    enableUserInput: Boolean,
+    content: @Composable () -> Unit
+) {
+    Box(modifier = modifier) {
+        content()
+        if (state.isVisible) {
+            Popup(
+                popupPositionProvider = positionProvider,
+                onDismissRequest = { state.dismiss() },
+                focusable = focusable
+            ) { tooltip() }
+        }
+    }
+}
diff --git a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt
index 4b9d393..9fa6d90 100644
--- a/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt
+++ b/compose/foundation/foundation/src/desktopMain/kotlin/androidx/compose/foundation/TooltipArea.desktop.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.foundation
 
-import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -38,7 +37,6 @@
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntRect
 import androidx.compose.ui.unit.dp
-import androidx.compose.ui.window.Popup
 import androidx.compose.ui.window.PopupPositionProvider
 import androidx.compose.ui.window.rememberComponentRectPositionProvider
 import androidx.compose.ui.window.rememberCursorPositionProvider
@@ -102,7 +100,7 @@
 ) {
     val mousePosition = remember { mutableStateOf(IntOffset.Zero) }
     var parentBounds by remember { mutableStateOf(IntRect.Zero) }
-    var isVisible by remember { mutableStateOf(false) }
+    val state = rememberBasicTooltipState(initialIsVisible = false)
     val scope = rememberCoroutineScope()
     var job: Job? by remember { mutableStateOf(null) }
 
@@ -110,16 +108,18 @@
         job?.cancel()
         job = scope.launch {
             delay(delayMillis.toLong())
-            isVisible = true
+            state.show()
         }
     }
 
     fun hide() {
         job?.cancel()
-        isVisible = false
+        state.dismiss()
     }
 
-    Box(
+    BasicTooltipBox(
+        positionProvider = tooltipPlacement.positionProvider(),
+        tooltip = tooltip,
         modifier = modifier
             .onGloballyPositioned { coordinates ->
                 val size = coordinates.size
@@ -129,6 +129,9 @@
                 )
                 parentBounds = IntRect(position, size)
             }
+            /**
+             * TODO: b/296850580 Figure out touch input story for desktop
+             */
             .pointerInput(Unit) {
                 awaitPointerEventScope {
                     while (true) {
@@ -141,9 +144,11 @@
                                     position.y.toInt() + parentBounds.top
                                 )
                             }
+
                             PointerEventType.Enter -> {
                                 startShowing()
                             }
+
                             PointerEventType.Exit -> {
                                 hide()
                             }
@@ -155,19 +160,12 @@
                 detectDown {
                     hide()
                 }
-            }
-    ) {
-        content()
-        if (isVisible) {
-            @OptIn(ExperimentalFoundationApi::class)
-            Popup(
-                popupPositionProvider = tooltipPlacement.positionProvider(),
-                onDismissRequest = { isVisible = false }
-            ) {
-                tooltip()
-            }
-        }
-    }
+            },
+        focusable = false,
+        enableUserInput = true,
+        state = state,
+        content = content
+    )
 }
 
 private suspend fun PointerInputScope.detectDown(onDown: (Offset) -> Unit) {
diff --git a/compose/material/material-icons-extended-outlined/build.gradle b/compose/material/material-icons-extended-outlined/build.gradle
deleted file mode 100644
index 5933def..0000000
--- a/compose/material/material-icons-extended-outlined/build.gradle
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply from: "../material-icons-extended/generate.gradle"
-
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
diff --git a/compose/material/material-icons-extended-rounded/build.gradle b/compose/material/material-icons-extended-rounded/build.gradle
deleted file mode 100644
index 5933def..0000000
--- a/compose/material/material-icons-extended-rounded/build.gradle
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply from: "../material-icons-extended/generate.gradle"
-
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
diff --git a/compose/material/material-icons-extended-sharp/build.gradle b/compose/material/material-icons-extended-sharp/build.gradle
deleted file mode 100644
index 5933def..0000000
--- a/compose/material/material-icons-extended-sharp/build.gradle
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply from: "../material-icons-extended/generate.gradle"
-
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
diff --git a/compose/material/material-icons-extended-twotone/build.gradle b/compose/material/material-icons-extended-twotone/build.gradle
deleted file mode 100644
index 5933def..0000000
--- a/compose/material/material-icons-extended-twotone/build.gradle
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-apply from: "../material-icons-extended/generate.gradle"
-
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
diff --git a/compose/material/material-icons-extended/README.md b/compose/material/material-icons-extended/README.md
deleted file mode 100644
index 21d3209..0000000
--- a/compose/material/material-icons-extended/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-This project provides the Compose Material Design extended icons
-
-To keep Kotlin compilation times down, each theme is compiled in its own Gradle project and then the resulting .class files are merged back into the output of this project
-
-Hopefully we can revert this when parallel compilation is supported:
-https://youtrack.jetbrains.com/issue/KT-46085
-
-See https://issuetracker.google.com/issues/178207305 and https://issuetracker.google.com/issues/184959797 for more information
diff --git a/compose/material/material-icons-extended/build.gradle b/compose/material/material-icons-extended/build.gradle
index ddff520..e6002b6 100644
--- a/compose/material/material-icons-extended/build.gradle
+++ b/compose/material/material-icons-extended/build.gradle
@@ -33,8 +33,6 @@
         android
 )
 
-apply from: "shared-dependencies.gradle"
-
 androidXMultiplatform {
     android()
     if (desktopEnabled) desktop()
@@ -126,22 +124,6 @@
     }
 }
 
-configurations {
-    embedThemesDebug {
-        attributes {
-            attribute(iconExportAttr, "true")
-            attribute(iconBuildTypeAttr, "debug")
-        }
-    }
-    embedThemesRelease {
-        attributes {
-            attribute(iconExportAttr, "true")
-            attribute(iconBuildTypeAttr, "release")
-        }
-    }
-
-}
-
 IconGenerationTask.registerExtendedIconThemeProject(project, android)
 
 androidx {
diff --git a/compose/material/material-icons-extended/generate.gradle b/compose/material/material-icons-extended/generate.gradle
deleted file mode 100644
index eb45afa..0000000
--- a/compose/material/material-icons-extended/generate.gradle
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file contains logic used for compiling the individual themes of material-icons-extended
-
-import androidx.build.AndroidXComposePlugin
-import androidx.build.Publish
-import androidx.build.RunApiTasks
-import androidx.compose.material.icons.generator.tasks.IconGenerationTask
-
-apply plugin: "AndroidXPlugin"
-apply plugin: "com.android.library"
-apply plugin: "AndroidXComposePlugin"
-
-apply from: "${buildscript.sourceFile.parentFile}/shared-dependencies.gradle"
-
-IconGenerationTask.registerExtendedIconThemeProject(project, android)
-
-dependencies.attributesSchema {
-    attribute(iconExportAttr)
-    attribute(iconBuildTypeAttr)
-}
-
-configurations {
-    def jarsDir = "${buildDir}/intermediates/aar_main_jar"
-    iconExportDebug {
-        attributes {
-            attribute(iconExportAttr, "true")
-            attribute(iconBuildTypeAttr, "debug")
-        }
-        outgoing.artifact(new File("${jarsDir}/debug/classes.jar")) {
-            builtBy("syncDebugLibJars")
-        }
-    }
-    iconExportRelease {
-        attributes {
-            attribute(iconExportAttr, "true")
-            attribute(iconBuildTypeAttr, "release")
-        }
-        outgoing.artifact(new File("${jarsDir}/release/classes.jar")) {
-            builtBy("syncReleaseLibJars")
-        }
-    }
-}
-
-androidx {
-    name = "Compose Material Icons Extended"
-    publish = Publish.NONE // actually embedded into the main aar rather than published separately
-    // This module has a large number (1000+) of generated source files and so doc generation /
-    // API tracking will simply take too long
-    runApiTasks = new RunApiTasks.No("A thousand generated source files")
-    inceptionYear = "2020"
-    description = "Compose Material Design extended icons. This module contains material icons of the corresponding theme. It is a very large dependency and should not be included directly."
-}
diff --git a/compose/material/material-icons-extended/shared-dependencies.gradle b/compose/material/material-icons-extended/shared-dependencies.gradle
deleted file mode 100644
index 2de0ef0..0000000
--- a/compose/material/material-icons-extended/shared-dependencies.gradle
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This file stores common dependencies that are used both by material-icons-extended and
-// by its specific theme projects (each of which compile a specific theme)
-
-import androidx.build.AndroidXComposePlugin
-import androidx.build.KmpPlatformsKt
-
-def desktopEnabled = KmpPlatformsKt.enableDesktop(project)
-
-androidXMultiplatform {
-    android()
-    if (desktopEnabled) desktop()
-}
-
-kotlin {
-    /*
-     * When updating dependencies, make sure to make an analogous update in the
-     * corresponding block above
-     */
-    sourceSets {
-        commonMain.dependencies {
-            api(project(":compose:material:material-icons-core"))
-            implementation(libs.kotlinStdlibCommon)
-            implementation(project(":compose:runtime:runtime"))
-        }
-    }
-}
-
-project.ext.iconExportAttr = Attribute.of("com.androidx.compose.material-icons-extended.Export", String)
-project.ext.iconBuildTypeAttr = Attribute.of("com.androidx.compose.material-icons-extended.BuildType", String)
diff --git a/compose/material/material/icons/README.md b/compose/material/material/icons/README.md
index fbb8a68..a561f99 100644
--- a/compose/material/material/icons/README.md
+++ b/compose/material/material/icons/README.md
@@ -6,7 +6,6 @@
  1. The `generator` module, in `generator/` - this module processes and generates Kotlin source files as part of the build step of the other modules. This module is not shipped as an artifact, and caches its outputs based on the input icons (found in `generator/raw-icons`).
  2. `material-icons-core` , in `core/` - this module contains _core_ icons, the set of most-commonly-used icons used by applications, including the icons that are required by Material components themselves, such as the menu icon. This module is fairly small and is depended on by `material`.
  3. `material-icons-extended`, in `extended/` - this module contains every icon that is not in `material-icons-core`, and has a transitive `api` dependency on `material-icons-core`, so depending on this module will provide every single Material icon (over 5000 at the time of writing). Due to the excessive size of this module, this module should ***NOT*** be included as a direct dependency of any other library, and should only be used if Proguard / R8 is enabled.
- 4. `material-icons-extended-$theme`, in `extended/` - these modules each contain a specific theme from material-icons-extended, to facilitate compiling the icon soure files more quickly in parallel
 
 ## Icon Generation
 
diff --git a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
index 4eae40a..f7c4b66 100644
--- a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
+++ b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/IconProcessor.kt
@@ -50,8 +50,7 @@
 class IconProcessor(
     private val iconDirectories: List<File>,
     private val expectedApiFile: File,
-    private val generatedApiFile: File,
-    private val verifyApi: Boolean = true
+    private val generatedApiFile: File
 ) {
     /**
      * @return a list of processed [Icon]s, from the provided [iconDirectories].
@@ -59,11 +58,9 @@
     fun process(): List<Icon> {
         val icons = loadIcons()
 
-        if (verifyApi) {
-            ensureIconsExistInAllThemes(icons)
-            writeApiFile(icons, generatedApiFile)
-            checkApi(expectedApiFile, generatedApiFile)
-        }
+        ensureIconsExistInAllThemes(icons)
+        writeApiFile(icons, generatedApiFile)
+        checkApi(expectedApiFile, generatedApiFile)
 
         return icons
     }
diff --git a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconGenerationTask.kt b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconGenerationTask.kt
index f264ab4..fe2a652 100644
--- a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconGenerationTask.kt
+++ b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconGenerationTask.kt
@@ -24,11 +24,9 @@
 import org.gradle.api.DefaultTask
 import org.gradle.api.Project
 import org.gradle.api.tasks.CacheableTask
-import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.InputDirectory
 import org.gradle.api.tasks.InputFile
 import org.gradle.api.tasks.Internal
-import org.gradle.api.tasks.Optional
 import org.gradle.api.tasks.OutputDirectory
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.PathSensitive
@@ -54,23 +52,11 @@
         project.rootProject.project(GeneratorProject).projectDir.resolve("raw-icons")
 
     /**
-     * Specific theme to generate icons for, or null to generate all
-     */
-    @Optional
-    @Input
-    var themeName: String? = null
-
-    /**
      * Specific icon directories to use in this task
      */
     @Internal
     fun getIconDirectories(): List<File> {
-        val themeName = themeName
-        if (themeName != null) {
-            return listOf(allIconsDirectory.resolve(themeName))
-        } else {
-            return allIconsDirectory.listFiles()!!.filter { it.isDirectory }
-        }
+        return allIconsDirectory.listFiles()!!.filter { it.isDirectory }
     }
 
     /**
@@ -102,12 +88,10 @@
         // material-icons-core loads and verifies all of the icons from all of the themes:
         // both that all icons are present in all themes, and also that no icons have been removed.
         // So, when we're loading just one theme, we don't need to verify it
-        val verifyApi = themeName == null
         return IconProcessor(
             getIconDirectories(),
             expectedApiFile,
-            generatedApiFile,
-            verifyApi
+            generatedApiFile
         ).process()
     }
 
@@ -160,7 +144,9 @@
             libraryExtension: LibraryExtension
         ) {
             libraryExtension.libraryVariants.all { variant ->
-                ExtendedIconGenerationTask.register(project, variant)
+                if (variant.name == "release") {
+                    ExtendedIconGenerationTask.register(project, variant)
+                }
             }
 
             // b/175401659 - disable lint as it takes a long time, and most errors should
@@ -213,16 +199,9 @@
 ): Pair<TaskProvider<T>, File> {
     val variantName = variant?.name ?: "allVariants"
 
-    val themeName = if (project.name.contains("material-icons-extended-")) {
-        project.name.replace("material-icons-extended-", "")
-    } else {
-        null
-    }
-
     val buildDirectory = project.buildDir.resolve("generatedIcons/$variantName")
 
     return tasks.register("$taskName${variantName.capitalize(Locale.getDefault())}", taskClass) {
-        it.themeName = themeName
         it.buildDirectory = buildDirectory
     } to buildDirectory
 }
diff --git a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconSourceTasks.kt b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconSourceTasks.kt
index 9e8c3fe..e59eb51 100644
--- a/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconSourceTasks.kt
+++ b/compose/material/material/icons/generator/src/main/kotlin/androidx/compose/material/icons/generator/tasks/IconSourceTasks.kt
@@ -44,12 +44,7 @@
                 CoreIconGenerationTask::class.java,
                 variant
             )
-            // Multiplatform
-            if (variant == null) {
-                registerIconGenerationTask(project, task, buildDirectory)
-            }
-            // AGP
-            else variant.registerIconGenerationTask(project, task, buildDirectory)
+            registerIconGenerationTask(project, task, buildDirectory)
         }
     }
 }
@@ -73,36 +68,7 @@
                 ExtendedIconGenerationTask::class.java,
                 variant
             )
-            // Multiplatform
-            if (variant == null) {
-                registerIconGenerationTask(project, task, buildDirectory)
-            }
-            // AGP
-            else variant.registerIconGenerationTask(project, task, buildDirectory)
-        }
-
-        /**
-         * Registers the icon generation task just for source jar generation, and not for
-         * compilation. This is temporarily needed since we manually parallelize compilation in
-         * material-icons-extended for the AGP build. When we remove that parallelization code,
-         * we can remove this too.
-         */
-        @JvmStatic
-        @Suppress("DEPRECATION") // BaseVariant
-        fun registerSourceJarOnly(
-            project: Project,
-            variant: com.android.build.gradle.api.BaseVariant
-        ) {
-            // Setup the source jar task if this is the release variant
-            if (variant.name == "release") {
-                val (task, buildDirectory) = project.registerGenerationTask(
-                    "generateExtendedIcons",
-                    ExtendedIconGenerationTask::class.java,
-                    variant
-                )
-                val generatedSrcMainDirectory = buildDirectory.resolve(GeneratedSrcMain)
-                project.addToSourceJar(generatedSrcMainDirectory, task)
-            }
+            registerIconGenerationTask(project, task, buildDirectory)
         }
     }
 }
@@ -123,42 +89,4 @@
     project.tasks.named("multiplatformSourceJar", Jar::class.java).configure {
         it.from(task.map { generatedSrcMainDirectory })
     }
-    project.addToSourceJar(generatedSrcMainDirectory, task)
-}
-
-/**
- * Helper to register [task] as the java source generating task that outputs to [buildDirectory].
- */
-@Suppress("DEPRECATION") // BaseVariant
-private fun com.android.build.gradle.api.BaseVariant.registerIconGenerationTask(
-    project: Project,
-    task: TaskProvider<*>,
-    buildDirectory: File
-) {
-    val generatedSrcMainDirectory = buildDirectory.resolve(IconGenerationTask.GeneratedSrcMain)
-    registerJavaGeneratingTask(task, generatedSrcMainDirectory)
-    // Setup the source jar task if this is the release variant
-    if (name == "release") {
-        project.addToSourceJar(generatedSrcMainDirectory, task)
-    }
-}
-
-/**
- * Adds the contents of [buildDirectory] to the source jar generated for this [Project] by [task]
- */
-// TODO: b/191485164 remove when AGP lets us get generated sources from a TestedExtension or
-// similar, then we can just add generated sources in SourceJarTaskHelper for all projects,
-// instead of needing one-off support here.
-private fun Project.addToSourceJar(buildDirectory: File, task: TaskProvider<*>) {
-    afterEvaluate {
-        val sourceJar = tasks.named("sourceJarRelease", Jar::class.java)
-        sourceJar.configure {
-            // Generating source jars requires the generation task to run first. This shouldn't
-            // be needed for the MPP build because we use builtBy to set up the dependency
-            // (https://github.com/gradle/gradle/issues/17250) but the path is different for AGP,
-            // so we will still need this for the AGP build.
-            it.dependsOn(task)
-            it.from(buildDirectory)
-        }
-    }
 }
diff --git a/compose/material/material/lint-baseline.xml b/compose/material/material/lint-baseline.xml
index c8e0bc4..564dcc8 100644
--- a/compose/material/material/lint-baseline.xml
+++ b/compose/material/material/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0-beta05" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0-beta05)" variant="all" version="8.1.0-beta05">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanThreadSleep"
@@ -137,6 +137,654 @@
     </issue>
 
     <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val titlePlaceable = measurables.firstOrNull { it.layoutId == &quot;title&quot; }?.measure("
+        errorLine2="                                         ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val textPlaceable = measurables.firstOrNull { it.layoutId == &quot;text&quot; }?.measure("
+        errorLine2="                                        ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            sequences.add(0, currentSequence.toList())"
+        errorLine2="                                             ~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (measurable in measurables) {"
+        errorLine2="                        ~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val badgePlaceable = measurables.first { it.layoutId == &quot;badge&quot; }.measure("
+        errorLine2="                                         ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Badge.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val anchorPlaceable = measurables.first { it.layoutId == &quot;anchor&quot; }.measure(constraints)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Badge.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val iconPlaceable = measurables.first { it.layoutId == &quot;icon&quot; }.measure(constraints)"
+        errorLine2="                                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;label&quot; }.measure("
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomNavigation.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.map { it.measure(looseConstraints) }"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomSheetScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .map { it.measure(looseConstraints) }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomSheetScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.map { it.measure(bodyConstraints) }"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomSheetScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            subcompose(BottomSheetScaffoldLayoutSlot.Fab, fab).map { it.measure(looseConstraints) }"
+        errorLine2="                                                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomSheetScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .map { it.measure(looseConstraints) }"
+        errorLine2="             ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/BottomSheetScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeables = measurables.map { it.measure(childConstraints) }"
+        errorLine2="                                     ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/ListItem.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val containerWidth = placeables.fold(0) { maxWidth, placeable ->"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/ListItem.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val iconPlaceable = measurables.first { it.layoutId == &quot;icon&quot; }.measure(constraints)"
+        errorLine2="                                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;label&quot; }.measure("
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingPlaceable = measurables.find {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingPlaceable = measurables.find { it.layoutId == TrailingId }"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LabelId }?.measure(labelConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == TextFieldId }.measure(textConstraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == PlaceholderId }?.measure(placeholderConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val borderPlaceable = measurables.first { it.layoutId == BorderId }.measure("
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, height)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelWidth = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                     ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingWidth = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingWidth = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderWidth = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingHeight = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingHeight = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                         ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelHeight = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, remainingWidth)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderHeight = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val snackbarPlaceables = subcompose(ScaffoldLayoutContent.Snackbar, snackbar).map {"
+        errorLine2="                                                                                      ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        tickFractions.groupBy { it > positionFractionEnd || it &lt; positionFractionStart }"
+        errorLine2="                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    list.map {"
+        errorLine2="                         ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        .minByOrNull { abs(lerp(minPx, maxPx, it) - current) }"
+        errorLine2="         ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val buttonPlaceable = measurables.first { it.layoutId == actionTag }.measure(constraints)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Snackbar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val textPlaceable = measurables.first { it.layoutId == textTag }.measure("
+        errorLine2="                                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Snackbar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val keys = state.items.map { it.key }.toMutableList()"
+        errorLine2="                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        keys.filterNotNull().mapTo(state.items) { key ->"
+        errorLine2="             ~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        keys.filterNotNull().mapTo(state.items) { key ->"
+        errorLine2="                             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                val animationDelay = if (isVisible &amp;&amp; keys.filterNotNull().size != 1) delay else 0"
+        errorLine2="                                                           ~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val a = anchors.filter { it &lt;= offset + 0.001 }.maxOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Swipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val b = anchors.filter { it >= offset - 0.001 }.minOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Swipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;text&quot; }.measure("
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Tab.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;icon&quot; }.measure(constraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/Tab.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val tabPlaceables = tabMeasurables.map {"
+        errorLine2="                                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val tabRowHeight = tabPlaceables.maxByOrNull { it.height }?.height ?: 0"
+        errorLine2="                                             ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabPlaceables.forEachIndexed { index, placeable ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                subcompose(TabSlots.Divider, divider).forEach {"
+        errorLine2="                                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                }.forEach {"
+        errorLine2="                  ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .map { it.measure(tabConstraints) }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            tabPlaceables.forEach {"
+        errorLine2="                          ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabPlaceables.forEach {"
+        errorLine2="                              ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                subcompose(TabSlots.Divider, divider).forEach {"
+        errorLine2="                                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                }.forEach {"
+        errorLine2="                  ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LeadingId }?.measure(looseConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingPlaceable = measurables.find { it.layoutId == TrailingId }"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LabelId }?.measure(labelConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .first { it.layoutId == TextFieldId }"
+        errorLine2="             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .find { it.layoutId == PlaceholderId }"
+        errorLine2="             ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, height)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelWidth = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                     ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingWidth = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingWidth = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderWidth = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingHeight = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingHeight = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                         ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelHeight = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, remainingWidth)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderHeight = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material/TextField.kt"/>
+    </issue>
+
+    <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in constructor AnchoredDraggableState has parameter &apos;positionalThreshold&apos; with type Function1&lt;? super Float, Float>."
         errorLine1="    internal val positionalThreshold: (totalDistance: Float) -> Float,"
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
index 6ae0c2a..36e5ddc 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/FloatingActionButtonTest.kt
@@ -17,6 +17,8 @@
 package androidx.compose.material
 
 import android.os.Build
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
@@ -26,8 +28,13 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Favorite
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import androidx.compose.testutils.assertShape
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Rect
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.layout.LayoutCoordinates
@@ -47,6 +54,7 @@
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -148,14 +156,18 @@
         rule.setMaterialContent {
             Column {
                 Spacer(
-                    Modifier.requiredSize(10.dp).weight(1f).onGloballyPositioned {
-                        item1Bounds = it.boundsInRoot()
-                    }
+                    Modifier
+                        .requiredSize(10.dp)
+                        .weight(1f)
+                        .onGloballyPositioned {
+                            item1Bounds = it.boundsInRoot()
+                        }
                 )
 
                 FloatingActionButton(
                     onClick = {},
-                    modifier = Modifier.weight(1f)
+                    modifier = Modifier
+                        .weight(1f)
                         .onGloballyPositioned {
                             buttonBounds = it.boundsInRoot()
                         }
@@ -163,7 +175,10 @@
                     Text("Button")
                 }
 
-                Spacer(Modifier.requiredSize(10.dp).weight(1f))
+                Spacer(
+                    Modifier
+                        .requiredSize(10.dp)
+                        .weight(1f))
             }
         }
 
@@ -257,7 +272,8 @@
                     }
                 ) {
                     Box(
-                        Modifier.size(2.dp)
+                        Modifier
+                            .size(2.dp)
                             .onGloballyPositioned { contentCoordinates = it }
                     )
                 }
@@ -286,7 +302,8 @@
                 ExtendedFloatingActionButton(
                     text = {
                         Box(
-                            Modifier.size(2.dp)
+                            Modifier
+                                .size(2.dp)
                                 .onGloballyPositioned { contentCoordinates = it }
                         )
                     },
@@ -319,13 +336,15 @@
                 ExtendedFloatingActionButton(
                     text = {
                         Box(
-                            Modifier.size(2.dp)
+                            Modifier
+                                .size(2.dp)
                                 .onGloballyPositioned { textCoordinates = it }
                         )
                     },
                     icon = {
                         Box(
-                            Modifier.size(10.dp)
+                            Modifier
+                                .size(10.dp)
                                 .onGloballyPositioned { iconCoordinates = it }
                         )
                     },
@@ -355,4 +374,112 @@
             }
         }
     }
+
+    @Test
+    fun floatingActionButtonElevation_newInteraction() {
+        val interactionSource = MutableInteractionSource()
+        val defaultElevation = 1.dp
+        val pressedElevation = 2.dp
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var elevation: State<Dp>
+
+        rule.setMaterialContent {
+            val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            elevation = fabElevation.elevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            interactionSource.tryEmit(PressInteraction.Press(Offset.Zero))
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(pressedElevation)
+        }
+    }
+
+    @Test
+    fun floatingActionButtonElevation_newValue() {
+        val interactionSource = MutableInteractionSource()
+        var defaultElevation by mutableStateOf(1.dp)
+        val pressedElevation = 2.dp
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var elevation: State<Dp>
+
+        rule.setMaterialContent {
+             val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            elevation = fabElevation.elevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            defaultElevation = 5.dp
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(5.dp)
+        }
+    }
+
+    @Test
+    fun floatingActionButtonElevation_newValueDuringInteraction() {
+        val interactionSource = MutableInteractionSource()
+        val defaultElevation = 1.dp
+        var pressedElevation by mutableStateOf(2.dp)
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var elevation: State<Dp>
+
+        rule.setMaterialContent {
+            val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            elevation = fabElevation.elevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            interactionSource.tryEmit(PressInteraction.Press(Offset.Zero))
+        }
+
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(pressedElevation)
+        }
+
+        rule.runOnIdle {
+            pressedElevation = 5.dp
+        }
+
+        // We are still pressed, so we should now show the updated value for the pressed state
+        rule.runOnIdle {
+            assertThat(elevation.value).isEqualTo(5.dp)
+        }
+    }
 }
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/InteractiveComponentSize.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/InteractiveComponentSize.kt
index 87ad9ab..f639ad9 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/InteractiveComponentSize.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/InteractiveComponentSize.kt
@@ -19,12 +19,15 @@
 import androidx.compose.runtime.ProvidableCompositionLocal
 import androidx.compose.runtime.staticCompositionLocalOf
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.layout.LayoutModifier
 import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.currentValueOf
+import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
@@ -43,20 +46,58 @@
  * This modifier is not needed for touch target expansion to happen. It only affects layout, to make
  * sure there is adequate space for touch target expansion.
  */
-@OptIn(ExperimentalMaterialApi::class)
-fun Modifier.minimumInteractiveComponentSize(): Modifier = composed(
-    inspectorInfo = debugInspectorInfo {
+fun Modifier.minimumInteractiveComponentSize(): Modifier = this then MinimumInteractiveModifier
+
+internal object MinimumInteractiveModifier :
+    ModifierNodeElement<MinimumInteractiveModifierNode>() {
+
+    override fun create(): MinimumInteractiveModifierNode = MinimumInteractiveModifierNode()
+
+    override fun update(node: MinimumInteractiveModifierNode) {}
+
+    override fun InspectorInfo.inspectableProperties() {
         name = "minimumInteractiveComponentSize"
         // TODO: b/214589635 - surface this information through the layout inspector in a better way
         //  - for now just add some information to help developers debug what this size represents.
         properties["README"] = "Reserves at least 48.dp in size to disambiguate touch " +
             "interactions if the element would measure smaller"
     }
-) {
-    if (LocalMinimumInteractiveComponentEnforcement.current) {
-        MinimumInteractiveComponentSizeModifier(minimumInteractiveComponentSize)
-    } else {
-        Modifier
+
+    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun equals(other: Any?) = (other === this)
+}
+
+internal class MinimumInteractiveModifierNode :
+    Modifier.Node(),
+    CompositionLocalConsumerModifierNode,
+    LayoutModifierNode {
+
+    @OptIn(ExperimentalMaterialApi::class)
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+        val enforcement = isAttached && currentValueOf(LocalMinimumInteractiveComponentEnforcement)
+        val size = minimumInteractiveComponentSize
+        val placeable = measurable.measure(constraints)
+
+        // Be at least as big as the minimum dimension in both dimensions
+        val width = if (enforcement) {
+            maxOf(placeable.width, size.width.roundToPx())
+        } else {
+            placeable.width
+        }
+        val height = if (enforcement) {
+            maxOf(placeable.height, size.height.roundToPx())
+        } else {
+            placeable.height
+        }
+
+        return layout(width, height) {
+            val centerX = ((width - placeable.width) / 2f).roundToInt()
+            val centerY = ((height - placeable.height) / 2f).roundToInt()
+            placeable.place(centerX, centerY)
+        }
     }
 }
 
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/BadgeBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/BadgeBenchmark.kt
new file mode 100644
index 0000000..53bc830
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/BadgeBenchmark.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Badge
+import androidx.compose.material3.BadgedBox
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import org.junit.Rule
+import org.junit.Test
+
+class BadgeBenchmark {
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    @Test
+    fun BadgeFirstPixel() { benchmarkRule.benchmarkToFirstPixel { BadgeTestCase() } }
+
+    @Test
+    fun BadgedBoxFirstPixel() { benchmarkRule.benchmarkToFirstPixel { BadgedBoxTestCase() } }
+}
+
+private class BadgedBoxTestCase : LayeredComposeTestCase() {
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() {
+        BadgedBox(
+            badge = { Spacer(Modifier.size(10.dp)) }
+        ) { Spacer(Modifier.size(24.dp)) }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
+
+private class BadgeTestCase : LayeredComposeTestCase() {
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() { Badge() }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CardBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CardBenchmark.kt
new file mode 100644
index 0000000..d82f319
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CardBenchmark.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Card
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class CardBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val cardTestCaseFactory = { CardTestCase() }
+    private val clickableCardTestCaseFactory = { ClickableCardTestCase() }
+
+    @Ignore
+    @Test
+    fun first_compose() {
+        benchmarkRule.benchmarkFirstCompose(cardTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_measure() {
+        benchmarkRule.benchmarkFirstMeasure(cardTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_layout() {
+        benchmarkRule.benchmarkFirstLayout(cardTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_draw() {
+        benchmarkRule.benchmarkFirstDraw(cardTestCaseFactory)
+    }
+
+    @Test
+    fun card_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(cardTestCaseFactory)
+    }
+
+    @Test
+    fun clickableCard_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(clickableCardTestCaseFactory)
+    }
+}
+
+internal class CardTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        Card(modifier = Modifier.size(200.dp)) { }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
+
+internal class ClickableCardTestCase : LayeredComposeTestCase() {
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() {
+        Card(onClick = {}, modifier = Modifier.size(200.dp)) { }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CheckboxBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CheckboxBenchmark.kt
new file mode 100644
index 0000000..0610c98
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/CheckboxBenchmark.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.material3.Checkbox
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class CheckboxBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val checkboxTestCaseFactory = { CheckboxTestCase() }
+
+    @Ignore
+    @Test
+    fun first_compose() {
+        benchmarkRule.benchmarkFirstCompose(checkboxTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_measure() {
+        benchmarkRule.benchmarkFirstMeasure(checkboxTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_layout() {
+        benchmarkRule.benchmarkFirstLayout(checkboxTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_draw() {
+        benchmarkRule.benchmarkFirstDraw(checkboxTestCaseFactory)
+    }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(checkboxTestCaseFactory)
+    }
+
+    @Test
+    fun toggle_recomposeMeasureLayout() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = checkboxTestCaseFactory,
+            assertOneRecomposition = false
+        )
+    }
+}
+
+internal class CheckboxTestCase : LayeredComposeTestCase(), ToggleableTestCase {
+
+    private var state by mutableStateOf(false)
+
+    @Composable
+    override fun MeasuredContent() {
+        Checkbox(checked = state, onCheckedChange = null)
+    }
+
+    override fun toggleState() {
+        state = !state
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ChipBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ChipBenchmark.kt
index d190cbf..e9e7609 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ChipBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ChipBenchmark.kt
@@ -32,9 +32,11 @@
 import androidx.compose.testutils.benchmark.benchmarkFirstDraw
 import androidx.compose.testutils.benchmark.benchmarkFirstLayout
 import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
 import androidx.compose.ui.Modifier
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -48,25 +50,34 @@
 
     private val chipTestCaseFactory = { ChipTestCase() }
 
+    @Ignore
     @Test
     fun first_compose() {
         benchmarkRule.benchmarkFirstCompose(chipTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun chip_measure() {
         benchmarkRule.benchmarkFirstMeasure(chipTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun chip_layout() {
         benchmarkRule.benchmarkFirstLayout(chipTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun chip_draw() {
         benchmarkRule.benchmarkFirstDraw(chipTestCaseFactory)
     }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(chipTestCaseFactory)
+    }
 }
 
 internal class ChipTestCase : LayeredComposeTestCase() {
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DatePickerBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DatePickerBenchmark.kt
index e5e5664..e5ba192 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DatePickerBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DatePickerBenchmark.kt
@@ -27,6 +27,7 @@
 import androidx.compose.testutils.benchmark.benchmarkFirstCompose
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -42,40 +43,58 @@
     private val dateInputTestCaseFactory = { DateInputTestCase() }
 
     @Test
+    fun datePicker_firstPixel() {
+        benchmarkRule.benchmarkFirstRenderUntilStable(datePickerTestCaseFactory)
+    }
+
+    @Test
+    fun dateInput_firstPixel() {
+        benchmarkRule.benchmarkFirstRenderUntilStable(dateInputTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
     fun first_compose_pickerMode() {
         benchmarkRule.benchmarkFirstCompose(datePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun first_compose_inputMode() {
         benchmarkRule.benchmarkFirstCompose(dateInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun datePicker_measure() {
         benchmarkRule.benchmarkMeasureUntilStable(datePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateInput_measure() {
         benchmarkRule.benchmarkMeasureUntilStable(dateInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun datePicker_layout() {
         benchmarkRule.benchmarkLayoutUntilStable(datePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateInput_layout() {
         benchmarkRule.benchmarkLayoutUntilStable(dateInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun datePicker_draw() {
         benchmarkRule.benchmarkDrawUntilStable(datePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateInput_draw() {
         benchmarkRule.benchmarkDrawUntilStable(dateInputTestCaseFactory)
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DateRangePickerBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DateRangePickerBenchmark.kt
index b9f97a3..61aec86 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DateRangePickerBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DateRangePickerBenchmark.kt
@@ -28,8 +28,10 @@
 import androidx.compose.testutils.benchmark.benchmarkFirstDraw
 import androidx.compose.testutils.benchmark.benchmarkFirstLayout
 import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -45,40 +47,58 @@
     private val dateRangeInputTestCaseFactory = { DateRangeInputTestCase() }
 
     @Test
+    fun dateRangePicker_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(dateRangePickerTestCaseFactory)
+    }
+
+    @Test
+    fun dateRangeInput_firstPixel() {
+        benchmarkRule.benchmarkFirstRenderUntilStable(dateRangeInputTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
     fun first_compose_pickerMode() {
         benchmarkRule.benchmarkFirstCompose(dateRangePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun first_compose_inputMode() {
         benchmarkRule.benchmarkFirstCompose(dateRangeInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangePicker_measure() {
         benchmarkRule.benchmarkFirstMeasure(dateRangePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangeInput_measure() {
         benchmarkRule.benchmarkMeasureUntilStable(dateRangeInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangePicker_layout() {
         benchmarkRule.benchmarkFirstLayout(dateRangePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangeInput_layout() {
         benchmarkRule.benchmarkLayoutUntilStable(dateRangeInputTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangePicker_draw() {
         benchmarkRule.benchmarkFirstDraw(dateRangePickerTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun dateRangeInput_draw() {
         benchmarkRule.benchmarkDrawUntilStable(dateRangeInputTestCaseFactory)
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DividerBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DividerBenchmark.kt
new file mode 100644
index 0000000..adea672
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/DividerBenchmark.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.VerticalDivider
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class DividerBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val horizontalDividerTestCaseFactory = { HorizontalDividerTestCase() }
+    private val verticalDividerTestCaseFactory = { VerticalDividerTestCase() }
+
+    @Ignore
+    @Test
+    fun horizontalDivider_first_compose() {
+        benchmarkRule.benchmarkFirstCompose(horizontalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun verticalDivider_first_compose() {
+        benchmarkRule.benchmarkFirstCompose(verticalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun horizontalDivider_measure() {
+        benchmarkRule.benchmarkFirstMeasure(horizontalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun verticalDivider_measure() {
+        benchmarkRule.benchmarkFirstMeasure(verticalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun horizontalDivider_layout() {
+        benchmarkRule.benchmarkFirstLayout(horizontalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun verticalDivider_layout() {
+        benchmarkRule.benchmarkFirstLayout(verticalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun horizontalDivider_draw() {
+        benchmarkRule.benchmarkFirstDraw(horizontalDividerTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun verticalDivider_draw() {
+        benchmarkRule.benchmarkFirstDraw(verticalDividerTestCaseFactory)
+    }
+
+    @Test
+    fun horizontalDivider_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(horizontalDividerTestCaseFactory)
+    }
+
+    @Test
+    fun verticalDivider_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(verticalDividerTestCaseFactory)
+    }
+}
+
+internal class HorizontalDividerTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        HorizontalDivider()
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
+
+internal class VerticalDividerTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        VerticalDivider()
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/FloatingActionButtonBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/FloatingActionButtonBenchmark.kt
new file mode 100644
index 0000000..40b4a89
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/FloatingActionButtonBenchmark.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.ExtendedFloatingActionButton
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class FloatingActionButtonBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val fabTestCaseFactory = { FloatingActionButtonTestCase() }
+    private val extendedFabTestCaseFactory = { ExtendedFloatingActionButtonTestCase() }
+
+    @Ignore
+    @Test
+    fun fab_first_compose() {
+        benchmarkRule.benchmarkFirstCompose(fabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun extendedFab_first_compose() {
+        benchmarkRule.benchmarkFirstCompose(extendedFabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun fab_measure() {
+        benchmarkRule.benchmarkFirstMeasure(fabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun extendedFab_measure() {
+        benchmarkRule.benchmarkFirstMeasure(extendedFabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun fab_layout() {
+        benchmarkRule.benchmarkFirstLayout(fabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun extendedFab_layout() {
+        benchmarkRule.benchmarkFirstLayout(extendedFabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun fab_draw() {
+        benchmarkRule.benchmarkFirstDraw(fabTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun extendedFab_draw() {
+        benchmarkRule.benchmarkFirstDraw(extendedFabTestCaseFactory)
+    }
+
+    @Test
+    fun fab_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(fabTestCaseFactory)
+    }
+
+    @Test
+    fun extendedFab_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(extendedFabTestCaseFactory)
+    }
+}
+
+internal class FloatingActionButtonTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        FloatingActionButton(onClick = { /*TODO*/ }) {
+            Box(modifier = Modifier.size(24.dp))
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
+
+internal class ExtendedFloatingActionButtonTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        ExtendedFloatingActionButton(
+            text = { Text(text = "Extended FAB") },
+            icon = {
+                Box(modifier = Modifier.size(24.dp))
+            },
+            onClick = { /*TODO*/ })
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ListItemBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ListItemBenchmark.kt
new file mode 100644
index 0000000..7bc00ae
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/ListItemBenchmark.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.ListItem
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+class ListItemBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val listItemTestCaseFactory = { ListItemTestCase() }
+
+    @Ignore
+    @Test
+    fun first_compose() {
+        benchmarkRule.benchmarkFirstCompose(listItemTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun listItem_measure() {
+        benchmarkRule.benchmarkFirstMeasure(listItemTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun listItem_layout() {
+        benchmarkRule.benchmarkFirstLayout(listItemTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun listItem_draw() {
+        benchmarkRule.benchmarkFirstDraw(listItemTestCaseFactory)
+    }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(listItemTestCaseFactory)
+    }
+}
+
+internal class ListItemTestCase : LayeredComposeTestCase() {
+
+    @Composable
+    override fun MeasuredContent() {
+        ListItem(
+            headlineContent = { Text(text = "List Item") },
+            overlineContent = { Text(text = "Overline Content") },
+            supportingContent = { Text(text = "Supporting Content") },
+            leadingContent = {
+                Box(modifier = Modifier.size(24.dp))
+            },
+            trailingContent = {
+                Box(modifier = Modifier.size(24.dp))
+            }
+        )
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationBarBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationBarBenchmark.kt
new file mode 100644
index 0000000..60607a0
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationBarBenchmark.kt
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.NavigationBar
+import androidx.compose.material3.NavigationBarItem
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableIntState
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class NavigationBarBenchmark {
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val testCaseFactory = { NavigationBarTestCase() }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkFirstRenderUntilStable(testCaseFactory)
+    }
+
+    @Test
+    fun changeSelection() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            testCaseFactory,
+            assertOneRecomposition = false,
+        )
+    }
+}
+
+internal class NavigationBarTestCase : LayeredComposeTestCase(), ToggleableTestCase {
+    private lateinit var selectedIndexState: MutableIntState
+
+    @Composable
+    override fun MeasuredContent() {
+        selectedIndexState = remember { mutableIntStateOf(0) }
+
+        NavigationBar {
+            NavigationBarItem(
+                selected = selectedIndexState.value == 0,
+                onClick = {},
+                icon = { Spacer(Modifier.size(24.dp)) },
+            )
+            NavigationBarItem(
+                selected = selectedIndexState.value == 1,
+                onClick = {},
+                icon = { Spacer(Modifier.size(24.dp)) },
+            )
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+
+    override fun toggleState() {
+        selectedIndexState.value = if (selectedIndexState.value == 0) 1 else 0
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt
new file mode 100644
index 0000000..9e0b6b1
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/NavigationRailBenchmark.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.NavigationRail
+import androidx.compose.material3.NavigationRailItem
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableIntState
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class NavigationRailBenchmark {
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val testCaseFactory = { NavigationRailTestCase() }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(testCaseFactory)
+    }
+
+    @Test
+    fun changeSelection() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            testCaseFactory,
+            assertOneRecomposition = false,
+        )
+    }
+}
+
+internal class NavigationRailTestCase : LayeredComposeTestCase(), ToggleableTestCase {
+    private lateinit var selectedIndexState: MutableIntState
+
+    @Composable
+    override fun MeasuredContent() {
+        selectedIndexState = remember { mutableIntStateOf(0) }
+
+        NavigationRail {
+            NavigationRailItem(
+                selected = selectedIndexState.value == 0,
+                onClick = {},
+                icon = { Spacer(Modifier.size(24.dp)) },
+            )
+            NavigationRailItem(
+                selected = selectedIndexState.value == 1,
+                onClick = {},
+                icon = { Spacer(Modifier.size(24.dp)) },
+            )
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+
+    override fun toggleState() {
+        selectedIndexState.value = if (selectedIndexState.value == 0) 1 else 0
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/RangeSliderBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/RangeSliderBenchmark.kt
new file mode 100644
index 0000000..270c5dd
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/RangeSliderBenchmark.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RangeSlider
+import androidx.compose.material3.RangeSliderState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.shadow
+import androidx.compose.ui.unit.dp
+import org.junit.Rule
+import org.junit.Test
+
+class RangeSliderBenchmark {
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val sliderTestCaseFactory = { RangeSliderTestCase() }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkFirstRenderUntilStable(sliderTestCaseFactory)
+    }
+
+    @Test
+    fun moveThumb() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = sliderTestCaseFactory
+        )
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+internal class RangeSliderTestCase : LayeredComposeTestCase(), ToggleableTestCase {
+
+    private lateinit var state: RangeSliderState
+
+    @Composable
+    override fun MeasuredContent() {
+        state = remember { RangeSliderState(steps = 15) }
+
+        RangeSlider(
+            state = state,
+            startThumb = {
+                Spacer(
+                    Modifier
+                        .size(48.dp)
+                        .background(color = MaterialTheme.colorScheme.primary)
+                        .clip(CircleShape)
+                        .shadow(10.dp, CircleShape)
+                )
+            })
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+
+    override fun toggleState() {
+        if (state.activeRangeStart == 0f) {
+            state.activeRangeStart = 1f
+        } else {
+            state.activeRangeStart = 0f
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/SurfaceBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/SurfaceBenchmark.kt
new file mode 100644
index 0000000..2487cb7
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/SurfaceBenchmark.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class SurfaceBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val surfaceTestCaseFactory = { SurfaceTestCase() }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(surfaceTestCaseFactory)
+    }
+}
+
+internal class SurfaceTestCase : LayeredComposeTestCase() {
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() {
+        Surface(Modifier.size(1.dp)) {}
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextBenchmark.kt
index 8408c0a..34eac1c 100644
--- a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextBenchmark.kt
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextBenchmark.kt
@@ -25,8 +25,10 @@
 import androidx.compose.testutils.benchmark.benchmarkFirstDraw
 import androidx.compose.testutils.benchmark.benchmarkFirstLayout
 import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -40,25 +42,34 @@
 
     private val textTestCaseFactory = { TextTestCase() }
 
+    @Ignore
     @Test
     fun first_compose() {
         benchmarkRule.benchmarkFirstCompose(textTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun text_measure() {
         benchmarkRule.benchmarkFirstMeasure(textTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun text_layout() {
         benchmarkRule.benchmarkFirstLayout(textTestCaseFactory)
     }
 
+    @Ignore
     @Test
     fun text_draw() {
         benchmarkRule.benchmarkFirstDraw(textTestCaseFactory)
     }
+
+    @Test
+    fun text_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(textTestCaseFactory)
+    }
 }
 
 internal class TextTestCase : LayeredComposeTestCase() {
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextFieldBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextFieldBenchmark.kt
new file mode 100644
index 0000000..d09b748
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TextFieldBenchmark.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.TextField
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.test.filters.LargeTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class TextFieldBenchmark(private val type: TextFieldType) {
+    companion object {
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() = TextFieldType.values()
+    }
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val textFieldTestCaseFactory = { TextFieldTestCase(type) }
+
+    @Test
+    fun firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(textFieldTestCaseFactory)
+    }
+
+    @Test
+    fun enterText() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = textFieldTestCaseFactory,
+            assertOneRecomposition = false,
+        )
+    }
+}
+
+internal class TextFieldTestCase(
+    private val type: TextFieldType
+) : LayeredComposeTestCase(), ToggleableTestCase {
+    private lateinit var state: MutableState<String>
+
+    @Composable
+    override fun MeasuredContent() {
+        state = remember { mutableStateOf("") }
+
+        when (type) {
+            TextFieldType.Filled ->
+                TextField(
+                    value = state.value,
+                    onValueChange = {},
+                )
+            TextFieldType.Outlined ->
+                OutlinedTextField(
+                    value = state.value,
+                    onValueChange = {},
+                )
+        }
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+
+    override fun toggleState() {
+        state.value = if (state.value.isEmpty()) "Lorem ipsum" else ""
+    }
+}
+
+enum class TextFieldType {
+    Filled, Outlined
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt
new file mode 100644
index 0000000..7dc1a20
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TooltipBenchmark.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.PlainTooltip
+import androidx.compose.material3.RichTooltip
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextButton
+import androidx.compose.material3.TooltipBox
+import androidx.compose.material3.TooltipDefaults
+import androidx.compose.material3.TooltipState
+import androidx.compose.material3.rememberTooltipState
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.ToggleableTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.testutils.benchmark.toggleStateBenchmarkComposeMeasureLayout
+import androidx.compose.ui.window.PopupPositionProvider
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import org.junit.Rule
+import org.junit.Test
+
+class TooltipBenchmark {
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val plainTooltipTestCaseFactory = { TooltipTestCase(TooltipType.Plain) }
+    private val richTooltipTestCaseFactory = { TooltipTestCase(TooltipType.Rich) }
+
+    @Test
+    fun plainTooltipFirstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(plainTooltipTestCaseFactory)
+    }
+
+    @Test
+    fun richTooltipFirstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(richTooltipTestCaseFactory)
+    }
+
+    @Test
+    fun plainTooltipVisibilityTest() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = plainTooltipTestCaseFactory,
+            assertOneRecomposition = false
+        )
+    }
+
+    @Test
+    fun richTooltipVisibilityTest() {
+        benchmarkRule.toggleStateBenchmarkComposeMeasureLayout(
+            caseFactory = richTooltipTestCaseFactory,
+            assertOneRecomposition = false
+        )
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+private class TooltipTestCase(
+    val tooltipType: TooltipType
+) : LayeredComposeTestCase(), ToggleableTestCase {
+    private lateinit var state: TooltipState
+    private lateinit var scope: CoroutineScope
+
+    @Composable
+    override fun MeasuredContent() {
+        state = rememberTooltipState()
+        scope = rememberCoroutineScope()
+
+        val tooltip: @Composable () -> Unit
+        val positionProvider: PopupPositionProvider
+        when (tooltipType) {
+            TooltipType.Plain -> {
+                tooltip = { PlainTooltipTest() }
+                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider()
+            }
+            TooltipType.Rich -> {
+                tooltip = { RichTooltipTest() }
+                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider()
+            }
+        }
+
+        TooltipBox(
+            positionProvider = positionProvider,
+            tooltip = tooltip,
+            state = state
+        ) {}
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+
+    override fun toggleState() {
+        if (state.isVisible) {
+            state.dismiss()
+        } else {
+            scope.launch { state.show() }
+        }
+    }
+
+    @Composable
+    private fun PlainTooltipTest() {
+        PlainTooltip { Text("Text") }
+    }
+
+    @Composable
+    private fun RichTooltipTest() {
+        RichTooltip(
+            title = { Text("Subhead") },
+            action = {
+                TextButton(onClick = {}) {
+                    Text(text = "Action")
+                }
+            }
+        ) { Text(text = "Text") }
+    }
+}
+
+private enum class TooltipType {
+    Plain, Rich
+}
diff --git a/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TopAppBarBenchmark.kt b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TopAppBarBenchmark.kt
new file mode 100644
index 0000000..4b66d90c
--- /dev/null
+++ b/compose/material3/benchmark/src/androidTest/java/androidx/compose/material3/benchmark/TopAppBarBenchmark.kt
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2023 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.material3.benchmark
+
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.LargeTopAppBar
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.LayeredComposeTestCase
+import androidx.compose.testutils.benchmark.ComposeBenchmarkRule
+import androidx.compose.testutils.benchmark.benchmarkFirstCompose
+import androidx.compose.testutils.benchmark.benchmarkFirstDraw
+import androidx.compose.testutils.benchmark.benchmarkFirstLayout
+import androidx.compose.testutils.benchmark.benchmarkFirstMeasure
+import androidx.compose.testutils.benchmark.benchmarkToFirstPixel
+import androidx.compose.ui.Modifier
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+class TopAppBarBenchmark {
+
+    @get:Rule
+    val benchmarkRule = ComposeBenchmarkRule()
+
+    private val topAppBarTestCaseFactory = { TopAppBarTestCase() }
+
+    // Picking the LargeTopAppBar to benchmark a two-row variation.
+    private val largeTopAppBarTestCaseFactory = { LargeTopAppBarTestCase() }
+
+    @Ignore
+    @Test
+    fun first_compose() {
+        benchmarkRule.benchmarkFirstCompose(topAppBarTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_measure() {
+        benchmarkRule.benchmarkFirstMeasure(topAppBarTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_layout() {
+        benchmarkRule.benchmarkFirstLayout(topAppBarTestCaseFactory)
+    }
+
+    @Ignore
+    @Test
+    fun first_draw() {
+        benchmarkRule.benchmarkFirstDraw(topAppBarTestCaseFactory)
+    }
+
+    @Test
+    fun topAppBar_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(topAppBarTestCaseFactory)
+    }
+
+    @Test
+    fun largeTopAppBar_firstPixel() {
+        benchmarkRule.benchmarkToFirstPixel(largeTopAppBarTestCaseFactory)
+    }
+}
+
+internal class TopAppBarTestCase : LayeredComposeTestCase() {
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() {
+        // Keeping it to the minimum, with just the necessary title.
+        TopAppBar(title = { Text("Hello") }, modifier = Modifier.fillMaxWidth())
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
+
+internal class LargeTopAppBarTestCase : LayeredComposeTestCase() {
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    override fun MeasuredContent() {
+        // Keeping it to the minimum, with just the necessary title.
+        LargeTopAppBar(title = { Text("Hello") }, modifier = Modifier.fillMaxWidth())
+    }
+
+    @Composable
+    override fun ContentWrappers(content: @Composable () -> Unit) {
+        MaterialTheme {
+            content()
+        }
+    }
+}
diff --git a/compose/material3/material3-adaptive/build.gradle b/compose/material3/material3-adaptive/build.gradle
index 5c97bb2..67f3ad9 100644
--- a/compose/material3/material3-adaptive/build.gradle
+++ b/compose/material3/material3-adaptive/build.gradle
@@ -119,3 +119,10 @@
             project.rootDir.absolutePath + "/../../golden/compose/material3/material3-adaptive"
     namespace "androidx.compose.material3.adaptive"
 }
+
+// b/295947829 createProjectZip mustRunAfter samples createProjectZip. Remove after https://github.com/gradle/gradle/issues/24368 is resolved
+project.tasks.configureEach { task ->
+    if (task.name == "createProjectZip") {
+        task.mustRunAfter(":compose:material3:material3-adaptive:material3-adaptive-samples:createProjectZip")
+    }
+}
diff --git a/compose/material3/material3-adaptive/lint-baseline.xml b/compose/material3/material3-adaptive/lint-baseline.xml
new file mode 100644
index 0000000..5820cd6
--- /dev/null
+++ b/compose/material3/material3-adaptive/lint-baseline.xml
@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    foldingFeatures.forEach {"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/compose/material3/adaptive/AndroidPosture.android.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val navigationPlaceables = navigationMeasurables.map { it.measure(constraints) }"
+        errorLine2="                                                         ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.filterNotNull()"
+        errorLine2="          ~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        if (alignments.all { alignments[0] != it }) {"
+        errorLine2="                       ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val contentPlaceables = contentMeasurables.map { it.measure("
+        errorLine2="                                                   ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    minHeight = layoutHeight - navigationPlaceables.maxOf { it.height },"
+        errorLine2="                                                                    ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    maxHeight = layoutHeight - navigationPlaceables.maxOf { it.height }"
+        errorLine2="                                                                    ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    minWidth = layoutWidth - navigationPlaceables.maxOf { it.width },"
+        errorLine2="                                                                  ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    maxWidth = layoutWidth - navigationPlaceables.maxOf { it.width }"
+        errorLine2="                                                                  ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    navigationPlaceables.forEach {"
+        errorLine2="                                         ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    contentPlaceables.forEach {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                        it.placeRelative(navigationPlaceables.maxOf { it.width }, 0)"
+        errorLine2="                                                              ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    navigationPlaceables.forEach {"
+        errorLine2="                                         ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                            layoutWidth - navigationPlaceables.maxOf { it.width },"
+        errorLine2="                                                               ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    contentPlaceables.forEach {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    navigationPlaceables.forEach {"
+        errorLine2="                                         ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    contentPlaceables.forEach {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                        it.placeRelative(0, navigationPlaceables.maxOf { it.height })"
+        errorLine2="                                                                 ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    contentPlaceables.forEach {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    navigationPlaceables.forEach {"
+        errorLine2="                                         ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                            layoutHeight - navigationPlaceables.maxOf { it.height })"
+        errorLine2="                                                                ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    paneMeasurables.forEachIndexed { index, paneMeasurable ->"
+        errorLine2="                                    ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        measurables.forEach {"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    measurables.forEach {"
+        errorLine2="                ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/adaptive/ThreePaneScaffold.kt"/>
+    </issue>
+
+</issues>
diff --git a/compose/material3/material3-adaptive/samples/build.gradle b/compose/material3/material3-adaptive/samples/build.gradle
new file mode 100644
index 0000000..4e99c03
--- /dev/null
+++ b/compose/material3/material3-adaptive/samples/build.gradle
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 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("AndroidXComposePlugin")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+
+    implementation(libs.kotlinStdlib)
+
+    compileOnly(project(":annotation:annotation-sampled"))
+
+    implementation(project(":compose:foundation:foundation"))
+    implementation(project(":compose:foundation:foundation-layout"))
+    implementation(project(":compose:material3:material3"))
+    implementation(project(":compose:material3:material3-adaptive"))
+    implementation(project(":compose:material3:material3-window-size-class"))
+    implementation(project(":compose:ui:ui-util"))
+    implementation("androidx.compose.ui:ui-tooling-preview:1.4.1")
+}
+
+androidx {
+    name = "Compose Material3 Adaptive Samples"
+    type = LibraryType.SAMPLES
+    inceptionYear = "2023"
+    description = "Contains the sample code for the AndroidX Compose Material Adaptive."
+}
+
+android {
+    namespace "androidx.compose.material3.adaptive.samples"
+}
diff --git a/compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3-adaptive/samples/NavigationSuiteScaffoldSamples.kt b/compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3-adaptive/samples/NavigationSuiteScaffoldSamples.kt
new file mode 100644
index 0000000..51ee44b
--- /dev/null
+++ b/compose/material3/material3-adaptive/samples/src/main/java/androidx/compose/material3-adaptive/samples/NavigationSuiteScaffoldSamples.kt
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2023 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.material3.adaptive.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Favorite
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
+import androidx.compose.material3.adaptive.NavigationSuite
+import androidx.compose.material3.adaptive.NavigationSuiteAlignment
+import androidx.compose.material3.adaptive.NavigationSuiteDefaults
+import androidx.compose.material3.adaptive.NavigationSuiteScaffold
+import androidx.compose.material3.adaptive.NavigationSuiteType
+import androidx.compose.material3.adaptive.calculateWindowAdaptiveInfo
+import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun NavigationSuiteScaffoldSample() {
+    var selectedItem by remember { mutableIntStateOf(0) }
+    val navItems = listOf("Songs", "Artists", "Playlists")
+    val navSuiteType =
+        NavigationSuiteDefaults.calculateFromAdaptiveInfo(calculateWindowAdaptiveInfo())
+
+    NavigationSuiteScaffold(
+        navigationSuite = {
+            NavigationSuite {
+                navItems.forEachIndexed { index, navItem ->
+                    item(
+                        icon = { Icon(Icons.Filled.Favorite, contentDescription = navItem) },
+                        label = { Text(navItem) },
+                        selected = selectedItem == index,
+                        onClick = { selectedItem = index }
+                    )
+                }
+            }
+        }
+    ) {
+        // Screen content.
+        Text(
+            modifier = Modifier.padding(16.dp),
+            text = "Current NavigationSuiteType: $navSuiteType"
+        )
+    }
+}
+
+@OptIn(ExperimentalMaterial3AdaptiveApi::class)
+@Preview
+@Sampled
+@Composable
+fun NavigationSuiteScaffoldCustomConfigSample() {
+    var selectedItem by remember { mutableIntStateOf(0) }
+    val navItems = listOf("Songs", "Artists", "Playlists")
+    val adaptiveInfo = calculateWindowAdaptiveInfo()
+    val customNavSuiteType = with(adaptiveInfo) {
+        if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Expanded) {
+            NavigationSuiteType.NavigationDrawer
+        } else if (windowSizeClass.widthSizeClass == WindowWidthSizeClass.Compact) {
+            NavigationSuiteType.NavigationRail
+        } else {
+            NavigationSuiteDefaults.calculateFromAdaptiveInfo(adaptiveInfo)
+        }
+    }
+
+    // Custom configuration that shows nav rail on end of screen in small screens, and navigation
+    // drawer in large screens.
+    NavigationSuiteScaffold(
+        navigationSuite = {
+            NavigationSuite(
+                layoutType = customNavSuiteType,
+                modifier = if (customNavSuiteType == NavigationSuiteType.NavigationRail) {
+                    Modifier.alignment(NavigationSuiteAlignment.EndVertical)
+                } else {
+                    Modifier
+                }
+            ) {
+                navItems.forEachIndexed { index, navItem ->
+                    item(
+                        icon = { Icon(Icons.Filled.Favorite, contentDescription = navItem) },
+                        label = { Text(navItem) },
+                        selected = selectedItem == index,
+                        onClick = { selectedItem = index }
+                    )
+                }
+            }
+        }
+    ) {
+        // Screen content.
+        Text(
+            modifier = Modifier.padding(16.dp),
+            text = "Current custom NavigationSuiteType: $customNavSuiteType"
+        )
+    }
+}
diff --git a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt b/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt
index 9620e34..71a31c5 100644
--- a/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt
+++ b/compose/material3/material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive/NavigationSuiteScaffold.kt
@@ -65,6 +65,11 @@
  * The Navigation Suite Scaffold wraps the provided content and places the adequate provided
  * navigation component on the screen according to the current [NavigationSuiteType].
  *
+ * Example default usage:
+ * @sample androidx.compose.material3.adaptive.samples.NavigationSuiteScaffoldSample
+ * Example custom configuration usage:
+ * @sample androidx.compose.material3.adaptive.samples.NavigationSuiteScaffoldCustomConfigSample
+ *
  * @param navigationSuite the navigation component to be displayed, typically [NavigationSuite]
  * @param modifier the [Modifier] to be applied to the navigation suite scaffold
  * @param containerColor the color used for the background of the navigation suite scaffold. Use
diff --git a/compose/material3/material3-window-size-class/lint-baseline.xml b/compose/material3/material3-window-size-class/lint-baseline.xml
new file mode 100644
index 0000000..6b8f7eb
--- /dev/null
+++ b/compose/material3/material3-window-size-class/lint-baseline.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            sortedSizeClasses.forEach {"
+        errorLine2="                              ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/windowsizeclass/WindowSizeClass.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            sortedSizeClasses.forEach {"
+        errorLine2="                              ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/windowsizeclass/WindowSizeClass.kt"/>
+    </issue>
+
+</issues>
diff --git a/compose/material3/material3/api/current.txt b/compose/material3/material3/api/current.txt
index 310ebce..9236b0f 100644
--- a/compose/material3/material3/api/current.txt
+++ b/compose/material3/material3/api/current.txt
@@ -176,11 +176,11 @@
   }
 
   public final class CalendarModelKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale, java.util.Map<java.lang.String,java.lang.Object> cache);
   }
 
   public final class CalendarModel_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale, java.util.Map<java.lang.String,java.lang.Object> cache);
   }
 
   @androidx.compose.runtime.Immutable public final class CardColors {
@@ -1039,9 +1039,6 @@
     method @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface PlainTooltipState extends androidx.compose.material3.TooltipState {
-  }
-
   public final class ProgressIndicatorDefaults {
     method @androidx.compose.runtime.Composable public long getCircularColor();
     method public int getCircularDeterminateStrokeCap();
@@ -1125,11 +1122,6 @@
     property public final long titleContentColor;
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface RichTooltipState extends androidx.compose.material3.TooltipState {
-    method public boolean isPersistent();
-    property public abstract boolean isPersistent;
-  }
-
   public final class ScaffoldDefaults {
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getContentWindowInsets();
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets contentWindowInsets;
@@ -1795,18 +1787,14 @@
     method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TimePickerState,?> Saver();
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public interface TooltipBoxScope {
-    method public androidx.compose.ui.Modifier tooltipTrigger(androidx.compose.ui.Modifier);
-  }
-
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class TooltipDefaults {
-    method public androidx.compose.foundation.MutatorMutex getGlobalMutatorMutex();
     method @androidx.compose.runtime.Composable public long getPlainTooltipContainerColor();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getPlainTooltipContainerShape();
     method @androidx.compose.runtime.Composable public long getPlainTooltipContentColor();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRichTooltipContainerShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors(optional long containerColor, optional long contentColor, optional long titleContentColor, optional long actionContentColor);
-    property public final androidx.compose.foundation.MutatorMutex GlobalMutatorMutex;
     property @androidx.compose.runtime.Composable public final long plainTooltipContainerColor;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape plainTooltipContainerShape;
     property @androidx.compose.runtime.Composable public final long plainTooltipContentColor;
@@ -1815,18 +1803,16 @@
   }
 
   public final class TooltipKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PlainTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional androidx.compose.material3.PlainTooltipState tooltipState, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void RichTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> text, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional androidx.compose.material3.RichTooltipState tooltipState, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.RichTooltipColors colors, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.PlainTooltipState rememberPlainTooltipState(optional androidx.compose.foundation.MutatorMutex mutatorMutex);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.RichTooltipState rememberRichTooltipState(boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @androidx.compose.runtime.Composable public static void PlainTooltip(optional androidx.compose.ui.Modifier modifier, optional long contentColor, optional long containerColor, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void RichTooltip(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional androidx.compose.material3.RichTooltipColors colors, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> text);
+    method @androidx.compose.runtime.Composable public static void TooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.material3.TooltipState state, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.material3.TooltipState TooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TooltipState rememberTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface TooltipState {
-    method public void dismiss();
-    method public boolean isVisible();
-    method public void onDispose();
-    method public suspend Object? show(kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    property public abstract boolean isVisible;
+  public interface TooltipState extends androidx.compose.foundation.BasicTooltipState {
+    method public androidx.compose.animation.core.MutableTransitionState<java.lang.Boolean> getTransition();
+    property public abstract androidx.compose.animation.core.MutableTransitionState<java.lang.Boolean> transition;
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarColors {
diff --git a/compose/material3/material3/api/restricted_current.txt b/compose/material3/material3/api/restricted_current.txt
index 310ebce..9236b0f 100644
--- a/compose/material3/material3/api/restricted_current.txt
+++ b/compose/material3/material3/api/restricted_current.txt
@@ -176,11 +176,11 @@
   }
 
   public final class CalendarModelKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale, java.util.Map<java.lang.String,java.lang.Object> cache);
   }
 
   public final class CalendarModel_androidKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public static String formatWithSkeleton(long utcTimeMillis, String skeleton, java.util.Locale locale, java.util.Map<java.lang.String,java.lang.Object> cache);
   }
 
   @androidx.compose.runtime.Immutable public final class CardColors {
@@ -1039,9 +1039,6 @@
     method @androidx.compose.runtime.Composable public static void OutlinedTextField(String value, kotlin.jvm.functions.Function1<? super java.lang.String,kotlin.Unit> onValueChange, optional androidx.compose.ui.Modifier modifier, optional boolean enabled, optional boolean readOnly, optional androidx.compose.ui.text.TextStyle textStyle, optional kotlin.jvm.functions.Function0<kotlin.Unit>? label, optional kotlin.jvm.functions.Function0<kotlin.Unit>? placeholder, optional kotlin.jvm.functions.Function0<kotlin.Unit>? leadingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? trailingIcon, optional kotlin.jvm.functions.Function0<kotlin.Unit>? prefix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? suffix, optional kotlin.jvm.functions.Function0<kotlin.Unit>? supportingText, optional boolean isError, optional androidx.compose.ui.text.input.VisualTransformation visualTransformation, optional androidx.compose.foundation.text.KeyboardOptions keyboardOptions, optional androidx.compose.foundation.text.KeyboardActions keyboardActions, optional boolean singleLine, optional int maxLines, optional int minLines, optional androidx.compose.foundation.interaction.MutableInteractionSource interactionSource, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.TextFieldColors colors);
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface PlainTooltipState extends androidx.compose.material3.TooltipState {
-  }
-
   public final class ProgressIndicatorDefaults {
     method @androidx.compose.runtime.Composable public long getCircularColor();
     method public int getCircularDeterminateStrokeCap();
@@ -1125,11 +1122,6 @@
     property public final long titleContentColor;
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface RichTooltipState extends androidx.compose.material3.TooltipState {
-    method public boolean isPersistent();
-    property public abstract boolean isPersistent;
-  }
-
   public final class ScaffoldDefaults {
     method @androidx.compose.runtime.Composable public androidx.compose.foundation.layout.WindowInsets getContentWindowInsets();
     property @androidx.compose.runtime.Composable public final androidx.compose.foundation.layout.WindowInsets contentWindowInsets;
@@ -1795,18 +1787,14 @@
     method public androidx.compose.runtime.saveable.Saver<androidx.compose.material3.TimePickerState,?> Saver();
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public interface TooltipBoxScope {
-    method public androidx.compose.ui.Modifier tooltipTrigger(androidx.compose.ui.Modifier);
-  }
-
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api public final class TooltipDefaults {
-    method public androidx.compose.foundation.MutatorMutex getGlobalMutatorMutex();
     method @androidx.compose.runtime.Composable public long getPlainTooltipContainerColor();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getPlainTooltipContainerShape();
     method @androidx.compose.runtime.Composable public long getPlainTooltipContentColor();
     method @androidx.compose.runtime.Composable public androidx.compose.ui.graphics.Shape getRichTooltipContainerShape();
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberPlainTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
+    method @androidx.compose.runtime.Composable public androidx.compose.ui.window.PopupPositionProvider rememberRichTooltipPositionProvider(optional float spacingBetweenTooltipAndAnchor);
     method @androidx.compose.runtime.Composable public androidx.compose.material3.RichTooltipColors richTooltipColors(optional long containerColor, optional long contentColor, optional long titleContentColor, optional long actionContentColor);
-    property public final androidx.compose.foundation.MutatorMutex GlobalMutatorMutex;
     property @androidx.compose.runtime.Composable public final long plainTooltipContainerColor;
     property @androidx.compose.runtime.Composable public final androidx.compose.ui.graphics.Shape plainTooltipContainerShape;
     property @androidx.compose.runtime.Composable public final long plainTooltipContentColor;
@@ -1815,18 +1803,16 @@
   }
 
   public final class TooltipKt {
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void PlainTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional androidx.compose.material3.PlainTooltipState tooltipState, optional androidx.compose.ui.graphics.Shape shape, optional long containerColor, optional long contentColor, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static void RichTooltipBox(kotlin.jvm.functions.Function0<kotlin.Unit> text, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional androidx.compose.material3.RichTooltipState tooltipState, optional androidx.compose.ui.graphics.Shape shape, optional androidx.compose.material3.RichTooltipColors colors, kotlin.jvm.functions.Function1<? super androidx.compose.material3.TooltipBoxScope,kotlin.Unit> content);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.PlainTooltipState rememberPlainTooltipState(optional androidx.compose.foundation.MutatorMutex mutatorMutex);
-    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.RichTooltipState rememberRichTooltipState(boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @androidx.compose.runtime.Composable public static void PlainTooltip(optional androidx.compose.ui.Modifier modifier, optional long contentColor, optional long containerColor, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method @androidx.compose.runtime.Composable public static void RichTooltip(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function0<kotlin.Unit>? title, optional kotlin.jvm.functions.Function0<kotlin.Unit>? action, optional androidx.compose.material3.RichTooltipColors colors, optional androidx.compose.ui.graphics.Shape shape, kotlin.jvm.functions.Function0<kotlin.Unit> text);
+    method @androidx.compose.runtime.Composable public static void TooltipBox(androidx.compose.ui.window.PopupPositionProvider positionProvider, kotlin.jvm.functions.Function0<kotlin.Unit> tooltip, androidx.compose.material3.TooltipState state, optional androidx.compose.ui.Modifier modifier, optional boolean focusable, optional boolean enableUserInput, kotlin.jvm.functions.Function0<kotlin.Unit> content);
+    method public static androidx.compose.material3.TooltipState TooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
+    method @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Composable public static androidx.compose.material3.TooltipState rememberTooltipState(optional boolean initialIsVisible, optional boolean isPersistent, optional androidx.compose.foundation.MutatorMutex mutatorMutex);
   }
 
-  @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public interface TooltipState {
-    method public void dismiss();
-    method public boolean isVisible();
-    method public void onDispose();
-    method public suspend Object? show(kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    property public abstract boolean isVisible;
+  public interface TooltipState extends androidx.compose.foundation.BasicTooltipState {
+    method public androidx.compose.animation.core.MutableTransitionState<java.lang.Boolean> getTransition();
+    property public abstract androidx.compose.animation.core.MutableTransitionState<java.lang.Boolean> transition;
   }
 
   @SuppressCompatibility @androidx.compose.material3.ExperimentalMaterial3Api @androidx.compose.runtime.Stable public final class TopAppBarColors {
diff --git a/compose/material3/material3/integration-tests/material3-catalog/build.gradle b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
index 0e8ccb9..c94165a 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/build.gradle
+++ b/compose/material3/material3/integration-tests/material3-catalog/build.gradle
@@ -34,6 +34,7 @@
     implementation project(":compose:material:material-icons-extended")
     implementation project(":compose:material3:material3")
     implementation project(":compose:material3:material3:material3-samples")
+    implementation project(":compose:material3:material3-adaptive:material3-adaptive-samples")
     implementation project(":datastore:datastore-preferences")
     implementation project(":navigation:navigation-compose")
 }
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
index 6745a59..9ab9751 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Components.kt
@@ -18,6 +18,7 @@
 
 import androidx.annotation.DrawableRes
 import androidx.compose.material3.catalog.library.R
+import androidx.compose.material3.catalog.library.util.AdaptiveMaterial3SourceUrl
 import androidx.compose.material3.catalog.library.util.ComponentGuidelinesUrl
 import androidx.compose.material3.catalog.library.util.DocsUrl
 import androidx.compose.material3.catalog.library.util.Material3SourceUrl
@@ -243,6 +244,20 @@
     examples = NavigationRailExamples
 )
 
+private val NavigationSuiteScaffold = Component(
+    id = nextId(),
+    name = "Navigation Suite Scaffold",
+    description = "The Navigation Suite Scaffold wraps the provided content and places the " +
+        "adequate provided navigation component on the screen according to the current " +
+        "NavigationSuiteType. \n\n" +
+        "Note: this sample is better experienced in a resizable emulator or foldable device.",
+    // No navigation suite scaffold icon
+    guidelinesUrl = "", // TODO: Add guidelines url when available
+    docsUrl = "", // TODO: Add docs url when available
+    sourceUrl = "$AdaptiveMaterial3SourceUrl/NavigationSuiteScaffold.kt",
+    examples = NavigationSuiteScaffoldExamples
+)
+
 private val ProgressIndicators = Component(
     id = nextId(),
     name = "Progress indicators",
@@ -398,6 +413,7 @@
     NavigationBar,
     NavigationDrawer,
     NavigationRail,
+    NavigationSuiteScaffold,
     ProgressIndicators,
     RadioButtons,
     SearchBars,
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
index 3fba476..c6d720e 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/model/Examples.kt
@@ -21,6 +21,9 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.width
 import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.material3.adaptive.samples.NavigationSuiteScaffoldCustomConfigSample
+import androidx.compose.material3.adaptive.samples.NavigationSuiteScaffoldSample
+import androidx.compose.material3.catalog.library.util.AdaptiveSampleSourceUrl
 import androidx.compose.material3.catalog.library.util.SampleSourceUrl
 import androidx.compose.material3.samples.AlertDialogSample
 import androidx.compose.material3.samples.AlertDialogWithCustomContentSample
@@ -719,6 +722,23 @@
     }
 )
 
+private const val NavigationSuiteScaffoldExampleDescription = "Navigation suite scaffold examples"
+private const val NavigationSuiteScaffoldExampleSourceUrl =
+    "$AdaptiveSampleSourceUrl/NavigationSuiteScaffoldSamples.kt"
+val NavigationSuiteScaffoldExamples =
+    listOf(
+        Example(
+            name = ::NavigationSuiteScaffoldSample.name,
+            description = NavigationSuiteScaffoldExampleDescription,
+            sourceUrl = NavigationSuiteScaffoldExampleSourceUrl,
+        ) { NavigationSuiteScaffoldSample() },
+        Example(
+            name = ::NavigationSuiteScaffoldCustomConfigSample.name,
+            description = NavigationSuiteScaffoldExampleDescription,
+            sourceUrl = NavigationSuiteScaffoldExampleSourceUrl,
+        ) { NavigationSuiteScaffoldCustomConfigSample() },
+    )
+
 private const val ProgressIndicatorsExampleDescription = "Progress indicators examples"
 private const val ProgressIndicatorsExampleSourceUrl = "$SampleSourceUrl/" +
     "ProgressIndicatorSamples.kt"
diff --git a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/util/Url.kt b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/util/Url.kt
index 8145968..0836cfe 100644
--- a/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/util/Url.kt
+++ b/compose/material3/material3/integration-tests/material3-catalog/src/main/java/androidx/compose/material3/catalog/library/util/Url.kt
@@ -40,6 +40,12 @@
 const val SampleSourceUrl = "https://cs.android.com/androidx/platform/frameworks/support/+/" +
     "androidx-main:compose/material3/" +
     "material3/samples/src/main/java/androidx/compose/material3/samples"
+const val AdaptiveMaterial3SourceUrl = "https://cs.android.com/androidx/platform/frameworks/" +
+    "support/+/androidx-main:compose/material3/" +
+    "material3-adaptive/src/commonMain/kotlin/androidx/compose/material3/adaptive"
+const val AdaptiveSampleSourceUrl = "https://cs.android.com/androidx/platform/frameworks/" +
+    "support/+/androidx-main:compose/material3/material3-adaptive" +
+    "samples/src/main/java/androidx/compose/material3-adaptive/samples"
 const val IssueUrl = "https://issuetracker.google.com/issues/new?component=742043"
 const val TermsUrl = "https://policies.google.com/terms"
 const val PrivacyUrl = "https://policies.google.com/privacy"
diff --git a/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt b/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
index e08d179..4a9b04d 100644
--- a/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
+++ b/compose/material3/material3/integration-tests/material3-demos/src/main/java/androidx/compose/material3/demos/TooltipDemo.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.material3.demos
 
-import androidx.compose.foundation.MutatorMutex
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
@@ -33,11 +32,12 @@
 import androidx.compose.material3.OutlinedButton
 import androidx.compose.material3.OutlinedCard
 import androidx.compose.material3.OutlinedTextField
-import androidx.compose.material3.PlainTooltipBox
-import androidx.compose.material3.PlainTooltipState
+import androidx.compose.material3.PlainTooltip
 import androidx.compose.material3.Text
+import androidx.compose.material3.TooltipBox
 import androidx.compose.material3.TooltipDefaults
-import androidx.compose.material3.rememberPlainTooltipState
+import androidx.compose.material3.TooltipState
+import androidx.compose.material3.rememberTooltipState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateListOf
@@ -47,10 +47,7 @@
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.unit.dp
-import kotlinx.coroutines.CancellableContinuation
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlinx.coroutines.withTimeout
 
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
@@ -67,14 +64,16 @@
         ) {
             var textFieldValue by remember { mutableStateOf("") }
             var textFieldTooltipText by remember { mutableStateOf("") }
-            val textFieldTooltipState = rememberPlainTooltipState()
+            val textFieldTooltipState = rememberTooltipState()
             val scope = rememberCoroutineScope()
-            val mutatorMutex = TooltipDefaults.GlobalMutatorMutex
-            PlainTooltipBox(
+            TooltipBox(
+                positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                 tooltip = {
-                    Text(textFieldTooltipText)
+                    PlainTooltip {
+                        Text(textFieldTooltipText)
+                    }
                 },
-                tooltipState = textFieldTooltipState
+                state = textFieldTooltipState
             ) {
                 OutlinedTextField(
                     value = textFieldValue,
@@ -93,7 +92,7 @@
                             textFieldTooltipState.show()
                         }
                     } else {
-                        val listItem = ItemInfo(textFieldValue, DemoTooltipState(mutatorMutex))
+                        val listItem = ItemInfo(textFieldValue, TooltipState())
                         listData.add(listItem)
                         textFieldValue = ""
                         scope.launch {
@@ -110,9 +109,14 @@
             verticalArrangement = Arrangement.spacedBy(4.dp)
         ) {
             items(listData) { item ->
-                PlainTooltipBox(
-                    tooltip = { Text("${item.itemName} added to list") },
-                    tooltipState = item.addedTooltipState
+                TooltipBox(
+                    positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                    tooltip = {
+                        PlainTooltip {
+                            Text("${item.itemName} added to list")
+                        }
+                    },
+                    state = item.addedTooltipState
                 ) {
                     ListItemCard(
                         itemName = item.itemName,
@@ -136,12 +140,18 @@
         ListItem(
             headlineContent = { Text(itemName) },
             trailingContent = {
-                PlainTooltipBox(
-                    tooltip = { Text("Delete $itemName") }
+                TooltipBox(
+                    positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+                    tooltip = {
+                        PlainTooltip {
+                            Text("Delete $itemName")
+                        }
+                    },
+                    state = rememberTooltipState(),
+                    enableUserInput = true
                 ) {
                     IconButton(
-                        onClick = onDelete,
-                        modifier = Modifier.tooltipTrigger()
+                        onClick = onDelete
                     ) {
                         Icon(
                             imageVector = Icons.Filled.Delete,
@@ -154,42 +164,7 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 class ItemInfo(
     val itemName: String,
-    val addedTooltipState: PlainTooltipState
+    val addedTooltipState: TooltipState
 )
-
-@OptIn(ExperimentalMaterial3Api::class)
-class DemoTooltipState(private val mutatorMutex: MutatorMutex) : PlainTooltipState {
-    override var isVisible by mutableStateOf(false)
-
-    private var job: (CancellableContinuation<Unit>)? = null
-
-    override suspend fun show() {
-        mutatorMutex.mutate {
-            try {
-                withTimeout(TOOLTIP_DURATION) {
-                    suspendCancellableCoroutine { continuation ->
-                        isVisible = true
-                        job = continuation
-                    }
-                }
-            } finally {
-                // timeout or cancellation has occurred
-                // and we close out the current tooltip.
-                isVisible = false
-            }
-        }
-    }
-
-    override fun dismiss() {
-        isVisible = false
-    }
-
-    override fun onDispose() {
-        job?.cancel()
-    }
-}
-
-private const val TOOLTIP_DURATION = 1000L
diff --git a/compose/material3/material3/lint-baseline.xml b/compose/material3/material3/lint-baseline.xml
index ae3e747..d765049 100644
--- a/compose/material3/material3/lint-baseline.xml
+++ b/compose/material3/material3/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanThreadSleep"
@@ -173,12 +173,1218 @@
     </issue>
 
     <issue
-        id="ExperimentalPropertyAnnotation"
-        message="This property does not have all required annotations to correctly mark it as experimental."
-        errorLine1="    @ExperimentalMaterial3Api"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            sequences.add(0, currentSequence.toList())"
+        errorLine2="                                             ~~~~~~">
         <location
-            file="src/commonMain/kotlin/androidx/compose/material3/SwipeableV2.kt"/>
+            file="src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (measurable in measurables) {"
+        errorLine2="                        ~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            sequences.forEachIndexed { i, placeables ->"
+        errorLine2="                      ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                placeables.forEachIndexed { j, placeable ->"
+        errorLine2="                           ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AlertDialog.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;navigationIcon&quot; }"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AppBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;actionIcons&quot; }"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AppBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;title&quot; }"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/AppBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val badgePlaceable = measurables.first { it.layoutId == &quot;badge&quot; }.measure("
+        errorLine2="                                         ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Badge.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val anchorPlaceable = measurables.first { it.layoutId == &quot;anchor&quot; }.measure(constraints)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Badge.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                dayNames.forEach {"
+        errorLine2="                         ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        weekdays.drop(2).forEachIndexed { index, day ->"
+        errorLine2="                         ~~~~~~~~~~~~~~">
+        <location
+            file="src/jvmMain/kotlin/androidx/compose/material3/LegacyCalendarModelImpl.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        ).map {"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val x = xCandidates.firstOrNull {"
+        errorLine2="                            ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        ).map {"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val y = yCandidates.firstOrNull {"
+        errorLine2="                            ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/MenuPosition.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == IconLayoutIdTag }.measure(looseConstraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .first { it.layoutId == IndicatorRippleLayoutIdTag }"
+        errorLine2="                 ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .firstOrNull { it.layoutId == IndicatorLayoutIdTag }"
+        errorLine2="                 ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .first { it.layoutId == LabelLayoutIdTag }"
+        errorLine2="                     ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationBar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == IconLayoutIdTag }.measure(looseConstraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .first { it.layoutId == IndicatorRippleLayoutIdTag }"
+        errorLine2="                 ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .firstOrNull { it.layoutId == IndicatorLayoutIdTag }"
+        errorLine2="                 ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .first { it.layoutId == LabelLayoutIdTag }"
+        errorLine2="                     ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/NavigationRail.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingPlaceable = measurables.find {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingPlaceable = measurables.find { it.layoutId == TrailingId }"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixPlaceable = measurables.find { it.layoutId == PrefixId }"
+        errorLine2="                                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixPlaceable = measurables.find { it.layoutId == SuffixId }"
+        errorLine2="                                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LabelId }?.measure(labelConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val supportingMeasurable = measurables.find { it.layoutId == SupportingId }"
+        errorLine2="                                               ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == TextFieldId }.measure(textConstraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == PlaceholderId }?.measure(placeholderConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val containerPlaceable = measurables.first { it.layoutId == ContainerId }.measure("
+        errorLine2="                                             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, height)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelWidth = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                     ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingWidth = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingWidth = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixWidth = measurables.find { it.layoutId == PrefixId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixWidth = measurables.find { it.layoutId == SuffixId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderWidth = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingHeight = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingHeight = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                         ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelHeight = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixHeight = measurables.find { it.layoutId == PrefixId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixHeight = measurables.find { it.layoutId == SuffixId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, remainingWidth)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderHeight = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val supportingHeight = measurables.find { it.layoutId == SupportingId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val topBarPlaceables = subcompose(ScaffoldLayoutContent.TopBar, topBar).map {"
+        errorLine2="                                                                                ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val topBarHeight = topBarPlaceables.maxByOrNull { it.height }?.height ?: 0"
+        errorLine2="                                            ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val snackbarPlaceables = subcompose(ScaffoldLayoutContent.Snackbar, snackbar).map {"
+        errorLine2="                                                                                      ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val snackbarHeight = snackbarPlaceables.maxByOrNull { it.height }?.height ?: 0"
+        errorLine2="                                                ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val snackbarWidth = snackbarPlaceables.maxByOrNull { it.width }?.width ?: 0"
+        errorLine2="                                               ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            subcompose(ScaffoldLayoutContent.Fab, fab).mapNotNull { measurable ->"
+        errorLine2="                                                       ~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val fabWidth = fabPlaceables.maxByOrNull { it.width }!!.width"
+        errorLine2="                                         ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val fabHeight = fabPlaceables.maxByOrNull { it.height }!!.height"
+        errorLine2="                                          ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.map { it.measure(looseConstraints) }"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val bottomBarHeight = bottomBarPlaceables.maxByOrNull { it.height }?.height"
+        errorLine2="                                                  ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.map { it.measure(looseConstraints) }"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            bodyContentPlaceables.forEach {"
+        errorLine2="                                  ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            topBarPlaceables.forEach {"
+        errorLine2="                             ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            snackbarPlaceables.forEach {"
+        errorLine2="                               ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            bottomBarPlaceables.forEach {"
+        errorLine2="                                ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                fabPlaceables.forEach {"
+        errorLine2="                              ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Scaffold.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                val iconPlaceables = iconMeasurables.map { it.measure(constraints) }"
+        errorLine2="                                                     ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                val iconDesiredWidth = iconMeasurables.fold(0) { acc, it ->"
+        errorLine2="                                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                val contentPlaceables = contentMeasurables.map { it.measure(constraints) }"
+        errorLine2="                                                           ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    iconPlaceables.forEach {"
+        errorLine2="                                   ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    contentPlaceables.forEach {"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SegmentedButton.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val thumbPlaceable = measurables.first {"
+        errorLine2="                                         ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trackPlaceable = measurables.first {"
+        errorLine2="                                         ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val startThumbPlaceable = measurables.first {"
+        errorLine2="                                              ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val endThumbPlaceable = measurables.first {"
+        errorLine2="                                            ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trackPlaceable = measurables.first {"
+        errorLine2="                                         ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                        list.map {"
+        errorLine2="                             ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                list.map {"
+        errorLine2="                     ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Slider.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.firstOrNull { it.layoutId == actionTag }?.measure(constraints)"
+        errorLine2="                        ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Snackbar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.firstOrNull { it.layoutId == dismissActionTag }?.measure(constraints)"
+        errorLine2="                        ~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Snackbar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val textPlaceable = measurables.first { it.layoutId == textTag }.measure("
+        errorLine2="                                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Snackbar.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val keys = state.items.map { it.key }.toMutableList()"
+        errorLine2="                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        keys.filterNotNull().mapTo(state.items) { key ->"
+        errorLine2="             ~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        keys.filterNotNull().mapTo(state.items) { key ->"
+        errorLine2="                             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                val animationDelay = if (isVisible &amp;&amp; keys.filterNotNull().size != 1) delay else 0"
+        errorLine2="                                                           ~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        state.items.forEach { (item, opacity) ->"
+        errorLine2="                    ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/SnackbarHost.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val a = anchors.filter { it &lt;= offset + 0.001 }.maxOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Swipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val b = anchors.filter { it >= offset - 0.001 }.minOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Swipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;text&quot; }.measure("
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Tab.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.first { it.layoutId == &quot;icon&quot; }.measure(constraints)"
+        errorLine2="                        ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Tab.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val tabRowHeight = tabMeasurables.fold(initial = 0) { max, curr ->"
+        errorLine2="                                              ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val tabPlaceables = tabMeasurables.map {"
+        errorLine2="                                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabPlaceables.forEachIndexed { index, placeable ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                subcompose(TabSlots.Divider, divider).forEach {"
+        errorLine2="                                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                }.forEach {"
+        errorLine2="                  ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val layoutHeight = tabMeasurables.fold(initial = 0) { curr, measurable ->"
+        errorLine2="                                              ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            tabMeasurables.forEach {"
+        errorLine2="                           ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val layoutWidth = tabPlaceables.fold(initial = padding * 2) { curr, measurable ->"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabPlaceables.forEachIndexed { index, placeable ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                subcompose(TabSlots.Divider, divider).forEach {"
+        errorLine2="                                                      ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                }.forEach {"
+        errorLine2="                  ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LeadingId }?.measure(looseConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingPlaceable = measurables.find { it.layoutId == TrailingId }"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixPlaceable = measurables.find { it.layoutId == PrefixId }"
+        errorLine2="                                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixPlaceable = measurables.find { it.layoutId == SuffixId }"
+        errorLine2="                                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            measurables.find { it.layoutId == LabelId }?.measure(labelConstraints)"
+        errorLine2="                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val supportingMeasurable = measurables.find { it.layoutId == SupportingId }"
+        errorLine2="                                               ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .first { it.layoutId == TextFieldId }"
+        errorLine2="             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .find { it.layoutId == PlaceholderId }"
+        errorLine2="             ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val containerPlaceable = measurables.first { it.layoutId == ContainerId }.measure("
+        errorLine2="                                             ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, height)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelWidth = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                     ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingWidth = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixWidth = measurables.find { it.layoutId == PrefixId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixWidth = measurables.find { it.layoutId == SuffixId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingWidth = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderWidth = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val leadingHeight = measurables.find { it.layoutId == LeadingId }?.let {"
+        errorLine2="                                        ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val trailingHeight = measurables.find { it.layoutId == TrailingId }?.let {"
+        errorLine2="                                         ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val labelHeight = measurables.find { it.layoutId == LabelId }?.let {"
+        errorLine2="                                      ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val prefixHeight = measurables.find { it.layoutId == PrefixId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val suffixHeight = measurables.find { it.layoutId == SuffixId }?.let {"
+        errorLine2="                                       ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            intrinsicMeasurer(measurables.first { it.layoutId == TextFieldId }, remainingWidth)"
+        errorLine2="                                          ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeholderHeight = measurables.find { it.layoutId == PlaceholderId }?.let {"
+        errorLine2="                                            ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val supportingHeight = measurables.find { it.layoutId == SupportingId }?.let {"
+        errorLine2="                                           ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TextField.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val spacer = measurables.first { it.layoutId == &quot;Spacer&quot; }"
+        errorLine2="                                     ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val items = measurables.filter { it.layoutId != &quot;Spacer&quot; }.map { item ->"
+        errorLine2="                                    ~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val items = measurables.filter { it.layoutId != &quot;Spacer&quot; }.map { item ->"
+        errorLine2="                                                                       ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val spacer = measurables.first { it.layoutId == &quot;Spacer&quot; }"
+        errorLine2="                                     ~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val items = measurables.filter { it.layoutId != &quot;Spacer&quot; }.map { item ->"
+        errorLine2="                                    ~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val items = measurables.filter { it.layoutId != &quot;Spacer&quot; }.map { item ->"
+        errorLine2="                                                                       ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeables = measurables.filter {"
+        errorLine2="                                     ~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.map { measurable -> measurable.measure(itemConstraints) }"
+        errorLine2="          ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val selectorMeasurable = measurables.find { it.layoutId == LayoutId.Selector }"
+        errorLine2="                                             ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val innerMeasurable = measurables.find { it.layoutId == LayoutId.InnerCircle }"
+        errorLine2="                                          ~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            placeables.forEachIndexed { i, it ->"
+        errorLine2="                       ~~~~~~~~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="private val ExtraHours = Hours.map { (it % 12 + 12) }"
+        errorLine2="                               ~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                                event.changes.forEach { it.consume() }"
+        errorLine2="                                              ~~~~~~~">
+        <location
+            file="src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt"/>
     </issue>
 
     <issue
@@ -201,15 +1407,6 @@
 
     <issue
         id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method BottomSheetScaffoldAnchorChangeHandler has parameter &apos;animateTo&apos; with type Function2&lt;? super SheetValue, ? super Float, Unit>."
-        errorLine1="    animateTo: (target: SheetValue, velocity: Float) -> Unit,"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method DateInputContent has parameter &apos;onDateSelectionChange&apos; with type Function1&lt;? super Long, Unit>."
         errorLine1="    onDateSelectionChange: (dateInMillis: Long?) -> Unit,"
         errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
@@ -426,24 +1623,6 @@
 
     <issue
         id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method modalBottomSheetSwipeable has parameter &apos;onDragStopped&apos; with type Function2&lt;? super CoroutineScope, ? super Float, Unit>."
-        errorLine1="    onDragStopped: CoroutineScope.(velocity: Float) -> Unit,"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method ModalBottomSheetAnchorChangeHandler has parameter &apos;animateTo&apos; with type Function2&lt;? super SheetValue, ? super Float, Unit>."
-        errorLine1="    animateTo: (target: SheetValue, velocity: Float) -> Unit,"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method Scrim has parameter &apos;fraction&apos; with type Function0&lt;Float>."
         errorLine1="    fraction: () -> Float,"
         errorLine2="              ~~~~~~~~~~~">
@@ -687,15 +1866,6 @@
 
     <issue
         id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method swipeAnchors has parameter &apos;calculateAnchor&apos; with type Function2&lt;? super T, ? super IntSize, Float>."
-        errorLine1="    calculateAnchor: (value: T, layoutSize: IntSize) -> Float?,"
-        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/material3/SwipeableV2.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in variable &apos;valueToOffset&apos; with type Function1&lt;? super Boolean, ? extends Float>."
         errorLine1="    val valueToOffset = remember&lt;(Boolean) -> Float>(minBound, maxBound) {"
         errorLine2="    ^">
diff --git a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
index 8a45008..ccfc03e 100644
--- a/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
+++ b/compose/material3/material3/samples/src/main/java/androidx/compose/material3/samples/TooltipSamples.kt
@@ -28,12 +28,13 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.OutlinedButton
-import androidx.compose.material3.PlainTooltipBox
-import androidx.compose.material3.RichTooltipBox
+import androidx.compose.material3.PlainTooltip
+import androidx.compose.material3.RichTooltip
 import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
-import androidx.compose.material3.rememberPlainTooltipState
-import androidx.compose.material3.rememberRichTooltipState
+import androidx.compose.material3.TooltipBox
+import androidx.compose.material3.TooltipDefaults
+import androidx.compose.material3.rememberTooltipState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
@@ -47,12 +48,17 @@
 @Sampled
 @Composable
 fun PlainTooltipSample() {
-    PlainTooltipBox(
-        tooltip = { Text("Add to favorites") }
+    TooltipBox(
+        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+        tooltip = {
+            PlainTooltip {
+                Text("Add to favorites")
+            }
+        },
+        state = rememberTooltipState()
     ) {
         IconButton(
-            onClick = { /* Icon button's click event */ },
-            modifier = Modifier.tooltipTrigger()
+            onClick = { /* Icon button's click event */ }
         ) {
             Icon(
                 imageVector = Icons.Filled.Favorite,
@@ -67,14 +73,19 @@
 @Sampled
 @Composable
 fun PlainTooltipWithManualInvocationSample() {
-    val tooltipState = rememberPlainTooltipState()
+    val tooltipState = rememberTooltipState()
     val scope = rememberCoroutineScope()
     Column(
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
-        PlainTooltipBox(
-            tooltip = { Text("Add to list") },
-            tooltipState = tooltipState
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            tooltip = {
+                PlainTooltip {
+                    Text("Add to list")
+                }
+            },
+            state = tooltipState
         ) {
             Icon(
                 imageVector = Icons.Filled.AddCircle,
@@ -94,21 +105,26 @@
 @Sampled
 @Composable
 fun RichTooltipSample() {
-    val tooltipState = rememberRichTooltipState(isPersistent = true)
+    val tooltipState = rememberTooltipState(isPersistent = true)
     val scope = rememberCoroutineScope()
-    RichTooltipBox(
-        title = { Text(richTooltipSubheadText) },
-        action = {
-            TextButton(
-                onClick = { scope.launch { tooltipState.dismiss() } }
-            ) { Text(richTooltipActionText) }
+    TooltipBox(
+        positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+        tooltip = {
+            RichTooltip(
+                title = { Text(richTooltipSubheadText) },
+                action = {
+                    TextButton(
+                        onClick = { scope.launch { tooltipState.dismiss() } }
+                    ) { Text(richTooltipActionText) }
+                }
+            ) {
+                Text(richTooltipText)
+            }
         },
-        text = { Text(richTooltipText) },
-        tooltipState = tooltipState
+        state = tooltipState
     ) {
         IconButton(
-            onClick = { /* Icon button's click event */ },
-            modifier = Modifier.tooltipTrigger()
+            onClick = { /* Icon button's click event */ }
         ) {
             Icon(
                 imageVector = Icons.Filled.Info,
@@ -117,28 +133,33 @@
         }
     }
 }
+
 @OptIn(ExperimentalMaterial3Api::class)
 @Sampled
 @Composable
 fun RichTooltipWithManualInvocationSample() {
-    val tooltipState = rememberRichTooltipState(isPersistent = true)
+    val tooltipState = rememberTooltipState(isPersistent = true)
     val scope = rememberCoroutineScope()
     Column(
         horizontalAlignment = Alignment.CenterHorizontally
     ) {
-        RichTooltipBox(
-            title = { Text(richTooltipSubheadText) },
-            action = {
-                TextButton(
-                    onClick = {
-                        scope.launch {
-                            tooltipState.dismiss()
-                        }
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            tooltip = {
+                RichTooltip(
+                    title = { Text(richTooltipSubheadText) },
+                    action = {
+                        TextButton(
+                            onClick = {
+                                scope.launch {
+                                    tooltipState.dismiss()
+                                }
+                            }
+                        ) { Text(richTooltipActionText) }
                     }
-                ) { Text(richTooltipActionText) }
+                ) { Text(richTooltipText) }
             },
-            text = { Text(richTooltipText) },
-            tooltipState = tooltipState
+            state = tooltipState
         ) {
             Icon(
                 imageVector = Icons.Filled.Info,
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/CalendarModelTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/CalendarModelTest.kt
index cf1d8dd..c7e969b 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/CalendarModelTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/CalendarModelTest.kt
@@ -223,16 +223,16 @@
         assertThat(newModel.plusMonths(month, 3)).isEqualTo(legacyModel.plusMonths(month, 3))
         assertThat(date).isEqualTo(legacyDate)
         assertThat(newModel.getDayOfWeek(date)).isEqualTo(legacyModel.getDayOfWeek(date))
-        assertThat(newModel.formatWithSkeleton(date, "MMM d, yyyy")).isEqualTo(
+        assertThat(newModel.formatWithSkeleton(date, "dMMMy")).isEqualTo(
             legacyModel.formatWithSkeleton(
                 date,
-                "MMM d, yyyy"
+                "dMMMy"
             )
         )
-        assertThat(newModel.formatWithSkeleton(month, "MMM yyyy")).isEqualTo(
+        assertThat(newModel.formatWithSkeleton(month, "MMMy")).isEqualTo(
             legacyModel.formatWithSkeleton(
                 month,
-                "MMM yyyy"
+                "MMMy"
             )
         )
     }
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateInputTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateInputTest.kt
index 7e7fe30..025e846 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateInputTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateInputTest.kt
@@ -224,7 +224,8 @@
         val fullDateDescription = formatWithSkeleton(
             selectedDateInUtcMillis,
             DatePickerDefaults.YearMonthWeekdayDaySkeleton,
-            Locale.US
+            Locale.US,
+            cache = mutableMapOf()
         )
 
         rule.onNodeWithText("May 11, 2010")
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
index 1d921e2..af0ce1f 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DatePickerTest.kt
@@ -501,7 +501,8 @@
         val fullDateDescription = formatWithSkeleton(
             selectedDateInUtcMillis,
             DatePickerDefaults.YearMonthWeekdayDaySkeleton,
-            Locale.US
+            Locale.US,
+            cache = mutableMapOf()
         )
 
         rule.onNodeWithContentDescription(label = "next", substring = true, ignoreCase = true)
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt
index a7b3187..eabb443 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/DateRangeInputTest.kt
@@ -242,16 +242,18 @@
                 )
             )
         }
-
+        val cache = mutableMapOf<String, Any>()
         val fullStartDateDescription = formatWithSkeleton(
             startDateMillis,
             DatePickerDefaults.YearMonthWeekdayDaySkeleton,
-            Locale.US
+            Locale.US,
+            cache
         )
         val fullEndDateDescription = formatWithSkeleton(
             endDateMillis,
             DatePickerDefaults.YearMonthWeekdayDaySkeleton,
-            Locale.US
+            Locale.US,
+            cache
         )
 
         val startHeadlineDescription = "$pickerStartDateHeadline: $fullStartDateDescription"
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
index e5fe046..bbae528 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ExposedDropdownMenuTest.kt
@@ -16,6 +16,10 @@
 
 package androidx.compose.material3
 
+import android.app.Activity
+import android.content.Context
+import android.content.ContextWrapper
+import android.view.WindowManager
 import android.widget.FrameLayout
 import androidx.compose.foundation.ScrollState
 import androidx.compose.foundation.gestures.animateScrollBy
@@ -30,7 +34,7 @@
 import androidx.compose.foundation.rememberScrollState
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.SideEffect
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
@@ -45,6 +49,7 @@
 import androidx.compose.ui.layout.onGloballyPositioned
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.test.assertIsDisplayed
@@ -57,10 +62,10 @@
 import androidx.compose.ui.test.performClick
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.test.swipe
+import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.viewinterop.AndroidView
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.uiautomator.By
@@ -68,16 +73,25 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
 import org.junit.Assume.assumeNotNull
 import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
 
 @OptIn(ExperimentalMaterial3Api::class)
 @MediumTest
-@RunWith(AndroidJUnit4::class)
-class ExposedDropdownMenuTest {
+@RunWith(Parameterized::class)
+class ExposedDropdownMenuTest(
+    private val softInputMode: SoftInputMode,
+) {
+    companion object {
+        @JvmStatic
+        @Parameterized.Parameters(name = "{0}")
+        fun parameters() = SoftInputMode.values()
+    }
 
     @get:Rule
     val rule = createComposeRule()
@@ -92,6 +106,7 @@
     fun edm_expandsOnClick_andCollapsesOnClickOutside() {
         var textFieldBounds = Rect.Zero
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(false) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -122,6 +137,7 @@
     @Test
     fun edm_collapsesOnTextFieldClick() {
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(true) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -142,6 +158,7 @@
     @Test
     fun edm_doesNotCollapse_whenTypingOnSoftKeyboard() {
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(false) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -177,6 +194,7 @@
     @Test
     fun edm_expandsAndFocusesTextField_whenTrailingIconClicked() {
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(false) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -198,6 +216,7 @@
     fun edm_doesNotExpand_ifTouchEndsOutsideBounds() {
         var textFieldBounds = Rect.Zero
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(false) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -237,6 +256,7 @@
         val testIndex = 2
         var textFieldSize = IntSize.Zero
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             LazyColumn(
                 modifier = Modifier.fillMaxSize(),
                 horizontalAlignment = Alignment.CenterHorizontally,
@@ -322,6 +342,7 @@
         lateinit var scrollState: ScrollState
         lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             scrollState = rememberScrollState()
             scope = rememberCoroutineScope()
             Column(Modifier.verticalScroll(scrollState)) {
@@ -370,6 +391,7 @@
         var textFieldBounds by mutableStateOf(Rect.Zero)
         var menuBounds by mutableStateOf(Rect.Zero)
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(true) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -394,6 +416,7 @@
     @Test
     fun edm_collapsesWithSelection_whenMenuItemClicked() {
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             var expanded by remember { mutableStateOf(true) }
             ExposedDropdownMenuForTest(
                 expanded = expanded,
@@ -412,11 +435,59 @@
         rule.onNodeWithTag(TFTag).assertTextContains(OptionName)
     }
 
+    @Test
+    fun edm_resizesWithinWindowBounds_uponImeAppearance() {
+        var actualMenuSize: IntSize? = null
+        var density: Density? = null
+        val itemSize = 50.dp
+        val itemCount = 10
+
+        rule.setMaterialContent(lightColorScheme()) {
+            density = LocalDensity.current
+            SoftInputMode(softInputMode)
+            Column(Modifier.fillMaxSize()) {
+                // Push the EDM down so opening the keyboard causes a pan/scroll
+                Spacer(Modifier.weight(1f))
+
+                ExposedDropdownMenuBox(
+                    expanded = true,
+                    onExpandedChange = { }
+                ) {
+                    TextField(
+                        modifier = Modifier.menuAnchor(),
+                        value = "",
+                        onValueChange = { },
+                        label = { Text("Label") },
+                    )
+                    ExposedDropdownMenu(
+                        expanded = true,
+                        onDismissRequest = { },
+                        modifier = Modifier.onGloballyPositioned {
+                            actualMenuSize = it.size
+                        }
+                    ) {
+                        repeat(itemCount) {
+                            Box(Modifier.size(itemSize))
+                        }
+                    }
+                }
+            }
+        }
+
+        // This would fit on screen if the keyboard wasn't displayed.
+        val menuPreferredHeight = with(density!!) {
+            (itemSize * itemCount + DropdownMenuVerticalPadding * 2).roundToPx()
+        }
+        // But the keyboard *is* displayed, forcing the actual size to be smaller.
+        assertThat(actualMenuSize!!.height).isLessThan(menuPreferredHeight)
+    }
+
     @Ignore("b/266109857")
     @Test
     fun edm_doesNotCrash_whenAnchorDetachedFirst() {
         var parent: FrameLayout? = null
-        rule.setContent {
+        rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             AndroidView(
                 factory = { context ->
                     FrameLayout(context).apply {
@@ -457,14 +528,16 @@
     @OptIn(ExperimentalMaterial3Api::class)
     @Test
     fun edm_withScrolledContent() {
+        lateinit var scrollState: ScrollState
         rule.setMaterialContent(lightColorScheme()) {
+            SoftInputMode(softInputMode)
             Box(Modifier.fillMaxSize()) {
                 ExposedDropdownMenuBox(
                     modifier = Modifier.align(Alignment.Center),
                     expanded = true,
                     onExpandedChange = { }
                 ) {
-                    val scrollState = rememberScrollState()
+                    scrollState = rememberScrollState()
                     TextField(
                         modifier = Modifier.menuAnchor(),
                         value = "",
@@ -477,20 +550,22 @@
                         scrollState = scrollState
                     ) {
                         repeat(100) {
-                            Box(
-                                Modifier
-                                    .testTag("MenuContent ${it + 1}")
-                                    .size(with(LocalDensity.current) { 70.toDp() })
+                            Text(
+                                text = "Text ${it + 1}",
+                                modifier = Modifier.testTag("MenuContent ${it + 1}"),
                             )
                         }
                     }
-                    LaunchedEffect(Unit) {
-                        scrollState.scrollTo(scrollState.maxValue)
-                    }
                 }
             }
         }
 
+        rule.runOnIdle {
+            runBlocking {
+                scrollState.scrollTo(scrollState.maxValue)
+            }
+        }
+
         rule.waitForIdle()
 
         rule.onNodeWithTag("MenuContent 1").assertIsNotDisplayed()
@@ -554,3 +629,30 @@
         }
     }
 }
+
+enum class SoftInputMode {
+    AdjustResize,
+    AdjustPan
+}
+
+@Suppress("DEPRECATION")
+@Composable
+fun SoftInputMode(mode: SoftInputMode) {
+    val context = LocalContext.current
+    DisposableEffect(mode) {
+        val activity = context.findActivityOrNull() ?: return@DisposableEffect onDispose {}
+        val originalMode = activity.window.attributes.softInputMode
+        activity.window.setSoftInputMode(when (mode) {
+            SoftInputMode.AdjustResize -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+            SoftInputMode.AdjustPan -> WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN
+        })
+        onDispose {
+            activity.window.setSoftInputMode(originalMode)
+        }
+    }
+}
+
+private tailrec fun Context.findActivityOrNull(): Activity? {
+    return (this as? Activity)
+        ?: (this as? ContextWrapper)?.baseContext?.findActivityOrNull()
+}
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
index 4d11904..9dfb619 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/FloatingActionButtonTest.kt
@@ -16,6 +16,8 @@
 
 package androidx.compose.material3
 
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
@@ -28,6 +30,7 @@
 import androidx.compose.material3.tokens.FabPrimarySmallTokens
 import androidx.compose.material3.tokens.FabPrimaryTokens
 import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.State
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.setValue
@@ -56,6 +59,7 @@
 import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.font.FontFamily
 import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.TextUnit
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -540,6 +544,127 @@
             .assertHeightIsEqualTo(FabPrimaryTokens.ContainerHeight)
             .assertWidthIsEqualTo(FabPrimaryTokens.ContainerWidth)
     }
+
+    @Test
+    fun floatingActionButtonElevation_newInteraction() {
+        val interactionSource = MutableInteractionSource()
+        val defaultElevation = 1.dp
+        val pressedElevation = 2.dp
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var tonalElevation: State<Dp>
+        lateinit var shadowElevation: State<Dp>
+
+        rule.setMaterialContent(lightColorScheme()) {
+            val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            tonalElevation = fabElevation.tonalElevation(interactionSource)
+            shadowElevation = fabElevation.shadowElevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(defaultElevation)
+            assertThat(shadowElevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            interactionSource.tryEmit(PressInteraction.Press(Offset.Zero))
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(pressedElevation)
+            assertThat(shadowElevation.value).isEqualTo(pressedElevation)
+        }
+    }
+
+    @Test
+    fun floatingActionButtonElevation_newValue() {
+        val interactionSource = MutableInteractionSource()
+        var defaultElevation by mutableStateOf(1.dp)
+        val pressedElevation = 2.dp
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var tonalElevation: State<Dp>
+        lateinit var shadowElevation: State<Dp>
+
+        rule.setMaterialContent(lightColorScheme()) {
+            val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            tonalElevation = fabElevation.tonalElevation(interactionSource)
+            shadowElevation = fabElevation.shadowElevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(defaultElevation)
+            assertThat(shadowElevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            defaultElevation = 5.dp
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(5.dp)
+            assertThat(shadowElevation.value).isEqualTo(5.dp)
+        }
+    }
+
+    @Test
+    fun floatingActionButtonElevation_newValueDuringInteraction() {
+        val interactionSource = MutableInteractionSource()
+        val defaultElevation = 1.dp
+        var pressedElevation by mutableStateOf(2.dp)
+        val hoveredElevation = 3.dp
+        val focusedElevation = 4.dp
+        lateinit var tonalElevation: State<Dp>
+        lateinit var shadowElevation: State<Dp>
+
+        rule.setMaterialContent(lightColorScheme()) {
+            val fabElevation = FloatingActionButtonDefaults.elevation(
+                defaultElevation = defaultElevation,
+                pressedElevation = pressedElevation,
+                hoveredElevation = hoveredElevation,
+                focusedElevation = focusedElevation
+            )
+
+            tonalElevation = fabElevation.tonalElevation(interactionSource)
+            shadowElevation = fabElevation.shadowElevation(interactionSource)
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(defaultElevation)
+            assertThat(shadowElevation.value).isEqualTo(defaultElevation)
+        }
+
+        rule.runOnIdle {
+            interactionSource.tryEmit(PressInteraction.Press(Offset.Zero))
+        }
+
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(pressedElevation)
+            assertThat(shadowElevation.value).isEqualTo(pressedElevation)
+        }
+
+        rule.runOnIdle {
+            pressedElevation = 5.dp
+        }
+
+        // We are still pressed, so we should now show the updated value for the pressed state
+        rule.runOnIdle {
+            assertThat(tonalElevation.value).isEqualTo(5.dp)
+            assertThat(shadowElevation.value).isEqualTo(5.dp)
+        }
+    }
 }
 
 fun assertWithinOnePixel(expected: Offset, actual: Offset) {
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
index a3fcc88..85a2ddc 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/ModalBottomSheetTest.kt
@@ -80,6 +80,8 @@
 import com.google.common.truth.Truth.assertThat
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
+import junit.framework.TestCase.assertFalse
+import junit.framework.TestCase.assertTrue
 import junit.framework.TestCase.fail
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
@@ -273,12 +275,13 @@
                 onDismissRequest = {},
                 sheetState = sheetState,
                 windowInsets = windowInsets
-                ) {
+            ) {
                 Box(
                     Modifier
                         // Deliberately use fraction != 1f
                         .fillMaxSize(0.6f)
-                        .testTag(sheetTag))
+                        .testTag(sheetTag)
+                )
             }
         }
 
@@ -309,7 +312,8 @@
                     Box(
                         Modifier
                             .fillMaxHeight(0.4f)
-                            .testTag(sheetTag)) {
+                            .testTag(sheetTag)
+                    ) {
                         Button(
                             onClick = { dispatcher.onBackPressed() },
                             modifier = Modifier.testTag(BackTestTag),
@@ -348,7 +352,8 @@
                     Box(
                         Modifier
                             .fillMaxHeight(0.6f)
-                            .testTag(sheetTag)) {
+                            .testTag(sheetTag)
+                    ) {
                         Button(
                             onClick = { dispatcher.onBackPressed() },
                             modifier = Modifier.testTag(BackTestTag),
@@ -424,14 +429,14 @@
                 sheetState = state,
                 dragHandle = null,
                 windowInsets = windowInsets
-                ) {}
+            ) {}
         }
-        assertThat(state.swipeableState.currentValue).isEqualTo(SheetValue.Hidden)
+        assertThat(state.anchoredDraggableState.currentValue).isEqualTo(SheetValue.Hidden)
         val hiddenOffset = state.requireOffset()
         scope.launch { state.show() }
         rule.waitForIdle()
 
-        assertThat(state.swipeableState.currentValue).isEqualTo(SheetValue.Expanded)
+        assertThat(state.anchoredDraggableState.currentValue).isEqualTo(SheetValue.Expanded)
         val expandedOffset = state.requireOffset()
 
         assertThat(hiddenOffset).isEqualTo(expandedOffset)
@@ -479,17 +484,16 @@
         rule.waitForIdle()
         assertThat(state.currentValue).isEqualTo(SheetValue.PartiallyExpanded) // We should
         // retain the current value if possible
-        assertThat(state.swipeableState.anchors).containsKey(SheetValue.Hidden)
-        assertThat(state.swipeableState.anchors).containsKey(SheetValue.PartiallyExpanded)
-        assertThat(state.swipeableState.anchors).containsKey(SheetValue.Expanded)
+        assertTrue(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Hidden))
+        assertTrue(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.PartiallyExpanded))
+        assertTrue(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Expanded))
 
         amountOfItems = 0 // When the sheet height is 0, we should only have a hidden anchor
         rule.waitForIdle()
         assertThat(state.currentValue).isEqualTo(SheetValue.Hidden)
-        assertThat(state.swipeableState.anchors).containsKey(SheetValue.Hidden)
-        assertThat(state.swipeableState.anchors)
-            .doesNotContainKey(SheetValue.PartiallyExpanded)
-        assertThat(state.swipeableState.anchors).doesNotContainKey(SheetValue.Expanded)
+        assertTrue(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Hidden))
+        assertFalse(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.PartiallyExpanded))
+        assertFalse(state.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Expanded))
     }
 
     @Test
@@ -660,10 +664,13 @@
             ModalBottomSheet(
                 onDismissRequest = {},
                 sheetState = sheetState,
-                dragHandle = { Box(
-                    Modifier
-                        .testTag(dragHandleTag)
-                        .size(dragHandleSize)) },
+                dragHandle = {
+                    Box(
+                        Modifier
+                            .testTag(dragHandleTag)
+                            .size(dragHandleSize)
+                    )
+                },
                 windowInsets = windowInsets
             ) {
                 Box(
@@ -847,10 +854,13 @@
                 WindowInsets(0) else BottomSheetDefaults.windowInsets
             ModalBottomSheet(
                 onDismissRequest = {},
-                dragHandle = { Box(
-                    Modifier
-                        .testTag(dragHandleTag)
-                        .size(dragHandleSize)) },
+                dragHandle = {
+                    Box(
+                        Modifier
+                            .testTag(dragHandleTag)
+                            .size(dragHandleSize)
+                    )
+                },
                 windowInsets = windowInsets
             ) {
                 Box(
@@ -878,10 +888,13 @@
             ModalBottomSheet(
                 onDismissRequest = {},
                 sheetState = sheetState,
-                dragHandle = { Box(
-                    Modifier
-                        .testTag(dragHandleTag)
-                        .size(dragHandleSize)) },
+                dragHandle = {
+                    Box(
+                        Modifier
+                            .testTag(dragHandleTag)
+                            .size(dragHandleSize)
+                    )
+                },
                 windowInsets = windowInsets
             ) {
                 Box(
@@ -919,10 +932,13 @@
             ModalBottomSheet(
                 onDismissRequest = {},
                 sheetState = sheetState,
-                dragHandle = { Box(
-                    Modifier
-                        .testTag(dragHandleTag)
-                        .size(dragHandleSize)) },
+                dragHandle = {
+                    Box(
+                        Modifier
+                            .testTag(dragHandleTag)
+                            .size(dragHandleSize)
+                    )
+                },
                 windowInsets = windowInsets
             ) {
                 Box(
@@ -967,10 +983,13 @@
             ModalBottomSheet(
                 onDismissRequest = {},
                 sheetState = sheetState,
-                dragHandle = { Box(
-                    Modifier
-                        .testTag(dragHandleTag)
-                        .size(dragHandleSize)) },
+                dragHandle = {
+                    Box(
+                        Modifier
+                            .testTag(dragHandleTag)
+                            .size(dragHandleSize)
+                    )
+                },
                 windowInsets = windowInsets
             ) {
                 Box(
@@ -1022,10 +1041,10 @@
         }
 
         assertThat(sheetState.currentValue).isEqualTo(SheetValue.Hidden)
-        assertThat(sheetState.swipeableState.hasAnchorForValue(SheetValue.PartiallyExpanded))
-            .isFalse()
-        assertThat(sheetState.swipeableState.hasAnchorForValue(SheetValue.Expanded))
-            .isFalse()
+        assertFalse(
+            sheetState.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.PartiallyExpanded)
+        )
+        assertFalse(sheetState.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Expanded))
 
         scope.launch { sheetState.show() }
         rule.waitForIdle()
@@ -1061,10 +1080,10 @@
         }
 
         assertThat(sheetState.currentValue).isEqualTo(SheetValue.Hidden)
-        assertThat(sheetState.swipeableState.hasAnchorForValue(SheetValue.PartiallyExpanded))
-            .isFalse()
-        assertThat(sheetState.swipeableState.hasAnchorForValue(SheetValue.Expanded))
-            .isFalse()
+        assertFalse(
+            sheetState.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.PartiallyExpanded)
+        )
+        assertFalse(sheetState.anchoredDraggableState.anchors.hasAnchorFor(SheetValue.Expanded))
 
         scope.launch { sheetState.show() }
         rule.waitForIdle()
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
index c9a6824..4abf86f9 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipScreenshotTest.kt
@@ -123,43 +123,49 @@
 
     @Composable
     private fun PlainTooltipTest() {
-        val tooltipState = rememberPlainTooltipState()
-        PlainTooltipBox(
-            tooltip = { Text("Tooltip Description") },
-            modifier = Modifier.testTag(TooltipTestTag),
-            tooltipState = tooltipState
+        val tooltipState = rememberTooltipState()
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            tooltip = {
+                PlainTooltip(
+                    modifier = Modifier.testTag(TooltipTestTag)
+                ) {
+                    Text("Tooltip Description")
+                }
+            },
+            modifier = Modifier.testTag(AnchorTestTag),
+            state = tooltipState
         ) {
             Icon(
                 Icons.Filled.Favorite,
-                contentDescription = null,
-                modifier = Modifier
-                    .testTag(AnchorTestTag)
-                    .tooltipTrigger()
+                contentDescription = null
             )
         }
     }
 
     @Composable
     private fun RichTooltipTest() {
-        val tooltipState = rememberRichTooltipState(isPersistent = true)
-        RichTooltipBox(
-            title = { Text("Title") },
-            text = {
-                Text(
-                    "Area for supportive text, providing a descriptive " +
-                        "message for the composable that the tooltip is anchored to."
-                )
+        val tooltipState = rememberTooltipState(isPersistent = true)
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            tooltip = {
+                RichTooltip(
+                    title = { Text("Title") },
+                    action = { TextButton(onClick = {}) { Text("Action Text") } },
+                    modifier = Modifier.testTag(TooltipTestTag)
+                ) {
+                    Text(
+                        "Area for supportive text, providing a descriptive " +
+                            "message for the composable that the tooltip is anchored to."
+                    )
+                }
             },
-            action = { TextButton(onClick = {}) { Text("Action Text") } },
-            tooltipState = tooltipState,
-            modifier = Modifier.testTag(TooltipTestTag)
+            state = tooltipState,
+            modifier = Modifier.testTag(AnchorTestTag)
         ) {
             Icon(
                 Icons.Filled.Favorite,
-                contentDescription = null,
-                modifier = Modifier
-                    .testTag(AnchorTestTag)
-                    .tooltipTrigger()
+                contentDescription = null
             )
         }
     }
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
index 70e6b64..8d05565 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TooltipTest.kt
@@ -16,6 +16,7 @@
 
 package androidx.compose.material3
 
+import androidx.compose.foundation.BasicTooltipDefaults
 import androidx.compose.foundation.MutatorMutex
 import androidx.compose.foundation.layout.size
 import androidx.compose.material.icons.Icons
@@ -31,13 +32,13 @@
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.getUnclippedBoundsInRoot
 import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.longClick
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.performTouchInput
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 import org.junit.Rule
 import org.junit.Test
@@ -53,13 +54,21 @@
 
     @Test
     fun plainTooltip_noContent_size() {
-        rule.setMaterialContent(lightColorScheme()) { PlainTooltipTest() }
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
+        rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState()
+            scope = rememberCoroutineScope()
+            PlainTooltipTest(tooltipState = state)
+        }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -72,13 +81,21 @@
 
     @Test
     fun richTooltip_noContent_size() {
-        rule.setMaterialContent(lightColorScheme()) { RichTooltipTest() }
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
+        rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState(isPersistent = true)
+            scope = rememberCoroutineScope()
+            RichTooltipTest(tooltipState = state)
+        }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -93,17 +110,24 @@
     fun plainTooltip_customSize_size() {
         val customWidth = 100.dp
         val customHeight = 100.dp
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState()
+            scope = rememberCoroutineScope()
             PlainTooltipTest(
-                modifier = Modifier.size(customWidth, customHeight)
+                modifier = Modifier.size(customWidth, customHeight),
+                tooltipState = state
             )
         }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -118,17 +142,24 @@
     fun richTooltip_customSize_size() {
         val customWidth = 100.dp
         val customHeight = 100.dp
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState(isPersistent = true)
+            scope = rememberCoroutineScope()
             RichTooltipTest(
-                modifier = Modifier.size(customWidth, customHeight)
+                modifier = Modifier.size(customWidth, customHeight),
+                tooltipState = state
             )
         }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -141,22 +172,29 @@
 
     @Test
     fun plainTooltip_content_padding() {
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState()
+            scope = rememberCoroutineScope()
             PlainTooltipTest(
                 tooltipContent = {
                     Text(
                         text = "Test",
                         modifier = Modifier.testTag(TextTestTag)
                     )
-                }
+                },
+                tooltipState = state
             )
         }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -169,19 +207,26 @@
 
     @Test
     fun richTooltip_content_padding() {
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
+            state = rememberTooltipState(isPersistent = true)
+            scope = rememberCoroutineScope()
             RichTooltipTest(
                 title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
                 text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                action = { Text(text = "Action", modifier = Modifier.testTag(ActionTestTag)) }
+                action = { Text(text = "Action", modifier = Modifier.testTag(ActionTestTag)) },
+                tooltipState = state
             )
         }
 
         // Stop auto advance for test consistency
         rule.mainClock.autoAdvance = false
 
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
@@ -211,12 +256,14 @@
 
     @Test
     fun plainTooltip_behavior() {
-        lateinit var tooltipState: PlainTooltipState
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
-            tooltipState = rememberPlainTooltipState()
+            state = rememberTooltipState()
+            scope = rememberCoroutineScope()
             PlainTooltipTest(
                 tooltipContent = { Text(text = "Test", modifier = Modifier.testTag(TextTestTag)) },
-                tooltipState = tooltipState
+                tooltipState = state
             )
         }
 
@@ -224,34 +271,37 @@
         rule.mainClock.autoAdvance = false
 
         // Tooltip should initially be not visible
-        assertThat(tooltipState.isVisible).isFalse()
+        assertThat(state.isVisible).isFalse()
 
-        // Long press the icon
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
 
         // Check that the tooltip is now showing
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isTrue()
+        assertThat(state.isVisible).isTrue()
 
         // Tooltip should dismiss itself after 1.5s
-        rule.mainClock.advanceTimeBy(milliseconds = TooltipDuration)
+        rule.mainClock.advanceTimeBy(milliseconds = BasicTooltipDefaults.TooltipDuration)
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isFalse()
+        assertThat(state.isVisible).isFalse()
     }
 
     @Test
     fun richTooltip_behavior_noAction() {
-        lateinit var tooltipState: RichTooltipState
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
-            tooltipState = rememberRichTooltipState(isPersistent = false)
+            state = rememberTooltipState(isPersistent = false)
+            scope = rememberCoroutineScope()
             RichTooltipTest(
                 title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
                 text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                tooltipState = tooltipState
+                tooltipState = state
             )
         }
 
@@ -259,41 +309,43 @@
         rule.mainClock.autoAdvance = false
 
         // Tooltip should initially be not visible
-        assertThat(tooltipState.isVisible).isFalse()
+        assertThat(state.isVisible).isFalse()
 
-        // Long press the icon
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
 
         // Check that the tooltip is now showing
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isTrue()
+        assertThat(state.isVisible).isTrue()
 
         // Tooltip should dismiss itself after 1.5s
-        rule.mainClock.advanceTimeBy(milliseconds = TooltipDuration)
+        rule.mainClock.advanceTimeBy(milliseconds = BasicTooltipDefaults.TooltipDuration)
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isFalse()
+        assertThat(state.isVisible).isFalse()
     }
 
     @Test
     fun richTooltip_behavior_persistent() {
-        lateinit var tooltipState: RichTooltipState
+        lateinit var state: TooltipState
+        lateinit var scope: CoroutineScope
         rule.setMaterialContent(lightColorScheme()) {
-            tooltipState = rememberRichTooltipState(isPersistent = true)
-            val scope = rememberCoroutineScope()
+            state = rememberTooltipState(isPersistent = true)
+            scope = rememberCoroutineScope()
             RichTooltipTest(
                 title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
                 text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
                 action = {
                     TextButton(
-                        onClick = { scope.launch { tooltipState.dismiss() } },
+                        onClick = { scope.launch { state.dismiss() } },
                         modifier = Modifier.testTag(ActionTestTag)
                     ) { Text(text = "Action") }
                 },
-                tooltipState = tooltipState
+                tooltipState = state
             )
         }
 
@@ -301,72 +353,90 @@
         rule.mainClock.autoAdvance = false
 
         // Tooltip should initially be not visible
-        assertThat(tooltipState.isVisible).isFalse()
+        assertThat(state.isVisible).isFalse()
 
-        // Long press the icon
-        rule.onNodeWithTag(AnchorTestTag)
-            .performTouchInput { longClick() }
+        // Trigger tooltip
+        scope.launch {
+            state.show()
+        }
 
         // Advance by the fade in time
         rule.mainClock.advanceTimeBy(TooltipFadeInDuration.toLong())
 
         // Check that the tooltip is now showing
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isTrue()
+        assertThat(state.isVisible).isTrue()
 
         // Tooltip should still be visible after the normal TooltipDuration, since we have an action.
-        rule.mainClock.advanceTimeBy(milliseconds = TooltipDuration)
+        rule.mainClock.advanceTimeBy(milliseconds = BasicTooltipDefaults.TooltipDuration)
         rule.waitForIdle()
-        assertThat(tooltipState.isVisible).isTrue()
+        assertThat(state.isVisible).isTrue()
 
         // Click the action and check that it closed the tooltip
         rule.onNodeWithTag(ActionTestTag)
             .performTouchInput { click() }
-        assertThat(tooltipState.isVisible).isFalse()
+
+        // Advance by the fade out duration
+        // plus some additional time to make sure that the tooltip is full faded out.
+        rule.mainClock.advanceTimeBy(TooltipFadeOutDuration.toLong() + 100L)
+        rule.waitForIdle()
+        assertThat(state.isVisible).isFalse()
     }
 
     @Test
     fun tooltipSync_global_onlyOneVisible() {
         val topTooltipTag = "Top Tooltip"
         val bottomTooltipTag = " Bottom Tooltip"
-        lateinit var topState: RichTooltipState
-        lateinit var bottomState: RichTooltipState
+        lateinit var topState: TooltipState
+        lateinit var bottomState: TooltipState
         rule.setMaterialContent(lightColorScheme()) {
             val scope = rememberCoroutineScope()
-            topState = rememberRichTooltipState(isPersistent = true)
-            bottomState = rememberRichTooltipState(isPersistent = true)
+            topState = rememberTooltipState(isPersistent = true)
+            bottomState = rememberTooltipState(isPersistent = true)
+            TooltipBox(
+                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                tooltip = {
+                    RichTooltip(
+                        title = {
+                            Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag))
+                        },
+                        action = {
+                            TextButton(
+                                modifier = Modifier.testTag(ActionTestTag),
+                                onClick = {}
+                            ) {
+                                Text(text = "Action")
+                            }
+                        }
 
-            RichTooltipBox(
-                title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
-                text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                action = {
-                    TextButton(
-                        modifier = Modifier.testTag(ActionTestTag),
-                        onClick = {}
-                    ) {
-                        Text(text = "Action")
-                    }
+                    ) { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) }
                 },
-                tooltipState = topState,
+                state = topState,
                 modifier = Modifier.testTag(topTooltipTag)
             ) {}
+            scope.launch { topState.show() }
 
-            RichTooltipBox(
-                title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
-                text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                action = {
-                    TextButton(
-                        modifier = Modifier.testTag(ActionTestTag),
-                        onClick = {}
-                    ) {
-                        Text(text = "Action")
-                    }
+            TooltipBox(
+                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                tooltip = {
+                    RichTooltip(
+                        title = {
+                            Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag))
+                        },
+                        action = {
+                            TextButton(
+                                modifier = Modifier.testTag(ActionTestTag),
+                                onClick = {}
+                            ) {
+                                Text(text = "Action")
+                            }
+                        }
+
+                    ) { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) }
                 },
-                tooltipState = bottomState,
+                state = bottomState,
                 modifier = Modifier.testTag(bottomTooltipTag)
             ) {}
-
-            scope.launch { topState.show() }
             scope.launch { bottomState.show() }
         }
 
@@ -386,46 +456,60 @@
     fun tooltipSync_local_bothVisible() {
         val topTooltipTag = "Top Tooltip"
         val bottomTooltipTag = " Bottom Tooltip"
-        lateinit var topState: RichTooltipState
-        lateinit var bottomState: RichTooltipState
+        lateinit var topState: TooltipState
+        lateinit var bottomState: TooltipState
         rule.setMaterialContent(lightColorScheme()) {
             val scope = rememberCoroutineScope()
-            topState = rememberRichTooltipState(
+            topState = rememberTooltipState(
                 isPersistent = true,
                 mutatorMutex = MutatorMutex()
             )
-            RichTooltipBox(
-                title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
-                text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                action = {
-                    TextButton(
-                        modifier = Modifier.testTag(ActionTestTag),
-                        onClick = {}
-                    ) {
-                        Text(text = "Action")
-                    }
+            TooltipBox(
+                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                tooltip = {
+                    RichTooltip(
+                        title = {
+                            Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag))
+                        },
+                        action = {
+                            TextButton(
+                                modifier = Modifier.testTag(ActionTestTag),
+                                onClick = {}
+                            ) {
+                                Text(text = "Action")
+                            }
+                        }
+
+                    ) { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) }
                 },
-                tooltipState = topState,
+                state = topState,
                 modifier = Modifier.testTag(topTooltipTag)
             ) {}
             scope.launch { topState.show() }
 
-            bottomState = rememberRichTooltipState(
+            bottomState = rememberTooltipState(
                 isPersistent = true,
                 mutatorMutex = MutatorMutex()
             )
-            RichTooltipBox(
-                title = { Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag)) },
-                text = { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) },
-                action = {
-                    TextButton(
-                        modifier = Modifier.testTag(ActionTestTag),
-                        onClick = {}
-                    ) {
-                        Text(text = "Action")
-                    }
+            TooltipBox(
+                positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+                tooltip = {
+                    RichTooltip(
+                        title = {
+                            Text(text = "Subhead", modifier = Modifier.testTag(SubheadTestTag))
+                        },
+                        action = {
+                            TextButton(
+                                modifier = Modifier.testTag(ActionTestTag),
+                                onClick = {}
+                            ) {
+                                Text(text = "Action")
+                            }
+                        }
+
+                    ) { Text(text = "Text", modifier = Modifier.testTag(TextTestTag)) }
                 },
-                tooltipState = bottomState,
+                state = bottomState,
                 modifier = Modifier.testTag(bottomTooltipTag)
             ) {}
             scope.launch { bottomState.show() }
@@ -447,19 +531,21 @@
     private fun PlainTooltipTest(
         modifier: Modifier = Modifier,
         tooltipContent: @Composable () -> Unit = {},
-        tooltipState: PlainTooltipState = rememberPlainTooltipState(),
+        tooltipState: TooltipState = rememberTooltipState(),
     ) {
-        PlainTooltipBox(
-            tooltip = tooltipContent,
-            tooltipState = tooltipState,
-            modifier = modifier.testTag(ContainerTestTag)
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
+            tooltip = {
+                PlainTooltip(
+                    modifier = modifier.testTag(ContainerTestTag),
+                    content = tooltipContent
+                )
+            },
+            state = tooltipState
         ) {
             Icon(
                 Icons.Filled.Favorite,
-                contentDescription = null,
-                modifier = Modifier
-                    .testTag(AnchorTestTag)
-                    .tooltipTrigger()
+                contentDescription = null
             )
         }
     }
@@ -470,21 +556,23 @@
         text: @Composable () -> Unit = {},
         title: (@Composable () -> Unit)? = null,
         action: (@Composable () -> Unit)? = null,
-        tooltipState: RichTooltipState = rememberRichTooltipState(action != null),
+        tooltipState: TooltipState = rememberTooltipState(action != null),
     ) {
-        RichTooltipBox(
-            text = text,
-            title = title,
-            action = action,
-            tooltipState = tooltipState,
-            modifier = modifier.testTag(ContainerTestTag)
+        TooltipBox(
+            positionProvider = TooltipDefaults.rememberRichTooltipPositionProvider(),
+            tooltip = {
+                RichTooltip(
+                    title = title,
+                    action = action,
+                    modifier = modifier.testTag(ContainerTestTag),
+                    text = text
+                )
+            },
+            state = tooltipState,
         ) {
             Icon(
                 Icons.Filled.Favorite,
-                contentDescription = null,
-                modifier = Modifier
-                    .testTag(AnchorTestTag)
-                    .tooltipTrigger()
+                contentDescription = null
             )
         }
     }
@@ -494,4 +582,3 @@
 private const val TextTestTag = "Text"
 private const val SubheadTestTag = "Subhead"
 private const val ActionTestTag = "Action"
-private const val AnchorTestTag = "Anchor"
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModel.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModel.android.kt
index 26a7b6f..8b9446b 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModel.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModel.android.kt
@@ -43,17 +43,21 @@
  * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
  * @param skeleton a date format skeleton
  * @param locale the [CalendarLocale] to use when formatting the given timestamp
+ * @param cache a [MutableMap] for caching formatter related results for better performance
  */
 @ExperimentalMaterial3Api
 actual fun formatWithSkeleton(
     utcTimeMillis: Long,
     skeleton: String,
-    locale: CalendarLocale
+    locale: CalendarLocale,
+    cache: MutableMap<String, Any>
 ): String {
-    val pattern = DateFormat.getBestDateTimePattern(locale, skeleton)
+    val pattern = cache.getOrPut(key = skeleton + locale.toLanguageTag()) {
+        DateFormat.getBestDateTimePattern(locale, skeleton)
+    }.toString()
     return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
-        CalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale)
+        CalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale, cache)
     } else {
-        LegacyCalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale)
+        LegacyCalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale, cache)
     }
 }
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModelImpl.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModelImpl.android.kt
index 952a15c..78d7752 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModelImpl.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/CalendarModelImpl.android.kt
@@ -134,8 +134,7 @@
         utcTimeMillis: Long,
         pattern: String,
         locale: CalendarLocale
-    ): String =
-        CalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale)
+    ): String = formatWithPattern(utcTimeMillis, pattern, locale, formatterCache)
 
     override fun parse(date: String, pattern: String): CalendarDate? {
         // TODO: A DateTimeFormatter can be reused.
@@ -166,15 +165,15 @@
          * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
          * @param pattern a date format pattern
          * @param locale the [CalendarLocale] to use when formatting the given timestamp
+         * @param cache a [MutableMap] for caching formatter related results for better performance
          */
         fun formatWithPattern(
             utcTimeMillis: Long,
             pattern: String,
-            locale: CalendarLocale
+            locale: CalendarLocale,
+            cache: MutableMap<String, Any>
         ): String {
-            val formatter: DateTimeFormatter =
-                DateTimeFormatter.ofPattern(pattern, locale)
-                    .withDecimalStyle(DecimalStyle.of(locale))
+            val formatter = getCachedDateTimeFormatter(pattern, locale, cache)
             return Instant
                 .ofEpochMilli(utcTimeMillis)
                 .atZone(utcTimeZoneId)
@@ -186,6 +185,18 @@
          * Holds a UTC [ZoneId].
          */
         internal val utcTimeZoneId: ZoneId = ZoneId.of("UTC")
+
+        private fun getCachedDateTimeFormatter(
+            pattern: String,
+            locale: CalendarLocale,
+            cache: MutableMap<String, Any>
+        ): DateTimeFormatter {
+            val key = pattern + locale.toLanguageTag()
+            return cache.getOrPut(key) {
+                DateTimeFormatter.ofPattern(pattern, locale)
+                    .withDecimalStyle(DecimalStyle.of(locale))
+            } as DateTimeFormatter
+        }
     }
 
     private fun getMonth(firstDayLocalDate: LocalDate): CalendarMonth {
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.kt
index bafe835..1fbf2f9 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/DynamicTonalPalette.kt
@@ -29,7 +29,7 @@
 import kotlin.math.roundToInt
 
 /** Dynamic colors in Material. */
-@RequiresApi(Build.VERSION_CODES.S)
+@RequiresApi(31)
 internal fun dynamicTonalPalette(context: Context): TonalPalette = TonalPalette(
     // The neutral tonal range from the generated dynamic color palette.
     neutral100 = ColorResourceHelper.getColor(context, android.R.color.system_neutral1_0),
@@ -72,16 +72,38 @@
     // generated dynamic color palette.
     neutralVariant100 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_0),
     neutralVariant99 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_10),
+    neutralVariant98 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(98f),
+    neutralVariant96 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(96f),
     neutralVariant95 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_50),
+    neutralVariant94 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(94f),
+    neutralVariant92 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(92f),
     neutralVariant90 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_100),
+    neutralVariant87 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(87f),
     neutralVariant80 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_200),
     neutralVariant70 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_300),
     neutralVariant60 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_400),
     neutralVariant50 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_500),
     neutralVariant40 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600),
     neutralVariant30 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_700),
+    neutralVariant24 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(24f),
+    neutralVariant22 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(22f),
     neutralVariant20 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_800),
+    neutralVariant17 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(17f),
+    neutralVariant12 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(12f),
     neutralVariant10 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_900),
+    neutralVariant6 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(6f),
+    neutralVariant4 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_600)
+        .setLuminance(4f),
     neutralVariant0 = ColorResourceHelper.getColor(context, android.R.color.system_neutral2_1000),
 
     // The primary tonal range from the generated dynamic color palette.
@@ -142,40 +164,14 @@
 @RequiresApi(Build.VERSION_CODES.S)
 fun dynamicLightColorScheme(context: Context): ColorScheme {
     val tonalPalette = dynamicTonalPalette(context)
-    return lightColorScheme(
-        primary = tonalPalette.primary40,
-        onPrimary = tonalPalette.primary100,
-        primaryContainer = tonalPalette.primary90,
-        onPrimaryContainer = tonalPalette.primary10,
-        inversePrimary = tonalPalette.primary80,
-        secondary = tonalPalette.secondary40,
-        onSecondary = tonalPalette.secondary100,
-        secondaryContainer = tonalPalette.secondary90,
-        onSecondaryContainer = tonalPalette.secondary10,
-        tertiary = tonalPalette.tertiary40,
-        onTertiary = tonalPalette.tertiary100,
-        tertiaryContainer = tonalPalette.tertiary90,
-        onTertiaryContainer = tonalPalette.tertiary10,
-        background = tonalPalette.neutral99,
-        onBackground = tonalPalette.neutral10,
-        surface = tonalPalette.neutral99,
-        onSurface = tonalPalette.neutral10,
-        surfaceVariant = tonalPalette.neutralVariant90,
-        onSurfaceVariant = tonalPalette.neutralVariant30,
-        inverseSurface = tonalPalette.neutral20,
-        inverseOnSurface = tonalPalette.neutral95,
-        outline = tonalPalette.neutralVariant50,
-        outlineVariant = tonalPalette.neutralVariant80,
-        scrim = tonalPalette.neutral0,
-        surfaceBright = tonalPalette.neutral98,
-        surfaceDim = tonalPalette.neutral87,
-        surfaceContainer = tonalPalette.neutral94,
-        surfaceContainerHigh = tonalPalette.neutral92,
-        surfaceContainerHighest = tonalPalette.neutral90,
-        surfaceContainerLow = tonalPalette.neutral96,
-        surfaceContainerLowest = tonalPalette.neutral100,
-        surfaceTint = tonalPalette.primary40,
-    )
+    return if (Build.VERSION.SDK_INT >= 34) {
+        // SDKs 34 and greater return appropriate Chroma6 values for neutral palette
+        dynamicLightColorScheme34(tonalPalette)
+    } else {
+        // SDKs 31-33 return Chroma4 values for neutral palette, we instead leverage neutral
+        // variant which provides chroma8 for less grey tones.
+        dynamicLightColorScheme31(tonalPalette)
+    }
 }
 
 /**
@@ -190,40 +186,14 @@
 @RequiresApi(Build.VERSION_CODES.S)
 fun dynamicDarkColorScheme(context: Context): ColorScheme {
     val tonalPalette = dynamicTonalPalette(context)
-    return darkColorScheme(
-        primary = tonalPalette.primary80,
-        onPrimary = tonalPalette.primary20,
-        primaryContainer = tonalPalette.primary30,
-        onPrimaryContainer = tonalPalette.primary90,
-        inversePrimary = tonalPalette.primary40,
-        secondary = tonalPalette.secondary80,
-        onSecondary = tonalPalette.secondary20,
-        secondaryContainer = tonalPalette.secondary30,
-        onSecondaryContainer = tonalPalette.secondary90,
-        tertiary = tonalPalette.tertiary80,
-        onTertiary = tonalPalette.tertiary20,
-        tertiaryContainer = tonalPalette.tertiary30,
-        onTertiaryContainer = tonalPalette.tertiary90,
-        background = tonalPalette.neutral10,
-        onBackground = tonalPalette.neutral90,
-        surface = tonalPalette.neutral10,
-        onSurface = tonalPalette.neutral90,
-        surfaceVariant = tonalPalette.neutralVariant30,
-        onSurfaceVariant = tonalPalette.neutralVariant80,
-        inverseSurface = tonalPalette.neutral90,
-        inverseOnSurface = tonalPalette.neutral20,
-        outline = tonalPalette.neutralVariant60,
-        outlineVariant = tonalPalette.neutral30,
-        scrim = tonalPalette.neutral0,
-        surfaceBright = tonalPalette.neutral24,
-        surfaceDim = tonalPalette.neutral6,
-        surfaceContainer = tonalPalette.neutral12,
-        surfaceContainerHigh = tonalPalette.neutral17,
-        surfaceContainerHighest = tonalPalette.neutral22,
-        surfaceContainerLow = tonalPalette.neutral10,
-        surfaceContainerLowest = tonalPalette.neutral4,
-        surfaceTint = tonalPalette.primary80,
-    )
+    return if (Build.VERSION.SDK_INT >= 34) {
+        // SDKs 34 and greater return appropriate Chroma6 values for neutral palette
+        dynamicDarkColorScheme34(tonalPalette)
+    } else {
+        // SDKs 31-33 return Chroma4 values for neutral palette, we instead leverage neutral
+        // variant which provides chroma8 for less grey tones.
+        dynamicDarkColorScheme31(tonalPalette)
+    }
 }
 
 @RequiresApi(23)
@@ -296,3 +266,147 @@
     }
     return MathUtils.clamp((delinearized * 255.0).roundToInt(), 0, 255)
 }
+
+@RequiresApi(31)
+internal fun dynamicLightColorScheme31(tonalPalette: TonalPalette) = lightColorScheme(
+    primary = tonalPalette.primary40,
+    onPrimary = tonalPalette.primary100,
+    primaryContainer = tonalPalette.primary90,
+    onPrimaryContainer = tonalPalette.primary10,
+    inversePrimary = tonalPalette.primary80,
+    secondary = tonalPalette.secondary40,
+    onSecondary = tonalPalette.secondary100,
+    secondaryContainer = tonalPalette.secondary90,
+    onSecondaryContainer = tonalPalette.secondary10,
+    tertiary = tonalPalette.tertiary40,
+    onTertiary = tonalPalette.tertiary100,
+    tertiaryContainer = tonalPalette.tertiary90,
+    onTertiaryContainer = tonalPalette.tertiary10,
+    background = tonalPalette.neutralVariant98,
+    onBackground = tonalPalette.neutralVariant10,
+    surface = tonalPalette.neutralVariant98,
+    onSurface = tonalPalette.neutralVariant10,
+    surfaceVariant = tonalPalette.neutralVariant90,
+    onSurfaceVariant = tonalPalette.neutralVariant30,
+    inverseSurface = tonalPalette.neutralVariant20,
+    inverseOnSurface = tonalPalette.neutralVariant95,
+    outline = tonalPalette.neutralVariant50,
+    outlineVariant = tonalPalette.neutralVariant80,
+    scrim = tonalPalette.neutralVariant0,
+    surfaceBright = tonalPalette.neutralVariant98,
+    surfaceDim = tonalPalette.neutralVariant87,
+    surfaceContainer = tonalPalette.neutralVariant94,
+    surfaceContainerHigh = tonalPalette.neutralVariant92,
+    surfaceContainerHighest = tonalPalette.neutralVariant90,
+    surfaceContainerLow = tonalPalette.neutralVariant96,
+    surfaceContainerLowest = tonalPalette.neutralVariant100,
+    surfaceTint = tonalPalette.primary40,
+)
+
+@RequiresApi(34)
+internal fun dynamicLightColorScheme34(tonalPalette: TonalPalette) = lightColorScheme(
+    primary = tonalPalette.primary40,
+    onPrimary = tonalPalette.primary100,
+    primaryContainer = tonalPalette.primary90,
+    onPrimaryContainer = tonalPalette.primary10,
+    inversePrimary = tonalPalette.primary80,
+    secondary = tonalPalette.secondary40,
+    onSecondary = tonalPalette.secondary100,
+    secondaryContainer = tonalPalette.secondary90,
+    onSecondaryContainer = tonalPalette.secondary10,
+    tertiary = tonalPalette.tertiary40,
+    onTertiary = tonalPalette.tertiary100,
+    tertiaryContainer = tonalPalette.tertiary90,
+    onTertiaryContainer = tonalPalette.tertiary10,
+    background = tonalPalette.neutral99,
+    onBackground = tonalPalette.neutral10,
+    surface = tonalPalette.neutral99,
+    onSurface = tonalPalette.neutral10,
+    surfaceVariant = tonalPalette.neutralVariant90,
+    onSurfaceVariant = tonalPalette.neutralVariant30,
+    inverseSurface = tonalPalette.neutral20,
+    inverseOnSurface = tonalPalette.neutral95,
+    outline = tonalPalette.neutralVariant50,
+    outlineVariant = tonalPalette.neutralVariant80,
+    scrim = tonalPalette.neutral0,
+    surfaceBright = tonalPalette.neutral98,
+    surfaceDim = tonalPalette.neutral87,
+    surfaceContainer = tonalPalette.neutral94,
+    surfaceContainerHigh = tonalPalette.neutral92,
+    surfaceContainerHighest = tonalPalette.neutral90,
+    surfaceContainerLow = tonalPalette.neutral96,
+    surfaceContainerLowest = tonalPalette.neutral100,
+    surfaceTint = tonalPalette.primary40,
+)
+
+@RequiresApi(31)
+internal fun dynamicDarkColorScheme31(tonalPalette: TonalPalette) = darkColorScheme(
+    primary = tonalPalette.primary80,
+    onPrimary = tonalPalette.primary20,
+    primaryContainer = tonalPalette.primary30,
+    onPrimaryContainer = tonalPalette.primary90,
+    inversePrimary = tonalPalette.primary40,
+    secondary = tonalPalette.secondary80,
+    onSecondary = tonalPalette.secondary20,
+    secondaryContainer = tonalPalette.secondary30,
+    onSecondaryContainer = tonalPalette.secondary90,
+    tertiary = tonalPalette.tertiary80,
+    onTertiary = tonalPalette.tertiary20,
+    tertiaryContainer = tonalPalette.tertiary30,
+    onTertiaryContainer = tonalPalette.tertiary90,
+    background = tonalPalette.neutralVariant10,
+    onBackground = tonalPalette.neutralVariant90,
+    surface = tonalPalette.neutralVariant10,
+    onSurface = tonalPalette.neutralVariant90,
+    surfaceVariant = tonalPalette.neutralVariant30,
+    onSurfaceVariant = tonalPalette.neutralVariant80,
+    inverseSurface = tonalPalette.neutralVariant90,
+    inverseOnSurface = tonalPalette.neutralVariant20,
+    outline = tonalPalette.neutralVariant60,
+    outlineVariant = tonalPalette.neutralVariant30,
+    scrim = tonalPalette.neutralVariant0,
+    surfaceBright = tonalPalette.neutralVariant24,
+    surfaceDim = tonalPalette.neutralVariant6,
+    surfaceContainer = tonalPalette.neutralVariant12,
+    surfaceContainerHigh = tonalPalette.neutralVariant17,
+    surfaceContainerHighest = tonalPalette.neutralVariant22,
+    surfaceContainerLow = tonalPalette.neutralVariant10,
+    surfaceContainerLowest = tonalPalette.neutralVariant4,
+    surfaceTint = tonalPalette.primary80,
+)
+
+@RequiresApi(34)
+internal fun dynamicDarkColorScheme34(tonalPalette: TonalPalette) = darkColorScheme(
+    primary = tonalPalette.primary80,
+    onPrimary = tonalPalette.primary20,
+    primaryContainer = tonalPalette.primary30,
+    onPrimaryContainer = tonalPalette.primary90,
+    inversePrimary = tonalPalette.primary40,
+    secondary = tonalPalette.secondary80,
+    onSecondary = tonalPalette.secondary20,
+    secondaryContainer = tonalPalette.secondary30,
+    onSecondaryContainer = tonalPalette.secondary90,
+    tertiary = tonalPalette.tertiary80,
+    onTertiary = tonalPalette.tertiary20,
+    tertiaryContainer = tonalPalette.tertiary30,
+    onTertiaryContainer = tonalPalette.tertiary90,
+    background = tonalPalette.neutral10,
+    onBackground = tonalPalette.neutral90,
+    surface = tonalPalette.neutral10,
+    onSurface = tonalPalette.neutral90,
+    surfaceVariant = tonalPalette.neutralVariant30,
+    onSurfaceVariant = tonalPalette.neutralVariant80,
+    inverseSurface = tonalPalette.neutral90,
+    inverseOnSurface = tonalPalette.neutral20,
+    outline = tonalPalette.neutralVariant60,
+    outlineVariant = tonalPalette.neutral30,
+    scrim = tonalPalette.neutral0,
+    surfaceBright = tonalPalette.neutral24,
+    surfaceDim = tonalPalette.neutral6,
+    surfaceContainer = tonalPalette.neutral12,
+    surfaceContainerHigh = tonalPalette.neutral17,
+    surfaceContainerHighest = tonalPalette.neutral22,
+    surfaceContainerLow = tonalPalette.neutral10,
+    surfaceContainerLowest = tonalPalette.neutral4,
+    surfaceTint = tonalPalette.primary80,
+)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.kt
index dbb011d..b3b34c4 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ExposedDropdownMenu.kt
@@ -71,6 +71,7 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.toSize
 import kotlin.math.max
+import kotlin.math.roundToInt
 
 /**
  * <a href="https://m3.material.io/components/menus/overview" class="external" target="_blank">Material Design Exposed Dropdown Menu</a>.
@@ -78,29 +79,31 @@
  * Menus display a list of choices on a temporary surface. They appear when users interact with a
  * button, action, or other control.
  *
- * Exposed dropdown menus display the currently selected item in a text field to which the menu is
- * anchored. In some cases, it can accept and display user input (whether or not it’s listed as a
- * menu choice). If the text field input is used to filter results in the menu, the component is
- * also known as "autocomplete" or a "combobox".
+ * Exposed dropdown menus, sometimes also called "spinners" or "combo boxes", display the currently
+ * selected item in a text field to which the menu is anchored. In some cases, it can accept and
+ * display user input (whether or not it’s listed as a menu choice), in which case it may be used to
+ * implement autocomplete.
  *
  * ![Exposed dropdown menu image](https://developer.android.com/images/reference/androidx/compose/material3/exposed-dropdown-menu.png)
  *
  * The [ExposedDropdownMenuBox] is expected to contain a [TextField] (or [OutlinedTextField]) and
- * [ExposedDropdownMenuBoxScope.ExposedDropdownMenu] as content.
+ * [ExposedDropdownMenu][ExposedDropdownMenuBoxScope.ExposedDropdownMenu] as content. The
+ * [menuAnchor][ExposedDropdownMenuBoxScope.menuAnchor] modifier should be passed to the text field.
  *
- * An example of read-only Exposed Dropdown Menu:
+ * An example of a read-only Exposed Dropdown Menu:
  * @sample androidx.compose.material3.samples.ExposedDropdownMenuSample
  *
- * An example of editable Exposed Dropdown Menu:
+ * An example of an editable Exposed Dropdown Menu:
  * @sample androidx.compose.material3.samples.EditableExposedDropdownMenuSample
  *
  * @param expanded whether the menu is expanded or not
  * @param onExpandedChange called when the exposed dropdown menu is clicked and the expansion state
  * changes.
- * @param modifier the [Modifier] to be applied to this exposed dropdown menu
- * @param content the content of this exposed dropdown menu, typically a [TextField] and an
- * [ExposedDropdownMenuBoxScope.ExposedDropdownMenu]. The [TextField] within [content] should be
- * passed the [ExposedDropdownMenuBoxScope.menuAnchor] modifier for proper menu behavior.
+ * @param modifier the [Modifier] to be applied to this ExposedDropdownMenuBox
+ * @param content the content of this ExposedDropdownMenuBox, typically a [TextField] and an
+ * [ExposedDropdownMenu][ExposedDropdownMenuBoxScope.ExposedDropdownMenu]. The
+ * [menuAnchor][ExposedDropdownMenuBoxScope.menuAnchor] modifier should be passed to the text field
+ * for proper menu behavior.
  */
 @ExperimentalMaterial3Api
 @Composable
@@ -111,13 +114,14 @@
     content: @Composable ExposedDropdownMenuBoxScope.() -> Unit
 ) {
     val config = LocalConfiguration.current
-    val density = LocalDensity.current
     val view = LocalView.current
+    val density = LocalDensity.current
 
+    val verticalMargin = with(density) { MenuVerticalMargin.roundToPx() }
+
+    var anchorCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
     var anchorWidth by remember { mutableIntStateOf(0) }
     var menuMaxHeight by remember { mutableIntStateOf(0) }
-    val verticalMargin = with(density) { MenuVerticalMargin.roundToPx() }
-    var anchorCoordinates by remember { mutableStateOf<LayoutCoordinates?>(null) }
 
     val focusRequester = remember { FocusRequester() }
     val menuDescription = getString(Strings.ExposedDropdownMenu)
@@ -130,11 +134,10 @@
                 .onGloballyPositioned {
                     anchorCoordinates = it
                     anchorWidth = it.size.width
-                    updateHeight(
+                    menuMaxHeight = calculateMaxHeight(
                         windowBounds = view.rootView.getWindowBounds(),
                         anchorBounds = anchorCoordinates.getAnchorBounds(),
                         verticalMargin = verticalMargin,
-                        onHeightUpdate = { newHeight -> menuMaxHeight = newHeight }
                     )
                 }
                 .expandable(
@@ -166,17 +169,18 @@
         scope.content()
     }
 
-    SideEffect {
-        if (expanded) focusRequester.requestFocus()
+    if (expanded) {
+        SoftKeyboardListener(view, density) {
+            menuMaxHeight = calculateMaxHeight(
+                windowBounds = view.rootView.getWindowBounds(),
+                anchorBounds = anchorCoordinates.getAnchorBounds(),
+                verticalMargin = verticalMargin,
+            )
+        }
     }
 
-    SoftKeyboardListener(view, density) {
-        updateHeight(
-            windowBounds = view.rootView.getWindowBounds(),
-            anchorBounds = anchorCoordinates.getAnchorBounds(),
-            verticalMargin = verticalMargin,
-            onHeightUpdate = { newHeight -> menuMaxHeight = newHeight }
-        )
+    SideEffect {
+        if (expanded) focusRequester.requestFocus()
     }
 }
 
@@ -186,6 +190,8 @@
     density: Density,
     onKeyboardVisibilityChange: () -> Unit,
 ) {
+    // It would be easier to listen to WindowInsets.ime, but that doesn't work with
+    // `setDecorFitsSystemWindows(window, true)`. Instead, listen to the view tree's global layout.
     DisposableEffect(view, density) {
         val listener =
             object : View.OnAttachStateChangeListener, ViewTreeObserver.OnGlobalLayoutListener {
@@ -1052,16 +1058,25 @@
     }
 }
 
-private fun updateHeight(
+private fun calculateMaxHeight(
     windowBounds: Rect,
     anchorBounds: Rect?,
     verticalMargin: Int,
-    onHeightUpdate: (Int) -> Unit
-) {
-    anchorBounds ?: return
-    val heightAbove = anchorBounds.top - windowBounds.top
-    val heightBelow = windowBounds.bottom - windowBounds.top - anchorBounds.bottom
-    onHeightUpdate(max(heightAbove, heightBelow).toInt() - verticalMargin)
+): Int {
+    anchorBounds ?: return 0
+
+    val marginedWindowTop = windowBounds.top + verticalMargin
+    val marginedWindowBottom = windowBounds.bottom - verticalMargin
+    val availableHeight =
+        if (anchorBounds.top > windowBounds.bottom || anchorBounds.bottom < windowBounds.top) {
+            (marginedWindowBottom - marginedWindowTop).roundToInt()
+        } else {
+            val heightAbove = anchorBounds.top - marginedWindowTop
+            val heightBelow = marginedWindowBottom - anchorBounds.bottom
+            max(heightAbove, heightBelow).roundToInt()
+        }
+
+    return max(availableHeight, 0)
 }
 
 private fun View.getWindowBounds(): Rect = ViewRect().let {
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
index abd7fee..85e41b3 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/ModalBottomSheet.android.kt
@@ -28,7 +28,6 @@
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.gestures.detectTapGestures
-import androidx.compose.foundation.gestures.draggable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.BoxWithConstraints
 import androidx.compose.foundation.layout.Column
@@ -64,6 +63,7 @@
 import androidx.compose.ui.graphics.isSpecified
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.AbstractComposeView
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
@@ -88,7 +88,6 @@
 import java.util.UUID
 import kotlin.math.max
 import kotlin.math.roundToInt
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
 
 /**
@@ -144,7 +143,7 @@
     }
     val scope = rememberCoroutineScope()
     val animateToDismiss: () -> Unit = {
-        if (sheetState.swipeableState.confirmValueChange(Hidden)) {
+        if (sheetState.anchoredDraggableState.confirmValueChange(Hidden)) {
             scope.launch { sheetState.hide() }.invokeOnCompletion {
                 if (!sheetState.isVisible) {
                     onDismissRequest()
@@ -158,22 +157,6 @@
         }
     }
 
-    // Callback that is invoked when the anchors have changed.
-    val anchorChangeHandler = remember(sheetState, scope) {
-        ModalBottomSheetAnchorChangeHandler(
-            state = sheetState,
-            animateTo = { target, velocity ->
-                scope.launch { sheetState.animateTo(target, velocity = velocity) }
-            },
-            snapTo = { target ->
-                val didSnapImmediately = sheetState.trySnapTo(target)
-                if (!didSnapImmediately) {
-                    scope.launch { sheetState.snapTo(target) }
-                }
-            }
-        )
-    }
-
     ModalBottomSheetPopup(
         onDismissRequest = {
             if (sheetState.currentValue == Expanded && sheetState.hasPartiallyExpandedState) {
@@ -215,13 +198,14 @@
                             )
                         }
                     )
-                    .modalBottomSheetSwipeable(
+                    .anchoredDraggable(
+                        state = sheetState.anchoredDraggableState,
+                        orientation = Orientation.Vertical,
+                        enabled = sheetState.isVisible
+                    )
+                    .modalBottomSheetAnchors(
                         sheetState = sheetState,
-                        anchorChangeHandler = anchorChangeHandler,
-                        screenHeight = fullHeight.toFloat(),
-                        onDragStopped = {
-                            settleToDismiss(it)
-                        },
+                        fullHeight = fullHeight.toFloat()
                     ),
                 shape = shape,
                 color = containerColor,
@@ -247,14 +231,17 @@
                                         }
                                         if (currentValue == PartiallyExpanded) {
                                             expand(expandActionLabel) {
-                                                if (swipeableState.confirmValueChange(Expanded)) {
+                                                if (anchoredDraggableState.confirmValueChange(
+                                                        Expanded
+                                                    )
+                                                ) {
                                                     scope.launch { sheetState.expand() }
                                                 }
                                                 true
                                             }
                                         } else if (hasPartiallyExpandedState) {
                                             collapse(collapseActionLabel) {
-                                                if (swipeableState.confirmValueChange(
+                                                if (anchoredDraggableState.confirmValueChange(
                                                         PartiallyExpanded
                                                     )
                                                 ) {
@@ -329,63 +316,32 @@
 }
 
 @ExperimentalMaterial3Api
-private fun Modifier.modalBottomSheetSwipeable(
+private fun Modifier.modalBottomSheetAnchors(
     sheetState: SheetState,
-    anchorChangeHandler: AnchorChangeHandler<SheetValue>,
-    screenHeight: Float,
-    onDragStopped: CoroutineScope.(velocity: Float) -> Unit,
-) = draggable(
-    state = sheetState.swipeableState.swipeDraggableState,
-    orientation = Orientation.Vertical,
-    enabled = sheetState.isVisible,
-    startDragImmediately = sheetState.swipeableState.isAnimationRunning,
-    onDragStopped = onDragStopped
-)
-    .swipeAnchors(
-        state = sheetState.swipeableState,
-        anchorChangeHandler = anchorChangeHandler,
-        possibleValues = setOf(Hidden, PartiallyExpanded, Expanded),
-    ) { value, sheetSize ->
-        when (value) {
-            Hidden -> screenHeight
-            PartiallyExpanded -> when {
-                sheetSize.height < screenHeight / 2 -> null
-                sheetState.skipPartiallyExpanded -> null
-                else -> screenHeight / 2f
-            }
+    fullHeight: Float
+) = onSizeChanged { sheetSize ->
 
-            Expanded -> if (sheetSize.height != 0) {
-                max(0f, screenHeight - sheetSize.height)
-            } else null
+    val newAnchors = DraggableAnchors {
+        Hidden at fullHeight
+        if (sheetSize.height > (fullHeight / 2) && !sheetState.skipPartiallyExpanded) {
+            PartiallyExpanded at fullHeight / 2f
+        }
+        if (sheetSize.height != 0) {
+            Expanded at max(0f, fullHeight - sheetSize.height)
         }
     }
 
-@ExperimentalMaterial3Api
-private fun ModalBottomSheetAnchorChangeHandler(
-    state: SheetState,
-    animateTo: (target: SheetValue, velocity: Float) -> Unit,
-    snapTo: (target: SheetValue) -> Unit,
-) = AnchorChangeHandler<SheetValue> { previousTarget, previousAnchors, newAnchors ->
-    val previousTargetOffset = previousAnchors[previousTarget]
-    val newTarget = when (previousTarget) {
+    val newTarget = when (sheetState.anchoredDraggableState.targetValue) {
         Hidden -> Hidden
         PartiallyExpanded, Expanded -> {
-            val hasPartiallyExpandedState = newAnchors.containsKey(PartiallyExpanded)
+            val hasPartiallyExpandedState = newAnchors.hasAnchorFor(PartiallyExpanded)
             val newTarget = if (hasPartiallyExpandedState) PartiallyExpanded
-            else if (newAnchors.containsKey(Expanded)) Expanded else Hidden
+            else if (newAnchors.hasAnchorFor(Expanded)) Expanded else Hidden
             newTarget
         }
     }
-    val newTargetOffset = newAnchors.getValue(newTarget)
-    if (newTargetOffset != previousTargetOffset) {
-        if (state.swipeableState.isAnimationRunning || previousAnchors.isEmpty()) {
-            // Re-target the animation to the new offset if it changed
-            animateTo(newTarget, state.swipeableState.lastVelocity)
-        } else {
-            // Snap to the new offset value of the target if no animation was running
-            snapTo(newTarget)
-        }
-    }
+
+    sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget)
 }
 
 /**
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TooltipPopup.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TooltipPopup.android.kt
deleted file mode 100644
index 1074b7e..0000000
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TooltipPopup.android.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2023 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.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-import androidx.compose.ui.window.PopupProperties
-
-@Composable
-@ExperimentalMaterial3Api
-internal actual fun TooltipPopup(
-    popupPositionProvider: PopupPositionProvider,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean,
-    content: @Composable () -> Unit
-) = Popup(
-    popupPositionProvider = popupPositionProvider,
-    onDismissRequest = onDismissRequest,
-    content = content,
-    properties = PopupProperties(focusable = focusable)
-)
diff --git a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.android.kt b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.android.kt
index 955ebc5..8a90585 100644
--- a/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.android.kt
+++ b/compose/material3/material3/src/androidMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.android.kt
@@ -23,7 +23,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -57,7 +56,7 @@
         }
     )
 
-    return remember { derivedStateOf { listener.isEnabled() } }
+    return listener
 }
 
 @Composable
@@ -77,11 +76,13 @@
     }
 }
 
-private class Listener : AccessibilityStateChangeListener, TouchExplorationStateChangeListener {
+private class Listener : AccessibilityStateChangeListener, TouchExplorationStateChangeListener,
+    State<Boolean> {
     private var accessibilityEnabled by mutableStateOf(false)
     private var touchExplorationEnabled by mutableStateOf(false)
 
-    fun isEnabled() = accessibilityEnabled && touchExplorationEnabled
+    override val value: Boolean
+        get() = accessibilityEnabled && touchExplorationEnabled
 
     override fun onAccessibilityStateChanged(it: Boolean) {
         accessibilityEnabled = it
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AnchoredDraggable.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AnchoredDraggable.kt
new file mode 100644
index 0000000..2d3d220
--- /dev/null
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/AnchoredDraggable.kt
@@ -0,0 +1,791 @@
+/*
+ * 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.material3
+
+/**
+ * This is a copy of androidx.compose.foundation.gestures.AnchoredDraggable until that API is
+ * promoted to stable in foundation. Any changes there should be replicated here.
+ */
+import androidx.annotation.FloatRange
+import androidx.compose.animation.core.AnimationSpec
+import androidx.compose.animation.core.SpringSpec
+import androidx.compose.animation.core.animate
+import androidx.compose.foundation.MutatePriority
+import androidx.compose.foundation.gestures.DragScope
+import androidx.compose.foundation.gestures.DraggableState
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.draggable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.offset
+import androidx.compose.runtime.Stable
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.runtime.structuralEqualityPolicy
+import androidx.compose.ui.Modifier
+import kotlin.math.abs
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+/**
+ * Structure that represents the anchors of a [AnchoredDraggableState].
+ *
+ * See the DraggableAnchors factory method to construct drag anchors using a default implementation.
+ */
+@ExperimentalMaterial3Api
+internal interface DraggableAnchors<T> {
+
+    /**
+     * Get the anchor position for an associated [value]
+     *
+     * @return The position of the anchor, or [Float.NaN] if the anchor does not exist
+     */
+    fun positionOf(value: T): Float
+
+    /**
+     * Whether there is an anchor position associated with the [value]
+     *
+     * @param value The value to look up
+     * @return true if there is an anchor for this value, false if there is no anchor for this value
+     */
+    fun hasAnchorFor(value: T): Boolean
+
+    /**
+     * Find the closest anchor to the [position].
+     *
+     * @param position The position to start searching from
+     *
+     * @return The closest anchor or null if the anchors are empty
+     */
+    fun closestAnchor(position: Float): T?
+
+    /**
+     * Find the closest anchor to the [position], in the specified direction.
+     *
+     * @param position The position to start searching from
+     * @param searchUpwards Whether to search upwards from the current position or downwards
+     *
+     * @return The closest anchor or null if the anchors are empty
+     */
+    fun closestAnchor(position: Float, searchUpwards: Boolean): T?
+
+    /**
+     * The smallest anchor, or [Float.NEGATIVE_INFINITY] if the anchors are empty.
+     */
+    fun minAnchor(): Float
+
+    /**
+     * The biggest anchor, or [Float.POSITIVE_INFINITY] if the anchors are empty.
+     */
+    fun maxAnchor(): Float
+
+    /**
+     * The amount of anchors
+     */
+    val size: Int
+}
+
+/**
+ * [DraggableAnchorsConfig] stores a mutable configuration anchors, comprised of values of [T] and
+ * corresponding [Float] positions. This [DraggableAnchorsConfig] is used to construct an immutable
+ * [DraggableAnchors] instance later on.
+ */
+@ExperimentalMaterial3Api
+internal class DraggableAnchorsConfig<T> {
+
+    internal val anchors = mutableMapOf<T, Float>()
+
+    /**
+     * Set the anchor position for [this] anchor.
+     *
+     * @param position The anchor position.
+     */
+    @Suppress("BuilderSetStyle")
+    infix fun T.at(position: Float) {
+        anchors[this] = position
+    }
+}
+
+/**
+ * Create a new [DraggableAnchors] instance using a builder function.
+ *
+ * @param builder A function with a [DraggableAnchorsConfig] that offers APIs to configure anchors
+ * @return A new [DraggableAnchors] instance with the anchor positions set by the `builder`
+ * function.
+ */
+@ExperimentalMaterial3Api
+internal fun <T : Any> DraggableAnchors(
+    builder: DraggableAnchorsConfig<T>.() -> Unit
+): DraggableAnchors<T> = MapDraggableAnchors(DraggableAnchorsConfig<T>().apply(builder).anchors)
+
+/**
+ * Enable drag gestures between a set of predefined values.
+ *
+ * When a drag is detected, the offset of the [AnchoredDraggableState] will be updated with the drag
+ * delta. You should use this offset to move your content accordingly (see [Modifier.offset]).
+ * When the drag ends, the offset will be animated to one of the anchors and when that anchor is
+ * reached, the value of the [AnchoredDraggableState] will also be updated to the value
+ * corresponding to the new anchor.
+ *
+ * Dragging is constrained between the minimum and maximum anchors.
+ *
+ * @param state The associated [AnchoredDraggableState].
+ * @param orientation The orientation in which the [anchoredDraggable] can be dragged.
+ * @param enabled Whether this [anchoredDraggable] is enabled and should react to the user's input.
+ * @param reverseDirection Whether to reverse the direction of the drag, so a top to bottom
+ * drag will behave like bottom to top, and a left to right drag will behave like right to left.
+ * @param interactionSource Optional [MutableInteractionSource] that will passed on to
+ * the internal [Modifier.draggable].
+ */
+@ExperimentalMaterial3Api
+internal fun <T> Modifier.anchoredDraggable(
+    state: AnchoredDraggableState<T>,
+    orientation: Orientation,
+    enabled: Boolean = true,
+    reverseDirection: Boolean = false,
+    interactionSource: MutableInteractionSource? = null
+) = draggable(
+    state = state.draggableState,
+    orientation = orientation,
+    enabled = enabled,
+    interactionSource = interactionSource,
+    reverseDirection = reverseDirection,
+    startDragImmediately = state.isAnimationRunning,
+    onDragStopped = { velocity -> launch { state.settle(velocity) } }
+)
+
+/**
+ * Scope used for suspending anchored drag blocks. Allows to set [AnchoredDraggableState.offset] to
+ * a new value.
+ *
+ * @see [AnchoredDraggableState.anchoredDrag] to learn how to start the anchored drag and get the
+ * access to this scope.
+ */
+@ExperimentalMaterial3Api
+internal interface AnchoredDragScope {
+    /**
+     * Assign a new value for an offset value for [AnchoredDraggableState].
+     *
+     * @param newOffset new value for [AnchoredDraggableState.offset].
+     * @param lastKnownVelocity last known velocity (if known)
+     */
+    fun dragTo(
+        newOffset: Float,
+        lastKnownVelocity: Float = 0f
+    )
+}
+
+/**
+ * State of the [anchoredDraggable] modifier.
+ * Use the constructor overload with anchors if the anchors are defined in composition, or update
+ * the anchors using [updateAnchors].
+ *
+ * This contains necessary information about any ongoing drag or animation and provides methods
+ * to change the state either immediately or by starting an animation.
+ *
+ * @param initialValue The initial value of the state.
+ * @param positionalThreshold The positional threshold, in px, to be used when calculating the
+ * target state while a drag is in progress and when settling after the drag ends. This is the
+ * distance from the start of a transition. It will be, depending on the direction of the
+ * interaction, added or subtracted from/to the origin offset. It should always be a positive value.
+ * @param velocityThreshold The velocity threshold (in px per second) that the end velocity has to
+ * exceed in order to animate to the next state, even if the [positionalThreshold] has not been
+ * reached.
+ * @param animationSpec The default animation that will be used to animate to a new state.
+ * @param confirmValueChange Optional callback invoked to confirm or veto a pending state change.
+ */
+@Suppress("PrimitiveInLambda")
+@Stable
+@ExperimentalMaterial3Api
+internal class AnchoredDraggableState<T>(
+    initialValue: T,
+    internal val positionalThreshold: (totalDistance: Float) -> Float,
+    internal val velocityThreshold: () -> Float,
+    val animationSpec: AnimationSpec<Float>,
+    internal val confirmValueChange: (newValue: T) -> Boolean = { true }
+) {
+
+    /**
+     * Construct an [AnchoredDraggableState] instance with anchors.
+     *
+     * @param initialValue The initial value of the state.
+     * @param anchors The anchors of the state. Use [updateAnchors] to update the anchors later.
+     * @param animationSpec The default animation that will be used to animate to a new state.
+     * @param confirmValueChange Optional callback invoked to confirm or veto a pending state
+     * change.
+     * @param positionalThreshold The positional threshold, in px, to be used when calculating the
+     * target state while a drag is in progress and when settling after the drag ends. This is the
+     * distance from the start of a transition. It will be, depending on the direction of the
+     * interaction, added or subtracted from/to the origin offset. It should always be a positive
+     * value.
+     * @param velocityThreshold The velocity threshold (in px per second) that the end velocity has
+     * to exceed in order to animate to the next state, even if the [positionalThreshold] has not
+     * been reached.
+     */
+    @ExperimentalMaterial3Api
+    constructor(
+        initialValue: T,
+        anchors: DraggableAnchors<T>,
+        positionalThreshold: (totalDistance: Float) -> Float,
+        velocityThreshold: () -> Float,
+        animationSpec: AnimationSpec<Float>,
+        confirmValueChange: (newValue: T) -> Boolean = { true }
+    ) : this(
+        initialValue,
+        positionalThreshold,
+        velocityThreshold,
+        animationSpec,
+        confirmValueChange
+    ) {
+        this.anchors = anchors
+        trySnapTo(initialValue)
+    }
+
+    private val dragMutex = InternalMutatorMutex()
+
+    internal val draggableState = object : DraggableState {
+
+        private val dragScope = object : DragScope {
+            override fun dragBy(pixels: Float) {
+                with(anchoredDragScope) {
+                    dragTo(newOffsetForDelta(pixels))
+                }
+            }
+        }
+
+        override suspend fun drag(
+            dragPriority: MutatePriority,
+            block: suspend DragScope.() -> Unit
+        ) {
+            this@AnchoredDraggableState.anchoredDrag(dragPriority) {
+                with(dragScope) { block() }
+            }
+        }
+
+        override fun dispatchRawDelta(delta: Float) {
+            this@AnchoredDraggableState.dispatchRawDelta(delta)
+        }
+    }
+
+    /**
+     * The current value of the [AnchoredDraggableState].
+     */
+    var currentValue: T by mutableStateOf(initialValue)
+        private set
+
+    /**
+     * The target value. This is the closest value to the current offset, taking into account
+     * positional thresholds. If no interactions like animations or drags are in progress, this
+     * will be the current value.
+     */
+    val targetValue: T by derivedStateOf {
+        dragTarget ?: run {
+            val currentOffset = offset
+            if (!currentOffset.isNaN()) {
+                computeTarget(currentOffset, currentValue, velocity = 0f)
+            } else currentValue
+        }
+    }
+
+    /**
+     * The closest value in the swipe direction from the current offset, not considering thresholds.
+     * If an [anchoredDrag] is in progress, this will be the target of that anchoredDrag (if
+     * specified).
+     */
+    internal val closestValue: T by derivedStateOf {
+        dragTarget ?: run {
+            val currentOffset = offset
+            if (!currentOffset.isNaN()) {
+                computeTargetWithoutThresholds(currentOffset, currentValue)
+            } else currentValue
+        }
+    }
+
+    /**
+     * The current offset, or [Float.NaN] if it has not been initialized yet.
+     *
+     * The offset will be initialized when the anchors are first set through [updateAnchors].
+     *
+     * Strongly consider using [requireOffset] which will throw if the offset is read before it is
+     * initialized. This helps catch issues early in your workflow.
+     */
+    var offset: Float by mutableFloatStateOf(Float.NaN)
+        private set
+
+    /**
+     * Require the current offset.
+     *
+     * @see offset
+     *
+     * @throws IllegalStateException If the offset has not been initialized yet
+     */
+    fun requireOffset(): Float {
+        check(!offset.isNaN()) {
+            "The offset was read before being initialized. Did you access the offset in a phase " +
+                "before layout, like effects or composition?"
+        }
+        return offset
+    }
+
+    /**
+     * Whether an animation is currently in progress.
+     */
+    val isAnimationRunning: Boolean get() = dragTarget != null
+
+    /**
+     * The fraction of the progress going from [currentValue] to [closestValue], within [0f..1f]
+     * bounds, or 1f if the [AnchoredDraggableState] is in a settled state.
+     */
+    @get:FloatRange(from = 0.0, to = 1.0)
+    val progress: Float by derivedStateOf(structuralEqualityPolicy()) {
+        val a = anchors.positionOf(currentValue)
+        val b = anchors.positionOf(closestValue)
+        val distance = abs(b - a)
+        if (!distance.isNaN() && distance > 1e-6f) {
+            val progress = (this.requireOffset() - a) / (b - a)
+            // If we are very close to 0f or 1f, we round to the closest
+            if (progress < 1e-6f) 0f else if (progress > 1 - 1e-6f) 1f else progress
+        } else 1f
+    }
+
+    /**
+     * The velocity of the last known animation. Gets reset to 0f when an animation completes
+     * successfully, but does not get reset when an animation gets interrupted.
+     * You can use this value to provide smooth reconciliation behavior when re-targeting an
+     * animation.
+     */
+    var lastVelocity: Float by mutableFloatStateOf(0f)
+        private set
+
+    private var dragTarget: T? by mutableStateOf(null)
+
+    var anchors: DraggableAnchors<T> by mutableStateOf(emptyDraggableAnchors())
+        private set
+
+    /**
+     * Update the anchors. If there is no ongoing [anchoredDrag] operation, snap to the [newTarget],
+     * otherwise restart the ongoing [anchoredDrag] operation (e.g. an animation) with the new
+     * anchors.
+     *
+     * <b>If your anchors depend on the size of the layout, updateAnchors should be called in the
+     * layout (placement) phase, e.g. through Modifier.onSizeChanged.</b> This ensures that the
+     * state is set up within the same frame.
+     * For static anchors, or anchors with different data dependencies, [updateAnchors] is safe to
+     * be called from side effects or layout.
+     *
+     * @param newAnchors The new anchors.
+     * @param newTarget The new target, by default the closest anchor or the current target if there
+     * are no anchors.
+     */
+    fun updateAnchors(
+        newAnchors: DraggableAnchors<T>,
+        newTarget: T = if (!offset.isNaN()) {
+            newAnchors.closestAnchor(offset) ?: targetValue
+        } else targetValue
+    ) {
+        if (anchors != newAnchors) {
+            anchors = newAnchors
+            // Attempt to snap. If nobody is holding the lock, we can immediately update the offset.
+            // If anybody is holding the lock, we send a signal to restart the ongoing work with the
+            // updated anchors.
+            val snapSuccessful = trySnapTo(newTarget)
+            if (!snapSuccessful) {
+                dragTarget = newTarget
+            }
+        }
+    }
+
+    /**
+     * Find the closest anchor, taking into account the [velocityThreshold] and
+     * [positionalThreshold], and settle at it with an animation.
+     *
+     * If the [velocity] is lower than the [velocityThreshold], the closest anchor by distance and
+     * [positionalThreshold] will be the target. If the [velocity] is higher than the
+     * [velocityThreshold], the [positionalThreshold] will <b>not</b> be considered and the next
+     * anchor in the direction indicated by the sign of the [velocity] will be the target.
+     */
+    suspend fun settle(velocity: Float) {
+        val previousValue = this.currentValue
+        val targetValue = computeTarget(
+            offset = requireOffset(),
+            currentValue = previousValue,
+            velocity = velocity
+        )
+        if (confirmValueChange(targetValue)) {
+            animateTo(targetValue, velocity)
+        } else {
+            // If the user vetoed the state change, rollback to the previous state.
+            animateTo(previousValue, velocity)
+        }
+    }
+
+    private fun computeTarget(
+        offset: Float,
+        currentValue: T,
+        velocity: Float
+    ): T {
+        val currentAnchors = anchors
+        val currentAnchorPosition = currentAnchors.positionOf(currentValue)
+        val velocityThresholdPx = velocityThreshold()
+        return if (currentAnchorPosition == offset || currentAnchorPosition.isNaN()) {
+            currentValue
+        } else if (currentAnchorPosition < offset) {
+            // Swiping from lower to upper (positive).
+            if (velocity >= velocityThresholdPx) {
+                currentAnchors.closestAnchor(offset, true)!!
+            } else {
+                val upper = currentAnchors.closestAnchor(offset, true)!!
+                val distance = abs(currentAnchors.positionOf(upper) - currentAnchorPosition)
+                val relativeThreshold = abs(positionalThreshold(distance))
+                val absoluteThreshold = abs(currentAnchorPosition + relativeThreshold)
+                if (offset < absoluteThreshold) currentValue else upper
+            }
+        } else {
+            // Swiping from upper to lower (negative).
+            if (velocity <= -velocityThresholdPx) {
+                currentAnchors.closestAnchor(offset, false)!!
+            } else {
+                val lower = currentAnchors.closestAnchor(offset, false)!!
+                val distance = abs(currentAnchorPosition - currentAnchors.positionOf(lower))
+                val relativeThreshold = abs(positionalThreshold(distance))
+                val absoluteThreshold = abs(currentAnchorPosition - relativeThreshold)
+                if (offset < 0) {
+                    // For negative offsets, larger absolute thresholds are closer to lower anchors
+                    // than smaller ones.
+                    if (abs(offset) < absoluteThreshold) currentValue else lower
+                } else {
+                    if (offset > absoluteThreshold) currentValue else lower
+                }
+            }
+        }
+    }
+
+    private fun computeTargetWithoutThresholds(
+        offset: Float,
+        currentValue: T,
+    ): T {
+        val currentAnchors = anchors
+        val currentAnchorPosition = currentAnchors.positionOf(currentValue)
+        return if (currentAnchorPosition == offset || currentAnchorPosition.isNaN()) {
+            currentValue
+        } else if (currentAnchorPosition < offset) {
+            currentAnchors.closestAnchor(offset, true) ?: currentValue
+        } else {
+            currentAnchors.closestAnchor(offset, false) ?: currentValue
+        }
+    }
+
+    private val anchoredDragScope: AnchoredDragScope = object : AnchoredDragScope {
+        override fun dragTo(newOffset: Float, lastKnownVelocity: Float) {
+            offset = newOffset
+            lastVelocity = lastKnownVelocity
+        }
+    }
+
+    /**
+     * Call this function to take control of drag logic and perform anchored drag with the latest
+     * anchors.
+     *
+     * All actions that change the [offset] of this [AnchoredDraggableState] must be performed
+     * within an [anchoredDrag] block (even if they don't call any other methods on this object)
+     * in order to guarantee that mutual exclusion is enforced.
+     *
+     * If [anchoredDrag] is called from elsewhere with the [dragPriority] higher or equal to ongoing
+     * drag, the ongoing drag will be cancelled.
+     *
+     * <b>If the [anchors] change while the [block] is being executed, it will be cancelled and
+     * re-executed with the latest anchors and target.</b> This allows you to target the correct
+     * state.
+     *
+     * @param dragPriority of the drag operation
+     * @param block perform anchored drag given the current anchor provided
+     */
+    suspend fun anchoredDrag(
+        dragPriority: MutatePriority = MutatePriority.Default,
+        block: suspend AnchoredDragScope.(anchors: DraggableAnchors<T>) -> Unit
+    ) {
+        try {
+            dragMutex.mutate(dragPriority) {
+                restartable(inputs = { anchors }) { latestAnchors ->
+                    anchoredDragScope.block(latestAnchors)
+                }
+            }
+        } finally {
+            val closest = anchors.closestAnchor(offset)
+            if (closest != null &&
+                abs(offset - anchors.positionOf(closest)) <= 0.5f &&
+                confirmValueChange.invoke(closest)
+            ) {
+                currentValue = closest
+            }
+        }
+    }
+
+    /**
+     * Call this function to take control of drag logic and perform anchored drag with the latest
+     * anchors and target.
+     *
+     * All actions that change the [offset] of this [AnchoredDraggableState] must be performed
+     * within an [anchoredDrag] block (even if they don't call any other methods on this object)
+     * in order to guarantee that mutual exclusion is enforced.
+     *
+     * This overload allows the caller to hint the target value that this [anchoredDrag] is intended
+     * to arrive to. This will set [AnchoredDraggableState.targetValue] to provided value so
+     * consumers can reflect it in their UIs.
+     *
+     * <b>If the [anchors] or [AnchoredDraggableState.targetValue] change while the [block] is being
+     * executed, it will be cancelled and re-executed with the latest anchors and target.</b> This
+     * allows you to target the correct state.
+     *
+     * If [anchoredDrag] is called from elsewhere with the [dragPriority] higher or equal to ongoing
+     * drag, the ongoing drag will be cancelled.
+     *
+     * @param targetValue hint the target value that this [anchoredDrag] is intended to arrive to
+     * @param dragPriority of the drag operation
+     * @param block perform anchored drag given the current anchor provided
+     */
+    suspend fun anchoredDrag(
+        targetValue: T,
+        dragPriority: MutatePriority = MutatePriority.Default,
+        block: suspend AnchoredDragScope.(anchors: DraggableAnchors<T>, targetValue: T) -> Unit
+    ) {
+        if (anchors.hasAnchorFor(targetValue)) {
+            try {
+                dragMutex.mutate(dragPriority) {
+                    dragTarget = targetValue
+                    restartable(
+                        inputs = { anchors to this@AnchoredDraggableState.targetValue }
+                    ) { (latestAnchors, latestTarget) ->
+                        anchoredDragScope.block(latestAnchors, latestTarget)
+                    }
+                }
+            } finally {
+                dragTarget = null
+                val closest = anchors.closestAnchor(offset)
+                if (closest != null &&
+                    abs(offset - anchors.positionOf(closest)) <= 0.5f &&
+                    confirmValueChange.invoke(closest)
+                ) {
+                    currentValue = closest
+                }
+            }
+        } else {
+            // Todo: b/283467401, revisit this behavior
+            currentValue = targetValue
+        }
+    }
+
+    internal fun newOffsetForDelta(delta: Float) =
+        ((if (offset.isNaN()) 0f else offset) + delta)
+            .coerceIn(anchors.minAnchor(), anchors.maxAnchor())
+
+    /**
+     * Drag by the [delta], coerce it in the bounds and dispatch it to the [AnchoredDraggableState].
+     *
+     * @return The delta the consumed by the [AnchoredDraggableState]
+     */
+    fun dispatchRawDelta(delta: Float): Float {
+        val newOffset = newOffsetForDelta(delta)
+        val oldOffset = if (offset.isNaN()) 0f else offset
+        offset = newOffset
+        return newOffset - oldOffset
+    }
+
+    /**
+     * Attempt to snap synchronously. Snapping can happen synchronously when there is no other drag
+     * transaction like a drag or an animation is progress. If there is another interaction in
+     * progress, the suspending [snapTo] overload needs to be used.
+     *
+     * @return true if the synchronous snap was successful, or false if we couldn't snap synchronous
+     */
+    private fun trySnapTo(targetValue: T): Boolean = dragMutex.tryMutate {
+        with(anchoredDragScope) {
+            val targetOffset = anchors.positionOf(targetValue)
+            if (!targetOffset.isNaN()) {
+                dragTo(targetOffset)
+                dragTarget = null
+            }
+            currentValue = targetValue
+        }
+    }
+
+    companion object {
+        /**
+         * The default [Saver] implementation for [AnchoredDraggableState].
+         */
+        @ExperimentalMaterial3Api
+        fun <T : Any> Saver(
+            animationSpec: AnimationSpec<Float>,
+            confirmValueChange: (T) -> Boolean,
+            positionalThreshold: (distance: Float) -> Float,
+            velocityThreshold: () -> Float,
+        ) = Saver<AnchoredDraggableState<T>, T>(
+            save = { it.currentValue },
+            restore = {
+                AnchoredDraggableState(
+                    initialValue = it,
+                    animationSpec = animationSpec,
+                    confirmValueChange = confirmValueChange,
+                    positionalThreshold = positionalThreshold,
+                    velocityThreshold = velocityThreshold
+                )
+            }
+        )
+    }
+}
+
+/**
+ * Snap to a [targetValue] without any animation.
+ * If the [targetValue] is not in the set of anchors, the [AnchoredDraggableState.currentValue] will
+ * be updated to the [targetValue] without updating the offset.
+ *
+ * @throws CancellationException if the interaction interrupted by another interaction like a
+ * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
+ *
+ * @param targetValue The target value of the animation
+ */
+@ExperimentalMaterial3Api
+internal suspend fun <T> AnchoredDraggableState<T>.snapTo(targetValue: T) {
+    anchoredDrag(targetValue = targetValue) { anchors, latestTarget ->
+        val targetOffset = anchors.positionOf(latestTarget)
+        if (!targetOffset.isNaN()) dragTo(targetOffset)
+    }
+}
+
+/**
+ * Animate to a [targetValue].
+ * If the [targetValue] is not in the set of anchors, the [AnchoredDraggableState.currentValue] will
+ * be updated to the [targetValue] without updating the offset.
+ *
+ * @throws CancellationException if the interaction interrupted by another interaction like a
+ * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
+ *
+ * @param targetValue The target value of the animation
+ * @param velocity The velocity the animation should start with
+ */
+@ExperimentalMaterial3Api
+internal suspend fun <T> AnchoredDraggableState<T>.animateTo(
+    targetValue: T,
+    velocity: Float = this.lastVelocity,
+) {
+    anchoredDrag(targetValue = targetValue) { anchors, latestTarget ->
+        val targetOffset = anchors.positionOf(latestTarget)
+        if (!targetOffset.isNaN()) {
+            var prev = if (offset.isNaN()) 0f else offset
+            animate(prev, targetOffset, velocity, animationSpec) { value, velocity ->
+                // Our onDrag coerces the value within the bounds, but an animation may
+                // overshoot, for example a spring animation or an overshooting interpolator
+                // We respect the user's intention and allow the overshoot, but still use
+                // DraggableState's drag for its mutex.
+                dragTo(value, velocity)
+                prev = value
+            }
+        }
+    }
+}
+
+/**
+ * Contains useful defaults for [anchoredDraggable] and [AnchoredDraggableState].
+ */
+@Stable
+@ExperimentalMaterial3Api
+internal object AnchoredDraggableDefaults {
+    /**
+     * The default animation used by [AnchoredDraggableState].
+     */
+    @get:ExperimentalMaterial3Api
+    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
+    @ExperimentalMaterial3Api
+    val AnimationSpec = SpringSpec<Float>()
+}
+
+private class AnchoredDragFinishedSignal : CancellationException() {
+    override fun fillInStackTrace(): Throwable {
+        stackTrace = emptyArray()
+        return this
+    }
+}
+
+private suspend fun <I> restartable(inputs: () -> I, block: suspend (I) -> Unit) {
+    try {
+        coroutineScope {
+            var previousDrag: Job? = null
+            snapshotFlow(inputs)
+                .collect { latestInputs ->
+                    previousDrag?.apply {
+                        cancel(AnchoredDragFinishedSignal())
+                        join()
+                    }
+                    previousDrag = launch(start = CoroutineStart.UNDISPATCHED) {
+                        block(latestInputs)
+                        this@coroutineScope.cancel(AnchoredDragFinishedSignal())
+                    }
+                }
+        }
+    } catch (anchoredDragFinished: AnchoredDragFinishedSignal) {
+        // Ignored
+    }
+}
+
+private fun <T> emptyDraggableAnchors() = MapDraggableAnchors<T>(emptyMap())
+
+@OptIn(ExperimentalMaterial3Api::class)
+private class MapDraggableAnchors<T>(private val anchors: Map<T, Float>) : DraggableAnchors<T> {
+
+    override fun positionOf(value: T): Float = anchors[value] ?: Float.NaN
+    override fun hasAnchorFor(value: T) = anchors.containsKey(value)
+
+    override fun closestAnchor(position: Float): T? = anchors.minByOrNull {
+        abs(position - it.value)
+    }?.key
+
+    override fun closestAnchor(
+        position: Float,
+        searchUpwards: Boolean
+    ): T? {
+        return anchors.minByOrNull { (_, anchor) ->
+            val delta = if (searchUpwards) anchor - position else position - anchor
+            if (delta < 0) Float.POSITIVE_INFINITY else delta
+        }?.key
+    }
+
+    override fun minAnchor() = anchors.values.minOrNull() ?: Float.NaN
+
+    override fun maxAnchor() = anchors.values.maxOrNull() ?: Float.NaN
+
+    override val size: Int
+        get() = anchors.size
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is MapDraggableAnchors<*>) return false
+
+        return anchors == other.anchors
+    }
+
+    override fun hashCode() = 31 * anchors.hashCode()
+
+    override fun toString() = "MapDraggableAnchors($anchors)"
+}
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
index 8df6937..fe98619 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/BottomSheetScaffold.kt
@@ -38,13 +38,14 @@
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.layout.SubcomposeLayout
+import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.semantics.collapse
 import androidx.compose.ui.semantics.dismiss
 import androidx.compose.ui.semantics.expand
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
-import kotlin.math.max
+import androidx.compose.ui.unit.IntSize
 import kotlin.math.roundToInt
 import kotlinx.coroutines.launch
 
@@ -113,6 +114,9 @@
     contentColor: Color = contentColorFor(containerColor),
     content: @Composable (PaddingValues) -> Unit
 ) {
+    val peekHeightPx = with(LocalDensity.current) {
+        sheetPeekHeight.roundToPx()
+    }
     BottomSheetScaffoldLayout(
         modifier = modifier,
         topBar = topBar,
@@ -130,7 +134,20 @@
                 state = scaffoldState.bottomSheetState,
                 peekHeight = sheetPeekHeight,
                 sheetSwipeEnabled = sheetSwipeEnabled,
-                layoutHeight = layoutHeight.toFloat(),
+                calculateAnchors = { sheetSize ->
+                    val sheetHeight = sheetSize.height
+                    DraggableAnchors {
+                        if (!scaffoldState.bottomSheetState.skipPartiallyExpanded) {
+                            PartiallyExpanded at (layoutHeight - peekHeightPx).toFloat()
+                        }
+                        if (sheetHeight != peekHeightPx) {
+                            Expanded at maxOf(layoutHeight - sheetHeight, 0).toFloat()
+                        }
+                        if (!scaffoldState.bottomSheetState.skipHiddenState) {
+                            Hidden at layoutHeight.toFloat()
+                        }
+                    }
+                },
                 shape = sheetShape,
                 containerColor = sheetContainerColor,
                 contentColor = sheetContentColor,
@@ -197,9 +214,10 @@
 @Composable
 private fun StandardBottomSheet(
     state: SheetState,
+    @Suppress("PrimitiveInLambda")
+    calculateAnchors: (sheetSize: IntSize) -> DraggableAnchors<SheetValue>,
     peekHeight: Dp,
     sheetSwipeEnabled: Boolean,
-    layoutHeight: Float,
     shape: Shape,
     containerColor: Color,
     contentColor: Color,
@@ -209,32 +227,16 @@
     content: @Composable ColumnScope.() -> Unit
 ) {
     val scope = rememberCoroutineScope()
-    val peekHeightPx = with(LocalDensity.current) { peekHeight.toPx() }
+
     val orientation = Orientation.Vertical
 
-    // Callback that is invoked when the anchors have changed.
-    val anchorChangeHandler = remember(state, scope) {
-        BottomSheetScaffoldAnchorChangeHandler(
-            state = state,
-            animateTo = { target, velocity ->
-                scope.launch {
-                    state.swipeableState.animateTo(
-                        target, velocity = velocity
-                    )
-                }
-            },
-            snapTo = { target ->
-                scope.launch { state.swipeableState.snapTo(target) }
-            }
-        )
-    }
     Surface(
         modifier = Modifier
             .widthIn(max = BottomSheetMaxWidth)
             .fillMaxWidth()
             .requiredHeightIn(min = peekHeight)
             .nestedScroll(
-                remember(state.swipeableState) {
+                remember(state.anchoredDraggableState) {
                     ConsumeSwipeWithinBottomSheetBoundsNestedScrollConnection(
                         sheetState = state,
                         orientation = orientation,
@@ -242,26 +244,20 @@
                     )
                 }
             )
-            .swipeableV2(
-                state = state.swipeableState,
+            .anchoredDraggable(
+                state = state.anchoredDraggableState,
                 orientation = orientation,
                 enabled = sheetSwipeEnabled
             )
-            .swipeAnchors(
-                state.swipeableState,
-                possibleValues = setOf(Hidden, PartiallyExpanded, Expanded),
-                anchorChangeHandler = anchorChangeHandler
-            ) { value, sheetSize ->
-                when (value) {
-                    PartiallyExpanded -> if (state.skipPartiallyExpanded)
-                        null else layoutHeight - peekHeightPx
-                    Expanded -> if (sheetSize.height == peekHeightPx.roundToInt()) {
-                        null
-                    } else {
-                        max(0f, layoutHeight - sheetSize.height)
+            .onSizeChanged { layoutSize ->
+                val newAnchors = calculateAnchors(layoutSize)
+                val newTarget = when (state.anchoredDraggableState.targetValue) {
+                    Hidden, PartiallyExpanded -> PartiallyExpanded
+                    Expanded -> {
+                        if (newAnchors.hasAnchorFor(Expanded)) Expanded else PartiallyExpanded
                     }
-                    Hidden -> if (state.skipHiddenState) null else layoutHeight
                 }
+                state.anchoredDraggableState.updateAnchors(newAnchors, newTarget)
             },
         shape = shape,
         color = containerColor,
@@ -275,35 +271,39 @@
                     getString(Strings.BottomSheetPartialExpandDescription)
                 val dismissActionLabel = getString(Strings.BottomSheetDismissDescription)
                 val expandActionLabel = getString(Strings.BottomSheetExpandDescription)
-                Box(Modifier
-                    .align(CenterHorizontally)
-                    .semantics(mergeDescendants = true) {
-                        with(state) {
-                            // Provides semantics to interact with the bottomsheet if there is more
-                            // than one anchor to swipe to and swiping is enabled.
-                            if (swipeableState.anchors.size > 1 && sheetSwipeEnabled) {
-                                if (currentValue == PartiallyExpanded) {
-                                    if (swipeableState.confirmValueChange(Expanded)) {
-                                        expand(expandActionLabel) {
-                                            scope.launch { expand() }; true
+                Box(
+                    Modifier
+                        .align(CenterHorizontally)
+                        .semantics(mergeDescendants = true) {
+                            with(state) {
+                                // Provides semantics to interact with the bottomsheet if there is more
+                                // than one anchor to swipe to and swiping is enabled.
+                                if (anchoredDraggableState.anchors.size > 1 && sheetSwipeEnabled) {
+                                    if (currentValue == PartiallyExpanded) {
+                                        if (anchoredDraggableState.confirmValueChange(Expanded)) {
+                                            expand(expandActionLabel) {
+                                                scope.launch { expand() }; true
+                                            }
+                                        }
+                                    } else {
+                                        if (anchoredDraggableState.confirmValueChange(
+                                                PartiallyExpanded
+                                            )
+                                        ) {
+                                            collapse(partialExpandActionLabel) {
+                                                scope.launch { partialExpand() }; true
+                                            }
                                         }
                                     }
-                                } else {
-                                    if (swipeableState.confirmValueChange(PartiallyExpanded)) {
-                                        collapse(partialExpandActionLabel) {
-                                            scope.launch { partialExpand() }; true
+                                    if (!state.skipHiddenState) {
+                                        dismiss(dismissActionLabel) {
+                                            scope.launch { hide() }
+                                            true
                                         }
                                     }
                                 }
-                                if (!state.skipHiddenState) {
-                                    dismiss(dismissActionLabel) {
-                                        scope.launch { hide() }
-                                        true
-                                    }
-                                }
                             }
-                        }
-                    },
+                        },
                 ) {
                     dragHandle()
                 }
@@ -378,27 +378,4 @@
     }
 }
 
-@ExperimentalMaterial3Api
-private fun BottomSheetScaffoldAnchorChangeHandler(
-    state: SheetState,
-    animateTo: (target: SheetValue, velocity: Float) -> Unit,
-    snapTo: (target: SheetValue) -> Unit,
-) = AnchorChangeHandler<SheetValue> { previousTarget, previousAnchors, newAnchors ->
-    val previousTargetOffset = previousAnchors[previousTarget]
-    val newTarget = when (previousTarget) {
-        Hidden, PartiallyExpanded -> PartiallyExpanded
-        Expanded -> if (newAnchors.containsKey(Expanded)) Expanded else PartiallyExpanded
-    }
-    val newTargetOffset = newAnchors.getValue(newTarget)
-    if (newTargetOffset != previousTargetOffset) {
-        if (state.swipeableState.isAnimationRunning) {
-            // Re-target the animation to the new offset if it changed
-            animateTo(newTarget, state.swipeableState.lastVelocity)
-        } else {
-            // Snap to the new offset value of the target if no animation was running
-            snapTo(newTarget)
-        }
-    }
-}
-
 private enum class BottomSheetScaffoldLayoutSlot { TopBar, Body, Sheet, Snackbar }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
index f99c8ab..ee1c6b4 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/CalendarModel.kt
@@ -38,12 +38,14 @@
  * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
  * @param skeleton a date format skeleton
  * @param locale the [CalendarLocale] to use when formatting the given timestamp
+ * @param cache a [MutableMap] for caching formatter related results for better performance
  */
 @ExperimentalMaterial3Api
 expect fun formatWithSkeleton(
     utcTimeMillis: Long,
     skeleton: String,
-    locale: CalendarLocale
+    locale: CalendarLocale,
+    cache: MutableMap<String, Any>
 ): String
 
 /**
@@ -54,6 +56,9 @@
 @ExperimentalMaterial3Api
 internal abstract class CalendarModel(val locale: CalendarLocale) {
 
+    // A map for caching formatter related results for better performance
+    internal val formatterCache = mutableMapOf<String, Any>()
+
     /**
      * A [CalendarDate] representing the current day.
      */
@@ -167,7 +172,7 @@
         skeleton: String,
         locale: CalendarLocale = this.locale
     ): String =
-        formatWithSkeleton(month.startUtcTimeMillis, skeleton, locale)
+        formatWithSkeleton(month.startUtcTimeMillis, skeleton, locale, formatterCache)
 
     /**
      * Formats a [CalendarDate] into a string with a given date format skeleton.
@@ -180,7 +185,7 @@
         date: CalendarDate,
         skeleton: String,
         locale: CalendarLocale = this.locale
-    ): String = formatWithSkeleton(date.utcTimeMillis, skeleton, locale)
+    ): String = formatWithSkeleton(date.utcTimeMillis, skeleton, locale, formatterCache)
 
     /**
      * Formats a UTC timestamp into a string with a given date format pattern.
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
index 67134c1..00c2306 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DatePicker.kt
@@ -70,7 +70,6 @@
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -1069,18 +1068,21 @@
  */
 @OptIn(ExperimentalMaterial3Api::class)
 @Immutable
-private class DatePickerFormatterImpl constructor(
+private class DatePickerFormatterImpl(
     val yearSelectionSkeleton: String,
     val selectedDateSkeleton: String,
     val selectedDateDescriptionSkeleton: String
 ) : DatePickerFormatter {
 
+    // A map for caching formatter related results for better performance
+    private val formatterCache = mutableMapOf<String, Any>()
+
     override fun formatMonthYear(
         monthMillis: Long?,
         locale: CalendarLocale
     ): String? {
         if (monthMillis == null) return null
-        return formatWithSkeleton(monthMillis, yearSelectionSkeleton, locale)
+        return formatWithSkeleton(monthMillis, yearSelectionSkeleton, locale, formatterCache)
     }
 
     override fun formatDate(
@@ -1095,7 +1097,8 @@
             } else {
                 selectedDateSkeleton
             },
-            locale
+            locale,
+            formatterCache
         )
     }
 
@@ -1468,37 +1471,41 @@
             month = 1 // January
         )
     }
-    LazyRow(
-        // Apply this to prevent the screen reader from scrolling to the next or previous month, and
-        // instead, traverse outside the Month composable when swiping from a focused first or last
-        // day of the month.
-        modifier = Modifier.semantics {
-            horizontalScrollAxisRange = ScrollAxisRange(value = { 0f }, maxValue = { 0f })
-        },
-        state = lazyListState,
-        // TODO(b/264687693): replace with the framework's rememberSnapFlingBehavior(lazyListState)
-        //  when promoted to stable
-        flingBehavior = DatePickerDefaults.rememberSnapFlingBehavior(lazyListState)
+    ProvideTextStyle(
+        MaterialTheme.typography.fromToken(DatePickerModalTokens.DateLabelTextFont)
     ) {
-        items(numberOfMonthsInRange(yearRange)) {
-            val month = calendarModel.plusMonths(
-                from = firstMonth,
-                addedMonthsCount = it
-            )
-            Box(
-                modifier = Modifier.fillParentMaxWidth()
-            ) {
-                Month(
-                    month = month,
-                    onDateSelectionChange = onDateSelectionChange,
-                    todayMillis = today.utcTimeMillis,
-                    startDateMillis = selectedDateMillis,
-                    endDateMillis = null,
-                    rangeSelectionInfo = null,
-                    dateFormatter = dateFormatter,
-                    selectableDates = selectableDates,
-                    colors = colors
+        LazyRow(
+            // Apply this to prevent the screen reader from scrolling to the next or previous month,
+            // and instead, traverse outside the Month composable when swiping from a focused first
+            // or last day of the month.
+            modifier = Modifier.semantics {
+                horizontalScrollAxisRange = ScrollAxisRange(value = { 0f }, maxValue = { 0f })
+            },
+            state = lazyListState,
+            // TODO(b/264687693): replace with the framework's rememberSnapFlingBehavior
+            //  (lazyListState) when promoted to stable
+            flingBehavior = DatePickerDefaults.rememberSnapFlingBehavior(lazyListState)
+        ) {
+            items(numberOfMonthsInRange(yearRange)) {
+                val month = calendarModel.plusMonths(
+                    from = firstMonth,
+                    addedMonthsCount = it
                 )
+                Box(
+                    modifier = Modifier.fillParentMaxWidth()
+                ) {
+                    Month(
+                        month = month,
+                        onDateSelectionChange = onDateSelectionChange,
+                        todayMillis = today.utcTimeMillis,
+                        startDateMillis = selectedDateMillis,
+                        endDateMillis = null,
+                        rangeSelectionInfo = null,
+                        dateFormatter = dateFormatter,
+                        selectableDates = selectableDates,
+                        colors = colors
+                    )
+                }
             }
         }
     }
@@ -1561,7 +1568,7 @@
                 horizontalArrangement = Arrangement.SpaceEvenly,
                 verticalAlignment = Alignment.CenterVertically
             ) {
-                dayNames.forEach {
+                for (it in dayNames) {
                     Box(
                         modifier = Modifier
                             .clearAndSetSemantics { contentDescription = it.first }
@@ -1608,97 +1615,96 @@
     }
 
     val defaultLocale = defaultLocale()
-    ProvideTextStyle(
-        MaterialTheme.typography.fromToken(DatePickerModalTokens.DateLabelTextFont)
+    var cellIndex = 0
+    Column(
+        modifier = Modifier
+            .requiredHeight(RecommendedSizeForAccessibility * MaxCalendarRows)
+            .then(rangeSelectionDrawModifier),
+        verticalArrangement = Arrangement.SpaceEvenly
     ) {
-        var cellIndex = 0
-        Column(
-            modifier = Modifier
-                .requiredHeight(RecommendedSizeForAccessibility * MaxCalendarRows)
-                .then(rangeSelectionDrawModifier),
-            verticalArrangement = Arrangement.SpaceEvenly
-        ) {
-            repeat(MaxCalendarRows) {
-                Row(
-                    modifier = Modifier.fillMaxWidth(),
-                    horizontalArrangement = Arrangement.SpaceEvenly,
-                    verticalAlignment = Alignment.CenterVertically
-                ) {
-                    repeat(DaysInWeek) {
-                        if (cellIndex < month.daysFromStartOfWeekToFirstOfMonth ||
-                            cellIndex >=
-                            (month.daysFromStartOfWeekToFirstOfMonth + month.numberOfDays)
-                        ) {
-                            // Empty cell
-                            Spacer(
-                                modifier = Modifier.requiredSize(
-                                    width = RecommendedSizeForAccessibility,
-                                    height = RecommendedSizeForAccessibility
-                                )
+        for (weekIndex in 0 until MaxCalendarRows) {
+            Row(
+                modifier = Modifier.fillMaxWidth(),
+                horizontalArrangement = Arrangement.SpaceEvenly,
+                verticalAlignment = Alignment.CenterVertically
+            ) {
+                for (dayIndex in 0 until DaysInWeek) {
+                    if (cellIndex < month.daysFromStartOfWeekToFirstOfMonth ||
+                        cellIndex >=
+                        (month.daysFromStartOfWeekToFirstOfMonth + month.numberOfDays)
+                    ) {
+                        // Empty cell
+                        Spacer(
+                            modifier = Modifier.requiredSize(
+                                width = RecommendedSizeForAccessibility,
+                                height = RecommendedSizeForAccessibility
                             )
-                        } else {
-                            val dayNumber = cellIndex - month.daysFromStartOfWeekToFirstOfMonth
-                            val dateInMillis = month.startUtcTimeMillis +
-                                (dayNumber * MillisecondsIn24Hours)
-                            val isToday = dateInMillis == todayMillis
-                            val startDateSelected = dateInMillis == startDateMillis
-                            val endDateSelected = dateInMillis == endDateMillis
-                            val inRange = remember(rangeSelectionInfo, dateInMillis) {
-                                derivedStateOf {
-                                    rangeSelectionInfo != null &&
-                                        dateInMillis >= (startDateMillis
+                        )
+                    } else {
+                        val dayNumber = cellIndex - month.daysFromStartOfWeekToFirstOfMonth
+                        val dateInMillis = month.startUtcTimeMillis +
+                            (dayNumber * MillisecondsIn24Hours)
+                        val isToday = dateInMillis == todayMillis
+                        val startDateSelected = dateInMillis == startDateMillis
+                        val endDateSelected = dateInMillis == endDateMillis
+                        val inRange = if (rangeSelectionInfo != null) {
+                            remember(rangeSelectionInfo, dateInMillis) {
+                                mutableStateOf(
+                                    dateInMillis >= (startDateMillis
                                         ?: Long.Companion.MAX_VALUE) &&
                                         dateInMillis <= (endDateMillis ?: Long.MIN_VALUE)
-                                }
-                            }
-                            val dayContentDescription = dayContentDescription(
-                                rangeSelectionEnabled = rangeSelectionInfo != null,
-                                isToday = isToday,
-                                isStartDate = startDateSelected,
-                                isEndDate = endDateSelected,
-                                isInRange = inRange.value
-                            )
-                            val formattedDateDescription = dateFormatter.formatDate(
-                                dateInMillis,
-                                defaultLocale,
-                                forContentDescription = true
-                            ) ?: ""
-                            Day(
-                                modifier = Modifier,
-                                selected = startDateSelected || endDateSelected,
-                                onClick = { onDateSelectionChange(dateInMillis) },
-                                // Only animate on the first selected day. This is important to
-                                // disable when drawing a range marker behind the days on an
-                                // end-date selection.
-                                animateChecked = startDateSelected,
-                                enabled = remember(dateInMillis) {
-                                    // Disabled a day in case its year is not selectable, or the
-                                    // date itself is specifically not allowed by the state's
-                                    // SelectableDates.
-                                    with(selectableDates) {
-                                        isSelectableYear(month.year) &&
-                                            isSelectableDate(dateInMillis)
-                                    }
-                                },
-                                today = isToday,
-                                inRange = inRange.value,
-                                description = if (dayContentDescription != null) {
-                                    "$dayContentDescription, $formattedDateDescription"
-                                } else {
-                                    formattedDateDescription
-                                },
-                                colors = colors
-                            ) {
-                                Text(
-                                    text = (dayNumber + 1).toLocalString(),
-                                    // The semantics are set at the Day level.
-                                    modifier = Modifier.clearAndSetSemantics { },
-                                    textAlign = TextAlign.Center
                                 )
-                            }
+                            }.value
+                        } else {
+                            false
                         }
-                        cellIndex++
+                        val dayContentDescription = dayContentDescription(
+                            rangeSelectionEnabled = rangeSelectionInfo != null,
+                            isToday = isToday,
+                            isStartDate = startDateSelected,
+                            isEndDate = endDateSelected,
+                            isInRange = inRange
+                        )
+                        val formattedDateDescription = dateFormatter.formatDate(
+                            dateInMillis,
+                            defaultLocale,
+                            forContentDescription = true
+                        ) ?: ""
+                        Day(
+                            modifier = Modifier,
+                            selected = startDateSelected || endDateSelected,
+                            onClick = { onDateSelectionChange(dateInMillis) },
+                            // Only animate on the first selected day. This is important to
+                            // disable when drawing a range marker behind the days on an
+                            // end-date selection.
+                            animateChecked = startDateSelected,
+                            enabled = remember(dateInMillis) {
+                                // Disabled a day in case its year is not selectable, or the
+                                // date itself is specifically not allowed by the state's
+                                // SelectableDates.
+                                with(selectableDates) {
+                                    isSelectableYear(month.year) &&
+                                        isSelectableDate(dateInMillis)
+                                }
+                            },
+                            today = isToday,
+                            inRange = inRange,
+                            description = if (dayContentDescription != null) {
+                                "$dayContentDescription, $formattedDateDescription"
+                            } else {
+                                formattedDateDescription
+                            },
+                            colors = colors
+                        ) {
+                            Text(
+                                text = (dayNumber + 1).toLocalString(),
+                                // The semantics are set at the Day level.
+                                modifier = Modifier.clearAndSetSemantics { },
+                                textAlign = TextAlign.Center
+                            )
+                        }
                     }
+                    cellIndex++
                 }
             }
         }
@@ -1760,11 +1766,6 @@
         selected = selected,
         onClick = onClick,
         modifier = modifier
-            .minimumInteractiveComponentSize()
-            .requiredSize(
-                DatePickerModalTokens.DateStateLayerWidth,
-                DatePickerModalTokens.DateStateLayerHeight
-            )
             // Apply and merge semantics here. This will ensure that when scrolling the list the
             // entire Day surface is treated as one unit and holds the date semantics even when it's
             // not completely visible atm.
@@ -1794,7 +1795,13 @@
             null
         }
     ) {
-        Box(contentAlignment = Alignment.Center) {
+        Box(
+            modifier = Modifier.requiredSize(
+                DatePickerModalTokens.DateStateLayerWidth,
+                DatePickerModalTokens.DateStateLayerHeight
+            ),
+            contentAlignment = Alignment.Center
+        ) {
             content()
         }
     }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
index 1f935ca..6d4650a 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/DateRangePicker.kt
@@ -31,8 +31,6 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Stable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberCoroutineScope
@@ -727,13 +725,31 @@
         )
     }
     ProvideTextStyle(
-        MaterialTheme.typography.fromToken(
-            DatePickerModalTokens.RangeSelectionMonthSubheadFont
-        )
+        MaterialTheme.typography.fromToken(DatePickerModalTokens.DateLabelTextFont)
     ) {
         val coroutineScope = rememberCoroutineScope()
         val scrollToPreviousMonthLabel = getString(Strings.DateRangePickerScrollToShowPreviousMonth)
         val scrollToNextMonthLabel = getString(Strings.DateRangePickerScrollToShowNextMonth)
+
+        // The updateDateSelection will invoke the onDatesSelectionChange with the proper
+        // selection according to the current state.
+        val onDateSelectionChange = { dateInMillis: Long ->
+            updateDateSelection(
+                dateInMillis = dateInMillis,
+                currentStartDateMillis = selectedStartDateMillis,
+                currentEndDateMillis = selectedEndDateMillis,
+                onDatesSelectionChange = onDatesSelectionChange
+            )
+        }
+
+        val customAccessibilityAction =
+            customScrollActions(
+                state = lazyListState,
+                coroutineScope = coroutineScope,
+                scrollUpLabel = scrollToPreviousMonthLabel,
+                scrollDownLabel = scrollToNextMonthLabel
+            )
+
         LazyColumn(
             // Apply this to have the screen reader traverse outside the visible list of months
             // and not scroll them by default.
@@ -751,59 +767,50 @@
                 Column(
                     modifier = Modifier.fillParentMaxWidth()
                 ) {
-                    Text(
-                        text = dateFormatter.formatMonthYear(
-                            month.startUtcTimeMillis,
-                            defaultLocale()
-                        ) ?: "-",
-                        modifier = Modifier
-                            .padding(paddingValues = CalendarMonthSubheadPadding)
-                            .clickable { /* no-op (needed for customActions to operate */ }
-                            .semantics {
-                                customActions = customScrollActions(
-                                    state = lazyListState,
-                                    coroutineScope = coroutineScope,
-                                    scrollUpLabel = scrollToPreviousMonthLabel,
-                                    scrollDownLabel = scrollToNextMonthLabel
-                                )
-                            },
-                        color = colors.subheadContentColor
-                    )
-                    val rangeSelectionInfo: State<SelectedRangeInfo?> =
-                        remember(selectedStartDateMillis, selectedEndDateMillis) {
-                            derivedStateOf {
-                                SelectedRangeInfo.calculateRangeInfo(
-                                    month = month,
-                                    startDate = selectedStartDateMillis?.let { date ->
-                                        calendarModel.getCanonicalDate(
-                                            date
-                                        )
-                                    },
-                                    endDate = selectedEndDateMillis?.let { date ->
-                                        calendarModel.getCanonicalDate(
-                                            date
-                                        )
-                                    }
-                                )
-                            }
-                        }
-                    // The updateDateSelection will invoke the onDatesSelectionChange with the proper
-                    // selection according to the current state.
-                    val onDateSelectionChange = { dateInMillis: Long ->
-                        updateDateSelection(
-                            dateInMillis = dateInMillis,
-                            currentStartDateMillis = selectedStartDateMillis,
-                            currentEndDateMillis = selectedEndDateMillis,
-                            onDatesSelectionChange = onDatesSelectionChange
+                    ProvideTextStyle(
+                        MaterialTheme.typography.fromToken(
+                            DatePickerModalTokens.RangeSelectionMonthSubheadFont
+                        )
+                    ) {
+                        Text(
+                            text = dateFormatter.formatMonthYear(
+                                month.startUtcTimeMillis,
+                                defaultLocale()
+                            ) ?: "-",
+                            modifier = Modifier
+                                .padding(paddingValues = CalendarMonthSubheadPadding)
+                                .clickable { /* no-op (needed for customActions to operate */ }
+                                .semantics {
+                                    customActions = customAccessibilityAction
+                                },
+                            color = colors.subheadContentColor
                         )
                     }
+                    val rangeSelectionInfo: SelectedRangeInfo? =
+                        if (selectedStartDateMillis != null &&
+                            selectedEndDateMillis != null
+                        ) {
+                            remember(selectedStartDateMillis, selectedEndDateMillis) {
+                                SelectedRangeInfo.calculateRangeInfo(
+                                    month = month,
+                                    startDate = calendarModel.getCanonicalDate(
+                                        selectedStartDateMillis
+                                    ),
+                                    endDate = calendarModel.getCanonicalDate(
+                                        selectedEndDateMillis
+                                    )
+                                )
+                            }
+                        } else {
+                            null
+                        }
                     Month(
                         month = month,
                         onDateSelectionChange = onDateSelectionChange,
                         todayMillis = today.utcTimeMillis,
                         startDateMillis = selectedStartDateMillis,
                         endDateMillis = selectedEndDateMillis,
-                        rangeSelectionInfo = rangeSelectionInfo.value,
+                        rangeSelectionInfo = rangeSelectionInfo,
                         dateFormatter = dateFormatter,
                         selectableDates = selectableDates,
                         colors = colors
@@ -822,7 +829,6 @@
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 private fun updateDateSelection(
     dateInMillis: Long,
     currentStartDateMillis: Long?,
@@ -857,7 +863,8 @@
  * A SelectedRangeInfo is created when a [Month] is composed with an `rangeSelectionEnabled` flag.
  */
 internal class SelectedRangeInfo(
-    val gridCoordinates: Pair<IntOffset, IntOffset>,
+    val gridStartCoordinates: IntOffset,
+    val gridEndCoordinates: IntOffset,
     val firstIsSelectionStart: Boolean,
     val lastIsSelectionEnd: Boolean
 ) {
@@ -871,44 +878,42 @@
         @OptIn(ExperimentalMaterial3Api::class)
         fun calculateRangeInfo(
             month: CalendarMonth,
-            startDate: CalendarDate?,
-            endDate: CalendarDate?
+            startDate: CalendarDate,
+            endDate: CalendarDate
         ): SelectedRangeInfo? {
-            if (startDate != null && endDate != null) {
-                if (startDate.utcTimeMillis > month.endUtcTimeMillis ||
-                    endDate.utcTimeMillis < month.startUtcTimeMillis
-                ) {
-                    return null
-                }
-                val firstIsSelectionStart = startDate.utcTimeMillis >= month.startUtcTimeMillis
-                val lastIsSelectionEnd = endDate.utcTimeMillis <= month.endUtcTimeMillis
-                val startGridItemOffset = if (firstIsSelectionStart) {
-                    month.daysFromStartOfWeekToFirstOfMonth + startDate.dayOfMonth - 1
-                } else {
-                    month.daysFromStartOfWeekToFirstOfMonth
-                }
-                val endGridItemOffset = if (lastIsSelectionEnd) {
-                    month.daysFromStartOfWeekToFirstOfMonth + endDate.dayOfMonth - 1
-                } else {
-                    month.daysFromStartOfWeekToFirstOfMonth + month.numberOfDays - 1
-                }
-
-                // Calculate the selected coordinates within the cells grid.
-                val startCoordinates = IntOffset(
-                    x = startGridItemOffset % DaysInWeek,
-                    y = startGridItemOffset / DaysInWeek
-                )
-                val endCoordinates = IntOffset(
-                    x = endGridItemOffset % DaysInWeek,
-                    y = endGridItemOffset / DaysInWeek
-                )
-                return SelectedRangeInfo(
-                    Pair(startCoordinates, endCoordinates),
-                    firstIsSelectionStart,
-                    lastIsSelectionEnd
-                )
+            if (startDate.utcTimeMillis > month.endUtcTimeMillis ||
+                endDate.utcTimeMillis < month.startUtcTimeMillis
+            ) {
+                return null
             }
-            return null
+            val firstIsSelectionStart = startDate.utcTimeMillis >= month.startUtcTimeMillis
+            val lastIsSelectionEnd = endDate.utcTimeMillis <= month.endUtcTimeMillis
+            val startGridItemOffset = if (firstIsSelectionStart) {
+                month.daysFromStartOfWeekToFirstOfMonth + startDate.dayOfMonth - 1
+            } else {
+                month.daysFromStartOfWeekToFirstOfMonth
+            }
+            val endGridItemOffset = if (lastIsSelectionEnd) {
+                month.daysFromStartOfWeekToFirstOfMonth + endDate.dayOfMonth - 1
+            } else {
+                month.daysFromStartOfWeekToFirstOfMonth + month.numberOfDays - 1
+            }
+
+            // Calculate the selected coordinates within the cells grid.
+            val gridStartCoordinates = IntOffset(
+                x = startGridItemOffset % DaysInWeek,
+                y = startGridItemOffset / DaysInWeek
+            )
+            val gridEndCoordinates = IntOffset(
+                x = endGridItemOffset % DaysInWeek,
+                y = endGridItemOffset / DaysInWeek
+            )
+            return SelectedRangeInfo(
+                gridStartCoordinates,
+                gridEndCoordinates,
+                firstIsSelectionStart,
+                lastIsSelectionEnd
+            )
         }
     }
 }
@@ -935,8 +940,8 @@
     val horizontalSpaceBetweenItems =
         (this.size.width - DaysInWeek * itemContainerWidth) / DaysInWeek
 
-    val (x1, y1) = selectedRangeInfo.gridCoordinates.first
-    val (x2, y2) = selectedRangeInfo.gridCoordinates.second
+    val (x1, y1) = selectedRangeInfo.gridStartCoordinates
+    val (x2, y2) = selectedRangeInfo.gridEndCoordinates
     // The endX and startX are offset to include only half the item's width when dealing with first
     // and last items in the selection in order to keep the selection edges rounded.
     var startX = x1 * (itemContainerWidth + horizontalSpaceBetweenItems) +
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/InteractiveComponentSize.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/InteractiveComponentSize.kt
index 31e307b..56d2814 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/InteractiveComponentSize.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/InteractiveComponentSize.kt
@@ -19,12 +19,15 @@
 import androidx.compose.runtime.ProvidableCompositionLocal
 import androidx.compose.runtime.staticCompositionLocalOf
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.layout.LayoutModifier
 import androidx.compose.ui.layout.Measurable
 import androidx.compose.ui.layout.MeasureResult
 import androidx.compose.ui.layout.MeasureScope
-import androidx.compose.ui.platform.debugInspectorInfo
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
+import androidx.compose.ui.node.LayoutModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.currentValueOf
+import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.DpSize
 import androidx.compose.ui.unit.dp
@@ -43,20 +46,58 @@
  * This modifier is not needed for touch target expansion to happen. It only affects layout, to make
  * sure there is adequate space for touch target expansion.
  */
-@OptIn(ExperimentalMaterial3Api::class)
-fun Modifier.minimumInteractiveComponentSize(): Modifier = composed(
-    inspectorInfo = debugInspectorInfo {
+fun Modifier.minimumInteractiveComponentSize(): Modifier = this then MinimumInteractiveModifier
+
+internal object MinimumInteractiveModifier :
+    ModifierNodeElement<MinimumInteractiveModifierNode>() {
+
+    override fun create(): MinimumInteractiveModifierNode = MinimumInteractiveModifierNode()
+
+    override fun update(node: MinimumInteractiveModifierNode) {}
+
+    override fun InspectorInfo.inspectableProperties() {
         name = "minimumInteractiveComponentSize"
         // TODO: b/214589635 - surface this information through the layout inspector in a better way
         //  - for now just add some information to help developers debug what this size represents.
         properties["README"] = "Reserves at least 48.dp in size to disambiguate touch " +
             "interactions if the element would measure smaller"
     }
-) {
-    if (LocalMinimumInteractiveComponentEnforcement.current) {
-        MinimumInteractiveComponentSizeModifier(minimumInteractiveComponentSize)
-    } else {
-        Modifier
+
+    override fun hashCode(): Int = System.identityHashCode(this)
+    override fun equals(other: Any?) = (other === this)
+}
+
+internal class MinimumInteractiveModifierNode :
+    Modifier.Node(),
+    CompositionLocalConsumerModifierNode,
+    LayoutModifierNode {
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    override fun MeasureScope.measure(
+        measurable: Measurable,
+        constraints: Constraints
+    ): MeasureResult {
+        val size = minimumInteractiveComponentSize
+        val placeable = measurable.measure(constraints)
+        val enforcement = isAttached && currentValueOf(LocalMinimumInteractiveComponentEnforcement)
+
+        // Be at least as big as the minimum dimension in both dimensions
+        val width = if (enforcement) {
+            maxOf(placeable.width, size.width.roundToPx())
+        } else {
+            placeable.width
+        }
+        val height = if (enforcement) {
+            maxOf(placeable.height, size.height.roundToPx())
+        } else {
+            placeable.height
+        }
+
+        return layout(width, height) {
+            val centerX = ((width - placeable.width) / 2f).roundToInt()
+            val centerY = ((height - placeable.height) / 2f).roundToInt()
+            placeable.place(centerX, centerY)
+        }
     }
 }
 
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
index e59e502..6b853de 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SheetDefaults.kt
@@ -130,7 +130,7 @@
      * was in before the swipe or animation started.
      */
 
-    val currentValue: SheetValue get() = swipeableState.currentValue
+    val currentValue: SheetValue get() = anchoredDraggableState.currentValue
 
     /**
      * The target value of the bottom sheet state.
@@ -139,13 +139,13 @@
      * swipe finishes. If an animation is running, this is the target value of that animation.
      * Finally, if no swipe or animation is in progress, this is the same as the [currentValue].
      */
-    val targetValue: SheetValue get() = swipeableState.targetValue
+    val targetValue: SheetValue get() = anchoredDraggableState.targetValue
 
     /**
      * Whether the modal bottom sheet is visible.
      */
     val isVisible: Boolean
-        get() = swipeableState.currentValue != Hidden
+        get() = anchoredDraggableState.currentValue != Hidden
 
     /**
      * Require the current offset (in pixels) of the bottom sheet.
@@ -163,20 +163,20 @@
      *
      * @throws IllegalStateException If the offset has not been initialized yet
      */
-    fun requireOffset(): Float = swipeableState.requireOffset()
+    fun requireOffset(): Float = anchoredDraggableState.requireOffset()
 
     /**
      * Whether the sheet has an expanded state defined.
      */
 
     val hasExpandedState: Boolean
-        get() = swipeableState.hasAnchorForValue(Expanded)
+        get() = anchoredDraggableState.anchors.hasAnchorFor(Expanded)
 
     /**
      * Whether the modal bottom sheet has a partially expanded state defined.
      */
     val hasPartiallyExpandedState: Boolean
-        get() = swipeableState.hasAnchorForValue(PartiallyExpanded)
+        get() = anchoredDraggableState.anchors.hasAnchorFor(PartiallyExpanded)
 
     /**
      * Fully expand the bottom sheet with animation and suspend until it is fully expanded or
@@ -185,7 +185,7 @@
      * @throws [CancellationException] if the animation is interrupted
      */
     suspend fun expand() {
-        swipeableState.animateTo(Expanded)
+        anchoredDraggableState.animateTo(Expanded)
     }
 
     /**
@@ -240,9 +240,9 @@
      */
     internal suspend fun animateTo(
         targetValue: SheetValue,
-        velocity: Float = swipeableState.lastVelocity
+        velocity: Float = anchoredDraggableState.lastVelocity
     ) {
-        swipeableState.animateTo(targetValue, velocity)
+        anchoredDraggableState.animateTo(targetValue, velocity)
     }
 
     /**
@@ -254,34 +254,25 @@
      * @param targetValue The target value of the animation
      */
     internal suspend fun snapTo(targetValue: SheetValue) {
-        swipeableState.snapTo(targetValue)
+        anchoredDraggableState.snapTo(targetValue)
     }
 
     /**
-     * Attempt to snap synchronously. Snapping can happen synchronously when there is no other swipe
-     * transaction like a drag or an animation is progress. If there is another interaction in
-     * progress, the suspending [snapTo] overload needs to be used.
-     *
-     * @return true if the synchronous snap was successful, or false if we couldn't snap synchronous
-     */
-    internal fun trySnapTo(targetValue: SheetValue) = swipeableState.trySnapTo(targetValue)
-
-    /**
      * Find the closest anchor taking into account the velocity and settle at it with an animation.
      */
     internal suspend fun settle(velocity: Float) {
-        swipeableState.settle(velocity)
+        anchoredDraggableState.settle(velocity)
     }
 
-    internal var swipeableState = SwipeableV2State(
+    internal var anchoredDraggableState = AnchoredDraggableState(
         initialValue = initialValue,
-        animationSpec = SwipeableV2Defaults.AnimationSpec,
+        animationSpec = AnchoredDraggableDefaults.AnimationSpec,
         confirmValueChange = confirmValueChange,
         positionalThreshold = { with(requireDensity()) { 56.dp.toPx() } },
         velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } }
     )
 
-    internal val offset: Float? get() = swipeableState.offset
+    internal val offset: Float? get() = anchoredDraggableState.offset
 
     internal var density: Density? = null
     private fun requireDensity() = requireNotNull(density) {
@@ -429,7 +420,7 @@
     override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
         val delta = available.toFloat()
         return if (delta < 0 && source == NestedScrollSource.Drag) {
-            sheetState.swipeableState.dispatchRawDelta(delta).toOffset()
+            sheetState.anchoredDraggableState.dispatchRawDelta(delta).toOffset()
         } else {
             Offset.Zero
         }
@@ -441,7 +432,7 @@
         source: NestedScrollSource
     ): Offset {
         return if (source == NestedScrollSource.Drag) {
-            sheetState.swipeableState.dispatchRawDelta(available.toFloat()).toOffset()
+            sheetState.anchoredDraggableState.dispatchRawDelta(available.toFloat()).toOffset()
         } else {
             Offset.Zero
         }
@@ -450,7 +441,8 @@
     override suspend fun onPreFling(available: Velocity): Velocity {
         val toFling = available.toFloat()
         val currentOffset = sheetState.requireOffset()
-        return if (toFling < 0 && currentOffset > sheetState.swipeableState.minOffset) {
+        val minAnchor = sheetState.anchoredDraggableState.anchors.minAnchor()
+        return if (toFling < 0 && currentOffset > minAnchor) {
             onFling(toFling)
             // since we go to the anchor with tween settling, consume all for the best UX
             available
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeToDismiss.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeToDismiss.kt
index 4506e25..4e7dcc8 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeToDismiss.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeToDismiss.kt
@@ -33,6 +33,7 @@
 import androidx.compose.runtime.saveable.Saver
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.unit.Density
@@ -129,38 +130,39 @@
     confirmValueChange: (DismissValue) -> Boolean = { true },
     positionalThreshold: (totalDistance: Float) -> Float
 ) {
-    internal val swipeableState = SwipeableV2State(
+    internal val anchoredDraggableState = AnchoredDraggableState(
         initialValue = initialValue,
+        animationSpec = AnchoredDraggableDefaults.AnimationSpec,
         confirmValueChange = confirmValueChange,
         positionalThreshold = positionalThreshold,
         velocityThreshold = { with(requireDensity()) { DismissThreshold.toPx() } }
     )
 
-    internal val offset: Float? get() = swipeableState.offset
+    internal val offset: Float get() = anchoredDraggableState.offset
 
     /**
      * Require the current offset.
      *
      * @throws IllegalStateException If the offset has not been initialized yet
      */
-    fun requireOffset(): Float = swipeableState.requireOffset()
+    fun requireOffset(): Float = anchoredDraggableState.requireOffset()
 
     /**
      * The current state value of the [DismissState].
      */
-    val currentValue: DismissValue get() = swipeableState.currentValue
+    val currentValue: DismissValue get() = anchoredDraggableState.currentValue
 
     /**
      * The target state. This is the closest state to the current offset (taking into account
      * positional thresholds). If no interactions like animations or drags are in progress, this
      * will be the current state.
      */
-    val targetValue: DismissValue get() = swipeableState.targetValue
+    val targetValue: DismissValue get() = anchoredDraggableState.targetValue
 
     /**
      * The fraction of the progress going from currentValue to targetValue, within [0f..1f] bounds.
      */
-    val progress: Float get() = swipeableState.progress
+    val progress: Float get() = anchoredDraggableState.progress
 
     /**
      * The direction (if any) in which the composable has been or is being dismissed.
@@ -169,9 +171,9 @@
      * change the background of the [SwipeToDismiss] if you want different actions on each side.
      */
     val dismissDirection: DismissDirection?
-        get() = if (offset == 0f || offset == null)
+        get() = if (offset == 0f || offset.isNaN())
             null
-        else if (offset!! > 0f) StartToEnd else EndToStart
+        else if (offset > 0f) StartToEnd else EndToStart
 
     /**
      * Whether the component has been dismissed in the given [direction].
@@ -188,7 +190,7 @@
      * @param targetValue The new target value
      */
     suspend fun snapTo(targetValue: DismissValue) {
-        swipeableState.snapTo(targetValue)
+        anchoredDraggableState.snapTo(targetValue)
     }
 
     /**
@@ -198,7 +200,7 @@
      *
      * @return the reason the reset animation ended
      */
-    suspend fun reset() = swipeableState.animateTo(targetValue = Default)
+    suspend fun reset() = anchoredDraggableState.animateTo(targetValue = Default)
 
     /**
      * Dismiss the component in the given [direction], with an animation and suspend. This method
@@ -208,7 +210,7 @@
      */
     suspend fun dismiss(direction: DismissDirection) {
         val targetValue = if (direction == StartToEnd) DismissedToEnd else DismissedToStart
-        swipeableState.animateTo(targetValue = targetValue)
+        anchoredDraggableState.animateTo(targetValue = targetValue)
     }
 
     internal var density: Density? = null
@@ -325,22 +327,26 @@
 
     Box(
         modifier
-            .swipeableV2(
-                state = state.swipeableState,
+            .anchoredDraggable(
+                state = state.anchoredDraggableState,
                 orientation = Orientation.Horizontal,
                 enabled = state.currentValue == Default,
                 reverseDirection = isRtl,
             )
-            .swipeAnchors(
-                state = state.swipeableState,
-                possibleValues = setOf(Default, DismissedToEnd, DismissedToStart)
-            ) { value, layoutSize ->
+            .onSizeChanged { layoutSize ->
                 val width = layoutSize.width.toFloat()
-                when (value) {
-                    DismissedToEnd -> if (StartToEnd in directions) width else null
-                    DismissedToStart -> if (EndToStart in directions) -width else null
-                    Default -> 0f
+                val newAnchors = DraggableAnchors {
+                    Default at 0f
+                    if (StartToEnd in directions) {
+                        DismissedToEnd at width
+                    }
+
+                    if (EndToStart in directions) {
+                        DismissedToStart at -width
+                    }
                 }
+
+                state.anchoredDraggableState.updateAnchors(newAnchors)
             }
     ) {
         Row(
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeableV2.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeableV2.kt
deleted file mode 100644
index dfead31..0000000
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/SwipeableV2.kt
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
- * 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.
- */
-// This is a mirror of androidx.compose.material.SwipeableV2.kt from M2.
-// DO NOT MODIFY DIRECTLY, make changes upstream and mirror them.
-
-package androidx.compose.material3
-
-import androidx.annotation.FloatRange
-import androidx.compose.animation.core.AnimationSpec
-import androidx.compose.animation.core.SpringSpec
-import androidx.compose.animation.core.animate
-import androidx.compose.foundation.MutatePriority
-import androidx.compose.foundation.gestures.DragScope
-import androidx.compose.foundation.gestures.DraggableState
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.draggable
-import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.offset
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Stable
-import androidx.compose.runtime.derivedStateOf
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableFloatStateOf
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.saveable.Saver
-import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.LocalDensity
-import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import kotlin.math.abs
-import kotlinx.coroutines.CancellationException
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-
-/**
- * Enable swipe gestures between a set of predefined values.
- *
- * When a swipe is detected, the offset of the [SwipeableV2State] will be updated with the swipe
- * delta. You should use this offset to move your content accordingly (see [Modifier.offset]).
- * When the swipe ends, the offset will be animated to one of the anchors and when that anchor is
- * reached, the value of the [SwipeableV2State] will also be updated to the value corresponding to
- * the new anchor.
- *
- * Swiping is constrained between the minimum and maximum anchors.
- *
- * @param state The associated [SwipeableV2State].
- * @param orientation The orientation in which the swipeable can be swiped.
- * @param enabled Whether this [swipeableV2] is enabled and should react to the user's input.
- * @param reverseDirection Whether to reverse the direction of the swipe, so a top to bottom
- * swipe will behave like bottom to top, and a left to right swipe will behave like right to left.
- * @param interactionSource Optional [MutableInteractionSource] that will passed on to
- * the internal [Modifier.draggable].
- */
-@ExperimentalMaterial3Api
-internal fun <T> Modifier.swipeableV2(
-    state: SwipeableV2State<T>,
-    orientation: Orientation,
-    enabled: Boolean = true,
-    reverseDirection: Boolean = false,
-    interactionSource: MutableInteractionSource? = null
-) = draggable(
-    state = state.swipeDraggableState,
-    orientation = orientation,
-    enabled = enabled,
-    interactionSource = interactionSource,
-    reverseDirection = reverseDirection,
-    startDragImmediately = state.isAnimationRunning,
-    onDragStopped = { velocity -> launch { state.settle(velocity) } }
-)
-
-/**
- * Define anchor points for a given [SwipeableV2State] based on this node's layout size and update
- * the state with them.
- *
- * @param state The associated [SwipeableV2State]
- * @param possibleValues All possible values the [SwipeableV2State] could be in.
- * @param anchorChangeHandler A callback to be invoked when the anchors have changed,
- * `null` by default. Components with custom reconciliation logic should implement this callback,
- * i.e. to re-target an in-progress animation.
- * @param calculateAnchor This method will be invoked to calculate the position of all
- * [possibleValues], given this node's layout size. Return the anchor's offset from the initial
- * anchor, or `null` to indicate that a value does not have an anchor.
- */
-@ExperimentalMaterial3Api
-internal fun <T> Modifier.swipeAnchors(
-    state: SwipeableV2State<T>,
-    possibleValues: Set<T>,
-    anchorChangeHandler: AnchorChangeHandler<T>? = null,
-    calculateAnchor: (value: T, layoutSize: IntSize) -> Float?,
-) = onSizeChanged { layoutSize ->
-    val previousAnchors = state.anchors
-    val newAnchors = mutableMapOf<T, Float>()
-    possibleValues.forEach {
-        val anchorValue = calculateAnchor(it, layoutSize)
-        if (anchorValue != null) {
-            newAnchors[it] = anchorValue
-        }
-    }
-    if (previousAnchors != newAnchors) {
-        val previousTarget = state.targetValue
-        val stateRequiresCleanup = state.updateAnchors(newAnchors)
-        if (stateRequiresCleanup) {
-            anchorChangeHandler?.onAnchorsChanged(
-                previousTarget,
-                previousAnchors,
-                newAnchors
-            )
-        }
-    }
-}
-
-/**
- * State of the [swipeableV2] modifier.
- *
- * This contains necessary information about any ongoing swipe or animation and provides methods
- * to change the state either immediately or by starting an animation. To create and remember a
- * [SwipeableV2State] use [rememberSwipeableV2State].
- *
- * @param initialValue The initial value of the state.
- * @param animationSpec The default animation that will be used to animate to a new state.
- * @param confirmValueChange Optional callback invoked to confirm or veto a pending state change.
- * @param positionalThreshold The positional threshold, in px, to be used when calculating the
- * target state while a swipe is in progress and when settling after the swipe ends. This is the
- * distance from the start of a transition. It will be, depending on the direction of the
- * interaction, added or subtracted from/to the origin offset. It should always be a positive value.
- * @param velocityThreshold The velocity threshold (in px per second) that the end velocity has to
- * exceed in order to animate to the next state, even if the [positionalThreshold] has not been
- * reached.
- */
-@Suppress("PrimitiveInLambda")
-@Stable
-@ExperimentalMaterial3Api
-internal class SwipeableV2State<T>(
-    initialValue: T,
-    internal val positionalThreshold: (totalDistance: Float) -> Float,
-    internal val velocityThreshold: () -> Float,
-    internal val animationSpec: AnimationSpec<Float> = SwipeableV2Defaults.AnimationSpec,
-    internal val confirmValueChange: (newValue: T) -> Boolean = { true },
-) {
-
-    private val swipeMutex = InternalMutatorMutex()
-
-    internal val swipeDraggableState = object : DraggableState {
-        private val dragScope = object : DragScope {
-            override fun dragBy(pixels: Float) {
-                this@SwipeableV2State.dispatchRawDelta(pixels)
-            }
-        }
-
-        override suspend fun drag(
-            dragPriority: MutatePriority,
-            block: suspend DragScope.() -> Unit
-        ) {
-            swipe(dragPriority) { dragScope.block() }
-        }
-
-        override fun dispatchRawDelta(delta: Float) {
-            this@SwipeableV2State.dispatchRawDelta(delta)
-        }
-    }
-
-    /**
-     * The current value of the [SwipeableV2State].
-     */
-    var currentValue: T by mutableStateOf(initialValue)
-        private set
-
-    /**
-     * The target value. This is the closest value to the current offset (taking into account
-     * positional thresholds). If no interactions like animations or drags are in progress, this
-     * will be the current value.
-     */
-    val targetValue: T by derivedStateOf {
-        animationTarget ?: run {
-            val currentOffset = offset
-            if (currentOffset != null) {
-                computeTarget(currentOffset, currentValue, velocity = 0f)
-            } else currentValue
-        }
-    }
-
-    /**
-     * The current offset, or null if it has not been initialized yet.
-     *
-     * The offset will be initialized during the first measurement phase of the node that the
-     * [swipeableV2] modifier is attached to. These are the phases:
-     * Composition { -> Effects } -> Layout { Measurement -> Placement } -> Drawing
-     * During the first composition, the offset will be null. In subsequent compositions, the offset
-     * will be derived from the anchors of the previous pass.
-     * Always prefer accessing the offset from a LaunchedEffect as it will be scheduled to be
-     * executed the next frame, after layout.
-     *
-     * To guarantee stricter semantics, consider using [requireOffset].
-     */
-    @get:Suppress("AutoBoxing")
-    var offset: Float? by mutableStateOf(null)
-        private set
-
-    /**
-     * Require the current offset.
-     *
-     * @throws IllegalStateException If the offset has not been initialized yet
-     */
-    fun requireOffset(): Float = checkNotNull(offset) {
-        "The offset was read before being initialized. Did you access the offset in a phase " +
-            "before layout, like effects or composition?"
-    }
-
-    /**
-     * Whether an animation is currently in progress.
-     */
-    val isAnimationRunning: Boolean get() = animationTarget != null
-
-    /**
-     * The fraction of the progress going from [currentValue] to [targetValue], within [0f..1f]
-     * bounds.
-     */
-    @get:FloatRange(from = 0.0, to = 1.0)
-    val progress: Float by derivedStateOf {
-        val a = anchors[currentValue] ?: 0f
-        val b = anchors[targetValue] ?: 0f
-        val distance = abs(b - a)
-        if (distance > 1e-6f) {
-            val progress = (this.requireOffset() - a) / (b - a)
-            // If we are very close to 0f or 1f, we round to the closest
-            if (progress < 1e-6f) 0f else if (progress > 1 - 1e-6f) 1f else progress
-        } else 1f
-    }
-
-    /**
-     * The velocity of the last known animation. Gets reset to 0f when an animation completes
-     * successfully, but does not get reset when an animation gets interrupted.
-     * You can use this value to provide smooth reconciliation behavior when re-targeting an
-     * animation.
-     */
-    var lastVelocity: Float by mutableFloatStateOf(0f)
-        private set
-
-    /**
-     * The minimum offset this state can reach. This will be the smallest anchor, or
-     * [Float.NEGATIVE_INFINITY] if the anchors are not initialized yet.
-     */
-    val minOffset by derivedStateOf { anchors.minOrNull() ?: Float.NEGATIVE_INFINITY }
-
-    /**
-     * The maximum offset this state can reach. This will be the biggest anchor, or
-     * [Float.POSITIVE_INFINITY] if the anchors are not initialized yet.
-     */
-    val maxOffset by derivedStateOf { anchors.maxOrNull() ?: Float.POSITIVE_INFINITY }
-
-    private var animationTarget: T? by mutableStateOf(null)
-
-    internal var anchors by mutableStateOf(emptyMap<T, Float>())
-
-    /**
-     * Update the anchors.
-     * If the previous set of anchors was empty, attempt to update the offset to match the initial
-     * value's anchor.
-     *
-     * @return true if the state needs to be adjusted after updating the anchors, e.g. if the
-     * initial value is not found in the initial set of anchors. false if no further updates are
-     * needed.
-     */
-    internal fun updateAnchors(newAnchors: Map<T, Float>): Boolean {
-        val previousAnchorsEmpty = anchors.isEmpty()
-        anchors = newAnchors
-        val initialValueHasAnchor = if (previousAnchorsEmpty) {
-            val initialValue = currentValue
-            val initialValueAnchor = anchors[initialValue]
-            val initialValueHasAnchor = initialValueAnchor != null
-            if (initialValueHasAnchor) trySnapTo(initialValue)
-            initialValueHasAnchor
-        } else true
-        return !initialValueHasAnchor || !previousAnchorsEmpty
-    }
-
-    /**
-     * Whether the [value] has an anchor associated with it.
-     */
-    fun hasAnchorForValue(value: T): Boolean = anchors.containsKey(value)
-
-    /**
-     * Snap to a [targetValue] without any animation.
-     * If the [targetValue] is not in the set of anchors, the [currentValue] will be updated to the
-     * [targetValue] without updating the offset.
-     *
-     * @throws CancellationException if the interaction interrupted by another interaction like a
-     * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
-     *
-     * @param targetValue The target value of the animation
-     */
-    suspend fun snapTo(targetValue: T) {
-        swipe { snap(targetValue) }
-    }
-
-    /**
-     * Animate to a [targetValue].
-     * If the [targetValue] is not in the set of anchors, the [currentValue] will be updated to the
-     * [targetValue] without updating the offset.
-     *
-     * @throws CancellationException if the interaction interrupted by another interaction like a
-     * gesture interaction or another programmatic interaction like a [animateTo] or [snapTo] call.
-     *
-     * @param targetValue The target value of the animation
-     * @param velocity The velocity the animation should start with, [lastVelocity] by default
-     */
-    suspend fun animateTo(
-        targetValue: T,
-        velocity: Float = lastVelocity,
-    ) {
-        val targetOffset = anchors[targetValue]
-        if (targetOffset != null) {
-            try {
-                swipe {
-                    animationTarget = targetValue
-                    var prev = offset ?: 0f
-                    animate(prev, targetOffset, velocity, animationSpec) { value, velocity ->
-                        // Our onDrag coerces the value within the bounds, but an animation may
-                        // overshoot, for example a spring animation or an overshooting interpolator
-                        // We respect the user's intention and allow the overshoot, but still use
-                        // DraggableState's drag for its mutex.
-                        offset = value
-                        prev = value
-                        lastVelocity = velocity
-                    }
-                    lastVelocity = 0f
-                }
-            } finally {
-                animationTarget = null
-                val endOffset = requireOffset()
-                val endState = anchors
-                    .entries
-                    .firstOrNull { (_, anchorOffset) -> abs(anchorOffset - endOffset) < 0.5f }
-                    ?.key
-                this.currentValue = endState ?: currentValue
-            }
-        } else {
-            currentValue = targetValue
-        }
-    }
-
-    /**
-     * Find the closest anchor taking into account the velocity and settle at it with an animation.
-     */
-    suspend fun settle(velocity: Float) {
-        val previousValue = this.currentValue
-        val targetValue = computeTarget(
-            offset = requireOffset(),
-            currentValue = previousValue,
-            velocity = velocity
-        )
-        if (confirmValueChange(targetValue)) {
-            animateTo(targetValue, velocity)
-        } else {
-            // If the user vetoed the state change, rollback to the previous state.
-            animateTo(previousValue, velocity)
-        }
-    }
-
-    /**
-     * Swipe by the [delta], coerce it in the bounds and dispatch it to the [SwipeableV2State].
-     *
-     * @return The delta the consumed by the [SwipeableV2State]
-     */
-    fun dispatchRawDelta(delta: Float): Float {
-        val currentDragPosition = offset ?: 0f
-        val potentiallyConsumed = currentDragPosition + delta
-        val clamped = potentiallyConsumed.coerceIn(minOffset, maxOffset)
-        val deltaToConsume = clamped - currentDragPosition
-        if (abs(deltaToConsume) >= 0) {
-            offset = ((offset ?: 0f) + deltaToConsume).coerceIn(minOffset, maxOffset)
-        }
-        return deltaToConsume
-    }
-
-    private fun computeTarget(
-        offset: Float,
-        currentValue: T,
-        velocity: Float
-    ): T {
-        val currentAnchors = anchors
-        val currentAnchor = currentAnchors[currentValue]
-        val velocityThresholdPx = velocityThreshold()
-        return if (currentAnchor == offset || currentAnchor == null) {
-            currentValue
-        } else if (currentAnchor < offset) {
-            // Swiping from lower to upper (positive).
-            if (velocity >= velocityThresholdPx) {
-                currentAnchors.closestAnchor(offset, true)
-            } else {
-                val upper = currentAnchors.closestAnchor(offset, true)
-                val distance = abs(currentAnchors.getValue(upper) - currentAnchor)
-                val relativeThreshold = abs(positionalThreshold(distance))
-                val absoluteThreshold = abs(currentAnchor + relativeThreshold)
-                if (offset < absoluteThreshold) currentValue else upper
-            }
-        } else {
-            // Swiping from upper to lower (negative).
-            if (velocity <= -velocityThresholdPx) {
-                currentAnchors.closestAnchor(offset, false)
-            } else {
-                val lower = currentAnchors.closestAnchor(offset, false)
-                val distance = abs(currentAnchor - currentAnchors.getValue(lower))
-                val relativeThreshold = abs(positionalThreshold(distance))
-                val absoluteThreshold = abs(currentAnchor - relativeThreshold)
-                if (offset < 0) {
-                    // For negative offsets, larger absolute thresholds are closer to lower anchors
-                    // than smaller ones.
-                    if (abs(offset) < absoluteThreshold) currentValue else lower
-                } else {
-                    if (offset > absoluteThreshold) currentValue else lower
-                }
-            }
-        }
-    }
-
-    private suspend fun swipe(
-        swipePriority: MutatePriority = MutatePriority.Default,
-        action: suspend () -> Unit
-    ): Unit = coroutineScope { swipeMutex.mutate(swipePriority, action) }
-
-    /**
-     * Attempt to snap synchronously. Snapping can happen synchronously when there is no other swipe
-     * transaction like a drag or an animation is progress. If there is another interaction in
-     * progress, the suspending [snapTo] overload needs to be used.
-     *
-     * @return true if the synchronous snap was successful, or false if we couldn't snap synchronous
-     */
-    internal fun trySnapTo(targetValue: T): Boolean = swipeMutex.tryMutate { snap(targetValue) }
-
-    private fun snap(targetValue: T) {
-        val targetOffset = anchors[targetValue]
-        if (targetOffset != null) {
-            dispatchRawDelta(targetOffset - (offset ?: 0f))
-            currentValue = targetValue
-            animationTarget = null
-        } else {
-            currentValue = targetValue
-        }
-    }
-
-    companion object {
-        /**
-         * The default [Saver] implementation for [SwipeableV2State].
-         */
-        @ExperimentalMaterial3Api
-        fun <T : Any> Saver(
-            animationSpec: AnimationSpec<Float>,
-            confirmValueChange: (T) -> Boolean,
-            positionalThreshold: (distance: Float) -> Float,
-            velocityThreshold: () -> Float
-        ) = Saver<SwipeableV2State<T>, T>(
-            save = { it.currentValue },
-            restore = {
-                SwipeableV2State(
-                    initialValue = it,
-                    animationSpec = animationSpec,
-                    confirmValueChange = confirmValueChange,
-                    positionalThreshold = positionalThreshold,
-                    velocityThreshold = velocityThreshold
-                )
-            }
-        )
-    }
-}
-
-/**
- * Create and remember a [SwipeableV2State].
- *
- * @param initialValue The initial value.
- * @param animationSpec The default animation that will be used to animate to a new value.
- * @param confirmValueChange Optional callback invoked to confirm or veto a pending value change.
- */
-@Suppress("PrimitiveInLambda")
-@Composable
-@ExperimentalMaterial3Api
-internal fun <T : Any> rememberSwipeableV2State(
-    initialValue: T,
-    animationSpec: AnimationSpec<Float> = SwipeableV2Defaults.AnimationSpec,
-    confirmValueChange: (newValue: T) -> Boolean = { true }
-): SwipeableV2State<T> {
-    val positionalThreshold = SwipeableV2Defaults.positionalThreshold
-    val velocityThreshold = SwipeableV2Defaults.velocityThreshold
-
-    return rememberSaveable(
-        initialValue, animationSpec, confirmValueChange, positionalThreshold, velocityThreshold,
-        saver = SwipeableV2State.Saver(
-            animationSpec = animationSpec,
-            confirmValueChange = confirmValueChange,
-            positionalThreshold = positionalThreshold,
-            velocityThreshold = velocityThreshold
-        ),
-    ) {
-        SwipeableV2State(
-            initialValue = initialValue,
-            animationSpec = animationSpec,
-            confirmValueChange = confirmValueChange,
-            positionalThreshold = positionalThreshold,
-            velocityThreshold = velocityThreshold
-        )
-    }
-}
-
-/**
- * Contains useful defaults for [swipeableV2] and [SwipeableV2State].
- */
-@Suppress("PrimitiveInLambda")
-@Stable
-@ExperimentalMaterial3Api
-internal object SwipeableV2Defaults {
-    /**
-     * The default animation used by [SwipeableV2State].
-     */
-    @ExperimentalMaterial3Api
-    val AnimationSpec = SpringSpec<Float>()
-
-    /**
-     * The default velocity threshold (1.8 dp per millisecond) used by [rememberSwipeableV2State].
-     */
-    @ExperimentalMaterial3Api
-    val velocityThreshold: () -> Float
-        @Composable get() = with(LocalDensity.current) { { 125.dp.toPx() } }
-
-    /**
-     * The default positional threshold (56 dp) used by [rememberSwipeableV2State]
-     */
-    @ExperimentalMaterial3Api
-    val positionalThreshold: (totalDistance: Float) -> Float
-        @Composable get() = with(LocalDensity.current) {
-            { 56.dp.toPx() }
-        }
-
-    /**
-     * A [AnchorChangeHandler] implementation that attempts to reconcile an in-progress animation
-     * by re-targeting it if necessary or finding the closest new anchor.
-     * If the previous anchor is not in the new set of anchors, this implementation will snap to the
-     * closest anchor.
-     *
-     * Consider implementing a custom handler for more complex components like sheets.
-     * The [animate] and [snap] lambdas hoist the animation and snap logic. Usually these will just
-     * delegate to [SwipeableV2State].
-     *
-     * @param state The [SwipeableV2State] the change handler will read from
-     * @param animate A lambda that gets invoked to start an animation to a new target
-     * @param snap A lambda that gets invoked to snap to a new target
-     */
-    @ExperimentalMaterial3Api
-    internal fun <T> ReconcileAnimationOnAnchorChangeHandler(
-        state: SwipeableV2State<T>,
-        animate: (target: T, velocity: Float) -> Unit,
-        snap: (target: T) -> Unit
-    ) = AnchorChangeHandler { previousTarget, previousAnchors, newAnchors ->
-        val previousTargetOffset = previousAnchors[previousTarget]
-        val newTargetOffset = newAnchors[previousTarget]
-        if (previousTargetOffset != newTargetOffset) {
-            if (newTargetOffset != null) {
-                animate(previousTarget, state.lastVelocity)
-            } else {
-                snap(newAnchors.closestAnchor(offset = state.requireOffset()))
-            }
-        }
-    }
-}
-
-/**
- * Defines a callback that is invoked when the anchors have changed.
- *
- * Components with custom reconciliation logic should implement this callback, for example to
- * re-target an in-progress animation when the anchors change.
- *
- * @see SwipeableV2Defaults.ReconcileAnimationOnAnchorChangeHandler for a default implementation
- */
-@ExperimentalMaterial3Api
-internal fun interface AnchorChangeHandler<T> {
-
-    /**
-     * Callback that is invoked when the anchors have changed, after the [SwipeableV2State] has been
-     * updated with them. Use this hook to re-launch animations or interrupt them if needed.
-     *
-     * @param previousTargetValue The target value before the anchors were updated
-     * @param previousAnchors The previously set anchors
-     * @param newAnchors The newly set anchors
-     */
-    fun onAnchorsChanged(
-        previousTargetValue: T,
-        previousAnchors: Map<T, Float>,
-        newAnchors: Map<T, Float>
-    )
-}
-
-private fun <T> Map<T, Float>.closestAnchor(
-    offset: Float = 0f,
-    searchUpwards: Boolean = false
-): T {
-    require(isNotEmpty()) { "The anchors were empty when trying to find the closest anchor" }
-    return minBy { (_, anchor) ->
-        val delta = if (searchUpwards) anchor - offset else offset - anchor
-        if (delta < 0) Float.POSITIVE_INFINITY else delta
-    }.key
-}
-
-private fun <T> Map<T, Float>.minOrNull() = minOfOrNull { (_, offset) -> offset }
-private fun <T> Map<T, Float>.maxOrNull() = maxOfOrNull { (_, offset) -> offset }
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
index 3f6e81e..22feae8 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TimePicker.kt
@@ -101,7 +101,6 @@
 import androidx.compose.runtime.structuralEqualityPolicy
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
 import androidx.compose.ui.draw.drawWithContent
 import androidx.compose.ui.focus.FocusRequester
 import androidx.compose.ui.focus.focusRequester
@@ -114,7 +113,9 @@
 import androidx.compose.ui.input.key.onKeyEvent
 import androidx.compose.ui.input.key.onPreviewKeyEvent
 import androidx.compose.ui.input.key.utf16CodePoint
-import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.input.pointer.PointerEvent
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNode
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.layout.LayoutModifier
 import androidx.compose.ui.layout.Measurable
@@ -124,7 +125,12 @@
 import androidx.compose.ui.layout.boundsInParent
 import androidx.compose.ui.layout.layoutId
 import androidx.compose.ui.layout.onGloballyPositioned
-import androidx.compose.ui.layout.onSizeChanged
+import androidx.compose.ui.node.CompositionLocalConsumerModifierNode
+import androidx.compose.ui.node.DelegatingNode
+import androidx.compose.ui.node.LayoutAwareModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
+import androidx.compose.ui.node.PointerInputModifierNode
+import androidx.compose.ui.node.requireDensity
 import androidx.compose.ui.platform.InspectorInfo
 import androidx.compose.ui.platform.InspectorValueInfo
 import androidx.compose.ui.platform.LocalDensity
@@ -149,6 +155,7 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.DpOffset
 import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.center
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.zIndex
@@ -926,10 +933,12 @@
             )
 
             val items = measurables.filter { it.layoutId != "Spacer" }.map { item ->
-                item.measure(constraints.copy(
-                    minWidth = 0,
-                    maxWidth = constraints.maxWidth / 2
-                ))
+                item.measure(
+                    constraints.copy(
+                        minWidth = 0,
+                        maxWidth = constraints.maxWidth / 2
+                    )
+                )
             }
 
             layout(constraints.maxWidth, constraints.maxHeight) {
@@ -969,10 +978,12 @@
             )
 
             val items = measurables.filter { it.layoutId != "Spacer" }.map { item ->
-                item.measure(constraints.copy(
-                    minHeight = 0,
-                    maxHeight = constraints.maxHeight / 2
-                ))
+                item.measure(
+                    constraints.copy(
+                        minHeight = 0,
+                        maxHeight = constraints.maxHeight / 2
+                    )
+                )
             }
 
             layout(constraints.maxWidth, constraints.maxHeight) {
@@ -1150,6 +1161,98 @@
     }
 }
 
+@OptIn(ExperimentalMaterial3Api::class)
+internal data class ClockDialModifier(
+    private val state: TimePickerState,
+    private val autoSwitchToMinute: Boolean,
+) : ModifierNodeElement<ClockDialNode>() {
+
+    override fun create(): ClockDialNode = ClockDialNode(
+        state = state,
+        autoSwitchToMinute = autoSwitchToMinute,
+    )
+
+    override fun update(node: ClockDialNode) {
+        node.updateNode(
+            state = state,
+            autoSwitchToMinute = autoSwitchToMinute,
+        )
+    }
+
+    override fun InspectorInfo.inspectableProperties() {
+        // Show nothing in the inspector.
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+internal class ClockDialNode(
+    private var state: TimePickerState,
+    private var autoSwitchToMinute: Boolean
+) : DelegatingNode(),
+    PointerInputModifierNode,
+    CompositionLocalConsumerModifierNode,
+    LayoutAwareModifierNode {
+
+    private var offsetX = 0f
+    private var offsetY = 0f
+    private val maxDist get() = with(requireDensity()) { MaxDistance.toPx() }
+
+    private val pointerInputTapNode = delegate(SuspendingPointerInputModifierNode {
+        detectTapGestures(
+            onPress = {
+                offsetX = it.x
+                offsetY = it.y
+            },
+            onTap = {
+                coroutineScope.launch { state.onTap(it.x, it.y, maxDist, autoSwitchToMinute) }
+            },
+        )
+    })
+
+    private val pointerInputDragNode = delegate(SuspendingPointerInputModifierNode {
+        detectDragGestures(onDragEnd = {
+            coroutineScope.launch {
+                if (state.selection == Selection.Hour && autoSwitchToMinute) {
+                    state.selection = Selection.Minute
+                    state.animateToCurrent()
+                } else if (state.selection == Selection.Minute) {
+                    state.settle()
+                }
+            }
+        }) { _, dragAmount ->
+            coroutineScope.launch {
+                offsetX += dragAmount.x
+                offsetY += dragAmount.y
+                state.update(atan(offsetY - state.center.y, offsetX - state.center.x))
+            }
+            state.moveSelector(offsetX, offsetY, maxDist)
+        }
+    })
+
+    override fun onRemeasured(size: IntSize) {
+        state.center = size.center
+    }
+
+    override fun onPointerEvent(
+        pointerEvent: PointerEvent,
+        pass: PointerEventPass,
+        bounds: IntSize
+    ) {
+        pointerInputTapNode.onPointerEvent(pointerEvent, pass, bounds)
+        pointerInputDragNode.onPointerEvent(pointerEvent, pass, bounds)
+    }
+
+    override fun onCancelPointerInput() {
+        pointerInputTapNode.onCancelPointerInput()
+        pointerInputDragNode.onCancelPointerInput()
+    }
+
+    fun updateNode(state: TimePickerState, autoSwitchToMinute: Boolean) {
+        this.state = state
+        this.autoSwitchToMinute = autoSwitchToMinute
+    }
+}
+
 @Composable
 internal fun ClockFace(
     state: TimePickerState,
@@ -1166,7 +1269,7 @@
     ) { screen ->
         CircularLayout(
             modifier = Modifier
-                .clockDial(state, autoSwitchToMinute)
+                .then(ClockDialModifier(state, autoSwitchToMinute))
                 .size(ClockDialContainerSize)
                 .drawSelector(state, colors),
             radius = OuterCircleSizeRadius,
@@ -1277,51 +1380,6 @@
     )
 }
 
-private fun Modifier.clockDial(state: TimePickerState, autoSwitchToMinute: Boolean): Modifier =
-    composed(debugInspectorInfo {
-    name = "clockDial"
-    properties["state"] = state
-}) {
-    var offsetX by remember { mutableFloatStateOf(0f) }
-    var offsetY by remember { mutableFloatStateOf(0f) }
-    val center by remember { mutableStateOf(IntOffset.Zero) }
-    val scope = rememberCoroutineScope()
-    val maxDist = with(LocalDensity.current) { MaxDistance.toPx() }
-
-        Modifier
-            .onSizeChanged { state.center = it.center }
-            .pointerInput(state, center, maxDist) {
-                detectTapGestures(
-                    onPress = {
-                        offsetX = it.x
-                        offsetY = it.y
-                    },
-                    onTap = {
-                        scope.launch { state.onTap(it.x, it.y, maxDist, autoSwitchToMinute) }
-                    },
-                )
-            }
-            .pointerInput(state, center, maxDist) {
-                detectDragGestures(onDragEnd = {
-                    scope.launch {
-                        if (state.selection == Selection.Hour && autoSwitchToMinute) {
-                            state.selection = Selection.Minute
-                            state.animateToCurrent()
-                        } else if (state.selection == Selection.Minute) {
-                            state.settle()
-                        }
-                    }
-                }) { _, dragAmount ->
-                    scope.launch {
-                        offsetX += dragAmount.x
-                        offsetY += dragAmount.y
-                        state.update(atan(offsetY - state.center.y, offsetX - state.center.x))
-                    }
-                    state.moveSelector(offsetX, offsetY, maxDist)
-                }
-            }
-}
-
 @Composable
 private fun ClockText(
     modifier: Modifier,
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TonalPalette.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TonalPalette.kt
index de0c458..c795263 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TonalPalette.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TonalPalette.kt
@@ -65,16 +65,27 @@
     // Ordered from the lightest shade [neutralVariant100] to the darkest shade [neutralVariant0].
     val neutralVariant100: Color,
     val neutralVariant99: Color,
+    val neutralVariant98: Color,
+    val neutralVariant96: Color,
     val neutralVariant95: Color,
+    val neutralVariant94: Color,
+    val neutralVariant92: Color,
     val neutralVariant90: Color,
+    val neutralVariant87: Color,
     val neutralVariant80: Color,
     val neutralVariant70: Color,
     val neutralVariant60: Color,
     val neutralVariant50: Color,
     val neutralVariant40: Color,
     val neutralVariant30: Color,
+    val neutralVariant24: Color,
+    val neutralVariant22: Color,
     val neutralVariant20: Color,
+    val neutralVariant17: Color,
+    val neutralVariant12: Color,
     val neutralVariant10: Color,
+    val neutralVariant6: Color,
+    val neutralVariant4: Color,
     val neutralVariant0: Color,
 
     // The primary tonal range from the generated dynamic color palette.
@@ -207,4 +218,17 @@
         tertiary20 = PaletteTokens.Tertiary20,
         tertiary10 = PaletteTokens.Tertiary10,
         tertiary0 = PaletteTokens.Tertiary0,
+
+        // Currently unused baseline palette values
+        neutralVariant98 = Color.Unspecified,
+        neutralVariant96 = Color.Unspecified,
+        neutralVariant94 = Color.Unspecified,
+        neutralVariant92 = Color.Unspecified,
+        neutralVariant87 = Color.Unspecified,
+        neutralVariant24 = Color.Unspecified,
+        neutralVariant22 = Color.Unspecified,
+        neutralVariant17 = Color.Unspecified,
+        neutralVariant12 = Color.Unspecified,
+        neutralVariant6 = Color.Unspecified,
+        neutralVariant4 = Color.Unspecified
     )
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
index 7052341..67bdfb5 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/Tooltip.kt
@@ -18,15 +18,16 @@
 
 import androidx.compose.animation.core.LinearEasing
 import androidx.compose.animation.core.LinearOutSlowInEasing
+import androidx.compose.animation.core.MutableTransitionState
 import androidx.compose.animation.core.Transition
 import androidx.compose.animation.core.animateFloat
 import androidx.compose.animation.core.tween
 import androidx.compose.animation.core.updateTransition
+import androidx.compose.foundation.BasicTooltipBox
+import androidx.compose.foundation.BasicTooltipDefaults
+import androidx.compose.foundation.BasicTooltipState
 import androidx.compose.foundation.MutatePriority
 import androidx.compose.foundation.MutatorMutex
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.awaitFirstDown
-import androidx.compose.foundation.gestures.waitForUpOrCancellation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.PaddingValues
@@ -38,29 +39,19 @@
 import androidx.compose.material3.tokens.RichTooltipTokens
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
-import androidx.compose.runtime.rememberCoroutineScope
-import androidx.compose.runtime.setValue
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.Shape
 import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.input.pointer.PointerEventPass
-import androidx.compose.ui.input.pointer.PointerEventTimeoutCancellationException
-import androidx.compose.ui.input.pointer.pointerInput
 import androidx.compose.ui.platform.LocalDensity
 import androidx.compose.ui.platform.debugInspectorInfo
-import androidx.compose.ui.semantics.LiveRegionMode
-import androidx.compose.ui.semantics.liveRegion
-import androidx.compose.ui.semantics.onLongClick
-import androidx.compose.ui.semantics.paneTitle
-import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntRect
@@ -69,13 +60,14 @@
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.PopupPositionProvider
 import kotlinx.coroutines.CancellableContinuation
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.suspendCancellableCoroutine
 import kotlinx.coroutines.withTimeout
 
-// TODO: add link to m3 doc once created by designer at the top
 /**
- * Plain tooltip that provides a descriptive message for an anchor.
+ * Material TooltipBox that wraps a composable with a tooltip.
+ *
+ * tooltips provide a descriptive message for an anchor.
+ * It can be used to call the users attention to the anchor.
  *
  * Tooltip that is invoked when the anchor is long pressed:
  *
@@ -85,58 +77,6 @@
  *
  * @sample androidx.compose.material3.samples.PlainTooltipWithManualInvocationSample
  *
- * @param tooltip the composable that will be used to populate the tooltip's content.
- * @param modifier the [Modifier] to be applied to the tooltip.
- * @param focusable [Boolean] that determines if the tooltip is focusable. When true,
- * the tooltip will consume touch events while it's shown and will have accessibility
- * focus move to the first element of the component. When false, the tooltip
- * won't consume touch events while it's shown but assistive-tech users will need
- * to swipe or drag to get to the first element of the component.
- * @param tooltipState handles the state of the tooltip's visibility.
- * @param shape the [Shape] that should be applied to the tooltip container.
- * @param containerColor [Color] that will be applied to the tooltip's container.
- * @param contentColor [Color] that will be applied to the tooltip's content.
- * @param content the composable that the tooltip will anchor to.
- */
-@Composable
-@ExperimentalMaterial3Api
-fun PlainTooltipBox(
-    tooltip: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    focusable: Boolean = true,
-    tooltipState: PlainTooltipState = rememberPlainTooltipState(),
-    shape: Shape = TooltipDefaults.plainTooltipContainerShape,
-    containerColor: Color = TooltipDefaults.plainTooltipContainerColor,
-    contentColor: Color = TooltipDefaults.plainTooltipContentColor,
-    content: @Composable TooltipBoxScope.() -> Unit
-) {
-    val tooltipAnchorPadding = with(LocalDensity.current) { TooltipAnchorPadding.roundToPx() }
-    val positionProvider = remember { PlainTooltipPositionProvider(tooltipAnchorPadding) }
-
-    TooltipBox(
-        tooltipContent = {
-            PlainTooltipImpl(
-                textColor = contentColor,
-                content = tooltip
-            )
-        },
-        modifier = modifier,
-        focusable = focusable,
-        tooltipState = tooltipState,
-        shape = shape,
-        containerColor = containerColor,
-        tooltipPositionProvider = positionProvider,
-        elevation = 0.dp,
-        maxWidth = PlainTooltipMaxWidth,
-        content = content
-    )
-}
-
-// TODO: add link to m3 doc once created by designer
-/**
- * Rich text tooltip that allows the user to pass in a title, text, and action.
- * Tooltips are used to provide a descriptive message for an anchor.
- *
  * Tooltip that is invoked when the anchor is long pressed:
  *
  * @sample androidx.compose.material3.samples.RichTooltipSample
@@ -145,266 +85,197 @@
  *
  * @sample androidx.compose.material3.samples.RichTooltipWithManualInvocationSample
  *
- * @param text the message to be displayed in the center of the tooltip.
+ * @param positionProvider [PopupPositionProvider] that will be used to place the tooltip
+ * relative to the anchor content.
+ * @param tooltip the composable that will be used to populate the tooltip's content.
+ * @param state handles the state of the tooltip's visibility.
  * @param modifier the [Modifier] to be applied to the tooltip.
  * @param focusable [Boolean] that determines if the tooltip is focusable. When true,
  * the tooltip will consume touch events while it's shown and will have accessibility
  * focus move to the first element of the component. When false, the tooltip
  * won't consume touch events while it's shown but assistive-tech users will need
  * to swipe or drag to get to the first element of the component.
- * @param tooltipState handles the state of the tooltip's visibility.
- * @param title An optional title for the tooltip.
- * @param action An optional action for the tooltip.
- * @param shape the [Shape] that should be applied to the tooltip container.
- * @param colors [RichTooltipColors] that will be applied to the tooltip's container and content.
+ * @param enableUserInput [Boolean] which determines if this TooltipBox will handle
+ * long press and mouse hover to trigger the tooltip through the state provided.
  * @param content the composable that the tooltip will anchor to.
  */
 @Composable
-@ExperimentalMaterial3Api
-fun RichTooltipBox(
-    text: @Composable () -> Unit,
+fun TooltipBox(
+    positionProvider: PopupPositionProvider,
+    tooltip: @Composable () -> Unit,
+    state: TooltipState,
     modifier: Modifier = Modifier,
     focusable: Boolean = true,
-    title: (@Composable () -> Unit)? = null,
-    action: (@Composable () -> Unit)? = null,
-    tooltipState: RichTooltipState = rememberRichTooltipState(action != null),
-    shape: Shape = TooltipDefaults.richTooltipContainerShape,
-    colors: RichTooltipColors = TooltipDefaults.richTooltipColors(),
-    content: @Composable TooltipBoxScope.() -> Unit
+    enableUserInput: Boolean = true,
+    content: @Composable () -> Unit,
 ) {
-    val tooltipAnchorPadding = with(LocalDensity.current) { TooltipAnchorPadding.roundToPx() }
-    val positionProvider = remember { RichTooltipPositionProvider(tooltipAnchorPadding) }
-
-    TooltipBox(
-        tooltipContent = {
-            RichTooltipImpl(
-                colors = colors,
-                title = title,
-                text = text,
-                action = action
-            )
-        },
-        shape = shape,
-        containerColor = colors.containerColor,
-        tooltipPositionProvider = positionProvider,
-        tooltipState = tooltipState,
-        elevation = RichTooltipTokens.ContainerElevation,
-        maxWidth = RichTooltipMaxWidth,
-        modifier = modifier,
+    val transition = updateTransition(state.transition, label = "tooltip transition")
+    BasicTooltipBox(
+        positionProvider = positionProvider,
+        tooltip = { Box(Modifier.animateTooltip(transition)) { tooltip() } },
         focusable = focusable,
+        enableUserInput = enableUserInput,
+        state = state,
+        modifier = modifier,
         content = content
     )
 }
 
 /**
- * TODO: Figure out what should live here vs. within foundation (b/262626721)
+ * Plain tooltip that provides a descriptive message.
+ *
+ * Usually used with [TooltipBox].
+ *
+ * @param modifier the [Modifier] to be applied to the tooltip.
+ * @param contentColor [Color] that will be applied to the tooltip's content.
+ * @param containerColor [Color] that will be applied to the tooltip's container.
+ * @param shape the [Shape] that should be applied to the tooltip container.
+ * @param content the composable that will be used to populate the tooltip's content.
  */
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun TooltipBox(
-    tooltipContent: @Composable () -> Unit,
-    tooltipPositionProvider: PopupPositionProvider,
-    modifier: Modifier,
-    focusable: Boolean,
-    shape: Shape,
-    tooltipState: TooltipState,
-    containerColor: Color,
-    elevation: Dp,
-    maxWidth: Dp,
-    content: @Composable TooltipBoxScope.() -> Unit,
-) {
-    val coroutineScope = rememberCoroutineScope()
-    val longPressLabel = getString(string = Strings.TooltipLongPressLabel)
-
-    val scope = remember(tooltipState) {
-        object : TooltipBoxScope {
-            override fun Modifier.tooltipTrigger(): Modifier {
-                val onLongPress = {
-                    coroutineScope.launch {
-                        tooltipState.show()
-                    }
-                }
-                return pointerInput(tooltipState) {
-                        awaitEachGesture {
-                            val longPressTimeout = viewConfiguration.longPressTimeoutMillis
-                            val pass = PointerEventPass.Initial
-
-                            // wait for the first down press
-                            awaitFirstDown(pass = pass)
-
-                            try {
-                                // listen to if there is up gesture within the longPressTimeout limit
-                                withTimeout(longPressTimeout) {
-                                    waitForUpOrCancellation(pass = pass)
-                                }
-                            } catch (_: PointerEventTimeoutCancellationException) {
-                                // handle long press - Show the tooltip
-                                onLongPress()
-
-                                // consume the children's click handling
-                                val event = awaitPointerEvent(pass = pass)
-                                event.changes.forEach { it.consume() }
-                            }
-                        }
-                    }.semantics(mergeDescendants = true) {
-                        onLongClick(
-                            label = longPressLabel,
-                            action = {
-                                onLongPress()
-                                true
-                            }
-                        )
-                    }
-            }
-        }
-    }
-
-    Box {
-        val transition = updateTransition(tooltipState.isVisible, label = "Tooltip transition")
-        if (transition.currentState || transition.targetState) {
-            val tooltipPaneDescription = getString(Strings.TooltipPaneDescription)
-            TooltipPopup(
-                popupPositionProvider = tooltipPositionProvider,
-                onDismissRequest = {
-                    if (tooltipState.isVisible) {
-                        coroutineScope.launch { tooltipState.dismiss() }
-                    }
-                },
-                focusable = focusable
-            ) {
-                Surface(
-                    modifier = modifier
-                        .sizeIn(
-                            minWidth = TooltipMinWidth,
-                            maxWidth = maxWidth,
-                            minHeight = TooltipMinHeight
-                        )
-                        .animateTooltip(transition)
-                        .semantics {
-                            liveRegion = LiveRegionMode.Assertive
-                            paneTitle = tooltipPaneDescription
-                        },
-                    shape = shape,
-                    color = containerColor,
-                    shadowElevation = elevation,
-                    tonalElevation = elevation,
-                    content = tooltipContent
-                )
-            }
-        }
-
-        scope.content()
-    }
-
-    DisposableEffect(tooltipState) {
-        onDispose { tooltipState.onDispose() }
-    }
-}
-
-@Composable
-private fun PlainTooltipImpl(
-    textColor: Color,
+fun PlainTooltip(
+    modifier: Modifier = Modifier,
+    contentColor: Color = TooltipDefaults.plainTooltipContentColor,
+    containerColor: Color = TooltipDefaults.plainTooltipContainerColor,
+    shape: Shape = TooltipDefaults.plainTooltipContainerShape,
     content: @Composable () -> Unit
 ) {
-    Box(modifier = Modifier.padding(PlainTooltipContentPadding)) {
-        val textStyle = MaterialTheme.typography.fromToken(PlainTooltipTokens.SupportingTextFont)
-        CompositionLocalProvider(
-            LocalContentColor provides textColor,
-            LocalTextStyle provides textStyle,
-            content = content
-        )
+    Surface(
+        modifier = modifier
+            .sizeIn(
+                minWidth = TooltipMinWidth,
+                maxWidth = PlainTooltipMaxWidth,
+                minHeight = TooltipMinHeight
+            ),
+        shape = shape,
+        color = containerColor
+    ) {
+        Box(modifier = Modifier.padding(PlainTooltipContentPadding)) {
+            val textStyle =
+                MaterialTheme.typography.fromToken(PlainTooltipTokens.SupportingTextFont)
+            CompositionLocalProvider(
+                LocalContentColor provides contentColor,
+                LocalTextStyle provides textStyle,
+                content = content
+            )
+        }
     }
 }
 
+/**
+ * Rich text tooltip that allows the user to pass in a title, text, and action.
+ * Tooltips are used to provide a descriptive message.
+ *
+ * Usually used with [TooltipBox]
+ *
+ * @param modifier the [Modifier] to be applied to the tooltip.
+ * @param title An optional title for the tooltip.
+ * @param action An optional action for the tooltip.
+ * @param colors [RichTooltipColors] that will be applied to the tooltip's container and content.
+ * @param shape the [Shape] that should be applied to the tooltip container.
+ * @param text the composable that will be used to populate the rich tooltip's text.
+ */
 @OptIn(ExperimentalMaterial3Api::class)
 @Composable
-private fun RichTooltipImpl(
-    colors: RichTooltipColors,
-    text: @Composable () -> Unit,
-    title: (@Composable () -> Unit)?,
-    action: (@Composable () -> Unit)?
+fun RichTooltip(
+    modifier: Modifier = Modifier,
+    title: (@Composable () -> Unit)? = null,
+    action: (@Composable () -> Unit)? = null,
+    colors: RichTooltipColors = TooltipDefaults.richTooltipColors(),
+    shape: Shape = TooltipDefaults.richTooltipContainerShape,
+    text: @Composable () -> Unit
 ) {
-    val actionLabelTextStyle =
-        MaterialTheme.typography.fromToken(RichTooltipTokens.ActionLabelTextFont)
-    val subheadTextStyle =
-        MaterialTheme.typography.fromToken(RichTooltipTokens.SubheadFont)
-    val supportingTextStyle =
-        MaterialTheme.typography.fromToken(RichTooltipTokens.SupportingTextFont)
-    Column(
-        modifier = Modifier.padding(horizontal = RichTooltipHorizontalPadding)
+    Surface(
+        modifier = modifier
+            .sizeIn(
+                minWidth = TooltipMinWidth,
+                maxWidth = RichTooltipMaxWidth,
+                minHeight = TooltipMinHeight
+            ),
+        shape = shape,
+        color = colors.containerColor,
+        shadowElevation = RichTooltipTokens.ContainerElevation,
+        tonalElevation = RichTooltipTokens.ContainerElevation
     ) {
-        title?.let {
+        val actionLabelTextStyle =
+            MaterialTheme.typography.fromToken(RichTooltipTokens.ActionLabelTextFont)
+        val subheadTextStyle =
+            MaterialTheme.typography.fromToken(RichTooltipTokens.SubheadFont)
+        val supportingTextStyle =
+            MaterialTheme.typography.fromToken(RichTooltipTokens.SupportingTextFont)
+
+        Column(
+            modifier = Modifier.padding(horizontal = RichTooltipHorizontalPadding)
+        ) {
+            title?.let {
+                Box(
+                    modifier = Modifier.paddingFromBaseline(top = HeightToSubheadFirstLine)
+                ) {
+                    CompositionLocalProvider(
+                        LocalContentColor provides colors.titleContentColor,
+                        LocalTextStyle provides subheadTextStyle,
+                        content = it
+                    )
+                }
+            }
             Box(
-                modifier = Modifier.paddingFromBaseline(top = HeightToSubheadFirstLine)
+                modifier = Modifier.textVerticalPadding(title != null, action != null)
             ) {
                 CompositionLocalProvider(
-                    LocalContentColor provides colors.titleContentColor,
-                    LocalTextStyle provides subheadTextStyle,
-                    content = it
+                    LocalContentColor provides colors.contentColor,
+                    LocalTextStyle provides supportingTextStyle,
+                    content = text
                 )
             }
-        }
-        Box(
-            modifier = Modifier.textVerticalPadding(title != null, action != null)
-        ) {
-            CompositionLocalProvider(
-                LocalContentColor provides colors.contentColor,
-                LocalTextStyle provides supportingTextStyle,
-                content = text
-            )
-        }
-        action?.let {
-            Box(
-                modifier = Modifier
-                    .requiredHeightIn(min = ActionLabelMinHeight)
-                    .padding(bottom = ActionLabelBottomPadding)
-            ) {
-                CompositionLocalProvider(
-                    LocalContentColor provides colors.actionContentColor,
-                    LocalTextStyle provides actionLabelTextStyle,
-                    content = it
-                )
+            action?.let {
+                Box(
+                    modifier = Modifier
+                        .requiredHeightIn(min = ActionLabelMinHeight)
+                        .padding(bottom = ActionLabelBottomPadding)
+                ) {
+                    CompositionLocalProvider(
+                        LocalContentColor provides colors.actionContentColor,
+                        LocalTextStyle provides actionLabelTextStyle,
+                        content = it
+                    )
+                }
             }
         }
     }
 }
 
 /**
- * Tooltip defaults that contain default values for both [PlainTooltipBox] and [RichTooltipBox]
+ * Tooltip defaults that contain default values for both [PlainTooltip] and [RichTooltip]
  */
 @ExperimentalMaterial3Api
 object TooltipDefaults {
     /**
-     * The global/default [MutatorMutex] used to sync Tooltips.
-     */
-    val GlobalMutatorMutex = MutatorMutex()
-
-    /**
-     * The default [Shape] for a [PlainTooltipBox]'s container.
+     * The default [Shape] for a [PlainTooltip]'s container.
      */
     val plainTooltipContainerShape: Shape
         @Composable get() = PlainTooltipTokens.ContainerShape.value
 
     /**
-     * The default [Color] for a [PlainTooltipBox]'s container.
+     * The default [Color] for a [PlainTooltip]'s container.
      */
     val plainTooltipContainerColor: Color
         @Composable get() = PlainTooltipTokens.ContainerColor.value
 
     /**
-     * The default [Color] for the content within the [PlainTooltipBox].
+     * The default [Color] for the content within the [PlainTooltip].
      */
     val plainTooltipContentColor: Color
         @Composable get() = PlainTooltipTokens.SupportingTextColor.value
 
     /**
-     * The default [Shape] for a [RichTooltipBox]'s container.
+     * The default [Shape] for a [RichTooltip]'s container.
      */
     val richTooltipContainerShape: Shape @Composable get() =
         RichTooltipTokens.ContainerShape.value
 
     /**
-     * Method to create a [RichTooltipColors] for [RichTooltipBox]
+     * Method to create a [RichTooltipColors] for [RichTooltip]
      * using [RichTooltipTokens] to obtain the default colors.
      */
     @Composable
@@ -420,6 +291,85 @@
             titleContentColor = titleContentColor,
             actionContentColor = actionContentColor
         )
+
+    /**
+     * [PopupPositionProvider] that should be used with [PlainTooltip].
+     * It correctly positions the tooltip in respect to the anchor content.
+     *
+     * @param spacingBetweenTooltipAndAnchor the spacing between the tooltip and the anchor content.
+     */
+    @Composable
+    fun rememberPlainTooltipPositionProvider(
+        spacingBetweenTooltipAndAnchor: Dp = SpacingBetweenTooltipAndAnchor
+    ): PopupPositionProvider {
+        val tooltipAnchorSpacing = with(LocalDensity.current) {
+            spacingBetweenTooltipAndAnchor.roundToPx()
+        }
+        return remember(tooltipAnchorSpacing) {
+            object : PopupPositionProvider {
+                override fun calculatePosition(
+                    anchorBounds: IntRect,
+                    windowSize: IntSize,
+                    layoutDirection: LayoutDirection,
+                    popupContentSize: IntSize
+                ): IntOffset {
+                    val x = anchorBounds.left + (anchorBounds.width - popupContentSize.width) / 2
+
+                    // Tooltip prefers to be above the anchor,
+                    // but if this causes the tooltip to overlap with the anchor
+                    // then we place it below the anchor
+                    var y = anchorBounds.top - popupContentSize.height - tooltipAnchorSpacing
+                    if (y < 0)
+                        y = anchorBounds.bottom + tooltipAnchorSpacing
+                    return IntOffset(x, y)
+                }
+            }
+        }
+    }
+
+    /**
+     * [PopupPositionProvider] that should be used with [RichTooltip].
+     * It correctly positions the tooltip in respect to the anchor content.
+     *
+     * @param spacingBetweenTooltipAndAnchor the spacing between the tooltip and the anchor content.
+     */
+    @Composable
+    fun rememberRichTooltipPositionProvider(
+        spacingBetweenTooltipAndAnchor: Dp = SpacingBetweenTooltipAndAnchor
+    ): PopupPositionProvider {
+        val tooltipAnchorSpacing = with(LocalDensity.current) {
+            spacingBetweenTooltipAndAnchor.roundToPx()
+        }
+        return remember(tooltipAnchorSpacing) {
+            object : PopupPositionProvider {
+                override fun calculatePosition(
+                    anchorBounds: IntRect,
+                    windowSize: IntSize,
+                    layoutDirection: LayoutDirection,
+                    popupContentSize: IntSize
+                ): IntOffset {
+                    var x = anchorBounds.right
+                    // Try to shift it to the left of the anchor
+                    // if the tooltip would collide with the right side of the screen
+                    if (x + popupContentSize.width > windowSize.width) {
+                        x = anchorBounds.left - popupContentSize.width
+                        // Center if it'll also collide with the left side of the screen
+                        if (x < 0)
+                            x = anchorBounds.left +
+                                (anchorBounds.width - popupContentSize.width) / 2
+                    }
+
+                    // Tooltip prefers to be above the anchor,
+                    // but if this causes the tooltip to overlap with the anchor
+                    // then we place it below the anchor
+                    var y = anchorBounds.top - popupContentSize.height - tooltipAnchorSpacing
+                    if (y < 0)
+                        y = anchorBounds.bottom + tooltipAnchorSpacing
+                    return IntOffset(x, y)
+                }
+            }
+        }
+    }
 }
 
 @Stable
@@ -453,286 +403,166 @@
 }
 
 /**
- * Scope of [PlainTooltipBox] and RichTooltipBox
- */
-@ExperimentalMaterial3Api
-interface TooltipBoxScope {
-    /**
-     * [Modifier] that should be applied to the anchor composable when showing the tooltip
-     * after long pressing the anchor composable is desired. It appends a long click to
-     * the composable that this modifier is chained with.
-     */
-    fun Modifier.tooltipTrigger(): Modifier
-}
-
-/**
- * Create and remember the default [PlainTooltipState].
+ * Create and remember the default [TooltipState] for [TooltipBox].
  *
+ * @param initialIsVisible the initial value for the tooltip's visibility when drawn.
+ * @param isPersistent [Boolean] that determines if the tooltip associated with this
+ * will be persistent or not. If isPersistent is true, then the tooltip will
+ * only be dismissed when the user clicks outside the bounds of the tooltip or if
+ * [TooltipState.dismiss] is called. When isPersistent is false, the tooltip will dismiss after
+ * a short duration. Ideally, this should be set to true when there is actionable content
+ * being displayed within a tooltip.
  * @param mutatorMutex [MutatorMutex] used to ensure that for all of the tooltips associated
  * with the mutator mutex, only one will be shown on the screen at any time.
+ *
  */
 @Composable
 @ExperimentalMaterial3Api
-fun rememberPlainTooltipState(
-    mutatorMutex: MutatorMutex = TooltipDefaults.GlobalMutatorMutex
-): PlainTooltipState =
-    remember { PlainTooltipStateImpl(mutatorMutex) }
-
-/**
- * Create and remember the default [RichTooltipState].
- *
- * @param isPersistent [Boolean] that determines if the tooltip associated with this
- * [RichTooltipState] will be persistent or not. If isPersistent is true, then the tooltip will
- * only be dismissed when the user clicks outside the bounds of the tooltip or if
- * [TooltipState.dismiss] is called. When isPersistent is false, the tooltip will dismiss after
- * a short duration. Ideally, this should be set to true when an action is provided to the
- * [RichTooltipBox] that this [RichTooltipState] is associated with.
- * @param mutatorMutex [MutatorMutex] used to ensure that for all of the tooltips associated
- * with the mutator mutex, only one will be shown on the screen at any time.
- */
-@Composable
-@ExperimentalMaterial3Api
-fun rememberRichTooltipState(
-    isPersistent: Boolean,
-    mutatorMutex: MutatorMutex = TooltipDefaults.GlobalMutatorMutex
-): RichTooltipState =
-    remember { RichTooltipStateImpl(isPersistent, mutatorMutex) }
-
-/**
- * The [TooltipState] that should be used with [RichTooltipBox]
- */
-@Stable
-@ExperimentalMaterial3Api
-interface PlainTooltipState : TooltipState
-
-/**
- * The [TooltipState] that should be used with [RichTooltipBox]
- */
-@Stable
-@ExperimentalMaterial3Api
-interface RichTooltipState : TooltipState {
-    val isPersistent: Boolean
+fun rememberTooltipState(
+    initialIsVisible: Boolean = false,
+    isPersistent: Boolean = false,
+    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
+): TooltipState {
+    return rememberSaveable(
+        isPersistent,
+        mutatorMutex,
+        saver = TooltipStateImpl.Saver
+    ) {
+        TooltipStateImpl(
+            initialIsVisible = initialIsVisible,
+            isPersistent = isPersistent,
+            mutatorMutex = mutatorMutex
+        )
+    }
 }
 
 /**
- * The default implementation for [RichTooltipState]
+ * Constructor extension function for [TooltipState]
  *
+ * @param initialIsVisible the initial value for the tooltip's visibility when drawn.
  * @param isPersistent [Boolean] that determines if the tooltip associated with this
- * [RichTooltipState] will be persistent or not. If isPersistent is true, then the tooltip will
+ * will be persistent or not. If isPersistent is true, then the tooltip will
  * only be dismissed when the user clicks outside the bounds of the tooltip or if
  * [TooltipState.dismiss] is called. When isPersistent is false, the tooltip will dismiss after
- * a short duration. Ideally, this should be set to true when an action is provided to the
- * [RichTooltipBox] that this [RichTooltipState] is associated with.
+ * a short duration. Ideally, this should be set to true when there is actionable content
+ * being displayed within a tooltip.
  * @param mutatorMutex [MutatorMutex] used to ensure that for all of the tooltips associated
  * with the mutator mutex, only one will be shown on the screen at any time.
  */
-@OptIn(ExperimentalMaterial3Api::class)
+fun TooltipState(
+    initialIsVisible: Boolean = false,
+    isPersistent: Boolean = true,
+    mutatorMutex: MutatorMutex = BasicTooltipDefaults.GlobalMutatorMutex
+): TooltipState =
+    TooltipStateImpl(
+        initialIsVisible = initialIsVisible,
+        isPersistent = isPersistent,
+        mutatorMutex = mutatorMutex
+    )
+
 @Stable
-internal class RichTooltipStateImpl(
+private class TooltipStateImpl(
+    initialIsVisible: Boolean,
     override val isPersistent: Boolean,
     private val mutatorMutex: MutatorMutex
-) : RichTooltipState {
+) : TooltipState {
+    override val transition: MutableTransitionState<Boolean> =
+        MutableTransitionState(initialIsVisible)
 
-    /**
-     * [Boolean] that will be used to update the visibility
-     * state of the associated tooltip.
-     */
-    override var isVisible: Boolean by mutableStateOf(false)
-        private set
+    override val isVisible: Boolean
+        get() = transition.currentState || transition.targetState
 
-    /**
+            /**
      * continuation used to clean up
      */
     private var job: (CancellableContinuation<Unit>)? = null
 
     /**
-     * Show the tooltip associated with the current [RichTooltipState].
-     * It will persist or dismiss after a short duration depending on [isPersistent].
-     * When this method is called, all of the other tooltips currently
-     * being shown will dismiss.
+     * Show the tooltip associated with the current [BasicTooltipState].
+     * When this method is called, all of the other tooltips associated
+     * with [mutatorMutex] will be dismissed.
+     *
+     * @param mutatePriority [MutatePriority] to be used with [mutatorMutex].
      */
-    override suspend fun show() {
+    override suspend fun show(
+        mutatePriority: MutatePriority
+    ) {
         val cancellableShow: suspend () -> Unit = {
             suspendCancellableCoroutine { continuation ->
-                isVisible = true
+                transition.targetState = true
                 job = continuation
             }
         }
 
         // Show associated tooltip for [TooltipDuration] amount of time
         // or until tooltip is explicitly dismissed depending on [isPersistent].
-        mutatorMutex.mutate(MutatePriority.Default) {
+        mutatorMutex.mutate(mutatePriority) {
             try {
                 if (isPersistent) {
                     cancellableShow()
                 } else {
-                    withTimeout(TooltipDuration) {
+                    withTimeout(BasicTooltipDefaults.TooltipDuration) {
                         cancellableShow()
                     }
                 }
             } finally {
                 // timeout or cancellation has occurred
                 // and we close out the current tooltip.
-                isVisible = false
+                dismiss()
             }
         }
     }
 
     /**
      * Dismiss the tooltip associated with
-     * this [RichTooltipState] if it's currently being shown.
-     */
-    override fun dismiss() {
-        isVisible = false
-    }
-
-    /**
-     * Cleans up [MutatorMutex] when the tooltip associated
-     * with this state leaves Composition.
-     */
-    override fun onDispose() {
-        job?.cancel()
-    }
-}
-
-/**
- * The default implementation for [PlainTooltipState]
- */
-@OptIn(ExperimentalMaterial3Api::class)
-@Stable
-internal class PlainTooltipStateImpl(private val mutatorMutex: MutatorMutex) : PlainTooltipState {
-
-    /**
-     * [Boolean] that will be used to update the visibility
-     * state of the associated tooltip.
-     */
-    override var isVisible by mutableStateOf(false)
-        private set
-
-    /**
-     * continuation used to clean up
-     */
-    private var job: (CancellableContinuation<Unit>)? = null
-
-    /**
-     * Show the tooltip associated with the current [PlainTooltipState].
-     * It will dismiss after a short duration. When this method is called,
-     * all of the other tooltips currently being shown will dismiss.
-     */
-    override suspend fun show() {
-        // Show associated tooltip for [TooltipDuration] amount of time.
-        mutatorMutex.mutate {
-            try {
-                withTimeout(TooltipDuration) {
-                    suspendCancellableCoroutine { continuation ->
-                        isVisible = true
-                        job = continuation
-                    }
-                }
-            } finally {
-                // timeout or cancellation has occurred
-                // and we close out the current tooltip.
-                isVisible = false
-            }
-        }
-    }
-
-    /**
-     * Dismiss the tooltip associated with
-     * this [PlainTooltipState] if it's currently being shown.
-     */
-    override fun dismiss() {
-        isVisible = false
-    }
-
-    /**
-     * Cleans up [MutatorMutex] when the tooltip associated
-     * with this state leaves Composition.
-     */
-    override fun onDispose() {
-        job?.cancel()
-    }
-}
-
-/**
- * The state that is associated with an instance of a tooltip.
- * Each instance of tooltips should have its own [TooltipState].
- */
-@Stable
-@ExperimentalMaterial3Api
-interface TooltipState {
-    /**
-     * [Boolean] that will be used to update the visibility
-     * state of the associated tooltip.
-     */
-    val isVisible: Boolean
-
-    /**
-     * Show the tooltip associated with the current [TooltipState].
-     * When this method is called all of the other tooltips currently
-     * being shown will dismiss.
-     */
-    suspend fun show()
-
-    /**
-     * Dismiss the tooltip associated with
      * this [TooltipState] if it's currently being shown.
      */
-    fun dismiss()
+    override fun dismiss() {
+        transition.targetState = false
+    }
 
     /**
-     * Clean up when the this state leaves Composition.
+     * Cleans up [mutatorMutex] when the tooltip associated
+     * with this state leaves Composition.
      */
-    fun onDispose()
-}
+    override fun onDispose() {
+        job?.cancel()
+    }
 
-private class PlainTooltipPositionProvider(
-    val tooltipAnchorPadding: Int
-) : PopupPositionProvider {
-    override fun calculatePosition(
-        anchorBounds: IntRect,
-        windowSize: IntSize,
-        layoutDirection: LayoutDirection,
-        popupContentSize: IntSize
-    ): IntOffset {
-        val x = anchorBounds.left + (anchorBounds.width - popupContentSize.width) / 2
-
-        // Tooltip prefers to be above the anchor,
-        // but if this causes the tooltip to overlap with the anchor
-        // then we place it below the anchor
-        var y = anchorBounds.top - popupContentSize.height - tooltipAnchorPadding
-        if (y < 0)
-            y = anchorBounds.bottom + tooltipAnchorPadding
-        return IntOffset(x, y)
+    companion object {
+        /**
+         * The default [Saver] implementation for [TooltipStateImpl].
+         */
+        val Saver = Saver<TooltipStateImpl, Any>(
+            save = {
+                listOf(
+                    it.isVisible,
+                    it.isPersistent,
+                    it.mutatorMutex
+                )
+            },
+            restore = {
+                val (isVisible, isPersistent, mutatorMutex) = it as List<*>
+                TooltipStateImpl(
+                    initialIsVisible = isVisible as Boolean,
+                    isPersistent = isPersistent as Boolean,
+                    mutatorMutex = mutatorMutex as MutatorMutex,
+                )
+            }
+        )
     }
 }
 
-private data class RichTooltipPositionProvider(
-    val tooltipAnchorPadding: Int
-) : PopupPositionProvider {
-    override fun calculatePosition(
-        anchorBounds: IntRect,
-        windowSize: IntSize,
-        layoutDirection: LayoutDirection,
-        popupContentSize: IntSize
-    ): IntOffset {
-        var x = anchorBounds.right
-        // Try to shift it to the left of the anchor
-        // if the tooltip would collide with the right side of the screen
-        if (x + popupContentSize.width > windowSize.width) {
-            x = anchorBounds.left - popupContentSize.width
-            // Center if it'll also collide with the left side of the screen
-            if (x < 0) x = anchorBounds.left + (anchorBounds.width - popupContentSize.width) / 2
-        }
-
-        // Tooltip prefers to be above the anchor,
-        // but if this causes the tooltip to overlap with the anchor
-        // then we place it below the anchor
-        var y = anchorBounds.top - popupContentSize.height - tooltipAnchorPadding
-        if (y < 0)
-            y = anchorBounds.bottom + tooltipAnchorPadding
-        return IntOffset(x, y)
-    }
+/**
+ * The state that is associated with a [TooltipBox].
+ * Each instance of [TooltipBox] should have its own [TooltipState].
+ */
+interface TooltipState : BasicTooltipState {
+    /**
+     * The current transition state of the tooltip.
+     * Used to start the transition of the tooltip when fading in and out.
+     */
+    val transition: MutableTransitionState<Boolean>
 }
 
 private fun Modifier.textVerticalPadding(
@@ -801,16 +631,7 @@
     )
 }
 
-@Composable
-@ExperimentalMaterial3Api
-internal expect fun TooltipPopup(
-    popupPositionProvider: PopupPositionProvider,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean,
-    content: @Composable () -> Unit
-)
-
-private val TooltipAnchorPadding = 4.dp
+private val SpacingBetweenTooltipAndAnchor = 4.dp
 internal val TooltipMinHeight = 24.dp
 internal val TooltipMinWidth = 40.dp
 private val PlainTooltipMaxWidth = 200.dp
@@ -825,7 +646,6 @@
 private val TextBottomPadding = 16.dp
 private val ActionLabelMinHeight = 36.dp
 private val ActionLabelBottomPadding = 8.dp
-internal const val TooltipDuration = 1500L
 // No specification for fade in and fade out duration, so aligning it with the behavior for snack bar
 internal const val TooltipFadeInDuration = 150
-private const val TooltipFadeOutDuration = 75
+internal const val TooltipFadeOutDuration = 75
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt
index 59e7756..85374bc 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/CalendarModel.desktop.kt
@@ -29,12 +29,14 @@
  * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
  * @param skeleton a date format skeleton
  * @param locale the [CalendarLocale] to use when formatting the given timestamp
+ * @param cache a [MutableMap] for caching formatter related results for better performance
  */
 @ExperimentalMaterial3Api
 actual fun formatWithSkeleton(
     utcTimeMillis: Long,
     skeleton: String,
-    locale: CalendarLocale
+    locale: CalendarLocale,
+    cache: MutableMap<String, Any>
 ): String {
     // Note: there is no equivalent in Java for Android's DateFormat.getBestDateTimePattern.
     // The JDK SimpleDateFormat expects a pattern, so the results will be "2023Jan7",
@@ -42,6 +44,7 @@
     return LegacyCalendarModelImpl.formatWithPattern(
         utcTimeMillis = utcTimeMillis,
         pattern = skeleton,
-        locale = locale
+        locale = locale,
+        cache = cache
     )
 }
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TooltipPopup.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TooltipPopup.desktop.kt
deleted file mode 100644
index cd83c7c..0000000
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TooltipPopup.desktop.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2023 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.material3
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.window.Popup
-import androidx.compose.ui.window.PopupPositionProvider
-
-@Composable
-@ExperimentalMaterial3Api
-internal actual fun TooltipPopup(
-    popupPositionProvider: PopupPositionProvider,
-    onDismissRequest: () -> Unit,
-    focusable: Boolean,
-    content: @Composable () -> Unit
-) = Popup(
-    popupPositionProvider = popupPositionProvider,
-    onDismissRequest = onDismissRequest,
-    content = content
-)
diff --git a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.desktop.kt b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.desktop.kt
index 6010c98..1c765e3 100644
--- a/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.desktop.kt
+++ b/compose/material3/material3/src/desktopMain/kotlin/androidx/compose/material3/TouchExplorationStateProvider.desktop.kt
@@ -18,7 +18,7 @@
 
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 
 /**
@@ -27,5 +27,5 @@
  */
 @Composable
 internal actual fun touchExplorationState(): State<Boolean> {
-    return remember { derivedStateOf { false } }
+    return remember { mutableStateOf(false) }
 }
diff --git a/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/ActualJvm.jvm.kt b/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/ActualJvm.jvm.kt
index 8cc86e9..6157a20d 100644
--- a/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/ActualJvm.jvm.kt
+++ b/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/ActualJvm.jvm.kt
@@ -19,6 +19,8 @@
 package androidx.compose.material3
 
 import java.text.NumberFormat
+import java.util.Locale
+import java.util.WeakHashMap
 
 /* Copy of androidx.compose.material.ActualJvm, mirrored from Foundation. This is used for the
    M2/M3-internal copy of MutatorMutex.
@@ -30,7 +32,7 @@
  * Represents a Locale for the calendar. This locale will be used when formatting dates, determining
  * the input format, and more.
  */
-actual typealias CalendarLocale = java.util.Locale
+actual typealias CalendarLocale = Locale
 
 /**
  * Returns a string representation of an integer for the current Locale.
@@ -40,9 +42,27 @@
     maxDigits: Int,
     isGroupingUsed: Boolean
 ): String {
-    val formatter = NumberFormat.getIntegerInstance()
-    formatter.isGroupingUsed = isGroupingUsed
-    formatter.minimumIntegerDigits = minDigits
-    formatter.maximumIntegerDigits = maxDigits
-    return formatter.format(this)
+    return getCachedDateTimeFormatter(
+        minDigits = minDigits,
+        maxDigits = maxDigits,
+        isGroupingUsed = isGroupingUsed
+    ).format(this)
+}
+
+private val cachedFormatters = WeakHashMap<String, NumberFormat>()
+private fun getCachedDateTimeFormatter(
+    minDigits: Int,
+    maxDigits: Int,
+    isGroupingUsed: Boolean
+): NumberFormat {
+    // Note: Using Locale.getDefault() as a best effort to obtain a unique key and keeping this
+    // function non-composable.
+    val key = "$minDigits.$maxDigits.$isGroupingUsed.${Locale.getDefault().toLanguageTag()}"
+    return cachedFormatters.getOrPut(key) {
+        NumberFormat.getIntegerInstance().apply {
+            this.isGroupingUsed = isGroupingUsed
+            this.minimumIntegerDigits = minDigits
+            this.maximumIntegerDigits = maxDigits
+        }
+    }
 }
diff --git a/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/LegacyCalendarModelImpl.kt b/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/LegacyCalendarModelImpl.kt
index 20a2b58..1220153 100644
--- a/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/LegacyCalendarModelImpl.kt
+++ b/compose/material3/material3/src/jvmMain/kotlin/androidx/compose/material3/LegacyCalendarModelImpl.kt
@@ -135,8 +135,7 @@
         utcTimeMillis: Long,
         pattern: String,
         locale: CalendarLocale
-    ): String =
-        LegacyCalendarModelImpl.formatWithPattern(utcTimeMillis, pattern, locale)
+    ): String = formatWithPattern(utcTimeMillis, pattern, locale, formatterCache)
 
     override fun parse(date: String, pattern: String): CalendarDate? {
         val dateFormat = SimpleDateFormat(pattern)
@@ -169,14 +168,15 @@
          * @param utcTimeMillis a UTC timestamp to format (milliseconds from epoch)
          * @param pattern a date format pattern
          * @param locale the [CalendarLocale] to use when formatting the given timestamp
+         * @param cache a [MutableMap] for caching formatter related results for better performance
          */
         fun formatWithPattern(
             utcTimeMillis: Long,
             pattern: String,
-            locale: CalendarLocale
+            locale: CalendarLocale,
+            cache: MutableMap<String, Any>
         ): String {
-            val dateFormat = SimpleDateFormat(pattern, locale)
-            dateFormat.timeZone = utcTimeZone
+            val dateFormat = getCachedSimpleDateFormat(pattern, locale, cache)
             val calendar = Calendar.getInstance(utcTimeZone)
             calendar.timeInMillis = utcTimeMillis
             return dateFormat.format(calendar.timeInMillis)
@@ -186,6 +186,18 @@
          * Holds a UTC [TimeZone].
          */
         internal val utcTimeZone: TimeZone = TimeZone.getTimeZone("UTC")
+
+        private fun getCachedSimpleDateFormat(
+            pattern: String,
+            locale: CalendarLocale,
+            cache: MutableMap<String, Any>
+        ): SimpleDateFormat {
+            return cache.getOrPut(pattern + locale.toLanguageTag()) {
+                val dateFormat = SimpleDateFormat(pattern, locale)
+                dateFormat.timeZone = utcTimeZone
+                dateFormat
+            } as SimpleDateFormat
+        }
     }
 
     /**
diff --git a/compose/runtime/runtime-saveable/build.gradle b/compose/runtime/runtime-saveable/build.gradle
index c219a78..7f1d7ff 100644
--- a/compose/runtime/runtime-saveable/build.gradle
+++ b/compose/runtime/runtime-saveable/build.gradle
@@ -79,7 +79,7 @@
                 implementation project(":compose:ui:ui-test-junit4")
                 implementation project(":compose:test-utils")
                 implementation "androidx.fragment:fragment:1.3.0"
-                implementation "androidx.activity:activity-compose:1.3.1"
+                implementation "androidx.activity:activity-compose:1.7.0"
                 implementation(libs.testUiautomator)
                 implementation(libs.testCore)
                 implementation(libs.testRules)
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 59b2edf..9dfa745 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -686,6 +686,7 @@
     method public boolean removeAll(java.util.Collection<? extends T> elements);
     method public boolean removeAll(java.util.List<? extends T> elements);
     method public T removeAt(int index);
+    method public inline void removeIf(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public void removeRange(int start, int end);
     method public boolean retainAll(java.util.Collection<? extends T> elements);
     method public inline boolean reversedAny(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index 7a42d00..7e80ac0 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -723,10 +723,12 @@
     method public boolean removeAll(java.util.Collection<? extends T> elements);
     method public boolean removeAll(java.util.List<? extends T> elements);
     method public T removeAt(int index);
+    method public inline void removeIf(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public void removeRange(int start, int end);
     method public boolean retainAll(java.util.Collection<? extends T> elements);
     method public inline boolean reversedAny(kotlin.jvm.functions.Function1<? super T,java.lang.Boolean> predicate);
     method public operator T set(int index, T element);
+    method @kotlin.PublishedApi internal void setSize(int newSize);
     method public void sortWith(java.util.Comparator<T> comparator);
     method public inline int sumBy(kotlin.jvm.functions.Function1<? super T,java.lang.Integer> selector);
     method @kotlin.PublishedApi internal Void throwNoSuchElementException();
diff --git a/compose/runtime/runtime/compose-runtime-benchmark/build.gradle b/compose/runtime/runtime/compose-runtime-benchmark/build.gradle
index 915a021..e350948 100644
--- a/compose/runtime/runtime/compose-runtime-benchmark/build.gradle
+++ b/compose/runtime/runtime/compose-runtime-benchmark/build.gradle
@@ -36,6 +36,7 @@
     androidTestImplementation(projectOrArtifact(":compose:foundation:foundation-layout"))
     androidTestImplementation(projectOrArtifact(":compose:material:material"))
     androidTestImplementation(projectOrArtifact(":compose:runtime:runtime"))
+    androidTestImplementation(projectOrArtifact(":compose:runtime:runtime-saveable"))
     androidTestImplementation(projectOrArtifact(":compose:ui:ui-text"))
     androidTestImplementation(projectOrArtifact(":compose:ui:ui-util"))
     androidTestImplementation(projectOrArtifact(":compose:test-utils"))
diff --git a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmark.kt b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmark.kt
index 147cc7b..187bc8c 100644
--- a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmark.kt
+++ b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmark.kt
@@ -226,6 +226,30 @@
             }
         }
     }
+
+    @UiThreadTest
+    @Test
+    fun benchmark_f_compose_Rect_1() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            Rect()
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun benchmark_f_compose_Rect_10() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(10) { Rect() }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun benchmark_f_compose_Rect_100() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(100) { Rect() }
+        }
+    }
 }
 
 class ColorModel(color: Color = Color.Black) {
diff --git a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmarkBase.kt b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmarkBase.kt
index 219446f..7334416 100644
--- a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmarkBase.kt
+++ b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/ComposeBenchmarkBase.kt
@@ -21,6 +21,7 @@
 import androidx.benchmark.ExperimentalBenchmarkConfigApi
 import androidx.benchmark.MetricCapture
 import androidx.benchmark.MicrobenchmarkConfig
+import androidx.benchmark.ProfilerConfig
 import androidx.benchmark.TimeCapture
 import androidx.benchmark.junit4.BenchmarkRule
 import androidx.compose.runtime.Composable
@@ -73,6 +74,7 @@
 @Composable
 private fun CountGroupsAndSlots(content: @Composable () -> Unit) {
     val data = currentComposer.compositionData
+    currentComposer.disableSourceInformation()
     CompositionLocalProvider(LocalInspectionTables provides compositionTables, content = content)
     SideEffect {
         compositionTables?.let {
@@ -110,6 +112,7 @@
                     }
                 }
             ),
+            profiler = ProfilerConfig.MethodTracing(),
         )
     )
 
@@ -137,7 +140,41 @@
                 runWithTimingDisabled {
                     activity.setContentView(emptyView)
                     testScheduler.advanceUntilIdle()
-                    Runtime.getRuntime().gc()
+                }
+            }
+        } finally {
+            activity.setContentView(emptyView)
+            testScheduler.advanceUntilIdle()
+            recomposer.cancel()
+        }
+    }
+
+    @ExperimentalCoroutinesApi
+    @ExperimentalTestApi
+    suspend fun TestScope.measureComposeFocused(block: @Composable () -> Unit) = coroutineScope {
+        val activity = activityRule.activity
+        val recomposer = Recomposer(coroutineContext)
+        val emptyView = View(activity)
+
+        try {
+            benchmarkRule.measureRepeatedSuspendable {
+                val benchmarkState = benchmarkRule.getState()
+                benchmarkState.pauseTiming()
+
+                activity.setContent(recomposer) {
+                    CountGroupsAndSlots {
+                        trace("Benchmark focus") {
+                            benchmarkState.resumeTiming()
+                            block()
+                            benchmarkState.pauseTiming()
+                        }
+                    }
+                }
+                benchmarkState.resumeTiming()
+
+                runWithTimingDisabled {
+                    activity.setContentView(emptyView)
+                    testScheduler.advanceUntilIdle()
                 }
             }
         } finally {
@@ -245,3 +282,12 @@
         updateModelCb = block
     }
 }
+
+private inline fun trace(name: String, block: () -> Unit) {
+    android.os.Trace.beginSection(name)
+    try {
+        block()
+    } finally {
+        android.os.Trace.endSection()
+    }
+}
diff --git a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/RememberSavableBenchmark.kt b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/RememberSavableBenchmark.kt
new file mode 100644
index 0000000..73bf219
--- /dev/null
+++ b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/RememberSavableBenchmark.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2023 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.runtime.benchmark
+
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.saveable.autoSaver
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.test.annotation.UiThreadTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class, ExperimentalTestApi::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RememberSaveableBenchmark : ComposeBenchmarkBase() {
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_1() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            @Suppress("UNUSED_VARIABLE")
+            val i: Int = rememberSaveable {
+                10
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_10() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(10) {
+                @Suppress("UNUSED_VARIABLE")
+                val i: Int = rememberSaveable {
+                    10
+                }
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_100() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(100) {
+                @Suppress("UNUSED_VARIABLE")
+                val i: Int = rememberSaveable {
+                    10
+                }
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_mutable_1() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            @Suppress("UNUSED_VARIABLE")
+            val i = rememberSaveable(stateSaver = autoSaver()) {
+                mutableStateOf(10)
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_mutable_10() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(10) {
+                @Suppress("UNUSED_VARIABLE")
+                val i = rememberSaveable(stateSaver = autoSaver()) {
+                    mutableStateOf(10)
+                }
+            }
+        }
+    }
+
+    @UiThreadTest
+    @Test
+    fun rememberSaveable_mutable_100() = runBlockingTestWithFrameClock {
+        measureComposeFocused {
+            repeat(100) {
+                @Suppress("UNUSED_VARIABLE")
+                val i = rememberSaveable(stateSaver = autoSaver()) {
+                    mutableStateOf(10)
+                }
+            }
+        }
+    }
+}
diff --git a/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/state/ComposeStateReadBenchmark.kt b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/state/ComposeStateReadBenchmark.kt
new file mode 100644
index 0000000..44a1a9f
--- /dev/null
+++ b/compose/runtime/runtime/compose-runtime-benchmark/src/androidTest/java/androidx/compose/runtime/benchmark/state/ComposeStateReadBenchmark.kt
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2023 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.runtime.benchmark.state
+
+import androidx.benchmark.junit4.BenchmarkRule
+import androidx.benchmark.junit4.measureRepeated
+import androidx.compose.runtime.Applier
+import androidx.compose.runtime.Composition
+import androidx.compose.runtime.Recomposer
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.snapshots.SnapshotStateObserver
+import androidx.test.filters.LargeTest
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.EmptyCoroutineContext
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class ComposeStateReadBenchmark(private val readContext: ReadContext) {
+    enum class ReadContext {
+        Composition,
+        Measure;
+    }
+
+    companion object {
+        private const val MEASURE_OBSERVATION_DEPTH = 5
+        private val OnCommitInvalidatingMeasure: (Any) -> Unit = {}
+
+        @Parameterized.Parameters(name = "{0}")
+        @JvmStatic
+        fun parameters() = arrayOf(ReadContext.Composition, ReadContext.Measure)
+    }
+
+    @get:Rule
+    val benchmarkRule = BenchmarkRule()
+
+    @Test
+    fun readState() {
+        val state = mutableIntStateOf(0)
+
+        benchmarkRead {
+            state.value
+        }
+    }
+
+    @Test
+    fun readDerivedState() {
+        val stateA = mutableIntStateOf(0)
+        val stateB = mutableIntStateOf(0)
+        val derivedState = derivedStateOf { stateA.value + stateB.value }
+
+        derivedState.value // precompute result
+
+        benchmarkRead {
+            derivedState.value
+        }
+    }
+
+    @Test
+    fun readDerivedState_secondRead() {
+        val stateA = mutableIntStateOf(0)
+        val stateB = mutableIntStateOf(0)
+        val derivedState = derivedStateOf { stateA.value + stateB.value }
+
+        derivedState.value // precompute result
+
+        benchmarkRead(before = { derivedState.value }) {
+            derivedState.value
+        }
+    }
+
+    @Test
+    fun readDerivedState_afterWrite() {
+        val stateA = mutableIntStateOf(0)
+        val stateB = mutableIntStateOf(0)
+        val derivedState = derivedStateOf { stateA.value + stateB.value }
+
+        derivedState.value // precompute result
+
+        benchmarkRead(before = { stateA.value += 1 }) {
+            derivedState.value
+        }
+    }
+
+    @Test
+    fun readState_afterWrite() {
+        val stateA = mutableIntStateOf(0)
+
+        benchmarkRead(before = { stateA.value += 1 }) {
+            stateA.value
+        }
+    }
+
+    @Test
+    fun readState_preinitialized() {
+        val stateA = mutableIntStateOf(0)
+        val stateB = mutableIntStateOf(0)
+
+        benchmarkRead(before = { stateA.value }) {
+            stateB.value
+        }
+    }
+
+    @Test
+    fun readDerivedState_preinitialized() {
+        val stateA = mutableIntStateOf(0)
+        val stateB = mutableIntStateOf(0)
+
+        val derivedStateA = derivedStateOf { stateA.value + stateB.value }
+        val derivedStateB = derivedStateOf { stateB.value + stateA.value }
+
+        benchmarkRead(before = { derivedStateA.value }) {
+            derivedStateB.value
+        }
+    }
+
+    private fun benchmarkRead(
+        before: () -> Unit = {},
+        after: () -> Unit = {},
+        measure: () -> Unit
+    ) {
+        val benchmarkState = benchmarkRule.getState()
+        benchmarkRule.measureRepeated {
+            benchmarkState.pauseTiming()
+            runInReadObservationScope {
+                before()
+                benchmarkState.resumeTiming()
+
+                measure()
+
+                benchmarkState.pauseTiming()
+                after()
+            }
+            benchmarkRule.getState().resumeTiming()
+        }
+    }
+
+    private fun runInReadObservationScope(scopeBlock: () -> Unit) {
+        when (readContext) {
+            ReadContext.Composition -> createComposition().setContent { scopeBlock() }
+            ReadContext.Measure -> {
+                SnapshotStateObserver { it() }.apply {
+                    val nodes = List(MEASURE_OBSERVATION_DEPTH) { Any() }
+                    start()
+                    recursiveObserve(nodes, nodes.size, scopeBlock)
+                    stop()
+                }
+            }
+        }
+    }
+
+    private fun SnapshotStateObserver.recursiveObserve(
+        nodes: List<Any>,
+        depth: Int,
+        block: () -> Unit
+    ) {
+        if (depth == 0) {
+            block()
+            return
+        }
+        observeReads(nodes[depth - 1], OnCommitInvalidatingMeasure) {
+            recursiveObserve(nodes, depth - 1, block)
+        }
+    }
+
+    private fun createComposition(
+        coroutineContext: CoroutineContext = EmptyCoroutineContext
+    ): Composition {
+        val applier = UnitApplier()
+        val recomposer = Recomposer(coroutineContext)
+        return Composition(applier, recomposer)
+    }
+
+    private class UnitApplier : Applier<Unit> {
+        override val current: Unit = Unit
+        override fun clear() {}
+        override fun move(from: Int, to: Int, count: Int) {}
+        override fun remove(index: Int, count: Int) {}
+        override fun up() {}
+        override fun insertTopDown(index: Int, instance: Unit) {}
+        override fun insertBottomUp(index: Int, instance: Unit) {}
+        override fun down(node: Unit) {}
+    }
+}
diff --git a/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/MovableContentSamples.kt b/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/MovableContentSamples.kt
index ebf18c2..e098eaa 100644
--- a/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/MovableContentSamples.kt
+++ b/compose/runtime/runtime/samples/src/main/java/androidx/compose/runtime/samples/MovableContentSamples.kt
@@ -31,7 +31,7 @@
 @Sampled
 @Composable
 fun MovableContentColumnRowSample(content: @Composable () -> Unit, vertical: Boolean) {
-    val movableContent = remember(content as Any) { movableContentOf(content) }
+    val movableContent = remember(content) { movableContentOf(content) }
 
     if (vertical) {
         Column {
diff --git a/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/ActualAndroid.android.kt b/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/ActualAndroid.android.kt
index e712b4a..13d9104 100644
--- a/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/ActualAndroid.android.kt
+++ b/compose/runtime/runtime/src/androidMain/kotlin/androidx/compose/runtime/ActualAndroid.android.kt
@@ -113,3 +113,5 @@
 internal actual fun logError(message: String, e: Throwable) {
     Log.e(LogTag, message, e)
 }
+
+internal actual val MainThreadId: Long = Looper.getMainLooper()?.thread?.id ?: -1
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
index 5c4170f..07a1d95 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Expect.kt
@@ -131,3 +131,7 @@
 ) : SnapshotContextElement
 
 internal expect fun logError(message: String, e: Throwable)
+
+internal expect fun currentThreadId(): Long
+
+internal expect fun currentThreadName(): String
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/MutableVector.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/MutableVector.kt
index 72de7b1..b539b12 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/MutableVector.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/MutableVector.kt
@@ -825,6 +825,32 @@
         }
     }
 
+    // Workaround to allow setting size from inline functions
+    @PublishedApi
+    internal fun setSize(newSize: Int) {
+        size = newSize
+    }
+
+    /**
+     * Removes items that satisfy [predicate]
+     */
+    inline fun removeIf(predicate: (T) -> Boolean) {
+        var gap = 0
+        val size = size
+        for (i in 0 until size) {
+            if (predicate(content[i] as T)) {
+                gap++
+                continue
+            }
+
+            if (gap > 0) {
+                content[i - gap] = content[i]
+            }
+        }
+        content.fill(null, fromIndex = size - gap, toIndex = size)
+        setSize(size - gap)
+    }
+
     /**
      * Keeps only [elements] in the [MutableVector] and removes all other values.
      */
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
index 304568c..c346941 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
@@ -27,6 +27,8 @@
 import androidx.compose.runtime.collection.fastForEach
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.composeRuntimeError
+import androidx.compose.runtime.currentThreadId
+import androidx.compose.runtime.currentThreadName
 import androidx.compose.runtime.observeDerivedStateRecalculations
 import androidx.compose.runtime.structuralEqualityPolicy
 
@@ -184,6 +186,12 @@
         }
     }
 
+    private inline fun removeScopeMapIf(block: (ObservedScopeMap) -> Boolean) {
+        synchronized(observedScopeMaps) {
+            observedScopeMaps.removeIf(block)
+        }
+    }
+
     /**
      * Method to call when unsubscribing from the apply observer.
      */
@@ -201,6 +209,11 @@
     private var currentMap: ObservedScopeMap? = null
 
     /**
+     * Thread id that has set the [currentMap]
+     */
+    private var currentMapThreadId = -1L
+
+    /**
      * Executes [block], observing state object reads during its execution.
      *
      * The [scope] and [onValueChangedForScope] are associated with any values that are read so
@@ -222,21 +235,29 @@
 
         val oldPaused = isPaused
         val oldMap = currentMap
+        val oldThreadId = currentMapThreadId
 
-        try {
-            isPaused = false
-            currentMap = scopeMap
-
-            scopeMap.observe(scope, readObserver, block)
-        } finally {
-            require(currentMap === scopeMap) {
-                "Inconsistent modification of observation scopes in SnapshotStateObserver. " +
+        if (oldThreadId != -1L) {
+            require(oldThreadId == currentThreadId()) {
+                "Detected multithreaded access to SnapshotStateObserver: " +
+                    "previousThreadId=$oldThreadId), " +
+                    "currentThread={id=${currentThreadId()}, name=${currentThreadName()}}. " +
                     "Note that observation on multiple threads in layout/draw is not supported. " +
                     "Make sure your measure/layout/draw for each Owner (AndroidComposeView) " +
                     "is executed on the same thread."
             }
+        }
+
+        try {
+            isPaused = false
+            currentMap = scopeMap
+            currentMapThreadId = Thread.currentThread().id
+
+            scopeMap.observe(scope, readObserver, block)
+        } finally {
             currentMap = oldMap
             isPaused = oldPaused
+            currentMapThreadId = oldThreadId
         }
     }
 
@@ -266,8 +287,9 @@
      * `onValueChangedForScope` callbacks passed in [observeReads].
      */
     fun clear(scope: Any) {
-        forEachScopeMap {
+        removeScopeMapIf {
             it.clearScopeObservations(scope)
+            !it.hasScopeObservations()
         }
     }
 
@@ -276,8 +298,9 @@
      * used when a scope is no longer in the hierarchy and should not receive any callbacks.
      */
     fun clearIf(predicate: (scope: Any) -> Boolean) {
-        forEachScopeMap { scopeMap ->
+        removeScopeMapIf { scopeMap ->
             scopeMap.removeScopeIf(predicate)
+            !scopeMap.hasScopeObservations()
         }
     }
 
@@ -516,6 +539,9 @@
             }
         }
 
+        fun hasScopeObservations(): Boolean =
+            scopeToValues.isNotEmpty()
+
         private fun removeObservation(scope: Any, value: Any) {
             valueToScopes.remove(value, scope)
             if (value is DerivedState<*> && value !in valueToScopes) {
diff --git a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.desktop.kt b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.desktop.kt
index 6594283..a150271 100644
--- a/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.desktop.kt
+++ b/compose/runtime/runtime/src/desktopMain/kotlin/androidx/compose/runtime/ActualDesktop.desktop.kt
@@ -102,3 +102,5 @@
     System.err.println(message)
     e.printStackTrace(System.err)
 }
+
+internal actual val MainThreadId: Long = -1
diff --git a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.jvm.kt b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.jvm.kt
index e73fbb9..63d84d7 100644
--- a/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.jvm.kt
+++ b/compose/runtime/runtime/src/jvmMain/kotlin/androidx/compose/runtime/ActualJvm.jvm.kt
@@ -50,19 +50,34 @@
     private val map = AtomicReference<ThreadMap>(emptyThreadMap)
     private val writeMutex = Any()
 
+    private var mainThreadValue: T? = null
+
     @Suppress("UNCHECKED_CAST")
-    actual fun get(): T? = map.get().get(Thread.currentThread().id) as T?
+    actual fun get(): T? {
+        val threadId = Thread.currentThread().id
+        return if (threadId == MainThreadId) {
+            mainThreadValue
+        } else {
+            map.get().get(Thread.currentThread().id) as T?
+        }
+    }
 
     actual fun set(value: T?) {
         val key = Thread.currentThread().id
-        synchronized(writeMutex) {
-            val current = map.get()
-            if (current.trySet(key, value)) return
-            map.set(current.newWith(key, value))
+        if (key == MainThreadId) {
+            mainThreadValue = value
+        } else {
+            synchronized(writeMutex) {
+                val current = map.get()
+                if (current.trySet(key, value)) return
+                map.set(current.newWith(key, value))
+            }
         }
     }
 }
 
+internal expect val MainThreadId: Long
+
 internal actual fun identityHashCode(instance: Any?): Int = System.identityHashCode(instance)
 
 @PublishedApi
@@ -117,3 +132,7 @@
         snapshot.unsafeLeave(oldState)
     }
 }
+
+internal actual fun currentThreadId(): Long = Thread.currentThread().id
+
+internal actual fun currentThreadName(): String = Thread.currentThread().name
diff --git a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
index 9fcac1a..fe09336 100644
--- a/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
+++ b/compose/runtime/runtime/src/nonEmulatorCommonTest/kotlin/androidx/compose/runtime/collection/MutableVectorTest.kt
@@ -824,6 +824,18 @@
     }
 
     @Test
+    fun removeIf() {
+        val l = mutableVectorOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+        l.removeIf { it % 2 == 0 }
+        assertEquals(5, l.size)
+        assertTrue(l.contentEquals(mutableVectorOf(1, 3, 5, 7, 9)))
+
+        l.removeIf { it % 2 != 0 }
+        assertEquals(0, l.size)
+        assertTrue(l.isEmpty())
+    }
+
+    @Test
     fun sortWith() {
         val l = mutableVectorOf(1, 4, 2, 5, 3)
         l.sortWith(Comparator { p0, p1 -> p0 - p1 })
diff --git a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/drawscope/DrawScopeTest.kt b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/drawscope/DrawScopeTest.kt
index 55a81a0..7f26707 100644
--- a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/drawscope/DrawScopeTest.kt
+++ b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/drawscope/DrawScopeTest.kt
@@ -23,8 +23,10 @@
 import androidx.compose.ui.graphics.Canvas
 import androidx.compose.ui.graphics.ClipOp
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
 import androidx.compose.ui.graphics.FilterQuality
 import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.ImageBitmapConfig
 import androidx.compose.ui.graphics.LinearGradientShader
 import androidx.compose.ui.graphics.Paint
 import androidx.compose.ui.graphics.PaintingStyle
@@ -40,6 +42,7 @@
 import androidx.compose.ui.graphics.nativeCanvas
 import androidx.compose.ui.graphics.toPixelMap
 import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -1770,6 +1773,52 @@
         }
     }
 
+    @Test
+    fun testBrushResetOnSubsequentDrawWithAlphaBitmap() {
+        val width = 200
+        val height = 200
+        val brush = Brush.horizontalGradient(
+            listOf(Color.Transparent, Color.Blue, Color.Transparent)
+        )
+        val maskBitmap = ImageBitmap(width / 2, height / 2, ImageBitmapConfig.Alpha8)
+        val maskCanvas = Canvas(maskBitmap)
+        maskCanvas.drawRect(
+            Rect(0f, 0f, width.toFloat(), height.toFloat()),
+            Paint().apply { color = Color.Green }
+        )
+        val colorFilter = ColorFilter.tint(Color.Red)
+        testDrawScopeAndCanvasAreEquivalent(
+            width,
+            height,
+            {
+                // Drawing an ImageBitmap after drawing a brush should unset the
+                // previously configured brush
+                drawRect(brush)
+                inset(width / 4f, height / 4f) {
+                    drawImage(maskBitmap, colorFilter = colorFilter)
+                }
+            },
+            { canvas ->
+                val paint = Paint().apply {
+                    brush.applyTo(Size(width.toFloat(), height.toFloat()), this, 1f)
+                }
+                canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
+                canvas.save()
+                canvas.translate(width / 4f, height / 4f)
+                canvas.drawImageRect(
+                    maskBitmap,
+                    srcOffset = IntOffset.Zero,
+                    srcSize = IntSize(width, height),
+                    dstOffset = IntOffset.Zero,
+                    dstSize = IntSize(width, height),
+                    Paint().apply {
+                        this.colorFilter = colorFilter
+                    })
+                canvas.restore()
+            }
+        )
+    }
+
     private inline fun testDrawTransformDefault(block: WrappedDrawTransform.() -> Unit) {
         val width = 100
         val height = 150
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/CanvasDrawScope.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/CanvasDrawScope.kt
index 36fe832..c8ea35b 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/CanvasDrawScope.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/CanvasDrawScope.kt
@@ -614,8 +614,10 @@
     ): Paint = selectPaint(style).apply {
         if (brush != null) {
             brush.applyTo(size, this, alpha)
-        } else if (this.alpha != alpha) {
-            this.alpha = alpha
+        } else {
+            if (this.shader != null) this.shader = null
+            if (this.color != Color.Black) this.color = Color.Black
+            if (this.alpha != alpha) this.alpha = alpha
         }
         if (this.colorFilter != colorFilter) this.colorFilter = colorFilter
         if (this.blendMode != blendMode) this.blendMode = blendMode
diff --git a/compose/ui/ui-text/api/current.txt b/compose/ui/ui-text/api/current.txt
index 7e15d2d..34c92ba 100644
--- a/compose/ui/ui-text/api/current.txt
+++ b/compose/ui/ui-text/api/current.txt
@@ -637,6 +637,12 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.ERROR, message="This is internal API that may change frequently and without warning.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY}) public @interface InternalPlatformTextApi {
   }
 
+  @SuppressCompatibility @androidx.compose.ui.text.android.InternalPlatformTextApi public final class StaticLayoutFactory {
+    method public android.text.StaticLayout create(CharSequence text, android.text.TextPaint paint, int width, optional int start, optional int end, optional android.text.TextDirectionHeuristic textDir, optional android.text.Layout.Alignment alignment, optional @IntRange(from=0L) int maxLines, optional android.text.TextUtils.TruncateAt? ellipsize, optional @IntRange(from=0L) int ellipsizedWidth, optional @FloatRange(from=0.0) float lineSpacingMultiplier, optional float lineSpacingExtra, optional int justificationMode, optional boolean includePadding, optional boolean useFallbackLineSpacing, optional int breakStrategy, optional int lineBreakStyle, optional int lineBreakWordStyle, optional int hyphenationFrequency, optional int[]? leftIndents, optional int[]? rightIndents);
+    method public boolean isFallbackLineSpacingEnabled(android.text.StaticLayout layout, boolean useFallbackLineSpacing);
+    field public static final androidx.compose.ui.text.android.StaticLayoutFactory INSTANCE;
+  }
+
 }
 
 package androidx.compose.ui.text.font {
@@ -738,6 +744,7 @@
   public final class FontFamilyResolver_androidKt {
     method public static androidx.compose.ui.text.font.FontFamily.Resolver createFontFamilyResolver(android.content.Context context);
     method public static androidx.compose.ui.text.font.FontFamily.Resolver createFontFamilyResolver(android.content.Context context, kotlin.coroutines.CoroutineContext coroutineContext);
+    method @SuppressCompatibility @androidx.compose.ui.text.InternalTextApi public static androidx.compose.ui.text.font.FontFamily.Resolver emptyCacheFontFamilyResolver(android.content.Context context);
     method public static androidx.compose.runtime.State<android.graphics.Typeface> resolveAsTypeface(androidx.compose.ui.text.font.FontFamily.Resolver, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight fontWeight, optional int fontStyle, optional int fontSynthesis);
   }
 
@@ -1088,6 +1095,20 @@
     property public final androidx.compose.ui.text.input.OffsetMapping Identity;
   }
 
+  @SuppressCompatibility @androidx.compose.ui.text.InternalTextApi public final class PartialGapBuffer {
+    ctor public PartialGapBuffer(String text);
+    method public operator char get(int index);
+    method public int getLength();
+    method public String getText();
+    method public void replace(int start, int end, String text);
+    method public void setText(String);
+    property public final int length;
+    property public final String text;
+    field public static final int BUF_SIZE = 255; // 0xff
+    field public static final int NOWHERE = -1; // 0xffffffff
+    field public static final int SURROUNDING_SIZE = 64; // 0x40
+  }
+
   public final class PasswordVisualTransformation implements androidx.compose.ui.text.input.VisualTransformation {
     ctor public PasswordVisualTransformation(optional char mask);
     method public androidx.compose.ui.text.input.TransformedText filter(androidx.compose.ui.text.AnnotatedString text);
diff --git a/compose/ui/ui-text/api/restricted_current.txt b/compose/ui/ui-text/api/restricted_current.txt
index 7e15d2d..34c92ba 100644
--- a/compose/ui/ui-text/api/restricted_current.txt
+++ b/compose/ui/ui-text/api/restricted_current.txt
@@ -637,6 +637,12 @@
   @SuppressCompatibility @kotlin.RequiresOptIn(level=kotlin.RequiresOptIn.Level.ERROR, message="This is internal API that may change frequently and without warning.") @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION, kotlin.annotation.AnnotationTarget.PROPERTY}) public @interface InternalPlatformTextApi {
   }
 
+  @SuppressCompatibility @androidx.compose.ui.text.android.InternalPlatformTextApi public final class StaticLayoutFactory {
+    method public android.text.StaticLayout create(CharSequence text, android.text.TextPaint paint, int width, optional int start, optional int end, optional android.text.TextDirectionHeuristic textDir, optional android.text.Layout.Alignment alignment, optional @IntRange(from=0L) int maxLines, optional android.text.TextUtils.TruncateAt? ellipsize, optional @IntRange(from=0L) int ellipsizedWidth, optional @FloatRange(from=0.0) float lineSpacingMultiplier, optional float lineSpacingExtra, optional int justificationMode, optional boolean includePadding, optional boolean useFallbackLineSpacing, optional int breakStrategy, optional int lineBreakStyle, optional int lineBreakWordStyle, optional int hyphenationFrequency, optional int[]? leftIndents, optional int[]? rightIndents);
+    method public boolean isFallbackLineSpacingEnabled(android.text.StaticLayout layout, boolean useFallbackLineSpacing);
+    field public static final androidx.compose.ui.text.android.StaticLayoutFactory INSTANCE;
+  }
+
 }
 
 package androidx.compose.ui.text.font {
@@ -738,6 +744,7 @@
   public final class FontFamilyResolver_androidKt {
     method public static androidx.compose.ui.text.font.FontFamily.Resolver createFontFamilyResolver(android.content.Context context);
     method public static androidx.compose.ui.text.font.FontFamily.Resolver createFontFamilyResolver(android.content.Context context, kotlin.coroutines.CoroutineContext coroutineContext);
+    method @SuppressCompatibility @androidx.compose.ui.text.InternalTextApi public static androidx.compose.ui.text.font.FontFamily.Resolver emptyCacheFontFamilyResolver(android.content.Context context);
     method public static androidx.compose.runtime.State<android.graphics.Typeface> resolveAsTypeface(androidx.compose.ui.text.font.FontFamily.Resolver, optional androidx.compose.ui.text.font.FontFamily? fontFamily, optional androidx.compose.ui.text.font.FontWeight fontWeight, optional int fontStyle, optional int fontSynthesis);
   }
 
@@ -1088,6 +1095,20 @@
     property public final androidx.compose.ui.text.input.OffsetMapping Identity;
   }
 
+  @SuppressCompatibility @androidx.compose.ui.text.InternalTextApi public final class PartialGapBuffer {
+    ctor public PartialGapBuffer(String text);
+    method public operator char get(int index);
+    method public int getLength();
+    method public String getText();
+    method public void replace(int start, int end, String text);
+    method public void setText(String);
+    property public final int length;
+    property public final String text;
+    field public static final int BUF_SIZE = 255; // 0xff
+    field public static final int NOWHERE = -1; // 0xffffffff
+    field public static final int SURROUNDING_SIZE = 64; // 0x40
+  }
+
   public final class PasswordVisualTransformation implements androidx.compose.ui.text.input.VisualTransformation {
     ctor public PasswordVisualTransformation(optional char mask);
     method public androidx.compose.ui.text.input.TransformedText filter(androidx.compose.ui.text.AnnotatedString text);
diff --git a/compose/ui/ui-text/lint-baseline.xml b/compose/ui/ui-text/lint-baseline.xml
index 240a988..f49a0ce 100644
--- a/compose/ui/ui-text/lint-baseline.xml
+++ b/compose/ui/ui-text/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanInlineOptIn"
@@ -29,222 +29,6 @@
     </issue>
 
     <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal open class BaselineShiftSpan(val multiplier: Float) : MetricAffectingSpan() {"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="fun emptyCacheFontFamilyResolver(context: Context): FontFamily.Resolver {"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.android.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class FontFeatureSpan(val fontFeatureSettings: String) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="class PartialGapBuffer(var text: String) {"
-        errorLine2="      ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/commonMain/kotlin/androidx/compose/ui/text/input/GapBuffer.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class IndentationFixSpan : LeadingMarginSpan {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal object LayoutCompat {"
-        errorLine2="                ~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal fun Layout.getLineForOffset(@IntRange(from = 0) offset: Int, upstream: Boolean): Int {"
-        errorLine2="                    ~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LayoutHelper(val layout: Layout) {"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LayoutIntrinsics("
-        errorLine2="               ~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LetterSpacingSpanEm(val letterSpacing: Float) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LetterSpacingSpanPx(@Px val letterSpacing: Float) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LineHeightSpan("
-        errorLine2="               ~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LineHeightStyleSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class PlaceholderSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal data class Segment("
-        errorLine2="                    ~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal object SegmentBreaker {"
-        errorLine2="                ~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="enum class SegmentType {"
-        errorLine2="           ~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class ShadowSpan("
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal open class SkewXSpan(val skewX: Float) : MetricAffectingSpan() {"
-        errorLine2="                    ~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="object StaticLayoutFactory {"
-        errorLine2="       ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TextDecorationSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TextLayout constructor("
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TypefaceSpan(val typeface: Typeface) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class WordBoundary("
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="../../../text/text/src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt"/>
-    </issue>
-
-    <issue
         id="ListIterator"
         message="Creating an unnecessary Iterator to iterate through a List"
         errorLine1="                        &quot;&apos;$key&apos; must be unique. Actual [ [${value.joinToString()}]&quot;"
diff --git a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.android.kt b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.android.kt
index 76cef40..1bfd354 100644
--- a/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.android.kt
+++ b/compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/font/FontFamilyResolver.android.kt
@@ -86,7 +86,6 @@
  *
  * This is primarily useful for testing or benchmarking.
  *
- * @suppress
  */
 @InternalTextApi // exposed for benchmarking, not a stable API.
 fun emptyCacheFontFamilyResolver(context: Context): FontFamily.Resolver {
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/GapBuffer.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/GapBuffer.kt
index 6b2f303..c211d6f 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/GapBuffer.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/input/GapBuffer.kt
@@ -225,7 +225,6 @@
  * is requested, this class flush the buffer and create new String, then start new gap buffer.
  *
  * @param text The initial text
- * @suppress
  */
 @InternalTextApi // "Used by benchmarks"
 class PartialGapBuffer(var text: String) {
diff --git a/compose/ui/ui-tooling-data/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/data/Inspectable.kt b/compose/ui/ui-tooling-data/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/data/Inspectable.kt
index b10d6135..8be0d0f 100644
--- a/compose/ui/ui-tooling-data/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/data/Inspectable.kt
+++ b/compose/ui/ui-tooling-data/src/androidAndroidTest/kotlin/androidx/compose/ui/tooling/data/Inspectable.kt
@@ -49,8 +49,6 @@
  *
  * @param compositionDataRecord [CompositionDataRecord] to record the SlotTable used in the
  * composition of [content]
- *
- * @suppress
  */
 @Composable
 @OptIn(InternalComposeApi::class)
diff --git a/compose/ui/ui-tooling-preview/api/current.txt b/compose/ui/ui-tooling-preview/api/current.txt
index 80d0e53..4d4cc08 100644
--- a/compose/ui/ui-tooling-preview/api/current.txt
+++ b/compose/ui/ui-tooling-preview/api/current.txt
@@ -24,8 +24,18 @@
     field public static final String PIXEL_3A_XL = "id:pixel_3a_xl";
     field public static final String PIXEL_3_XL = "id:pixel_3_xl";
     field public static final String PIXEL_4 = "id:pixel_4";
+    field public static final String PIXEL_4A = "id:pixel_4a";
     field public static final String PIXEL_4_XL = "id:pixel_4_xl";
+    field public static final String PIXEL_5 = "id:pixel_5";
+    field public static final String PIXEL_6 = "id:pixel_6";
+    field public static final String PIXEL_6A = "id:pixel_6a";
+    field public static final String PIXEL_6_PRO = "id:pixel_6_pro";
+    field public static final String PIXEL_7 = "id:pixel_7";
+    field public static final String PIXEL_7A = "id:pixel_7a";
+    field public static final String PIXEL_7_PRO = "id:pixel_7_pro";
     field public static final String PIXEL_C = "id:pixel_c";
+    field public static final String PIXEL_FOLD = "id:pixel_fold";
+    field public static final String PIXEL_TABLET = "id:pixel_tablet";
     field public static final String PIXEL_XL = "id:pixel_xl";
     field public static final String TABLET = "spec:id=reference_tablet,shape=Normal,width=1280,height=800,unit=dp,dpi=240";
     field public static final String TV_1080p = "spec:shape=Normal,width=1920,height=1080,unit=dp,dpi=420";
diff --git a/compose/ui/ui-tooling-preview/api/restricted_current.txt b/compose/ui/ui-tooling-preview/api/restricted_current.txt
index 80d0e53..4d4cc08 100644
--- a/compose/ui/ui-tooling-preview/api/restricted_current.txt
+++ b/compose/ui/ui-tooling-preview/api/restricted_current.txt
@@ -24,8 +24,18 @@
     field public static final String PIXEL_3A_XL = "id:pixel_3a_xl";
     field public static final String PIXEL_3_XL = "id:pixel_3_xl";
     field public static final String PIXEL_4 = "id:pixel_4";
+    field public static final String PIXEL_4A = "id:pixel_4a";
     field public static final String PIXEL_4_XL = "id:pixel_4_xl";
+    field public static final String PIXEL_5 = "id:pixel_5";
+    field public static final String PIXEL_6 = "id:pixel_6";
+    field public static final String PIXEL_6A = "id:pixel_6a";
+    field public static final String PIXEL_6_PRO = "id:pixel_6_pro";
+    field public static final String PIXEL_7 = "id:pixel_7";
+    field public static final String PIXEL_7A = "id:pixel_7a";
+    field public static final String PIXEL_7_PRO = "id:pixel_7_pro";
     field public static final String PIXEL_C = "id:pixel_c";
+    field public static final String PIXEL_FOLD = "id:pixel_fold";
+    field public static final String PIXEL_TABLET = "id:pixel_tablet";
     field public static final String PIXEL_XL = "id:pixel_xl";
     field public static final String TABLET = "spec:id=reference_tablet,shape=Normal,width=1280,height=800,unit=dp,dpi=240";
     field public static final String TV_1080p = "spec:shape=Normal,width=1920,height=1080,unit=dp,dpi=420";
diff --git a/compose/ui/ui-tooling-preview/lint-baseline.xml b/compose/ui/ui-tooling-preview/lint-baseline.xml
deleted file mode 100644
index beb06e4..0000000
--- a/compose/ui/ui-tooling-preview/lint-baseline.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0)" variant="all" version="8.1.0">
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="annotation class Device"
-        errorLine2="                 ~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Device.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="annotation class Wallpaper"
-        errorLine2="                 ~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Wallpaper.kt"/>
-    </issue>
-
-</issues>
diff --git a/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Device.kt b/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Device.kt
index 3ac0473..c140060 100644
--- a/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Device.kt
+++ b/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Device.kt
@@ -43,6 +43,16 @@
     const val PIXEL_3A_XL = "id:pixel_3a_xl"
     const val PIXEL_4 = "id:pixel_4"
     const val PIXEL_4_XL = "id:pixel_4_xl"
+    const val PIXEL_4A = "id:pixel_4a"
+    const val PIXEL_5 = "id:pixel_5"
+    const val PIXEL_6 = "id:pixel_6"
+    const val PIXEL_6_PRO = "id:pixel_6_pro"
+    const val PIXEL_6A = "id:pixel_6a"
+    const val PIXEL_7 = "id:pixel_7"
+    const val PIXEL_7_PRO = "id:pixel_7_pro"
+    const val PIXEL_7A = "id:pixel_7a"
+    const val PIXEL_FOLD = "id:pixel_fold"
+    const val PIXEL_TABLET = "id:pixel_tablet"
 
     const val AUTOMOTIVE_1024p = "id:automotive_1024p_landscape"
 
@@ -74,7 +84,6 @@
 
 /**
  * Annotation for defining the [Preview] device to use.
- * @suppress
  */
 @Retention(AnnotationRetention.SOURCE)
 @Suppress("DEPRECATION")
@@ -102,6 +111,16 @@
         Devices.PIXEL_3A_XL,
         Devices.PIXEL_4,
         Devices.PIXEL_4_XL,
+        Devices.PIXEL_4A,
+        Devices.PIXEL_5,
+        Devices.PIXEL_6,
+        Devices.PIXEL_6_PRO,
+        Devices.PIXEL_6A,
+        Devices.PIXEL_7,
+        Devices.PIXEL_7_PRO,
+        Devices.PIXEL_7A,
+        Devices.PIXEL_FOLD,
+        Devices.PIXEL_TABLET,
 
         Devices.AUTOMOTIVE_1024p,
 
@@ -119,4 +138,4 @@
         Devices.TV_1080p,
     ]
 )
-annotation class Device
+internal annotation class Device
diff --git a/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Wallpaper.kt b/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Wallpaper.kt
index 4dbc0972..34f0979 100644
--- a/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Wallpaper.kt
+++ b/compose/ui/ui-tooling-preview/src/androidMain/kotlin/androidx/compose/ui/tooling/preview/Wallpaper.kt
@@ -36,9 +36,8 @@
 
 /**
  * Annotation for defining the wallpaper to use for dynamic theming in the [Preview].
- * @suppress
  */
 @Retention(AnnotationRetention.SOURCE)
 @IntDef(Wallpapers.NONE, Wallpapers.RED_DOMINATED_EXAMPLE, Wallpapers.GREEN_DOMINATED_EXAMPLE,
     Wallpapers.BLUE_DOMINATED_EXAMPLE, Wallpapers.YELLOW_DOMINATED_EXAMPLE)
-annotation class Wallpaper
+internal annotation class Wallpaper
diff --git a/compose/ui/ui-tooling/api/current.txt b/compose/ui/ui-tooling/api/current.txt
index d037816..8c37ddf 100644
--- a/compose/ui/ui-tooling/api/current.txt
+++ b/compose/ui/ui-tooling/api/current.txt
@@ -10,6 +10,10 @@
     method @Deprecated @androidx.compose.runtime.Composable public static void InInspectionModeOnly(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
+  public final class PreviewActivity extends androidx.activity.ComponentActivity implements androidx.lifecycle.LifecycleOwner {
+    ctor public PreviewActivity();
+  }
+
 }
 
 package androidx.compose.ui.tooling.animation {
diff --git a/compose/ui/ui-tooling/api/restricted_current.txt b/compose/ui/ui-tooling/api/restricted_current.txt
index d037816..b42f0a6 100644
--- a/compose/ui/ui-tooling/api/restricted_current.txt
+++ b/compose/ui/ui-tooling/api/restricted_current.txt
@@ -10,6 +10,10 @@
     method @Deprecated @androidx.compose.runtime.Composable public static void InInspectionModeOnly(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
+  public final class PreviewActivity extends androidx.activity.ComponentActivity {
+    ctor public PreviewActivity();
+  }
+
 }
 
 package androidx.compose.ui.tooling.animation {
diff --git a/compose/ui/ui-tooling/lint-baseline.xml b/compose/ui/ui-tooling/lint-baseline.xml
index 0265d07..7b89361 100644
--- a/compose/ui/ui-tooling/lint-baseline.xml
+++ b/compose/ui/ui-tooling/lint-baseline.xml
@@ -1,50 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0)" variant="all" version="8.1.0">
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="data class ViewInfo("
-        errorLine2="           ~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class ComposeViewAdapter : FrameLayout {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    internal lateinit var clock: PreviewAnimationClock"
-        errorLine2="                          ~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    fun hasAnimations() = hasAnimations"
-        errorLine2="        ~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="class PreviewActivity : ComponentActivity() {"
-        errorLine2="      ~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt"/>
-    </issue>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanThreadSleep"
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
index aea52a6..b91e1e6 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt
@@ -82,11 +82,9 @@
 /**
  * Class containing the minimum information needed by the Preview to map components to the
  * source code and render boundaries.
- *
- * @suppress
  */
 @OptIn(UiToolingDataApi::class)
-data class ViewInfo(
+internal data class ViewInfo(
     val fileName: String,
     val lineNumber: Int,
     val bounds: IntRect,
@@ -122,7 +120,6 @@
  *  - `tools:animationClockStartTime`: When set, a [PreviewAnimationClock] will control the
  *  animations in the [ComposeViewAdapter] context.
  *
- * @suppress
  */
 @Suppress("unused")
 @OptIn(UiToolingDataApi::class)
@@ -425,8 +422,6 @@
 
     /**
      * Clock that controls the animations defined in the context of this [ComposeViewAdapter].
-     *
-     * @suppress
      */
     @VisibleForTesting
     internal lateinit var clock: PreviewAnimationClock
@@ -566,8 +561,6 @@
      *  method instead of the property directly is we use Java reflection to call it from Android
      *  Studio, and to find the property we'd need to filter the method names using `contains`
      *  instead of `equals`.
-     *
-     *  @suppress
      */
     fun hasAnimations() = hasAnimations
 
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt
index be6273d..b55bb40 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt
@@ -44,8 +44,8 @@
  * the key `parameterProviderClassName`. Optionally, `parameterProviderIndex` can also be set to
  * display a specific provider value instead of all of them.
  *
- * @suppress
  */
+@Suppress("ForbiddenSuperClass")
 class PreviewActivity : ComponentActivity() {
 
     private val TAG = "PreviewActivity"
diff --git a/compose/ui/ui/api/current.txt b/compose/ui/ui/api/current.txt
index dda58d9..e2ac70a 100644
--- a/compose/ui/ui/api/current.txt
+++ b/compose/ui/ui/api/current.txt
@@ -257,6 +257,64 @@
 
 }
 
+package androidx.compose.ui.draganddrop {
+
+  public final class DragAndDropEvent {
+    ctor public DragAndDropEvent(int type, android.view.DragEvent dragEvent);
+    method public int getType();
+    method public void setType(int);
+    property public final int type;
+  }
+
+  @kotlin.jvm.JvmInline public final value class DragAndDropEventType {
+    field public static final androidx.compose.ui.draganddrop.DragAndDropEventType.Companion Companion;
+  }
+
+  public static final class DragAndDropEventType.Companion {
+    method public int getChanged();
+    method public int getDropped();
+    method public int getEnded();
+    method public int getEntered();
+    method public int getExited();
+    method public int getMoved();
+    method public int getStarted();
+    method public int getUnknown();
+    property public final int Changed;
+    property public final int Dropped;
+    property public final int Ended;
+    property public final int Entered;
+    property public final int Exited;
+    property public final int Moved;
+    property public final int Started;
+    property public final int Unknown;
+  }
+
+  public final class DragAndDropInfo {
+    ctor public DragAndDropInfo(long size, androidx.compose.ui.draganddrop.DragAndDropTransfer transfer, kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> onDrawDragShadow);
+    method public kotlin.jvm.functions.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> getOnDrawDragShadow();
+    method public long getSize();
+    method public androidx.compose.ui.draganddrop.DragAndDropTransfer getTransfer();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> onDrawDragShadow;
+    property public final long size;
+    property public final androidx.compose.ui.draganddrop.DragAndDropTransfer transfer;
+  }
+
+  public final class DragAndDropTransfer {
+    ctor public DragAndDropTransfer(android.content.ClipData clipData, optional Object? localState, optional int flags);
+    method public android.content.ClipData getClipData();
+    method public int getFlags();
+    method public Object? getLocalState();
+    property public final android.content.ClipData clipData;
+    property public final int flags;
+    property public final Object? localState;
+  }
+
+  public final class DragAndDrop_androidKt {
+    method public static android.view.DragEvent getDragEvent(androidx.compose.ui.draganddrop.DragAndDropEvent);
+  }
+
+}
+
 package androidx.compose.ui.draw {
 
   public final class AlphaKt {
@@ -1932,6 +1990,7 @@
     ctor public VelocityTracker();
     method public void addPosition(long timeMillis, long position);
     method public long calculateVelocity();
+    method public long calculateVelocity(long maximumVelocity);
     method public void resetTracking();
   }
 
@@ -1939,6 +1998,7 @@
     ctor public VelocityTracker1D(boolean isDataDifferential);
     method public void addDataPoint(long timeMillis, float dataPoint);
     method public float calculateVelocity();
+    method public float calculateVelocity(float maximumVelocity);
     method public boolean isDataDifferential();
     method public void resetTracking();
     property public final boolean isDataDifferential;
@@ -1967,9 +2027,11 @@
 
   public final class RotaryScrollEvent {
     method public float getHorizontalScrollPixels();
+    method public int getInputDeviceId();
     method public long getUptimeMillis();
     method public float getVerticalScrollPixels();
     property public final float horizontalScrollPixels;
+    property public final int inputDeviceId;
     property public final long uptimeMillis;
     property public final float verticalScrollPixels;
   }
@@ -2669,6 +2731,7 @@
     property public long doubleTapMinTimeMillis;
     property public long doubleTapTimeoutMillis;
     property public long longPressTimeoutMillis;
+    property public int maximumFlingVelocity;
     property public float touchSlop;
   }
 
@@ -2884,11 +2947,13 @@
     method public long getDoubleTapMinTimeMillis();
     method public long getDoubleTapTimeoutMillis();
     method public long getLongPressTimeoutMillis();
+    method public default int getMaximumFlingVelocity();
     method public default long getMinimumTouchTargetSize();
     method public float getTouchSlop();
     property public abstract long doubleTapMinTimeMillis;
     property public abstract long doubleTapTimeoutMillis;
     property public abstract long longPressTimeoutMillis;
+    property public default int maximumFlingVelocity;
     property public default long minimumTouchTargetSize;
     property public abstract float touchSlop;
   }
diff --git a/compose/ui/ui/api/restricted_current.txt b/compose/ui/ui/api/restricted_current.txt
index 1557073..9866e4c 100644
--- a/compose/ui/ui/api/restricted_current.txt
+++ b/compose/ui/ui/api/restricted_current.txt
@@ -257,6 +257,64 @@
 
 }
 
+package androidx.compose.ui.draganddrop {
+
+  public final class DragAndDropEvent {
+    ctor public DragAndDropEvent(int type, android.view.DragEvent dragEvent);
+    method public int getType();
+    method public void setType(int);
+    property public final int type;
+  }
+
+  @kotlin.jvm.JvmInline public final value class DragAndDropEventType {
+    field public static final androidx.compose.ui.draganddrop.DragAndDropEventType.Companion Companion;
+  }
+
+  public static final class DragAndDropEventType.Companion {
+    method public int getChanged();
+    method public int getDropped();
+    method public int getEnded();
+    method public int getEntered();
+    method public int getExited();
+    method public int getMoved();
+    method public int getStarted();
+    method public int getUnknown();
+    property public final int Changed;
+    property public final int Dropped;
+    property public final int Ended;
+    property public final int Entered;
+    property public final int Exited;
+    property public final int Moved;
+    property public final int Started;
+    property public final int Unknown;
+  }
+
+  public final class DragAndDropInfo {
+    ctor public DragAndDropInfo(long size, androidx.compose.ui.draganddrop.DragAndDropTransfer transfer, kotlin.jvm.functions.Function1<? super androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> onDrawDragShadow);
+    method public kotlin.jvm.functions.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> getOnDrawDragShadow();
+    method public long getSize();
+    method public androidx.compose.ui.draganddrop.DragAndDropTransfer getTransfer();
+    property public final kotlin.jvm.functions.Function1<androidx.compose.ui.graphics.drawscope.DrawScope,kotlin.Unit> onDrawDragShadow;
+    property public final long size;
+    property public final androidx.compose.ui.draganddrop.DragAndDropTransfer transfer;
+  }
+
+  public final class DragAndDropTransfer {
+    ctor public DragAndDropTransfer(android.content.ClipData clipData, optional Object? localState, optional int flags);
+    method public android.content.ClipData getClipData();
+    method public int getFlags();
+    method public Object? getLocalState();
+    property public final android.content.ClipData clipData;
+    property public final int flags;
+    property public final Object? localState;
+  }
+
+  public final class DragAndDrop_androidKt {
+    method public static android.view.DragEvent getDragEvent(androidx.compose.ui.draganddrop.DragAndDropEvent);
+  }
+
+}
+
 package androidx.compose.ui.draw {
 
   public final class AlphaKt {
@@ -1932,6 +1990,7 @@
     ctor public VelocityTracker();
     method public void addPosition(long timeMillis, long position);
     method public long calculateVelocity();
+    method public long calculateVelocity(long maximumVelocity);
     method public void resetTracking();
   }
 
@@ -1939,6 +1998,7 @@
     ctor public VelocityTracker1D(boolean isDataDifferential);
     method public void addDataPoint(long timeMillis, float dataPoint);
     method public float calculateVelocity();
+    method public float calculateVelocity(float maximumVelocity);
     method public boolean isDataDifferential();
     method public void resetTracking();
     property public final boolean isDataDifferential;
@@ -1967,9 +2027,11 @@
 
   public final class RotaryScrollEvent {
     method public float getHorizontalScrollPixels();
+    method public int getInputDeviceId();
     method public long getUptimeMillis();
     method public float getVerticalScrollPixels();
     property public final float horizontalScrollPixels;
+    property public final int inputDeviceId;
     property public final long uptimeMillis;
     property public final float verticalScrollPixels;
   }
@@ -2722,6 +2784,7 @@
     property public long doubleTapMinTimeMillis;
     property public long doubleTapTimeoutMillis;
     property public long longPressTimeoutMillis;
+    property public int maximumFlingVelocity;
     property public float touchSlop;
   }
 
@@ -2938,11 +3001,13 @@
     method public long getDoubleTapMinTimeMillis();
     method public long getDoubleTapTimeoutMillis();
     method public long getLongPressTimeoutMillis();
+    method public default int getMaximumFlingVelocity();
     method public default long getMinimumTouchTargetSize();
     method public float getTouchSlop();
     property public abstract long doubleTapMinTimeMillis;
     property public abstract long doubleTapTimeoutMillis;
     property public abstract long longPressTimeoutMillis;
+    property public default int maximumFlingVelocity;
     property public default long minimumTouchTargetSize;
     property public abstract float touchSlop;
   }
diff --git a/compose/ui/ui/lint-baseline.xml b/compose/ui/ui/lint-baseline.xml
index a5c5fb7..7bd4109 100644
--- a/compose/ui/ui/lint-baseline.xml
+++ b/compose/ui/ui/lint-baseline.xml
@@ -436,24 +436,6 @@
     <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in variable &apos;scrollAction&apos; with type AccessibilityAction&lt;Function2&lt;? super Float, ? super Float, ? extends Boolean>>."
-        errorLine1="                val scrollAction ="
-        errorLine2="                ^">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in variable &apos;vare2b4ac12&apos; with type AccessibilityAction&lt;Function2&lt;? super Float, ? super Float, ? extends Boolean>>."
-        errorLine1="                    node.unmergedConfig.getOrNull(SemanticsActions.ScrollBy) ?: return false"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt"/>
-    </issue>
-
-    <issue
-        id="PrimitiveInLambda"
-        message="Use a functional interface instead of lambda syntax for lambdas with primitive values in variable &apos;scrollAction&apos; with type AccessibilityAction&lt;Function2&lt;? super Float, ? super Float, ? extends Boolean>>."
         errorLine1="                var scrollAction = scrollableAncestor?.config?.getOrNull(SemanticsActions.ScrollBy)"
         errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
index 465ab5d..dd2e368 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
@@ -718,15 +718,26 @@
         val node3 = rule.onNodeWithText(text3).fetchSemanticsNode()
         val overlaidNode = rule.onNodeWithText(overlaidText).fetchSemanticsNode()
 
-        val overlaidANI = provider.createAccessibilityNodeInfo(overlaidNode.id)
-        val overlaidTraversalAfterValue =
-            overlaidANI?.extras?.getInt(EXTRA_DATA_TEST_TRAVERSALAFTER_VAL)
+        val node3ANI = provider.createAccessibilityNodeInfo(node3.id)
+        val node3TraversalBefore =
+            node3ANI?.extras?.getInt(EXTRA_DATA_TEST_TRAVERSALBEFORE_VAL)
 
         // Nodes 1, 2, and 3 are all children of a larger column; this means with a hierarchy
         // comparison (like SemanticsSort), the third text node should come before the overlaid node
         // — OverlaidNode should be read last
-        assertNotEquals(overlaidTraversalAfterValue, 0)
-        assertEquals(overlaidTraversalAfterValue, node3.id)
+        assertNotEquals(node3TraversalBefore, 0)
+        assertEquals(node3TraversalBefore, overlaidNode.id)
+
+        val overlaidANI = provider.createAccessibilityNodeInfo(overlaidNode.id)
+        // `getInt` returns the value associated with the given key, or 0 if no mapping of
+        // the desired type exists for the given key.
+        val overlaidTraversalAfter =
+            overlaidANI?.extras?.getInt(EXTRA_DATA_TEST_TRAVERSALAFTER_VAL)
+
+        // Older versions of Samsung voice assistant crash if both traversalBefore
+        // and traversalAfter redundantly express the same ordering relation, so
+        // we should only have traversalBefore here.
+        assertEquals(overlaidTraversalAfter, 0)
     }
 
     @Composable
@@ -1640,15 +1651,12 @@
         val child1 = rule.onNodeWithTag(childTag1).fetchSemanticsNode()
         val child2 = rule.onNodeWithTag(childTag2).fetchSemanticsNode()
 
-        val child1ANI = provider.createAccessibilityNodeInfo(child1.id)
         val child2ANI = provider.createAccessibilityNodeInfo(child2.id)
         val child2TraverseBefore = child2ANI?.extras?.getInt(EXTRA_DATA_TEST_TRAVERSALBEFORE_VAL)
-        val child1TraverseAfter = child1ANI?.extras?.getInt(EXTRA_DATA_TEST_TRAVERSALAFTER_VAL)
 
         // We want child2 to come before child1
         assertEquals(2, root.replacedChildren.size)
         assertEquals(child2TraverseBefore, child1.id)
-        assertEquals(child1TraverseAfter, child2.id)
     }
 
     @Test
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
index 0d4f41a..8a407fd 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidComposeViewAccessibilityDelegateCompatTest.kt
@@ -36,6 +36,7 @@
 import androidx.compose.runtime.structuralEqualityPolicy
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.MutableRect
@@ -71,6 +72,8 @@
 import androidx.compose.ui.platform.TextToolbar
 import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.platform.WindowInfo
+import androidx.compose.ui.platform.coreshims.ContentCaptureSessionCompat
+import androidx.compose.ui.platform.coreshims.ViewStructureCompat
 import androidx.compose.ui.platform.getAllUncoveredSemanticsNodesToMap
 import androidx.compose.ui.platform.invertTo
 import androidx.compose.ui.semantics.CustomAccessibilityAction
@@ -81,7 +84,9 @@
 import androidx.compose.ui.semantics.ScrollAxisRange
 import androidx.compose.ui.semantics.SemanticsNode
 import androidx.compose.ui.semantics.SemanticsOwner
+import androidx.compose.ui.semantics.SemanticsPropertyKey
 import androidx.compose.ui.semantics.SemanticsPropertyReceiver
+import androidx.compose.ui.semantics.clearAndSetSemantics
 import androidx.compose.ui.semantics.clearTextSubstitution
 import androidx.compose.ui.semantics.collapse
 import androidx.compose.ui.semantics.contentDescription
@@ -97,6 +102,7 @@
 import androidx.compose.ui.semantics.getTextLayoutResult
 import androidx.compose.ui.semantics.heading
 import androidx.compose.ui.semantics.horizontalScrollAxisRange
+import androidx.compose.ui.semantics.invisibleToUser
 import androidx.compose.ui.semantics.isShowingTextSubstitution
 import androidx.compose.ui.semantics.liveRegion
 import androidx.compose.ui.semantics.onClick
@@ -134,10 +140,8 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.toOffset
 import androidx.core.view.ViewCompat
-import androidx.core.view.ViewStructureCompat
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
 import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
-import androidx.core.view.contentcapture.ContentCaptureSessionCompat
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.MediumTest
@@ -504,6 +508,115 @@
     }
 
     @Test
+    @SdkSuppress(minSdkVersion = 24)
+    fun testIsNotImportant_empty() {
+        var semanticsNode: SemanticsNode
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) { }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    fun testIsImportant_emptyMerging() {
+        var semanticsNode: SemanticsNode
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = true) { }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(true, info.isImportantForAccessibility)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    @OptIn(ExperimentalComposeUiApi::class)
+    fun testIsNotImportant_testOnlyProperties() {
+        var semanticsNode: SemanticsNode
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            testTag = "tag"
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            testTagsAsResourceId = true
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            testTag = "tag"
+            invisibleToUser()
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    @OptIn(ExperimentalComposeUiApi::class)
+    fun testIsImportant_accessibilitySpeakableProperties() {
+        var semanticsNode: SemanticsNode
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            stateDescription = "stateDescription"
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(true, info.isImportantForAccessibility)
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            testTag = "tag" // test that also including a non-speakable property doesn't matter
+            heading()
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(true, info.isImportantForAccessibility)
+
+        info = AccessibilityNodeInfoCompat.obtain()
+        semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            onClick("clickLabel") { true }
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(true, info.isImportantForAccessibility)
+    }
+
+    val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
+    var SemanticsPropertyReceiver.pickedDate by PickedDateKey
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    @OptIn(ExperimentalComposeUiApi::class)
+    fun testIsNotImportant_customSemanticsProperty() {
+        val semanticsNode = createSemanticsNodeWithProperties(1, mergeDescendants = false) {
+            pickedDate = 1445378400 // 2015-10-21
+        }
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 24)
+    fun testIsNotImportant_clearedWithTestTag() {
+        val layoutNode = LayoutNode(semanticsId = 1)
+        layoutNode.modifier = Modifier.clearAndSetSemantics {
+            testTag = "tag"
+        }.semantics(mergeDescendants = true) {
+            stateDescription = "stateDescription"
+        }
+        val childNode1 = createSemanticsNodeWithChildren(2, emptyList()) {
+            text = AnnotatedString("foo")
+        }
+        layoutNode.zSortedChildren.add(childNode1.layoutNode)
+        layoutNode.attach(MockOwner())
+        val semanticsNode = SemanticsNode(layoutNode, true)
+        accessibilityDelegate.populateAccessibilityNodeInfoProperties(1, info, semanticsNode)
+        assertEquals(false, info.isImportantForAccessibility)
+    }
+
+    @Test
     fun nodeWithTextAndLayoutResult_className_textView() {
         val semanticsNode = createSemanticsNodeWithProperties(1, true) {
             text = AnnotatedString("")
@@ -2060,6 +2173,10 @@
         TODO("Not yet implemented")
     }
 
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        TODO("Not yet implemented")
+    }
+
     val invalidatedLayers = mutableListOf<OwnedLayer>()
 
     override fun createLayer(
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/MemoryLeakTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/MemoryLeakTest.kt
index 57158e4..21fab87 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/MemoryLeakTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/MemoryLeakTest.kt
@@ -25,16 +25,27 @@
 import androidx.compose.foundation.text.BasicText
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MonotonicFrameClock
+import androidx.compose.runtime.Recomposer
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshots.Snapshot
 import androidx.compose.testutils.ComposeTestCase
 import androidx.compose.testutils.createAndroidComposeBenchmarkRunner
 import androidx.compose.ui.platform.AndroidUiDispatcher
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.viewinterop.AndroidView
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
 import java.text.NumberFormat
 import java.util.Locale
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.yield
@@ -51,6 +62,7 @@
     val activityTestRule = androidx.test.rule.ActivityTestRule(ComponentActivity::class.java)
 
     @Test
+    @SdkSuppress(minSdkVersion = 22) // b/266743031
     fun disposeAndRemoveOwnerView_assertViewWasGarbageCollected() = runBlocking {
         class SimpleTestCase : ComposeTestCase {
             @Composable
@@ -145,6 +157,58 @@
         Log.d("memoryCheckerTest", totalSum.toString())
     }
 
+    @OptIn(ExperimentalTestApi::class, ExperimentalCoroutinesApi::class)
+    @Test
+    fun recreateAndroidView_assertNoLeak() = runBlocking(AndroidUiDispatcher.Main) {
+        val immediateClock = object : MonotonicFrameClock {
+            override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R): R {
+                yield()
+                return onFrame(0L)
+            }
+        }
+        val context = coroutineContext + immediateClock
+        val recomposer = Recomposer(context)
+
+        suspend fun doFrame() {
+            Snapshot.sendApplyNotifications()
+
+            var pendingCount = 0
+            while (recomposer.hasPendingWork) {
+                pendingCount++
+                yield()
+                if (pendingCount == 10) {
+                    error("Recomposer still pending work after 10 frames.")
+                }
+            }
+        }
+
+        var compose by mutableStateOf(false)
+        activityTestRule.activity.setContent(recomposer) {
+            if (compose) {
+                AndroidView(factory = {
+                    object : View(it) { val alloc = List(1024) { 0 } }
+                })
+            }
+        }
+        launch(context = context, start = CoroutineStart.UNDISPATCHED) {
+            recomposer.runRecomposeAndApplyChanges()
+        }
+        doFrame()
+
+        loopAndVerifyMemory(ignoreFirstRun = true, iterations = 400, gcFrequency = 40) {
+            // Add AndroidView into the composition
+            compose = true
+            doFrame()
+
+            // This removes the AndroidView
+            compose = false
+            doFrame()
+        }
+
+        recomposer.cancel()
+        recomposer.join()
+    }
+
     /**
      * Runs the given code in a loop for exactly [iterations] times and every [gcFrequency] it will
      * force garbage collection and check the allocated heap size.
@@ -155,7 +219,7 @@
         iterations: Int,
         gcFrequency: Int,
         ignoreFirstRun: Boolean = false,
-        operationToPerform: () -> Unit
+        operationToPerform: suspend () -> Unit
     ) {
         val rawStats = ArrayList<Long>(iterations / gcFrequency)
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
index 3a813aa..0e0a75b 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/vector/VectorTest.kt
@@ -26,6 +26,7 @@
 import androidx.activity.ComponentActivity
 import androidx.annotation.RequiresApi
 import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.height
@@ -863,7 +864,11 @@
                 contentDescription = null,
                 modifier = Modifier
                     .testTag(testTag)
-                    .background(Color.Red)
+                    .background(
+                        Brush.horizontalGradient(
+                            listOf(Color.Transparent, Color.Yellow, Color.Transparent)
+                        )
+                    )
                     .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen },
                 contentScale = ContentScale.FillBounds,
                 colorFilter = colorFilter
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/focus/FocusAwareEventPropagationTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/focus/FocusAwareEventPropagationTest.kt
index 6d7da47..e350b81 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/focus/FocusAwareEventPropagationTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/focus/FocusAwareEventPropagationTest.kt
@@ -64,7 +64,7 @@
 
     private val sentEvent: Any = when (nodeType) {
         KeyInput, InterruptedSoftKeyboardInput -> KeyEvent(AndroidKeyEvent(ACTION_DOWN, KEYCODE_A))
-        RotaryInput -> RotaryScrollEvent(1f, 1f, 0L)
+        RotaryInput -> RotaryScrollEvent(1f, 1f, 0L, 0)
     }
     private var receivedEvent: Any? = null
     private val initialFocus = FocusRequester()
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
index 3169f96..a367f75 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
@@ -22,6 +22,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.MutableRect
@@ -3829,4 +3830,8 @@
         get() = TODO("Not yet implemented")
 
     override val sharedDrawScope = LayoutNodeDrawScope()
+
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        TODO("Not yet implemented")
+    }
 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
index b12dab1..a9970b5 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
@@ -23,6 +23,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.Offset
@@ -3431,6 +3432,10 @@
         }
     }
 
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        TODO("Not yet implemented")
+    }
+
     override fun registerOnLayoutCompletedListener(listener: Owner.OnLayoutCompletedListener) {
         TODO("Not yet implemented")
     }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
index c2b3768..31db4be 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/pointer/SuspendingPointerInputFilterTest.kt
@@ -18,8 +18,11 @@
 
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReusableContent
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.rememberUpdatedState
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.geometry.Offset
@@ -858,4 +861,45 @@
         }
         assertThat(events).hasSize(2)
     }
+
+    @Test
+    @MediumTest
+    fun lambdaIsRecapturedWhenReused() {
+        val tag = "box"
+        val events = mutableListOf<Int>()
+
+        @Composable
+        fun BoxWithKey(key: Int) {
+            // imitating one of the recommended patterns for Modifier.pointerInput() where we use
+            // rememberUpdatedState in order to have the latest value inside the suspending lambda.
+            // technically the state backing rememberUpdatedState will be recreated when the reuse
+            // happens so Modifier.pointerInput() have to update it's lambda to the new one even
+            // given that the key (Unit) didn't change.
+            val currentKey by rememberUpdatedState(key)
+            Box(
+                Modifier
+                    .testTag(tag)
+                    .fillMaxSize()
+                    .pointerInput(Unit) {
+                        events.add(currentKey)
+                    })
+        }
+
+        var key by mutableStateOf(0)
+
+        rule.setContent {
+            ReusableContent(key = key) {
+                BoxWithKey(key)
+            }
+        }
+
+        rule.runOnIdle {
+            key++
+        }
+
+        rule.onNodeWithTag(tag).performTouchInput {
+            down(Offset.Zero)
+        }
+        assertThat(events).isEqualTo(listOf(key))
+    }
 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEventTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEventTest.kt
index 06d53a3..e6eb02c 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEventTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEventTest.kt
@@ -274,6 +274,41 @@
     }
 
     @Test
+    fun rotaryEventHasDeviceId() {
+        val DEVICE_ID = 1234
+
+        // Arrange.
+        ContentWithInitialFocus {
+            Box(
+                modifier = Modifier
+                    .onRotaryScrollEvent {
+                        receivedEvent = it
+                        true
+                    }
+                    .focusable(initiallyFocused = true)
+            )
+        }
+
+        // Act.
+        rule.runOnIdle {
+            rootView.dispatchGenericMotionEvent(
+                MotionEventBuilder.newBuilder()
+                    .setAction(ACTION_SCROLL)
+                    .setSource(SOURCE_ROTARY_ENCODER)
+                    .setDeviceId(DEVICE_ID)
+                    .build()
+            )
+        }
+
+        // Assert.
+        rule.runOnIdle {
+            with(checkNotNull(receivedEvent)) {
+                assertThat(inputDeviceId).isEqualTo(DEVICE_ID)
+            }
+        }
+    }
+
+    @Test
     fun rotaryEventUsesTestTime() {
         val TIME_DELTA = 1234L
 
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/Helpers.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/Helpers.kt
index 7bace0b..a7a3aa9 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/Helpers.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/Helpers.kt
@@ -19,6 +19,7 @@
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.MutableRect
 import androidx.compose.ui.geometry.Offset
@@ -208,6 +209,7 @@
     override fun requestFocus() = TODO("Not yet implemented")
     override fun onSemanticsChange() = TODO("Not yet implemented")
     override fun getFocusDirection(keyEvent: KeyEvent) = TODO("Not yet implemented")
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean = TODO("Not yet implemented")
 }
 
 internal fun defaultRootConstraints() = Constraints(maxWidth = 100, maxHeight = 100)
@@ -312,12 +314,14 @@
     (measurePolicy as SmartMeasurePolicy).queryAlignmentLinesDuringMeasure = true
 }
 
-internal fun LayoutNode.runDuringMeasure(block: () -> Unit) {
+internal fun LayoutNode.runDuringMeasure(once: Boolean = true, block: () -> Unit) {
     (measurePolicy as SmartMeasurePolicy).preMeasureCallback = block
+    (measurePolicy as SmartMeasurePolicy).shouldClearPreMeasureCallback = once
 }
 
-internal fun LayoutNode.runDuringLayout(block: () -> Unit) {
+internal fun LayoutNode.runDuringLayout(once: Boolean = true, block: () -> Unit) {
     (measurePolicy as SmartMeasurePolicy).preLayoutCallback = block
+    (measurePolicy as SmartMeasurePolicy).shouldClearPreLayoutCallback = once
 }
 
 internal val LayoutNode.first: LayoutNode get() = children.first()
@@ -364,7 +368,9 @@
     open var wrapChildren = false
     open var queryAlignmentLinesDuringMeasure = false
     var preMeasureCallback: (() -> Unit)? = null
+    var shouldClearPreMeasureCallback = false
     var preLayoutCallback: (() -> Unit)? = null
+    var shouldClearPreLayoutCallback = false
     var measuredLayoutDirection: LayoutDirection? = null
         protected set
     var childrenLayoutDirection: LayoutDirection? = null
@@ -382,7 +388,9 @@
     ): MeasureResult {
         measuresCount++
         preMeasureCallback?.invoke()
-        preMeasureCallback = null
+        if (shouldClearPreMeasureCallback) {
+            preMeasureCallback = null
+        }
         val childConstraints = if (size == null) {
             constraints
         } else {
@@ -409,7 +417,9 @@
         return layout(maxWidth, maxHeight) {
             layoutsCount++
             preLayoutCallback?.invoke()
-            preLayoutCallback = null
+            if (shouldClearPreLayoutCallback) {
+                preLayoutCallback = null
+            }
             if (shouldPlaceChildren) {
                 placeables.forEach { placeable ->
                     if (placeWithLayer) {
@@ -450,7 +460,9 @@
     ): MeasureResult {
         measuresCount++
         preMeasureCallback?.invoke()
-        preMeasureCallback = null
+        if (shouldClearPreMeasureCallback) {
+            preMeasureCallback = null
+        }
         val childConstraints = if (size == null) {
             constraints
         } else {
@@ -459,7 +471,9 @@
         }
         return layout(childConstraints.maxWidth, childConstraints.maxHeight) {
             preLayoutCallback?.invoke()
-            preLayoutCallback = null
+            if (shouldClearPreLayoutCallback) {
+                preLayoutCallback = null
+            }
             layoutsCount++
             measurables.forEach {
                 val placeable = it.measure(childConstraints)
@@ -494,14 +508,18 @@
     ): MeasureResult {
         measuresCount++
         preMeasureCallback?.invoke()
-        preMeasureCallback = null
+        if (shouldClearPreMeasureCallback) {
+            preMeasureCallback = null
+        }
 
         val width = size ?: if (!wrapChildren) constraints.maxWidth else constraints.minWidth
         val height = size ?: if (!wrapChildren) constraints.maxHeight else constraints.minHeight
         return layout(width, height) {
             layoutsCount++
             preLayoutCallback?.invoke()
-            preLayoutCallback = null
+            if (shouldClearPreLayoutCallback) {
+                preLayoutCallback = null
+            }
         }
     }
 }
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
index 1725987..ad914a7 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
@@ -19,6 +19,7 @@
 package androidx.compose.ui.layout
 
 import androidx.activity.ComponentActivity
+import androidx.compose.animation.AnimatedContent
 import androidx.compose.animation.animateContentSize
 import androidx.compose.animation.core.Animatable
 import androidx.compose.animation.core.AnimationVector2D
@@ -52,6 +53,7 @@
 import androidx.compose.foundation.layout.widthIn
 import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.shape.RoundedCornerShape
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
@@ -62,6 +64,7 @@
 import androidx.compose.runtime.movableContentOf
 import androidx.compose.runtime.mutableStateListOf
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
@@ -98,6 +101,7 @@
 import kotlin.math.roundToInt
 import kotlin.random.Random
 import kotlin.test.assertNotNull
+import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import org.junit.Ignore
 import org.junit.Rule
@@ -2230,6 +2234,83 @@
         }
     }
 
+    @Test
+    fun forceMeasureLookaheadRootInParentsMeasurePass() {
+        var show by mutableStateOf(false)
+        var lookaheadOffset: Offset? = null
+        var offset: Offset? = null
+        rule.setContent {
+            CompositionLocalProvider(LocalDensity provides Density(1f)) {
+                // Mutate this state in measure
+                Box(Modifier.fillMaxSize()) {
+                    val size by produceState(initialValue = 200) {
+                        delay(500)
+                        value = 600 - value
+                    }
+                    LazyColumn(Modifier.layout { measurable, _ ->
+                        // Mutate this state in measure. This state will later be used in descendant's
+                        // composition.
+                        show = size > 300
+                        measurable.measure(Constraints.fixed(size, size)).run {
+                            layout(width, height) { place(0, 0) }
+                        }
+                    }) {
+                        item {
+                            SubcomposeLayout(Modifier.fillMaxSize()) {
+                                val placeable = subcompose(Unit) {
+                                    // read the value to force a recomposition
+                                    Box(
+                                        Modifier.requiredSize(222.dp)
+                                    ) {
+                                        AnimatedContent(show, Modifier.requiredSize(200.dp)) {
+                                            if (it) {
+                                                Row(
+                                                    Modifier
+                                                        .fillMaxSize()
+                                                        .layout { measurable, constraints ->
+                                                            val p = measurable.measure(constraints)
+                                                            layout(p.width, p.height) {
+                                                                coordinates
+                                                                    ?.positionInRoot()
+                                                                    .let {
+                                                                        if (isLookingAhead) {
+                                                                            lookaheadOffset = it
+                                                                        } else {
+                                                                            offset = it
+                                                                        }
+                                                                    }
+                                                                p.place(0, 0)
+                                                            }
+                                                        }) {}
+                                            } else {
+                                                Row(
+                                                    Modifier.size(10.dp)
+                                                ) {}
+                                            }
+                                        }
+                                    }
+                                }[0].measure(Constraints(0, 2000, 0, 2000))
+                                // Measure with the same constraints to ensure the child (i.e. Box)
+                                // gets no constraints change and hence starts forceMeasureSubtree
+                                // from there
+                                layout(700, 800) {
+                                    placeable.place(0, 0)
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        rule.waitUntil(2000) {
+            show
+        }
+        rule.waitForIdle()
+
+        assertEquals(Offset(-150f, 0f), lookaheadOffset)
+        assertEquals(Offset(-150f, 0f), offset)
+    }
+
     @OptIn(ExperimentalComposeUiApi::class)
     @Test
     fun lookaheadSizeTrackedWhenModifierChanges() {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacedChildTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacedChildTest.kt
index f857392..5a1943b 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacedChildTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/PlacedChildTest.kt
@@ -312,6 +312,113 @@
             assertThat(placementCount).isEqualTo(0)
         }
     }
+
+    @Test
+    fun forceMeasureTheSubtreeSkipsNodesMeasuringInLayoutBlock() {
+        val remeasurings = mutableListOf<Int>()
+        val root = root {
+            runDuringMeasure(once = false) {
+                remeasurings.add(0)
+            }
+            add(
+                node {
+                    measureInLayoutBlock()
+                    runDuringMeasure(once = false) {
+                        remeasurings.add(1)
+                    }
+                    add(
+                        node {
+                            runDuringMeasure(once = false) {
+                                remeasurings.add(2)
+                            }
+                            size = 10
+                        }
+                    )
+                }
+            )
+            add(
+                node {
+                    runDuringMeasure(once = false) {
+                        remeasurings.add(3)
+                    }
+                }
+            )
+        }
+
+        val delegate = createDelegate(root)
+
+        remeasurings.clear()
+        root.requestRemeasure() // node with index 0
+        root.first.first.requestRemeasure() // node with index 2
+        root.second.requestRemeasure() // node with index 3
+        delegate.measureAndLayout()
+
+        assertThat(remeasurings).isEqualTo(listOf(0, 3, 2))
+    }
+
+    @Test
+    fun forceMeasureTheSubtreeDoesntRelayoutWhenParentsSizeChanges() {
+        val order = mutableListOf<Int>()
+        val root = root {
+            runDuringMeasure(once = false) {
+                order.add(0)
+            }
+            runDuringLayout(once = false) {
+                order.add(1)
+            }
+            add(
+                node {
+                    runDuringMeasure(once = false) {
+                        order.add(2)
+                    }
+                    runDuringLayout(once = false) {
+                        order.add(3)
+                    }
+                    add(
+                        node {
+                            runDuringMeasure(once = false) {
+                                order.add(6)
+                            }
+                            runDuringLayout(once = false) {
+                                order.add(7)
+                            }
+                            size = 10
+                        }
+                    )
+                }
+            )
+            add(
+                node {
+                    runDuringMeasure(once = false) {
+                        order.add(4)
+                    }
+                    runDuringLayout(once = false) {
+                        order.add(5)
+                    }
+                }
+            )
+        }
+
+        val delegate = createDelegate(root)
+
+        order.clear()
+        root.requestRemeasure() // node with indexes 0 and 1
+        root.first.first.size = 20
+        root.first.first.requestRemeasure() // node with indexes 6 and 7
+        root.second.requestRemeasure() // node with indexes 4 and 5
+        delegate.measureAndLayout()
+
+        assertThat(order).isEqualTo(listOf(
+            0, // remeasure root
+            6, // force remeasure root.first.first, it will change the size
+            2, // remeasure root.first because the size changed
+            4, // remeasure root.second
+            1, // relayout root
+            3, // relayout root.first
+            7, // relayout root.first.first
+            5, // relayout root.second
+        ))
+    }
 }
 
 private val UseChildSizeButNotPlace = object : LayoutNode.NoIntrinsicsMeasurePolicy("") {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
index 205b312..44ae78e 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/SubcomposeLayoutTest.kt
@@ -2382,7 +2382,10 @@
                 val content = if (showContent) {
                     subcompose(0) {
                         Box {
-                            AndroidView(::View, Modifier.fillMaxSize().testTag("AndroidView"))
+                            AndroidView(::View,
+                                Modifier
+                                    .fillMaxSize()
+                                    .testTag("AndroidView"))
                         }
                     }
                 } else emptyList()
@@ -2495,7 +2498,9 @@
                         Box {
                             SubcomposeLayout { constraints ->
                                 val placeable = measure(Unit, constraints) {
-                                    Box(modifier = Modifier.size(10.dp).then(measureCountModifier))
+                                    Box(modifier = Modifier
+                                        .size(10.dp)
+                                        .then(measureCountModifier))
 
                                     DisposableEffect(Unit) {
                                         val capturedSlotId = slotId
@@ -2539,6 +2544,42 @@
         }
     }
 
+    @Test
+    fun slotIsProperlyDeactivatedAfterUpdatingReusePolicy() {
+        var state by mutableStateOf(SubcomposeLayoutState(SubcomposeSlotReusePolicy(1)))
+        var shouldCompose by mutableStateOf(true)
+        var disposed = false
+        rule.setContent {
+            SubcomposeLayout(state) { constraints ->
+                val placeables = if (shouldCompose) {
+                    subcompose(Unit) {
+                        DisposableEffect(Unit) {
+                            onDispose {
+                                disposed = true
+                            }
+                        }
+                    }.map {
+                        it.measure(constraints)
+                    }
+                } else {
+                    emptyList()
+                }
+                layout(100, 100) {
+                    placeables.forEach { it.place(0, 0) }
+                }
+            }
+        }
+
+        rule.runOnIdle {
+            state = SubcomposeLayoutState(SubcomposeSlotReusePolicy(1))
+            shouldCompose = false
+        }
+
+        rule.runOnIdle {
+            assertThat(disposed).isTrue()
+        }
+    }
+
     private fun SubcomposeMeasureScope.measure(
         slotId: Any,
         constraints: Constraints,
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
index d052e2e..69554df 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/semantics/SemanticsTests.kt
@@ -58,8 +58,10 @@
 import androidx.compose.ui.test.onNodeWithContentDescription
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.TextLayoutResult
 import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
 import androidx.compose.ui.util.fastForEach
 import androidx.compose.ui.util.fastMap
 import androidx.compose.ui.zIndex
@@ -1145,6 +1147,39 @@
         assertEquals(
             AnnotatedString("hello"), newConfig.getOrNull(SemanticsProperties.OriginalText))
     }
+
+    @Test
+    fun testGetTextSizeFromTextLayoutResult() {
+        var density = Float.NaN
+        rule.setContent {
+            with(LocalDensity.current) {
+                density = 1.sp.toPx()
+            }
+            Surface {
+                Text(
+                    AnnotatedString("hello"),
+                    Modifier
+                        .testTag(TestTag),
+                    fontSize = 14.sp,
+                )
+            }
+        }
+
+        val config = rule.onNodeWithTag(TestTag, true).fetchSemanticsNode().config
+
+        val textLayoutResult: TextLayoutResult
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        val getLayoutResult = config[SemanticsActions.GetTextLayoutResult]
+            .action?.invoke(textLayoutResults)
+
+        assertEquals(true, getLayoutResult)
+
+        textLayoutResult = textLayoutResults[0]
+        val result = textLayoutResult.layoutInput
+
+        assertEquals(density, result.density.density)
+        assertEquals(14.0f, result.style.fontSize.value)
+    }
 }
 
 private fun SemanticsNodeInteraction.assertDoesNotHaveProperty(property: SemanticsPropertyKey<*>) {
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingListParityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingListParityTest.kt
index 18b6f6e..b5aa683 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingListParityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingListParityTest.kt
@@ -29,7 +29,6 @@
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.LazyListState
 import androidx.compose.material.Text
@@ -83,7 +82,7 @@
     }
 
     @Test
-    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem() = runBlocking {
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_smallVeryFast() = runBlocking {
         val state = LazyListState()
 
         // starting with view
@@ -91,7 +90,8 @@
         checkVisibility(composeView(), View.GONE)
         checkVisibility(recyclerView(), View.VISIBLE)
 
-        swipeView(R.id.view_list)
+        smallGestureVeryFast(R.id.view_list)
+        rule.waitForIdle()
         recyclerView().awaitScrollIdle()
 
         val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
@@ -117,7 +117,219 @@
         rule.runOnIdle {
             val currentTopInCompose = state.firstVisibleItemIndex
             val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
-            assertTrue("Difference was=$diff") { diff <= 3 }
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
+        }
+    }
+
+    @Test
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_smallFast() = runBlocking {
+        val state = LazyListState()
+
+        // starting with view
+        createActivity(state)
+        checkVisibility(composeView(), View.GONE)
+        checkVisibility(recyclerView(), View.VISIBLE)
+
+        smallGestureFast(R.id.view_list)
+        rule.waitForIdle()
+        recyclerView().awaitScrollIdle()
+
+        val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
+
+        // switch visibilities
+        rule.runOnUiThread {
+            rule.activity.findViewById<RecyclerView>(R.id.view_list).visibility = View.GONE
+            rule.activity.findViewById<ComposeView>(R.id.compose_view).visibility = View.VISIBLE
+        }
+
+        checkVisibility(composeView(), View.VISIBLE)
+        checkVisibility(recyclerView(), View.GONE)
+
+        assertTrue { isValidGesture(recyclerView().motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        rule.runOnUiThread {
+            for (event in recyclerView().motionEvents) {
+                composeView().dispatchTouchEvent(event)
+            }
+        }
+
+        rule.runOnIdle {
+            val currentTopInCompose = state.firstVisibleItemIndex
+            val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
+        }
+    }
+
+    @Test
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_smallSlow() = runBlocking {
+        val state = LazyListState()
+
+        // starting with view
+        createActivity(state)
+        checkVisibility(composeView(), View.GONE)
+        checkVisibility(recyclerView(), View.VISIBLE)
+
+        smallGestureSlow(R.id.view_list)
+        rule.waitForIdle()
+        recyclerView().awaitScrollIdle()
+
+        val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
+
+        // switch visibilities
+        rule.runOnUiThread {
+            rule.activity.findViewById<RecyclerView>(R.id.view_list).visibility = View.GONE
+            rule.activity.findViewById<ComposeView>(R.id.compose_view).visibility = View.VISIBLE
+        }
+
+        checkVisibility(composeView(), View.VISIBLE)
+        checkVisibility(recyclerView(), View.GONE)
+
+        assertTrue { isValidGesture(recyclerView().motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        rule.runOnUiThread {
+            for (event in recyclerView().motionEvents) {
+                composeView().dispatchTouchEvent(event)
+            }
+        }
+
+        rule.runOnIdle {
+            val currentTopInCompose = state.firstVisibleItemIndex
+            val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
+        }
+    }
+
+    @Test
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_largeFast() = runBlocking {
+        val state = LazyListState()
+
+        // starting with view
+        createActivity(state)
+        checkVisibility(composeView(), View.GONE)
+        checkVisibility(recyclerView(), View.VISIBLE)
+
+        largeGestureFast(R.id.view_list)
+        rule.waitForIdle()
+        recyclerView().awaitScrollIdle()
+
+        val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
+
+        // switch visibilities
+        rule.runOnUiThread {
+            rule.activity.findViewById<RecyclerView>(R.id.view_list).visibility = View.GONE
+            rule.activity.findViewById<ComposeView>(R.id.compose_view).visibility = View.VISIBLE
+        }
+
+        checkVisibility(composeView(), View.VISIBLE)
+        checkVisibility(recyclerView(), View.GONE)
+
+        assertTrue { isValidGesture(recyclerView().motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        rule.runOnUiThread {
+            for (event in recyclerView().motionEvents) {
+                composeView().dispatchTouchEvent(event)
+            }
+        }
+
+        rule.runOnIdle {
+            val currentTopInCompose = state.firstVisibleItemIndex
+            val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
+        }
+    }
+
+    @Test
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_largeVeryFast() = runBlocking {
+        val state = LazyListState()
+
+        // starting with view
+        createActivity(state)
+        checkVisibility(composeView(), View.GONE)
+        checkVisibility(recyclerView(), View.VISIBLE)
+
+        largeGestureVeryFast(R.id.view_list)
+        rule.waitForIdle()
+        recyclerView().awaitScrollIdle()
+
+        val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
+
+        // switch visibilities
+        rule.runOnUiThread {
+            rule.activity.findViewById<RecyclerView>(R.id.view_list).visibility = View.GONE
+            rule.activity.findViewById<ComposeView>(R.id.compose_view).visibility = View.VISIBLE
+        }
+
+        checkVisibility(composeView(), View.VISIBLE)
+        checkVisibility(recyclerView(), View.GONE)
+
+        assertTrue { isValidGesture(recyclerView().motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        rule.runOnUiThread {
+            for (event in recyclerView().motionEvents) {
+                composeView().dispatchTouchEvent(event)
+            }
+        }
+
+        rule.runOnIdle {
+            val currentTopInCompose = state.firstVisibleItemIndex
+            val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
+        }
+    }
+
+    @Test
+    fun equalLists_withEqualFlings_shouldFinishAtTheSameItem_orthogonal() = runBlocking {
+        val state = LazyListState()
+
+        // starting with view
+        createActivity(state)
+        checkVisibility(composeView(), View.GONE)
+        checkVisibility(recyclerView(), View.VISIBLE)
+
+        orthogonalGesture(R.id.view_list)
+        rule.waitForIdle()
+        recyclerView().awaitScrollIdle()
+
+        val childAtTheTopOfView = layoutManager?.findFirstVisibleItemPosition() ?: 0
+
+        // switch visibilities
+        rule.runOnUiThread {
+            rule.activity.findViewById<RecyclerView>(R.id.view_list).visibility = View.GONE
+            rule.activity.findViewById<ComposeView>(R.id.compose_view).visibility = View.VISIBLE
+        }
+
+        checkVisibility(composeView(), View.VISIBLE)
+        checkVisibility(recyclerView(), View.GONE)
+
+        assertTrue { isValidGesture(recyclerView().motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        rule.runOnUiThread {
+            for (event in recyclerView().motionEvents) {
+                composeView().dispatchTouchEvent(event)
+            }
+        }
+
+        rule.runOnIdle {
+            val currentTopInCompose = state.firstVisibleItemIndex
+            val diff = (currentTopInCompose - childAtTheTopOfView).absoluteValue
+            val message = "Compose=$currentTopInCompose View=$childAtTheTopOfView " +
+                "Difference was=$diff"
+            assertTrue(message) { diff <= ItemDifferenceThreshold }
         }
     }
 
@@ -171,22 +383,16 @@
             view.visibility == visibility
         }
     }
-
-    private fun swipeView(id: Int) {
-        controlledSwipeUp(id)
-        rule.waitForIdle()
-    }
 }
 
 @Composable
 fun TestComposeList(state: LazyListState) {
     LazyColumn(Modifier.fillMaxSize(), state = state) {
-        items(200) {
+        items(1000) {
             Box(
                 modifier = Modifier
                     .fillMaxWidth()
                     .height(64.dp)
-                    .padding(2.dp)
                     .background(Color.Black)
             ) {
                 Text(text = it.toString(), color = Color.White)
@@ -196,7 +402,7 @@
 }
 
 private class ListAdapter : RecyclerView.Adapter<ListViewHolder>() {
-    val items = (0 until 200).map { it.toString() }
+    val items = (0 until 1000).map { it.toString() }
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
         return ListViewHolder(
             LayoutInflater.from(parent.context)
@@ -250,3 +456,5 @@
         }
     }
 }
+
+private const val ItemDifferenceThreshold = 3
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingParityTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingParityTest.kt
index 5663ea1..124d13f 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingParityTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/viewinterop/VelocityTrackingParityTest.kt
@@ -24,34 +24,53 @@
 import androidx.activity.ComponentActivity
 import androidx.annotation.LayoutRes
 import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.awaitEachGesture
+import androidx.compose.foundation.gestures.awaitFirstDown
+import androidx.compose.foundation.gestures.awaitTouchSlopOrCancellation
 import androidx.compose.foundation.gestures.draggable
 import androidx.compose.foundation.gestures.rememberDraggableState
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.background
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.AwaitPointerEventScope
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.PointerId
+import androidx.compose.ui.input.pointer.PointerInputChange
+import androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.input.pointer.positionChangedIgnoreConsumed
 import androidx.compose.ui.input.pointer.util.VelocityTrackerAddPointsFix
+import androidx.compose.ui.input.pointer.util.addPointerInputChange
 import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.platform.ViewConfiguration
 import androidx.compose.ui.test.junit4.createAndroidComposeRule
 import androidx.compose.ui.tests.R
 import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.util.fastFirstOrNull
 import androidx.lifecycle.Lifecycle
 import androidx.test.core.app.ActivityScenario
 import androidx.test.espresso.Espresso
+import androidx.test.espresso.UiController
 import androidx.test.espresso.action.CoordinatesProvider
 import androidx.test.espresso.action.GeneralLocation
 import androidx.test.espresso.action.GeneralSwipeAction
+import androidx.test.espresso.action.MotionEvents
 import androidx.test.espresso.action.Press
-import androidx.test.espresso.action.Swipe
+import androidx.test.espresso.action.Swiper
 import androidx.test.espresso.matcher.ViewMatchers.withId
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import com.google.common.truth.Truth.assertThat
+import com.google.errorprone.annotations.CanIgnoreReturnValue
+import kotlin.math.absoluteValue
 import kotlin.test.assertTrue
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.coroutineScope
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -70,12 +89,12 @@
     private val composeView: ComposeView
         get() = rule.activity.findViewById(R.id.compose_view)
 
-    private var latestComposeVelocity = 0f
+    private var latestComposeVelocity = Velocity.Zero
 
     @OptIn(ExperimentalComposeUiApi::class)
     @Before
     fun setUp() {
-        latestComposeVelocity = 0f
+        latestComposeVelocity = Velocity.Zero
         VelocityTrackerAddPointsFix = true
     }
 
@@ -84,16 +103,17 @@
     }
 
     @Test
-    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity() {
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_smallVeryFast() {
         // Arrange
         createActivity()
         checkVisibility(composeView, View.GONE)
         checkVisibility(draggableView, View.VISIBLE)
 
         // Act: Use system to send motion events and collect them.
-        swipeView(R.id.draggable_view)
+        smallGestureVeryFast(R.id.draggable_view)
 
-        val latestVelocityInView = draggableView.latestVelocity.y
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
 
         // switch visibility
         rule.runOnUiThread {
@@ -110,21 +130,189 @@
         for (event in draggableView.motionEvents) {
             composeView.dispatchTouchEvent(event)
         }
-        val latestVelocityInCompose = latestComposeVelocity
 
-        val diff = kotlin.math.abs(latestVelocityInView - latestVelocityInCompose)
         // assert
-        assertThat(diff).isWithin(VelocityDifferenceTolerance * latestVelocityInView)
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
     }
 
-    private fun createActivity() {
+    @Test
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_smallFast() {
+        // Arrange
+        createActivity()
+        checkVisibility(composeView, View.GONE)
+        checkVisibility(draggableView, View.VISIBLE)
+
+        // Act: Use system to send motion events and collect them.
+        smallGestureFast(R.id.draggable_view)
+
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
+
+        // switch visibility
+        rule.runOnUiThread {
+            composeView.visibility = View.VISIBLE
+            draggableView.visibility = View.GONE
+        }
+
+        checkVisibility(composeView, View.VISIBLE)
+        checkVisibility(draggableView, View.GONE)
+
+        assertTrue { isValidGesture(draggableView.motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        for (event in draggableView.motionEvents) {
+            composeView.dispatchTouchEvent(event)
+        }
+
+        // assert
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
+    }
+
+    @Test
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_smallSlow() {
+        // Arrange
+        createActivity()
+        checkVisibility(composeView, View.GONE)
+        checkVisibility(draggableView, View.VISIBLE)
+
+        // Act: Use system to send motion events and collect them.
+        smallGestureSlow(R.id.draggable_view)
+
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
+
+        // switch visibility
+        rule.runOnUiThread {
+            composeView.visibility = View.VISIBLE
+            draggableView.visibility = View.GONE
+        }
+
+        checkVisibility(composeView, View.VISIBLE)
+        checkVisibility(draggableView, View.GONE)
+
+        assertTrue { isValidGesture(draggableView.motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        for (event in draggableView.motionEvents) {
+            composeView.dispatchTouchEvent(event)
+        }
+        // assert
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
+    }
+
+    @Test
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_largeFast() {
+        // Arrange
+        createActivity()
+        checkVisibility(composeView, View.GONE)
+        checkVisibility(draggableView, View.VISIBLE)
+
+        // Act: Use system to send motion events and collect them.
+        largeGestureFast(R.id.draggable_view)
+
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
+
+        // switch visibility
+        rule.runOnUiThread {
+            composeView.visibility = View.VISIBLE
+            draggableView.visibility = View.GONE
+        }
+
+        checkVisibility(composeView, View.VISIBLE)
+        checkVisibility(draggableView, View.GONE)
+
+        assertTrue { isValidGesture(draggableView.motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        for (event in draggableView.motionEvents) {
+            composeView.dispatchTouchEvent(event)
+        }
+
+        // assert
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
+    }
+
+    @Test
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_largeVeryFast() {
+        // Arrange
+        createActivity()
+        checkVisibility(composeView, View.GONE)
+        checkVisibility(draggableView, View.VISIBLE)
+
+        // Act: Use system to send motion events and collect them.
+        largeGestureVeryFast(R.id.draggable_view)
+
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
+
+        // switch visibility
+        rule.runOnUiThread {
+            composeView.visibility = View.VISIBLE
+            draggableView.visibility = View.GONE
+        }
+
+        checkVisibility(composeView, View.VISIBLE)
+        checkVisibility(draggableView, View.GONE)
+
+        assertTrue { isValidGesture(draggableView.motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        for (event in draggableView.motionEvents) {
+            composeView.dispatchTouchEvent(event)
+        }
+
+        // assert
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
+    }
+
+    @Test
+    fun equalDraggable_withEqualSwipes_shouldProduceSimilarVelocity_orthogonal() {
+        // Arrange
+        createActivity(true)
+        checkVisibility(composeView, View.GONE)
+        checkVisibility(draggableView, View.VISIBLE)
+
+        // Act: Use system to send motion events and collect them.
+        orthogonalGesture(R.id.draggable_view)
+
+        val latestVelocityInViewX = draggableView.latestVelocity.x
+        val latestVelocityInViewY = draggableView.latestVelocity.y
+
+        // switch visibility
+        rule.runOnUiThread {
+            composeView.visibility = View.VISIBLE
+            draggableView.visibility = View.GONE
+        }
+
+        checkVisibility(composeView, View.VISIBLE)
+        checkVisibility(draggableView, View.GONE)
+
+        assertTrue { isValidGesture(draggableView.motionEvents.filterNotNull()) }
+
+        // Inject the same events in compose view
+        for (event in draggableView.motionEvents) {
+            composeView.dispatchTouchEvent(event)
+        }
+
+        // assert
+        assertIsWithinTolerance(latestComposeVelocity.x, latestVelocityInViewX)
+        assertIsWithinTolerance(latestComposeVelocity.y, latestVelocityInViewY)
+    }
+
+    private fun createActivity(twoDimensional: Boolean = false) {
         rule
             .activityRule
             .scenario
             .createActivityWithComposeContent(
                 R.layout.velocity_tracker_compose_vs_view
             ) {
-                TestComposeDraggable {
+                TestComposeDraggable(twoDimensional) {
                     latestComposeVelocity = it
                 }
             }
@@ -134,46 +322,154 @@
         view.visibility == visibility
     }
 
-    private fun swipeView(id: Int) {
-        controlledSwipeUp(id)
-        rule.waitForIdle()
+    private fun assertIsWithinTolerance(composeVelocity: Float, viewVelocity: Float) {
+        if (composeVelocity.absoluteValue > 1f && viewVelocity.absoluteValue > 1f) {
+            val tolerance = VelocityDifferenceTolerance * kotlin.math.abs(viewVelocity)
+            assertThat(composeVelocity).isWithin(tolerance).of(viewVelocity)
+        } else {
+            assertThat(composeVelocity.toInt()).isEqualTo(viewVelocity.toInt())
+        }
     }
 }
 
-internal fun controlledSwipeUp(id: Int) {
+internal fun smallGestureVeryFast(id: Int) {
     Espresso.onView(withId(id))
         .perform(
             espressoSwipe(
+                SwiperWithTime(15),
                 GeneralLocation.CENTER,
-                GeneralLocation.TOP_CENTER
+                GeneralLocation.translate(GeneralLocation.CENTER, 0f, -50f)
+            )
+        )
+}
+
+internal fun smallGestureFast(id: Int) {
+    Espresso.onView(withId(id))
+        .perform(
+            espressoSwipe(
+                SwiperWithTime(25),
+                GeneralLocation.CENTER,
+                GeneralLocation.translate(GeneralLocation.CENTER, 0f, -50f)
+            )
+        )
+}
+
+internal fun smallGestureSlow(id: Int) {
+    Espresso.onView(withId(id))
+        .perform(
+            espressoSwipe(
+                SwiperWithTime(200),
+                GeneralLocation.CENTER,
+                GeneralLocation.translate(GeneralLocation.CENTER, 0f, -50f)
+            )
+        )
+}
+
+internal fun largeGestureFast(id: Int) {
+    Espresso.onView(withId(id))
+        .perform(
+            espressoSwipe(
+                SwiperWithTime(25),
+                GeneralLocation.CENTER,
+                GeneralLocation.translate(GeneralLocation.CENTER, 0f, -500f)
+            )
+        )
+}
+
+internal fun largeGestureVeryFast(id: Int) {
+    Espresso.onView(withId(id))
+        .perform(
+            espressoSwipe(
+                SwiperWithTime(15),
+                GeneralLocation.CENTER,
+                GeneralLocation.translate(GeneralLocation.CENTER, 0f, -500f)
+            )
+        )
+}
+
+internal fun orthogonalGesture(id: Int) {
+    Espresso.onView(withId(id))
+        .perform(
+            espressoSwipe(
+                SwiperWithTime(50),
+                GeneralLocation.CENTER,
+                GeneralLocation.translate(GeneralLocation.CENTER, -200f, -200f)
             )
         )
 }
 
 private fun espressoSwipe(
+    swiper: Swiper,
     start: CoordinatesProvider,
     end: CoordinatesProvider
 ): GeneralSwipeAction {
     return GeneralSwipeAction(
-        Swipe.FAST, start, end,
+        swiper, start, end,
         Press.FINGER
     )
 }
 
 @Composable
-fun TestComposeDraggable(onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit) {
-    Box(
-        Modifier
-            .fillMaxSize()
-            .background(Color.Black)
-            .draggable(
-                rememberDraggableState(onDelta = { }),
-                onDragStopped = onDragStopped,
-                orientation = Orientation.Vertical
-            )
-    )
+fun TestComposeDraggable(
+    twoDimensional: Boolean = false,
+    onDragStopped: (velocity: Velocity) -> Unit
+) {
+    val viewConfiguration = object : ViewConfiguration by LocalViewConfiguration.current {
+        override val maximumFlingVelocity: Int
+            get() = Int.MAX_VALUE // unlimited
+    }
+    CompositionLocalProvider(LocalViewConfiguration provides viewConfiguration) {
+        Box(
+            Modifier
+                .fillMaxSize()
+                .background(Color.Black)
+                .then(
+                    if (twoDimensional) {
+                        Modifier.draggable2D(onDragStopped)
+                    } else {
+                        Modifier.draggable(
+                            rememberDraggableState(onDelta = { }),
+                            onDragStopped = { onDragStopped.invoke(Velocity(0.0f, it)) },
+                            orientation = Orientation.Vertical
+                        )
+                    }
+                )
+        )
+    }
 }
 
+fun Modifier.draggable2D(onDragStopped: (Velocity) -> Unit) =
+    this.pointerInput(Unit) {
+        coroutineScope {
+            awaitEachGesture {
+                val tracker = androidx.compose.ui.input.pointer.util.VelocityTracker()
+                val initialDown =
+                    awaitFirstDown(
+                        requireUnconsumed = false,
+                        pass = PointerEventPass.Initial
+                    )
+                tracker.addPointerInputChange(initialDown)
+
+                awaitTouchSlopOrCancellation(initialDown.id) { change, _ ->
+                    tracker.addPointerInputChange(change)
+                    change.consume()
+                }
+
+                val lastEvent = awaitDragOrUp(initialDown.id) {
+                    tracker.addPointerInputChange(it)
+                    it.consume()
+                    it.positionChangedIgnoreConsumed()
+                }
+                lastEvent?.let {
+                    tracker.addPointerInputChange(it)
+                }
+                onDragStopped(
+                    tracker.calculateVelocity()
+                )
+            }
+        }
+    }
+
 private fun ActivityScenario<*>.createActivityWithComposeContent(
     @LayoutRes layout: Int,
     content: @Composable () -> Unit,
@@ -237,4 +533,115 @@
 }
 
 // 1% tolerance
-private const val VelocityDifferenceTolerance = 0.01f
+private const val VelocityDifferenceTolerance = 0.1f
+
+/**
+ * Copied from androidx.test.espresso.action.Swipe
+ */
+internal data class SwiperWithTime(val gestureDurationMs: Int) : Swiper {
+    override fun sendSwipe(
+        uiController: UiController,
+        startCoordinates: FloatArray,
+        endCoordinates: FloatArray,
+        precision: FloatArray
+    ): Swiper.Status {
+        return sendLinearSwipe(
+            uiController,
+            startCoordinates,
+            endCoordinates,
+            precision,
+            gestureDurationMs
+        )
+    }
+
+    private fun checkElementIndex(index: Int, size: Int): Int {
+        return checkElementIndex(index, size, "index")
+    }
+
+    @CanIgnoreReturnValue
+    private fun checkElementIndex(index: Int, size: Int, desc: String): Int {
+        // Carefully optimized for execution by hotspot (explanatory comment above)
+        if (index < 0 || index >= size) {
+            throw IndexOutOfBoundsException(badElementIndex(index, size, desc))
+        }
+        return index
+    }
+
+    private fun badElementIndex(index: Int, size: Int, desc: String): String {
+        return if (index < 0) {
+            String.format("%s (%s) must not be negative", desc, index)
+        } else if (size < 0) {
+            throw IllegalArgumentException("negative size: $size")
+        } else { // index >= size
+            String.format("%s (%s) must be less than size (%s)", desc, index, size)
+        }
+    }
+
+    private fun interpolate(start: FloatArray, end: FloatArray, steps: Int): Array<FloatArray> {
+        checkElementIndex(1, start.size)
+        checkElementIndex(1, end.size)
+        val res = Array(steps) {
+            FloatArray(
+                2
+            )
+        }
+        for (i in 1 until steps + 1) {
+            res[i - 1][0] = start[0] + (end[0] - start[0]) * i / (steps + 2f)
+            res[i - 1][1] = start[1] + (end[1] - start[1]) * i / (steps + 2f)
+        }
+        return res
+    }
+
+    private fun sendLinearSwipe(
+        uiController: UiController,
+        startCoordinates: FloatArray,
+        endCoordinates: FloatArray,
+        precision: FloatArray,
+        duration: Int
+    ): Swiper.Status {
+        val steps = interpolate(startCoordinates, endCoordinates, 10)
+        val events: MutableList<MotionEvent> = ArrayList()
+        val downEvent = MotionEvents.obtainDownEvent(startCoordinates, precision)
+        events.add(downEvent)
+        try {
+            val intervalMS = (duration / steps.size).toLong()
+            var eventTime = downEvent.downTime
+            for (step in steps) {
+                eventTime += intervalMS
+                events.add(MotionEvents.obtainMovement(downEvent, eventTime, step))
+            }
+            eventTime += intervalMS
+            events.add(MotionEvents.obtainUpEvent(downEvent, eventTime, endCoordinates))
+            uiController.injectMotionEventSequence(events)
+        } catch (e: Exception) {
+            return Swiper.Status.FAILURE
+        } finally {
+            for (event in events) {
+                event.recycle()
+            }
+        }
+        return Swiper.Status.SUCCESS
+    }
+}
+
+private suspend inline fun AwaitPointerEventScope.awaitDragOrUp(
+    pointerId: PointerId,
+    hasDragged: (PointerInputChange) -> Boolean
+): PointerInputChange? {
+    var pointer = pointerId
+    while (true) {
+        val event = awaitPointerEvent()
+        val dragEvent = event.changes.fastFirstOrNull { it.id == pointer } ?: return null
+        if (dragEvent.changedToUpIgnoreConsumed()) {
+            val otherDown = event.changes.fastFirstOrNull { it.pressed }
+            if (otherDown == null) {
+                // This is the last "up"
+                return dragEvent
+            } else {
+                pointer = otherDown.id
+            }
+        } else if (hasDragged(dragEvent)) {
+            return dragEvent
+        }
+    }
+}
diff --git a/compose/ui/ui/src/main/res/layout/android_compose_lists_fling.xml b/compose/ui/ui/src/androidAndroidTest/res/layout/android_compose_lists_fling.xml
similarity index 100%
rename from compose/ui/ui/src/main/res/layout/android_compose_lists_fling.xml
rename to compose/ui/ui/src/androidAndroidTest/res/layout/android_compose_lists_fling.xml
diff --git a/compose/ui/ui/src/main/res/layout/android_compose_lists_fling_item.xml b/compose/ui/ui/src/androidAndroidTest/res/layout/android_compose_lists_fling_item.xml
similarity index 96%
rename from compose/ui/ui/src/main/res/layout/android_compose_lists_fling_item.xml
rename to compose/ui/ui/src/androidAndroidTest/res/layout/android_compose_lists_fling_item.xml
index bbcfe5a..50744cd 100644
--- a/compose/ui/ui/src/main/res/layout/android_compose_lists_fling_item.xml
+++ b/compose/ui/ui/src/androidAndroidTest/res/layout/android_compose_lists_fling_item.xml
@@ -18,7 +18,6 @@
     android:layout_width="match_parent"
     android:background="@android:color/black"
     android:layout_height="64dp"
-    android:layout_margin="2dp"
     android:orientation="vertical">
 
     <TextView
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/ComposeDragShadowBuilder.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/ComposeDragShadowBuilder.kt
new file mode 100644
index 0000000..f0ebab1
--- /dev/null
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/ComposeDragShadowBuilder.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2023 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.draganddrop
+
+import android.graphics.Canvas as AndroidCanvas
+import android.graphics.Point
+import android.view.View
+import androidx.compose.ui.graphics.Canvas
+import androidx.compose.ui.graphics.drawscope.CanvasDrawScope
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.LayoutDirection
+
+/**
+ * Draws a drag shadow for a [View.DragShadowBuilder] with a [Painter].
+ * If there is no painter provided in [dragAndDropInfo], it will attempt to create a default by trying to
+ * copy pixels in the rect bounded by the dragged item.
+ */
+internal class ComposeDragShadowBuilder(
+    private val density: Density,
+    private val dragAndDropInfo: DragAndDropInfo,
+) : View.DragShadowBuilder() {
+
+    override fun onProvideShadowMetrics(
+        outShadowSize: Point,
+        outShadowTouchPoint: Point
+    ) = with(density) {
+        outShadowSize.set(
+            dragAndDropInfo.size.width.toDp().roundToPx(),
+            dragAndDropInfo.size.height.toDp().roundToPx()
+        )
+        outShadowTouchPoint.set(
+            outShadowSize.x / 2,
+            outShadowSize.y / 2
+        )
+    }
+
+    override fun onDrawShadow(canvas: AndroidCanvas) {
+        CanvasDrawScope().draw(
+            density = density,
+            size = dragAndDropInfo.size,
+            layoutDirection = LayoutDirection.Ltr,
+            canvas = Canvas(canvas),
+            block = dragAndDropInfo.onDrawDragShadow,
+        )
+    }
+}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.android.kt
new file mode 100644
index 0000000..dfe7d4e
--- /dev/null
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.android.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 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.draganddrop
+
+import android.content.ClipData
+import android.view.DragEvent
+import android.view.View
+import androidx.compose.ui.geometry.Offset
+
+/**
+ * [DragAndDropTransfer] representation for the Android platform.
+ * It provides the [ClipData] required for drag and drop.
+ */
+actual class DragAndDropTransfer(
+    /**
+     * The [ClipData] being transferred.
+     */
+    val clipData: ClipData,
+    /**
+     * Optional local state for the DnD operation
+     * @see [View.startDragAndDrop]
+     */
+    val localState: Any? = null,
+    /**
+     * Flags for the drag and drop operation.
+     * @see [View.startDragAndDrop]
+     */
+    val flags: Int = 0,
+)
+
+/**
+ * Android [DragAndDropEvent] which delegates to a [DragEvent]
+ */
+actual class DragAndDropEvent(
+    /**
+     * An indication of the reason the drag and drop event was sent
+     */
+    actual var type: DragAndDropEventType,
+    internal var dragEvent: DragEvent
+)
+
+/**
+ * Returns the backing [DragEvent] to read platform specific data
+ */
+val DragAndDropEvent.dragEvent get() = this.dragEvent
+
+internal actual val DragAndDropEvent.positionInRoot: Offset
+    get() = Offset(
+        x = dragEvent.x,
+        y = dragEvent.y
+    )
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.android.kt
new file mode 100644
index 0000000..8c3e583
--- /dev/null
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.android.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023 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.input.rotary
+
+/**
+ * This event represents a rotary input event.
+ *
+ * Some Wear OS devices contain a physical rotating side button, or a rotating bezel. When the user
+ * turns the button or rotates the bezel, a [RotaryScrollEvent] is sent to the item in focus.
+ */
+actual class RotaryScrollEvent internal constructor(
+    /**
+     * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
+     * can scroll vertically.
+     */
+    actual val verticalScrollPixels: Float,
+
+    /**
+     * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
+     * can scroll horizontally.
+     */
+    actual val horizontalScrollPixels: Float,
+
+    /**
+     * The time in milliseconds at which this even occurred. The start (`0`) time is
+     * platform-dependent.
+     */
+    actual val uptimeMillis: Long,
+
+    /**
+     * The id for the input device that this event came from
+     */
+    val inputDeviceId: Int
+) {
+    override fun equals(other: Any?): Boolean = other is RotaryScrollEvent &&
+        other.verticalScrollPixels == verticalScrollPixels &&
+        other.horizontalScrollPixels == horizontalScrollPixels &&
+        other.uptimeMillis == uptimeMillis &&
+        other.inputDeviceId == inputDeviceId
+
+    override fun hashCode(): Int = 0
+        .let { verticalScrollPixels.hashCode() }
+        .let { 31 * it + horizontalScrollPixels.hashCode() }
+        .let { 31 * it + uptimeMillis.hashCode() }
+        .let { 31 * it + inputDeviceId.hashCode() }
+
+    override fun toString(): String = "RotaryScrollEvent(" +
+        "verticalScrollPixels=$verticalScrollPixels," +
+        "horizontalScrollPixels=$horizontalScrollPixels," +
+        "uptimeMillis=$uptimeMillis," +
+        "deviceId=$inputDeviceId)"
+}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
index 2f3b345..ef354a4 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
@@ -69,6 +69,8 @@
 import androidx.compose.ui.autofill.AutofillTree
 import androidx.compose.ui.autofill.performAutofill
 import androidx.compose.ui.autofill.populateViewStructure
+import androidx.compose.ui.draganddrop.ComposeDragShadowBuilder
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusDirection.Companion.Down
 import androidx.compose.ui.focus.FocusDirection.Companion.Exit
@@ -659,7 +661,7 @@
      * This function is used by the testing framework to send key events.
      */
     override fun sendKeyEvent(keyEvent: KeyEvent): Boolean =
-        // First dispatch the key event to mimic the event being intercepted before it is sent to
+    // First dispatch the key event to mimic the event being intercepted before it is sent to
         // the soft keyboard.
         focusOwner.dispatchInterceptedSoftKeyboardEvent(keyEvent) ||
             // Next, send the key event to the Soft Keyboard.
@@ -735,6 +737,32 @@
         }
     }
 
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        val density = with(context.resources) {
+            Density(
+                density = displayMetrics.density,
+                fontScale = configuration.fontScale
+            )
+        }
+        val shadowBuilder = ComposeDragShadowBuilder(
+            density = density,
+            dragAndDropInfo = dragAndDropInfo,
+        )
+        @Suppress("DEPRECATION")
+        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+            AndroidComposeViewStartDragAndDropN.startDragAndDrop(
+                view = this,
+                dragAndDropInfo = dragAndDropInfo,
+                dragShadowBuilder = shadowBuilder,
+            )
+        else startDrag(
+            dragAndDropInfo.transfer.clipData,
+            shadowBuilder,
+            dragAndDropInfo.transfer.localState,
+            dragAndDropInfo.transfer.flags,
+        )
+    }
+
     private fun clearChildInvalidObservations(viewGroup: ViewGroup) {
         for (i in 0 until viewGroup.childCount) {
             val child = viewGroup.getChildAt(i)
@@ -1007,6 +1035,7 @@
 
     @Suppress("NOTHING_TO_INLINE")
     private inline operator fun ULong.component1() = (this shr 32).toInt()
+
     @Suppress("NOTHING_TO_INLINE")
     private inline operator fun ULong.component2() = (this and 0xFFFFFFFFUL).toInt()
 
@@ -1399,7 +1428,8 @@
         val rotaryEvent = RotaryScrollEvent(
             verticalScrollPixels = axisValue * getScaledVerticalScrollFactor(config, context),
             horizontalScrollPixels = axisValue * getScaledHorizontalScrollFactor(config, context),
-            uptimeMillis = event.eventTime
+            uptimeMillis = event.eventTime,
+            inputDeviceId = event.deviceId
         )
         return focusOwner.dispatchRotaryEvent(rotaryEvent)
     }
@@ -2153,3 +2183,19 @@
         return event.getRawX(index).isFinite() && event.getRawY(index).isFinite()
     }
 }
+
+@RequiresApi(Build.VERSION_CODES.N)
+private object AndroidComposeViewStartDragAndDropN {
+    @DoNotInline
+    @RequiresApi(Build.VERSION_CODES.N)
+    fun startDragAndDrop(
+        view: View,
+        dragAndDropInfo: DragAndDropInfo,
+        dragShadowBuilder: ComposeDragShadowBuilder
+    ): Boolean = view.startDragAndDrop(
+        dragAndDropInfo.transfer.clipData,
+        dragShadowBuilder,
+        dragAndDropInfo.transfer.localState,
+        dragAndDropInfo.transfer.flags,
+    )
+}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
index f4deee8..18e0502 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
@@ -17,6 +17,7 @@
 package androidx.compose.ui.platform
 
 import android.accessibilityservice.AccessibilityServiceInfo
+import android.annotation.SuppressLint
 import android.content.Context
 import android.graphics.RectF
 import android.graphics.Region
@@ -65,6 +66,9 @@
 import androidx.compose.ui.platform.accessibility.hasCollectionInfo
 import androidx.compose.ui.platform.accessibility.setCollectionInfo
 import androidx.compose.ui.platform.accessibility.setCollectionItemInfo
+import androidx.compose.ui.platform.coreshims.ContentCaptureSessionCompat
+import androidx.compose.ui.platform.coreshims.ViewCompatShims
+import androidx.compose.ui.platform.coreshims.ViewStructureCompat
 import androidx.compose.ui.semantics.AccessibilityAction
 import androidx.compose.ui.semantics.CustomAccessibilityAction
 import androidx.compose.ui.semantics.LiveRegionMode
@@ -96,12 +100,10 @@
 import androidx.core.view.ViewCompat
 import androidx.core.view.ViewCompat.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
 import androidx.core.view.ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE
-import androidx.core.view.ViewStructureCompat
 import androidx.core.view.accessibility.AccessibilityEventCompat
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat
 import androidx.core.view.accessibility.AccessibilityNodeProviderCompat
-import androidx.core.view.contentcapture.ContentCaptureSessionCompat
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
@@ -788,10 +790,16 @@
         info.packageName = view.context.packageName
 
         // This property exists to distinguish semantically meaningful nodes from purely structural
-        // or decorative UI elements. In Compose, LayoutNodes without semantics are simply omitted
-        // from the AccessibilityNodeInfo tree. Therefore, every AccessibilityNodeInfo qualifies as
-        // "important".
-        info.isImportantForAccessibility = true
+        // or decorative UI elements.  Most nodes are considered important, except:
+        // * Non-merging nodes with only non-accessibility-speakable properties.
+        //     * Of the built-in ones, the key example is testTag.
+        //     * Custom SemanticsPropertyKeys defined outside the UI package
+        //       are also non-speakable.
+        // * Non-merging nodes that are empty: notably, clearAndSetSemantics {}
+        //   and the root of the SemanticsNode tree.
+        info.isImportantForAccessibility =
+            semanticsNode.unmergedConfig.isMergingSemanticsOfDescendants ||
+            semanticsNode.unmergedConfig.containsImportantForAccessibility()
 
         semanticsNode.replacedChildren.fastForEach { child ->
             if (currentSemanticsNodes.contains(child.id)) {
@@ -1243,14 +1251,15 @@
         val afterId = idToAfterMap[virtualViewId]
         afterId?.let {
             val afterView = view.androidViewsHandler.semanticsIdToView(afterId)
+            // Specially use `traversalAfter` value if the node after is a View,
+            // as expressing the order using traversalBefore in this case would require mutating the
+            // View itself, which is not under Compose's full control.
             if (afterView != null) {
                 info.setTraversalAfter(afterView)
-            } else {
-                info.setTraversalAfter(view, afterId)
+                addExtraDataToAccessibilityNodeInfoHelper(
+                    virtualViewId, info.unwrap(), EXTRA_DATA_TEST_TRAVERSALAFTER_VAL, null
+                )
             }
-            addExtraDataToAccessibilityNodeInfoHelper(
-                virtualViewId, info.unwrap(), EXTRA_DATA_TEST_TRAVERSALAFTER_VAL, null
-            )
         }
     }
 
@@ -1711,6 +1720,10 @@
                 }
 
                 val viewport = node.layoutInfo.coordinates.boundsInParent().size
+
+                // The lint warning text is unstable because anonymous lambdas have an autogenerated
+                // name, so suppress this lint warning with @SuppressLint instead of a baseline.
+                @SuppressLint("PrimitiveInLambda")
                 val scrollAction =
                     node.unmergedConfig.getOrNull(SemanticsActions.ScrollBy) ?: return false
 
@@ -1935,16 +1948,7 @@
                 Log.e(LogTag, "Invalid arguments for accessibility character locations")
                 return
             }
-            val textLayoutResults = mutableListOf<TextLayoutResult>()
-            // Note now it only works for single Text/TextField until we fix b/157474582.
-            val getLayoutResult = node.unmergedConfig[SemanticsActions.GetTextLayoutResult]
-                .action?.invoke(textLayoutResults)
-            val textLayoutResult: TextLayoutResult
-            if (getLayoutResult == true) {
-                textLayoutResult = textLayoutResults[0]
-            } else {
-                return
-            }
+            val textLayoutResult = getTextLayoutResult(node.unmergedConfig) ?: return
             val boundingRects = mutableListOf<RectF?>()
             for (i in 0 until positionInfoLength) {
                 // This is a workaround until we fix the merging issue in b/157474582.
@@ -2762,8 +2766,22 @@
     }
 
     private fun View.getContentCaptureSessionCompat(): ContentCaptureSessionCompat? {
-        ViewCompat.setImportantForContentCapture(this, ViewCompat.IMPORTANT_FOR_CONTENT_CAPTURE_YES)
-        return ViewCompat.getContentCaptureSession(this)
+        ViewCompatShims.setImportantForContentCapture(
+            this,
+            ViewCompatShims.IMPORTANT_FOR_CONTENT_CAPTURE_YES
+        )
+        return ViewCompatShims.getContentCaptureSession(this)
+    }
+
+    private fun getTextLayoutResult(configuration: SemanticsConfiguration): TextLayoutResult? {
+        val textLayoutResults = mutableListOf<TextLayoutResult>()
+        val getLayoutResult = configuration.getOrNull(SemanticsActions.GetTextLayoutResult)
+            ?.action?.invoke(textLayoutResults) ?: return null
+        return if (getLayoutResult) {
+            textLayoutResults[0]
+        } else {
+            null
+        }
     }
 
     private fun SemanticsNode.toViewStructure(): ViewStructureCompat? {
@@ -2772,7 +2790,7 @@
             return null
         }
 
-        val rootAutofillId = ViewCompat.getAutofillId(view) ?: return null
+        val rootAutofillId = ViewCompatShims.getAutofillId(view) ?: return null
         val parentNode = parent
         val parentAutofillId = if (parentNode != null) {
             session.newAutofillId(parentNode.id.toLong()) ?: return null
@@ -2802,6 +2820,12 @@
             structure.setClassName(it)
         }
 
+        getTextLayoutResult(configuration)?.let {
+            val input = it.layoutInput
+            val px = input.style.fontSize.value * input.density.density * input.density.fontScale
+            structure.setTextStyle(px, 0, 0, 0)
+        }
+
         with(boundsInParent) {
             structure.setDimens(
                 left.toInt(), top.toInt(), 0, 0, width.toInt(), height.toInt()
@@ -3196,17 +3220,7 @@
                 if (!node.unmergedConfig.contains(SemanticsActions.GetTextLayoutResult)) {
                     return null
                 }
-                // TODO(b/157474582): Note now it only works for single Text/TextField until we
-                //  fix the merging issue.
-                val textLayoutResults = mutableListOf<TextLayoutResult>()
-                val textLayoutResult: TextLayoutResult
-                val getLayoutResult = node.unmergedConfig[SemanticsActions.GetTextLayoutResult]
-                    .action?.invoke(textLayoutResults)
-                if (getLayoutResult == true) {
-                    textLayoutResult = textLayoutResults[0]
-                } else {
-                    return null
-                }
+                val textLayoutResult = getTextLayoutResult(node.unmergedConfig) ?: return null
                 if (granularity == AccessibilityNodeInfoCompat.MOVEMENT_GRANULARITY_LINE) {
                     iterator = AccessibilityIterators.LineTextSegmentIterator.getInstance()
                     iterator.initialize(text, textLayoutResult)
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidViewConfiguration.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidViewConfiguration.android.kt
index d9149bf..b0c5420 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidViewConfiguration.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidViewConfiguration.android.kt
@@ -30,4 +30,7 @@
 
     override val touchSlop: Float
         get() = viewConfiguration.scaledTouchSlop.toFloat()
+
+    override val maximumFlingVelocity: Int
+        get() = viewConfiguration.scaledMaximumFlingVelocity
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.android.kt
index f30e414..e585134 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.android.kt
@@ -28,6 +28,7 @@
     @ExperimentalComposeUiApi
     val TestTagsAsResourceId = SemanticsPropertyKey<Boolean>(
         name = "TestTagsAsResourceId",
+        isImportantForAccessibility = false,
         mergePolicy = { parentValue, _ -> parentValue }
     )
 }
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
index 3eab661..bef25e7e 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/viewinterop/AndroidViewHolder.android.kt
@@ -175,15 +175,11 @@
             return owner.snapshotObserver
         }
 
-    private val onCommitAffectingUpdate: (AndroidViewHolder) -> Unit = {
-        handler.post(runUpdate)
-    }
-
     private val runUpdate: () -> Unit = {
         // If we're not attached, the observer isn't started, so don't bother running it.
         // onAttachedToWindow will run an update the next time the view is attached.
         if (hasUpdateBlock && isAttachedToWindow) {
-            snapshotObserver.observeReads(this, onCommitAffectingUpdate, update)
+            snapshotObserver.observeReads(this, OnCommitAffectingUpdate, update)
         }
     }
 
@@ -583,6 +579,12 @@
     override fun isNestedScrollingEnabled(): Boolean {
         return view.isNestedScrollingEnabled
     }
+
+    companion object {
+        private val OnCommitAffectingUpdate: (AndroidViewHolder) -> Unit = {
+            it.handler.post(it.runUpdate)
+        }
+    }
 }
 
 private fun View.layoutAccordingTo(layoutNode: LayoutNode) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.kt
new file mode 100644
index 0000000..de73bd3
--- /dev/null
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.kt
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2023 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.draganddrop
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.drawscope.DrawScope
+
+/**
+ * Definition for a type representing transferable data. It could be a remote URI,
+ * rich text data on the clip board, a local file, or more.
+ */
+expect class DragAndDropTransfer
+
+@kotlin.jvm.JvmInline
+value class DragAndDropEventType private constructor(private val value: Int) {
+
+    override fun toString(): String = when (value) {
+        1 -> "Started"
+        2 -> "Entered"
+        3 -> "Moved"
+        4 -> "Exited"
+        5 -> "Changed"
+        6 -> "Dropped"
+        7 -> "Ended"
+        else -> "Unknown"
+    }
+    companion object {
+        /**
+         * An unknown drag and drop type.
+         */
+        val Unknown = DragAndDropEventType(0)
+
+        /**
+         * A drag and drop session has just been started. All eligible listeners will be notified and
+         * allowed to register their intent to keep receiving drag and drop events.
+         */
+        val Started = DragAndDropEventType(1)
+
+        /**
+         * A drag and drop event has just entered the bounds of this listener.
+         */
+        val Entered = DragAndDropEventType(2)
+
+        /**
+         * A drag and drop event has moved within the bounds of this listener.
+         */
+        val Moved = DragAndDropEventType(3)
+
+        /**
+         * A drag and drop event has just left the bounds of this listener.
+         */
+        val Exited = DragAndDropEventType(4)
+
+        /**
+         * A drag and drop event has changed within the bounds of this listener. Perhaps a modifier
+         * key has been pressed or released.
+         */
+        val Changed = DragAndDropEventType(5)
+
+        /**
+         * A drag and drop event is being concluded inside the bounds of this listener. The listener
+         * has the option to accept or reject the drag.
+         */
+        val Dropped = DragAndDropEventType(6)
+
+        /**
+         * A previously started drag and drop session has been concluded. All eligible listeners
+         * will be notified of this event. This gives an opportunity to reset a listener's state.
+         */
+        val Ended = DragAndDropEventType(7)
+    }
+}
+
+/**
+ * A representation of an event sent by the platform during a drag and drop operation.
+ */
+expect class DragAndDropEvent {
+    /**
+     * An indication of the reason the drag and drop event was sent
+     */
+    var type: DragAndDropEventType
+        private set
+}
+
+/**
+ * Returns the position of this [DragAndDropEvent] relative to the root Compose View in the
+ * layout hierarchy.
+ */
+internal expect val DragAndDropEvent.positionInRoot: Offset
+
+/**
+ * Metadata summarizing the properties used during a drag event
+ */
+class DragAndDropInfo(
+    /**
+     * The size of the drag shadow for the item that was dragged
+     */
+    val size: Size,
+    /**
+     * The data to transfer after the drag and drop event completes
+     */
+    val transfer: DragAndDropTransfer,
+    /**
+     * A [DrawScope] receiving lambda to draw the drag shadow for the drag and drop operation
+     */
+    val onDrawDragShadow: DrawScope.() -> Unit,
+)
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
index fabb572..6a35182 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker.kt
@@ -73,10 +73,34 @@
     /**
      * Computes the estimated velocity of the pointer at the time of the last provided data point.
      *
+     * The velocity calculated will not be limited. Unlike [calculateVelocity(maximumVelocity)]
+     * the resulting velocity won't be limited.
+     *
      * This can be expensive. Only call this when you need the velocity.
      */
-    fun calculateVelocity(): Velocity {
-        return Velocity(xVelocityTracker.calculateVelocity(), yVelocityTracker.calculateVelocity())
+    fun calculateVelocity(): Velocity =
+        calculateVelocity(Velocity(Float.MAX_VALUE, Float.MAX_VALUE))
+
+    /**
+     * Computes the estimated velocity of the pointer at the time of the last provided data point.
+     *
+     * The method allows specifying the maximum absolute value for the calculated
+     * velocity. If the absolute value of the calculated velocity exceeds the specified
+     * maximum, the return value will be clamped down to the maximum. For example, if
+     * the absolute maximum velocity is specified as "20", a calculated velocity of "25"
+     * will be returned as "20", and a velocity of "-30" will be returned as "-20".
+     *
+     * @param maximumVelocity the absolute values of the X and Y maximum velocities to
+     * be returned in units/second. `units` is the units of the positions provided to this
+     * VelocityTracker.
+     */
+    fun calculateVelocity(maximumVelocity: Velocity): Velocity {
+        check(maximumVelocity.x > 0f && maximumVelocity.y > 0) {
+            "maximumVelocity should be a positive value. You specified=$maximumVelocity"
+        }
+        val velocityX = xVelocityTracker.calculateVelocity(maximumVelocity.x)
+        val velocityY = yVelocityTracker.calculateVelocity(maximumVelocity.y)
+        return Velocity(velocityX, velocityY)
     }
 
     /**
@@ -186,9 +210,10 @@
     }
 
     /**
-     * Computes the estimated velocity at the time of the last provided data point. The units of
-     * velocity will be `units/second`, where `units` is the units of the data points provided via
-     * [addDataPoint].
+     * Computes the estimated velocity at the time of the last provided data point.
+     *
+     * The units of velocity will be `units/second`, where `units` is the units of the data
+     * points provided via [addDataPoint].
      *
      * This can be expensive. Only call this when you need the velocity.
      */
@@ -242,6 +267,33 @@
     }
 
     /**
+     * Computes the estimated velocity at the time of the last provided data point.
+     *
+     * The method allows specifying the maximum absolute value for the calculated
+     * velocity. If the absolute value of the calculated velocity exceeds the specified
+     * maximum, the return value will be clamped down to the maximum. For example, if
+     * the absolute maximum velocity is specified as "20", a calculated velocity of "25"
+     * will be returned as "20", and a velocity of "-30" will be returned as "-20".
+     *
+     * @param maximumVelocity the absolute value of the maximum velocity to be returned in
+     * units/second, where `units` is the units of the positions provided to this VelocityTracker.
+     */
+    fun calculateVelocity(maximumVelocity: Float): Float {
+        check(maximumVelocity > 0f) {
+            "maximumVelocity should be a positive value. You specified=$maximumVelocity"
+        }
+        val velocity = calculateVelocity()
+
+        return if (velocity == 0.0f) {
+            0.0f
+        } else if (velocity > 0) {
+            velocity.coerceAtMost(maximumVelocity)
+        } else {
+            velocity.coerceAtLeast(-maximumVelocity)
+        }
+    }
+
+    /**
      * Clears data points added by [addDataPoint].
      */
     fun resetTracking() {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.kt
index c79101e..10ec62d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.kt
@@ -18,41 +18,23 @@
 
 /**
  * This event represents a rotary input event.
- *
- * Some Wear OS devices contain a physical rotating side button, or a rotating bezel. When the user
- * turns the button or rotates the bezel, a [RotaryScrollEvent] is sent to the item in focus.
  */
-class RotaryScrollEvent internal constructor(
+expect class RotaryScrollEvent {
     /**
      * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
      * can scroll vertically.
      */
-    val verticalScrollPixels: Float,
+    val verticalScrollPixels: Float
 
     /**
      * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
      * can scroll horizontally.
      */
-    val horizontalScrollPixels: Float,
+    val horizontalScrollPixels: Float
 
     /**
      * The time in milliseconds at which this even occurred. The start (`0`) time is
      * platform-dependent.
      */
     val uptimeMillis: Long
-) {
-    override fun equals(other: Any?): Boolean = other is RotaryScrollEvent &&
-        other.verticalScrollPixels == verticalScrollPixels &&
-        other.horizontalScrollPixels == horizontalScrollPixels &&
-        other.uptimeMillis == uptimeMillis
-
-    override fun hashCode(): Int = 0
-            .let { verticalScrollPixels.hashCode() }
-            .let { 31 * it + horizontalScrollPixels.hashCode() }
-            .let { 31 * it + uptimeMillis.hashCode() }
-
-    override fun toString(): String = "RotaryScrollEvent(" +
-        "verticalScrollPixels=$verticalScrollPixels," +
-        "horizontalScrollPixels=$horizontalScrollPixels," +
-        "uptimeMillis=$uptimeMillis)"
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
index 5c52ed5..8abb20b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
@@ -567,15 +567,16 @@
                         node.resetLayoutState()
                         if (deactivate) {
                             nodeState.composition?.deactivate()
+                            nodeState.activeState = mutableStateOf(false)
+                        } else {
+                            nodeState.active = false
                         }
                         // create a new instance to avoid change notifications
-                        nodeState.activeState = mutableStateOf(false)
                         nodeState.slotId = ReusedSlotId
                     }
                 }
             }
             slotIdToNode.clear()
-            Snapshot.sendApplyNotifications()
         }
 
         makeSureStateIsConsistent()
@@ -673,7 +674,6 @@
             nodeState.activeState = mutableStateOf(true)
             nodeState.forceReuse = true
             nodeState.forceRecompose = true
-            Snapshot.sendApplyNotifications()
             node
         }
     }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DepthSortedSet.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DepthSortedSet.kt
index 6ee9680..9eb7246 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DepthSortedSet.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/DepthSortedSet.kt
@@ -176,6 +176,8 @@
     }
 
     fun isEmpty(): Boolean = set.isEmpty() && lookaheadSet.isEmpty()
+    fun isEmpty(affectsLookahead: Boolean): Boolean =
+        if (affectsLookahead) lookaheadSet.isEmpty() else set.isEmpty()
 
     fun isNotEmpty(): Boolean = !isEmpty()
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
index 225410d..dbfd908 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/MeasureAndLayoutDelegate.kt
@@ -366,17 +366,21 @@
      * to be called to determine only how large the root is with minimal effort.
      */
     fun measureOnly() {
-        performMeasureAndLayout {
-            if (root.lookaheadRoot != null) {
-                // This call will walk the tree to look for lookaheadMeasurePending nodes and
-                // do a lookahead remeasure for those nodes only.
-                recurseRemeasure(root, affectsLookahead = true)
-            } else {
-                // First do a lookahead remeasure pass for all the lookaheadMeasurePending nodes,
-                // followed by a remeasure pass for the rest of the tree.
-                remeasureLookaheadRootsInSubtree(root)
+        if (relayoutNodes.isNotEmpty()) {
+            performMeasureAndLayout {
+                if (!relayoutNodes.isEmpty(affectsLookahead = true)) {
+                    if (root.lookaheadRoot != null) {
+                        // This call will walk the tree to look for lookaheadMeasurePending nodes and
+                        // do a lookahead remeasure for those nodes only.
+                        remeasureOnly(root, affectsLookahead = true)
+                    } else {
+                        // First do a lookahead remeasure pass for all the lookaheadMeasurePending nodes,
+                        // followed by a remeasure pass for the rest of the tree.
+                        remeasureLookaheadRootsInSubtree(root)
+                    }
+                }
+                remeasureOnly(root, affectsLookahead = false)
             }
-            recurseRemeasure(root, affectsLookahead = false)
         }
     }
 
@@ -385,7 +389,7 @@
             if (it.isOutMostLookaheadRoot()) {
                 // This call will walk the subtree to look for lookaheadMeasurePending nodes and
                 // do a recursive lookahead remeasure starting at the root.
-                recurseRemeasure(it, affectsLookahead = true)
+                remeasureOnly(it, affectsLookahead = true)
             } else {
                 // Only search downward when no lookahead root is found
                 remeasureLookaheadRootsInSubtree(it)
@@ -393,22 +397,6 @@
         }
     }
 
-    /**
-     * Walks the hierarchy from [layoutNode] and remeasures [layoutNode] and any
-     * descendants that affect its size.
-     */
-    private fun recurseRemeasure(layoutNode: LayoutNode, affectsLookahead: Boolean) {
-        remeasureOnly(layoutNode, affectsLookahead)
-
-        layoutNode.forEachChild { child ->
-            if (child.measureAffectsParent) {
-                recurseRemeasure(child, affectsLookahead)
-            }
-        }
-        // The child measurement may have invalidated layoutNode's measurement
-        remeasureOnly(layoutNode, affectsLookahead)
-    }
-
     fun measureAndLayout(layoutNode: LayoutNode, constraints: Constraints) {
         require(layoutNode != root) { "measureAndLayout called on root" }
         performMeasureAndLayout {
@@ -531,22 +519,23 @@
      */
     private fun remeasureOnly(layoutNode: LayoutNode, affectsLookahead: Boolean) {
         val constraints = if (layoutNode === root) rootConstraints!! else null
-        if (affectsLookahead && layoutNode.lookaheadMeasurePending) {
+        if (affectsLookahead) {
             doLookaheadRemeasure(layoutNode, constraints)
-        } else if (!affectsLookahead && layoutNode.measurePending) {
+        } else {
             doRemeasure(layoutNode, constraints)
         }
     }
 
     /**
-     * Makes sure the passed [layoutNode] and its subtree is remeasured and has the final sizes.
+     * Makes sure the passed [layoutNode] and its subtree has the final sizes.
+     * The nodes which can potentially affect the parent size will be remeasured.
      *
      * The node or some of the nodes in its subtree can still be kept unmeasured if they are
      * not placed and don't affect the parent size. See [requestRemeasure] for details.
      */
     fun forceMeasureTheSubtree(layoutNode: LayoutNode, affectsLookahead: Boolean) {
         // if there is nothing in `relayoutNodes` everything is remeasured.
-        if (relayoutNodes.isEmpty()) {
+        if (relayoutNodes.isEmpty(affectsLookahead)) {
             return
         }
 
@@ -555,40 +544,62 @@
             "forceMeasureTheSubtree should be executed during the measureAndLayout pass"
         }
 
-        val pending: (LayoutNode) -> Boolean = {
-            if (affectsLookahead) {
-                it.lookaheadMeasurePending
-            } else {
-                it.measurePending
-            }
-        }
         // if this node is not yet measured this invocation shouldn't be needed.
-        require(!pending(layoutNode)) { "node not yet measured" }
+        require(!layoutNode.measurePending(affectsLookahead)) { "node not yet measured" }
 
+        forceMeasureTheSubtreeInternal(layoutNode, affectsLookahead)
+    }
+
+    private fun onlyRemeasureIfScheduled(node: LayoutNode, affectsLookahead: Boolean) {
+        if (node.measurePending(affectsLookahead) &&
+            relayoutNodes.contains(node, affectsLookahead)
+        ) {
+            // we don't need to run relayout as part of this logic. so the node will
+            // not be removed from `relayoutNodes` in order to be visited again during
+            // the regular pass. it is important as the parent of this node can decide
+            // to not place this child, so the child relayout should be skipped.
+            remeasureAndRelayoutIfNeeded(node, affectsLookahead, relayoutNeeded = false)
+        }
+    }
+
+    private fun forceMeasureTheSubtreeInternal(layoutNode: LayoutNode, affectsLookahead: Boolean) {
         layoutNode.forEachChild { child ->
-            if (pending(child) && relayoutNodes.contains(child, affectsLookahead)) {
-                // we don't need to run relayout as part of this logic. so the node will
-                // not be removed from `relayoutNodes` in order to be visited again during
-                // the regular pass. it is important as the parent of this node can decide
-                // to not place this child, so the child relayout should be skipped.
-                remeasureAndRelayoutIfNeeded(child, affectsLookahead, relayoutNeeded = false)
+            // When LookaheadRoot's parent gets forceMeasureSubtree call, it means we need to check
+            // both lookahead invalidation and non-lookahead invalidation, just like a measure()
+            // call from LookaheadRoot's parent would start the two tracks - lookahead and post
+            // lookahead measurements.
+            if (child.isOutMostLookaheadRoot() && !affectsLookahead) {
+                // Force subtree measure hitting a lookahead root, pending lookahead measure. This
+                // could happen when the "applyChanges" cause nodes to be attached in lookahead
+                // subtree while the "applyChanges" is a part of the ancestor's subcomposition
+                // in the measure pass.
+                if (child.lookaheadMeasurePending && relayoutNodes.contains(child, true)) {
+                    remeasureAndRelayoutIfNeeded(child, true, relayoutNeeded = false)
+                } else {
+                    forceMeasureTheSubtree(child, true)
+                }
             }
 
-            // if the child is still in NeedsRemeasure state then this child remeasure wasn't
-            // needed. it can happen for example when this child is not placed and can't affect
-            // the parent size. we can skip the whole subtree.
-            if (!pending(child)) {
-                // run recursively for the subtree.
-                forceMeasureTheSubtree(child, affectsLookahead)
+            // only proceed if child's size can affect the parent size
+            if (!affectsLookahead && child.measureAffectsParent ||
+                affectsLookahead && child.measureAffectsParentLookahead
+            ) {
+                onlyRemeasureIfScheduled(child, affectsLookahead)
+
+                // if the child is still in NeedsRemeasure state then this child remeasure wasn't
+                // needed. it can happen for example when this child is not placed and can't affect
+                // the parent size. we can skip the whole subtree.
+                if (!child.measurePending(affectsLookahead)) {
+                    // run recursively for the subtree.
+                    forceMeasureTheSubtreeInternal(child, affectsLookahead)
+                }
             }
         }
 
         // if the child was resized during the remeasurement it could request a remeasure on
         // the parent. we need to remeasure now as this function assumes the whole subtree is
         // fully measured as a result of the invocation.
-        if (pending(layoutNode) && relayoutNodes.remove(layoutNode, affectsLookahead)) {
-            remeasureAndRelayoutIfNeeded(layoutNode)
-        }
+        onlyRemeasureIfScheduled(layoutNode, affectsLookahead)
     }
 
     /**
@@ -621,9 +632,14 @@
         get() = measurePending && measureAffectsParent
 
     private val LayoutNode.canAffectParentInLookahead
-        get() = lookaheadMeasurePending &&
-            (measuredByParentInLookahead == InMeasureBlock ||
+        get() = lookaheadMeasurePending && measureAffectsParentLookahead
+
+    private val LayoutNode.measureAffectsParentLookahead
+        get() = (measuredByParentInLookahead == InMeasureBlock ||
                 layoutDelegate.lookaheadAlignmentLinesOwner?.alignmentLines?.required == true)
 
+    private fun LayoutNode.measurePending(affectsLookahead: Boolean) =
+        if (affectsLookahead) lookaheadMeasurePending else measurePending
+
     class PostponedRequest(val node: LayoutNode, val isLookahead: Boolean, val isForced: Boolean)
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
index 20e43e3..b205277 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
@@ -23,6 +23,7 @@
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.areObjectsOfSameType
+import androidx.compose.ui.input.pointer.SuspendPointerInputElement
 import androidx.compose.ui.layout.ModifierInfo
 
 private val SentinelHead = object : Modifier.Node() {
@@ -218,6 +219,16 @@
         tailToHead {
             if (it.isAttached) it.reset()
         }
+        current?.let { elements ->
+            elements.forEachIndexed { i, element ->
+                // we need to make sure the suspending pointer input modifier node is updated after
+                // being reset so we use the latest lambda, even if the keys provided as input
+                // didn't change.
+                if (element is SuspendPointerInputElement) {
+                    elements[i] = ForceUpdateElement
+                }
+            }
+        }
         runDetachLifecycle()
         markAsDetached()
     }
@@ -797,7 +808,7 @@
 internal fun actionForModifiers(prev: Modifier.Element, next: Modifier.Element): Int {
     return if (prev == next)
         ActionReuse
-    else if (areObjectsOfSameType(prev, next))
+    else if (areObjectsOfSameType(prev, next) || prev === ForceUpdateElement)
         ActionUpdate
     else
         ActionReplace
@@ -833,3 +844,20 @@
     }
     return result
 }
+
+@Suppress("ModifierNodeInspectableProperties")
+private object ForceUpdateElement : ModifierNodeElement<Modifier.Node>() {
+    override fun create(): Modifier.Node {
+        throw IllegalStateException("Shouldn't be called")
+    }
+
+    override fun update(node: Modifier.Node) {
+        throw IllegalStateException("Shouldn't be called")
+    }
+
+    override fun hashCode(): Int = 100
+
+    override fun equals(other: Any?): Boolean = other === this
+
+    override fun toString() = "ForceUpdateElement"
+}
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
index a933cd4..8c84e52 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
@@ -19,6 +19,7 @@
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.Offset
@@ -310,6 +311,14 @@
         session: suspend PlatformTextInputSessionScope.() -> Nothing
     ): Nothing
 
+    /**
+     * Initiates a drag-and-drop operation containing the data in [DragAndDropInfo].
+     * @return true if the method completes successfully, or false if it fails anywhere.
+     * Returning false means the system was unable to do a drag because of another
+     * ongoing operation or some other reasons.
+     */
+    fun drag(dragAndDropInfo: DragAndDropInfo): Boolean
+
     companion object {
         /**
          * Enables additional (and expensive to do in production) assertions. Useful to be set
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ViewConfiguration.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ViewConfiguration.kt
index 79fd45b..6a829a5 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ViewConfiguration.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/platform/ViewConfiguration.kt
@@ -54,4 +54,9 @@
      */
     val minimumTouchTargetSize: DpSize
         get() = DpSize(48.dp, 48.dp)
+
+    /**
+     * The maximum velocity a fling can start with.
+     */
+    val maximumFlingVelocity: Int get() = Int.MAX_VALUE
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsConfiguration.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsConfiguration.kt
index 922af3f..000dd66 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsConfiguration.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsConfiguration.kt
@@ -74,6 +74,9 @@
         return props.containsKey(key)
     }
 
+    internal fun containsImportantForAccessibility() =
+        props.keys.any { it.isImportantForAccessibility }
+
     /**
      * Whether the semantic information provided by the owning component and
      * all of its descendants should be treated as one logical entity.
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
index 39e6cb6..4b4e33f 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsProperties.kt
@@ -36,7 +36,7 @@
     /**
      * @see SemanticsPropertyReceiver.contentDescription
      */
-    val ContentDescription = SemanticsPropertyKey<List<String>>(
+    val ContentDescription = AccessibilityKey<List<String>>(
         name = "ContentDescription",
         mergePolicy = { parentValue, childValue ->
             parentValue?.toMutableList()?.also { it.addAll(childValue) } ?: childValue
@@ -46,18 +46,18 @@
     /**
      * @see SemanticsPropertyReceiver.stateDescription
      */
-    val StateDescription = SemanticsPropertyKey<String>("StateDescription")
+    val StateDescription = AccessibilityKey<String>("StateDescription")
 
     /**
      * @see SemanticsPropertyReceiver.progressBarRangeInfo
      */
     val ProgressBarRangeInfo =
-        SemanticsPropertyKey<ProgressBarRangeInfo>("ProgressBarRangeInfo")
+        AccessibilityKey<ProgressBarRangeInfo>("ProgressBarRangeInfo")
 
     /**
      * @see SemanticsPropertyReceiver.paneTitle
      */
-    val PaneTitle = SemanticsPropertyKey<String>(
+    val PaneTitle = AccessibilityKey<String>(
         name = "PaneTitle",
         mergePolicy = { _, _ ->
             throw IllegalStateException(
@@ -67,33 +67,33 @@
     )
 
     /** @see SemanticsPropertyReceiver.selectableGroup */
-    val SelectableGroup = SemanticsPropertyKey<Unit>("SelectableGroup")
+    val SelectableGroup = AccessibilityKey<Unit>("SelectableGroup")
 
     /** @see SemanticsPropertyReceiver.collectionInfo */
-    val CollectionInfo = SemanticsPropertyKey<CollectionInfo>("CollectionInfo")
+    val CollectionInfo = AccessibilityKey<CollectionInfo>("CollectionInfo")
 
     /** @see SemanticsPropertyReceiver.collectionItemInfo */
-    val CollectionItemInfo = SemanticsPropertyKey<CollectionItemInfo>("CollectionItemInfo")
+    val CollectionItemInfo = AccessibilityKey<CollectionItemInfo>("CollectionItemInfo")
 
     /**
      * @see SemanticsPropertyReceiver.heading
      */
-    val Heading = SemanticsPropertyKey<Unit>("Heading")
+    val Heading = AccessibilityKey<Unit>("Heading")
 
     /**
      * @see SemanticsPropertyReceiver.disabled
      */
-    val Disabled = SemanticsPropertyKey<Unit>("Disabled")
+    val Disabled = AccessibilityKey<Unit>("Disabled")
 
     /**
      * @see SemanticsPropertyReceiver.liveRegion
      */
-    val LiveRegion = SemanticsPropertyKey<LiveRegionMode>("LiveRegion")
+    val LiveRegion = AccessibilityKey<LiveRegionMode>("LiveRegion")
 
     /**
      * @see SemanticsPropertyReceiver.focused
      */
-    val Focused = SemanticsPropertyKey<Boolean>("Focused")
+    val Focused = AccessibilityKey<Boolean>("Focused")
 
     /**
      * @see SemanticsPropertyReceiver.isContainer
@@ -107,7 +107,7 @@
     /**
      * @see SemanticsPropertyReceiver.isTraversalGroup
      */
-    val IsTraversalGroup = SemanticsPropertyKey<Boolean>("IsTraversalGroup")
+    val IsTraversalGroup = AccessibilityKey<Boolean>("IsTraversalGroup")
 
     /**
      * @see SemanticsPropertyReceiver.invisibleToUser
@@ -123,7 +123,7 @@
     /**
      * @see SemanticsPropertyReceiver.traversalIndex
      */
-    val TraversalIndex = SemanticsPropertyKey<Float>(
+    val TraversalIndex = AccessibilityKey<Float>(
         name = "TraversalIndex",
         mergePolicy = { parentValue, _ ->
             // Never merge traversal indices
@@ -135,18 +135,18 @@
      * @see SemanticsPropertyReceiver.horizontalScrollAxisRange
      */
     val HorizontalScrollAxisRange =
-        SemanticsPropertyKey<ScrollAxisRange>("HorizontalScrollAxisRange")
+        AccessibilityKey<ScrollAxisRange>("HorizontalScrollAxisRange")
 
     /**
      * @see SemanticsPropertyReceiver.verticalScrollAxisRange
      */
     val VerticalScrollAxisRange =
-        SemanticsPropertyKey<ScrollAxisRange>("VerticalScrollAxisRange")
+        AccessibilityKey<ScrollAxisRange>("VerticalScrollAxisRange")
 
     /**
      * @see SemanticsPropertyReceiver.popup
      */
-    val IsPopup = SemanticsPropertyKey<Unit>(
+    val IsPopup = AccessibilityKey<Unit>(
         name = "IsPopup",
         mergePolicy = { _, _ ->
             throw IllegalStateException(
@@ -159,7 +159,7 @@
     /**
      * @see SemanticsPropertyReceiver.dialog
      */
-    val IsDialog = SemanticsPropertyKey<Unit>(
+    val IsDialog = AccessibilityKey<Unit>(
         name = "IsDialog",
         mergePolicy = { _, _ ->
             throw IllegalStateException(
@@ -178,13 +178,14 @@
      *
      * @see SemanticsPropertyReceiver.role
      */
-    val Role = SemanticsPropertyKey<Role>("Role") { parentValue, _ -> parentValue }
+    val Role = AccessibilityKey<Role>("Role") { parentValue, _ -> parentValue }
 
     /**
      * @see SemanticsPropertyReceiver.testTag
      */
     val TestTag = SemanticsPropertyKey<String>(
         name = "TestTag",
+        isImportantForAccessibility = false,
         mergePolicy = { parentValue, _ ->
             // Never merge TestTags, to avoid leaking internal test tags to parents.
             parentValue
@@ -194,7 +195,7 @@
     /**
      * @see SemanticsPropertyReceiver.text
      */
-    val Text = SemanticsPropertyKey<List<AnnotatedString>>(
+    val Text = AccessibilityKey<List<AnnotatedString>>(
         name = "Text",
         mergePolicy = { parentValue, childValue ->
             parentValue?.toMutableList()?.also { it.addAll(childValue) } ?: childValue
@@ -214,37 +215,37 @@
     /**
      * @see SemanticsPropertyReceiver.editableText
      */
-    val EditableText = SemanticsPropertyKey<AnnotatedString>(name = "EditableText")
+    val EditableText = AccessibilityKey<AnnotatedString>(name = "EditableText")
 
     /**
      * @see SemanticsPropertyReceiver.textSelectionRange
      */
-    val TextSelectionRange = SemanticsPropertyKey<TextRange>("TextSelectionRange")
+    val TextSelectionRange = AccessibilityKey<TextRange>("TextSelectionRange")
 
     /**
      * @see SemanticsPropertyReceiver.onImeAction
      */
-    val ImeAction = SemanticsPropertyKey<ImeAction>("ImeAction")
+    val ImeAction = AccessibilityKey<ImeAction>("ImeAction")
 
     /**
      * @see SemanticsPropertyReceiver.selected
      */
-    val Selected = SemanticsPropertyKey<Boolean>("Selected")
+    val Selected = AccessibilityKey<Boolean>("Selected")
 
     /**
      * @see SemanticsPropertyReceiver.toggleableState
      */
-    val ToggleableState = SemanticsPropertyKey<ToggleableState>("ToggleableState")
+    val ToggleableState = AccessibilityKey<ToggleableState>("ToggleableState")
 
     /**
      * @see SemanticsPropertyReceiver.password
      */
-    val Password = SemanticsPropertyKey<Unit>("Password")
+    val Password = AccessibilityKey<Unit>("Password")
 
     /**
      * @see SemanticsPropertyReceiver.error
      */
-    val Error = SemanticsPropertyKey<String>("Error")
+    val Error = AccessibilityKey<String>("Error")
 
     /**
      * @see SemanticsPropertyReceiver.indexForKey
@@ -366,7 +367,7 @@
      * @see SemanticsPropertyReceiver.customActions
      */
     val CustomActions =
-        SemanticsPropertyKey<List<CustomAccessibilityAction>>("CustomActions")
+        AccessibilityKey<List<CustomAccessibilityAction>>("CustomActions")
 
     /**
      * @see SemanticsPropertyReceiver.pageUp
@@ -403,6 +404,40 @@
     }
 ) {
     /**
+     * Whether this type of property provides information relevant to accessibility services.
+     *
+     * Most built-in semantics properties are relevant to accessibility, but a very common
+     * exception is testTag. Nodes with only a testTag still need to be included
+     * in the AccessibilityNodeInfo tree because UIAutomator tests rely on
+     * that, but we mark them `isImportantForAccessibility = false` on the AccessibilityNodeInfo
+     * to inform accessibility services that they are best ignored.
+     *
+     * The default value is false and it is not exposed as a public API. That's because
+     * it is impossible in the first place for `SemanticsPropertyKey`s
+     * defined outside the UI package to be relevant to accessibility, because
+     * for each accessibility-relevant SemanticsProperty type to get plumbed into the
+     * AccessibilityNodeInfo, the private `createNodeInfo` implementation must also have
+     * a line of code.
+     */
+    internal var isImportantForAccessibility = false
+        private set
+
+    internal constructor(
+        name: String,
+        isImportantForAccessibility: Boolean,
+    ) : this(name) {
+        this.isImportantForAccessibility = isImportantForAccessibility
+    }
+
+    internal constructor(
+        name: String,
+        isImportantForAccessibility: Boolean,
+        mergePolicy: (T?, T) -> T?
+    ) : this(name, mergePolicy) {
+        this.isImportantForAccessibility = isImportantForAccessibility
+    }
+
+    /**
      * Method implementing the semantics merge policy of a particular key.
      *
      * When mergeDescendants is set on a semantics node, then this function will called for each
@@ -435,7 +470,7 @@
     }
 
     override fun toString(): String {
-        return "SemanticsPropertyKey: $name"
+        return "AccessibilityKey: $name"
     }
 }
 
@@ -446,6 +481,24 @@
     )
 }
 
+internal fun <T> AccessibilityKey(
+    name: String
+) =
+    SemanticsPropertyKey<T>(
+        name = name,
+        isImportantForAccessibility = true
+    )
+
+internal fun <T> AccessibilityKey(
+    name: String,
+    mergePolicy: (T?, T) -> T?
+) =
+    SemanticsPropertyKey<T>(
+        name = name,
+        isImportantForAccessibility = true,
+        mergePolicy = mergePolicy
+    )
+
 /**
  * Standard accessibility action.
  *
@@ -483,8 +536,8 @@
 // inline to break static initialization cycle issue
 private inline fun <T : Function<Boolean>> ActionPropertyKey(
     name: String
-): SemanticsPropertyKey<AccessibilityAction<T>> {
-    return SemanticsPropertyKey(
+) =
+    AccessibilityKey<AccessibilityAction<T>>(
         name = name,
         mergePolicy = { parentValue, childValue ->
             AccessibilityAction(
@@ -493,7 +546,6 @@
             )
         }
     )
-}
 
 /**
  * Custom accessibility action.
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.desktop.kt
new file mode 100644
index 0000000..c23cc36
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/draganddrop/DragAndDrop.desktop.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.draganddrop
+
+import androidx.compose.ui.geometry.Offset
+import java.awt.dnd.DropTargetEvent as AwtDropTargetEvent
+
+actual class DragAndDropTransfer
+
+/**
+ * AWT [DragAndDropEvent] which delegates to a [AwtDropTargetEvent]
+ */
+actual class DragAndDropEvent(
+    actual var type: DragAndDropEventType,
+    internal var dropTargetEvent: AwtDropTargetEvent
+)
+
+internal actual val DragAndDropEvent.positionInRoot: Offset
+    get() = TODO()
diff --git a/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.desktop.kt b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.desktop.kt
new file mode 100644
index 0000000..02ae758
--- /dev/null
+++ b/compose/ui/ui/src/desktopMain/kotlin/androidx/compose/ui/input/rotary/RotaryScrollEvent.desktop.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 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.input.rotary
+
+/**
+ * This event represents a rotary input event.
+ *
+ * Some devices contain a physical rotating side button, or a rotating bezel. When the user
+ * turns the button or rotates the bezel, a [RotaryScrollEvent] is sent to the item in focus.
+ */
+actual class RotaryScrollEvent internal constructor(
+    /**
+     * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
+     * can scroll vertically.
+     */
+    actual val verticalScrollPixels: Float,
+
+    /**
+     * The amount to scroll (in pixels) in response to a [RotaryScrollEvent] in a container that
+     * can scroll horizontally.
+     */
+    actual val horizontalScrollPixels: Float,
+
+    /**
+     * The time in milliseconds at which this even occurred. The start (`0`) time is
+     * platform-dependent.
+     */
+    actual val uptimeMillis: Long,
+
+) {
+    override fun equals(other: Any?): Boolean = other is RotaryScrollEvent &&
+        other.verticalScrollPixels == verticalScrollPixels &&
+        other.horizontalScrollPixels == horizontalScrollPixels &&
+        other.uptimeMillis == uptimeMillis
+
+    override fun hashCode(): Int = 0
+        .let { verticalScrollPixels.hashCode() }
+        .let { 31 * it + horizontalScrollPixels.hashCode() }
+        .let { 31 * it + uptimeMillis.hashCode() }
+
+    override fun toString(): String = "RotaryScrollEvent(" +
+        "verticalScrollPixels=$verticalScrollPixels," +
+        "horizontalScrollPixels=$horizontalScrollPixels," +
+        "uptimeMillis=$uptimeMillis)"
+}
diff --git a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/AutofillIdCompat.java b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/AutofillIdCompat.java
new file mode 100644
index 0000000..53360b6
--- /dev/null
+++ b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/AutofillIdCompat.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.platform.coreshims;
+
+import android.view.autofill.AutofillId;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+/**
+ * Helper for accessing features in {@link AutofillId}.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class AutofillIdCompat {
+    // Only guaranteed to be non-null on SDK_INT >= 26.
+    private final Object mWrappedObj;
+
+    @RequiresApi(26)
+    private AutofillIdCompat(@NonNull AutofillId obj) {
+        mWrappedObj = obj;
+    }
+
+    /**
+     * Provides a backward-compatible wrapper for {@link AutofillId}.
+     * <p>
+     * This method is not supported on devices running SDK < 26 since the platform
+     * class will not be available.
+     *
+     * @param autofillId platform class to wrap
+     * @return wrapped class
+     */
+    @RequiresApi(26)
+    @NonNull
+    public static AutofillIdCompat toAutofillIdCompat(@NonNull AutofillId autofillId) {
+        return new AutofillIdCompat(autofillId);
+    }
+
+    /**
+     * Provides the {@link AutofillId} represented by this object.
+     * <p>
+     * This method is not supported on devices running SDK < 26 since the platform
+     * class will not be available.
+     *
+     * @return platform class object
+     * @see AutofillIdCompat#toAutofillIdCompat(AutofillId)
+     */
+    @RequiresApi(26)
+    @NonNull
+    public AutofillId toAutofillId() {
+        return (AutofillId) mWrappedObj;
+    }
+}
diff --git a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java
new file mode 100644
index 0000000..788ae0b
--- /dev/null
+++ b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ContentCaptureSessionCompat.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.platform.coreshims;
+
+import static android.os.Build.VERSION.SDK_INT;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewStructure;
+import android.view.autofill.AutofillId;
+import android.view.contentcapture.ContentCaptureSession;
+
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Helper for accessing features in {@link ContentCaptureSession}.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ContentCaptureSessionCompat {
+
+    private static final String KEY_VIEW_TREE_APPEARING = "TREAT_AS_VIEW_TREE_APPEARING";
+    private static final String KEY_VIEW_TREE_APPEARED = "TREAT_AS_VIEW_TREE_APPEARED";
+    // Only guaranteed to be non-null on SDK_INT >= 29.
+    private final Object mWrappedObj;
+    private final View mView;
+
+    /**
+     * Provides a backward-compatible wrapper for {@link ContentCaptureSession}.
+     * <p>
+     * This method is not supported on devices running SDK < 29 since the platform
+     * class will not be available.
+     *
+     * @param contentCaptureSession platform class to wrap
+     * @param host view hosting the session.
+     * @return wrapped class
+     */
+    @RequiresApi(29)
+    @NonNull
+    public static ContentCaptureSessionCompat toContentCaptureSessionCompat(
+            @NonNull ContentCaptureSession contentCaptureSession, @NonNull View host) {
+        return new ContentCaptureSessionCompat(contentCaptureSession, host);
+    }
+
+    /**
+     * Provides the {@link ContentCaptureSession} represented by this object.
+     * <p>
+     * This method is not supported on devices running SDK < 29 since the platform
+     * class will not be available.
+     *
+     * @return platform class object
+     * @see ContentCaptureSessionCompat#toContentCaptureSessionCompat(ContentCaptureSession, View)
+     */
+    @RequiresApi(29)
+    @NonNull
+    public ContentCaptureSession toContentCaptureSession() {
+        return (ContentCaptureSession) mWrappedObj;
+    }
+
+    /**
+     * Creates a {@link ContentCaptureSessionCompat} instance.
+     *
+     * @param contentCaptureSession {@link ContentCaptureSession} for this host View.
+     * @param host view hosting the session.
+     */
+    @RequiresApi(29)
+    private ContentCaptureSessionCompat(@NonNull ContentCaptureSession contentCaptureSession,
+            @NonNull View host) {
+        this.mWrappedObj = contentCaptureSession;
+        this.mView = host;
+    }
+
+    /**
+     * Creates a new {@link AutofillId} for a virtual child, so it can be used to uniquely identify
+     * the children in the session.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method returns null.
+     * </ul>
+     *
+     * @param virtualChildId id of the virtual child, relative to the parent.
+     *
+     * @return {@link AutofillId} for the virtual child
+     */
+    @Nullable
+    public AutofillId newAutofillId(long virtualChildId) {
+        if (SDK_INT >= 29) {
+            return Api29Impl.newAutofillId(
+                    (ContentCaptureSession) mWrappedObj,
+                    Objects.requireNonNull(ViewCompatShims.getAutofillId(mView)).toAutofillId(),
+                    virtualChildId);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a {@link ViewStructure} for a "virtual" view, so it can be passed to
+     * {@link #notifyViewsAppeared} by the view managing the virtual view hierarchy.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method returns null.
+     * </ul>
+     *
+     * @param parentId id of the virtual view parent (it can be obtained by calling
+     * {@link ViewStructure#getAutofillId()} on the parent).
+     * @param virtualId id of the virtual child, relative to the parent.
+     *
+     * @return a new {@link ViewStructure} that can be used for Content Capture purposes.
+     */
+    @Nullable
+    public ViewStructureCompat newVirtualViewStructure(
+            @NonNull AutofillId parentId, long virtualId) {
+        if (SDK_INT >= 29) {
+            return ViewStructureCompat.toViewStructureCompat(
+                    Api29Impl.newVirtualViewStructure(
+                            (ContentCaptureSession) mWrappedObj, parentId, virtualId));
+        }
+        return null;
+    }
+
+    /**
+     * Notifies the Content Capture Service that a list of nodes has appeared in the view structure.
+     *
+     * <p>Typically called manually by views that handle their own virtual view hierarchy.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 34 and above, this method matches platform behavior.
+     * <li>SDK 29 through 33, this method is a best-effort to match platform behavior, by
+     * wrapping the virtual children with a pair of special view appeared events.
+     * <li>SDK 28 and below, this method does nothing.
+     *
+     * @param appearedNodes nodes that have appeared. Each element represents a view node that has
+     * been added to the view structure. The order of the elements is important, which should be
+     * preserved as the attached order of when the node is attached to the virtual view hierarchy.
+     */
+    public void notifyViewsAppeared(@NonNull List<ViewStructure> appearedNodes) {
+        if (SDK_INT >= 34) {
+            Api34Impl.notifyViewsAppeared((ContentCaptureSession) mWrappedObj, appearedNodes);
+        } else if (SDK_INT >= 29) {
+            ViewStructure treeAppearing = Api29Impl.newViewStructure(
+                    (ContentCaptureSession) mWrappedObj, mView);
+            Api23Impl.getExtras(treeAppearing).putBoolean(KEY_VIEW_TREE_APPEARING, true);
+            Api29Impl.notifyViewAppeared((ContentCaptureSession) mWrappedObj, treeAppearing);
+
+            for (int i = 0; i < appearedNodes.size(); i++) {
+                Api29Impl.notifyViewAppeared(
+                        (ContentCaptureSession) mWrappedObj, appearedNodes.get(i));
+            }
+
+            ViewStructure treeAppeared = Api29Impl.newViewStructure(
+                    (ContentCaptureSession) mWrappedObj, mView);
+            Api23Impl.getExtras(treeAppeared).putBoolean(KEY_VIEW_TREE_APPEARED, true);
+            Api29Impl.notifyViewAppeared((ContentCaptureSession) mWrappedObj, treeAppeared);
+        }
+    }
+
+    /**
+     * Notifies the Content Capture Service that many nodes has been removed from a virtual view
+     * structure.
+     *
+     * <p>Should only be called by views that handle their own virtual view hierarchy.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 34 and above, this method matches platform behavior.
+     * <li>SDK 29 through 33, this method is a best-effort to match platform behavior, by
+     * wrapping the virtual children with a pair of special view appeared events.
+     * <li>SDK 28 and below, this method does nothing.
+     * </ul>
+     *
+     * @param virtualIds ids of the virtual children.
+     */
+    public void notifyViewsDisappeared(@NonNull long[] virtualIds) {
+        if (SDK_INT >= 34) {
+            Api29Impl.notifyViewsDisappeared(
+                    (ContentCaptureSession) mWrappedObj,
+                    Objects.requireNonNull(ViewCompatShims.getAutofillId(mView)).toAutofillId(),
+                    virtualIds);
+        } else if (SDK_INT >= 29) {
+            ViewStructure treeAppearing = Api29Impl.newViewStructure(
+                    (ContentCaptureSession) mWrappedObj, mView);
+            Api23Impl.getExtras(treeAppearing).putBoolean(KEY_VIEW_TREE_APPEARING, true);
+            Api29Impl.notifyViewAppeared((ContentCaptureSession) mWrappedObj, treeAppearing);
+
+            Api29Impl.notifyViewsDisappeared(
+                    (ContentCaptureSession) mWrappedObj,
+                    Objects.requireNonNull(ViewCompatShims.getAutofillId(mView)).toAutofillId(),
+                    virtualIds);
+
+            ViewStructure treeAppeared = Api29Impl.newViewStructure(
+                    (ContentCaptureSession) mWrappedObj, mView);
+            Api23Impl.getExtras(treeAppeared).putBoolean(KEY_VIEW_TREE_APPEARED, true);
+            Api29Impl.notifyViewAppeared((ContentCaptureSession) mWrappedObj, treeAppeared);
+        }
+    }
+
+    /**
+     * Notifies the Intelligence Service that the value of a text node has been changed.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method does nothing.
+     * </ul>
+     *
+     * @param id of the node.
+     * @param text new text.
+     */
+    public void notifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text) {
+        if (SDK_INT >= 29) {
+            Api29Impl.notifyViewTextChanged((ContentCaptureSession) mWrappedObj, id, text);
+        }
+    }
+
+    @RequiresApi(34)
+    private static class Api34Impl {
+        private Api34Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void notifyViewsAppeared(
+                ContentCaptureSession contentCaptureSession, List<ViewStructure> appearedNodes) {
+            // new API in U
+            contentCaptureSession.notifyViewsAppeared(appearedNodes);
+        }
+    }
+    @RequiresApi(29)
+    private static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void notifyViewsDisappeared(
+                ContentCaptureSession contentCaptureSession, AutofillId hostId, long[] virtualIds) {
+            contentCaptureSession.notifyViewsDisappeared(hostId, virtualIds);
+        }
+
+        @DoNotInline
+        static void notifyViewAppeared(
+                ContentCaptureSession contentCaptureSession, ViewStructure node) {
+            contentCaptureSession.notifyViewAppeared(node);
+        }
+        @DoNotInline
+        static ViewStructure newViewStructure(
+                ContentCaptureSession contentCaptureSession, View view) {
+            return contentCaptureSession.newViewStructure(view);
+        }
+
+        @DoNotInline
+        static ViewStructure newVirtualViewStructure(ContentCaptureSession contentCaptureSession,
+                AutofillId parentId, long virtualId) {
+            return contentCaptureSession.newVirtualViewStructure(parentId, virtualId);
+        }
+
+
+        @DoNotInline
+        static AutofillId newAutofillId(ContentCaptureSession contentCaptureSession,
+                AutofillId hostId, long virtualChildId) {
+            return contentCaptureSession.newAutofillId(hostId, virtualChildId);
+        }
+
+        @DoNotInline
+        public static void notifyViewTextChanged(ContentCaptureSession contentCaptureSession,
+                AutofillId id, CharSequence charSequence) {
+            contentCaptureSession.notifyViewTextChanged(id, charSequence);
+
+        }
+    }
+    @RequiresApi(23)
+    private static class Api23Impl {
+        private Api23Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static Bundle getExtras(ViewStructure viewStructure) {
+            return viewStructure.getExtras();
+        }
+
+    }
+}
diff --git a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewCompatShims.java b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewCompatShims.java
new file mode 100644
index 0000000..f94c668
--- /dev/null
+++ b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewCompatShims.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.platform.coreshims;
+
+import android.os.Build;
+import android.view.View;
+import android.view.autofill.AutofillId;
+import android.view.contentcapture.ContentCaptureSession;
+
+import androidx.annotation.DoNotInline;
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Helper for accessing features in {@link View}.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ViewCompatShims {
+    private ViewCompatShims() {
+        // This class is not instantiable.
+    }
+
+    @IntDef({
+            IMPORTANT_FOR_CONTENT_CAPTURE_AUTO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO,
+            IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS,
+            IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ImportantForContentCapture {}
+
+    /**
+     * Automatically determine whether a view is important for content capture.
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_AUTO = 0x0;
+
+    /**
+     * The view is important for content capture, and its children (if any) will be traversed.
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES = 0x1;
+
+    /**
+     * The view is not important for content capture, but its children (if any) will be traversed.
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO = 0x2;
+
+    /**
+     * The view is important for content capture, but its children (if any) will not be traversed.
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS = 0x4;
+
+    /**
+     * The view is not important for content capture, and its children (if any) will not be
+     * traversed.
+     */
+    public static final int IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS = 0x8;
+
+    /**
+     * Sets the mode for determining whether this view is considered important for content capture.
+     *
+     * <p>The platform determines the importance for autofill automatically but you
+     * can use this method to customize the behavior. Typically, a view that provides text should
+     * be marked as {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 30 and above, this method matches platform behavior.
+     * <li>SDK 29 and below, this method does nothing.
+     * </ul>
+     *
+     * @param v The View against which to invoke the method.
+     * @param mode {@link #IMPORTANT_FOR_CONTENT_CAPTURE_AUTO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES}, {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO},
+     * {@link #IMPORTANT_FOR_CONTENT_CAPTURE_YES_EXCLUDE_DESCENDANTS},
+     * or {@link #IMPORTANT_FOR_CONTENT_CAPTURE_NO_EXCLUDE_DESCENDANTS}.
+     *
+     * @attr ref android.R.styleable#View_importantForContentCapture
+     */
+    public static void setImportantForContentCapture(@NonNull View v,
+            @ImportantForContentCapture int mode) {
+        if (Build.VERSION.SDK_INT >= 30) {
+            Api30Impl.setImportantForContentCapture(v, mode);
+        }
+    }
+
+    /**
+     * Gets the session used to notify content capture events.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 29 and above, this method matches platform behavior.
+     * <li>SDK 28 and below, this method always return null.
+     * </ul>
+     *
+     * @param v The View against which to invoke the method.
+     * @return session explicitly set by {@link #setContentCaptureSession(ContentCaptureSession)},
+     * inherited by ancestors, default session or {@code null} if content capture is disabled for
+     * this view.
+     */
+    @Nullable
+    public static ContentCaptureSessionCompat getContentCaptureSession(@NonNull View v) {
+        if (Build.VERSION.SDK_INT >= 29) {
+            ContentCaptureSession session = Api29Impl.getContentCaptureSession(v);
+            if (session == null) {
+                return null;
+            }
+            return ContentCaptureSessionCompat.toContentCaptureSessionCompat(session, v);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
+     *
+     * <p>The autofill id is created on demand, unless it is explicitly set by
+     * {@link #setAutofillId(AutofillId)}.
+     *
+     * <p>See {@link #setAutofillId(AutofillId)} for more info.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 26 and above, this method matches platform behavior.
+     * <li>SDK 25 and below, this method always return null.
+     * </ul>
+     *
+     * @param v The View against which to invoke the method.
+     * @return The View's autofill id.
+     */
+    @Nullable
+    public static AutofillIdCompat getAutofillId(@NonNull View v) {
+        if (Build.VERSION.SDK_INT >= 26) {
+            return AutofillIdCompat.toAutofillIdCompat(Api26Impl.getAutofillId(v));
+        }
+        return null;
+    }
+
+    @RequiresApi(26)
+    static class Api26Impl {
+        private Api26Impl() {
+            // This class is not instantiable.
+        }
+        @DoNotInline
+        public static AutofillId getAutofillId(View view) {
+            return view.getAutofillId();
+        }
+    }
+
+    @RequiresApi(29)
+    private static class Api29Impl {
+        private Api29Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static ContentCaptureSession getContentCaptureSession(View view) {
+            return view.getContentCaptureSession();
+        }
+    }
+
+    @RequiresApi(30)
+    private static class Api30Impl {
+        private Api30Impl() {
+            // This class is not instantiable.
+        }
+        @DoNotInline
+        static void setImportantForContentCapture(View view, int mode) {
+            view.setImportantForContentCapture(mode);
+        }
+    }
+}
diff --git a/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewStructureCompat.java b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewStructureCompat.java
new file mode 100644
index 0000000..3ffcfc2
--- /dev/null
+++ b/compose/ui/ui/src/main/java/androidx/compose/ui/platform/coreshims/ViewStructureCompat.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.platform.coreshims;
+
+import static android.os.Build.VERSION.SDK_INT;
+
+import android.view.ViewStructure;
+
+import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
+
+/**
+ * Helper for accessing features in {@link ViewStructure}.
+ * <p>
+ * Currently this helper class only has features for content capture usage. Other features for
+ * Autofill are not available.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY)
+public class ViewStructureCompat {
+
+    // Only guaranteed to be non-null on SDK_INT >= 23.
+    private final Object mWrappedObj;
+
+    /**
+     * Provides a backward-compatible wrapper for {@link ViewStructure}.
+     * <p>
+     * This method is not supported on devices running SDK < 23 since the platform
+     * class will not be available.
+     *
+     * @param contentCaptureSession platform class to wrap
+     * @return wrapped class
+     */
+    @RequiresApi(23)
+    @NonNull
+    public static ViewStructureCompat toViewStructureCompat(
+            @NonNull ViewStructure contentCaptureSession) {
+        return new ViewStructureCompat(contentCaptureSession);
+    }
+
+    /**
+     * Provides the {@link ViewStructure} represented by this object.
+     * <p>
+     * This method is not supported on devices running SDK < 23 since the platform
+     * class will not be available.
+     *
+     * @return platform class object
+     * @see ViewStructureCompat#toViewStructureCompat(ViewStructure)
+     */
+    @RequiresApi(23)
+    @NonNull
+    public ViewStructure toViewStructure() {
+        return (ViewStructure) mWrappedObj;
+    }
+
+    private ViewStructureCompat(@NonNull ViewStructure viewStructure) {
+        this.mWrappedObj = viewStructure;
+    }
+
+    /**
+     * Set the text that is associated with this view.  There is no selection
+     * associated with the text.  The text may have style spans to supply additional
+     * display and semantic information.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 23 and above, this method matches platform behavior.
+     * <li>SDK 22 and below, this method does nothing.
+     * </ul>
+     */
+    public void setText(@NonNull CharSequence charSequence) {
+        if (SDK_INT >= 23) {
+            Api23Impl.setText((ViewStructure) mWrappedObj, charSequence);
+        }
+    }
+
+    /**
+     * Set the class name of the view, as per
+     * {@link android.view.View#getAccessibilityClassName View.getAccessibilityClassName()}.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 23 and above, this method matches platform behavior.
+     * <li>SDK 22 and below, this method does nothing.
+     * </ul>
+     */
+    public void setClassName(@NonNull String string) {
+        if (SDK_INT >= 23) {
+            Api23Impl.setClassName((ViewStructure) mWrappedObj, string);
+        }
+    }
+
+    /**
+     * Explicitly set default global style information for text that was previously set with
+     * {@link #setText}.
+     *
+     * @param size The size, in pixels, of the text.
+     * @param fgColor The foreground color, packed as 0xAARRGGBB.
+     * @param bgColor The background color, packed as 0xAARRGGBB.
+     * @param style Style flags, as defined by {@link android.app.assist.AssistStructure.ViewNode}.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 23 and above, this method matches platform behavior.
+     * <li>SDK 22 and below, this method does nothing.
+     * </ul>
+     */
+    public void setTextStyle(float size, int fgColor, int bgColor, int style) {
+        if (SDK_INT >= 23) {
+            Api23Impl.setTextStyle((ViewStructure) mWrappedObj, size, fgColor, bgColor, style);
+        }
+    }
+
+    /**
+     * Set the content description of the view, as per
+     * {@link android.view.View#getContentDescription View.getContentDescription()}.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 23 and above, this method matches platform behavior.
+     * <li>SDK 22 and below, this method does nothing.
+     * </ul>
+     */
+    public void setContentDescription(@NonNull CharSequence charSequence) {
+        if (SDK_INT >= 23) {
+            Api23Impl.setContentDescription((ViewStructure) mWrappedObj, charSequence);
+        }
+    }
+
+    /**
+     * Set the basic dimensions of this view.
+     *
+     * @param left The view's left position, in pixels relative to its parent's left edge.
+     * @param top The view's top position, in pixels relative to its parent's top edge.
+     * @param scrollX How much the view's x coordinate space has been scrolled, in pixels.
+     * @param scrollY How much the view's y coordinate space has been scrolled, in pixels.
+     * @param width The view's visible width, in pixels.  This is the width visible on screen,
+     * not the total data width of a scrollable view.
+     * @param height The view's visible height, in pixels.  This is the height visible on
+     * screen, not the total data height of a scrollable view.
+     *
+     * Compatibility behavior:
+     * <ul>
+     * <li>SDK 23 and above, this method matches platform behavior.
+     * <li>SDK 22 and below, this method does nothing.
+     * </ul>
+     */
+    public void setDimens(int left, int top, int scrollX, int scrollY, int width, int height) {
+        if (SDK_INT >= 23) {
+            Api23Impl.setDimens(
+                    (ViewStructure) mWrappedObj, left, top, scrollX, scrollY, width, height);
+        }
+    }
+
+    @RequiresApi(23)
+    private static class Api23Impl {
+        private Api23Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static void setDimens(ViewStructure viewStructure, int left, int top, int scrollX,
+                int scrollY, int width, int height) {
+            viewStructure.setDimens(left, top, scrollX, scrollY, width, height);
+        }
+
+        @DoNotInline
+        static void setText(ViewStructure viewStructure, CharSequence charSequence) {
+            viewStructure.setText(charSequence);
+        }
+
+        @DoNotInline
+        static void setClassName(ViewStructure viewStructure, String string) {
+            viewStructure.setClassName(string);
+        }
+
+        @DoNotInline
+        static void setContentDescription(ViewStructure viewStructure, CharSequence charSequence) {
+            viewStructure.setContentDescription(charSequence);
+        }
+
+        @DoNotInline
+        static void setTextStyle(
+                ViewStructure viewStructure, float size, int fgColor, int bgColor, int style) {
+            viewStructure.setTextStyle(size, fgColor, bgColor, style);
+        }
+    }
+}
diff --git a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
index 81d62ef..123aafb 100644
--- a/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
+++ b/compose/ui/ui/src/skikoMain/kotlin/androidx/compose/ui/platform/SkiaBasedOwner.skiko.kt
@@ -29,6 +29,7 @@
 import androidx.compose.ui.PrimaryPressedPointerButtons
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusDirection
 import androidx.compose.ui.focus.FocusDirection.Companion.In
 import androidx.compose.ui.focus.FocusDirection.Companion.Next
@@ -508,6 +509,10 @@
         component.textInputSession(session)
     }
 
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        TODO("Not yet implemented")
+    }
+
     // A Stub for the PointerIconService required in Owner.kt
     override val pointerIconService: PointerIconService =
         object : PointerIconService {
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker1DTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker1DTest.kt
index be20d3e..a847660 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker1DTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTracker1DTest.kt
@@ -38,6 +38,7 @@
             VelocityTracker1D(isDataDifferential = true, Strategy.Lsq2)
         }
     }
+
     @Test
     fun twoPoints_nonDifferentialValues() {
         checkTestCase(
@@ -651,7 +652,7 @@
 
     /** Test cases derived from [VelocityTrackerTest]. */
     @Test
-    fun testsFromThe2DVelocityTrackerTest() {
+    fun testsFromThe2DVelocityTrackerTest_noClamping() {
         var xDataPoints: MutableList<DataPointAtTime> = mutableListOf()
         var yDataPoints: MutableList<DataPointAtTime> = mutableListOf()
 
@@ -692,6 +693,58 @@
         }
     }
 
+    @Test
+    fun calculateVelocityWithMaxValue_valueShouldBeGreaterThanZero() {
+        val tracker = VelocityTracker1D()
+        assertThrows(IllegalStateException::class.java) {
+            tracker.calculateVelocity(-1f)
+        }
+    }
+
+    @Test
+    fun testsFromThe2DVelocityTrackerTest_withVelocityClamping() {
+        var xDataPoints: MutableList<DataPointAtTime> = mutableListOf()
+        var yDataPoints: MutableList<DataPointAtTime> = mutableListOf()
+        val maximumVelocity = 500f
+        var i = 0
+        velocityEventData.forEach {
+            if (it.down) {
+                xDataPoints.add(DataPointAtTime(it.uptime, it.position.x))
+                yDataPoints.add(DataPointAtTime(it.uptime, it.position.y))
+            } else {
+                // Check velocity along the X axis
+                checkTestCase(
+                    VelocityTrackingTestCase(
+                        differentialDataPoints = false,
+                        dataPoints = xDataPoints,
+                        expectedVelocities = listOf(
+                            ExpectedVelocity(
+                                Strategy.Lsq2, expected2DVelocities[i].first
+                            )
+                        ),
+                        maximumVelocity = maximumVelocity
+                    ),
+                )
+                // Check velocity along the Y axis
+                checkTestCase(
+                    VelocityTrackingTestCase(
+                        differentialDataPoints = false,
+                        dataPoints = yDataPoints,
+                        expectedVelocities = listOf(
+                            ExpectedVelocity(
+                                Strategy.Lsq2, expected2DVelocities[i].second
+                            )
+                        ),
+                        maximumVelocity = maximumVelocity
+                    ),
+                )
+                xDataPoints = mutableListOf()
+                yDataPoints = mutableListOf()
+                i += 1
+            }
+        }
+    }
+
     private fun checkTestCase(testCase: VelocityTrackingTestCase) {
         testCase.expectedVelocities.forEach { expectedVelocity ->
             val tracker = VelocityTracker1D(
@@ -702,11 +755,21 @@
                 tracker.addDataPoint(it.time, it.dataPoint)
             }
 
-            assertWithMessage("Wrong velocity for data points: ${testCase.dataPoints}" +
-                "\nExpected velocity: {$expectedVelocity}")
-                .that(tracker.calculateVelocity())
-                .isWithin(abs(expectedVelocity.velocity) * Tolerance)
-                .of(expectedVelocity.velocity)
+            val clampedVelocity = if (expectedVelocity.velocity == 0.0f) {
+                0.0f
+            } else if (expectedVelocity.velocity > 0) {
+                expectedVelocity.velocity.coerceAtMost(testCase.maximumVelocity)
+            } else {
+                expectedVelocity.velocity.coerceAtLeast(-testCase.maximumVelocity)
+            }
+
+            assertWithMessage(
+                "Wrong velocity for data points: ${testCase.dataPoints}" +
+                    "\nExpected velocity: {$clampedVelocity}"
+            )
+                .that(tracker.calculateVelocity(testCase.maximumVelocity))
+                .isWithin(abs(clampedVelocity) * Tolerance)
+                .of(clampedVelocity)
         }
     }
 }
@@ -718,5 +781,6 @@
 private data class VelocityTrackingTestCase(
     val differentialDataPoints: Boolean,
     val dataPoints: List<DataPointAtTime>,
-    val expectedVelocities: List<ExpectedVelocity>
+    val expectedVelocities: List<ExpectedVelocity>,
+    val maximumVelocity: Float = Float.MAX_VALUE
 )
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
index 2016513..88c22cf 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/input/pointer/util/VelocityTrackerTest.kt
@@ -19,6 +19,9 @@
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.unit.Velocity
 import com.google.common.truth.Truth.assertThat
+import kotlin.math.absoluteValue
+import kotlin.math.sign
+import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -40,7 +43,30 @@
                 checkVelocity(
                     tracker.calculateVelocity(),
                     expected2DVelocities[i].first,
-                    expected2DVelocities[i].second)
+                    expected2DVelocities[i].second
+                )
+                tracker.resetTracking()
+                i += 1
+            }
+        }
+    }
+
+    @Test
+    fun calculateVelocity_returnsExpectedValues_withMaximumVelocity() {
+        val tracker = VelocityTracker()
+        var i = 0
+        val maximumVelocity = Velocity(200f, 200f)
+        velocityEventData.forEach {
+            if (it.down) {
+                tracker.addPosition(it.uptime, it.position)
+            } else {
+                val expectedDx = expected2DVelocities[i].first
+                val expectedDY = expected2DVelocities[i].second
+                checkVelocity(
+                    tracker.calculateVelocity(maximumVelocity = maximumVelocity),
+                    expectedDx.absoluteValue.coerceAtMost(maximumVelocity.x) * expectedDx.sign,
+                    expectedDY.absoluteValue.coerceAtMost(maximumVelocity.y) * expectedDY.sign
+                )
                 tracker.resetTracking()
                 i += 1
             }
@@ -93,6 +119,18 @@
         assertThat(tracker.calculateVelocity()).isEqualTo(Velocity.Zero)
     }
 
+    @Test
+    fun calculateVelocityWithMaxValue_valueShouldBeGreaterThanZero() {
+        val tracker = VelocityTracker()
+        Assert.assertThrows(IllegalStateException::class.java) {
+            tracker.calculateVelocity(Velocity(-1f, 1f))
+        }
+
+        Assert.assertThrows(IllegalStateException::class.java) {
+            tracker.calculateVelocity(Velocity(1f, -1f))
+        }
+    }
+
     private fun checkVelocity(actual: Velocity, expectedDx: Float, expectedDy: Float) {
         assertThat(actual.x).isWithin(0.1f).of(expectedDx)
         assertThat(actual.y).isWithin(0.1f).of(expectedDy)
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
index 35642ad..8a9f3ad 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
@@ -20,6 +20,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.draw.DrawModifier
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.focus.FocusDirection
@@ -2621,6 +2622,10 @@
         TODO("Not yet implemented")
     }
 
+    override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+        TODO("Not yet implemented")
+    }
+
     val invalidatedLayers = mutableListOf<OwnedLayer>()
 
     override fun createLayer(
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
index d9a10fd..b107857 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
@@ -25,6 +25,7 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.autofill.Autofill
 import androidx.compose.ui.autofill.AutofillTree
+import androidx.compose.ui.draganddrop.DragAndDropInfo
 import androidx.compose.ui.focus.FocusOwner
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Canvas
@@ -421,6 +422,10 @@
         ): Nothing {
             TODO("Not yet implemented")
         }
+
+        override fun drag(dragAndDropInfo: DragAndDropInfo): Boolean {
+            TODO("Not yet implemented")
+        }
     }
 }
 
diff --git a/constraintlayout/constraintlayout-compose/lint-baseline.xml b/constraintlayout/constraintlayout-compose/lint-baseline.xml
index cacb99a..c1c9585 100644
--- a/constraintlayout/constraintlayout-compose/lint-baseline.xml
+++ b/constraintlayout/constraintlayout-compose/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanInlineOptIn"
@@ -47,6 +47,123 @@
     </issue>
 
     <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val a = anchors.filter { it &lt;= offset + 0.001 }.maxOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/carousel/CarouselSwipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val b = anchors.filter { it >= offset - 0.001 }.minOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/carousel/CarouselSwipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (child in root.children) {"
+        errorLine2="                   ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            root.children.forEach { child ->"
+        errorLine2="                          ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            for (child in root.children) {"
+        errorLine2="                       ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            for (child in root.children) {"
+        errorLine2="                       ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (element in designElements) {"
+        errorLine2="                     ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ConstraintLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            root.children.forEach { child ->"
+        errorLine2="                          ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (child in root.children) {"
+        errorLine2="                   ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (child in root.children) {"
+        errorLine2="                   ~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/MotionMeasurer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    root.children.forEach { constraintWidget ->"
+        errorLine2="                  ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ToolingUtils.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        constraintWidget.anchors.forEach { anchor ->"
+        errorLine2="                                 ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ToolingUtils.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    helperReferences.forEach(helperReferencesArray::put)"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/androidMain/kotlin/androidx/constraintlayout/compose/ToolingUtils.kt"/>
+    </issue>
+
+    <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method setThresholds$lint_module has parameter &apos;&lt;set-?>&apos; with type Function2&lt;? super Float, ? super Float, Float>."
         errorLine1="    internal var thresholds: (Float, Float) -> Float by mutableStateOf({ _, _ -> 0f })"
diff --git a/core/core-location-altitude-proto/build.gradle b/core/core-location-altitude-proto/build.gradle
index c8455e4..02afaf0 100644
--- a/core/core-location-altitude-proto/build.gradle
+++ b/core/core-location-altitude-proto/build.gradle
@@ -50,22 +50,6 @@
     }
 }
 
-def preferencesProtoJarJarTask = tasks.register("exportJar", Jar) {
-    archiveBaseName.set("export")
-    from(sourceSets.main.output)
-    // The proto-lite dependency includes .proto files, which are not used by the altitude
-    // compatibility library. When apps depend on this library as well as proto-lite directly, these
-    // files conflict since jarjar only renames the java classes. Remove them here since they are
-    // unused.
-    exclude("**/*.proto")
-
-    from(zipTree(configurations.detachedConfiguration(
-            dependencies.create(libs.protobufLite.get())).getSingleFile()))
-}
-
-def jarjarConf = configurations.register("export")
-artifacts.add(jarjarConf.name, preferencesProtoJarJarTask.flatMap { it.archiveFile })
-
 androidx {
     name = "Location Altitude Compatibility Library Protos"
     publish = Publish.NONE
diff --git a/core/core-location-altitude/build.gradle b/core/core-location-altitude/build.gradle
index e8c31d9..ddd54e2 100644
--- a/core/core-location-altitude/build.gradle
+++ b/core/core-location-altitude/build.gradle
@@ -35,14 +35,17 @@
 BundleInsideHelper.forInsideAar(
         project,
         /* from = */ "com.google.protobuf",
-        /* to =   */ "androidx.core.location.altitude.impl.proto"
+        /* to =   */ "androidx.core.location.altitude.impl.proto",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
     api(libs.kotlinStdlib)
     api("androidx.annotation:annotation:1.5.0")
 
-    bundleInside(project(path: ":core:core-location-altitude-proto", configuration: "export"))
+    bundleInside(project(":core:core-location-altitude-proto"))
 
     implementation(libs.autoValueAnnotations)
     implementation(project(":core:core"))
diff --git a/core/core-telecom/api/current.txt b/core/core-telecom/api/current.txt
index 28e309e..b01e13c 100644
--- a/core/core-telecom/api/current.txt
+++ b/core/core-telecom/api/current.txt
@@ -26,13 +26,6 @@
   public static final class CallAttributesCompat.Companion {
   }
 
-  public interface CallControlCallback {
-    method public suspend Object? onAnswer(int callType, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onDisconnect(android.telecom.DisconnectCause disconnectCause, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onSetActive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onSetInactive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-  }
-
   public interface CallControlScope extends kotlinx.coroutines.CoroutineScope {
     method public suspend Object? answer(int callType, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend Object? disconnect(android.telecom.DisconnectCause disconnectCause, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
@@ -42,7 +35,6 @@
     method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> isMuted();
     method public suspend Object? requestEndpointChange(androidx.core.telecom.CallEndpointCompat endpoint, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend Object? setActive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public void setCallback(androidx.core.telecom.CallControlCallback callControlCallback);
     method public suspend Object? setInactive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     property public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.core.telecom.CallEndpointCompat>> availableEndpoints;
     property public abstract kotlinx.coroutines.flow.Flow<androidx.core.telecom.CallEndpointCompat> currentCallEndpoint;
@@ -74,7 +66,7 @@
     method public int getCode();
     property public final int code;
     field public static final androidx.core.telecom.CallException.Companion Companion;
-    field public static final int ERROR_CALLBACKS_CODE = 2; // 0x2
+    field public static final int ERROR_BUILD_VERSION_CODE = 0; // 0x0
     field public static final int ERROR_UNKNOWN_CODE = 1; // 0x1
   }
 
@@ -83,7 +75,7 @@
 
   @RequiresApi(android.os.Build.VERSION_CODES.O) public final class CallsManager {
     ctor public CallsManager(android.content.Context context);
-    method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public suspend Object? addCall(androidx.core.telecom.CallAttributesCompat callAttributes, kotlin.jvm.functions.Function1<? super androidx.core.telecom.CallControlScope,kotlin.Unit> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public suspend Object? addCall(androidx.core.telecom.CallAttributesCompat callAttributes, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onAnswer, kotlin.jvm.functions.Function2<? super android.telecom.DisconnectCause,? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onDisconnect, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onSetActive, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onSetInactive, kotlin.jvm.functions.Function1<? super androidx.core.telecom.CallControlScope,kotlin.Unit> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public void registerAppWithTelecom(int capabilities);
     field public static final int CAPABILITY_BASELINE = 1; // 0x1
     field public static final int CAPABILITY_SUPPORTS_CALL_STREAMING = 4; // 0x4
diff --git a/core/core-telecom/api/restricted_current.txt b/core/core-telecom/api/restricted_current.txt
index 28e309e..b01e13c 100644
--- a/core/core-telecom/api/restricted_current.txt
+++ b/core/core-telecom/api/restricted_current.txt
@@ -26,13 +26,6 @@
   public static final class CallAttributesCompat.Companion {
   }
 
-  public interface CallControlCallback {
-    method public suspend Object? onAnswer(int callType, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onDisconnect(android.telecom.DisconnectCause disconnectCause, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onSetActive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public suspend Object? onSetInactive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-  }
-
   public interface CallControlScope extends kotlinx.coroutines.CoroutineScope {
     method public suspend Object? answer(int callType, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend Object? disconnect(android.telecom.DisconnectCause disconnectCause, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
@@ -42,7 +35,6 @@
     method public kotlinx.coroutines.flow.Flow<java.lang.Boolean> isMuted();
     method public suspend Object? requestEndpointChange(androidx.core.telecom.CallEndpointCompat endpoint, kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     method public suspend Object? setActive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
-    method public void setCallback(androidx.core.telecom.CallControlCallback callControlCallback);
     method public suspend Object? setInactive(kotlin.coroutines.Continuation<? super java.lang.Boolean>);
     property public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.core.telecom.CallEndpointCompat>> availableEndpoints;
     property public abstract kotlinx.coroutines.flow.Flow<androidx.core.telecom.CallEndpointCompat> currentCallEndpoint;
@@ -74,7 +66,7 @@
     method public int getCode();
     property public final int code;
     field public static final androidx.core.telecom.CallException.Companion Companion;
-    field public static final int ERROR_CALLBACKS_CODE = 2; // 0x2
+    field public static final int ERROR_BUILD_VERSION_CODE = 0; // 0x0
     field public static final int ERROR_UNKNOWN_CODE = 1; // 0x1
   }
 
@@ -83,7 +75,7 @@
 
   @RequiresApi(android.os.Build.VERSION_CODES.O) public final class CallsManager {
     ctor public CallsManager(android.content.Context context);
-    method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public suspend Object? addCall(androidx.core.telecom.CallAttributesCompat callAttributes, kotlin.jvm.functions.Function1<? super androidx.core.telecom.CallControlScope,kotlin.Unit> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public suspend Object? addCall(androidx.core.telecom.CallAttributesCompat callAttributes, kotlin.jvm.functions.Function2<? super java.lang.Integer,? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onAnswer, kotlin.jvm.functions.Function2<? super android.telecom.DisconnectCause,? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onDisconnect, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onSetActive, kotlin.jvm.functions.Function1<? super kotlin.coroutines.Continuation<? super java.lang.Boolean>,?> onSetInactive, kotlin.jvm.functions.Function1<? super androidx.core.telecom.CallControlScope,kotlin.Unit> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     method @RequiresPermission("android.permission.MANAGE_OWN_CALLS") public void registerAppWithTelecom(int capabilities);
     field public static final int CAPABILITY_BASELINE = 1; // 0x1
     field public static final int CAPABILITY_SUPPORTS_CALL_STREAMING = 4; // 0x4
diff --git a/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/CallingMainActivity.kt b/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/CallingMainActivity.kt
index 64619dd..b793f38 100644
--- a/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/CallingMainActivity.kt
+++ b/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/CallingMainActivity.kt
@@ -124,10 +124,13 @@
 
             CoroutineScope(Dispatchers.IO).launch(handler) {
                 try {
-                    mCallsManager!!.addCall(attributes) {
-                        // set the client callback implementation
-                        setCallback(callObject.mCallControlCallbackImpl)
-
+                    mCallsManager!!.addCall(
+                        attributes,
+                        callObject.mOnAnswerLambda,
+                        callObject.mOnDisconnectLambda,
+                        callObject.mOnSetActiveLambda,
+                        callObject.mOnSetInActiveLambda
+                    ) {
                         // inject client control interface into the VoIP call object
                         callObject.setCallId(getCallId().toString())
                         callObject.setCallControl(this)
diff --git a/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/VoipCall.kt b/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/VoipCall.kt
index c984ad9..5089cd9 100644
--- a/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/VoipCall.kt
+++ b/core/core-telecom/integration-tests/testapp/src/main/java/androidx/core/telecom/test/VoipCall.kt
@@ -19,7 +19,6 @@
 import android.telecom.DisconnectCause
 import android.util.Log
 import androidx.annotation.RequiresApi
-import androidx.core.telecom.CallControlCallback
 import androidx.core.telecom.CallControlScope
 import androidx.core.telecom.CallEndpointCompat
 
@@ -34,23 +33,28 @@
     var mIsMuted = false
     var mTelecomCallId: String = ""
 
-    val mCallControlCallbackImpl = object : CallControlCallback {
-        override suspend fun onSetActive(): Boolean {
-            mAdapter?.updateCallState(mTelecomCallId, "Active")
-            return true
-        }
-        override suspend fun onSetInactive(): Boolean {
-            mAdapter?.updateCallState(mTelecomCallId, "Inactive")
-            return true
-        }
-        override suspend fun onAnswer(callType: Int): Boolean {
-            mAdapter?.updateCallState(mTelecomCallId, "Answered")
-            return true
-        }
-        override suspend fun onDisconnect(disconnectCause: DisconnectCause): Boolean {
-            mAdapter?.updateCallState(mTelecomCallId, "Disconnected")
-            return true
-        }
+    val mOnSetActiveLambda: suspend () -> Boolean = {
+        Log.i(TAG, "onSetActive: completing")
+        mAdapter?.updateCallState(mTelecomCallId, "Active")
+        true
+    }
+
+    val mOnSetInActiveLambda: suspend () -> Boolean = {
+        Log.i(TAG, "onSetInactive: completing")
+        mAdapter?.updateCallState(mTelecomCallId, "Inactive")
+        true
+    }
+
+    val mOnAnswerLambda: suspend (type: Int) -> Boolean = {
+        Log.i(TAG, "onAnswer: callType=[$it]")
+        mAdapter?.updateCallState(mTelecomCallId, "Answered")
+        true
+    }
+
+    val mOnDisconnectLambda: suspend (cause: DisconnectCause) -> Boolean = {
+        Log.i(TAG, "onDisconnect: disconnectCause=[$it]")
+        mAdapter?.updateCallState(mTelecomCallId, "Disconnected")
+        true
     }
 
     fun setCallControl(callControl: CallControlScope) {
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlCallbacksTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlCallbacksTest.kt
index 302eac0..717b07b9 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlCallbacksTest.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlCallbacksTest.kt
@@ -312,8 +312,12 @@
     private fun verifyAnswerCall() {
         assertFalse(TestUtils.mOnAnswerCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
                     assertNotNull("The returned Call object is <NULL>", call)
@@ -332,8 +336,12 @@
     private fun verifyDisconnectCall() {
         assertFalse(TestUtils.mOnDisconnectCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
                     assertNotNull("The returned Call object is <NULL>", call)
@@ -353,8 +361,12 @@
     private fun verifyHoldCall() {
         assertFalse(TestUtils.mOnSetInactiveCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
                     assertNotNull("The returned Call object is <NULL>", call)
@@ -377,8 +389,12 @@
     private fun verifyUnholdCall() {
         assertFalse(TestUtils.mOnSetActiveCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
                     assertNotNull("The returned Call object is <NULL>", call)
@@ -404,8 +420,12 @@
     private fun verifyRejectAnswerCall(callState: Int) {
         assertFalse(TestUtils.mOnAnswerCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 // Note that this is reset in BaseTelecomTest in setUp/destroy
                 TestUtils.mCompleteOnAnswer = false
                 launch {
@@ -429,8 +449,12 @@
     private fun verifyRejectHoldCall() {
         assertFalse(TestUtils.mOnSetInactiveCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 TestUtils.mCompleteOnSetInactive = false
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
@@ -454,8 +478,12 @@
     private fun verifyRejectUnholdCall() {
         assertFalse(TestUtils.mOnSetActiveCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
                     assertNotNull("The returned Call object is <NULL>", call)
@@ -482,8 +510,12 @@
     private fun verifyRejectDisconnectCall(invokeDisconnect: Boolean) {
         assertFalse(TestUtils.mOnDisconnectCallbackCalled)
         runBlocking {
-            mCallsManager.addCall(TestUtils.INCOMING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.INCOMING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda) {
                 TestUtils.mCompleteOnDisconnect = false
                 launch {
                     val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlsTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlsTest.kt
index 9c64b4a..45daaeb 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlsTest.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/BasicCallControlsTest.kt
@@ -23,7 +23,6 @@
 import androidx.core.telecom.CallAttributesCompat
 import androidx.core.telecom.CallControlScope
 import androidx.core.telecom.CallEndpointCompat
-import androidx.core.telecom.CallException
 import androidx.core.telecom.internal.utils.Utils
 import androidx.core.telecom.test.utils.BaseTelecomTest
 import androidx.core.telecom.test.utils.MockInCallService
@@ -123,8 +122,10 @@
     @Test(timeout = 10000)
     fun testTogglingHoldOnActiveCall_NoHoldCapabilities() {
         setUpV2Test()
-        assertFalse(TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES
-            .hasSupportsSetInactiveCapability())
+        assertFalse(
+            TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES
+                .hasSupportsSetInactiveCapability()
+        )
         runBlocking_ShouldFailHold(TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES)
     }
 
@@ -154,18 +155,6 @@
         verifyMuteStateChange()
     }
 
-    /**
-     * assert that an exception is thrown in the call flow when CallControlScope#setCallbacks isn't
-     * the first function to be invoked. The call should use the *V2 platform APIs* under the hood.
-     */
-    @SdkSuppress(minSdkVersion = VERSION_CODES.UPSIDE_DOWN_CAKE)
-    @LargeTest
-    @Test(timeout = 10000)
-    fun testBasicCallControlCallbackOperations_CallbackNotSet() {
-        setUpV2Test()
-        verifyAnswerCallFails_CallbackNotSet()
-    }
-
     /***********************************************************************************************
      *                           Backwards Compatibility Layer tests
      *********************************************************************************************/
@@ -220,8 +209,10 @@
     @Test(timeout = 10000)
     fun testTogglingHoldOnActiveCall_NoHoldCapabilities_BackwardsCompat() {
         setUpBackwardsCompatTest()
-        assertFalse(TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES
-            .hasSupportsSetInactiveCapability())
+        assertFalse(
+            TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES
+                .hasSupportsSetInactiveCapability()
+        )
         runBlocking_ShouldFailHold(TestUtils.OUTGOING_NO_HOLD_CAP_CALL_ATTRIBUTES)
     }
 
@@ -255,19 +246,6 @@
     }
 
     /**
-     * assert that an exception is thrown in the call flow when CallControlScope#setCallbacks isn't
-     * the first function to be invoked. The call should use the
-     * *[android.telecom.ConnectionService] and [android.telecom.Connection] APIs* under the hood.
-     */
-    @SdkSuppress(minSdkVersion = VERSION_CODES.O)
-    @LargeTest
-    @Test(timeout = 10000)
-    fun testBasicCallControlCallbackOperations_BackwardsCompat_CallbackNotSet() {
-        setUpBackwardsCompatTest()
-        verifyAnswerCallFails_CallbackNotSet()
-    }
-
-    /**
      * Verify that the [androidx.core.telecom.CallsManager.addCall] blocks until the session is
      * disconnected
      */
@@ -278,8 +256,13 @@
         setUpBackwardsCompatTest()
         var flag = false
         runBlocking {
-            mCallsManager.addCall(TestUtils.OUTGOING_CALL_ATTRIBUTES) {
-                setCallback(TestUtils.mCallControlCallbacksImpl)
+            mCallsManager.addCall(
+                TestUtils.OUTGOING_CALL_ATTRIBUTES,
+                TestUtils.mOnAnswerLambda,
+                TestUtils.mOnDisconnectLambda,
+                TestUtils.mOnSetActiveLambda,
+                TestUtils.mOnSetInActiveLambda,
+            ) {
                 launch {
                     delay(10)
                     disconnect(DisconnectCause(DisconnectCause.LOCAL))
@@ -428,33 +411,6 @@
         }
     }
 
-    @Suppress("deprecation")
-    private fun verifyAnswerCallFails_CallbackNotSet() {
-        try {
-            runBlocking {
-                // Skip setting callback
-                assertWithinTimeout_addCall(TestUtils.INCOMING_CALL_ATTRIBUTES, false) {
-                    launch {
-                        val call = TestUtils.waitOnInCallServiceToReachXCalls(1)
-                        assertNotNull("The returned Call object is <NULL>", call)
-                        // Send answer request
-                        answer(CallAttributesCompat.CALL_TYPE_AUDIO_CALL)
-                        // Always send the disconnect signal if possible:
-                        disconnect(DisconnectCause(DisconnectCause.LOCAL))
-                        // CallException should be thrown at this point. Add failing assertion to
-                        // ensure that the exception is always thrown.
-                        assertTrue("Call was set to active without setting callbacks", false)
-                    }
-                }
-            }
-        } catch (e: CallException) {
-            // Exception should be thrown from not setting the callback.
-            assertTrue(e.code == CallException.ERROR_CALLBACKS_CODE)
-            // Assert that the callback wasn't invoked
-            assertFalse(TestUtils.mOnAnswerCallbackCalled)
-        }
-    }
-
     private fun getAnotherEndpoint(
         currentEndpoint: CallEndpointCompat,
         availableEndpoints: List<CallEndpointCompat>
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/JetpackConnectionServiceTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/JetpackConnectionServiceTest.kt
index 1bdfbdc..35a88ff 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/JetpackConnectionServiceTest.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/JetpackConnectionServiceTest.kt
@@ -124,7 +124,12 @@
         ConnectionRequest {
         // wrap in PendingRequest
         val pr = JetpackConnectionService.PendingConnectionRequest(
-            callAttributesCompat, callChannels, mWorkerContext, null, CompletableDeferred()
+            callAttributesCompat, callChannels, mWorkerContext, null,
+            TestUtils.mOnAnswerLambda,
+            TestUtils.mOnDisconnectLambda,
+            TestUtils.mOnSetActiveLambda,
+            TestUtils.mOnSetInActiveLambda,
+            CompletableDeferred()
         )
         // add to the list of pendingRequests
         JetpackConnectionService.mPendingConnectionRequests.add(pr)
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/BaseTelecomTest.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/BaseTelecomTest.kt
index aa162db..71c4280 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/BaseTelecomTest.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/BaseTelecomTest.kt
@@ -143,20 +143,20 @@
      */
     suspend fun assertWithinTimeout_addCall(
         attributes: CallAttributesCompat,
-        setCallback: Boolean = true,
         assertBlock: CallControlScope.() -> (Unit)
     ) {
         Log.i(TestUtils.LOG_TAG, "assertWithinTimeout_addCall")
         var callControlScope: CallControlScope? = null
         try {
             withTimeout(TestUtils.WAIT_ON_ASSERTS_TO_FINISH_TIMEOUT) {
-                mCallsManager.addCall(attributes) {
+                mCallsManager.addCall(
+                    attributes,
+                    TestUtils.mOnAnswerLambda,
+                    TestUtils.mOnDisconnectLambda,
+                    TestUtils.mOnSetActiveLambda,
+                    TestUtils.mOnSetInActiveLambda,
+                ) {
                     callControlScope = this
-                    if (setCallback) {
-                        setCallback(TestUtils.mCallControlCallbacksImpl)
-                        Log.i(TestUtils.LOG_TAG, "assertWithinTimeout_addCall: setCallback " +
-                            "to ${TestUtils.mCallControlCallbacksImpl}")
-                    }
                     assertBlock()
                 }
             }
diff --git a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/TestUtils.kt b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/TestUtils.kt
index 68c9de5..5aba448 100644
--- a/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/TestUtils.kt
+++ b/core/core-telecom/src/androidTest/java/androidx/core/telecom/test/utils/TestUtils.kt
@@ -28,7 +28,6 @@
 import android.util.Log
 import androidx.annotation.RequiresApi
 import androidx.core.telecom.CallAttributesCompat
-import androidx.core.telecom.CallControlCallback
 import androidx.core.telecom.internal.utils.BuildVersionAdapter
 import androidx.test.platform.app.InstrumentationRegistry
 import java.io.FileInputStream
@@ -133,35 +132,28 @@
         }
     }
 
-    /**
-     * This [CallControlCallback] implementation will be called by the platform whenever an
-     * InCallService wants to [answer, setActive, setInactive, or disconnect] a particular call
-     * and will immediately complete/reject the transaction depending on the return type.
-     */
-    val mCallControlCallbacksImpl = object : CallControlCallback {
-        override suspend fun onSetActive(): Boolean {
-            Log.i(LOG_TAG, "mCACCCI: onSetActive: completing")
-            mOnSetActiveCallbackCalled = true
-            return mCompleteOnSetActive
-        }
+    val mOnSetActiveLambda: suspend () -> Boolean = {
+        Log.i(LOG_TAG, "onSetActive: completing")
+        mOnSetActiveCallbackCalled = true
+        mCompleteOnSetActive
+    }
 
-        override suspend fun onSetInactive(): Boolean {
-            Log.i(LOG_TAG, "mCACCCI: onSetInactive: completing")
-            mOnSetInactiveCallbackCalled = true
-            return mCompleteOnSetInactive
-        }
+    val mOnSetInActiveLambda: suspend () -> Boolean = {
+        Log.i(LOG_TAG, "onSetInactive: completing")
+        mOnSetInactiveCallbackCalled = true
+        mCompleteOnSetInactive
+    }
 
-        override suspend fun onAnswer(callType: Int): Boolean {
-            Log.i(LOG_TAG, "mCACCCI: onAnswer: callType=[$callType]")
-            mOnAnswerCallbackCalled = true
-            return mCompleteOnAnswer
-        }
+    val mOnAnswerLambda: suspend (type: Int) -> Boolean = {
+        Log.i(LOG_TAG, "onAnswer: callType=[$it]")
+        mOnAnswerCallbackCalled = true
+        mCompleteOnAnswer
+    }
 
-        override suspend fun onDisconnect(disconnectCause: DisconnectCause): Boolean {
-            Log.i(LOG_TAG, "mCACCCI: onDisconnect: disconnectCause=[$disconnectCause]")
-            mOnDisconnectCallbackCalled = true
-            return mCompleteOnDisconnect
-        }
+    val mOnDisconnectLambda: suspend (cause: DisconnectCause) -> Boolean = {
+        Log.i(LOG_TAG, "onDisconnect: disconnectCause=[$it]")
+        mOnDisconnectCallbackCalled = true
+        mCompleteOnDisconnect
     }
 
     // Flags for determining whether the given callback was invoked or not
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/CallControlCallback.kt b/core/core-telecom/src/main/java/androidx/core/telecom/CallControlCallback.kt
deleted file mode 100644
index b39bb5c..0000000
--- a/core/core-telecom/src/main/java/androidx/core/telecom/CallControlCallback.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.core.telecom
-
-/**
- * CallControlCallback relays call updates (that require a response) from the Telecom framework out
- * to the application. This can include operations which the app must implement on a Call due to the
- * presence of other calls on the device, requests relayed from a Bluetooth device, or from another
- * calling surface.
- *
- *
- * All CallControlCallbacks are transactional, meaning that a client must
- * complete the suspend fun with a [Boolean] response in order to complete the
- * CallControlCallback. If the operation has been completed, the [suspend fun] should return
- * true. Otherwise, the suspend fun should be returned with a false to represent the
- * CallControlCallback cannot be completed on the client side.
- *
- *
- * Note: Each CallEventCallback has a timeout of 5000 milliseconds. Failing to complete the
- * suspend fun before the timeout will result in a failed transaction.
- */
-interface CallControlCallback {
-    /**
-     * Telecom is informing your VoIP application to set the call active.  Telecom is requesting
-     * this on behalf of an system service (e.g. Automotive service) or a device (e.g. Wearable).
-     *
-     * @return true to indicate your VoIP application can set the call (that corresponds to this
-     * CallControlCallback) to active. Otherwise, return false to indicate your application is
-     * unable to process the request and telecom will cancel the external request.
-     */
-    suspend fun onSetActive(): Boolean
-
-    /**
-     * Telecom is informing your VoIP application to set the call inactive. This is the same as
-     * holding a call for two endpoints but can be extended to setting a meeting inactive. Telecom
-     * is requesting this on behalf of an system service (e.g. Automotive service) or a device (e.g.
-     * Wearable).
-     *
-     * Note: Your app must stop using the microphone and playing incoming media when returning.
-     *
-     * @return true to indicate your VoIP application can transition the call state to inactive.
-     * Otherwise, return false to indicate your application is  unable to process the request and
-     * telecom will cancel the external request.
-     */
-    suspend fun onSetInactive(): Boolean
-
-    /**
-     * Telecom is informing your VoIP application to answer an incoming call and set it to active.
-     * Telecom is requesting this on behalf of an system service (e.g. Automotive service) or a
-     * device (e.g. Wearable).
-     *
-     * @param callType that call is requesting to be answered as.
-     *
-     * @return true to indicate your VoIP application can answer the call with the given
-     * [CallAttributesCompat.Companion.CallType]. Otherwise, return false to indicate your application is
-     * unable to process the request and telecom will cancel the external request.
-     */
-    suspend fun onAnswer(@CallAttributesCompat.Companion.CallType callType: Int): Boolean
-
-    /**
-     * Telecom is informing your VoIP application to disconnect the call. Telecom is requesting this
-     * on behalf of an system service (e.g. Automotive service) or a device (e.g. Wearable).
-     *
-     * @param disconnectCause represents the cause for disconnecting the call.
-     *
-     * @return true when your VoIP application has disconnected the call. Otherwise, return false to
-     * indicate your application is unable to process the request. However, telecom will still
-     * disconnect and untrack the call.
-     */
-    suspend fun onDisconnect(disconnectCause: android.telecom.DisconnectCause): Boolean
-}
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/CallControlScope.kt b/core/core-telecom/src/main/java/androidx/core/telecom/CallControlScope.kt
index 0714c39..c90b9b4 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/CallControlScope.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/CallControlScope.kt
@@ -45,14 +45,6 @@
  */
 interface CallControlScope : CoroutineScope {
     /**
-     * This method should be the first method called within the [CallControlScope] and your VoIP
-     * application should pass in a valid implementation of [CallControlCallback].  Failing to call
-     * this method first will result in a [CallException] to be thrown.
-     */
-    @Suppress("ExecutorRegistration")
-    fun setCallback(callControlCallback: CallControlCallback)
-
-    /**
      * @return the 128-bit universally unique identifier Telecom assigned to this CallControlScope.
      * This id can be helpful for debugging when dumping the telecom system.
      */
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/CallException.kt b/core/core-telecom/src/main/java/androidx/core/telecom/CallException.kt
index 93af510..75506f2 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/CallException.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/CallException.kt
@@ -34,33 +34,26 @@
     companion object {
         @RestrictTo(RestrictTo.Scope.LIBRARY)
         @Retention(AnnotationRetention.SOURCE)
-        @IntDef(ERROR_UNKNOWN_CODE, ERROR_CALLBACKS_CODE)
+        @IntDef(ERROR_BUILD_VERSION_CODE, ERROR_UNKNOWN_CODE)
         annotation class CallErrorCode
 
         /**
          * The operation has failed due to an unknown or unspecified error.
          */
+        const val ERROR_BUILD_VERSION_CODE = 0
+
+        internal const val ERROR_BUILD_VERSION_MSG: String = "Core-Telecom only supports builds" +
+            " from Oreo (Android 8) and above.  In order to utilize Core-Telecom, your device" +
+            " must be updated."
+
+        /**
+         * The operation has failed due to an unknown or unspecified error.
+         */
         const val ERROR_UNKNOWN_CODE = 1
 
-        /**
-         * This error code is thrown whenever a call is added via [CallsManager.addCall] and the
-         * [CallControlScope.setCallback]s is not the first API called in the session block or at
-         * all. In order to avoid this exception, ensure your [CallControlScope] is calling
-         * [CallControlScope.setCallback]s.
-         */
-        const val ERROR_CALLBACKS_CODE = 2
-
-        internal const val ERROR_CALLBACKS_MSG: String = "Error, when using the " +
-            "[CallControlScope], you must first set the " +
-            "[androidx.core.telecom.CallControlCallback]s via [CallControlScope]#[setCallback]"
-
-        internal const val ERROR_BUILD_VERSION: String = "Core-Telecom only supports builds from" +
-            " Oreo (Android 8) and above.  In order to utilize Core-Telecom, your device must" +
-            " be updated."
-
         internal fun codeToMessage(@CallErrorCode code: Int): String {
             when (code) {
-                ERROR_CALLBACKS_CODE -> return ERROR_CALLBACKS_MSG
+                ERROR_BUILD_VERSION_CODE -> return ERROR_BUILD_VERSION_MSG
             }
             return "An Unknown Error has occurred while using the Core-Telecom APIs"
         }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt b/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
index 89c75e8..9d0baa9f 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/CallsManager.kt
@@ -180,16 +180,66 @@
      *
      * @param callAttributes     attributes of the new call (incoming or outgoing, address, etc. )
      * @param block              DSL interface block that will run when the call is ready
+     * @param onAnswer           Telecom is informing your VoIP application to answer an incoming
+     *                           call and  set it to active. Telecom is requesting this on behalf
+     *                           of an system service (e.g. Automotive service) or a device (e.g.
+     *                           Wearable).
+     *
+     *                           @param callType that call is requesting to be answered as.
+     *
+     *                           @return true to indicate your VoIP application can answer the
+     *                           call with the given [CallAttributesCompat.Companion.CallType].
+     *                           Otherwise, return false to indicate your application is unable to
+     *                           process the request and telecom will cancel the external request.
+     *
+     * @param onDisconnect       Telecom is informing your VoIP application to disconnect the
+     *                           incoming  call and set it to active. Telecom is requesting this on
+     *                           behalf of an system service (e.g. Automotive service) or a device
+     *                           (e.g. Wearable).
+     *
+     *                           @param disconnectCause represents the cause for disconnecting the
+     *                           call.
+     *
+     *                           @return true when your VoIP application has disconnected the call.
+     *                           Otherwise, return false to indicate your application is unable to
+     *                           process the request. However, telecom will still
+     * @param onSetActive        Telecom is informing your VoIP application to set the call active.
+     *                           Telecom is requesting this on behalf of an system service (e.g.
+     *                           Automotive service) or a device (e.g. Wearable).
+     *
+     *                           @return true to indicate your VoIP application can set the call
+     *                           (that corresponds to this lambda function) to active.
+     *                           Otherwise, return false to indicate your application is unable to
+     *                           process the request and telecom will cancel the external request.
+     *
+     * @param onSetInactive      Telecom is informing your VoIP application to set the call
+     *                           inactive. This is the same as holding a call for two endpoints but
+     *                           can be extended to setting a meeting inactive. Telecom is
+     *                           requesting this on behalf of an system service (e.g. Automotive
+     *                           service) or a device (e.g.Wearable). Note: Your app must stop
+     *                           using the microphone and playing incoming media when returning.
+     *
+     *                           @return true to indicate your VoIP application can set the call
+     *                           (that corresponds to this lambda function) to inactive.
+     *                           Otherwise, return false to indicate your application is unable to
+     *                           process the request and telecom will cancel the external request.
+     *
+     * Note: Each lambda function (onAnswer, onDisconnect, onSetActive, onSetInactive) has a
+     * timeout of 5000 milliseconds. Failing to complete the suspend fun before the timeout will
+     * result in a failed transaction.
      *
      * @Throws UnsupportedOperationException if the device is on an invalid build
      * @Throws CancellationException if the call failed to be added within 5000 milliseconds
-     * @Throws CallException if [CallControlScope.setCallback] is not called first within the block
      */
     @RequiresPermission(value = "android.permission.MANAGE_OWN_CALLS")
     @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
     @Suppress("ClassVerificationFailure")
     suspend fun addCall(
         callAttributes: CallAttributesCompat,
+        onAnswer: suspend (callType: @CallAttributesCompat.Companion.CallType Int) -> Boolean,
+        onDisconnect: suspend (disconnectCause: android.telecom.DisconnectCause) -> Boolean,
+        onSetActive: suspend () -> Boolean,
+        onSetInactive: suspend () -> Boolean,
         block: CallControlScope.() -> Unit
     ) {
         // This API is not supported for device running anything below Android O (26)
@@ -210,7 +260,13 @@
             val openResult = CompletableDeferred<CallSession>(parent = coroutineContext.job)
             // CallSession is responsible for handling both CallControl responses from the Platform
             // and propagates CallControlCallbacks that originate in the Platform out to the client.
-            val callSession = CallSession(coroutineContext, blockingSessionExecution)
+            val callSession = CallSession(
+                coroutineContext,
+                onAnswer,
+                onDisconnect,
+                onSetActive,
+                onSetInactive,
+                blockingSessionExecution)
 
             /**
              * The Platform [android.telecom.TelecomManager.addCall] requires a
@@ -261,7 +317,15 @@
                 CompletableDeferred<CallSessionLegacy>(parent = coroutineContext.job)
 
             val request = JetpackConnectionService.PendingConnectionRequest(
-                callAttributes, callChannels, coroutineContext, openResult, blockingSessionExecution
+                callAttributes,
+                callChannels,
+                coroutineContext,
+                openResult,
+                onAnswer,
+                onDisconnect,
+                onSetActive,
+                onSetInactive,
+                blockingSessionExecution
             )
 
             mConnectionService.createConnectionRequest(mTelecomManager, request)
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSession.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSession.kt
index 495b7b9..52901d2 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSession.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSession.kt
@@ -22,7 +22,6 @@
 import android.telecom.CallException
 import android.telecom.DisconnectCause
 import androidx.annotation.RequiresApi
-import androidx.core.telecom.CallControlCallback
 import androidx.core.telecom.CallControlScope
 import androidx.core.telecom.CallEndpointCompat
 import androidx.core.telecom.internal.utils.EndpointUtils
@@ -39,11 +38,14 @@
 @Suppress("ClassVerificationFailure")
 internal class CallSession(
     coroutineContext: CoroutineContext,
+    val onAnswerCallback: suspend (callType: Int) -> Boolean,
+    val onDisconnectCallback: suspend (disconnectCause: DisconnectCause) -> Boolean,
+    val onSetActiveCallback: suspend () -> Boolean,
+    val onSetInactiveCallback: suspend () -> Boolean,
     private val blockingSessionExecution: CompletableDeferred<Unit>
 ) {
     private val mCoroutineContext = coroutineContext
     private var mPlatformInterface: android.telecom.CallControl? = null
-    private var mClientInterface: CallControlCallback? = null
 
     class CallControlCallbackImpl(private val callSession: CallSession) :
         android.telecom.CallControlCallback {
@@ -111,18 +113,6 @@
     }
 
     /**
-     * pass in the clients callback implementation for CallControlCallback that is set in the
-     * CallsManager#addCall scope.
-     */
-    fun setCallControlCallback(clientCallbackImpl: CallControlCallback) {
-        mClientInterface = clientCallbackImpl
-    }
-
-    fun hasClientSetCallbacks(): Boolean {
-        return mClientInterface != null
-    }
-
-    /**
      * Custom OutcomeReceiver that handles the Platform responses to a CallControl API call
      */
     inner class CallControlReceiver(deferred: CompletableDeferred<Boolean>) :
@@ -189,28 +179,28 @@
      */
     fun onSetActive(wasCompleted: Consumer<Boolean>) {
         CoroutineScope(mCoroutineContext).launch {
-            val clientResponse: Boolean = mClientInterface!!.onSetActive()
+            val clientResponse: Boolean = onSetActiveCallback()
             wasCompleted.accept(clientResponse)
         }
     }
 
     fun onSetInactive(wasCompleted: Consumer<Boolean>) {
         CoroutineScope(mCoroutineContext).launch {
-            val clientResponse: Boolean = mClientInterface!!.onSetInactive()
+            val clientResponse: Boolean = onSetInactiveCallback()
             wasCompleted.accept(clientResponse)
         }
     }
 
     fun onAnswer(videoState: Int, wasCompleted: Consumer<Boolean>) {
         CoroutineScope(mCoroutineContext).launch {
-            val clientResponse: Boolean = mClientInterface!!.onAnswer(videoState)
+            val clientResponse: Boolean = onAnswerCallback(videoState)
             wasCompleted.accept(clientResponse)
         }
     }
 
     fun onDisconnect(cause: DisconnectCause, wasCompleted: Consumer<Boolean>) {
         CoroutineScope(mCoroutineContext).launch {
-            val clientResponse: Boolean = mClientInterface!!.onDisconnect(cause)
+            val clientResponse: Boolean = onDisconnectCallback(cause)
             wasCompleted.accept(clientResponse)
             blockingSessionExecution.complete(Unit)
         }
@@ -227,38 +217,27 @@
         private val blockingSessionExecution: CompletableDeferred<Unit>,
         override val coroutineContext: CoroutineContext
     ) : CallControlScope {
-        //  handle actionable/handshake events that originate in the platform
-        //  and require a response from the client
-        override fun setCallback(callControlCallback: CallControlCallback) {
-            session.setCallControlCallback(callControlCallback)
-        }
-
         // handle requests that originate from the client and propagate into platform
         //  return the platforms response which indicates success of the request.
         override fun getCallId(): ParcelUuid {
             CoroutineScope(session.mCoroutineContext).launch {
-                verifySessionCallbacks()
             }
             return session.getCallId()
         }
 
         override suspend fun setActive(): Boolean {
-            verifySessionCallbacks()
             return session.setActive()
         }
 
         override suspend fun setInactive(): Boolean {
-            verifySessionCallbacks()
             return session.setInactive()
         }
 
         override suspend fun answer(callType: Int): Boolean {
-            verifySessionCallbacks()
             return session.answer(callType)
         }
 
         override suspend fun disconnect(disconnectCause: DisconnectCause): Boolean {
-            verifySessionCallbacks()
             val response = session.disconnect(disconnectCause)
             blockingSessionExecution.complete(Unit)
             return response
@@ -266,7 +245,6 @@
 
         override suspend fun requestEndpointChange(endpoint: CallEndpointCompat):
             Boolean {
-            verifySessionCallbacks()
             return session.requestEndpointChange(
                 EndpointUtils.Api34PlusImpl.toCallEndpoint(endpoint)
             )
@@ -281,17 +259,5 @@
 
         override val isMuted: Flow<Boolean> =
             callChannels.isMutedChannel.receiveAsFlow()
-
-        private suspend fun verifySessionCallbacks() {
-            CoroutineScope(session.mCoroutineContext).launch {
-                if (!session.hasClientSetCallbacks()) {
-                    // Always send disconnect signal so that we don't end up with stuck calls.
-                    session.disconnect(DisconnectCause(DisconnectCause.LOCAL))
-                    throw androidx.core.telecom.CallException(
-                        androidx.core.telecom.CallException.ERROR_CALLBACKS_CODE
-                    )
-                }
-           }
-        }
     }
 }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSessionLegacy.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSessionLegacy.kt
index 441cd6d..1d6f411 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSessionLegacy.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/CallSessionLegacy.kt
@@ -26,10 +26,8 @@
 import android.util.Log
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresApi
-import androidx.core.telecom.CallControlCallback
 import androidx.core.telecom.CallControlScope
 import androidx.core.telecom.CallEndpointCompat
-import androidx.core.telecom.CallException
 import androidx.core.telecom.internal.utils.EndpointUtils
 import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.CompletableDeferred
@@ -43,11 +41,14 @@
     private val id: ParcelUuid,
     private val callChannels: CallChannels,
     private val coroutineContext: CoroutineContext,
+    val onAnswerCallback: suspend (callType: Int) -> Boolean,
+    val onDisconnectCallback: suspend (disconnectCause: DisconnectCause) -> Boolean,
+    val onSetActiveCallback: suspend () -> Boolean,
+    val onSetInactiveCallback: suspend () -> Boolean,
     private val blockingSessionExecution: CompletableDeferred<Unit>
 ) : android.telecom.Connection() {
     // instance vars
     private val TAG: String = CallSessionLegacy::class.java.simpleName
-    private var mClientInterface: CallControlCallback? = null
     private var mCachedBluetoothDevices: ArrayList<BluetoothDevice> = ArrayList()
 
     companion object {
@@ -61,14 +62,6 @@
         const val STATE_DISCONNECTED = 6
     }
 
-    fun setCallControlCallback(callControlCallback: CallControlCallback) {
-        mClientInterface = callControlCallback
-    }
-
-    fun hasClientSetCallbacks(): Boolean {
-        return mClientInterface != null
-    }
-
     /**
      * =========================================================================================
      *                Call State Updates
@@ -232,7 +225,7 @@
         CoroutineScope(coroutineContext).launch {
             // Note the slight deviation here where onAnswer does not put the call into an ACTIVE
             // state as it does in the platform. This behavior is intentional for this path.
-            val clientCanAnswer = mClientInterface!!.onAnswer(videoState)
+            val clientCanAnswer: Boolean = onAnswerCallback(videoState)
             if (clientCanAnswer) {
                 setActive()
                 setVideoState(videoState)
@@ -245,7 +238,7 @@
 
     override fun onUnhold() {
         CoroutineScope(coroutineContext).launch {
-            val clientCanUnhold = mClientInterface!!.onSetActive()
+            val clientCanUnhold = onSetActiveCallback()
             if (clientCanUnhold) {
                 setActive()
             }
@@ -254,7 +247,7 @@
 
     override fun onHold() {
         CoroutineScope(coroutineContext).launch {
-            val clientCanHold = mClientInterface!!.onSetInactive()
+            val clientCanHold = onSetInactiveCallback()
             if (clientCanHold) {
                 setOnHold()
             }
@@ -263,7 +256,7 @@
 
     override fun onDisconnect() {
         CoroutineScope(coroutineContext).launch {
-            mClientInterface!!.onDisconnect(
+            onDisconnectCallback(
                 DisconnectCause(DisconnectCause.LOCAL)
             )
             setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
@@ -274,7 +267,7 @@
     override fun onReject(rejectReason: Int) {
         CoroutineScope(coroutineContext).launch {
             if (state == Call.STATE_RINGING) {
-                mClientInterface!!.onDisconnect(
+                onDisconnectCallback(
                     DisconnectCause(DisconnectCause.REJECTED)
                 )
                 setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
@@ -285,7 +278,7 @@
     override fun onReject(rejectMessage: String) {
         CoroutineScope(coroutineContext).launch {
             if (state == Call.STATE_RINGING) {
-                mClientInterface!!.onDisconnect(
+                onDisconnectCallback(
                     DisconnectCause(DisconnectCause.REJECTED)
                 )
                 setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
@@ -296,7 +289,7 @@
     override fun onReject() {
         CoroutineScope(coroutineContext).launch {
             if (state == Call.STATE_RINGING) {
-                mClientInterface!!.onDisconnect(
+                onDisconnectCallback(
                     DisconnectCause(DisconnectCause.REJECTED)
                 )
                 setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
@@ -315,43 +308,31 @@
         private val blockingSessionExecution: CompletableDeferred<Unit>,
         override val coroutineContext: CoroutineContext
     ) : CallControlScope {
-        //  handle actionable/handshake events that originate in the platform
-        //  and require a response from the client
-        override fun setCallback(callControlCallback: CallControlCallback) {
-            session.setCallControlCallback(callControlCallback)
-        }
-
         // handle requests that originate from the client and propagate into platform
         //  return the platforms response which indicates success of the request.
         override fun getCallId(): ParcelUuid {
-            verifySessionCallbacks()
             return session.getCallId()
         }
 
         override suspend fun setActive(): Boolean {
-            verifySessionCallbacks()
             return session.setConnectionActive()
         }
 
         override suspend fun setInactive(): Boolean {
-            verifySessionCallbacks()
             return session.setConnectionInactive()
         }
 
         override suspend fun answer(callType: Int): Boolean {
-            verifySessionCallbacks()
             return session.answer(callType)
         }
 
         override suspend fun disconnect(disconnectCause: DisconnectCause): Boolean {
-            verifySessionCallbacks()
             val result = session.setConnectionDisconnect(disconnectCause)
             blockingSessionExecution.complete(Unit)
             return result
         }
 
         override suspend fun requestEndpointChange(endpoint: CallEndpointCompat): Boolean {
-            verifySessionCallbacks()
             return session.requestEndpointChange(endpoint)
         }
 
@@ -364,13 +345,5 @@
 
         override val isMuted: Flow<Boolean> =
             callChannels.isMutedChannel.receiveAsFlow()
-
-        private fun verifySessionCallbacks() {
-            if (!session.hasClientSetCallbacks()) {
-                // Always send disconnect signal so that we don't end up with stuck calls.
-                session.setDisconnected(DisconnectCause(DisconnectCause.LOCAL))
-                throw CallException(CallException.ERROR_CALLBACKS_CODE)
-            }
-        }
     }
 }
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/JetpackConnectionService.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/JetpackConnectionService.kt
index b22a4e5..1d73d5f 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/JetpackConnectionService.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/JetpackConnectionService.kt
@@ -20,6 +20,7 @@
 import android.telecom.Connection
 import android.telecom.ConnectionRequest
 import android.telecom.ConnectionService
+import android.telecom.DisconnectCause
 import android.telecom.PhoneAccountHandle
 import android.telecom.TelecomManager
 import android.telecom.VideoProfile
@@ -41,6 +42,10 @@
         val callChannel: CallChannels,
         val coroutineContext: CoroutineContext,
         val completableDeferred: CompletableDeferred<CallSessionLegacy>?,
+        val onAnswer: suspend (callType: Int) -> Boolean,
+        val onDisconnect: suspend (disconnectCause: DisconnectCause) -> Boolean,
+        val onSetActive: suspend () -> Boolean,
+        val onSetInactive: suspend () -> Boolean,
         val execution: CompletableDeferred<Unit>
     )
 
@@ -143,6 +148,10 @@
             ParcelUuid.fromString(UUID.randomUUID().toString()),
             targetRequest.callChannel,
             targetRequest.coroutineContext,
+            targetRequest.onAnswer,
+            targetRequest.onDisconnect,
+            targetRequest.onSetActive,
+            targetRequest.onSetInactive,
             targetRequest.execution
         )
 
diff --git a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
index fa4b4ba..0d672bb 100644
--- a/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
+++ b/core/core-telecom/src/main/java/androidx/core/telecom/internal/utils/Utils.kt
@@ -72,7 +72,7 @@
 
         fun verifyBuildVersion() {
             if (mBuildVersion.hasInvalidBuildVersion()) {
-                throw UnsupportedOperationException(CallException.ERROR_BUILD_VERSION)
+                throw UnsupportedOperationException(CallException.ERROR_BUILD_VERSION_MSG)
             }
         }
 
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 019f4c6..d998e4c 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -72,6 +72,7 @@
     method public static androidx.core.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public void requestUsageTimeReport(android.app.PendingIntent);
     method public androidx.core.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect?);
+    method public androidx.core.app.ActivityOptionsCompat setShareIdentityEnabled(boolean);
     method public android.os.Bundle? toBundle();
     method public void update(androidx.core.app.ActivityOptionsCompat);
     field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
@@ -798,7 +799,7 @@
     method public abstract void cancel(String!, int, String!);
     method public abstract void cancelAll(String!);
     method public abstract void notify(String!, int, String!, android.app.Notification!);
-    method public android.os.IBinder! onBind(android.content.Intent!);
+    method @DeprecatedSinceApi(api=19, message="SDKs past 19 have no need for side channeling.") public android.os.IBinder! onBind(android.content.Intent!);
   }
 
   public final class NotificationManagerCompat {
@@ -2461,12 +2462,12 @@
     method public androidx.core.view.ContentInfoCompat.Builder setSource(int);
   }
 
-  public class DifferentialMotionFlingHelper {
-    ctor public DifferentialMotionFlingHelper(android.content.Context, androidx.core.view.DifferentialMotionFlingHelper.DifferentialMotionFlingTarget);
+  public class DifferentialMotionFlingController {
+    ctor public DifferentialMotionFlingController(android.content.Context, androidx.core.view.DifferentialMotionFlingTarget);
     method public void onMotionEvent(android.view.MotionEvent, int);
   }
 
-  public static interface DifferentialMotionFlingHelper.DifferentialMotionFlingTarget {
+  public interface DifferentialMotionFlingTarget {
     method public float getScaledScrollFactor();
     method public boolean startDifferentialMotionFling(float);
     method public void stopDifferentialMotionFling();
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 75bc7fa..011967a 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -90,6 +90,7 @@
     method public static androidx.core.app.ActivityOptionsCompat makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public void requestUsageTimeReport(android.app.PendingIntent);
     method public androidx.core.app.ActivityOptionsCompat setLaunchBounds(android.graphics.Rect?);
+    method public androidx.core.app.ActivityOptionsCompat setShareIdentityEnabled(boolean);
     method public android.os.Bundle? toBundle();
     method public void update(androidx.core.app.ActivityOptionsCompat);
     field public static final String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
@@ -896,7 +897,7 @@
     method public abstract void cancel(String!, int, String!);
     method public abstract void cancelAll(String!);
     method public abstract void notify(String!, int, String!, android.app.Notification!);
-    method public android.os.IBinder! onBind(android.content.Intent!);
+    method @DeprecatedSinceApi(api=19, message="SDKs past 19 have no need for side channeling.") public android.os.IBinder! onBind(android.content.Intent!);
   }
 
   public final class NotificationManagerCompat {
@@ -2899,12 +2900,12 @@
   @IntDef({androidx.core.view.ContentInfoCompat.SOURCE_APP, androidx.core.view.ContentInfoCompat.SOURCE_CLIPBOARD, androidx.core.view.ContentInfoCompat.SOURCE_INPUT_METHOD, androidx.core.view.ContentInfoCompat.SOURCE_DRAG_AND_DROP, androidx.core.view.ContentInfoCompat.SOURCE_AUTOFILL, androidx.core.view.ContentInfoCompat.SOURCE_PROCESS_TEXT}) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface ContentInfoCompat.Source {
   }
 
-  public class DifferentialMotionFlingHelper {
-    ctor public DifferentialMotionFlingHelper(android.content.Context, androidx.core.view.DifferentialMotionFlingHelper.DifferentialMotionFlingTarget);
+  public class DifferentialMotionFlingController {
+    ctor public DifferentialMotionFlingController(android.content.Context, androidx.core.view.DifferentialMotionFlingTarget);
     method public void onMotionEvent(android.view.MotionEvent, int);
   }
 
-  public static interface DifferentialMotionFlingHelper.DifferentialMotionFlingTarget {
+  public interface DifferentialMotionFlingTarget {
     method public float getScaledScrollFactor();
     method public boolean startDifferentialMotionFling(float);
     method public void stopDifferentialMotionFling();
diff --git a/core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingHelperTest.java b/core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingControllerTest.java
similarity index 93%
rename from core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingHelperTest.java
rename to core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingControllerTest.java
index d0072b8..83cd7e1 100644
--- a/core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingHelperTest.java
+++ b/core/core/src/androidTest/java/androidx/core/view/DifferentialMotionFlingControllerTest.java
@@ -32,20 +32,20 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class DifferentialMotionFlingHelperTest {
+public class DifferentialMotionFlingControllerTest {
     private int mMinVelocity = 0;
     private int mMaxVelocity = Integer.MAX_VALUE;
     /** A fake velocity value that's going to be returned from the velocity provider. */
     private float mVelocity;
     private boolean mVelocityCalculated;
 
-    private final DifferentialMotionFlingHelper.DifferentialVelocityProvider mVelocityProvider =
+    private final DifferentialMotionFlingController.DifferentialVelocityProvider mVelocityProvider =
             (vt, event, axis) -> {
                 mVelocityCalculated = true;
                 return mVelocity;
             };
 
-    private final DifferentialMotionFlingHelper.FlingVelocityThresholdCalculator
+    private final DifferentialMotionFlingController.FlingVelocityThresholdCalculator
             mVelocityThresholdCalculator =
                     (ctx, buffer, event, axis) -> {
                         buffer[0] = mMinVelocity;
@@ -55,11 +55,11 @@
     private final TestDifferentialMotionFlingTarget mFlingTarget =
             new TestDifferentialMotionFlingTarget();
 
-    private DifferentialMotionFlingHelper mFlingHelper;
+    private DifferentialMotionFlingController mFlingController;
 
     @Before
     public void setUp() throws Exception {
-        mFlingHelper = new DifferentialMotionFlingHelper(
+        mFlingController = new DifferentialMotionFlingController(
                 ApplicationProvider.getApplicationContext(),
                 mFlingTarget,
                 mVelocityThresholdCalculator,
@@ -166,7 +166,7 @@
 
     private void deliverEventWithVelocity(MotionEvent ev, int axis, float velocity) {
         mVelocity = velocity;
-        mFlingHelper.onMotionEvent(ev, axis);
+        mFlingController.onMotionEvent(ev, axis);
         ev.recycle();
     }
 
diff --git a/core/core/src/androidTest/java/androidx/core/view/TestDifferentialMotionFlingTarget.java b/core/core/src/androidTest/java/androidx/core/view/TestDifferentialMotionFlingTarget.java
index 3651cd6..ea058b4 100644
--- a/core/core/src/androidTest/java/androidx/core/view/TestDifferentialMotionFlingTarget.java
+++ b/core/core/src/androidTest/java/androidx/core/view/TestDifferentialMotionFlingTarget.java
@@ -17,10 +17,9 @@
 package androidx.core.view;
 
 /**
- * A test implementation for {@link DifferentialMotionFlingHelper.DifferentialMotionFlingTarget}.
+ * A test implementation for {@link DifferentialMotionFlingTarget}.
  */
-class TestDifferentialMotionFlingTarget
-        implements DifferentialMotionFlingHelper.DifferentialMotionFlingTarget {
+class TestDifferentialMotionFlingTarget implements DifferentialMotionFlingTarget {
     float mLastFlingVelocity = 0;
     int mNumStops = 0;
 
diff --git a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewOnGenericMotionEventTest.java b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewOnGenericMotionEventTest.java
index f45f0c7..29abb0e 100644
--- a/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewOnGenericMotionEventTest.java
+++ b/core/core/src/androidTest/java/androidx/core/widget/NestedScrollViewOnGenericMotionEventTest.java
@@ -22,7 +22,7 @@
 
 import android.view.MotionEvent;
 
-import androidx.core.view.DifferentialMotionFlingHelper;
+import androidx.core.view.DifferentialMotionFlingController;
 import androidx.core.view.InputDeviceCompat;
 import androidx.core.view.MotionEventCompat;
 import androidx.test.core.app.ApplicationProvider;
@@ -37,7 +37,7 @@
 @RunWith(AndroidJUnit4.class)
 public class NestedScrollViewOnGenericMotionEventTest {
 
-    private DifferentialMotionFlingHelper mSpyDifferentialFlingHelper;
+    private DifferentialMotionFlingController mSpyDifferentialFlingController;
 
     private NestedScrollView mNestedScrollView;
 
@@ -45,8 +45,8 @@
     public void setUp() throws Exception {
         mNestedScrollView = new NestedScrollView(ApplicationProvider.getApplicationContext());
 
-        mSpyDifferentialFlingHelper = spy(mNestedScrollView.mDifferentialMotionFlingHelper);
-        mNestedScrollView.mDifferentialMotionFlingHelper = mSpyDifferentialFlingHelper;
+        mSpyDifferentialFlingController = spy(mNestedScrollView.mDifferentialMotionFlingController);
+        mNestedScrollView.mDifferentialMotionFlingController = mSpyDifferentialFlingController;
     }
 
     @Test
@@ -55,7 +55,7 @@
 
         mNestedScrollView.onGenericMotionEvent(event);
 
-        verify(mSpyDifferentialFlingHelper).onMotionEvent(event, MotionEventCompat.AXIS_SCROLL);
+        verify(mSpyDifferentialFlingController).onMotionEvent(event, MotionEventCompat.AXIS_SCROLL);
     }
 
     @Test
@@ -64,7 +64,7 @@
 
         mNestedScrollView.onGenericMotionEvent(event);
 
-        verify(mSpyDifferentialFlingHelper).onMotionEvent(event, MotionEvent.AXIS_VSCROLL);
+        verify(mSpyDifferentialFlingController).onMotionEvent(event, MotionEvent.AXIS_VSCROLL);
     }
 
     @Test
diff --git a/core/core/src/main/java/androidx/core/app/ActivityCompat.java b/core/core/src/main/java/androidx/core/app/ActivityCompat.java
index dea976c..8f27f72 100644
--- a/core/core/src/main/java/androidx/core/app/ActivityCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ActivityCompat.java
@@ -363,6 +363,7 @@
      * the target class type is unconstrained, an explicit cast may be
      * necessary.
      *
+     * @param activity activity in which to find a view.
      * @param id the ID to search for
      * @return a view with given ID
      * @see Activity#findViewById(int)
@@ -388,6 +389,7 @@
      * will be called to handle shared elements on the <i>launched</i> Activity. This requires
      * {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS}.
      *
+     * @param activity activity for which to set the callback.
      * @param callback Used to manipulate shared element transitions on the launched Activity.
      */
     public static void setEnterSharedElementCallback(@NonNull Activity activity,
@@ -407,6 +409,7 @@
      * calls will only come when returning from the started Activity.
      * This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS}.
      *
+     * @param activity activity for which to set the callback.
      * @param callback Used to manipulate shared element transitions on the launching Activity.
      */
     public static void setExitSharedElementCallback(@NonNull Activity activity,
@@ -642,6 +645,7 @@
     /**
      * Create {@link DragAndDropPermissionsCompat} object bound to this activity and controlling
      * the access permissions for content URIs associated with the {@link android.view.DragEvent}.
+     * @param activity activity for which to request the permission.
      * @param dragEvent Drag event to request permission for
      * @return The {@link DragAndDropPermissionsCompat} object used to control access to the content
      * URIs. {@code null} if no content URIs are associated with the event or if permissions could
@@ -690,6 +694,7 @@
      * so that the system can learn appropriate ranking signals linking the activity's
      * locus id with the matching shortcut.
      *
+     * @param activity activity for which to set locus id.
      * @param locusId  a unique, stable id that identifies this {@code Activity} instance. LocusId
      *      is an opaque ID that links this Activity's state to different Android concepts:
      *      {@link androidx.core.content.pm.ShortcutInfoCompat.Builder#setLocusId(LocusIdCompat)}.
diff --git a/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java b/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
index 1afd50d..dd3ecdb 100644
--- a/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ActivityOptionsCompat.java
@@ -297,6 +297,15 @@
             }
             return Api24Impl.getLaunchBounds(mActivityOptions);
         }
+
+        @Override
+        public ActivityOptionsCompat setShareIdentityEnabled(boolean shareIdentity) {
+            if (Build.VERSION.SDK_INT < 34) {
+                return this;
+            }
+            return new ActivityOptionsCompatImpl(
+                    Api34Impl.setShareIdentityEnabled(mActivityOptions, shareIdentity));
+        }
     }
 
     protected ActivityOptionsCompat() {
@@ -376,6 +385,32 @@
         // Do nothing.
     }
 
+    /**
+     * Sets whether the identity of the launching app should be shared with the activity.
+     *
+     * <p>Use this option when starting an activity that needs to know the identity of the
+     * launching app; with this set to {@code true}, the activity will have access to the launching
+     * app's package name and uid.
+     *
+     * <p>Defaults to {@code false} if not set. This is a no-op before U.
+     *
+     * <p>Note, even if the launching app does not explicitly enable sharing of its identity, if
+     * the activity is started with {@code Activity#startActivityForResult}, then {@link
+     * Activity#getCallingPackage()} will still return the launching app's package name to
+     * allow validation of the result's recipient. Also, an activity running within a package
+     * signed by the same key used to sign the platform (some system apps such as Settings will
+     * be signed with the platform's key) will have access to the launching app's identity.
+     *
+     * @param shareIdentity whether the launching app's identity should be shared with the activity
+     * @return {@code this} {@link ActivityOptions} instance.
+     * @see Activity#getLaunchedFromPackage()
+     * @see Activity#getLaunchedFromUid()
+     */
+    @NonNull
+    public ActivityOptionsCompat setShareIdentityEnabled(boolean shareIdentity) {
+        return this;
+    }
+
     @RequiresApi(16)
     static class Api16Impl {
         private Api16Impl() {
@@ -467,4 +502,17 @@
             return activityOptions.getLaunchBounds();
         }
     }
+
+    @RequiresApi(34)
+    static class Api34Impl {
+        private Api34Impl() {
+            // This class is not instantiable.
+        }
+
+        @DoNotInline
+        static ActivityOptions setShareIdentityEnabled(ActivityOptions activityOptions,
+                boolean shareIdentity) {
+            return activityOptions.setShareIdentityEnabled(shareIdentity);
+        }
+    }
 }
diff --git a/core/core/src/main/java/androidx/core/app/NotificationCompatSideChannelService.java b/core/core/src/main/java/androidx/core/app/NotificationCompatSideChannelService.java
index 901bc7e..7dbda2c 100644
--- a/core/core/src/main/java/androidx/core/app/NotificationCompatSideChannelService.java
+++ b/core/core/src/main/java/androidx/core/app/NotificationCompatSideChannelService.java
@@ -24,6 +24,8 @@
 import android.os.RemoteException;
 import android.support.v4.app.INotificationSideChannel;
 
+import androidx.annotation.DeprecatedSinceApi;
+
 /**
  * Abstract service to receive side channel notifications sent from
  * {@link androidx.core.app.NotificationManagerCompat}.
@@ -44,6 +46,7 @@
  */
 public abstract class NotificationCompatSideChannelService extends Service {
     @Override
+    @DeprecatedSinceApi(api = 19, message = "SDKs past 19 have no need for side channeling.")
     public IBinder onBind(Intent intent) {
         if (intent.getAction().equals(NotificationManagerCompat.ACTION_BIND_SIDE_CHANNEL)) {
             // Block side channel service connections if the current sdk has no need for
diff --git a/core/core/src/main/java/androidx/core/app/ServiceCompat.java b/core/core/src/main/java/androidx/core/app/ServiceCompat.java
index ae56964..043850e 100644
--- a/core/core/src/main/java/androidx/core/app/ServiceCompat.java
+++ b/core/core/src/main/java/androidx/core/app/ServiceCompat.java
@@ -180,6 +180,7 @@
     /**
      * Remove the passed service from foreground state, allowing it to be killed if
      * more memory is needed.
+     * @param service service to remove.
      * @param flags Additional behavior options: {@link #STOP_FOREGROUND_REMOVE},
      * {@link #STOP_FOREGROUND_DETACH}.
      * @see Service#startForeground(int, Notification)
diff --git a/core/core/src/main/java/androidx/core/content/ContentResolverCompat.java b/core/core/src/main/java/androidx/core/content/ContentResolverCompat.java
index d615a01..ff0ffae 100644
--- a/core/core/src/main/java/androidx/core/content/ContentResolverCompat.java
+++ b/core/core/src/main/java/androidx/core/content/ContentResolverCompat.java
@@ -53,6 +53,7 @@
      * </ul>
      * </p>
      *
+     * @param resolver resolver to use for the query.
      * @param uri The URI, using the content:// scheme, for the content to
      *         retrieve.
      * @param projection A list of which columns to return. Passing null will
diff --git a/core/core/src/main/java/androidx/core/content/ContextCompat.java b/core/core/src/main/java/androidx/core/content/ContextCompat.java
index d283059..be0c7a3 100644
--- a/core/core/src/main/java/androidx/core/content/ContextCompat.java
+++ b/core/core/src/main/java/androidx/core/content/ContextCompat.java
@@ -514,6 +514,7 @@
      * Starting in {@link Build.VERSION_CODES#LOLLIPOP}, the
      * returned drawable will be styled for the specified Context's theme.
      *
+     * @param context context to use for getting the drawable.
      * @param id The desired resource identifier, as generated by the aapt tool.
      *           This integer encodes the package, type, and resource entry.
      *           The value 0 is an invalid identifier.
@@ -549,6 +550,7 @@
      * Starting in {@link Build.VERSION_CODES#M}, the returned
      * color state list will be styled for the specified Context's theme.
      *
+     * @param context context to use for getting the color state list.
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
@@ -568,6 +570,7 @@
      * Starting in {@link Build.VERSION_CODES#M}, the returned
      * color will be styled for the specified Context's theme.
      *
+     * @param context context to use for getting the color.
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
@@ -588,6 +591,7 @@
     /**
      * Determine whether <em>you</em> have been granted a particular permission.
      *
+     * @param context context for which to check the permission.
      * @param permission The name of the permission being checked.
      * @return {@link PackageManager#PERMISSION_GRANTED} if you have the
      * permission, or {@link PackageManager#PERMISSION_DENIED} if not.
diff --git a/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java b/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
index ea50f63..f8d72df 100644
--- a/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
+++ b/core/core/src/main/java/androidx/core/content/pm/ShortcutManagerCompat.java
@@ -176,6 +176,7 @@
      *
      * <p>Use {@link android.app.PendingIntent#getIntentSender()} to create a {@link IntentSender}.
      *
+     * @param context context to use for the request.
      * @param shortcut new shortcut to pin
      * @param callback if not null, this intent will be sent when the shortcut is pinned
      *
@@ -227,6 +228,7 @@
      * <p>This should be used by an Activity to set result in response to
      * {@link Intent#ACTION_CREATE_SHORTCUT}.
      *
+     * @param context context to use for the intent.
      * @param shortcut new shortcut to pin
      * @return the intent that should be set as the result for the calling activity
      *
@@ -266,6 +268,7 @@
      *                   method with other flag will be ignored.
      * </ul>
      *
+     * @param context context to use for the shortcuts.
      * @return list of {@link ShortcutInfoCompat}s that match the flag.
      *
      * <p>At least one of the {@code MATCH} flags should be set. Otherwise no shortcuts will be
diff --git a/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java b/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
index c8a8317..681aa16 100644
--- a/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
+++ b/core/core/src/main/java/androidx/core/content/res/ResourcesCompat.java
@@ -120,6 +120,7 @@
      * Prior to API level 21, the theme will not be applied and this method
      * simply calls through to {@link Resources#getDrawable(int)}.
      *
+     * @param res   resources to use for getting the drawable.
      * @param id    The desired resource identifier, as generated by the aapt
      *              tool. This integer encodes the package, type, and resource
      *              entry. The value 0 is an invalid identifier.
@@ -151,6 +152,7 @@
      * Prior to API level 21, the theme will not be applied and this method
      * calls through to Resources#getDrawableForDensity(int, int).
      *
+     * @param res resources to use for getting the drawable.
      * @param id      The desired resource identifier, as generated by the aapt
      *                tool. This integer encodes the package, type, and resource
      *                entry. The value 0 is an invalid identifier.
@@ -183,6 +185,7 @@
      * Prior to API level 23, the theme will not be applied and this method
      * calls through to {@link Resources#getColor(int)}.
      *
+     * @param res resources to use for getting the color.
      * @param id    The desired resource identifier, as generated by the aapt
      *              tool. This integer encodes the package, type, and resource
      *              entry. The value 0 is an invalid identifier.
@@ -208,6 +211,7 @@
      * ID. The resource may contain either a single raw color value or a
      * complex {@link ColorStateList} holding multiple possible colors.
      *
+     * @param res resources to use for getting the color state list.
      * @param id    The desired resource identifier of a {@link ColorStateList},
      *              as generated by the aapt tool. This integer encodes the
      *              package, type, and resource entry. The value 0 is an invalid
@@ -362,6 +366,7 @@
     /**
      * Retrieve a floating-point value for a particular resource ID.
      *
+     * @param res resources to use for getting the value.
      * @param id The desired resource identifier, as generated by the aapt
      *           tool. This integer encodes the package, type, and resource
      *           entry. The value 0 is an invalid identifier.
diff --git a/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java b/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
index d8b67a1..b10563e 100644
--- a/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/BitmapCompat.java
@@ -75,6 +75,7 @@
      * This property is only a suggestion that can be ignored by the
      * renderer. It is not guaranteed to have any effect.
      *
+     * @param bitmap bitmap for which to set the state.
      * @param hasMipMap indicates whether the renderer should attempt
      *                  to use mipmaps
      * @see Bitmap#setHasMipMap(boolean)
diff --git a/core/core/src/main/java/androidx/core/graphics/PathUtils.java b/core/core/src/main/java/androidx/core/graphics/PathUtils.java
index 8c88875..d08541d 100644
--- a/core/core/src/main/java/androidx/core/graphics/PathUtils.java
+++ b/core/core/src/main/java/androidx/core/graphics/PathUtils.java
@@ -36,6 +36,8 @@
      *
      * <em>Note:</em> This method requires API 26 or newer.
      *
+     * @param path path to flatten.
+     *
      * @see #flatten(Path, float)
      */
     @RequiresApi(26)
@@ -49,6 +51,7 @@
      *
      * <em>Note:</em> This method requires API 26 or newer.
      *
+     * @param path path to flatten.
      * @param error The acceptable error for a line on the Path. Typically this would be
      *              0.5 so that the error is less than half a pixel.
      *
diff --git a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
index 63bc7fb..0df99eb 100644
--- a/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/TypefaceCompat.java
@@ -315,6 +315,7 @@
      * This method is thread safe.
      * </p>
      *
+     * @param context context to use for the creation.
      * @param family An existing {@link Typeface} object. In case of {@code null}, the default
      *               typeface is used instead.
      * @param weight The desired weight to be drawn.
diff --git a/core/core/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java b/core/core/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
index d738031..3d01b86 100644
--- a/core/core/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
+++ b/core/core/src/main/java/androidx/core/graphics/drawable/DrawableCompat.java
@@ -119,6 +119,10 @@
      * different from the drawable bounds.
      *
      * @param drawable The Drawable against which to invoke the method.
+     * @param left position in pixels of the left bound
+     * @param top position in pixels of the top bound
+     * @param right position in pixels of the right bound
+     * @param bottom position in pixels of the bottom bound
      */
     public static void setHotspotBounds(@NonNull Drawable drawable, int left, int top,
             int right, int bottom) {
@@ -262,6 +266,7 @@
     /**
      * Inflate this Drawable from an XML resource optionally styled by a theme.
      *
+     * @param drawable drawable to inflate.
      * @param res Resources used to resolve attribute values
      * @param parser XML parser from which to inflate this Drawable
      * @param attrs Base set of attribute values
@@ -351,6 +356,7 @@
      * layout direction, as the Drawable has no capacity to do the resolution on
      * its own.
      *
+     * @param drawable drawable for which to set the layout direction.
      * @param layoutDirection the resolved layout direction for the drawable,
      *                        either {@link ViewCompat#LAYOUT_DIRECTION_LTR}
      *                        or {@link ViewCompat#LAYOUT_DIRECTION_RTL}
diff --git a/core/core/src/main/java/androidx/core/os/HandlerCompat.java b/core/core/src/main/java/androidx/core/os/HandlerCompat.java
index 3ca278f4..3106865 100644
--- a/core/core/src/main/java/androidx/core/os/HandlerCompat.java
+++ b/core/core/src/main/java/androidx/core/os/HandlerCompat.java
@@ -113,6 +113,7 @@
      * </ul>
      *
      * @param looper the Looper that the new Handler should be bound to
+     * @param callback callback to send events to
      * @return a new async Handler instance
      * @see Handler#createAsync(Looper, Handler.Callback)
      */
@@ -162,6 +163,7 @@
      * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
      * Time spent in deep sleep will add an additional delay to execution.
      *
+     * @param handler handler to use for posting the runnable.
      * @param r The Runnable that will be executed.
      * @param token An instance which can be used to cancel {@code r} via
      *         {@link Handler#removeCallbacksAndMessages}.
diff --git a/core/core/src/main/java/androidx/core/os/MessageCompat.java b/core/core/src/main/java/androidx/core/os/MessageCompat.java
index 7340ab2..5b40799 100644
--- a/core/core/src/main/java/androidx/core/os/MessageCompat.java
+++ b/core/core/src/main/java/androidx/core/os/MessageCompat.java
@@ -64,6 +64,7 @@
      * <p>
      * This API has no effect prior to API 16.
      *
+     * @param message message for this to set the mode.
      * @param async True if the message is asynchronous.
      *
      * @see #isAsynchronous(Message)
diff --git a/core/core/src/main/java/androidx/core/provider/DocumentsContractCompat.java b/core/core/src/main/java/androidx/core/provider/DocumentsContractCompat.java
index 2938434..3765bfc 100644
--- a/core/core/src/main/java/androidx/core/provider/DocumentsContractCompat.java
+++ b/core/core/src/main/java/androidx/core/provider/DocumentsContractCompat.java
@@ -193,6 +193,7 @@
     /**
      * Create a new document with given MIME type and display name.
      *
+     * @param content           the resolver to use to create the document.
      * @param parentDocumentUri directory with {@link Document#FLAG_DIR_SUPPORTS_CREATE}
      * @param mimeType          MIME type of new document
      * @param displayName       name of new document
@@ -232,6 +233,7 @@
      * This method was only added in {@link Build.VERSION_CODES#N}. On versions prior to this,
      * this method calls through to {@link DocumentsContract#deleteDocument(ContentResolver, Uri)}.
      *
+     * @param content the resolver to use to remove the document.
      * @param documentUri       document with {@link Document#FLAG_SUPPORTS_REMOVE}
      * @param parentDocumentUri parent document of the document to remove.
      * @return true if the document was removed successfully.
diff --git a/core/core/src/main/java/androidx/core/provider/FontProvider.java b/core/core/src/main/java/androidx/core/provider/FontProvider.java
index 0a32e83..6b2101b 100644
--- a/core/core/src/main/java/androidx/core/provider/FontProvider.java
+++ b/core/core/src/main/java/androidx/core/provider/FontProvider.java
@@ -17,6 +17,7 @@
 package androidx.core.provider;
 
 import android.annotation.SuppressLint;
+import android.content.ContentProviderClient;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
@@ -29,8 +30,9 @@
 import android.net.Uri;
 import android.os.Build;
 import android.os.CancellationSignal;
+import android.os.RemoteException;
+import android.util.Log;
 
-import androidx.annotation.DoNotInline;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
@@ -126,6 +128,7 @@
                 .appendPath("file")
                 .build();
         Cursor cursor = null;
+        ContentQueryWrapper queryWrapper = ContentQueryWrapper.make(context, uri);
         try {
             String[] projection = {
                     FontsContractCompat.Columns._ID, FontsContractCompat.Columns.FILE_ID,
@@ -134,15 +137,8 @@
                     FontsContractCompat.Columns.WEIGHT, FontsContractCompat.Columns.ITALIC,
                     FontsContractCompat.Columns.RESULT_CODE};
 
-            ContentResolver resolver = context.getContentResolver();
-            if (Build.VERSION.SDK_INT > 16) {
-                cursor = Api16Impl.query(resolver, uri, projection, "query = ?",
+            cursor = queryWrapper.query(uri, projection, "query = ?",
                         new String[]{request.getQuery()}, null, cancellationSignal);
-            } else {
-                // No cancellation signal.
-                cursor = resolver.query(uri, projection, "query = ?",
-                        new String[]{request.getQuery()}, null);
-            }
 
             if (cursor != null && cursor.getCount() > 0) {
                 final int resultCodeColumnIndex = cursor.getColumnIndex(
@@ -182,6 +178,7 @@
             if (cursor != null) {
                 cursor.close();
             }
+            queryWrapper.close();
         }
         return result.toArray(new FontInfo[0]);
     }
@@ -227,19 +224,105 @@
         return shaList;
     }
 
-    @RequiresApi(16)
-    static class Api16Impl {
-        private Api16Impl() {
-            // This class is not instantiable.
+    /**
+     * Interface for absorbing querying ContentProvider API dependencies.
+     */
+    private interface ContentQueryWrapper {
+        Cursor query(
+                Uri uri,
+                String[] projection,
+                String selection,
+                String[] selectionArgs,
+                String sortOrder,
+                CancellationSignal cancellationSignal);
+        void close();
+
+        static ContentQueryWrapper make(Context context, Uri uri) {
+            if (Build.VERSION.SDK_INT < 16) {
+                return new ContentQueryWrapperBaseImpl(context);
+            } else if (Build.VERSION.SDK_INT < 24) {
+                return new ContentQueryWrapperApi16Impl(context, uri);
+            } else {
+                return new ContentQueryWrapperApi24Impl(context, uri);
+            }
+        }
+    }
+
+    private static class ContentQueryWrapperBaseImpl implements ContentQueryWrapper {
+        private ContentResolver mResolver;
+        ContentQueryWrapperBaseImpl(Context context) {
+            mResolver = context.getContentResolver();
         }
 
-        @SuppressWarnings("SameParameterValue")
-        @DoNotInline
-        static Cursor query(ContentResolver contentResolver, Uri uri, String[] projection,
-                String selection, String[] selectionArgs, String sortOrder,
-                Object cancellationSignal) { // Avoid implicit NewApi cast for CancellationSignal
-            return contentResolver.query(uri, projection, selection, selectionArgs, sortOrder,
-                    (CancellationSignal) cancellationSignal);
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder, CancellationSignal cancellationSignal) {
+            return mResolver.query(uri, projection, selection, selectionArgs, sortOrder);
+        }
+
+        @Override
+        public void close() {
+            mResolver = null;
+        }
+    }
+
+    @RequiresApi(16)
+    private static class ContentQueryWrapperApi16Impl implements ContentQueryWrapper {
+        private final ContentProviderClient mClient;
+        ContentQueryWrapperApi16Impl(Context context, Uri uri) {
+            mClient = context.getContentResolver().acquireUnstableContentProviderClient(uri);
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder, CancellationSignal cancellationSignal) {
+            if (mClient == null) {
+                return null;
+            }
+            try {
+                return mClient.query(uri, projection, selection, selectionArgs, sortOrder,
+                        cancellationSignal);
+            } catch (RemoteException e) {
+                Log.w("FontsProvider", "Unable to query the content provider", e);
+                return null;
+            }
+        }
+
+        @Override
+        public void close() {
+            if (mClient != null) {
+                mClient.release();
+            }
+        }
+    }
+
+    @RequiresApi(24)
+    private static class ContentQueryWrapperApi24Impl implements ContentQueryWrapper {
+        private final ContentProviderClient mClient;
+        ContentQueryWrapperApi24Impl(Context context, Uri uri) {
+            mClient = context.getContentResolver().acquireUnstableContentProviderClient(uri);
+        }
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder, CancellationSignal cancellationSignal) {
+            if (mClient == null) {
+                return null;
+            }
+            try {
+                return mClient.query(uri, projection, selection, selectionArgs, sortOrder,
+                        cancellationSignal);
+            } catch (RemoteException e) {
+                Log.w("FontsProvider", "Unable to query the content provider", e);
+                return null;
+            }
+        }
+
+        @Override
+        public void close() {
+            if (mClient != null) {
+                mClient.close();
+            }
         }
     }
 }
diff --git a/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java b/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
index 24368ba..0d4edc6 100644
--- a/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
+++ b/core/core/src/main/java/androidx/core/text/util/LinkifyCompat.java
@@ -213,6 +213,7 @@
      *  @param matchFilter  The filter that is used to allow the client code
      *                      additional control over which pattern matches are
      *                      to be converted into links.
+     * @param transformFilter Filter to allow the client code to update the link found.
      */
     public static void addLinks(@NonNull TextView text, @NonNull Pattern pattern,
             @Nullable String scheme, @Nullable MatchFilter matchFilter,
diff --git a/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java b/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
index e32353e..1f3ffb0 100644
--- a/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ContentInfoCompat.java
@@ -310,6 +310,7 @@
      * <p>Except for the {@link ClipData} items, the returned objects will contain all the same
      * metadata as the passed-in {@link ContentInfo}.
      *
+     * @param payload payload to add to returned pair.
      * @param itemPredicate The predicate to test each {@link ClipData.Item} to determine which
      *                      partition to place it into.
      * @return A pair containing the partitioned content. The pair's first object will have the
diff --git a/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingHelper.java b/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingController.java
similarity index 83%
rename from core/core/src/main/java/androidx/core/view/DifferentialMotionFlingHelper.java
rename to core/core/src/main/java/androidx/core/view/DifferentialMotionFlingController.java
index 66c312d..335d66c 100644
--- a/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingHelper.java
+++ b/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingController.java
@@ -26,7 +26,7 @@
 import androidx.annotation.VisibleForTesting;
 
 /**
- * Helper for controlling differential motion flings.
+ * Controller differential motion flings.
  *
  * <p><b>Differential motion</b> here refers to motions that report change in position instead of
  * absolution position. For instance, differential data points of 2, -1, 5 represent: there was
@@ -37,12 +37,12 @@
  * the target View (that is, the View on which we want to fling), and this class processes the event
  * to orchestrate fling.
  *
- * <p>Note that this helper class currently works to control fling only in one direction at a time.
+ * <p>Note that this class currently works to control fling only in one direction at a time.
  * As such, it works independently of horizontal/vertical orientations. It requests its client to
  * start/stop fling, and it's up to the client to choose the fling direction based on its specific
  * internal configurations and/or preferences.
  */
-public class DifferentialMotionFlingHelper {
+public class DifferentialMotionFlingController {
     private final Context mContext;
     private final DifferentialMotionFlingTarget mTarget;
 
@@ -97,47 +97,18 @@
         float getCurrentVelocity(VelocityTracker vt, MotionEvent event, int axis);
     }
 
-    /**
-     * Represents an entity that may be flung by a differential motion or an entity that initiates
-     * fling on a target View.
-     */
-    public interface DifferentialMotionFlingTarget {
-        /**
-         * Start flinging on the target View by a given velocity.
-         *
-         * @param velocity the fling velocity, in pixels/second.
-         * @return {@code true} if fling was successfully initiated, {@code false} otherwise.
-         */
-        boolean startDifferentialMotionFling(float velocity);
-
-        /** Stop any ongoing fling on the target View that is caused by a differential motion. */
-        void stopDifferentialMotionFling();
-
-        /**
-         * Returns the scaled scroll factor to be used for differential motions. This is the
-         * value that the raw {@link MotionEvent} values should be multiplied with to get pixels.
-         *
-         * <p>This usually is one of the values provided by {@link ViewConfigurationCompat}. It is
-         * up to the client to choose and provide any value as per its internal configuration.
-         *
-         * @see ViewConfigurationCompat#getScaledHorizontalScrollFactor(ViewConfiguration, Context)
-         * @see ViewConfigurationCompat#getScaledVerticalScrollFactor(ViewConfiguration, Context)
-         */
-        float getScaledScrollFactor();
-    }
-
     /** Constructs an instance for a given {@link DifferentialMotionFlingTarget}. */
-    public DifferentialMotionFlingHelper(
+    public DifferentialMotionFlingController(
             @NonNull Context context,
             @NonNull DifferentialMotionFlingTarget target) {
         this(context,
                 target,
-                DifferentialMotionFlingHelper::calculateFlingVelocityThresholds,
-                DifferentialMotionFlingHelper::getCurrentVelocity);
+                DifferentialMotionFlingController::calculateFlingVelocityThresholds,
+                DifferentialMotionFlingController::getCurrentVelocity);
     }
 
     @VisibleForTesting
-    DifferentialMotionFlingHelper(
+    DifferentialMotionFlingController(
             Context context,
             DifferentialMotionFlingTarget target,
             FlingVelocityThresholdCalculator velocityThresholdCalculator,
diff --git a/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingTarget.java b/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingTarget.java
new file mode 100644
index 0000000..b795604
--- /dev/null
+++ b/core/core/src/main/java/androidx/core/view/DifferentialMotionFlingTarget.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.core.view;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * Represents an entity that may be flung by a differential motion or an entity that initiates
+ * fling on a target View.
+ */
+public interface DifferentialMotionFlingTarget {
+    /**
+     * Start flinging on the target View by a given velocity.
+     *
+     * @param velocity the fling velocity, in pixels/second.
+     * @return {@code true} if fling was successfully initiated, {@code false} otherwise.
+     */
+    boolean startDifferentialMotionFling(float velocity);
+
+    /** Stop any ongoing fling on the target View that is caused by a differential motion. */
+    void stopDifferentialMotionFling();
+
+    /**
+     * Returns the scaled scroll factor to be used for differential motions. This is the
+     * value that the raw {@link MotionEvent} values should be multiplied with to get pixels.
+     *
+     * <p>This usually is one of the values provided by {@link ViewConfigurationCompat}. It is
+     * up to the client to choose and provide any value as per its internal configuration.
+     *
+     * @see ViewConfigurationCompat#getScaledHorizontalScrollFactor(ViewConfiguration, Context)
+     * @see ViewConfigurationCompat#getScaledVerticalScrollFactor(ViewConfiguration, Context)
+     */
+    float getScaledScrollFactor();
+}
diff --git a/core/core/src/main/java/androidx/core/view/DragStartHelper.java b/core/core/src/main/java/androidx/core/view/DragStartHelper.java
index 0c6db11..6d86d81 100644
--- a/core/core/src/main/java/androidx/core/view/DragStartHelper.java
+++ b/core/core/src/main/java/androidx/core/view/DragStartHelper.java
@@ -94,6 +94,7 @@
      * The newly created helper is not initially attached to the view, {@link #attach} must be
      * called explicitly.
      * @param view A View
+     * @param listener listener for the drag events.
      */
     public DragStartHelper(@NonNull View view, @NonNull OnDragStartListener listener) {
         mView = view;
diff --git a/core/core/src/main/java/androidx/core/view/MarginLayoutParamsCompat.java b/core/core/src/main/java/androidx/core/view/MarginLayoutParamsCompat.java
index ca2a214..4237d43 100644
--- a/core/core/src/main/java/androidx/core/view/MarginLayoutParamsCompat.java
+++ b/core/core/src/main/java/androidx/core/view/MarginLayoutParamsCompat.java
@@ -147,6 +147,7 @@
     /**
      * Set the layout direction.
      *
+     * @param lp LayoutParameters for which to set the layout direction.
      * @param layoutDirection the layout direction.
      *        Should be either {@link ViewCompat#LAYOUT_DIRECTION_LTR}
      *                     or {@link ViewCompat#LAYOUT_DIRECTION_RTL}.
diff --git a/core/core/src/main/java/androidx/core/view/MenuItemCompat.java b/core/core/src/main/java/androidx/core/view/MenuItemCompat.java
index 04fdc22..715b9ba 100644
--- a/core/core/src/main/java/androidx/core/view/MenuItemCompat.java
+++ b/core/core/src/main/java/androidx/core/view/MenuItemCompat.java
@@ -298,6 +298,7 @@
      * The menu item must be configured to expand or collapse its action view using the flag
      * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
      *
+     * @param item item on which to set the listener.
      * @param listener Listener that will respond to expand/collapse events
      * @return This menu item instance for call chaining
      *
@@ -394,6 +395,7 @@
      * <p>
      * See {@link Menu} for the menu types that support shortcuts.
      *
+     * @param item item for which to set the shortcut.
      * @param numericChar The numeric shortcut key. This is the shortcut when
      *        using a numeric (e.g., 12-key) keyboard.
      * @param numericModifiers The numeric modifier associated with the shortcut. It should
@@ -424,6 +426,7 @@
      * <p>
      * See {@link Menu} for the menu types that support shortcuts.
      *
+     * @param item item for which to set the shortcut.
      * @param numericChar The numeric shortcut key.  This is the shortcut when
      *                 using a 12-key (numeric) keyboard.
      * @param numericModifiers The modifier associated with the shortcut. It should
@@ -474,6 +477,7 @@
      * <p>
      * See {@link Menu} for the menu types that support shortcuts.
      *
+     * @param item item for which to set the shortcut.
      * @param alphaChar The alphabetic shortcut key. This is the shortcut when
      *        using a keyboard with alphabetic keys.
      * @param alphaModifiers The modifier associated with the shortcut. It should
@@ -522,6 +526,7 @@
      * automatically mutate the icon and apply the specified tint and
      * tint mode.
      *
+     * @param item item for which to set the tint.
      * @param tint the tint to apply, may be {@code null} to clear tint
      *
      * @see #getIconTintList(MenuItem)
@@ -558,6 +563,7 @@
      * {@link #setIconTintList(MenuItem, ColorStateList)} to the item's icon. The default mode is
      * {@link PorterDuff.Mode#SRC_IN}.
      *
+     * @param item item for which to set the tint mode.
      * @param tintMode the blending mode used to apply the tint, may be
      *                 {@code null} to clear tint
      * @see #setIconTintList(MenuItem, ColorStateList)
diff --git a/core/core/src/main/java/androidx/core/view/MotionEventCompat.java b/core/core/src/main/java/androidx/core/view/MotionEventCompat.java
index 7a35f54..b39a46c 100644
--- a/core/core/src/main/java/androidx/core/view/MotionEventCompat.java
+++ b/core/core/src/main/java/androidx/core/view/MotionEventCompat.java
@@ -548,6 +548,7 @@
 
     /**
      * Determines whether the event is from the given source.
+     * @param event motion event for which to check the source.
      * @param source The input source to check against.
      * @return Whether the event is from the given source.
      */
@@ -559,6 +560,7 @@
      * Get axis value for the first pointer index (may be an
      * arbitrary pointer identifier).
      *
+     * @param event motion event for which to get the value.
      * @param axis The axis identifier for the axis value to retrieve.
      *
      * @see #AXIS_X
@@ -576,6 +578,7 @@
      * Returns the value of the requested axis for the given pointer <em>index</em>
      * (use {@link #getPointerId(MotionEvent, int)} to find the pointer identifier for this index).
      *
+     * @param event motion event for which to get the value.
      * @param axis The axis identifier for the axis value to retrieve.
      * @param pointerIndex Raw index of pointer to retrieve.  Value may be from 0
      * (the first pointer that is down) to {@link #getPointerCount(MotionEvent)}-1.
diff --git a/core/core/src/main/java/androidx/core/view/NestedScrollingChildHelper.java b/core/core/src/main/java/androidx/core/view/NestedScrollingChildHelper.java
index 37fe721..652c503 100644
--- a/core/core/src/main/java/androidx/core/view/NestedScrollingChildHelper.java
+++ b/core/core/src/main/java/androidx/core/view/NestedScrollingChildHelper.java
@@ -139,6 +139,7 @@
      * @param axes Supported nested scroll axes.
      *             See {@link androidx.core.view.NestedScrollingChild2#startNestedScroll(int,
      *             int)}.
+     * @param type type of the scroll.
      * @return true if a cooperating parent view was found and nested scrolling started successfully
      */
     public boolean startNestedScroll(@ScrollAxis int axes, @NestedScrollType int type) {
diff --git a/core/core/src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java b/core/core/src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java
index 8e83bcf..317f3b4 100644
--- a/core/core/src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ScaleGestureDetectorCompat.java
@@ -34,6 +34,7 @@
      * receive onScale callbacks when the user performs a doubleTap followed by a swipe. Note that
      * this is enabled by default if the app targets API 19 and newer.
      *
+     * @param scaleGestureDetector detector for which to set the scaling mode.
      * @param enabled true to enable quick scaling, false to disable
      *
      * @deprecated Use {@link #setQuickScaleEnabled(ScaleGestureDetector, boolean)} that takes
@@ -50,6 +51,7 @@
      * receive onScale callbacks when the user performs a doubleTap followed by a swipe. Note that
      * this is enabled by default if the app targets API 19 and newer.
      *
+     * @param scaleGestureDetector detector for which to set the scaling mode.
      * @param enabled true to enable quick scaling, false to disable
      */
     public static void setQuickScaleEnabled(
diff --git a/core/core/src/main/java/androidx/core/view/ViewCompat.java b/core/core/src/main/java/androidx/core/view/ViewCompat.java
index 5fa5a59..ec39ba4 100644
--- a/core/core/src/main/java/androidx/core/view/ViewCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ViewCompat.java
@@ -56,9 +56,9 @@
 import android.view.WindowInsetsController;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityRecord;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeProvider;
+import android.view.accessibility.AccessibilityRecord;
 import android.view.autofill.AutofillId;
 import android.view.contentcapture.ContentCaptureSession;
 import android.view.inputmethod.InputConnection;
@@ -551,7 +551,8 @@
      *
      * No-op before API 29.
      *
-     *  @param context Context under which this view is created.
+     * @param view view for which to save the data.
+     * @param context Context under which this view is created.
      * @param styleable A reference to styleable array R.styleable.Foo
      * @param attrs AttributeSet used to construct this view.
      * @param t Resolved {@link TypedArray} returned by a call to
@@ -602,16 +603,16 @@
      * (allow over-scrolling only if the view content is larger than the container),
      * or {@link #OVER_SCROLL_NEVER}.
      *
-     * @param v The View against which to invoke the method.
+     * @param view The View against which to invoke the method.
      * @return This view's over-scroll mode.
      * @deprecated Call {@link View#getOverScrollMode()} directly. This method will be
      * removed in a future release.
      */
     @Deprecated
     @OverScroll
-    public static int getOverScrollMode(View v) {
+    public static int getOverScrollMode(View view) {
         //noinspection ResourceType
-        return v.getOverScrollMode();
+        return view.getOverScrollMode();
     }
 
     /**
@@ -623,14 +624,14 @@
      * Setting the over-scroll mode of a view will have an effect only if the
      * view is capable of scrolling.
      *
-     * @param v The View against which to invoke the method.
+     * @param view The View against which to invoke the method.
      * @param overScrollMode The new over-scroll mode for this view.
      * @deprecated Call {@link View#setOverScrollMode(int)} directly. This method will be
      * removed in a future release.
      */
     @Deprecated
-    public static void setOverScrollMode(View v, @OverScroll int overScrollMode) {
-        v.setOverScrollMode(overScrollMode);
+    public static void setOverScrollMode(View view, @OverScroll int overScrollMode) {
+        view.setOverScrollMode(overScrollMode);
     }
 
     /**
@@ -761,6 +762,7 @@
      * the delegate to null, an empty delegate will be attached to ensure that other compatibility
      * behavior continues to work for this view.
      *
+     * @param v view for which to set the delegate.
      * @param delegate the object to which accessibility method calls should be
      *                 delegated
      * @see AccessibilityDelegateCompat
@@ -801,12 +803,13 @@
      * <p>This method is only supported on API >= 26.
      * On API 25 and below, it is a no-op</p>
      *
+     * @param view view for which to set the hints.
      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
      * {@link android.R.attr#autofillHints}
      */
-    public static void setAutofillHints(@NonNull View v, @Nullable String... autofillHints) {
+    public static void setAutofillHints(@NonNull View view, @Nullable String... autofillHints) {
         if (Build.VERSION.SDK_INT >= 26) {
-            Api26Impl.setAutofillHints(v, autofillHints);
+            Api26Impl.setAutofillHints(view, autofillHints);
         }
     }
 
@@ -1456,6 +1459,7 @@
      * <p>
      * <em>Note:</em> Prior to API 21, this method will always return {@code true}.
      *
+     * @param view view for which to check the state.
      * @return Whether the view is exposed for accessibility.
      * @see #setImportantForAccessibility(View, int)
      * @see #getImportantForAccessibility(View)
@@ -1482,6 +1486,7 @@
      * This is intended to be controlled by screen readers. Apps changing focus can confuse
      * screen readers, and the resulting behavior can vary by device and screen reader version.
      *
+     * @param view view on which to perform the action.
      * @param action The action to perform.
      * @param arguments Optional action arguments.
      * @return Whether the action was performed.
@@ -1723,6 +1728,7 @@
      * {@code android:contentDescription}. It is expected that a content description mostly
      * remains constant, while a state description updates from time to time.
      *
+     * @param view view for which to set the description.
      * @param stateDescription the state description of this node.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -1745,6 +1751,7 @@
      * You must call {@link #setStateDescription(View, CharSequence)} to modify the
      * state description.
      *
+     * @param view view for which to get the description
      * @return the state description
      * @see #setStateDescription(View, CharSequence)
      */
@@ -2033,6 +2040,7 @@
      * the target class type is unconstrained, an explicit cast may be
      * necessary.
      *
+     * @param view the view to start the search from.
      * @param id the ID to search for
      * @return a view with given ID
      * @see View#findViewById(int)
@@ -2055,6 +2063,7 @@
      * Indicates whether this View is opaque. An opaque View guarantees that it will
      * draw all the pixels overlapping its bounds using a fully opaque color.
      *
+     * @param view view for which to check the state.
      * @return True if this View is guaranteed to be fully opaque, false otherwise.
      * @deprecated Use {@link View#isOpaque()} directly. This method will be
      * removed in a future release.
@@ -2074,6 +2083,7 @@
      *
      * @param size How big the view wants to be
      * @param measureSpec Constraints imposed by the parent
+     * @param childMeasuredState Size information bit mask for the view's children.
      * @return Size information bit mask as defined by
      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
      *
@@ -2468,6 +2478,7 @@
      * This effectively positions the object post-layout, in addition to wherever the object's
      * layout placed it.
      *
+     * @param view view for which to set the translation.
      * @param value The horizontal position of this view relative to its left position,
      * in pixels.
      *
@@ -2483,6 +2494,7 @@
      * This effectively positions the object post-layout, in addition to wherever the object's
      * layout placed it.
      *
+     * @param view view for which to set the translation.
      * @param value The vertical position of this view relative to its top position,
      * in pixels.
      *
@@ -2503,6 +2515,7 @@
      * performance implications, especially for large views. It is best to use the alpha property
      * sparingly and transiently, as in the case of fading animations.</p>
      *
+     * @param view view to set the alpha on.
      * @param value The opacity of the view.
      *
      * @deprecated Use {@link View#setAlpha(float)} directly.
@@ -2518,6 +2531,7 @@
      * the x value passed in and the current left property of the view as determined
      * by the layout bounds.
      *
+     * @param view view to set the position on.
      * @param value The visual x position of this view, in pixels.
      *
      * @deprecated Use {@link View#setX(float)} directly.
@@ -2533,6 +2547,7 @@
      * the y value passed in and the current top property of the view as determined by the
      * layout bounds.
      *
+     * @param view view to set the position on.
      * @param value The visual y position of this view, in pixels.
      *
      * @deprecated Use {@link View#setY(float)} directly.
@@ -2546,6 +2561,7 @@
      * Sets the degrees that the view is rotated around the pivot point. Increasing values
      * result in clockwise rotation.
      *
+     * @param view view to set the rotation on.
      * @param value The degrees of rotation.
      *
      * @deprecated Use {@link View#setRotation(float)} directly.
@@ -2560,6 +2576,7 @@
      * Increasing values result in clockwise rotation from the viewpoint of looking down the
      * x axis.
      *
+     * @param view view to set the rotation on.
      * @param value The degrees of X rotation.
      *
      * @deprecated Use {@link View#setRotationX(float)} directly.
@@ -2574,6 +2591,7 @@
      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
      * down the y axis.
      *
+     * @param view view to set the rotation on.
      * @param value The degrees of Y rotation.
      *
      * @deprecated Use {@link View#setRotationY(float)} directly.
@@ -2587,6 +2605,7 @@
      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
      * the view's unscaled width. A value of 1 means that no scaling is applied.
      *
+     * @param view view to set the scale on.
      * @param value The scaling factor.
      *
      * @deprecated Use {@link View#setScaleX(float)} directly.
@@ -2600,6 +2619,7 @@
      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
      * the view's unscaled width. A value of 1 means that no scaling is applied.
      *
+     * @param view view to set the scale on.
      * @param value The scaling factor.
      *
      * @deprecated Use {@link View#setScaleY(float)} directly.
@@ -2613,6 +2633,7 @@
      * The x location of the point around which the view is
      * {@link #setRotation(View, float) rotated} and {@link #setScaleX(View, float) scaled}.
      *
+     * @param view view for which to get the pivot.
      * @deprecated Use {@link View#getPivotX()} directly.
      */
     @Deprecated
@@ -2627,6 +2648,7 @@
      * Setting this property disables this behavior and causes the view to use only the
      * explicitly set pivotX and pivotY values.
      *
+     * @param view view for which to set the pivot.
      * @param value The x location of the pivot point.
      *
      * @deprecated Use {@link View#setPivotX(float)} directly.
@@ -2640,6 +2662,7 @@
      * The y location of the point around which the view is {@link #setRotation(View,
      * float) rotated} and {@link #setScaleY(View, float) scaled}.
      *
+     * @param view view for which to get the pivot.
      * @return The y location of the pivot point.
      *
      * @deprecated Use {@link View#getPivotY()} directly.
@@ -2656,6 +2679,7 @@
      * Setting this property disables this behavior and causes the view to use only the
      * explicitly set pivotX and pivotY values.
      *
+     * @param view view for which to set the pivot.
      * @param value The y location of the pivot point.
      *
      * @deprecated Use {@link View#setPivotX(float)} directly.
@@ -2666,6 +2690,7 @@
     }
 
     /**
+     * @param view view for which to get the rotation.
      * @deprecated Use {@link View#getRotation()} directly.
      */
     @Deprecated
@@ -2674,6 +2699,7 @@
     }
 
     /**
+     * @param view view for which to get the rotation.
      * @deprecated Use {@link View#getRotationX()} directly.
      */
     @Deprecated
@@ -2682,6 +2708,7 @@
     }
 
     /**
+     * @param view view for which to get the rotation.
      * @deprecated Use {@link View#getRotationY()} directly.
      */
     @Deprecated
@@ -2690,6 +2717,7 @@
     }
 
     /**
+     * @param view view for which to get the scale.
      * @deprecated Use {@link View#getScaleX()} directly.
      */
     @Deprecated
@@ -2698,6 +2726,7 @@
     }
 
     /**
+     * @param view view for which to get the scale.
      * @deprecated Use {@link View#getScaleY()} directly.
      */
     @Deprecated
@@ -2706,6 +2735,7 @@
     }
 
     /**
+     * @param view view for which to get the X.
      * @deprecated Use {@link View#getX()} directly.
      */
     @Deprecated
@@ -2714,6 +2744,7 @@
     }
 
     /**
+     * @param view view for which to get the Y.
      * @deprecated Use {@link View#getY()} directly.
      */
     @Deprecated
@@ -2722,6 +2753,8 @@
     }
 
     /**
+     * @param view view for which to set the elevation.
+     * @param elevation view elevation in pixels.
      * Sets the base elevation of this view, in pixels.
      */
     public static void setElevation(@NonNull View view, float elevation) {
@@ -2733,6 +2766,7 @@
     /**
      * The base elevation of this view relative to its parent, in pixels.
      *
+     * @param view view for which to get the elevation.
      * @return The base depth position of the view, in pixels.
      */
     public static float getElevation(@NonNull View view) {
@@ -2744,6 +2778,8 @@
 
     /**
      * Sets the depth location of this view relative to its {@link #getElevation(View) elevation}.
+     * @param view view for which to set the translation.
+     * @param translationZ the depth of location of this view relative its elevation.
      */
     public static void setTranslationZ(@NonNull View view, float translationZ) {
         if (Build.VERSION.SDK_INT >= 21) {
@@ -2754,6 +2790,7 @@
     /**
      * The depth location of this view relative to its {@link #getElevation(View) elevation}.
      *
+     * @param view view for which to get the translation.
      * @return The depth of this view relative to its elevation.
      */
     public static float getTranslationZ(@NonNull View view) {
@@ -2805,6 +2842,8 @@
     /**
      * Returns the current system UI visibility that is currently set for the entire window.
      *
+     * @param view view for which to get the visibility.
+     *
      * @deprecated SystemUiVisibility flags are deprecated. Use
      * {@link WindowInsetsController} instead.
      */
@@ -2819,6 +2858,8 @@
     /**
      * Ask that a new dispatch of {@code View.onApplyWindowInsets(WindowInsets)} be performed. This
      * falls back to {@code View.requestFitSystemWindows()} where available.
+     *
+     * @param view view for which to send the request.
      */
     public static void requestApplyInsets(@NonNull View view) {
         if (Build.VERSION.SDK_INT >= 20) {
@@ -2832,6 +2873,7 @@
      * Tells the ViewGroup whether to draw its children in the order defined by the method
      * {@code ViewGroup.getChildDrawingOrder(int, int)}.
      *
+     * @param viewGroup the ViewGroup for which to set the mode.
      * @param enabled true if the order of the children when drawing is determined by
      *        {@link ViewGroup#getChildDrawingOrder(int, int)}, false otherwise
      *
@@ -2865,10 +2907,12 @@
     /**
      * Returns true if this view should adapt to fit system window insets. This method will always
      * return false before API 16 (Jellybean).
+     *
+     * @param view view for which to get the state.
      */
-    public static boolean getFitsSystemWindows(@NonNull View v) {
+    public static boolean getFitsSystemWindows(@NonNull View view) {
         if (Build.VERSION.SDK_INT >= 16) {
-            return Api16Impl.getFitsSystemWindows(v);
+            return Api16Impl.getFitsSystemWindows(view);
         }
         return false;
     }
@@ -2879,6 +2923,10 @@
      * the default implementation of {@link View#fitSystemWindows(Rect)} will be
      * executed. See that method for more details.
      *
+     * @param view view for which to set the state.
+     * @param fitSystemWindows whether or not this view should account for system screen
+     *                         decorations.
+     *
      * @deprecated Use {@link View#setFitsSystemWindows(boolean)} directly.
      */
     @Deprecated
@@ -2893,21 +2941,25 @@
      * On API 21 and above, also calls <code>StateListAnimator#jumpToCurrentState()</code>
      * if there is a StateListAnimator attached to this view.
      *
+     * @param view view for which to jump the drawable state.
      * @deprecated Use {@link View#jumpDrawablesToCurrentState()} directly.
      */
     @Deprecated
-    public static void jumpDrawablesToCurrentState(View v) {
-        v.jumpDrawablesToCurrentState();
+    public static void jumpDrawablesToCurrentState(View view) {
+        view.jumpDrawablesToCurrentState();
     }
 
     /**
      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
      * window insets to this view. This will only take effect on devices with API 21 or above.
+     *
+     * @param view view on which to the listener.
+     * @param listener listener for the applied window insets.
      */
-    public static void setOnApplyWindowInsetsListener(@NonNull final View v,
+    public static void setOnApplyWindowInsetsListener(@NonNull final View view,
             final @Nullable OnApplyWindowInsetsListener listener) {
         if (Build.VERSION.SDK_INT >= 21) {
-            Api21Impl.setOnApplyWindowInsetsListener(v, listener);
+            Api21Impl.setOnApplyWindowInsetsListener(view, listener);
         }
     }
 
@@ -2948,6 +3000,7 @@
      * The method returns the insets provided minus any that were applied by this view or its
      * children.</p>
      *
+     * @param view view for which to dispatch the request.
      * @param insets Insets to apply
      * @return The provided insets minus the insets that were consumed
      */
@@ -2975,6 +3028,7 @@
      * <p>
      * On devices running API 28 and below, this method has no effect.
      *
+     * @param view view for which to set the exclusion rects.
      * @param rects A list of precision gesture regions that this view needs to function correctly
      * @see View#setSystemGestureExclusionRects
      */
@@ -2991,6 +3045,8 @@
      * <p>
      * On devices running API 28 and below, this method always returns an empty list.
      *
+     * @param view view for which to get the exclusion rects.
+     *
      * @see View#getSystemGestureExclusionRects
      */
     @NonNull
@@ -3024,6 +3080,7 @@
      * Compute insets that should be consumed by this view and the ones that should propagate
      * to those under it.
      *
+     * @param view view for which insets need to be computed.
      * @param insets Insets currently being processed by this View, likely received as a parameter
      *           to {@link View#onApplyWindowInsets(WindowInsets)}.
      * @param outLocalInsets A Rect that will receive the insets that should be consumed
@@ -3084,6 +3141,7 @@
      * <p>
      * Prior to API 21, this method has no effect.
      *
+     * @param view view for which to set the callback.
      * @param callback The callback to set, or <code>null</code> to remove the currently installed
      *                 callback
      */
@@ -3299,14 +3357,15 @@
      * Controls whether the entire hierarchy under this view will save its
      * state when a state saving traversal occurs from its parent.
      *
+     * @param view view for which to set the state.
      * @param enabled Set to false to <em>disable</em> state saving, or true
      * (the default) to allow it.
      *
      * @deprecated Use {@link View#setSaveFromParentEnabled(boolean)} directly.
      */
     @Deprecated
-    public static void setSaveFromParentEnabled(View v, boolean enabled) {
-        v.setSaveFromParentEnabled(enabled);
+    public static void setSaveFromParentEnabled(View view, boolean enabled) {
+        view.setSaveFromParentEnabled(enabled);
     }
 
     /**
@@ -3316,6 +3375,7 @@
      * currently interacting with.  Activation is a longer-term state that the
      * user can move views in and out of.
      *
+     * @param view view for which to set the state.
      * @param activated true if the view must be activated, false otherwise
      *
      * @deprecated Use {@link View#setActivated(boolean)} directly.
@@ -3337,6 +3397,7 @@
      * ImageView with only the foreground image. The default implementation returns true; subclasses
      * should override if they have cases which can be optimized.</p>
      *
+     * @param view view for which to get the state.
      * @return true if the content in this view might overlap, false otherwise.
      */
     public static boolean hasOverlappingRendering(@NonNull View view) {
@@ -3350,6 +3411,7 @@
      * Return if the padding as been set through relative values
      * {@code View.setPaddingRelative(int, int, int, int)} or thru
      *
+     * @param view view for which to get the state.
      * @return true if the padding is relative or false if it is not.
      */
     public static boolean isPaddingRelative(@NonNull View view) {
@@ -3363,7 +3425,9 @@
      * Set the background of the {@code view} to a given Drawable, or remove the background. If the
      * background has padding, {@code view}'s padding is set to the background's padding. However,
      * when a background is removed, this View's padding isn't touched. If setting the padding is
-     * desired, please use{@code setPadding(int, int, int, int)}.
+     * desired, please use {@code setPadding(int, int, int, int)}.
+     * @param view view for which to set the background.
+     * @param background the drawable to use as view background.
      */
     public static void setBackground(@NonNull View view, @Nullable Drawable background) {
         if (Build.VERSION.SDK_INT >= 16) {
@@ -3478,6 +3542,7 @@
      * while a nested scroll is in progress has the effect of
      * {@link #stopNestedScroll(View) stopping} the nested scroll.</p>
      *
+     * @param view view for which to set the state.
      * @param enabled true to enable nested scrolling, false to disable
      *
      * @see #isNestedScrollingEnabled(View)
@@ -3522,6 +3587,7 @@
      * <p>This version of the method just calls {@link #startNestedScroll(View, int, int)} using
      * the touch input type.</p>
      *
+     * @param view view for which to start the scroll.
      * @param axes Flags consisting of a combination of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}
      *             and/or {@link ViewCompat#SCROLL_AXIS_VERTICAL}.
      * @return true if a cooperative parent was found and nested scrolling has been enabled for
@@ -3544,6 +3610,8 @@
      * <p>This version of the method just calls {@link #stopNestedScroll(View, int)} using the
      * touch input type.</p>
      *
+     * @param view view for which to stop the scroll.
+     *
      * @see #startNestedScroll(View, int)
      */
     @SuppressWarnings("RedundantCast") // Intentionally invoking interface method.
@@ -3561,6 +3629,7 @@
      * <p>This version of the method just calls {@link #hasNestedScrollingParent(View, int)}
      * using the touch input type.</p>
      *
+     * @param view view for which to check the parent.
      * @return whether this view has a nested scrolling parent
      */
     @SuppressWarnings("RedundantCast") // Intentionally invoking interface method.
@@ -3581,6 +3650,7 @@
      * {@link #dispatchNestedScroll(View, int, int, int, int, int[], int)} using the touch input
      * type.</p>
      *
+     * @param view view for which to dispatch the scroll.
      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
@@ -3612,6 +3682,7 @@
      * {@link #dispatchNestedPreScroll(View, int, int, int[], int[], int)} using the touch input
      * type.</p>
      *
+     * @param view view for which to dispatch the scroll.
      * @param dx Horizontal scroll distance in pixels
      * @param dy Vertical scroll distance in pixels
      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
@@ -3664,6 +3735,7 @@
      * {@link NestedScrollingParent#onNestedScroll(View, int, int, int, int)}.
      * </p>
      *
+     * @param view view on which to start the scroll.
      * @param axes Flags consisting of a combination of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}
      *             and/or {@link ViewCompat#SCROLL_AXIS_VERTICAL}.
      * @param type the type of input which cause this scroll event
@@ -3689,6 +3761,7 @@
      *
      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
      *
+     * @param view view for which to stop the scroll.
      * @param type the type of input which cause this scroll event
      * @see #startNestedScroll(View, int)
      */
@@ -3706,6 +3779,7 @@
      * <p>The presence of a nested scrolling parent indicates that this view has initiated
      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
      *
+     * @param view view for which to check the parent.
      * @param type the type of input which cause this scroll event
      * @return whether this view has a nested scrolling parent
      */
@@ -3736,6 +3810,7 @@
      * to be 0, in order to tell how much was actually consumed up the hierarchy of scrolling
      * parents.
      *
+     * @param view view for which to dispatch the scroll.
      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
@@ -3772,6 +3847,7 @@
      * {@link #dispatchNestedPreScroll(View, int, int, int[], int[]) dispatchNestedPreScroll} before
      * consuming a component of the scroll event themselves.
      *
+     * @param view view for which to dispatch the scroll.
      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
@@ -3805,6 +3881,7 @@
      * scrolling operation to consume some or all of the scroll operation before the child view
      * consumes it.</p>
      *
+     * @param view view for which to dispatch the scroll.
      * @param dx Horizontal scroll distance in pixels
      * @param dy Vertical scroll distance in pixels
      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
@@ -3841,6 +3918,7 @@
      * its own content, it can use this method to delegate the fling to its nested scrolling
      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
      *
+     * @param view view for which to dispatch the fling.
      * @param velocityX Horizontal fling velocity in pixels per second
      * @param velocityY Vertical fling velocity in pixels per second
      * @param consumed true if the child consumed the fling, false otherwise
@@ -3885,6 +3963,7 @@
      * should not offer a horizontal fling velocity to its parents since scrolling along that
      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
      *
+     * @param view view for which to dispatch the fling.
      * @param velocityX Horizontal fling velocity in pixels per second
      * @param velocityY Vertical fling velocity in pixels per second
      * @return true if a nested scrolling parent consumed the fling
@@ -3953,6 +4032,8 @@
      * {@link #setTranslationZ(View, float) translationZ} property plus the current
      * {@link #getElevation(View) elevation} property.
      *
+     * @param view view for which to get the position.
+     *
      * @return The visual z position of this view, in pixels.
      */
     public static float getZ(@NonNull View view) {
@@ -3972,6 +4053,7 @@
      *     <li>API &lt; 21: No-op</li>
      * </ul>
      *
+     * @param view view for which to set the position.
      * @param z The visual z position of this view, in pixels.
      */
     public static void setZ(@NonNull View view, float z) {
@@ -3983,6 +4065,7 @@
     /**
      * Offset this view's vertical location by the specified number of pixels.
      *
+     * @param view view that needs to be offset.
      * @param offset the number of pixels to offset the view by
      */
     public static void offsetTopAndBottom(@NonNull View view, int offset) {
@@ -4031,6 +4114,7 @@
     /**
      * Offset this view's horizontal location by the specified amount of pixels.
      *
+     * @param view view which needs to be offset.
      * @param offset the number of pixels to offset the view by
      */
     public static void offsetLeftAndRight(@NonNull View view, int offset) {
@@ -4142,6 +4226,7 @@
      * <p>
      * See {@link #setScrollIndicators(View, int, int)} for usage information.
      *
+     * @param view view for which to set the state.
      * @param indicators a bitmask of indicators that should be enabled, or
      *                   {@code 0} to disable all indicators
      *
@@ -4167,6 +4252,7 @@
      * <p>
      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators}
      *
+     * @param view view for which to set the state.
      * @param indicators the indicator direction, or the logical OR of multiple
      *             indicator directions. One or more of:
      *             <ul>
@@ -4177,6 +4263,7 @@
      *               <li>{@link #SCROLL_INDICATOR_START}</li>
      *               <li>{@link #SCROLL_INDICATOR_END}</li>
      *             </ul>
+     * @param mask the mask for scroll indicators.
      *
      * @see #setScrollIndicators(View, int)
      * @see #getScrollIndicators(View)
@@ -4198,6 +4285,8 @@
      * To check whether the bottom scroll indicator is enabled, use the value
      * of {@code (ViewCompat.getScrollIndicators(view) & ViewCompat.SCROLL_INDICATOR_BOTTOM) != 0}.
      *
+     * @param view view for which to get the state.
+     *
      * @return a bitmask representing the enabled scroll indicators
      */
     public static int getScrollIndicators(@NonNull View view) {
@@ -4209,6 +4298,7 @@
 
     /**
      * Set the pointer icon for the current view.
+     * @param view view for which to set the pointer icon.
      * @param pointerIcon A PointerIconCompat instance which will be shown when the mouse hovers.
      */
     public static void setPointerIcon(@NonNull View view, @Nullable PointerIconCompat pointerIcon) {
@@ -4248,6 +4338,7 @@
      * <p>Prior to API 26 this does nothing. Use TooltipCompat class from v7 appcompat library
      * for a compatible tooltip implementation.</p>
      *
+     * @param view view for which to set the tooltip.
      * @param tooltipText the tooltip text
      */
     public static void setTooltipText(@NonNull View view, @Nullable CharSequence tooltipText) {
@@ -4306,6 +4397,7 @@
      * Sets the ID of the next keyboard navigation cluster root view. Does nothing if {@code view}
      * is not a keyboard navigation cluster or if API < 26.
      *
+     * @param view view for which to set the ID.
      * @param nextClusterForwardId next cluster ID, or {@link View#NO_ID} if the framework
      *                             should decide automatically.
      */
@@ -4319,6 +4411,7 @@
      * Returns whether {@code view} is a root of a keyboard navigation cluster. Always returns
      * {@code false} on API < 26.
      *
+     * @param view view for which to check the cluster.
      * @return {@code true} if this view is a root of a cluster, or {@code false} otherwise.
      */
     public static boolean isKeyboardNavigationCluster(@NonNull View view) {
@@ -4332,6 +4425,7 @@
      * Set whether {@code view} is a root of a keyboard navigation cluster. Does nothing if
      * API < 26.
      *
+     * @param view view for which to set the cluster.
      * @param isCluster {@code true} to mark {@code view} as the root of a cluster, {@code false}
      *                  to unmark.
      */
@@ -4348,6 +4442,7 @@
      * Focus gets restored for a view hierarchy when the root of the hierarchy gets added to a
      * window or serves as a target of cluster navigation.
      *
+     * @param view view for which to check the state.
      * @return {@code true} if {@code view} is the default-focus view, {@code false} otherwise.
      */
     public static boolean isFocusedByDefault(@NonNull View view) {
@@ -4366,6 +4461,7 @@
      * <p>
      * Does nothing on API < 26.
      *
+     * @param view view for which to set the state.
      * @param isFocusedByDefault {@code true} to set {@code view} as the default-focus view,
      *                           {@code false} otherwise.
      */
@@ -4379,6 +4475,7 @@
      * Find the nearest keyboard navigation cluster in the specified direction.
      * This does not actually give focus to that cluster.
      *
+     * @param view view on which to do the search.
      * @param currentCluster The starting point of the search. {@code null} means the current
      *                       cluster is not found yet.
      * @param direction Direction to look.
@@ -4400,6 +4497,7 @@
      * including {@code view} if it is a cluster root itself) to {@code views}. Does nothing
      * on API < 26.
      *
+     * @param view view on which to make the change.
      * @param views collection of keyboard navigation cluster roots found so far.
      * @param direction direction to look.
      */
@@ -4415,6 +4513,7 @@
      * If the default-focus view cannot be found or if API < 26, this falls back to calling
      * {@link View#requestFocus(int)}.
      *
+     * @param view view on which to make the change.
      * @return {@code true} if {@code view} or one of its descendants took focus, {@code false}
      *         otherwise.
      */
@@ -4437,6 +4536,7 @@
      * this method to return true. A view set to {@link View#FOCUSABLE_AUTO} that resolves
      * to focusable will not.</p>
      *
+     * @param view view on which to make the change.
      * @return {@code true} if the view is focusable or if the view contains a focusable
      *         view, {@code false} otherwise
      */
@@ -4472,26 +4572,27 @@
      * Adds a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
      * UI thread.
      *
+     * @param view view on which to add the listener.
      * @param listener a receiver of unhandled {@link KeyEvent}s.
      * @see #removeOnUnhandledKeyEventListener
      */
-    @SuppressWarnings("unchecked")
-    public static void addOnUnhandledKeyEventListener(@NonNull View v,
+    public static void addOnUnhandledKeyEventListener(@NonNull View view,
             final @NonNull OnUnhandledKeyEventListenerCompat listener) {
         if (Build.VERSION.SDK_INT >= 28) {
-            Api28Impl.addOnUnhandledKeyEventListener(v, listener);
+            Api28Impl.addOnUnhandledKeyEventListener(view, listener);
             return;
         }
+        @SuppressWarnings("unchecked")
         ArrayList<OnUnhandledKeyEventListenerCompat> viewListeners =
                 (ArrayList<OnUnhandledKeyEventListenerCompat>)
-                        v.getTag(R.id.tag_unhandled_key_listeners);
+                        view.getTag(R.id.tag_unhandled_key_listeners);
         if (viewListeners == null) {
             viewListeners = new ArrayList<>();
-            v.setTag(R.id.tag_unhandled_key_listeners, viewListeners);
+            view.setTag(R.id.tag_unhandled_key_listeners, viewListeners);
         }
         viewListeners.add(listener);
         if (viewListeners.size() == 1) {
-            UnhandledKeyEventManager.registerListeningView(v);
+            UnhandledKeyEventManager.registerListeningView(view);
         }
     }
 
@@ -4499,23 +4600,24 @@
      * Removes a listener which will receive unhandled {@link KeyEvent}s. This must be called on the
      * UI thread.
      *
+     * @param view view from which to remove the listener.
      * @param listener a receiver of unhandled {@link KeyEvent}s.
      * @see #addOnUnhandledKeyEventListener
      */
-    @SuppressWarnings("unchecked")
-    public static void removeOnUnhandledKeyEventListener(@NonNull View v,
+    public static void removeOnUnhandledKeyEventListener(@NonNull View view,
             @NonNull OnUnhandledKeyEventListenerCompat listener) {
         if (Build.VERSION.SDK_INT >= 28) {
-            Api28Impl.removeOnUnhandledKeyEventListener(v, listener);
+            Api28Impl.removeOnUnhandledKeyEventListener(view, listener);
             return;
         }
+        @SuppressWarnings("unchecked")
         ArrayList<OnUnhandledKeyEventListenerCompat> viewListeners =
                 (ArrayList<OnUnhandledKeyEventListenerCompat>)
-                        v.getTag(R.id.tag_unhandled_key_listeners);
+                        view.getTag(R.id.tag_unhandled_key_listeners);
         if (viewListeners != null) {
             viewListeners.remove(listener);
             if (viewListeners.size() == 0) {
-                UnhandledKeyEventManager.unregisterListeningView(v);
+                UnhandledKeyEventManager.unregisterListeningView(view);
             }
         }
     }
diff --git a/core/core/src/main/java/androidx/core/view/ViewGroupCompat.java b/core/core/src/main/java/androidx/core/view/ViewGroupCompat.java
index d892cdd..207e55f 100644
--- a/core/core/src/main/java/androidx/core/view/ViewGroupCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ViewGroupCompat.java
@@ -124,6 +124,7 @@
      * Valid values are either {@link #LAYOUT_MODE_CLIP_BOUNDS} or
      * {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
      *
+     * @param group ViewGroup for which to set the mode.
      * @param mode the layout mode to use during layout operations
      *
      * @see #getLayoutMode(ViewGroup)
@@ -137,6 +138,7 @@
     /**
      * Changes whether or not this ViewGroup should be treated as a single entity during
      * Activity Transitions.
+     * @param group ViewGroup for which to set the mode.
      * @param isTransitionGroup Whether or not the ViewGroup should be treated as a unit
      *                          in Activity transitions. If false, the ViewGroup won't transition,
      *                          only its children. If true, the entire ViewGroup will transition
diff --git a/core/core/src/main/java/androidx/core/view/ViewParentCompat.java b/core/core/src/main/java/androidx/core/view/ViewParentCompat.java
index 7c14bb5..517fc9b8 100644
--- a/core/core/src/main/java/androidx/core/view/ViewParentCompat.java
+++ b/core/core/src/main/java/androidx/core/view/ViewParentCompat.java
@@ -76,6 +76,7 @@
      * {@link #onStartNestedScroll(ViewParent, View, View, int, int)} using the touch input type.
      * </p>
      *
+     * @param parent ViewParent that contains the child view.
      * @param child Direct child of this ViewParent containing target
      * @param target View that initiated the nested scroll
      * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
@@ -94,6 +95,7 @@
      * {@link #onNestedScrollAccepted(ViewParent, View, View, int, int)} using the touch input type.
      * </p>
      *
+     * @param parent ViewParent that contains the child view.
      * @param child Direct child of this ViewParent containing target
      * @param target View that initiated the nested scroll
      * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
@@ -110,6 +112,7 @@
      * <p>This version of the method just calls {@link #onStopNestedScroll(ViewParent, View, int)}
      * using the touch input type.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      */
     public static void onStopNestedScroll(@NonNull ViewParent parent, @NonNull View target) {
@@ -123,6 +126,7 @@
      * {@link #onNestedScroll(ViewParent, View, int, int, int, int, int)} using the touch input
      * type.
      *
+     * @param parent ViewParent that contains the target view.
      * @param target The descendent view controlling the nested scroll
      * @param dxConsumed Horizontal scroll distance in pixels already consumed by target
      * @param dyConsumed Vertical scroll distance in pixels already consumed by target
@@ -150,7 +154,8 @@
      * a list within a vertical drawer where the drawer begins dragging once the edge of inner
      * scrolling content is reached.</p>
      *
-     * @param target The descendent view controlling the nested scroll
+     * @param parent ViewParent that contains the target view.
+     * @param target The descendant view controlling the nested scroll
      * @param dxConsumed Horizontal scroll distance in pixels already consumed by target
      * @param dyConsumed Vertical scroll distance in pixels already consumed by target
      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by target
@@ -170,6 +175,7 @@
      * {@link #onNestedPreScroll(ViewParent, View, int, int, int[], int)} using the touch input
      * type.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      * @param dx Horizontal scroll distance in pixels
      * @param dy Vertical scroll distance in pixels
@@ -196,6 +202,7 @@
      * will receive a call to {@link #onStopNestedScroll(ViewParent, View, int)}.
      * </p>
      *
+     * @param parent ViewParent that contains the child view.
      * @param child Direct child of this ViewParent containing target
      * @param target View that initiated the nested scroll
      * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
@@ -236,6 +243,7 @@
      * for the nested scroll. Implementations of this method should always call their superclass's
      * implementation of this method if one is present.</p>
      *
+     * @param parent ViewParent that contains the child view.
      * @param child Direct child of this ViewParent containing target
      * @param target View that initiated the nested scroll
      * @param nestedScrollAxes Flags consisting of {@link ViewCompat#SCROLL_AXIS_HORIZONTAL},
@@ -276,6 +284,7 @@
      * Implementations of this method should always call their superclass's implementation of this
      * method if one is present.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      * @param type the type of input which cause this scroll event
      */
@@ -315,6 +324,7 @@
      * a list within a vertical drawer where the drawer begins dragging once the edge of inner
      * scrolling content is reached.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target The descendent view controlling the nested scroll
      * @param dxConsumed Horizontal scroll distance in pixels already consumed by target
      * @param dyConsumed Vertical scroll distance in pixels already consumed by target
@@ -375,6 +385,7 @@
      * This parameter will never be null. Initial values for consumed[0] and consumed[1]
      * will always be 0.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      * @param dx Horizontal scroll distance in pixels
      * @param dy Vertical scroll distance in pixels
@@ -415,6 +426,7 @@
      * its own content, it can use this method to delegate the fling to its nested scrolling
      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      * @param velocityX Horizontal velocity in pixels per second
      * @param velocityY Vertical velocity in pixels per second
@@ -453,6 +465,7 @@
      * <code>true</code> from this method, the parent indicates that the child should not
      * fling its own internal content as well.</p>
      *
+     * @param parent ViewParent that contains the target view.
      * @param target View that initiated the nested scroll
      * @param velocityX Horizontal velocity in pixels per second
      * @param velocityY Vertical velocity in pixels per second
@@ -479,6 +492,8 @@
      * Notifies a view parent that the accessibility state of one of its
      * descendants has changed and that the structure of the subtree is
      * different.
+     *
+     * @param parent ViewParent that contains the target view.
      * @param child The direct child whose subtree has changed.
      * @param source The descendant view that changed.
      * @param changeType A bit mask of the types of changes that occurred. One
diff --git a/core/core/src/main/java/androidx/core/view/WindowCompat.java b/core/core/src/main/java/androidx/core/view/WindowCompat.java
index 178501d..4cdb4dd 100644
--- a/core/core/src/main/java/androidx/core/view/WindowCompat.java
+++ b/core/core/src/main/java/androidx/core/view/WindowCompat.java
@@ -78,6 +78,7 @@
      * the target class type is unconstrained, an explicit cast may be
      * necessary.
      *
+     * @param window window in which to find the view.
      * @param id the ID to search for
      * @return a view with given ID
      * @see ViewCompat#requireViewById(View, int)
diff --git a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java
index fbea1ca..c8cd11d 100644
--- a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java
+++ b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityEventCompat.java
@@ -371,6 +371,7 @@
      * Appends an {@link AccessibilityRecord} to the end of
      * event records.
      *
+     * @param event event for which to append the record.
      * @param record The record to append.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -386,6 +387,7 @@
     /**
      * Gets the record at a given index.
      *
+     * @param event event for which to get the record.
      * @param index The index.
      * @return The record at the specified index.
      *
@@ -422,6 +424,7 @@
      * Sets the bit mask of node tree changes signaled by an
      * {@link #TYPE_WINDOW_CONTENT_CHANGED} event.
      *
+     * @param event event for which to set the types.
      * @param changeTypes The bit mask of change types.
      * @throws IllegalStateException If called from an AccessibilityService.
      * @see #getContentChangeTypes(AccessibilityEvent)
@@ -459,6 +462,7 @@
     /**
      * Sets the movement granularity that was traversed.
      *
+     * @param event event for which to set the granularity.
      * @param granularity The granularity.
      *
      * @throws IllegalStateException If called from an AccessibilityService.
@@ -495,6 +499,7 @@
      * <li>etc.
      * </ul>
      *
+     * @param event event for which to set the action.
      * @param action The action.
      * @throws IllegalStateException If called from an AccessibilityService.
      * @see AccessibilityNodeInfoCompat#performAction(int)
diff --git a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java
index 0df339c..a5e0a2b 100644
--- a/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java
+++ b/core/core/src/main/java/androidx/core/view/accessibility/AccessibilityManagerCompat.java
@@ -161,6 +161,7 @@
      * Registers a {@link TouchExplorationStateChangeListener} for changes in
      * the global touch exploration state of the system.
      *
+     * @param manager AccessibilityManager for which to add the listener.
      * @param listener The listener.
      * @return True if successfully registered.
      */
@@ -177,6 +178,7 @@
     /**
      * Unregisters a {@link TouchExplorationStateChangeListener}.
      *
+     * @param manager AccessibilityManager for which to remove the listener.
      * @param listener The listener.
      * @return True if successfully unregistered.
      */
diff --git a/core/core/src/main/java/androidx/core/view/inputmethod/EditorInfoCompat.java b/core/core/src/main/java/androidx/core/view/inputmethod/EditorInfoCompat.java
index fedfc4b..5f89ffe 100644
--- a/core/core/src/main/java/androidx/core/view/inputmethod/EditorInfoCompat.java
+++ b/core/core/src/main/java/androidx/core/view/inputmethod/EditorInfoCompat.java
@@ -207,6 +207,7 @@
      * for IMEs to provide many modern features right after the connection setup. We recommend
      * calling this method in your implementation.
      *
+     * @param editorInfo the editor with which to set the text.
      * @param sourceText The complete input text.
      */
     public static void setInitialSurroundingText(@NonNull EditorInfo editorInfo,
@@ -227,6 +228,7 @@
      * try to include the selected text within {@code subText} to give the system best flexibility
      * to choose where and how to trim {@code subText} when necessary.
      *
+     * @param editorInfo the editor with which to set the text.
      * @param subText The input text. When it was trimmed, {@code subTextStart} must be provided
      *                correctly.
      * @param subTextStart  The position that the input text got trimmed. For example, when the
@@ -344,6 +346,7 @@
      * Get <var>n</var> characters of text before the current cursor position. May be {@code null}
      * when the protocol is not supported.
      *
+     * @param editorInfo the editor with which to get the text.
      * @param length The expected length of the text.
      * @param flags Supplies additional options controlling how the text is returned. May be
      * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
@@ -381,6 +384,7 @@
      * Gets the selected text, if any. May be {@code null} when no text is selected or the selected
      * text is way too long.
      *
+     * @param editorInfo the editor with which to get the text.
      * @param flags Supplies additional options controlling how the text is returned. May be
      * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
      * @return the text that is currently selected, if any. It could be an empty string when there
@@ -425,6 +429,7 @@
      * Get <var>n</var> characters of text after the current cursor position. May be {@code null}
      * when the protocol is not supported.
      *
+     * @param editorInfo the editor with which to get the text.
      * @param length The expected length of the text.
      * @param flags Supplies additional options controlling how the text is returned. May be
      * either 0 or {@link InputConnection#GET_TEXT_WITH_STYLES}.
diff --git a/core/core/src/main/java/androidx/core/widget/CheckedTextViewCompat.java b/core/core/src/main/java/androidx/core/widget/CheckedTextViewCompat.java
index 95d06da..1e9ab56 100644
--- a/core/core/src/main/java/androidx/core/widget/CheckedTextViewCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/CheckedTextViewCompat.java
@@ -48,6 +48,7 @@
      * automatically mutate the drawable and apply the specified tint and tint
      * mode using {@link DrawableCompat#setTintList(Drawable, ColorStateList)}.
      *
+     * @param textView CheckedTextView for which to apply the tint.
      * @param tint the tint to apply, may be {@code null} to clear tint
      * @see #setCheckMarkTintList(CheckedTextView, ColorStateList)
      */
@@ -81,6 +82,7 @@
      * {@link #setCheckMarkTintList(CheckedTextView, ColorStateList)}} to the check mark drawable.
      * The default mode is {@link PorterDuff.Mode#SRC_IN}.
      *
+     * @param textView CheckedTextView for which to apply the tint mode.
      * @param tintMode the blending mode used to apply the tint, may be
      *                 {@code null} to clear tint
      * @see #getCheckMarkTintMode(CheckedTextView)
diff --git a/core/core/src/main/java/androidx/core/widget/CompoundButtonCompat.java b/core/core/src/main/java/androidx/core/widget/CompoundButtonCompat.java
index 40f9d3c..9c45f41 100644
--- a/core/core/src/main/java/androidx/core/widget/CompoundButtonCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/CompoundButtonCompat.java
@@ -50,6 +50,7 @@
      * automatically mutate the drawable and apply the specified tint and tint
      * mode using {@link DrawableCompat#setTintList(Drawable, ColorStateList)}.
      *
+     * @param button button for which to apply the tint.
      * @param tint the tint to apply, may be {@code null} to clear tint
      *
      * @see #setButtonTintList(CompoundButton, ColorStateList)
@@ -84,6 +85,7 @@
      * {@link #setButtonTintList(CompoundButton, ColorStateList)}} to the button drawable. The
      * default mode is {@link PorterDuff.Mode#SRC_IN}.
      *
+     * @param button button for which to apply the tint mode.
      * @param tintMode the blending mode used to apply the tint, may be
      *                 {@code null} to clear tint
      *
diff --git a/core/core/src/main/java/androidx/core/widget/EdgeEffectCompat.java b/core/core/src/main/java/androidx/core/widget/EdgeEffectCompat.java
index a976eef..3723d24 100644
--- a/core/core/src/main/java/androidx/core/widget/EdgeEffectCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/EdgeEffectCompat.java
@@ -228,6 +228,7 @@
      *     }
      * </pre>
      *
+     * @param edgeEffect EdgeEffect to use.
      * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to
      *                      1.f (full length of the view) or negative values to express change
      *                      back toward the edge reached to initiate the effect.
diff --git a/core/core/src/main/java/androidx/core/widget/ListViewCompat.java b/core/core/src/main/java/androidx/core/widget/ListViewCompat.java
index 1e4175d..66180fd 100644
--- a/core/core/src/main/java/androidx/core/widget/ListViewCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/ListViewCompat.java
@@ -59,6 +59,7 @@
     /**
      * Check if the items in the list can be scrolled in a certain direction.
      *
+     * @param listView ListView for which to check the state.
      * @param direction Negative to check scrolling up, positive to check
      *            scrolling down.
      * @return true if the list can be scrolled in the specified direction,
diff --git a/core/core/src/main/java/androidx/core/widget/NestedScrollView.java b/core/core/src/main/java/androidx/core/widget/NestedScrollView.java
index b2f87ab..da12fe7 100644
--- a/core/core/src/main/java/androidx/core/widget/NestedScrollView.java
+++ b/core/core/src/main/java/androidx/core/widget/NestedScrollView.java
@@ -56,7 +56,8 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.core.R;
 import androidx.core.view.AccessibilityDelegateCompat;
-import androidx.core.view.DifferentialMotionFlingHelper;
+import androidx.core.view.DifferentialMotionFlingController;
+import androidx.core.view.DifferentialMotionFlingTarget;
 import androidx.core.view.MotionEventCompat;
 import androidx.core.view.NestedScrollingChild3;
 import androidx.core.view.NestedScrollingChildHelper;
@@ -228,12 +229,12 @@
     private OnScrollChangeListener mOnScrollChangeListener;
 
     @VisibleForTesting
-    final DifferentialMotionFlingTarget mDifferentialMotionFlingTarget =
-            new DifferentialMotionFlingTarget();
+    final DifferentialMotionFlingTargetImpl mDifferentialMotionFlingTarget =
+            new DifferentialMotionFlingTargetImpl();
 
     @VisibleForTesting
-    DifferentialMotionFlingHelper mDifferentialMotionFlingHelper =
-            new DifferentialMotionFlingHelper(getContext(), mDifferentialMotionFlingTarget);
+    DifferentialMotionFlingController mDifferentialMotionFlingController =
+            new DifferentialMotionFlingController(getContext(), mDifferentialMotionFlingTarget);
 
     public NestedScrollView(@NonNull Context context) {
         this(context, null);
@@ -1354,7 +1355,7 @@
 
                 scrollBy(-invertedDelta, x, ViewCompat.TYPE_NON_TOUCH, isSourceMouse);
                 if (flingAxis != 0) {
-                    mDifferentialMotionFlingHelper.onMotionEvent(motionEvent, flingAxis);
+                    mDifferentialMotionFlingController.onMotionEvent(motionEvent, flingAxis);
                 }
 
                 return true;
@@ -2569,8 +2570,7 @@
         }
     }
 
-    class DifferentialMotionFlingTarget
-            implements DifferentialMotionFlingHelper.DifferentialMotionFlingTarget {
+    class DifferentialMotionFlingTargetImpl implements DifferentialMotionFlingTarget {
         @Override
         public boolean startDifferentialMotionFling(float velocity) {
             if (velocity == 0) {
diff --git a/core/core/src/main/java/androidx/core/widget/PopupWindowCompat.java b/core/core/src/main/java/androidx/core/widget/PopupWindowCompat.java
index 59abc4e..415bedd 100644
--- a/core/core/src/main/java/androidx/core/widget/PopupWindowCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/PopupWindowCompat.java
@@ -86,6 +86,7 @@
      * Sets whether the popup window should overlap its anchor view when
      * displayed as a drop-down.
      *
+     * @param popupWindow popup window for which to set the anchor.
      * @param overlapAnchor Whether the popup should overlap its anchor.
      */
     @SuppressWarnings("JavaReflectionMemberAccess") // Reflective access to private method
@@ -149,6 +150,7 @@
      * {@link android.view.WindowManager.LayoutParams#type} therefore the value should match any
      * value {@link android.view.WindowManager.LayoutParams#type} accepts.
      *
+     * @param popupWindow popup window for which to set the layout type.
      * @param layoutType Layout type for this window.
      *
      * @see android.view.WindowManager.LayoutParams#type
diff --git a/core/core/src/main/java/androidx/core/widget/TextViewCompat.java b/core/core/src/main/java/androidx/core/widget/TextViewCompat.java
index 0e58694..9c5cabf 100644
--- a/core/core/src/main/java/androidx/core/widget/TextViewCompat.java
+++ b/core/core/src/main/java/androidx/core/widget/TextViewCompat.java
@@ -143,6 +143,11 @@
      * {@link TextView#setCompoundDrawables} or related methods.
      *
      * @param textView The TextView against which to invoke the method.
+     * @param start position in pixels of the start bound
+     * @param top position in pixels of the top bound
+     * @param end position in pixels of the end bound
+     * @param bottom position in pixels of the bottom bound
+     *
      * @attr name android:drawableStart
      * @attr name android:drawableTop
      * @attr name android:drawableEnd
@@ -170,6 +175,11 @@
      * {@link TextView#setCompoundDrawables} or related methods.
      *
      * @param textView The TextView against which to invoke the method.
+     * @param start drawable to use at start
+     * @param top drawable to use at top
+     * @param end drawable to use at end
+     * @param bottom drawable to use at bottom
+     *
      * @attr name android:drawableStart
      * @attr name android:drawableTop
      * @attr name android:drawableEnd
@@ -319,6 +329,7 @@
      * Specify whether this widget should automatically scale the text to try to perfectly fit
      * within the layout bounds by using the default auto-size configuration.
      *
+     * @param textView TextView for which to set the mode.
      * @param autoSizeTextType the type of auto-size. Must be one of
      *        {@link TextViewCompat#AUTO_SIZE_TEXT_TYPE_NONE} or
      *        {@link TextViewCompat#AUTO_SIZE_TEXT_TYPE_UNIFORM}
@@ -340,6 +351,7 @@
      * within the layout bounds. If all the configuration params are valid the type of auto-size is
      * set to {@link TextViewCompat#AUTO_SIZE_TEXT_TYPE_UNIFORM}.
      *
+     * @param textView TextView for which to set the mode.
      * @param autoSizeMinTextSize the minimum text size available for auto-size
      * @param autoSizeMaxTextSize the maximum text size available for auto-size
      * @param autoSizeStepGranularity the auto-size step granularity. It is used in conjunction with
@@ -377,6 +389,7 @@
      * within the layout bounds. If at least one value from the <code>presetSizes</code> is valid
      * then the type of auto-size is set to {@link TextViewCompat#AUTO_SIZE_TEXT_TYPE_UNIFORM}.
      *
+     * @param textView TextView for which to set the mode.
      * @param presetSizes an {@code int} array of sizes in pixels
      * @param unit the desired dimension unit for the preset sizes above. See {@link TypedValue} for
      *             the possible dimension units
@@ -702,6 +715,7 @@
      * <strong>Note</strong> that if {@code FontMetrics.top} or {@code FontMetrics.ascent} was
      * already greater than {@code firstBaselineToTopHeight}, the top padding is not updated.
      *
+     * @param textView TextView for which to set the padding.
      * @param firstBaselineToTopHeight distance between first baseline to top of the container
      *      in pixels
      *
@@ -747,6 +761,7 @@
      * <strong>Note</strong> that if {@code FontMetrics.bottom} or {@code FontMetrics.descent} was
      * already greater than {@code lastBaselineToBottomHeight}, the bottom padding is not updated.
      *
+     * @param textView TextView for which to set the padding.
      * @param lastBaselineToBottomHeight distance between last baseline to bottom of the container
      *      in pixels
      *
diff --git a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/PublicKeyCredentialControllerUtilityTest.kt b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/PublicKeyCredentialControllerUtilityTest.kt
index 72f7b84..ed80e40 100644
--- a/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/PublicKeyCredentialControllerUtilityTest.kt
+++ b/credentials/credentials-play-services-auth/src/androidTest/java/androidx/credentials/playservices/createpublickeycredential/PublicKeyCredentialControllerUtilityTest.kt
@@ -19,8 +19,11 @@
 import androidx.credentials.GetPublicKeyCredentialOption
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
+import androidx.testutils.assertThrows
 import com.google.android.gms.fido.fido2.api.common.ErrorCode
 import com.google.common.truth.Truth.assertThat
+import org.json.JSONArray
+import org.json.JSONException
 import org.json.JSONObject
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -75,10 +78,8 @@
         "pubKeyCredParams",
       PublicKeyCredentialControllerUtility.Companion.JSON_KEY_CLIENT_EXTENSION_RESULTS to
         "clientExtensionResults",
-      PublicKeyCredentialControllerUtility.Companion.JSON_KEY_CRED_PROPS to
-          "credProps",
-      PublicKeyCredentialControllerUtility.Companion.JSON_KEY_RK to
-          "rk"
+      PublicKeyCredentialControllerUtility.Companion.JSON_KEY_CRED_PROPS to "credProps",
+      PublicKeyCredentialControllerUtility.Companion.JSON_KEY_RK to "rk"
     )
 
   private val TEST_REQUEST_JSON = "{\"hi\":{\"there\":{\"lol\":\"Value\"}}}"
@@ -184,8 +185,12 @@
       .isEqualTo(publicKeyCredType)
     assertThat(json.get(PublicKeyCredentialControllerUtility.JSON_KEY_AUTH_ATTACHMENT))
       .isEqualTo(authenticatorAttachment)
-    assertThat(json.getJSONObject(PublicKeyCredentialControllerUtility
-      .JSON_KEY_CLIENT_EXTENSION_RESULTS).toString()).isEqualTo(expectedClientExtensions)
+    assertThat(
+        json
+          .getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
+          .toString()
+      )
+      .isEqualTo(expectedClientExtensions)
 
     // There is some embedded JSON so we should make sure we test that.
     var embeddedResponse =
@@ -200,14 +205,19 @@
       .isEqualTo(PublicKeyCredentialControllerUtility.b64Encode(byteArrayUserHandle))
 
     // ClientExtensions are another group of embedded JSON
-    var clientExtensions = json.getJSONObject(PublicKeyCredentialControllerUtility
-      .JSON_KEY_CLIENT_EXTENSION_RESULTS)
+    var clientExtensions =
+      json.getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
     assertThat(clientExtensions.get(PublicKeyCredentialControllerUtility.JSON_KEY_CRED_PROPS))
       .isNotNull()
-    assertThat(clientExtensions.getJSONObject(PublicKeyCredentialControllerUtility
-      .JSON_KEY_CRED_PROPS).getBoolean(PublicKeyCredentialControllerUtility.JSON_KEY_RK)).isTrue()
+    assertThat(
+        clientExtensions
+          .getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CRED_PROPS)
+          .getBoolean(PublicKeyCredentialControllerUtility.JSON_KEY_RK)
+      )
+      .isTrue()
   }
 
+  @Test
   fun toAssertPasskeyResponse_authenticatorAssertionResponse_noUserHandle_success() {
     val byteArrayClientDataJson = byteArrayOf(0x48, 101, 108, 108, 111)
     val byteArrayAuthenticatorData = byteArrayOf(0x48, 101, 108, 108, 112)
@@ -241,8 +251,12 @@
       .isEqualTo(publicKeyCredType)
     assertThat(json.get(PublicKeyCredentialControllerUtility.JSON_KEY_AUTH_ATTACHMENT))
       .isEqualTo(authenticatorAttachment)
-    assertThat(json.getJSONObject(PublicKeyCredentialControllerUtility
-      .JSON_KEY_CLIENT_EXTENSION_RESULTS).toString()).isEqualTo(JSONObject().toString())
+    assertThat(
+        json
+          .getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
+          .toString()
+      )
+      .isEqualTo(JSONObject().toString())
 
     // There is some embedded JSON so we should make sure we test that.
     var embeddedResponse =
@@ -257,6 +271,7 @@
       .isFalse()
   }
 
+  @Test
   fun toAssertPasskeyResponse_authenticatorAssertionResponse_noAuthenticatorAttachment_success() {
     val byteArrayClientDataJson = byteArrayOf(0x48, 101, 108, 108, 111)
     val byteArrayAuthenticatorData = byteArrayOf(0x48, 101, 108, 108, 112)
@@ -289,8 +304,12 @@
       .isEqualTo(publicKeyCredType)
     assertThat(json.optJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_AUTH_ATTACHMENT))
       .isNull()
-    assertThat(json.getJSONObject(PublicKeyCredentialControllerUtility
-      .JSON_KEY_CLIENT_EXTENSION_RESULTS).toString()).isEqualTo(JSONObject().toString())
+    assertThat(
+        json
+          .getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
+          .toString()
+      )
+      .isEqualTo(JSONObject().toString())
 
     // There is some embedded JSON so we should make sure we test that.
     var embeddedResponse =
@@ -304,4 +323,331 @@
     assertThat(embeddedResponse.has(PublicKeyCredentialControllerUtility.JSON_KEY_USER_HANDLE))
       .isFalse()
   }
+
+  @Test
+  fun toCreatePasskeyResponseJson_addOptionalAuthenticatorAttachmentAndRequiredExt() {
+    val json = JSONObject()
+
+    PublicKeyCredentialControllerUtility.addOptionalAuthenticatorAttachmentAndRequiredExtensions(
+      "attachment",
+      true,
+      true,
+      json
+    )
+
+    var clientExtensionResults =
+      json.getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
+    var credPropsObject =
+      clientExtensionResults.getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CRED_PROPS)
+
+    assertThat(json.get(PublicKeyCredentialControllerUtility.JSON_KEY_AUTH_ATTACHMENT))
+      .isEqualTo("attachment")
+    assertThat(credPropsObject.get(PublicKeyCredentialControllerUtility.JSON_KEY_RK))
+      .isEqualTo(true)
+  }
+
+  @Test
+  fun toCreatePasskeyResponseJson_addOptionalAuthenticatorAttachmentAndRequiredExt_noClientExt() {
+    val json = JSONObject()
+
+    PublicKeyCredentialControllerUtility.addOptionalAuthenticatorAttachmentAndRequiredExtensions(
+      "attachment",
+      false,
+      null,
+      json
+    )
+
+    var clientExtensionResults =
+      json.getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_EXTENSION_RESULTS)
+
+    assertThat(json.get(PublicKeyCredentialControllerUtility.JSON_KEY_AUTH_ATTACHMENT))
+      .isEqualTo("attachment")
+    assertThat(
+        clientExtensionResults.optJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_RK)
+      )
+      .isNull()
+  }
+
+  @Test
+  fun toCreatePasskeyResponseJson_addAuthenticatorAttestationResponse_success() {
+    val json = JSONObject()
+    val byteArrayClientDataJson = byteArrayOf(0x48, 101, 108, 108, 111)
+    val byteArrayAttestationObject = byteArrayOf(0x48, 101, 108, 108, 112)
+    var transportArray = arrayOf("transport")
+
+    PublicKeyCredentialControllerUtility.addAuthenticatorAttestationResponse(
+      byteArrayClientDataJson,
+      byteArrayAttestationObject,
+      transportArray,
+      json
+    )
+
+    var response = json.getJSONObject(PublicKeyCredentialControllerUtility.JSON_KEY_RESPONSE)
+
+    assertThat(response.get(PublicKeyCredentialControllerUtility.JSON_KEY_CLIENT_DATA))
+      .isEqualTo(PublicKeyCredentialControllerUtility.b64Encode(byteArrayClientDataJson))
+    assertThat(response.get(PublicKeyCredentialControllerUtility.JSON_KEY_ATTESTATION_OBJ))
+      .isEqualTo(PublicKeyCredentialControllerUtility.b64Encode(byteArrayAttestationObject))
+    assertThat(response.get(PublicKeyCredentialControllerUtility.JSON_KEY_TRANSPORTS))
+      .isEqualTo(JSONArray(transportArray))
+  }
+
+  @Test
+  fun convertJSON_requiredFields_success() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+    var output = PublicKeyCredentialControllerUtility.convertJSON(json)
+
+    assertThat(output.getUser().getId()).isNotEmpty()
+    assertThat(output.getUser().getName()).isEqualTo("Name of User")
+    assertThat(output.getUser().getDisplayName()).isEqualTo("Display Name of User")
+    assertThat(output.getUser().getIcon()).isEqualTo("icon.png")
+    assertThat(output.getChallenge()).isNotEmpty()
+    assertThat(output.getRp().getId()).isNotEmpty()
+    assertThat(output.getRp().getName()).isEqualTo("Name of RP")
+    assertThat(output.getRp().getIcon()).isEqualTo("rpicon.png")
+    assertThat(output.getParameters().get(0).getAlgorithmIdAsInteger()).isEqualTo(-7)
+    assertThat(output.getParameters().get(0).getTypeAsString()).isEqualTo("public-key")
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingRpId() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingRpName() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingRp() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingPubKeyCredParams() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingChallenge() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingUser() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingUserId() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"name\": \"Name of User\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingUserName() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"displayName\": \"Display Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
+
+  @Test
+  fun convertJSON_requiredFields_failOnMissingUserDisplayName() {
+    var json =
+      JSONObject(
+        "{" +
+          "\"rp\": {" +
+          "\"id\": \"rpidvalue\"," +
+          "\"name\": \"Name of RP\"," +
+          "\"icon\": \"rpicon.png\"" +
+          "}," +
+          "\"pubKeyCredParams\": [{" +
+          "\"alg\": -7," +
+          "\"type\": \"public-key\"" +
+          "}]," +
+          "\"challenge\": \"dGVzdA==\"," +
+          "\"user\": {" +
+          "\"id\": \"idvalue\"," +
+          "\"name\": \"Name of User\"," +
+          "\"icon\": \"icon.png\"" +
+          "}" +
+          "}"
+      )
+
+    assertThrows<JSONException> { PublicKeyCredentialControllerUtility.convertJSON(json) }
+  }
 }
diff --git a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/PublicKeyCredentialControllerUtility.kt b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/PublicKeyCredentialControllerUtility.kt
index 836f040..4b38772 100644
--- a/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/PublicKeyCredentialControllerUtility.kt
+++ b/credentials/credentials-play-services-auth/src/main/java/androidx/credentials/playservices/controllers/CreatePublicKeyCredential/PublicKeyCredentialControllerUtility.kt
@@ -65,612 +65,587 @@
 import org.json.JSONException
 import org.json.JSONObject
 
-/**
- * A utility class to handle logic for the begin sign in controller.
- */
+/** A utility class to handle logic for the begin sign in controller. */
 internal class PublicKeyCredentialControllerUtility {
 
-    companion object {
+  companion object {
 
-        internal val JSON_KEY_CLIENT_DATA = "clientDataJSON"
-        internal val JSON_KEY_ATTESTATION_OBJ = "attestationObject"
-        internal val JSON_KEY_AUTH_DATA = "authenticatorData"
-        internal val JSON_KEY_SIGNATURE = "signature"
-        internal val JSON_KEY_USER_HANDLE = "userHandle"
-        internal val JSON_KEY_RESPONSE = "response"
-        internal val JSON_KEY_ID = "id"
-        internal val JSON_KEY_RAW_ID = "rawId"
-        internal val JSON_KEY_TYPE = "type"
-        internal val JSON_KEY_RPID = "rpId"
-        internal val JSON_KEY_CHALLENGE = "challenge"
-        internal val JSON_KEY_APPID = "appid"
-        internal val JSON_KEY_THIRD_PARTY_PAYMENT = "thirdPartyPayment"
-        internal val JSON_KEY_AUTH_SELECTION = "authenticatorSelection"
-        internal val JSON_KEY_REQUIRE_RES_KEY = "requireResidentKey"
-        internal val JSON_KEY_RES_KEY = "residentKey"
-        internal val JSON_KEY_AUTH_ATTACHMENT = "authenticatorAttachment"
-        internal val JSON_KEY_TIMEOUT = "timeout"
-        internal val JSON_KEY_EXCLUDE_CREDENTIALS = "excludeCredentials"
-        internal val JSON_KEY_TRANSPORTS = "transports"
-        internal val JSON_KEY_RP = "rp"
-        internal val JSON_KEY_NAME = "name"
-        internal val JSON_KEY_ICON = "icon"
-        internal val JSON_KEY_ALG = "alg"
-        internal val JSON_KEY_USER = "user"
-        internal val JSON_KEY_DISPLAY_NAME = "displayName"
-        internal val JSON_KEY_USER_VERIFICATION_METHOD = "userVerificationMethod"
-        internal val JSON_KEY_KEY_PROTECTION_TYPE = "keyProtectionType"
-        internal val JSON_KEY_MATCHER_PROTECTION_TYPE = "matcherProtectionType"
-        internal val JSON_KEY_EXTENSTIONS = "extensions"
-        internal val JSON_KEY_ATTESTATION = "attestation"
-        internal val JSON_KEY_PUB_KEY_CRED_PARAMS = "pubKeyCredParams"
-        internal val JSON_KEY_CLIENT_EXTENSION_RESULTS = "clientExtensionResults"
-        internal val JSON_KEY_RK = "rk"
-        internal val JSON_KEY_CRED_PROPS = "credProps"
+    internal val JSON_KEY_CLIENT_DATA = "clientDataJSON"
+    internal val JSON_KEY_ATTESTATION_OBJ = "attestationObject"
+    internal val JSON_KEY_AUTH_DATA = "authenticatorData"
+    internal val JSON_KEY_SIGNATURE = "signature"
+    internal val JSON_KEY_USER_HANDLE = "userHandle"
+    internal val JSON_KEY_RESPONSE = "response"
+    internal val JSON_KEY_ID = "id"
+    internal val JSON_KEY_RAW_ID = "rawId"
+    internal val JSON_KEY_TYPE = "type"
+    internal val JSON_KEY_RPID = "rpId"
+    internal val JSON_KEY_CHALLENGE = "challenge"
+    internal val JSON_KEY_APPID = "appid"
+    internal val JSON_KEY_THIRD_PARTY_PAYMENT = "thirdPartyPayment"
+    internal val JSON_KEY_AUTH_SELECTION = "authenticatorSelection"
+    internal val JSON_KEY_REQUIRE_RES_KEY = "requireResidentKey"
+    internal val JSON_KEY_RES_KEY = "residentKey"
+    internal val JSON_KEY_AUTH_ATTACHMENT = "authenticatorAttachment"
+    internal val JSON_KEY_TIMEOUT = "timeout"
+    internal val JSON_KEY_EXCLUDE_CREDENTIALS = "excludeCredentials"
+    internal val JSON_KEY_TRANSPORTS = "transports"
+    internal val JSON_KEY_RP = "rp"
+    internal val JSON_KEY_NAME = "name"
+    internal val JSON_KEY_ICON = "icon"
+    internal val JSON_KEY_ALG = "alg"
+    internal val JSON_KEY_USER = "user"
+    internal val JSON_KEY_DISPLAY_NAME = "displayName"
+    internal val JSON_KEY_USER_VERIFICATION_METHOD = "userVerificationMethod"
+    internal val JSON_KEY_KEY_PROTECTION_TYPE = "keyProtectionType"
+    internal val JSON_KEY_MATCHER_PROTECTION_TYPE = "matcherProtectionType"
+    internal val JSON_KEY_EXTENSTIONS = "extensions"
+    internal val JSON_KEY_ATTESTATION = "attestation"
+    internal val JSON_KEY_PUB_KEY_CRED_PARAMS = "pubKeyCredParams"
+    internal val JSON_KEY_CLIENT_EXTENSION_RESULTS = "clientExtensionResults"
+    internal val JSON_KEY_RK = "rk"
+    internal val JSON_KEY_CRED_PROPS = "credProps"
 
-        /**
-         * This function converts a request json to a PublicKeyCredentialCreationOptions, where
-         * there should be a direct mapping from the input string to this data type. See
-         * [here](https://w3c.github.io/webauthn/#sctn-parseCreationOptionsFromJSON) for more
-         * details. This occurs in the registration, or create, flow for public key credentials.
-         *
-         * @param request a credential manager data type that holds a requestJson that is expected
-         * to parse completely into PublicKeyCredentialCreationOptions
-         * @throws JSONException If required data is not present in the requestJson
-         */
-        @JvmStatic
-        fun convert(request: CreatePublicKeyCredentialRequest): PublicKeyCredentialCreationOptions {
-            val requestJson = request.requestJson
-            val json = JSONObject(requestJson)
-            val builder = PublicKeyCredentialCreationOptions.Builder()
-
-            parseRequiredChallengeAndUser(json, builder)
-            parseRequiredRpAndParams(json, builder)
-
-            parseOptionalWithRequiredDefaultsAttestationAndExcludeCredentials(json, builder)
-
-            parseOptionalTimeout(json, builder)
-            parseOptionalAuthenticatorSelection(json, builder)
-            parseOptionalExtensions(json, builder)
-
-            return builder.build()
-        }
-
-        /**
-         * Converts the response from fido back to json so it can be passed into CredentialManager.
-         */
-        fun toCreatePasskeyResponseJson(cred: PublicKeyCredential): String {
-            val json = JSONObject()
-            val authenticatorResponse = cred.response
-            if (authenticatorResponse is AuthenticatorAttestationResponse) {
-                val responseJson = JSONObject()
-                responseJson.put(
-                    JSON_KEY_CLIENT_DATA,
-                    b64Encode(authenticatorResponse.clientDataJSON))
-                responseJson.put(
-                    JSON_KEY_ATTESTATION_OBJ,
-                    b64Encode(authenticatorResponse.attestationObject))
-                val transportArray = convertToProperNamingScheme(authenticatorResponse)
-                val transports = JSONArray(transportArray)
-
-                responseJson.put(JSON_KEY_TRANSPORTS, transports)
-                json.put(JSON_KEY_RESPONSE, responseJson)
-            } else {
-                Log.e(TAG, "Authenticator response expected registration response but " +
-                    "got: ${authenticatorResponse.javaClass.name}")
-            }
-
-            addOptionalAuthenticatorAttachmentAndRequiredExtensions(
-                cred.authenticatorAttachment,
-                cred.clientExtensionResults != null,
-                cred.clientExtensionResults?.credProps?.isDiscoverableCredential,
-                json
-            )
-
-            json.put(JSON_KEY_ID, cred.id)
-            json.put(JSON_KEY_RAW_ID, b64Encode(cred.rawId))
-            json.put(JSON_KEY_TYPE, cred.type)
-            return json.toString()
-        }
-
-        private fun convertToProperNamingScheme(
-            authenticatorResponse: AuthenticatorAttestationResponse
-        ): Array<out String> {
-            val transportArray = authenticatorResponse.transports
-            var ix = 0
-            for (transport in transportArray) {
-                if (transport == "cable") {
-                    transportArray[ix] = "hybrid"
-                }
-                ix += 1
-            }
-            return transportArray
-        }
-
-        // This can be shared by both get and create flow response parsers
-        private fun addOptionalAuthenticatorAttachmentAndRequiredExtensions(
-            authenticatorAttachment: String?,
-            hasClientExtensionResults: Boolean,
-            isDiscoverableCredential: Boolean?,
-            json: JSONObject
-        ) {
-
-            if (authenticatorAttachment != null) {
-                json.put(JSON_KEY_AUTH_ATTACHMENT, authenticatorAttachment)
-            }
-
-            val clientExtensionsJson = JSONObject()
-
-            if (hasClientExtensionResults) {
-                try {
-                    if (isDiscoverableCredential != null) {
-                        val credPropsObject = JSONObject()
-                        credPropsObject.put(JSON_KEY_RK, isDiscoverableCredential)
-                        clientExtensionsJson.put(JSON_KEY_CRED_PROPS, credPropsObject)
-                    }
-                } catch (t: Throwable) {
-                    Log.e(TAG, "ClientExtensionResults faced possible implementation " +
-                        "inconsistency in uvmEntries - $t")
-                }
-            }
-            json.put(JSON_KEY_CLIENT_EXTENSION_RESULTS, clientExtensionsJson)
-        }
-
-        fun toAssertPasskeyResponse(cred: SignInCredential): String {
-            var json = JSONObject()
-            val publicKeyCred = cred.publicKeyCredential
-
-            when (val authenticatorResponse = publicKeyCred?.response!!) {
-                is AuthenticatorErrorResponse -> {
-                    throw beginSignInPublicKeyCredentialResponseContainsError(
-                        authenticatorResponse.errorCode,
-                        authenticatorResponse.errorMessage)
-                }
-                is AuthenticatorAssertionResponse -> {
-                    beginSignInAssertionResponse(
-                        authenticatorResponse.clientDataJSON,
-                        authenticatorResponse.authenticatorData,
-                        authenticatorResponse.signature,
-                        authenticatorResponse.userHandle,
-                        json,
-                        publicKeyCred.id,
-                        publicKeyCred.rawId,
-                        publicKeyCred.type,
-                        publicKeyCred.authenticatorAttachment,
-                        publicKeyCred.clientExtensionResults != null,
-                        publicKeyCred.clientExtensionResults?.credProps?.isDiscoverableCredential
-                    )
-                }
-                else -> {
-                Log.e(
-                    TAG,
-                    "AuthenticatorResponse expected assertion response but " +
-                        "got: ${authenticatorResponse.javaClass.name}")
-                }
-            }
-            return json.toString()
-        }
-
-        internal fun beginSignInAssertionResponse(
-            clientDataJSON: ByteArray,
-            authenticatorData: ByteArray,
-            signature: ByteArray,
-            userHandle: ByteArray?,
-            json: JSONObject,
-            publicKeyCredId: String,
-            publicKeyCredRawId: ByteArray,
-            publicKeyCredType: String,
-            authenticatorAttachment: String?,
-            hasClientExtensionResults: Boolean,
-            isDiscoverableCredential: Boolean?
-        ) {
-            val responseJson = JSONObject()
-            responseJson.put(
-                JSON_KEY_CLIENT_DATA,
-                b64Encode(clientDataJSON)
-            )
-            responseJson.put(
-                JSON_KEY_AUTH_DATA,
-                b64Encode(authenticatorData)
-            )
-            responseJson.put(
-                JSON_KEY_SIGNATURE,
-                b64Encode(signature)
-            )
-            userHandle?.let {
-                responseJson.put(
-                    JSON_KEY_USER_HANDLE, b64Encode(userHandle)
-                )
-            }
-            json.put(JSON_KEY_RESPONSE, responseJson)
-            json.put(JSON_KEY_ID, publicKeyCredId)
-            json.put(JSON_KEY_RAW_ID, b64Encode(publicKeyCredRawId))
-            json.put(JSON_KEY_TYPE, publicKeyCredType)
-            addOptionalAuthenticatorAttachmentAndRequiredExtensions(
-                authenticatorAttachment,
-                hasClientExtensionResults,
-                isDiscoverableCredential,
-                json
-            )
-        }
-
-        /**
-         * Converts from the Credential Manager public key credential option to the Play Auth
-         * Module passkey json option.
-         *
-         * @return the current auth module passkey request
-         */
-        fun convertToPlayAuthPasskeyJsonRequest(option: GetPublicKeyCredentialOption):
-            BeginSignInRequest.PasskeyJsonRequestOptions {
-            return BeginSignInRequest.PasskeyJsonRequestOptions.Builder()
-                .setSupported(true)
-                .setRequestJson(option.requestJson)
-                .build()
-        }
-
-        /**
-         * Converts from the Credential Manager public key credential option to the Play Auth
-         * Module passkey option, used in a backwards compatible flow for the auth dependency.
-         *
-         * @return the backwards compatible auth module passkey request
-         */
-        @Deprecated("Upgrade GMS version so 'convertToPlayAuthPasskeyJsonRequest' is used")
-        @Suppress("deprecation")
-        fun convertToPlayAuthPasskeyRequest(option: GetPublicKeyCredentialOption):
-            BeginSignInRequest.PasskeysRequestOptions {
-            val json = JSONObject(option.requestJson)
-            val rpId = json.optString(JSON_KEY_RPID, "")
-            if (rpId.isEmpty()) {
-                throw JSONException(
-                    "GetPublicKeyCredentialOption - rpId not specified in the " +
-                    "request or is unexpectedly empty")
-            }
-            val challenge = getChallenge(json)
-            return BeginSignInRequest.PasskeysRequestOptions.Builder()
-                .setSupported(true)
-                .setRpId(rpId)
-                .setChallenge(challenge)
-                .build()
-        }
-
-        private fun getChallenge(json: JSONObject): ByteArray {
-            val challengeB64 = json.optString(JSON_KEY_CHALLENGE, "")
-            if (challengeB64.isEmpty()) {
-                throw JSONException(
-                    "Challenge not found in request or is unexpectedly empty")
-            }
-            return b64Decode(challengeB64)
-        }
-
-        /**
-         * Indicates if an error was propagated from the underlying Fido API.
-         *
-         * @param cred the public key credential response object from fido
-         *
-         * @return an exception if it exists, else null indicating no exception
-         */
-        fun publicKeyCredentialResponseContainsError(
-            cred: PublicKeyCredential
-        ): CreateCredentialException? {
-            val authenticatorResponse: AuthenticatorResponse = cred.response
-            if (authenticatorResponse is AuthenticatorErrorResponse) {
-                val code = authenticatorResponse.errorCode
-                var exceptionError = orderedErrorCodeToExceptions[code]
-                var msg = authenticatorResponse.errorMessage
-                val exception: CreateCredentialException
-                if (exceptionError == null) {
-                    exception = CreatePublicKeyCredentialDomException(
-                        UnknownError(), "unknown fido gms exception - $msg"
-                    )
-                } else {
-                    // This fix is quite fragile because it relies on that the fido module
-                    // does not change its error message, but is the only viable solution
-                    // because there's no other differentiator.
-                    if (code == ErrorCode.CONSTRAINT_ERR &&
-                        msg?.contains("Unable to get sync account") == true
-                    ) {
-                        exception = CreateCredentialCancellationException(
-                            "Passkey registration was cancelled by the user.")
-                    } else {
-                        exception = CreatePublicKeyCredentialDomException(exceptionError, msg)
-                    }
-                }
-                return exception
-            }
-            return null
-        }
-
-        // Helper method for the begin sign in flow to identify an authenticator error response
-        internal fun beginSignInPublicKeyCredentialResponseContainsError(
-            code: ErrorCode,
-            msg: String?,
-        ): GetCredentialException {
-            var exceptionError = orderedErrorCodeToExceptions[code]
-            val exception: GetCredentialException
-            if (exceptionError == null) {
-                exception = GetPublicKeyCredentialDomException(
-                    UnknownError(), "unknown fido gms exception - $msg"
-                )
-            } else {
-                // This fix is quite fragile because it relies on that the fido module
-                // does not change its error message, but is the only viable solution
-                // because there's no other differentiator.
-                if (code == ErrorCode.CONSTRAINT_ERR &&
-                    msg?.contains("Unable to get sync account") == true
-                ) {
-                    exception = GetCredentialCancellationException(
-                        "Passkey retrieval was cancelled by the user.")
-                } else {
-                    exception = GetPublicKeyCredentialDomException(exceptionError, msg)
-                }
-            }
-            return exception
-        }
-
-        internal fun parseOptionalExtensions(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            if (json.has(JSON_KEY_EXTENSTIONS)) {
-                val extensions = json.getJSONObject(JSON_KEY_EXTENSTIONS)
-                val extensionBuilder = AuthenticationExtensions.Builder()
-                val appIdExtension = extensions.optString(JSON_KEY_APPID, "")
-                if (appIdExtension.isNotEmpty()) {
-                    extensionBuilder.setFido2Extension(FidoAppIdExtension(appIdExtension))
-                }
-                val thirdPartyPaymentExtension = extensions.optBoolean(
-                    JSON_KEY_THIRD_PARTY_PAYMENT, false)
-                if (thirdPartyPaymentExtension) {
-                    extensionBuilder.setGoogleThirdPartyPaymentExtension(
-                        GoogleThirdPartyPaymentExtension(true)
-                    )
-                }
-                val uvmStatus = extensions.optBoolean("uvm", false)
-                if (uvmStatus) {
-                    extensionBuilder.setUserVerificationMethodExtension(
-                        UserVerificationMethodExtension(true)
-                    )
-                }
-                builder.setAuthenticationExtensions(extensionBuilder.build())
-            }
-        }
-
-        internal fun parseOptionalAuthenticatorSelection(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            if (json.has(JSON_KEY_AUTH_SELECTION)) {
-                val authenticatorSelection = json.getJSONObject(
-                    JSON_KEY_AUTH_SELECTION
-                )
-                val authSelectionBuilder = AuthenticatorSelectionCriteria.Builder()
-                val requireResidentKey = authenticatorSelection.optBoolean(
-                    JSON_KEY_REQUIRE_RES_KEY, false)
-                val residentKey = authenticatorSelection
-                    .optString(JSON_KEY_RES_KEY, "")
-                var residentKeyRequirement: ResidentKeyRequirement? = null
-                if (residentKey.isNotEmpty()) {
-                    residentKeyRequirement = ResidentKeyRequirement.fromString(residentKey)
-                }
-                authSelectionBuilder
-                    .setRequireResidentKey(requireResidentKey)
-                    .setResidentKeyRequirement(residentKeyRequirement)
-                val authenticatorAttachmentString = authenticatorSelection
-                    .optString(JSON_KEY_AUTH_ATTACHMENT, "")
-                if (authenticatorAttachmentString.isNotEmpty()) {
-                    authSelectionBuilder.setAttachment(
-                        Attachment.fromString(
-                            authenticatorAttachmentString
-                        )
-                    )
-                }
-                builder.setAuthenticatorSelection(
-                    authSelectionBuilder.build()
-                )
-            }
-        }
-
-        internal fun parseOptionalTimeout(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            if (json.has(JSON_KEY_TIMEOUT)) {
-                val timeout = json.getLong(JSON_KEY_TIMEOUT).toDouble() / 1000
-                builder.setTimeoutSeconds(timeout)
-            }
-        }
-
-        internal fun parseOptionalWithRequiredDefaultsAttestationAndExcludeCredentials(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            val excludeCredentialsList: MutableList<PublicKeyCredentialDescriptor> = ArrayList()
-            if (json.has(JSON_KEY_EXCLUDE_CREDENTIALS)) {
-                val pubKeyDescriptorJSONs = json.getJSONArray(JSON_KEY_EXCLUDE_CREDENTIALS)
-                for (i in 0 until pubKeyDescriptorJSONs.length()) {
-                    val descriptorJSON = pubKeyDescriptorJSONs.getJSONObject(i)
-                    val descriptorId = b64Decode(descriptorJSON.getString(JSON_KEY_ID))
-                    val descriptorType = descriptorJSON.getString(JSON_KEY_TYPE)
-                    if (descriptorType.isEmpty()) {
-                        throw JSONException(
-                            "PublicKeyCredentialDescriptor type value is not " +
-                            "found or unexpectedly empty")
-                    }
-                    if (descriptorId.isEmpty()) {
-                        throw JSONException(
-                            "PublicKeyCredentialDescriptor id value is not " +
-                            "found or unexpectedly empty")
-                    }
-                    var transports: MutableList<Transport>? = null
-                    if (descriptorJSON.has(JSON_KEY_TRANSPORTS)) {
-                        transports = ArrayList()
-                        val descriptorTransports = descriptorJSON.getJSONArray(
-                            JSON_KEY_TRANSPORTS
-                        )
-                        for (j in 0 until descriptorTransports.length()) {
-                            try {
-                                transports.add(Transport.fromString(
-                                    descriptorTransports.getString(j)))
-                            } catch (e: Transport.UnsupportedTransportException) {
-                                throw CreatePublicKeyCredentialDomException(EncodingError(),
-                                    e.message)
-                            }
-                        }
-                    }
-                    excludeCredentialsList.add(
-                        PublicKeyCredentialDescriptor(
-                            descriptorType,
-                            descriptorId, transports
-                        )
-                    )
-                }
-            }
-            builder.setExcludeList(excludeCredentialsList)
-
-            var attestationString = json.optString(JSON_KEY_ATTESTATION, "none")
-            if (attestationString.isEmpty()) {
-                attestationString = "none"
-            }
-            builder.setAttestationConveyancePreference(
-                AttestationConveyancePreference.fromString(attestationString)
-            )
-        }
-
-        internal fun parseRequiredRpAndParams(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            val rp = json.getJSONObject(JSON_KEY_RP)
-            val rpId = rp.getString(JSON_KEY_ID)
-            val rpName = rp.optString(JSON_KEY_NAME, "")
-            var rpIcon: String? = rp.optString(JSON_KEY_ICON, "")
-            if (rpIcon!!.isEmpty()) {
-                rpIcon = null
-            }
-            if (rpName.isEmpty()) {
-                throw JSONException(
-                    "PublicKeyCredentialCreationOptions rp name is " +
-                    "missing or unexpectedly empty")
-            }
-            if (rpId.isEmpty()) {
-                throw JSONException(
-                    "PublicKeyCredentialCreationOptions rp ID is " +
-                    "missing or unexpectedly empty")
-            }
-            builder.setRp(
-                PublicKeyCredentialRpEntity(
-                    rpId,
-                    rpName,
-                    rpIcon
-                )
-            )
-
-            val pubKeyCredParams = json.getJSONArray(JSON_KEY_PUB_KEY_CRED_PARAMS)
-            val paramsList: MutableList<PublicKeyCredentialParameters> = ArrayList()
-            for (i in 0 until pubKeyCredParams.length()) {
-                val param = pubKeyCredParams.getJSONObject(i)
-                val paramAlg = param.getLong(JSON_KEY_ALG).toInt()
-                val typeParam = param.optString(JSON_KEY_TYPE, "")
-                if (typeParam.isEmpty()) {
-                    throw JSONException(
-                        "PublicKeyCredentialCreationOptions " +
-                        "PublicKeyCredentialParameter type missing or unexpectedly empty")
-                }
-                if (checkAlgSupported(paramAlg)) {
-                    paramsList.add(
-                        PublicKeyCredentialParameters(typeParam, paramAlg))
-                }
-            }
-            builder.setParameters(paramsList)
-        }
-
-        internal fun parseRequiredChallengeAndUser(
-            json: JSONObject,
-            builder: PublicKeyCredentialCreationOptions.Builder
-        ) {
-            val challenge = getChallenge(json)
-            builder.setChallenge(challenge)
-
-            val user = json.getJSONObject(JSON_KEY_USER)
-            val userId = b64Decode(user.getString(JSON_KEY_ID))
-            val userName = user.getString(JSON_KEY_NAME)
-            val displayName = user.getString(JSON_KEY_DISPLAY_NAME)
-            val userIcon = user.optString(JSON_KEY_ICON, "")
-            if (displayName.isEmpty()) {
-                throw JSONException(
-                    "PublicKeyCredentialCreationOptions UserEntity missing " +
-                    "displayName or they are unexpectedly empty")
-            }
-            if (userId.isEmpty()) {
-                throw JSONException(
-                    "PublicKeyCredentialCreationOptions UserEntity missing " +
-                    "user id or they are unexpectedly empty")
-            }
-            if (userName.isEmpty()) {
-                throw JSONException(
-                    "PublicKeyCredentialCreationOptions UserEntity missing " +
-                    "user name or they are unexpectedly empty")
-            }
-            builder.setUser(
-                PublicKeyCredentialUserEntity(
-                    userId,
-                    userName,
-                    userIcon,
-                    displayName
-                )
-            )
-        }
-
-        /**
-         * Decode specific to public key credential encoded strings, or any string
-         * that requires NO_PADDING, NO_WRAP and URL_SAFE flags for base 64 decoding.
-         *
-         * @param str the string the decode into a bytearray
-         */
-        fun b64Decode(str: String): ByteArray {
-            return Base64.decode(str, FLAGS)
-        }
-
-        /**
-         * Encode specific to public key credential decoded strings, or any string
-         * that requires NO_PADDING, NO_WRAP and URL_SAFE flags for base 64 encoding.
-         *
-         * @param data the bytearray to encode into a string
-         */
-        fun b64Encode(data: ByteArray): String {
-            return Base64.encodeToString(data, FLAGS)
-        }
-
-        /**
-         * Some values are not supported in the webauthn spec - this catches those values
-         * and returns false - otherwise it returns true.
-         *
-         * @param alg the int code of the cryptography algorithm used in the webauthn flow
-         */
-        fun checkAlgSupported(alg: Int): Boolean {
-            try {
-                COSEAlgorithmIdentifier.fromCoseValue(alg)
-                return true
-            } catch (_: Throwable) {
-            }
-            return false
-        }
-
-        private const val FLAGS = Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING
-        private const val TAG = "PublicKeyUtility"
-        internal val orderedErrorCodeToExceptions = linkedMapOf(ErrorCode.UNKNOWN_ERR to
-            UnknownError(),
-            ErrorCode.ABORT_ERR to AbortError(),
-            ErrorCode.ATTESTATION_NOT_PRIVATE_ERR to NotReadableError(),
-            ErrorCode.CONSTRAINT_ERR to ConstraintError(),
-            ErrorCode.DATA_ERR to DataError(),
-            ErrorCode.INVALID_STATE_ERR to InvalidStateError(),
-            ErrorCode.ENCODING_ERR to EncodingError(),
-            ErrorCode.NETWORK_ERR to NetworkError(),
-            ErrorCode.NOT_ALLOWED_ERR to NotAllowedError(),
-            ErrorCode.NOT_SUPPORTED_ERR to NotSupportedError(),
-            ErrorCode.SECURITY_ERR to SecurityError(),
-            ErrorCode.TIMEOUT_ERR to TimeoutError()
-        )
+    /**
+     * This function converts a request json to a PublicKeyCredentialCreationOptions, where there
+     * should be a direct mapping from the input string to this data type. See
+     * [here](https://w3c.github.io/webauthn/#sctn-parseCreationOptionsFromJSON) for more details.
+     * This occurs in the registration, or create, flow for public key credentials.
+     *
+     * @param request a credential manager data type that holds a requestJson that is expected to
+     *   parse completely into PublicKeyCredentialCreationOptions
+     * @throws JSONException If required data is not present in the requestJson
+     */
+    @JvmStatic
+    fun convert(request: CreatePublicKeyCredentialRequest): PublicKeyCredentialCreationOptions {
+      return convertJSON(JSONObject(request.requestJson))
     }
+
+    internal fun convertJSON(json: JSONObject): PublicKeyCredentialCreationOptions {
+      val builder = PublicKeyCredentialCreationOptions.Builder()
+
+      parseRequiredChallengeAndUser(json, builder)
+      parseRequiredRpAndParams(json, builder)
+
+      parseOptionalWithRequiredDefaultsAttestationAndExcludeCredentials(json, builder)
+
+      parseOptionalTimeout(json, builder)
+      parseOptionalAuthenticatorSelection(json, builder)
+      parseOptionalExtensions(json, builder)
+
+      return builder.build()
+    }
+
+    /** Converts the response from fido back to json so it can be passed into CredentialManager. */
+    fun toCreatePasskeyResponseJson(cred: PublicKeyCredential): String {
+      val json = JSONObject()
+      val authenticatorResponse = cred.response
+      if (authenticatorResponse is AuthenticatorAttestationResponse) {
+        val transportArray = convertToProperNamingScheme(authenticatorResponse)
+        addAuthenticatorAttestationResponse(
+          authenticatorResponse.clientDataJSON,
+          authenticatorResponse.attestationObject,
+          transportArray,
+          json
+        )
+      } else {
+        Log.e(
+          TAG,
+          "Authenticator response expected registration response but " +
+            "got: ${authenticatorResponse.javaClass.name}"
+        )
+      }
+
+      addOptionalAuthenticatorAttachmentAndRequiredExtensions(
+        cred.authenticatorAttachment,
+        cred.clientExtensionResults != null,
+        cred.clientExtensionResults?.credProps?.isDiscoverableCredential,
+        json
+      )
+
+      json.put(JSON_KEY_ID, cred.id)
+      json.put(JSON_KEY_RAW_ID, b64Encode(cred.rawId))
+      json.put(JSON_KEY_TYPE, cred.type)
+      return json.toString()
+    }
+
+    internal fun addAuthenticatorAttestationResponse(
+      clientDataJSON: ByteArray,
+      attestationObject: ByteArray,
+      transportArray: Array<out String>,
+      json: JSONObject
+    ) {
+      val responseJson = JSONObject()
+      responseJson.put(JSON_KEY_CLIENT_DATA, b64Encode(clientDataJSON))
+      responseJson.put(JSON_KEY_ATTESTATION_OBJ, b64Encode(attestationObject))
+      responseJson.put(JSON_KEY_TRANSPORTS, JSONArray(transportArray))
+      json.put(JSON_KEY_RESPONSE, responseJson)
+    }
+
+    private fun convertToProperNamingScheme(
+      authenticatorResponse: AuthenticatorAttestationResponse
+    ): Array<out String> {
+      val transportArray = authenticatorResponse.transports
+      var ix = 0
+      for (transport in transportArray) {
+        if (transport == "cable") {
+          transportArray[ix] = "hybrid"
+        }
+        ix += 1
+      }
+      return transportArray
+    }
+
+    // This can be shared by both get and create flow response parsers
+    internal fun addOptionalAuthenticatorAttachmentAndRequiredExtensions(
+      authenticatorAttachment: String?,
+      hasClientExtensionResults: Boolean,
+      isDiscoverableCredential: Boolean?,
+      json: JSONObject
+    ) {
+
+      if (authenticatorAttachment != null) {
+        json.put(JSON_KEY_AUTH_ATTACHMENT, authenticatorAttachment)
+      }
+
+      val clientExtensionsJson = JSONObject()
+
+      if (hasClientExtensionResults) {
+        try {
+          if (isDiscoverableCredential != null) {
+            val credPropsObject = JSONObject()
+            credPropsObject.put(JSON_KEY_RK, isDiscoverableCredential)
+            clientExtensionsJson.put(JSON_KEY_CRED_PROPS, credPropsObject)
+          }
+        } catch (t: Throwable) {
+          Log.e(
+            TAG,
+            "ClientExtensionResults faced possible implementation " +
+              "inconsistency in uvmEntries - $t"
+          )
+        }
+      }
+      json.put(JSON_KEY_CLIENT_EXTENSION_RESULTS, clientExtensionsJson)
+    }
+
+    fun toAssertPasskeyResponse(cred: SignInCredential): String {
+      var json = JSONObject()
+      val publicKeyCred = cred.publicKeyCredential
+
+      when (val authenticatorResponse = publicKeyCred?.response!!) {
+        is AuthenticatorErrorResponse -> {
+          throw beginSignInPublicKeyCredentialResponseContainsError(
+            authenticatorResponse.errorCode,
+            authenticatorResponse.errorMessage
+          )
+        }
+        is AuthenticatorAssertionResponse -> {
+          beginSignInAssertionResponse(
+            authenticatorResponse.clientDataJSON,
+            authenticatorResponse.authenticatorData,
+            authenticatorResponse.signature,
+            authenticatorResponse.userHandle,
+            json,
+            publicKeyCred.id,
+            publicKeyCred.rawId,
+            publicKeyCred.type,
+            publicKeyCred.authenticatorAttachment,
+            publicKeyCred.clientExtensionResults != null,
+            publicKeyCred.clientExtensionResults?.credProps?.isDiscoverableCredential
+          )
+        }
+        else -> {
+          Log.e(
+            TAG,
+            "AuthenticatorResponse expected assertion response but " +
+              "got: ${authenticatorResponse.javaClass.name}"
+          )
+        }
+      }
+      return json.toString()
+    }
+
+    internal fun beginSignInAssertionResponse(
+      clientDataJSON: ByteArray,
+      authenticatorData: ByteArray,
+      signature: ByteArray,
+      userHandle: ByteArray?,
+      json: JSONObject,
+      publicKeyCredId: String,
+      publicKeyCredRawId: ByteArray,
+      publicKeyCredType: String,
+      authenticatorAttachment: String?,
+      hasClientExtensionResults: Boolean,
+      isDiscoverableCredential: Boolean?
+    ) {
+      val responseJson = JSONObject()
+      responseJson.put(JSON_KEY_CLIENT_DATA, b64Encode(clientDataJSON))
+      responseJson.put(JSON_KEY_AUTH_DATA, b64Encode(authenticatorData))
+      responseJson.put(JSON_KEY_SIGNATURE, b64Encode(signature))
+      userHandle?.let { responseJson.put(JSON_KEY_USER_HANDLE, b64Encode(userHandle)) }
+      json.put(JSON_KEY_RESPONSE, responseJson)
+      json.put(JSON_KEY_ID, publicKeyCredId)
+      json.put(JSON_KEY_RAW_ID, b64Encode(publicKeyCredRawId))
+      json.put(JSON_KEY_TYPE, publicKeyCredType)
+      addOptionalAuthenticatorAttachmentAndRequiredExtensions(
+        authenticatorAttachment,
+        hasClientExtensionResults,
+        isDiscoverableCredential,
+        json
+      )
+    }
+
+    /**
+     * Converts from the Credential Manager public key credential option to the Play Auth Module
+     * passkey json option.
+     *
+     * @return the current auth module passkey request
+     */
+    fun convertToPlayAuthPasskeyJsonRequest(
+      option: GetPublicKeyCredentialOption
+    ): BeginSignInRequest.PasskeyJsonRequestOptions {
+      return BeginSignInRequest.PasskeyJsonRequestOptions.Builder()
+        .setSupported(true)
+        .setRequestJson(option.requestJson)
+        .build()
+    }
+
+    /**
+     * Converts from the Credential Manager public key credential option to the Play Auth Module
+     * passkey option, used in a backwards compatible flow for the auth dependency.
+     *
+     * @return the backwards compatible auth module passkey request
+     */
+    @Deprecated("Upgrade GMS version so 'convertToPlayAuthPasskeyJsonRequest' is used")
+    @Suppress("deprecation")
+    fun convertToPlayAuthPasskeyRequest(
+      option: GetPublicKeyCredentialOption
+    ): BeginSignInRequest.PasskeysRequestOptions {
+      val json = JSONObject(option.requestJson)
+      val rpId = json.optString(JSON_KEY_RPID, "")
+      if (rpId.isEmpty()) {
+        throw JSONException(
+          "GetPublicKeyCredentialOption - rpId not specified in the " +
+            "request or is unexpectedly empty"
+        )
+      }
+      val challenge = getChallenge(json)
+      return BeginSignInRequest.PasskeysRequestOptions.Builder()
+        .setSupported(true)
+        .setRpId(rpId)
+        .setChallenge(challenge)
+        .build()
+    }
+
+    private fun getChallenge(json: JSONObject): ByteArray {
+      val challengeB64 = json.optString(JSON_KEY_CHALLENGE, "")
+      if (challengeB64.isEmpty()) {
+        throw JSONException("Challenge not found in request or is unexpectedly empty")
+      }
+      return b64Decode(challengeB64)
+    }
+
+    /**
+     * Indicates if an error was propagated from the underlying Fido API.
+     *
+     * @param cred the public key credential response object from fido
+     * @return an exception if it exists, else null indicating no exception
+     */
+    fun publicKeyCredentialResponseContainsError(
+      cred: PublicKeyCredential
+    ): CreateCredentialException? {
+      val authenticatorResponse: AuthenticatorResponse = cred.response
+      if (authenticatorResponse is AuthenticatorErrorResponse) {
+        val code = authenticatorResponse.errorCode
+        var exceptionError = orderedErrorCodeToExceptions[code]
+        var msg = authenticatorResponse.errorMessage
+        val exception: CreateCredentialException
+        if (exceptionError == null) {
+          exception =
+            CreatePublicKeyCredentialDomException(
+              UnknownError(),
+              "unknown fido gms exception - $msg"
+            )
+        } else {
+          // This fix is quite fragile because it relies on that the fido module
+          // does not change its error message, but is the only viable solution
+          // because there's no other differentiator.
+          if (
+            code == ErrorCode.CONSTRAINT_ERR && msg?.contains("Unable to get sync account") == true
+          ) {
+            exception =
+              CreateCredentialCancellationException(
+                "Passkey registration was cancelled by the user."
+              )
+          } else {
+            exception = CreatePublicKeyCredentialDomException(exceptionError, msg)
+          }
+        }
+        return exception
+      }
+      return null
+    }
+
+    // Helper method for the begin sign in flow to identify an authenticator error response
+    internal fun beginSignInPublicKeyCredentialResponseContainsError(
+      code: ErrorCode,
+      msg: String?,
+    ): GetCredentialException {
+      var exceptionError = orderedErrorCodeToExceptions[code]
+      val exception: GetCredentialException
+      if (exceptionError == null) {
+        exception =
+          GetPublicKeyCredentialDomException(UnknownError(), "unknown fido gms exception - $msg")
+      } else {
+        // This fix is quite fragile because it relies on that the fido module
+        // does not change its error message, but is the only viable solution
+        // because there's no other differentiator.
+        if (
+          code == ErrorCode.CONSTRAINT_ERR && msg?.contains("Unable to get sync account") == true
+        ) {
+          exception =
+            GetCredentialCancellationException("Passkey retrieval was cancelled by the user.")
+        } else {
+          exception = GetPublicKeyCredentialDomException(exceptionError, msg)
+        }
+      }
+      return exception
+    }
+
+    internal fun parseOptionalExtensions(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      if (json.has(JSON_KEY_EXTENSTIONS)) {
+        val extensions = json.getJSONObject(JSON_KEY_EXTENSTIONS)
+        val extensionBuilder = AuthenticationExtensions.Builder()
+        val appIdExtension = extensions.optString(JSON_KEY_APPID, "")
+        if (appIdExtension.isNotEmpty()) {
+          extensionBuilder.setFido2Extension(FidoAppIdExtension(appIdExtension))
+        }
+        val thirdPartyPaymentExtension = extensions.optBoolean(JSON_KEY_THIRD_PARTY_PAYMENT, false)
+        if (thirdPartyPaymentExtension) {
+          extensionBuilder.setGoogleThirdPartyPaymentExtension(
+            GoogleThirdPartyPaymentExtension(true)
+          )
+        }
+        val uvmStatus = extensions.optBoolean("uvm", false)
+        if (uvmStatus) {
+          extensionBuilder.setUserVerificationMethodExtension(UserVerificationMethodExtension(true))
+        }
+        builder.setAuthenticationExtensions(extensionBuilder.build())
+      }
+    }
+
+    internal fun parseOptionalAuthenticatorSelection(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      if (json.has(JSON_KEY_AUTH_SELECTION)) {
+        val authenticatorSelection = json.getJSONObject(JSON_KEY_AUTH_SELECTION)
+        val authSelectionBuilder = AuthenticatorSelectionCriteria.Builder()
+        val requireResidentKey = authenticatorSelection.optBoolean(JSON_KEY_REQUIRE_RES_KEY, false)
+        val residentKey = authenticatorSelection.optString(JSON_KEY_RES_KEY, "")
+        var residentKeyRequirement: ResidentKeyRequirement? = null
+        if (residentKey.isNotEmpty()) {
+          residentKeyRequirement = ResidentKeyRequirement.fromString(residentKey)
+        }
+        authSelectionBuilder
+          .setRequireResidentKey(requireResidentKey)
+          .setResidentKeyRequirement(residentKeyRequirement)
+        val authenticatorAttachmentString =
+          authenticatorSelection.optString(JSON_KEY_AUTH_ATTACHMENT, "")
+        if (authenticatorAttachmentString.isNotEmpty()) {
+          authSelectionBuilder.setAttachment(Attachment.fromString(authenticatorAttachmentString))
+        }
+        builder.setAuthenticatorSelection(authSelectionBuilder.build())
+      }
+    }
+
+    internal fun parseOptionalTimeout(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      if (json.has(JSON_KEY_TIMEOUT)) {
+        val timeout = json.getLong(JSON_KEY_TIMEOUT).toDouble() / 1000
+        builder.setTimeoutSeconds(timeout)
+      }
+    }
+
+    internal fun parseOptionalWithRequiredDefaultsAttestationAndExcludeCredentials(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      val excludeCredentialsList: MutableList<PublicKeyCredentialDescriptor> = ArrayList()
+      if (json.has(JSON_KEY_EXCLUDE_CREDENTIALS)) {
+        val pubKeyDescriptorJSONs = json.getJSONArray(JSON_KEY_EXCLUDE_CREDENTIALS)
+        for (i in 0 until pubKeyDescriptorJSONs.length()) {
+          val descriptorJSON = pubKeyDescriptorJSONs.getJSONObject(i)
+          val descriptorId = b64Decode(descriptorJSON.getString(JSON_KEY_ID))
+          val descriptorType = descriptorJSON.getString(JSON_KEY_TYPE)
+          if (descriptorType.isEmpty()) {
+            throw JSONException(
+              "PublicKeyCredentialDescriptor type value is not " + "found or unexpectedly empty"
+            )
+          }
+          if (descriptorId.isEmpty()) {
+            throw JSONException(
+              "PublicKeyCredentialDescriptor id value is not " + "found or unexpectedly empty"
+            )
+          }
+          var transports: MutableList<Transport>? = null
+          if (descriptorJSON.has(JSON_KEY_TRANSPORTS)) {
+            transports = ArrayList()
+            val descriptorTransports = descriptorJSON.getJSONArray(JSON_KEY_TRANSPORTS)
+            for (j in 0 until descriptorTransports.length()) {
+              try {
+                transports.add(Transport.fromString(descriptorTransports.getString(j)))
+              } catch (e: Transport.UnsupportedTransportException) {
+                throw CreatePublicKeyCredentialDomException(EncodingError(), e.message)
+              }
+            }
+          }
+          excludeCredentialsList.add(
+            PublicKeyCredentialDescriptor(descriptorType, descriptorId, transports)
+          )
+        }
+      }
+      builder.setExcludeList(excludeCredentialsList)
+
+      var attestationString = json.optString(JSON_KEY_ATTESTATION, "none")
+      if (attestationString.isEmpty()) {
+        attestationString = "none"
+      }
+      builder.setAttestationConveyancePreference(
+        AttestationConveyancePreference.fromString(attestationString)
+      )
+    }
+
+    internal fun parseRequiredRpAndParams(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      val rp = json.getJSONObject(JSON_KEY_RP)
+      val rpId = rp.getString(JSON_KEY_ID)
+      val rpName = rp.optString(JSON_KEY_NAME, "")
+      var rpIcon: String? = rp.optString(JSON_KEY_ICON, "")
+      if (rpIcon!!.isEmpty()) {
+        rpIcon = null
+      }
+      if (rpName.isEmpty()) {
+        throw JSONException(
+          "PublicKeyCredentialCreationOptions rp name is " + "missing or unexpectedly empty"
+        )
+      }
+      if (rpId.isEmpty()) {
+        throw JSONException(
+          "PublicKeyCredentialCreationOptions rp ID is " + "missing or unexpectedly empty"
+        )
+      }
+      builder.setRp(PublicKeyCredentialRpEntity(rpId, rpName, rpIcon))
+
+      val pubKeyCredParams = json.getJSONArray(JSON_KEY_PUB_KEY_CRED_PARAMS)
+      val paramsList: MutableList<PublicKeyCredentialParameters> = ArrayList()
+      for (i in 0 until pubKeyCredParams.length()) {
+        val param = pubKeyCredParams.getJSONObject(i)
+        val paramAlg = param.getLong(JSON_KEY_ALG).toInt()
+        val typeParam = param.optString(JSON_KEY_TYPE, "")
+        if (typeParam.isEmpty()) {
+          throw JSONException(
+            "PublicKeyCredentialCreationOptions " +
+              "PublicKeyCredentialParameter type missing or unexpectedly empty"
+          )
+        }
+        if (checkAlgSupported(paramAlg)) {
+          paramsList.add(PublicKeyCredentialParameters(typeParam, paramAlg))
+        }
+      }
+      builder.setParameters(paramsList)
+    }
+
+    internal fun parseRequiredChallengeAndUser(
+      json: JSONObject,
+      builder: PublicKeyCredentialCreationOptions.Builder
+    ) {
+      val challenge = getChallenge(json)
+      builder.setChallenge(challenge)
+
+      val user = json.getJSONObject(JSON_KEY_USER)
+      val userId = b64Decode(user.getString(JSON_KEY_ID))
+      val userName = user.getString(JSON_KEY_NAME)
+      val displayName = user.getString(JSON_KEY_DISPLAY_NAME)
+      val userIcon = user.optString(JSON_KEY_ICON, "")
+      if (displayName.isEmpty()) {
+        throw JSONException(
+          "PublicKeyCredentialCreationOptions UserEntity missing " +
+            "displayName or they are unexpectedly empty"
+        )
+      }
+      if (userId.isEmpty()) {
+        throw JSONException(
+          "PublicKeyCredentialCreationOptions UserEntity missing " +
+            "user id or they are unexpectedly empty"
+        )
+      }
+      if (userName.isEmpty()) {
+        throw JSONException(
+          "PublicKeyCredentialCreationOptions UserEntity missing " +
+            "user name or they are unexpectedly empty"
+        )
+      }
+      builder.setUser(PublicKeyCredentialUserEntity(userId, userName, userIcon, displayName))
+    }
+
+    /**
+     * Decode specific to public key credential encoded strings, or any string that requires
+     * NO_PADDING, NO_WRAP and URL_SAFE flags for base 64 decoding.
+     *
+     * @param str the string the decode into a bytearray
+     */
+    fun b64Decode(str: String): ByteArray {
+      return Base64.decode(str, FLAGS)
+    }
+
+    /**
+     * Encode specific to public key credential decoded strings, or any string that requires
+     * NO_PADDING, NO_WRAP and URL_SAFE flags for base 64 encoding.
+     *
+     * @param data the bytearray to encode into a string
+     */
+    fun b64Encode(data: ByteArray): String {
+      return Base64.encodeToString(data, FLAGS)
+    }
+
+    /**
+     * Some values are not supported in the webauthn spec - this catches those values and returns
+     * false - otherwise it returns true.
+     *
+     * @param alg the int code of the cryptography algorithm used in the webauthn flow
+     */
+    fun checkAlgSupported(alg: Int): Boolean {
+      try {
+        COSEAlgorithmIdentifier.fromCoseValue(alg)
+        return true
+      } catch (_: Throwable) {}
+      return false
+    }
+
+    private const val FLAGS = Base64.NO_WRAP or Base64.URL_SAFE or Base64.NO_PADDING
+    private const val TAG = "PublicKeyUtility"
+    internal val orderedErrorCodeToExceptions =
+      linkedMapOf(
+        ErrorCode.UNKNOWN_ERR to UnknownError(),
+        ErrorCode.ABORT_ERR to AbortError(),
+        ErrorCode.ATTESTATION_NOT_PRIVATE_ERR to NotReadableError(),
+        ErrorCode.CONSTRAINT_ERR to ConstraintError(),
+        ErrorCode.DATA_ERR to DataError(),
+        ErrorCode.INVALID_STATE_ERR to InvalidStateError(),
+        ErrorCode.ENCODING_ERR to EncodingError(),
+        ErrorCode.NETWORK_ERR to NetworkError(),
+        ErrorCode.NOT_ALLOWED_ERR to NotAllowedError(),
+        ErrorCode.NOT_SUPPORTED_ERR to NotSupportedError(),
+        ErrorCode.SECURITY_ERR to SecurityError(),
+        ErrorCode.TIMEOUT_ERR to TimeoutError()
+      )
+  }
 }
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerJavaTest.java b/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerJavaTest.java
index 5b332ac..b909602 100644
--- a/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerJavaTest.java
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerJavaTest.java
@@ -19,7 +19,6 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.content.Intent;
-import android.os.Build;
 
 import androidx.annotation.RequiresApi;
 import androidx.credentials.CreatePasswordResponse;
@@ -43,10 +42,6 @@
 
     @Test
     public void test_setGetCreateCredentialException() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         Intent intent = new Intent();
 
         CreateCredentialInterruptedException initialException =
@@ -62,10 +57,6 @@
 
     @Test
     public void test_setGetCreateCredentialException_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         assertThat(
                         IntentHandlerConverters.getCreateCredentialException(
                                 BLANK_INTENT))
@@ -74,10 +65,6 @@
 
     @Test
     public void test_credentialException() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         Intent intent = new Intent();
         GetCredentialInterruptedException initialException =
                 new GetCredentialInterruptedException("message");
@@ -92,19 +79,12 @@
 
     @Test
     public void test_credentialException_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         assertThat(IntentHandlerConverters.getGetCredentialException(BLANK_INTENT))
                 .isNull();
     }
 
     @Test
     public void test_beginGetResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
 
         Intent intent = new Intent();
         BeginGetCredentialResponse initialResponse =
@@ -120,20 +100,12 @@
 
     @Test
     public void test_beginGetResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         assertThat(IntentHandlerConverters.getBeginGetResponse(BLANK_INTENT))
                 .isNull();
     }
 
     @Test
     public void test_credentialResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         Intent intent = new Intent();
         PasswordCredential credential = new PasswordCredential("a", "b");
         GetCredentialResponse initialResponse = new GetCredentialResponse(credential);
@@ -148,20 +120,12 @@
 
     @Test
     public void test_credentialResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         assertThat(IntentHandlerConverters.getGetCredentialResponse(BLANK_INTENT))
                 .isNull();
     }
 
     @Test
     public void test_createCredentialCredentialResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         Intent intent = new Intent();
         CreatePasswordResponse initialResponse = new CreatePasswordResponse();
 
@@ -176,10 +140,6 @@
 
     @Test
     public void test_createCredentialCredentialResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return;
-        }
-
         assertThat(
                         IntentHandlerConverters
                                 .getCreateCredentialCredentialResponse(BLANK_INTENT))
diff --git a/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerTest.kt b/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerTest.kt
index c9ed499..7e9e1a2 100644
--- a/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerTest.kt
+++ b/credentials/credentials/src/androidTest/java/androidx/credentials/provider/PendingIntentHandlerTest.kt
@@ -16,7 +16,6 @@
 package androidx.credentials.provider
 
 import android.content.Intent
-import android.os.Build
 import androidx.annotation.RequiresApi
 import androidx.credentials.CreatePasswordResponse
 import androidx.credentials.GetCredentialResponse
@@ -37,10 +36,6 @@
 class PendingIntentHandlerTest {
     @Test
     fun test_createCredentialException() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val initialException = CreateCredentialInterruptedException("message")
 
@@ -53,20 +48,12 @@
 
     @Test()
     fun test_createCredentialException_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         assertThat(intent.getCreateCredentialException()).isNull()
     }
 
     @Test
     fun test_credentialException() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val initialException = GetCredentialInterruptedException("message")
 
@@ -79,20 +66,12 @@
 
     @Test
     fun test_credentialException_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         assertThat(intent.getGetCredentialException()).isNull()
     }
 
     @Test
     fun test_beginGetResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val initialResponse = BeginGetCredentialResponse.Builder().build()
 
@@ -105,20 +84,12 @@
 
     @Test
     fun test_beginGetResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         assertThat(intent.getBeginGetResponse()).isNull()
     }
 
     @Test
     fun test_credentialResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val credential = PasswordCredential("a", "b")
         val initialResponse = GetCredentialResponse(credential)
@@ -132,20 +103,12 @@
 
     @Test
     fun test_credentialResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         assertThat(intent.getGetCredentialResponse()).isNull()
     }
 
     @Test
     fun test_createCredentialCredentialResponse() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val initialResponse = CreatePasswordResponse()
 
@@ -158,10 +121,6 @@
 
     @Test
     fun test_createCredentialCredentialResponse_throwsWhenEmptyIntent() {
-        if (Build.VERSION.SDK_INT >= 34) {
-            return
-        }
-
         val intent = Intent()
         val r = intent.getCreateCredentialCredentialResponse()
         assertThat(r).isNull()
diff --git a/credentials/credentials/src/main/java/androidx/credentials/provider/CallingAppInfo.kt b/credentials/credentials/src/main/java/androidx/credentials/provider/CallingAppInfo.kt
index 38b38c7..daf5878 100644
--- a/credentials/credentials/src/main/java/androidx/credentials/provider/CallingAppInfo.kt
+++ b/credentials/credentials/src/main/java/androidx/credentials/provider/CallingAppInfo.kt
@@ -64,7 +64,7 @@
      * origin will only be returned if the [packageName] and the fingerprints of certificates
      * obtained from the [signingInfo] match with that of an app allowlisted
      * in [privilegedAllowlist]. The format of this JSON must adhere to the following sample.
-     *
+     * ```
      * {"apps": [
      *    {
      *       "type": "android",
@@ -82,6 +82,7 @@
      *       }
      *     }
      * ]}
+     * ```
      *
      * All keys in the JSON must be exactly as stated in the sample above. Note that if the build
      * for a given fingerprint is specified as 'userdebug', that fingerprint will
diff --git a/datastore/datastore-core/build.gradle b/datastore/datastore-core/build.gradle
index 9931fbc..f9faa96 100644
--- a/datastore/datastore-core/build.gradle
+++ b/datastore/datastore-core/build.gradle
@@ -24,6 +24,7 @@
     id("AndroidXPlugin")
     id("com.android.library")
     id("com.google.protobuf")
+    id ("kotlin-parcelize")
 }
 
 def enableNative = KmpPlatformsKt.enableNative(project)
@@ -117,6 +118,7 @@
                 implementation(project(":internal-testutils-truth"))
                 implementation(libs.testRunner)
                 implementation(libs.testCore)
+                implementation("androidx.lifecycle:lifecycle-service:2.6.1")
 
                 // Workaround bug in 1.8.0, was supposed be fixed in RC2/final, but apparently not.
                 implementation(libs.kotlinTestJunit)
diff --git a/datastore/datastore-core/src/androidAndroidTest/AndroidManifest.xml b/datastore/datastore-core/src/androidAndroidTest/AndroidManifest.xml
index 791dfd1..c25da00 100644
--- a/datastore/datastore-core/src/androidAndroidTest/AndroidManifest.xml
+++ b/datastore/datastore-core/src/androidAndroidTest/AndroidManifest.xml
@@ -15,89 +15,16 @@
   -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
-
     <application>
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$SimpleUpdateFileService"
+        <service android:name="androidx.datastore.core.twoWayIpc.TwoWayIpcService"
             android:enabled="true"
             android:exported="false"
-            android:process=":SimpleUpdateFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$SimpleUpdateOkioService"
+            android:process=":TwoWayIpcService" />
+        <service android:name="androidx.datastore.core.twoWayIpc.TwoWayIpcService2"
             android:enabled="true"
             android:exported="false"
-            android:process=":SimpleUpdateOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateWriterFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":ConcurrentReadUpdateWriterFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateWriterOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":ConcurrentReadUpdateWriterOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateReaderFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":ConcurrentReadUpdateReaderFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$ConcurrentReadUpdateReaderOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":ConcurrentReadUpdateReaderOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedUpdateDataFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedUpdateDataOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataWithReadFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedUpdateDataWithReadFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedUpdateDataWithReadOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedUpdateDataWithReadOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$FailedUpdateDataFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":FailedUpdateDataFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$FailedUpdateDataOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":FailedUpdateDataOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$CancelledUpdateDataFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":CancelledUpdateDataFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$CancelledUpdateDataOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":CancelledUpdateDataOkioService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedHandlerUpdateDataFileService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedHandlerUpdateDataFileService" />
-        <service
-            android:name="androidx.datastore.core.MultiProcessDataStoreMultiProcessTest$InterleavedHandlerUpdateDataOkioService"
-            android:enabled="true"
-            android:exported="false"
-            android:process=":InterleavedHandlerUpdateDataOkioService" />
+            android:process=":TwoWayIpcService2" />
     </application>
 
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/DirectTestService.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/DirectTestService.kt
deleted file mode 100644
index cc77d47..0000000
--- a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/DirectTestService.kt
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * 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.datastore.core
-
-import android.app.Service
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.content.ServiceConnection
-import android.content.pm.PackageManager
-import android.os.Bundle
-import android.os.Handler
-import android.os.IBinder
-import android.os.Looper
-import android.os.Message
-import android.os.Messenger
-import android.os.RemoteException
-import androidx.datastore.testing.TestMessageProto.FooProto
-import com.google.common.collect.ImmutableList
-import java.io.Serializable
-import java.util.concurrent.CountDownLatch
-
-private val THROWABLE_BUNDLE_KEY: String = "throwable"
-
-internal class Latch {
-    private var signaled: Boolean = false
-
-    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
-    fun signal() {
-        synchronized(this) {
-            signaled = true
-            (this as java.lang.Object).notify()
-        }
-    }
-
-    @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
-    fun awaitSignal() {
-        synchronized(this) {
-            while (!signaled) {
-                try {
-                    (this as java.lang.Object).wait()
-                } catch (_: InterruptedException) {
-                    // Ignore.
-                }
-            }
-            signaled = false
-        }
-    }
-}
-
-abstract class DirectTestService() : Service() {
-    private val SERVICE_CLASS = this::class.java
-
-    @Suppress("DEPRECATION")
-    private val messenger: Messenger = Messenger(Handler(HandlerCallback()))
-    private val resume: Latch = Latch()
-    private val done: Latch = Latch()
-    private lateinit var testData: Bundle
-    private lateinit var thread: Thread
-    private lateinit var testFailure: Throwable
-
-    // It should be setup in `beforeTest`
-    internal lateinit var store: DataStore<FooProto>
-
-    override fun onBind(intent: Intent): IBinder {
-        return messenger.getBinder()
-    }
-
-    override fun onCreate() {
-        // No-op
-    }
-
-    override fun onDestroy() {
-        // No-op
-    }
-
-    protected abstract fun beforeTest(testData: Bundle)
-
-    protected abstract fun runTest()
-
-    protected fun waitForSignal() {
-        done.signal()
-        resume.awaitSignal()
-    }
-
-    private fun handle(msg: Message) {
-        if (!this::thread.isInitialized) {
-            testData = msg.getData()
-            thread = Thread(Runner())
-            thread.start()
-        } else {
-            resume.signal()
-        }
-        done.awaitSignal()
-        try {
-            val response: Message = Message.obtain()
-            if (this::testFailure.isInitialized) {
-                val data = Bundle()
-                data.putSerializable(THROWABLE_BUNDLE_KEY, testFailure as Serializable)
-                response.setData(data)
-            }
-            msg.replyTo.send(response)
-        } catch (ex: RemoteException) {
-            throw RuntimeException("Test service failed to ack message", ex)
-        }
-    }
-
-    private inner class HandlerCallback : Handler.Callback {
-        override fun handleMessage(msg: Message): Boolean {
-            handle(msg)
-            return true
-        }
-    }
-
-    private inner class Runner : Runnable {
-        override fun run() {
-            try {
-                beforeTest(testData)
-                waitForSignal()
-                runTest()
-            } catch (t: Throwable) {
-                testFailure = t
-            } finally {
-                done.signal()
-            }
-        }
-    }
-}
-
-class BlockingServiceConnection(
-    private val context: Context,
-    private val serviceIntent: Intent
-) :
-    ServiceConnection {
-    private lateinit var isConnected: CountDownLatch
-    private var service: Messenger? = null
-    private var remoteException: Throwable? = null
-
-    override fun onServiceConnected(className: ComponentName, serviceBinder: IBinder) {
-        service = Messenger(serviceBinder)
-        isConnected.countDown()
-    }
-
-    override fun onServiceDisconnected(className: ComponentName) {
-        service = null
-    }
-
-    fun isServiceConnected(): Boolean {
-        return service != null
-    }
-
-    @Suppress("DEPRECATION")
-    fun connect(connectedLatch: CountDownLatch) {
-        isConnected = connectedLatch
-        val serviceExists: Boolean =
-            context.bindService(serviceIntent, this, Context.BIND_AUTO_CREATE)
-
-        if (!serviceExists) {
-            val targetPackage: String = serviceIntent.getComponent()!!.getPackageName()
-            val targetService: String = serviceIntent.getComponent()!!.getClassName()
-
-            try {
-                context.getPackageManager().getPackageInfo(targetPackage, 0)
-            } catch (e: PackageManager.NameNotFoundException) {
-                throw IllegalStateException("Package not installed [$targetPackage]", e)
-            }
-            throw IllegalStateException("Package installed but service not found [$targetService]")
-        }
-    }
-
-    fun signal(msgData: Bundle?, isDelivered: CountDownLatch) {
-        val blockingHandler: BlockingHandler = BlockingHandler(Looper.getMainLooper(), isDelivered)
-        val msg: Message = Message.obtain()
-        msg.replyTo = Messenger(blockingHandler)
-        msgData?.let { msg.setData(it) }
-        try {
-            service?.send(msg)
-        } catch (e: RemoteException) {
-            throw RuntimeException("Remote service failed", e)
-        }
-    }
-
-    fun propagateRemoteExceptionIfPresent() {
-        if (remoteException != null) {
-            throw RuntimeException(remoteException!!)
-        }
-    }
-
-    private inner class BlockingHandler constructor(
-        private val looper: Looper,
-        private val isDelivered: CountDownLatch
-    ) :
-        Handler(looper) {
-
-        @Suppress("DEPRECATION")
-        override fun handleMessage(msg: Message) {
-            remoteException = msg.getData().getSerializable(THROWABLE_BUNDLE_KEY) as Throwable?
-            isDelivered.countDown()
-        }
-    }
-}
-
-internal fun setUpService(
-    context: Context,
-    service: Class<out Service>,
-    testData: Bundle
-): BlockingServiceConnection {
-    val serviceIntent = Intent(context, service)
-    return setUpServicesInternal(context, ImmutableList.of(serviceIntent), testData)[0]
-}
-
-internal fun setUpServices(
-    context: Context,
-    services: List<Class<out Service>>,
-    testData: Bundle
-): List<BlockingServiceConnection> {
-    val serviceIntents: MutableList<Intent> = ArrayList()
-    for (service in services) {
-        serviceIntents.add(Intent(context, service))
-    }
-    return setUpServicesInternal(context, serviceIntents, testData)
-}
-
-private fun setUpServicesInternal(
-    context: Context,
-    serviceIntents: List<Intent>,
-    testData: Bundle
-): List<BlockingServiceConnection> {
-    val connections: MutableList<BlockingServiceConnection> = ArrayList()
-    for (serviceIntent in serviceIntents) {
-        val connection = BlockingServiceConnection(context, serviceIntent)
-        connections.add(connection)
-    }
-    val connectLatch = CountDownLatch(connections.size)
-    for (connection in connections) {
-        connection.connect(connectLatch)
-    }
-    connectLatch.await()
-
-    // Send initial test data
-    val signalLatch = CountDownLatch(connections.size)
-    for (connection in connections) {
-        connection.signal(testData, signalLatch)
-    }
-    signalLatch.await()
-    for (connection in connections) {
-        connection.propagateRemoteExceptionIfPresent()
-    }
-    return connections
-}
-
-internal fun signalService(connection: BlockingServiceConnection) {
-    return signalServices(ImmutableList.of(connection))
-}
-
-internal fun signalServices(connections: List<BlockingServiceConnection>) {
-    val latch = CountDownLatch(connections.size)
-    for (connection in connections) {
-        connection.signal( /* msgData= */null, latch)
-    }
-    latch.await()
-    for (connection in connections) {
-        connection.propagateRemoteExceptionIfPresent()
-    }
-}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/MultiProcessDataStoreMultiProcessTest.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/MultiProcessDataStoreMultiProcessTest.kt
deleted file mode 100644
index 5535964..0000000
--- a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/MultiProcessDataStoreMultiProcessTest.kt
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * 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.datastore.core
-
-import android.content.Context
-import android.os.Bundle
-import androidx.datastore.core.handlers.NoOpCorruptionHandler
-import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
-import androidx.datastore.core.okio.OkioSerializer
-import androidx.datastore.core.okio.OkioStorage
-import androidx.datastore.testing.TestMessageProto.FooProto
-import androidx.test.core.app.ApplicationProvider
-import com.google.common.truth.Truth.assertThat
-import com.google.protobuf.ExtensionRegistryLite
-import java.io.File
-import java.io.FileOutputStream
-import java.io.IOException
-import java.io.OutputStreamWriter
-import kotlin.coroutines.CoroutineContext
-import kotlin.time.Duration.Companion.milliseconds
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.async
-import kotlinx.coroutines.cancelChildren
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.newSingleThreadContext
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
-import okio.FileSystem
-import okio.Path.Companion.toPath
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.rules.TemporaryFolder
-import org.junit.runner.RunWith
-import org.junit.runners.JUnit4
-
-private const val PATH_BUNDLE_KEY: String = "path"
-private const val STORAGE_BUNDLE_KEY: String = "storage"
-private const val STORAGE_FILE: String = "FILE"
-private const val STORAGE_OKIO: String = "OKIO"
-private val PROTO_SERIALIZER: Serializer<FooProto> = ProtoSerializer<FooProto>(
-    FooProto.getDefaultInstance(),
-    ExtensionRegistryLite.getEmptyRegistry()
-)
-private val PROTO_OKIO_SERIALIZER: OkioSerializer<FooProto> = ProtoOkioSerializer<FooProto>(
-    FooProto.getDefaultInstance(),
-    ExtensionRegistryLite.getEmptyRegistry()
-)
-private const val TEST_TEXT: String = "abc"
-internal val WRITE_TEXT: (FooProto) -> FooProto = { f: FooProto ->
-    f.toBuilder().setText(TEST_TEXT).build()
-}
-private val WRITE_BOOLEAN: (FooProto) -> FooProto = { f: FooProto ->
-    f.toBuilder().setBoolean(true).build()
-}
-private val INCREMENT_INTEGER: (FooProto) -> FooProto = { f: FooProto ->
-    f.toBuilder().setInteger(f.integer + 1).build()
-}
-
-private val DEFAULT_FOO: FooProto = FooProto.getDefaultInstance()
-private val FOO_WITH_TEXT: FooProto =
-    FooProto.newBuilder().setText(TEST_TEXT).build()
-private val FOO_WITH_TEXT_AND_BOOLEAN: FooProto =
-    FooProto.newBuilder().setText(TEST_TEXT).setBoolean(true).build()
-
-private val FILESYSTEM = FileSystem.SYSTEM
-
-@ExperimentalCoroutinesApi
-private fun createDataStore(
-    bundle: Bundle,
-    scope: TestScope,
-    corruptionHandler: CorruptionHandler<FooProto> = NoOpCorruptionHandler<FooProto>(),
-    context: CoroutineContext = UnconfinedTestDispatcher()
-): DataStore<FooProto> {
-    val file = File(bundle.getString(PATH_BUNDLE_KEY)!!)
-    val produceFile = { file }
-    val variant = StorageVariant.valueOf(bundle.getString(STORAGE_BUNDLE_KEY)!!)
-    val storage = if (variant == StorageVariant.FILE) {
-        FileStorage(
-            PROTO_SERIALIZER,
-            { MultiProcessCoordinator(context, it) },
-            produceFile
-        )
-    } else {
-        OkioStorage(
-            FILESYSTEM,
-            PROTO_OKIO_SERIALIZER,
-            { _, _ -> MultiProcessCoordinator(context, file) },
-            { file.absolutePath.toPath() }
-        )
-    }
-    return DataStoreImpl(
-        storage = storage,
-        scope = scope,
-        corruptionHandler = corruptionHandler
-    )
-}
-
-internal enum class StorageVariant(val storage: String) {
-    FILE(STORAGE_FILE), OKIO(STORAGE_OKIO)
-}
-
-@OptIn(DelicateCoroutinesApi::class)
-@ExperimentalCoroutinesApi
-@RunWith(JUnit4::class)
-class MultiProcessDataStoreMultiProcessTest {
-    @get:Rule
-    val tempFolder = TemporaryFolder()
-
-    private lateinit var testFile: File
-    private lateinit var dataStoreContext: CoroutineContext
-    private lateinit var dataStoreScope: TestScope
-
-    private val mainContext: Context = ApplicationProvider.getApplicationContext()
-
-    private fun createDataStoreBundle(path: String, variant: StorageVariant): Bundle {
-        val data = Bundle()
-        data.putString(PATH_BUNDLE_KEY, path)
-        data.putString(STORAGE_BUNDLE_KEY, variant.storage)
-        return data
-    }
-
-    @Before
-    fun setUp() {
-        testFile = tempFolder.newFile()
-        dataStoreContext = UnconfinedTestDispatcher()
-        dataStoreScope = TestScope(dataStoreContext + Job())
-    }
-
-    @Test
-    fun testSimpleUpdateData_file() = testSimpleUpdateData_runner(StorageVariant.FILE)
-
-    @Test
-    fun testSimpleUpdateData_okio() = testSimpleUpdateData_runner(StorageVariant.OKIO)
-
-    private fun testSimpleUpdateData_runner(variant: StorageVariant) =
-        runTest(timeout = 10000.milliseconds) {
-            val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-            val dataStore: DataStore<FooProto> =
-                createDataStore(testData, dataStoreScope, context = dataStoreContext)
-            val serviceClasses = mapOf(
-                StorageVariant.FILE to SimpleUpdateFileService::class,
-                StorageVariant.OKIO to SimpleUpdateOkioService::class
-            )
-            val connection: BlockingServiceConnection =
-                setUpService(mainContext, serviceClasses[variant]!!.java, testData)
-
-            assertThat(dataStore.data.first()).isEqualTo(DEFAULT_FOO)
-
-            // Other proc commits TEST_TEXT update
-            signalService(connection)
-
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-        }
-
-    open class SimpleUpdateFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                WRITE_TEXT(it)
-            }
-        }
-    }
-
-    class SimpleUpdateOkioService : SimpleUpdateFileService()
-
-    @Test
-    fun testConcurrentReadUpdate_file() = testConcurrentReadUpdate_runner(StorageVariant.FILE)
-
-    @Test
-    fun testConcurrentReadUpdate_okio() = testConcurrentReadUpdate_runner(StorageVariant.OKIO)
-
-    private fun testConcurrentReadUpdate_runner(variant: StorageVariant) =
-        runTest(timeout = 10000.milliseconds) {
-            val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-            val dataStore: DataStore<FooProto> =
-                createDataStore(testData, dataStoreScope, context = dataStoreContext)
-            val writerServiceClasses = mapOf(
-                StorageVariant.FILE to ConcurrentReadUpdateWriterFileService::class,
-                StorageVariant.OKIO to ConcurrentReadUpdateWriterOkioService::class
-            )
-            val writerConnection: BlockingServiceConnection =
-                setUpService(mainContext, writerServiceClasses[variant]!!.java, testData)
-
-            // Start with TEST_TEXT
-            dataStore.updateData { f: FooProto -> WRITE_TEXT(f) }
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-
-            // Writer process starts (but does not yet commit) "true"
-            signalService(writerConnection)
-
-            // We can continue reading datastore while the writer process is mid-write
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-
-            val readerServiceClasses = mapOf(
-                StorageVariant.FILE to ConcurrentReadUpdateReaderFileService::class,
-                StorageVariant.OKIO to ConcurrentReadUpdateReaderOkioService::class
-            )
-            // New processes that start in the meantime can also read
-            val readerConnection: BlockingServiceConnection =
-                setUpService(mainContext, readerServiceClasses[variant]!!.java, testData)
-            signalService(readerConnection)
-
-            // The other process finishes writing "true"; we (and other readers) should pick up the new data
-            signalService(writerConnection)
-
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
-            signalService(readerConnection)
-        }
-
-    open class ConcurrentReadUpdateWriterFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                waitForSignal()
-                WRITE_BOOLEAN(it)
-            }
-        }
-    }
-
-    class ConcurrentReadUpdateWriterOkioService : ConcurrentReadUpdateWriterFileService()
-
-    open class ConcurrentReadUpdateReaderFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            assertThat(store.data.first()).isEqualTo(FOO_WITH_TEXT)
-            waitForSignal()
-            assertThat(store.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
-        }
-    }
-
-    class ConcurrentReadUpdateReaderOkioService : ConcurrentReadUpdateReaderFileService()
-
-    @Test
-    fun testInterleavedUpdateData_file() = testInterleavedUpdateData_runner(StorageVariant.FILE)
-
-    @Test
-    fun testInterleavedUpdateData_okio() = testInterleavedUpdateData_runner(StorageVariant.OKIO)
-
-    private fun testInterleavedUpdateData_runner(variant: StorageVariant) =
-        runTest(UnconfinedTestDispatcher(), timeout = 10000.milliseconds) {
-            val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-            val dataStore: DataStore<FooProto> =
-                createDataStore(testData, dataStoreScope, context = dataStoreContext)
-            val serviceClasses = mapOf(
-                StorageVariant.FILE to InterleavedUpdateDataFileService::class,
-                StorageVariant.OKIO to InterleavedUpdateDataOkioService::class
-            )
-            val connection: BlockingServiceConnection =
-                setUpService(mainContext, serviceClasses[variant]!!.java, testData)
-
-            // Other proc starts TEST_TEXT update, then waits for signal
-            signalService(connection)
-
-            // We start "true" update, then wait for condition
-            val condition = CompletableDeferred<Unit>()
-            val write = async(newSingleThreadContext("blockedWriter")) {
-                dataStore.updateData {
-                    condition.await()
-                    WRITE_BOOLEAN(it)
-                }
-            }
-
-            // Allow the other proc's update to run to completion, then allow ours to run to completion
-            val unblockOurUpdate = async {
-                delay(100)
-                signalService(connection)
-                condition.complete(Unit)
-            }
-
-            unblockOurUpdate.await()
-            write.await()
-
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
-        }
-
-    open class InterleavedUpdateDataFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                waitForSignal()
-                WRITE_TEXT(it)
-            }
-        }
-    }
-
-    class InterleavedUpdateDataOkioService : InterleavedUpdateDataFileService()
-
-    @Test
-    fun testInterleavedUpdateDataWithLocalRead_file() =
-        testInterleavedUpdateDataWithLocalRead_runner(StorageVariant.FILE)
-
-    @Test
-    fun testInterleavedUpdateDataWithLocalRead_okio() =
-        testInterleavedUpdateDataWithLocalRead_runner(StorageVariant.OKIO)
-
-    private fun testInterleavedUpdateDataWithLocalRead_runner(variant: StorageVariant) =
-        runTest(UnconfinedTestDispatcher(), timeout = 10000.milliseconds) {
-            val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-            val dataStore: DataStore<FooProto> =
-                createDataStore(testData, dataStoreScope, context = dataStoreContext)
-            val serviceClasses = mapOf(
-                StorageVariant.FILE to InterleavedUpdateDataWithReadFileService::class,
-                StorageVariant.OKIO to InterleavedUpdateDataWithReadOkioService::class
-            )
-            val connection: BlockingServiceConnection =
-                setUpService(
-                    mainContext,
-                    serviceClasses[variant]!!.java,
-                    testData
-                )
-
-            // Invalidate any local cache
-            assertThat(dataStore.data.first()).isEqualTo(DEFAULT_FOO)
-            signalService(connection)
-
-            // Queue and start local write
-            val writeStarted = CompletableDeferred<Unit>()
-            val finishWrite = CompletableDeferred<Unit>()
-
-            val write = async {
-                dataStore.updateData {
-                    writeStarted.complete(Unit)
-                    finishWrite.await()
-                    FOO_WITH_TEXT
-                }
-            }
-            writeStarted.await()
-
-            // Queue remote write
-            signalService(connection)
-
-            // Local uncached read; this should see data initially written remotely.
-            assertThat(dataStore.data.first()).isEqualTo(
-                FooProto.newBuilder().setInteger(1).build()
-            )
-
-            // Unblock writes; the local write is delayed to ensure the remote write remains blocked.
-            val remoteWrite = async(newSingleThreadContext("blockedWriter")) {
-                signalService(connection)
-            }
-
-            val localWrite = async(newSingleThreadContext("unblockLocalWrite")) {
-                delay(500)
-                finishWrite.complete(Unit)
-                write.await()
-            }
-
-            localWrite.await()
-            remoteWrite.await()
-
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT_AND_BOOLEAN)
-        }
-
-    open class InterleavedUpdateDataWithReadFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                INCREMENT_INTEGER(it)
-            }
-
-            waitForSignal()
-
-            val write = async {
-                store.updateData {
-                    WRITE_BOOLEAN(it)
-                }
-            }
-            waitForSignal()
-            write.await()
-        }
-    }
-
-    class InterleavedUpdateDataWithReadOkioService : InterleavedUpdateDataWithReadFileService()
-
-    @Test
-    fun testUpdateDataExceptionUnblocksOtherProcessFromWriting_file() =
-        testUpdateDataExceptionUnblocksOtherProcessFromWriting_runner(StorageVariant.FILE)
-
-    @Test
-    fun testUpdateDataExceptionUnblocksOtherProcessFromWriting_okio() =
-        testUpdateDataExceptionUnblocksOtherProcessFromWriting_runner(StorageVariant.OKIO)
-
-    private fun testUpdateDataExceptionUnblocksOtherProcessFromWriting_runner(
-        variant: StorageVariant
-    ) = runTest(timeout = 10000.milliseconds) {
-        val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-        val dataStore: DataStore<FooProto> =
-            createDataStore(testData, dataStoreScope, context = dataStoreContext)
-        val serviceClasses = mapOf(
-            StorageVariant.FILE to FailedUpdateDataFileService::class,
-            StorageVariant.OKIO to FailedUpdateDataOkioService::class
-        )
-        val connection: BlockingServiceConnection =
-            setUpService(mainContext, serviceClasses[variant]!!.java, testData)
-
-        val blockWrite = CompletableDeferred<Unit>()
-        val waitForWrite = CompletableDeferred<Unit>()
-
-        val write = async {
-            try {
-                dataStore.updateData {
-                    blockWrite.await()
-                    throw IOException("Something went wrong")
-                }
-            } catch (e: IOException) {
-                waitForWrite.complete(Unit)
-            }
-        }
-
-        assertThat(write.isActive).isTrue()
-        assertThat(write.isCompleted).isFalse()
-
-        blockWrite.complete(Unit)
-        waitForWrite.await()
-
-        assertThat(write.isActive).isFalse()
-        assertThat(write.isCompleted).isTrue()
-
-        signalService(connection)
-
-        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-    }
-
-    open class FailedUpdateDataFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                WRITE_TEXT(it)
-            }
-        }
-    }
-
-    class FailedUpdateDataOkioService : FailedUpdateDataFileService()
-
-    @Test
-    fun testUpdateDataCancellationUnblocksOtherProcessFromWriting_file() =
-        testUpdateDataCancellationUnblocksOtherProcessFromWriting_runner(StorageVariant.FILE)
-
-    @Test
-    fun testUpdateDataCancellationUnblocksOtherProcessFromWriting_okio() =
-        testUpdateDataCancellationUnblocksOtherProcessFromWriting_runner(StorageVariant.OKIO)
-
-    private fun testUpdateDataCancellationUnblocksOtherProcessFromWriting_runner(
-        variant: StorageVariant
-    ) = runTest(UnconfinedTestDispatcher(), timeout = 10000.milliseconds) {
-        val localScope = TestScope(UnconfinedTestDispatcher() + Job())
-        val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-        val dataStore: DataStore<FooProto> =
-            createDataStore(testData, localScope, context = dataStoreContext)
-        val serviceClasses = mapOf(
-            StorageVariant.FILE to CancelledUpdateDataFileService::class,
-            StorageVariant.OKIO to CancelledUpdateDataOkioService::class
-        )
-        val connection: BlockingServiceConnection =
-            setUpService(mainContext, serviceClasses[variant]!!.java, testData)
-
-        val blockWrite = CompletableDeferred<Unit>()
-
-        val write = localScope.async {
-            dataStore.updateData {
-                blockWrite.await()
-                WRITE_BOOLEAN(it)
-            }
-        }
-
-        assertThat(write.isActive).isTrue()
-        assertThat(write.isCompleted).isFalse()
-
-        // dataStore.updateData cancelled immediately
-        localScope.coroutineContext.cancelChildren()
-
-        assertThat(write.isActive).isFalse()
-        assertThat(write.isCompleted).isTrue()
-
-        signalService(connection)
-
-        // able to read the new value written from the other process
-        assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-    }
-
-    // A duplicate from CancelledUpdateDataService to make sure Android framework would create a
-    // new process for this test. Otherwise the test would hang infinitely because the tests bind
-    // to an existing service created by the previous test.
-    open class CancelledUpdateDataFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            store = createDataStore(testData, scope)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                WRITE_TEXT(it)
-            }
-        }
-    }
-
-    class CancelledUpdateDataOkioService : CancelledUpdateDataFileService()
-
-    @Test
-    fun testReadUpdateCorrupt_file() = testReadUpdateCorrupt_runner(StorageVariant.FILE)
-
-    @Test
-    fun testReadUpdateCorrupt_okio() = testReadUpdateCorrupt_runner(StorageVariant.OKIO)
-
-    private fun testReadUpdateCorrupt_runner(variant: StorageVariant) =
-        runTest(timeout = 10000.milliseconds) {
-            FileOutputStream(testFile).use {
-                OutputStreamWriter(it).write("garbage")
-            }
-            val testData: Bundle = createDataStoreBundle(testFile.absolutePath, variant)
-            val serviceClasses = mapOf(
-                StorageVariant.FILE to InterleavedHandlerUpdateDataFileService::class,
-                StorageVariant.OKIO to InterleavedHandlerUpdateDataOkioService::class
-            )
-            val connection: BlockingServiceConnection =
-                setUpService(mainContext, serviceClasses[variant]!!.java, testData)
-            val corruptionHandler = ReplaceFileCorruptionHandler<FooProto> {
-                signalService(connection)
-                FOO_WITH_TEXT_AND_BOOLEAN
-            }
-            val dataStore: DataStore<FooProto> =
-                createDataStore(testData, dataStoreScope, corruptionHandler, dataStoreContext)
-
-            // Other proc starts TEST_TEXT then waits for signal within handler
-            signalService(connection)
-
-            assertThat(dataStore.data.first()).isEqualTo(FOO_WITH_TEXT)
-
-            // version file should be ready at this point
-            val sharedCounter = SharedCounter.create {
-                File(testFile.absolutePath + ".version")
-            }
-            // only 1 write should be done to handle the corruption, so version is incremented by 1
-            assertThat(sharedCounter.getValue()).isEqualTo(1)
-        }
-
-    open class InterleavedHandlerUpdateDataFileService(
-        private val scope: TestScope = TestScope(UnconfinedTestDispatcher() + Job())
-    ) : DirectTestService() {
-        override fun beforeTest(testData: Bundle) {
-            val corruptionHandler: CorruptionHandler<FooProto> =
-                ReplaceFileCorruptionHandler<FooProto> {
-                    waitForSignal()
-                    DEFAULT_FOO
-                }
-            store = createDataStore(testData, scope, corruptionHandler)
-        }
-
-        override fun runTest() = runBlocking<Unit> {
-            store.updateData {
-                WRITE_TEXT(it)
-            }
-        }
-    }
-
-    class InterleavedHandlerUpdateDataOkioService : InterleavedHandlerUpdateDataFileService()
-}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt
new file mode 100644
index 0000000..1557dd7
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/InterProcessCompletableTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess
+
+import android.os.Parcelable
+import androidx.datastore.core.twoWayIpc.InterProcessCompletable
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.IpcUnit
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.yield
+import kotlinx.parcelize.Parcelize
+import org.junit.Rule
+import org.junit.Test
+
+class InterProcessCompletableTest {
+    @get:Rule
+    val multiProcess = MultiProcessTestRule()
+
+    @Parcelize
+    private data class Value(val value: String) : Parcelable
+
+    @Parcelize
+    private data class Complete(
+        val hostLatch: InterProcessCompletable<Value>,
+        val remoteLatch: InterProcessCompletable<Value>,
+        val hostValue: Value,
+        val remoteValue: Value
+    ) : IpcAction<IpcUnit>() {
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): IpcUnit {
+            assertThat(
+                hostLatch.await(subject)
+            ).isEqualTo(hostValue)
+            remoteLatch.complete(subject, remoteValue)
+            return IpcUnit
+        }
+    }
+
+    @Test
+    fun completeInRemoteProcess() = multiProcess.runTest {
+        val subject = multiProcess.createConnection().createSubject(this)
+        val hostLatch = InterProcessCompletable<Value>()
+        val remoteLatch = InterProcessCompletable<Value>()
+        val remoteInvocation = async {
+            subject.invokeInRemoteProcess(
+                Complete(
+                    hostLatch = hostLatch,
+                    remoteLatch = remoteLatch,
+                    hostValue = Value("host"),
+                    remoteValue = Value("remote")
+                )
+            )
+        }
+        yield()
+        // cannot complete, we didn't release the host latch
+        assertThat(remoteInvocation.isActive).isTrue()
+        hostLatch.complete(subject, Value("host"))
+        remoteInvocation.await()
+        assertThat(remoteLatch.await(subject)).isEqualTo(Value("remote"))
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt
new file mode 100644
index 0000000..c3351b3
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessDataStoreIpcTest.kt
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess
+
+import androidx.datastore.core.CorruptionException
+import androidx.datastore.core.CorruptionHandler
+import androidx.datastore.core.IOException
+import androidx.datastore.core.SharedCounter
+import androidx.datastore.core.multiprocess.ipcActions.ReadTextAction
+import androidx.datastore.core.multiprocess.ipcActions.SetTextAction
+import androidx.datastore.core.multiprocess.ipcActions.StorageVariant
+import androidx.datastore.core.multiprocess.ipcActions.createMultiProcessTestDatastore
+import androidx.datastore.core.multiprocess.ipcActions.datastore
+import androidx.datastore.core.twoWayIpc.InterProcessCompletable
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.IpcUnit
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testing.TestMessageProto.FooProto
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import kotlinx.parcelize.Parcelize
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+class MultiProcessDataStoreIpcTest {
+    @get:Rule
+    val multiProcessRule = MultiProcessTestRule()
+
+    @get:Rule
+    val tmpFolder = TemporaryFolder()
+
+    @Test
+    fun testSimpleUpdateData_file() = testSimpleUpdateData(StorageVariant.FILE)
+
+    @Test
+    fun testSimpleUpdateData_okio() = testSimpleUpdateData(StorageVariant.OKIO)
+
+    private fun testSimpleUpdateData(storageVariant: StorageVariant) = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        val file = tmpFolder.newFile()
+        val datastore = createMultiProcessTestDatastore(
+            filePath = file.canonicalPath,
+            storageVariant = storageVariant,
+            hostDatastoreScope = multiProcessRule.datastoreScope,
+            subjects = arrayOf(subject)
+        )
+        subject.invokeInRemoteProcess(SetTextAction("abc"))
+        assertThat(datastore.data.first().text).isEqualTo("abc")
+        datastore.updateData {
+            it.toBuilder().setText("hostValue").build()
+        }
+        // read from remote process
+        assertThat(
+            subject.invokeInRemoteProcess(
+                ReadTextAction()
+            ).value
+        ).isEqualTo("hostValue")
+    }
+
+    @Test
+    fun testConcurrentReadUpdate_file() = testConcurrentReadUpdate(StorageVariant.FILE)
+
+    @Test
+    fun testConcurrentReadUpdate_okio() = testConcurrentReadUpdate(StorageVariant.OKIO)
+
+    private fun testConcurrentReadUpdate(storageVariant: StorageVariant) =
+        multiProcessRule.runTest {
+            val subject1 = multiProcessRule.createConnection().createSubject(
+                multiProcessRule.datastoreScope
+            )
+            val subject2 = multiProcessRule.createConnection().createSubject(
+                multiProcessRule.datastoreScope
+            )
+            val file = tmpFolder.newFile()
+            val dataStore = createMultiProcessTestDatastore(
+                filePath = file.canonicalPath,
+                storageVariant = storageVariant,
+                hostDatastoreScope = multiProcessRule.datastoreScope,
+                subjects = arrayOf(subject1, subject2)
+            )
+            // start with data
+            dataStore.updateData {
+                it.toBuilder().setText("hostData").build()
+            }
+            val commitWriteLatch = InterProcessCompletable<IpcUnit>()
+            val writeStartedLatch = InterProcessCompletable<IpcUnit>()
+            val setTextAction = async {
+                subject1.invokeInRemoteProcess(
+                    SetTextAction(
+                        value = "remoteValue",
+                        commitTransactionLatch = commitWriteLatch,
+                        transactionStartedLatch = writeStartedLatch
+                    )
+                )
+            }
+            writeStartedLatch.await(subject1)
+            // we can still read
+            assertThat(dataStore.data.first().text).isEqualTo("hostData")
+            // writer process can read data
+            assertThat(
+                subject1.invokeInRemoteProcess(
+                    ReadTextAction()
+                ).value
+            ).isEqualTo("hostData")
+            // another process can read data
+            assertThat(
+                subject2.invokeInRemoteProcess(
+                    ReadTextAction()
+                ).value
+            ).isEqualTo("hostData")
+            commitWriteLatch.complete(subject1, IpcUnit)
+            setTextAction.await()
+            // now everyone should see the new value
+            assertThat(dataStore.data.first().text).isEqualTo("remoteValue")
+            assertThat(
+                subject1.invokeInRemoteProcess(
+                    ReadTextAction()
+                ).value
+            ).isEqualTo("remoteValue")
+            assertThat(
+                subject2.invokeInRemoteProcess(
+                    ReadTextAction()
+                ).value
+            ).isEqualTo("remoteValue")
+        }
+
+    @Test
+    fun testInterleavedUpdateData_file() = testInterleavedUpdateData(StorageVariant.FILE)
+
+    @Test
+    fun testInterleavedUpdateData_okio() = testInterleavedUpdateData(StorageVariant.OKIO)
+
+    private fun testInterleavedUpdateData(storageVariant: StorageVariant) =
+        multiProcessRule.runTest {
+            val subject = multiProcessRule.createConnection().createSubject(
+                multiProcessRule.datastoreScope
+            )
+            val file = tmpFolder.newFile()
+            val dataStore = createMultiProcessTestDatastore(
+                filePath = file.canonicalPath,
+                storageVariant = storageVariant,
+                hostDatastoreScope = multiProcessRule.datastoreScope,
+                subjects = arrayOf(subject)
+            )
+            val remoteWriteStarted = InterProcessCompletable<IpcUnit>()
+            val allowRemoteCommit = InterProcessCompletable<IpcUnit>()
+            val remoteUpdate = async {
+                // update text in remote
+                subject.invokeInRemoteProcess(
+                    SetTextAction(
+                        value = "remoteValue",
+                        transactionStartedLatch = remoteWriteStarted,
+                        commitTransactionLatch = allowRemoteCommit
+                    )
+                )
+            }
+            // wait for remote write to start
+            remoteWriteStarted.await(subject)
+            // start a host update, which will be blocked
+            val hostUpdateStarted = CompletableDeferred<Unit>()
+            val hostUpdate = async {
+                hostUpdateStarted.complete(Unit)
+                dataStore.updateData {
+                    it.toBuilder().setInteger(99).build()
+                }
+            }
+            // let our host update start
+            hostUpdateStarted.await()
+            // give it some to be blocked
+            delay(100)
+            // both are running
+            assertThat(hostUpdate.isActive).isTrue()
+            assertThat(remoteUpdate.isActive).isTrue()
+            // commit remote transaction
+            allowRemoteCommit.complete(subject, IpcUnit)
+            // wait for both
+            listOf(hostUpdate, remoteUpdate).awaitAll()
+            dataStore.data.first().let {
+                assertThat(it.text).isEqualTo("remoteValue")
+                assertThat(it.integer).isEqualTo(99)
+            }
+        }
+
+    @Test
+    fun testInterleavedUpdateDataWithLocalRead_file() =
+        testInterleavedUpdateDataWithLocalRead(StorageVariant.FILE)
+
+    @Test
+    fun testInterleavedUpdateDataWithLocalRead_okio() =
+        testInterleavedUpdateDataWithLocalRead(StorageVariant.OKIO)
+
+    @Parcelize
+    private data class InterleavedDoubleUpdateAction(
+        val updatedInteger: InterProcessCompletable<IpcUnit> = InterProcessCompletable(),
+        val unblockBooleanWrite: InterProcessCompletable<IpcUnit> = InterProcessCompletable(),
+        val willWriteBooleanData: InterProcessCompletable<IpcUnit> = InterProcessCompletable(),
+    ) : IpcAction<IpcUnit>() {
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): IpcUnit {
+            subject.datastore.updateData {
+                it.toBuilder().setInteger(
+                    it.integer + 1
+                ).build()
+            }
+            updatedInteger.complete(subject, IpcUnit)
+            unblockBooleanWrite.await(subject)
+            willWriteBooleanData.complete(subject, IpcUnit)
+            subject.datastore.updateData {
+                it.toBuilder().setBoolean(true).build()
+            }
+            return IpcUnit
+        }
+    }
+    private fun testInterleavedUpdateDataWithLocalRead(storageVariant: StorageVariant) =
+        multiProcessRule.runTest {
+            val subject = multiProcessRule.createConnection().createSubject(
+                multiProcessRule.datastoreScope
+            )
+            val file = tmpFolder.newFile()
+            val dataStore = createMultiProcessTestDatastore(
+                filePath = file.canonicalPath,
+                storageVariant = storageVariant,
+                hostDatastoreScope = multiProcessRule.datastoreScope,
+                subjects = arrayOf(subject)
+            )
+            // invalidate local cache
+            assertThat(dataStore.data.first()).isEqualTo(FooProto.getDefaultInstance())
+            val remoteAction = InterleavedDoubleUpdateAction()
+            val remoteActionExecution = async {
+                subject.invokeInRemoteProcess(remoteAction)
+            }
+            // Queue and start local write
+            val writeStarted = CompletableDeferred<Unit>()
+            val finishWrite = CompletableDeferred<Unit>()
+
+            // wait for remote to write the int value
+            remoteAction.updatedInteger.await(subject)
+
+            val hostWrite = async {
+                dataStore.updateData {
+                    writeStarted.complete(Unit)
+                    finishWrite.await()
+                    FooProto.newBuilder().setText("hostValue").build()
+                }
+            }
+            writeStarted.await()
+            // our write is blocked so we should only see the int value for now
+            assertThat(dataStore.data.first()).isEqualTo(
+                FooProto.newBuilder().setInteger(1).build()
+            )
+            // unblock the remote write but it will be blocked as we already have a write
+            // lock in host process
+            remoteAction.unblockBooleanWrite.complete(subject, IpcUnit)
+            // wait for remote to be ready to write
+            remoteAction.willWriteBooleanData.await(subject)
+            // delay some to ensure remote is really blocked
+            delay(200)
+            finishWrite.complete(Unit)
+            // wait for both
+            listOf(hostWrite, remoteActionExecution).awaitAll()
+            // both writes committed
+            assertThat(
+                dataStore.data.first()
+            ).isEqualTo(
+                FooProto.getDefaultInstance().toBuilder()
+                    .setText("hostValue")
+                    // int is not set since local did override it w/ default
+                    .setBoolean(true)
+                    .build()
+            )
+        }
+
+    @Test
+    fun testUpdateDataExceptionUnblocksOtherProcessFromWriting_file() =
+        testUpdateDataExceptionUnblocksOtherProcessFromWriting(StorageVariant.FILE)
+
+    @Test
+    fun testUpdateDataExceptionUnblocksOtherProcessFromWriting_okio() =
+        testUpdateDataExceptionUnblocksOtherProcessFromWriting(StorageVariant.OKIO)
+
+    private fun testUpdateDataExceptionUnblocksOtherProcessFromWriting(
+        storageVariant: StorageVariant
+    ) = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        val file = tmpFolder.newFile()
+        val dataStore = createMultiProcessTestDatastore(
+            filePath = file.canonicalPath,
+            storageVariant = storageVariant,
+            hostDatastoreScope = multiProcessRule.datastoreScope,
+            subjects = arrayOf(subject)
+        )
+        val blockWrite = CompletableDeferred<Unit>()
+        val localWriteStarted = CompletableDeferred<Unit>()
+
+        val write = async {
+            try {
+                dataStore.updateData {
+                    localWriteStarted.complete(Unit)
+                    blockWrite.await()
+                    throw IOException("Something went wrong")
+                }
+            } catch (_: IOException) {
+            }
+        }
+        localWriteStarted.await()
+        val setTextAction = async {
+            subject.invokeInRemoteProcess(
+                SetTextAction(
+                    value = "remoteValue"
+                )
+            )
+        }
+        delay(100)
+        // cannot start since we are holding the lock
+        assertThat(setTextAction.isActive).isTrue()
+        blockWrite.complete(Unit)
+        listOf(write, setTextAction).awaitAll()
+        assertThat(dataStore.data.first().text).isEqualTo("remoteValue")
+    }
+
+    @Test
+    fun testUpdateDataCancellationUnblocksOtherProcessFromWriting_file() =
+        testUpdateDataCancellationUnblocksOtherProcessFromWriting(StorageVariant.FILE)
+
+    @Test
+    fun testUpdateDataCancellationUnblocksOtherProcessFromWriting_okio() =
+        testUpdateDataCancellationUnblocksOtherProcessFromWriting(StorageVariant.OKIO)
+
+    private fun testUpdateDataCancellationUnblocksOtherProcessFromWriting(
+        storageVariant: StorageVariant
+    ) = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        val file = tmpFolder.newFile()
+        val localScope = CoroutineScope(Dispatchers.IO)
+        val dataStore = createMultiProcessTestDatastore(
+            filePath = file.canonicalPath,
+            storageVariant = storageVariant,
+            hostDatastoreScope = multiProcessRule.datastoreScope,
+            subjects = arrayOf(subject)
+        )
+        val blockWrite = CompletableDeferred<Unit>()
+        val startedWrite = CompletableDeferred<Unit>()
+
+        localScope.launch {
+            dataStore.updateData {
+                startedWrite.complete(Unit)
+                blockWrite.await()
+                it.toBuilder().setInteger(3).build()
+            }
+        }
+        startedWrite.await()
+        val setTextAction = async {
+            subject.invokeInRemoteProcess(
+                SetTextAction(
+                    value = "remoteValue"
+                )
+            )
+        }
+        delay(100)
+        // cannot start since we are holding the lock
+        assertThat(setTextAction.isActive).isTrue()
+        // cancel the scope that is holding the write lock
+        localScope.cancel()
+        // wait for remote to finish
+        setTextAction.await()
+        assertThat(dataStore.data.first()).isEqualTo(
+            FooProto.getDefaultInstance()
+                .toBuilder()
+                .setText("remoteValue")
+                .build()
+        )
+    }
+
+    @Test
+    fun testReadUpdateCorrupt_file() = testReadUpdateCorrupt(StorageVariant.FILE)
+
+    @Test
+    fun testReadUpdateCorrupt_okio() = testReadUpdateCorrupt(StorageVariant.OKIO)
+
+    private class TestCorruptionHandler : CorruptionHandler<FooProto> {
+        override suspend fun handleCorruption(ex: CorruptionException): FooProto {
+            return createRecoveryValue(inMainProcess)
+        }
+
+        companion object {
+            var inMainProcess = false
+
+            fun createRecoveryValue(mainProcess: Boolean): FooProto {
+                return FooProto.getDefaultInstance()
+                    .toBuilder()
+                    .setText("defaultCorruptValue, main process? $mainProcess")
+                    .build()
+            }
+        }
+    }
+
+    private fun testReadUpdateCorrupt(storageVariant: StorageVariant) = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        val file = tmpFolder.newFile()
+        // corrupt file
+        file.writeText("garbage")
+        // set a shared value so we can know which corruption handler did run
+        TestCorruptionHandler.inMainProcess = true
+        val dataStore = createMultiProcessTestDatastore(
+            filePath = file.canonicalPath,
+            storageVariant = storageVariant,
+            hostDatastoreScope = multiProcessRule.datastoreScope,
+            corruptionHandler = TestCorruptionHandler::class.java,
+            subjects = arrayOf(subject)
+        )
+        val blockSetText = InterProcessCompletable<IpcUnit>()
+        val writeStarted = InterProcessCompletable<IpcUnit>()
+        val setTextAction = async {
+            subject.invokeInRemoteProcess(
+                SetTextAction(
+                    value = "remoteValue",
+                    commitTransactionLatch = blockSetText,
+                    transactionStartedLatch = writeStarted
+                )
+            )
+        }
+        writeStarted.await(subject)
+        // we read the corruption handler value since the write hasn't happened yet
+        // the write in the remote process already started, hence we'll read its recovery value
+        assertThat(dataStore.data.first()).isEqualTo(
+            TestCorruptionHandler.createRecoveryValue(
+                mainProcess = false
+            )
+        )
+        // version file should be ready at this point
+        val sharedCounter = SharedCounter.create {
+            file.parentFile!!.resolve("${file.name}.version")
+        }
+        // only 1 write should be done to handle the corruption, so version is incremented by 1
+        assertThat(sharedCounter.getValue()).isEqualTo(1)
+        // unblock write
+        blockSetText.complete(subject, IpcUnit)
+        // wait for write to finish
+        setTextAction.await()
+        // now we can see the value written there
+        assertThat(dataStore.data.first().text).isEqualTo(
+            "remoteValue"
+        )
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt
new file mode 100644
index 0000000..0bbcdbc
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/MultiProcessTestRule.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess
+
+import androidx.datastore.core.twoWayIpc.TwoWayIpcConnection
+import androidx.datastore.core.twoWayIpc.TwoWayIpcService
+import androidx.datastore.core.twoWayIpc.TwoWayIpcService2
+import androidx.test.platform.app.InstrumentationRegistry
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
+import kotlinx.coroutines.withTimeout
+import org.junit.rules.TestWatcher
+import org.junit.runner.Description
+
+/**
+ * Used for testing multi-process cases while also maintaining resources so that services
+ * are properly closed after test.
+ */
+class MultiProcessTestRule : TestWatcher() {
+    private val context = InstrumentationRegistry.getInstrumentation().context
+
+    // use a real scope, it is too hard to use a TestScope when we cannot control the IPC
+    val datastoreScope = CoroutineScope(
+        Dispatchers.IO + Job()
+    )
+    private val connectionsMutex = Mutex()
+    private val connections = mutableListOf<TwoWayIpcConnection>()
+    private val availableServiceClasses = mutableListOf<Class<out TwoWayIpcService>>(
+        TwoWayIpcService::class.java,
+        TwoWayIpcService2::class.java
+    )
+
+    fun runTest(block: suspend CoroutineScope.() -> Unit) {
+        // don't use datastore scope here as it will not finish by itself.
+        runBlocking {
+            withTimeout(TEST_TIMEOUT) {
+                block()
+            }
+        }
+    }
+
+    suspend fun createConnection(): TwoWayIpcConnection {
+        val connection = connectionsMutex.withLock {
+            val klass = availableServiceClasses.removeFirstOrNull() ?: error(
+                "Cannot create more services," +
+                    "you can declare more in the manifest if needed"
+            )
+            TwoWayIpcConnection(context, klass).also {
+                connections.add(it)
+            }
+        }
+        connection.connect()
+        return connection
+    }
+
+    override fun finished(description: Description) {
+        super.finished(description)
+        connections.forEach {
+            it.disconnect()
+        }
+        datastoreScope.cancel()
+    }
+
+    companion object {
+        val TEST_TIMEOUT = 10.seconds
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt
new file mode 100644
index 0000000..f081fb6
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/TwoWayIpcTest.kt
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess
+
+import android.os.Parcelable
+import androidx.datastore.core.twoWayIpc.CompositeServiceSubjectModel
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import com.google.common.truth.Truth.assertThat
+import kotlinx.parcelize.Parcelize
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class TwoWayIpcTest {
+    @get:Rule
+    val multiProcessRule = MultiProcessTestRule()
+
+    @Parcelize
+    internal class MultiplyBy3Action(
+        var input: Int
+    ) : IpcAction<MultiplyBy3Action.Output>() {
+        @Parcelize
+        data class Output(val value: Int) : Parcelable
+
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): Output {
+            return Output(input * 3)
+        }
+    }
+
+    @Test
+    fun sample() = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        assertThat(
+            subject.invokeInRemoteProcess(MultiplyBy3Action(3))
+        ).isEqualTo(MultiplyBy3Action.Output(9))
+    }
+
+    @Parcelize
+    internal class ThrowingAction : IpcAction<ThrowingAction>() {
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): ThrowingAction {
+            error("some error i got")
+        }
+    }
+
+    @Test
+    fun exceptionThrown() = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject = connection.createSubject(this)
+        val result = runCatching {
+            subject.invokeInRemoteProcess(ThrowingAction())
+        }
+        assertThat(result.exceptionOrNull()).hasMessageThat().contains(
+            "some error i got"
+        )
+    }
+
+    @Parcelize
+    internal data class ValueInRemoteAction(
+        val id: String,
+        val value: String,
+        val set: Boolean
+    ) : IpcAction<ValueInRemoteAction.Output>() {
+
+        @Parcelize
+        data class Output(val value: String) : Parcelable
+
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): Output {
+            if (set) {
+                subject.data[StringKey(id)] = value
+            }
+            return Output(subject.data[StringKey(id)])
+        }
+
+        data class StringKey(val id: String) : CompositeServiceSubjectModel.Key<String>()
+    }
+
+    @Test
+    fun multipleSubjects() = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val subject1 = connection.createSubject(this)
+        val subject2 = connection.createSubject(this)
+        val action = ValueInRemoteAction(
+            id = "a", value = "b", set = true
+        )
+        assertThat(
+            subject1.invokeInRemoteProcess(action).value
+        ).isEqualTo("b")
+        assertThat(
+            subject2.invokeInRemoteProcess(action).value
+        ).isEqualTo("b")
+
+        assertThat(
+            subject1.invokeInRemoteProcess(action.copy(value = "c")).value
+        ).isEqualTo("c")
+
+        assertThat(
+            // don't set
+            subject1.invokeInRemoteProcess(action.copy(value = "d", set = false)).value
+        ).isEqualTo("c")
+        assertThat(
+            // don't set
+            subject2.invokeInRemoteProcess(action.copy(value = "d", set = false)).value
+        ).isEqualTo("b")
+    }
+
+    @Parcelize
+    internal class SendFromRemoteProcess(
+        val value: String
+    ) : IpcAction<SendFromRemoteProcess>() {
+
+        @Parcelize
+        internal class ActionInMainProcess(
+            val value: String
+        ) : IpcAction<ActionInMainProcess>() {
+            override suspend fun invokeInRemoteProcess(
+                subject: TwoWayIpcSubject
+            ): ActionInMainProcess {
+                subject.data[VALUE_KEY] = value
+                return this
+            }
+        }
+
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): SendFromRemoteProcess {
+            subject.invokeInRemoteProcess(
+                ActionInMainProcess(
+                    "$value-$value"
+                )
+            )
+            return this
+        }
+
+        companion object {
+            val VALUE_KEY = CompositeServiceSubjectModel.Key<String>()
+        }
+    }
+
+    @Test
+    fun getMessageFromRemoteProcess() = multiProcessRule.runTest {
+        val connection = multiProcessRule.createConnection()
+        val hostSubject = connection.createSubject(this)
+        hostSubject.invokeInRemoteProcess(SendFromRemoteProcess("hello"))
+        assertThat(
+            hostSubject.data[SendFromRemoteProcess.VALUE_KEY]
+        ).isEqualTo("hello-hello")
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt
new file mode 100644
index 0000000..8ba0080
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/CreateDatastoreAction.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess.ipcActions
+
+import android.os.Parcelable
+import androidx.datastore.core.CorruptionHandler
+import androidx.datastore.core.DataStoreImpl
+import androidx.datastore.core.FileStorage
+import androidx.datastore.core.MultiProcessCoordinator
+import androidx.datastore.core.ProtoOkioSerializer
+import androidx.datastore.core.ProtoSerializer
+import androidx.datastore.core.Serializer
+import androidx.datastore.core.handlers.NoOpCorruptionHandler
+import androidx.datastore.core.okio.OkioSerializer
+import androidx.datastore.core.okio.OkioStorage
+import androidx.datastore.core.twoWayIpc.CompositeServiceSubjectModel
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.SubjectReadWriteProperty
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import androidx.datastore.testing.TestMessageProto.FooProto
+import com.google.protobuf.ExtensionRegistryLite
+import java.io.File
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.parcelize.Parcelize
+import okio.FileSystem
+import okio.Path.Companion.toPath
+
+private val PROTO_SERIALIZER: Serializer<FooProto> = ProtoSerializer<FooProto>(
+    FooProto.getDefaultInstance(),
+    ExtensionRegistryLite.getEmptyRegistry()
+)
+private val PROTO_OKIO_SERIALIZER: OkioSerializer<FooProto> = ProtoOkioSerializer<FooProto>(
+    FooProto.getDefaultInstance(),
+    ExtensionRegistryLite.getEmptyRegistry()
+)
+
+internal enum class StorageVariant {
+    FILE, OKIO
+}
+/**
+ * Creates the same datastore in current process as well as in the other given [subjects].
+ */
+internal suspend fun createMultiProcessTestDatastore(
+    filePath: String,
+    storageVariant: StorageVariant,
+    hostDatastoreScope: CoroutineScope,
+    corruptionHandler: Class<out CorruptionHandler<FooProto>>? = null,
+    vararg subjects: TwoWayIpcSubject
+): DataStoreImpl<FooProto> {
+    val currentProcessDatastore = createDatastore(
+        filePath = filePath,
+        storageVariant = storageVariant,
+        datastoreScope = hostDatastoreScope,
+        corruptionHandler = corruptionHandler,
+    )
+    subjects.forEach {
+        it.invokeInRemoteProcess(
+            CreateDatastoreAction(
+                filePath = filePath,
+                storageVariant = storageVariant,
+                corruptionHandler = corruptionHandler,
+            )
+        )
+    }
+    return currentProcessDatastore
+}
+
+private fun createDatastore(
+    filePath: String,
+    storageVariant: StorageVariant,
+    datastoreScope: CoroutineScope,
+    corruptionHandler: Class<out CorruptionHandler<FooProto>>?
+): DataStoreImpl<FooProto> {
+    val file = File(filePath)
+    val produceFile = { file }
+    val storage = if (storageVariant == StorageVariant.FILE) {
+        FileStorage(
+            PROTO_SERIALIZER,
+            { MultiProcessCoordinator(Dispatchers.Default, it) },
+            produceFile
+        )
+    } else {
+        OkioStorage(
+            FileSystem.SYSTEM,
+            PROTO_OKIO_SERIALIZER,
+            { path, _ -> MultiProcessCoordinator(Dispatchers.Default, path.toFile()) },
+            { file.absolutePath.toPath() }
+        )
+    }
+    val corruptionHandlerInstance =
+        corruptionHandler?.getDeclaredConstructor()?.also {
+            it.isAccessible = true
+        }?.newInstance() ?: NoOpCorruptionHandler()
+    return DataStoreImpl(
+        storage = storage,
+        scope = datastoreScope,
+        corruptionHandler = corruptionHandlerInstance
+    )
+}
+
+@Parcelize
+private class CreateDatastoreAction(
+    private val filePath: String,
+    private val storageVariant: StorageVariant,
+    private val corruptionHandler: Class<out CorruptionHandler<FooProto>>?
+) : IpcAction<CreateDatastoreAction>(), Parcelable {
+    override suspend fun invokeInRemoteProcess(
+        subject: TwoWayIpcSubject
+    ): CreateDatastoreAction {
+        val store =
+            createDatastore(filePath, storageVariant, subject.datastoreScope, corruptionHandler)
+        subject.datastore = store
+        return this
+    }
+}
+
+private val DATASTORE_KEY =
+    CompositeServiceSubjectModel.Key<DataStoreImpl<FooProto>>()
+
+internal var TwoWayIpcSubject.datastore by SubjectReadWriteProperty(DATASTORE_KEY)
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt
new file mode 100644
index 0000000..9e64a90
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/ReadTextAction.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess.ipcActions
+
+import android.os.Parcelable
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import kotlinx.coroutines.flow.first
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+internal class ReadTextAction : IpcAction<ReadTextAction.TextValue>() {
+    @Parcelize
+    data class TextValue(val value: String) : Parcelable
+
+    override suspend fun invokeInRemoteProcess(
+        subject: TwoWayIpcSubject
+    ): TextValue {
+        return TextValue(
+            subject.datastore.data.first().text
+        )
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt
new file mode 100644
index 0000000..f442d6ca
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/multiprocess/ipcActions/SetTextAction.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 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.datastore.core.multiprocess.ipcActions
+
+import android.os.Parcelable
+import androidx.datastore.core.twoWayIpc.InterProcessCompletable
+import androidx.datastore.core.twoWayIpc.IpcAction
+import androidx.datastore.core.twoWayIpc.IpcUnit
+import androidx.datastore.core.twoWayIpc.TwoWayIpcSubject
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+internal class SetTextAction(
+    private val value: String,
+    private val transactionStartedLatch: InterProcessCompletable<IpcUnit>? = null,
+    private val commitTransactionLatch: InterProcessCompletable<IpcUnit>? = null,
+) : IpcAction<IpcUnit>(), Parcelable {
+    override suspend fun invokeInRemoteProcess(
+        subject: TwoWayIpcSubject
+    ): IpcUnit {
+        subject.datastore.updateData {
+            transactionStartedLatch?.complete(subject, IpcUnit)
+            commitTransactionLatch?.await(subject)
+            it.toBuilder().setText(value).build()
+        }
+        return IpcUnit
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt
new file mode 100644
index 0000000..7bc55d8
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/CompositeServiceSubjectModel.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * A data container that provides a place to stash values with keys and get them back.
+ *
+ * @see IpcAction
+ * @see TwoWayIpcSubject
+ */
+internal class CompositeServiceSubjectModel {
+    private val data = ConcurrentHashMap<Key<*>, Any?>()
+
+    open class Key<T>
+
+    @Suppress("UNCHECKED_CAST")
+    operator fun <T> get(key: Key<T>) = data[key] as T
+
+    fun <T> contains(key: Key<T>) = data.containsKey(key)
+
+    operator fun <T> set(key: Key<T>, value: T?) {
+        data[key] = value
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt
new file mode 100644
index 0000000..f6209bd
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/InterProcessCompletable.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.os.Parcelable
+import java.util.UUID
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.parcelize.Parcelize
+
+/**
+ * A [Parcelable] [CompletableDeferred] implementation that can be shared
+ * across processes.
+ */
+@Parcelize
+internal class InterProcessCompletable<T : Parcelable> constructor(
+    private val key: String = UUID.randomUUID().toString(),
+) : Parcelable {
+    suspend fun complete(subject: TwoWayIpcSubject, value: T) {
+        IpcLogger.log("will complete $key")
+        subject.crossProcessCompletableController.complete(key, value)
+    }
+
+    suspend fun await(subject: TwoWayIpcSubject): T {
+        return subject.crossProcessCompletableController.obtainInCurrentProcess<T>(key).await()
+    }
+
+    override fun toString(): String {
+        return "completable[$key]"
+    }
+}
+
+/**
+ * Manages [InterProcessCompletable] instances across processes.
+ * When an instance is completed in one process, its value will be dispatched
+ * to the other process as well.
+ */
+private class CrossProcessCompletableController(
+    private val subject: TwoWayIpcSubject
+) {
+    private val completables = mutableMapOf<String, CompletableDeferred<*>>()
+
+    private fun <T> get(key: String) = synchronized(this) {
+        @Suppress("UNCHECKED_CAST")
+        completables.getOrPut(key) {
+            CompletableDeferred<T>()
+        } as CompletableDeferred<T>
+    }
+
+    private fun <T : Parcelable> completeInCurrentProcess(key: String, value: T) {
+        IpcLogger.log("complete internal $key")
+        get<T>(key).complete(value)
+    }
+
+    fun <T : Parcelable> obtainInCurrentProcess(key: String): CompletableDeferred<T> {
+        return get(key)
+    }
+
+    suspend fun <T : Parcelable> complete(key: String, value: T) {
+        completeInCurrentProcess(key, value)
+        IpcLogger.log("will complete $key in remote process")
+        subject.invokeInRemoteProcess(
+            CompleteCompletableAction(
+                key = key,
+                value = value
+            )
+        )
+        IpcLogger.log("completed $key in remote process")
+    }
+
+    @Parcelize
+    private data class CompleteCompletableAction<T : Parcelable>(
+        private val key: String,
+        private val value: T
+    ) : IpcAction<IpcUnit>() {
+        override suspend fun invokeInRemoteProcess(
+            subject: TwoWayIpcSubject
+        ): IpcUnit {
+            subject.crossProcessCompletableController.completeInCurrentProcess(key, value)
+            return IpcUnit
+        }
+    }
+}
+
+@Suppress("PrivatePropertyName")
+private val COMPLETABLE_CONTROLLER_KEY =
+    CompositeServiceSubjectModel.Key<CrossProcessCompletableController>()
+private val TwoWayIpcSubject.crossProcessCompletableController: CrossProcessCompletableController
+    get() {
+        if (!data.contains(COMPLETABLE_CONTROLLER_KEY)) {
+            synchronized(this) {
+                data[COMPLETABLE_CONTROLLER_KEY] =
+                    CrossProcessCompletableController(this)
+            }
+        }
+        return data[COMPLETABLE_CONTROLLER_KEY]
+    }
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcAction.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcAction.kt
new file mode 100644
index 0000000..aae26bc
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcAction.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+/**
+ * A [Parcelable] action that can be executed in a remote process, inside a [TwoWayIpcSubject].
+ */
+internal abstract class IpcAction<T : Parcelable> : Parcelable {
+    abstract suspend fun invokeInRemoteProcess(
+        subject: TwoWayIpcSubject
+    ): T
+}
+
+/**
+ * Utility object for [IpcAction]s that do not return a value.
+ */
+@Parcelize
+object IpcUnit : Parcelable
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcLogger.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcLogger.kt
new file mode 100644
index 0000000..7cdb98e
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/IpcLogger.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.app.Application
+import android.os.Build
+import android.util.Log
+
+/**
+ * Used for logging in multi process tests.
+ * Multi process tests are really hard to debug, hence it is useful to have logs
+ * around when needed.
+ */
+object IpcLogger {
+    fun log(message: Any) {
+        if (ENABLED) {
+            Log.d("DATASTORE-MULTIPROCESS-${getProcessName()}", message.toString())
+        }
+    }
+
+    private fun getProcessName(): String {
+        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+            Application.getProcessName()
+        } else {
+            "notAvailable"
+        }
+    }
+
+    @Suppress("MayBeConstant")
+    val ENABLED = false
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt
new file mode 100644
index 0000000..3ad835e
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcBus.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import androidx.datastore.core.twoWayIpc.IpcLogger.log
+import java.util.UUID
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withTimeout
+
+/**
+ * A bus that can be used across processes to make IPC calls.
+ *
+ * You wouldn't use this directly, instead, use [TwoWayIpcSubject] combined with
+ * [IpcAction].
+ */
+class TwoWayIpcBus(
+    val executionScope: CoroutineScope,
+    val handler: suspend (Bundle?) -> Bundle?
+) {
+    private val pendingMessages = mutableMapOf<String, CompletableDeferred<Bundle?>>()
+    val incomingMessenger = Messenger(
+        object : Handler(
+            Looper.getMainLooper()
+        ) {
+            override fun handleMessage(msg: Message) {
+                val copy = Message.obtain().also {
+                    it.copyFrom(msg)
+                }
+                copy.data?.classLoader = TwoWayIpcBus::class.java.classLoader
+                executionScope.launch {
+                    handleIncomingMessage(copy)
+                }
+            }
+        }
+    )
+
+    private lateinit var outgoingMessenger: Messenger
+
+    private suspend fun handleIncomingMessage(msg: Message) {
+        log("incoming message")
+        val uuid = msg.data.getString(KEY_UUID) ?: error("no uuid in message")
+        log("id: $uuid, what: ${msg.what}")
+        when (msg.what) {
+            MSG_EXECUTE_ACTION -> {
+                val payload = msg.data.getBundle(KEY_PAYLOAD)
+                val responseMessage = Message.obtain()
+                responseMessage.data.putString(KEY_UUID, uuid)
+                try {
+                    val handlerResponse = handler(payload)
+                    responseMessage.what = MSG_ACTION_RESPONSE
+                    responseMessage.data.putBundle(KEY_PAYLOAD, handlerResponse)
+                } catch (th: Throwable) {
+                    log("error while handling message, ${th.stackTraceToString()}")
+                    responseMessage.what = MSG_EXCEPTION
+                    responseMessage.data.putString(KEY_STACKTRACE, th.stackTraceToString())
+                }
+                msg.replyTo.send(responseMessage)
+            }
+
+            MSG_ACTION_RESPONSE -> {
+                val responseHandle = synchronized(pendingMessages) {
+                    pendingMessages.remove(uuid)
+                } ?: error("no response handle for $uuid")
+                responseHandle.complete(
+                    msg.data.getBundle(KEY_PAYLOAD)
+                )
+            }
+
+            MSG_EXCEPTION -> {
+                val responseHandle = synchronized(pendingMessages) {
+                    pendingMessages.remove(uuid)
+                } ?: error("no response handle for $uuid")
+                val exceptionMessage = msg.data.getString(KEY_STACKTRACE)
+                responseHandle.completeExceptionally(
+                    RuntimeException("exception in remote process: $exceptionMessage")
+                )
+            }
+
+            else -> {
+                // respond with error
+                msg.replyTo.send(
+                    Message.obtain().also {
+                        it.what = MSG_EXCEPTION
+                        it.data.putString(KEY_STACKTRACE, "unknown message what: ${msg.what}")
+                    }
+                )
+            }
+        }
+    }
+
+    fun setOutgoingMessenger(messenger: Messenger) {
+        outgoingMessenger = messenger
+    }
+
+    suspend fun sendMessage(
+        payload: Bundle?
+    ): Bundle? {
+        val uuid = UUID.randomUUID().toString()
+        log("sending message $uuid")
+        val response = CompletableDeferred<Bundle?>()
+        synchronized(pendingMessages) {
+            pendingMessages[uuid] = response
+        }
+
+        val message = Message.obtain()
+        message.what = MSG_EXECUTE_ACTION
+        message.data.putBundle(KEY_PAYLOAD, payload)
+        message.data.putString(KEY_UUID, uuid)
+        message.replyTo = incomingMessenger
+        message.data?.classLoader = TwoWayIpcBus::class.java.classLoader
+        outgoingMessenger.send(message)
+        log("sent message $uuid")
+        return withTimeout(TIMEOUT) {
+            response.await()
+        }.also {
+            log("received response for $uuid")
+        }
+    }
+
+    companion object {
+        private val TIMEOUT = 5.seconds
+        private const val MSG_EXECUTE_ACTION = 1
+        private const val MSG_ACTION_RESPONSE = 2
+        private const val MSG_EXCEPTION = 3
+        private const val KEY_UUID = "ipc_uuid"
+        private const val KEY_PAYLOAD = "ipc_payload"
+        private const val KEY_STACKTRACE = "ipc_stacktrace"
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt
new file mode 100644
index 0000000..b9e34a5
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcConnection.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.content.pm.PackageManager
+import android.os.Handler
+import android.os.IBinder
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CompletableDeferred
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.withTimeout
+
+/**
+ * A [ServiceConnection] implementation that talks to an instance of
+ * [TwoWayIpcService].
+ */
+class TwoWayIpcConnection(
+    private val context: Context,
+    private val klass: Class<out TwoWayIpcService>,
+) : ServiceConnection {
+    private val connectionEstablished = CompletableDeferred<Messenger>()
+    private suspend fun <T> withConnectionTimeout(block: suspend () -> T): T {
+        return withTimeout(TIMEOUT) {
+            block()
+        }
+    }
+
+    suspend fun connect() {
+        val intent = Intent(context, klass)
+        withConnectionTimeout {
+            val serviceExists: Boolean = context.bindService(intent, this, Context.BIND_AUTO_CREATE)
+
+            if (!serviceExists) {
+                val targetPackage: String = intent.component!!.packageName
+                val targetService: String = intent.component!!.className
+
+                try {
+                    context.packageManager.getPackageInfo(targetPackage, 0)
+                } catch (e: PackageManager.NameNotFoundException) {
+                    throw IllegalStateException("Package not installed [$targetPackage]", e)
+                }
+                throw IllegalStateException(
+                    "Package installed but service not found [$targetService]"
+                )
+            }
+            connectionEstablished.await()
+        }
+    }
+
+    fun disconnect() {
+        context.unbindService(this)
+    }
+
+    private suspend fun sendMessage(message: Message): Message = withConnectionTimeout {
+        val response = CompletableDeferred<Message>()
+        message.replyTo = Messenger(object : Handler(Looper.getMainLooper()) {
+            override fun handleMessage(msg: Message) {
+                if (msg.what == TwoWayIpcService.MSG_CREATE_SUBJECT) {
+                    val stacktrace = msg.data.getString("ipc_stacktrace") ?: "missing stacktrace"
+                    response.completeExceptionally(
+                        AssertionError("Exception in remote process: $stacktrace")
+                    )
+                } else {
+                    response.complete(Message.obtain().also { it.copyFrom(msg) })
+                }
+            }
+        })
+        connectionEstablished.await().send(
+            message
+        )
+        response.await()
+    }
+
+    override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
+        connectionEstablished.complete(Messenger(binder))
+    }
+
+    override fun onServiceDisconnected(componentName: ComponentName) {
+        // this is called only if the service crashes
+    }
+
+    internal suspend fun createSubject(
+        hostExecutionScope: CoroutineScope,
+    ): TwoWayIpcSubject {
+        val hostSubject = TwoWayIpcSubject(
+            datastoreScope = hostExecutionScope
+        )
+        val message = Message.obtain()
+        message.what = TwoWayIpcService.MSG_CREATE_SUBJECT
+        message.data.putParcelable("messenger", hostSubject.bus.incomingMessenger)
+        val response = sendMessage(message)
+
+        @Suppress("DEPRECATION") val outgoingMessenger =
+            response.data.getParcelable<Messenger>("messenger")
+        checkNotNull(outgoingMessenger) {
+            "didn't receive an outgoing messenger"
+        }
+        hostSubject.bus.setOutgoingMessenger(outgoingMessenger)
+        return hostSubject
+    }
+
+    companion object {
+        val TIMEOUT = 5.seconds
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt
new file mode 100644
index 0000000..a47b9a3
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcService.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.content.Intent
+import android.os.Handler
+import android.os.IBinder
+import android.os.Looper
+import android.os.Message
+import android.os.Messenger
+import androidx.lifecycle.LifecycleService
+import androidx.lifecycle.lifecycleScope
+
+/**
+ * Another service of the same type, that runs in another separate
+ * process.
+ *
+ * @see TwoWayIpcService
+ */
+class TwoWayIpcService2 : TwoWayIpcService()
+
+/**
+ * An Android [android.app.Service] implementation that can create and maintain
+ * multiple [TwoWayIpcSubject] instances.
+ *
+ * It properly scopes those subjects and destroys their scopes when the Service is
+ * destroyed, allowing tests to properly maintain resources.
+ *
+ * @see androidx.datastore.core.multiprocess.MultiProcessTestRule
+ */
+open class TwoWayIpcService : LifecycleService() {
+    private val subjects = mutableListOf<TwoWayIpcSubject>()
+    private val messenger: Messenger = Messenger(
+        Handler(
+            Looper.getMainLooper()
+        ) { incoming ->
+            // make a copy to prevent recycling
+            when (incoming.what) {
+                MSG_CREATE_SUBJECT -> {
+                    val subject = TwoWayIpcSubject(lifecycleScope).also {
+                        subjects.add(it)
+                    }
+
+                    @Suppress("DEPRECATION")
+                    val messenger = incoming.data.getParcelable<Messenger>("messenger")
+                    checkNotNull(messenger) {
+                        "missing messenger"
+                    }
+                    subject.bus.setOutgoingMessenger(messenger)
+                    val response = Message.obtain().also {
+                        it.data.putParcelable("messenger", subject.bus.incomingMessenger)
+                    }
+                    incoming.replyTo.send(response)
+                }
+
+                else -> error("unknown message type ${incoming.what}")
+            }
+            true
+        }
+    )
+
+    override fun onBind(intent: Intent): IBinder? {
+        return messenger.binder
+    }
+
+    companion object {
+        const val MSG_CREATE_SUBJECT = 500
+    }
+}
diff --git a/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt
new file mode 100644
index 0000000..3d5b7f6
--- /dev/null
+++ b/datastore/datastore-core/src/androidTest/java/androidx/datastore/core/twoWayIpc/TwoWayIpcSubject.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 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.datastore.core.twoWayIpc
+
+import android.os.Bundle
+import android.os.Parcelable
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+import kotlinx.coroutines.CoroutineScope
+
+/**
+ * A class that represents a test subject for DataStore multi-process tests.
+ * Each test subject is given a [datastoreScope] as well as a [data] so they
+ * can keep state.
+ *
+ * Subjects execute [IpcAction]s which contain the actual test logic.
+ */
+internal class TwoWayIpcSubject(
+    val datastoreScope: CoroutineScope
+) {
+    val bus: TwoWayIpcBus = TwoWayIpcBus(
+        executionScope = datastoreScope,
+        handler = this::handleIncomingAction
+    )
+    val data = CompositeServiceSubjectModel()
+
+    private suspend fun handleIncomingAction(bundle: Bundle?): Bundle {
+        @Suppress("DEPRECATION")
+        val ipcAction = bundle?.getParcelable<IpcAction<*>>(KEY_ACTION)
+        checkNotNull(ipcAction) {
+            "no ipc action in bundle"
+        }
+        IpcLogger.log("executing action: ${ipcAction::class.java}")
+
+        val response = ipcAction.invokeInRemoteProcess(this)
+        IpcLogger.log("executed action: ${ipcAction::class.java}")
+        return Bundle().also {
+            it.putParcelable(KEY_RESPONSE, response)
+        }
+    }
+
+    suspend fun <T : Parcelable> invokeInRemoteProcess(action: IpcAction<T>): T {
+        val response = bus.sendMessage(Bundle().also {
+            it.putParcelable(KEY_ACTION, action)
+        })
+        checkNotNull(response) {
+            "No response received for $action"
+        }
+        @Suppress("DEPRECATION")
+        return response.getParcelable(KEY_RESPONSE) ?: error(
+            "didn't get a response from remote process"
+        )
+    }
+
+    companion object {
+        private const val KEY_ACTION = "ipc_action"
+        private const val KEY_RESPONSE = "ipc_response"
+    }
+}
+
+/**
+ * A property delegate to stash values into the [CompositeServiceSubjectModel] of a
+ * [TwoWayIpcSubject].
+ */
+internal class SubjectReadWriteProperty<T>(
+    private val key: CompositeServiceSubjectModel.Key<T>
+) : ReadWriteProperty<TwoWayIpcSubject, T> {
+    override fun getValue(thisRef: TwoWayIpcSubject, property: KProperty<*>): T {
+        return thisRef.data[key]
+    }
+
+    override fun setValue(thisRef: TwoWayIpcSubject, property: KProperty<*>, value: T) {
+        thisRef.data[key] = value
+    }
+}
diff --git a/datastore/datastore-core/src/jvmTest/kotlin/androidx/datastore/core/SimpleActorTest.kt b/datastore/datastore-core/src/jvmTest/kotlin/androidx/datastore/core/SimpleActorTest.kt
index bb3b250..bd6186d 100644
--- a/datastore/datastore-core/src/jvmTest/kotlin/androidx/datastore/core/SimpleActorTest.kt
+++ b/datastore/datastore-core/src/jvmTest/kotlin/androidx/datastore/core/SimpleActorTest.kt
@@ -22,16 +22,19 @@
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicBoolean
 import kotlin.coroutines.AbstractCoroutineContextElement
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.coroutineContext
+import kotlin.time.Duration.Companion.seconds
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.Job
+import kotlinx.coroutines.TimeoutCancellationException
 import kotlinx.coroutines.asCoroutineDispatcher
 import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.awaitCancellation
 import kotlinx.coroutines.cancelAndJoin
 import kotlinx.coroutines.delay
@@ -40,7 +43,7 @@
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runTest
-import org.junit.Ignore
+import kotlinx.coroutines.withTimeout
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.Timeout
@@ -73,16 +76,15 @@
         assertThat(msgs).isEqualTo(listOf(1, 2, 3, 4))
     }
 
-    @Ignore("b/281516026")
     @Test
     fun testOnCompleteIsCalledWhenScopeIsCancelled() = runBlocking<Unit> {
         val scope = CoroutineScope(Job())
-        val called = AtomicBoolean(false)
+        val called = CompletableDeferred<Unit>()
 
         val actor = SimpleActor<Int>(
             scope,
             onComplete = {
-                assertThat(called.compareAndSet(false, true)).isTrue()
+                called.complete(Unit)
             },
             onUndeliveredElement = { _, _ -> }
         ) {
@@ -93,7 +95,13 @@
 
         scope.coroutineContext.job.cancelAndJoin()
 
-        assertThat(called.get()).isTrue()
+        try {
+            withTimeout(5.seconds) {
+                called.await()
+            }
+        } catch (timeout: TimeoutCancellationException) {
+            throw AssertionError("on complete has not been called")
+        }
     }
 
     @Test
@@ -244,11 +252,9 @@
         sender.await()
     }
 
-    @Ignore // b/250077079
     @Test
     fun testAllMessagesAreRespondedTo() = runBlocking<Unit> {
-        val myScope =
-            CoroutineScope(Job() + Executors.newFixedThreadPool(4).asCoroutineDispatcher())
+        val myScope = CoroutineScope(Job() + Dispatchers.IO)
 
         val actorScope = CoroutineScope(Job())
         val actor = SimpleActor<CompletableDeferred<Unit?>>(
@@ -261,23 +267,20 @@
             it.complete(Unit)
         }
 
-        val waiters = myScope.async {
-            repeat(100_000) { _ ->
-                launch {
-                    try {
-                        CompletableDeferred<Unit?>().also {
-                            actor.offer(it)
-                        }.await()
-                    } catch (cancelled: CancellationException) {
-                        // This is OK
-                    }
+        val waiters = (0 until 10_000).map {
+            myScope.async {
+                try {
+                    CompletableDeferred<Unit?>().also {
+                        actor.offer(it)
+                    }.await()
+                } catch (cancelled: CancellationException) {
+                    // This is OK
                 }
             }
         }
-
         delay(100)
         actorScope.coroutineContext.job.cancelAndJoin()
-        waiters.await()
+        waiters.awaitAll()
     }
 
     class TestElement(val name: String) : AbstractCoroutineContextElement(Key) {
diff --git a/datastore/datastore-preferences-core/build.gradle b/datastore/datastore-preferences-core/build.gradle
index 10aff40..2c998ab 100644
--- a/datastore/datastore-preferences-core/build.gradle
+++ b/datastore/datastore-preferences-core/build.gradle
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-
 import androidx.build.BundleInsideHelper
 import androidx.build.KmpPlatformsKt
 import androidx.build.LibraryType
 import androidx.build.PlatformIdentifier
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
-import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
 
 plugins {
     id("AndroidXPlugin")
@@ -109,11 +107,14 @@
 BundleInsideHelper.forInsideJarKmp(
         project,
         /* from = */ "com.google.protobuf",
-        /* to =   */ "androidx.datastore.preferences.protobuf"
+        /* to =   */ "androidx.datastore.preferences.protobuf",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
-    bundleInside(project(path: ":datastore:datastore-preferences-proto", configuration: "export"))
+    bundleInside(project(":datastore:datastore-preferences-proto"))
 }
 
 androidx {
diff --git a/datastore/datastore-preferences-proto/build.gradle b/datastore/datastore-preferences-proto/build.gradle
index e8a46b7b..0d18af0c 100644
--- a/datastore/datastore-preferences-proto/build.gradle
+++ b/datastore/datastore-preferences-proto/build.gradle
@@ -25,17 +25,13 @@
 
 dependencies {
     implementation(libs.protobufLite)
-    api(project(":datastore:datastore-core"))
+    compileOnly(project(":datastore:datastore-core"))
 }
 
 protobuf {
     protoc {
         artifact = libs.protobufCompiler.get()
     }
-
-    // Generates the java proto-lite code for the protos in this project. See
-    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
-    // for more information.
     generateProtoTasks {
         all().each { task ->
             task.builtins {
@@ -56,22 +52,6 @@
     }
 }
 
-// Create export artifact for for JarJaring
-def preferencesProtoJarJarTask = tasks.register("exportJar", Jar) {
-    archiveBaseName.set("export")
-    from(sourceSets.main.output)
-    // The proto-lite dependency includes .proto files, which are not used by datastore. When apps
-    // depend on datastore as well as proto-lite directly, these files conflict since jarjar only
-    // renames the java classes. Remove them here since they are unused.
-    exclude("**/*.proto")
-
-    from(zipTree(configurations.detachedConfiguration(
-            dependencies.create(libs.protobufLite.get())).getSingleFile()))
-}
-
-def jarjarConf = configurations.register("export")
-artifacts.add(jarjarConf.name, preferencesProtoJarJarTask.flatMap { it.archiveFile })
-
 androidx {
     name = "Preferences DataStore Proto"
     publish = Publish.NONE
diff --git a/development/build_log_simplifier/messages.ignore b/development/build_log_simplifier/messages.ignore
index e0af7f0..f56473d 100644
--- a/development/build_log_simplifier/messages.ignore
+++ b/development/build_log_simplifier/messages.ignore
@@ -720,13 +720,3 @@
 w: file://\$SUPPORT/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/window/PopupTestUtils\.kt:[0-9]+:[0-9]+ 'getter for windowLayoutParams: EspressoOptional<WindowManager\.LayoutParams!>!' is deprecated\. Deprecated in Java
 # b/271306193 remove after aosp/2589888 :emoji:emoji:spdxSbomForRelease
 spdx sboms require a version but project: noto\-emoji\-compat\-flatbuffers has no specified version
-# > Configure project :androidx-demos
-WARNING: The option setting 'android\.experimental\.disableCompileSdkChecks=true' is experimental\.
-The current default is 'false'\.
-WARNING: The option setting 'android\.r[0-9]+\.maxWorkers=[0-9]+' is experimental\.
-# > Task :compose:ui:ui:compileReleaseKotlinAndroid
-e: Daemon compilation failed: Could not connect to Kotlin compile daemon
-java\.lang\.RuntimeException: Could not connect to Kotlin compile daemon
-Errors were stored into \$SUPPORT/\.gradle/kotlin/errors/errors\-[0-9]+\.log
-# > Task :vectordrawable:integration-tests:testapp:createReleaseCompatibleScreenManifests
-exception: info: \[ksp\] loaded provider\(s\): \[androidx\.room\.RoomKspProcessor\$Provider\]
diff --git a/development/importMaven/importMaven.sh b/development/importMaven/importMaven.sh
index 91a8fc8..6e4b96f 100755
--- a/development/importMaven/importMaven.sh
+++ b/development/importMaven/importMaven.sh
@@ -3,7 +3,18 @@
 set -e
 WORKING_DIR=`pwd`
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
+ALLOW_JETBRAINS_DEV="false"
+
+for arg in "$@"
+do
+    if [ "$arg" == "--allow-jetbrains-dev" ]; then
+      ALLOW_JETBRAINS_DEV="true"
+    fi
+done
+
 # build importMaven
-(cd $SCRIPT_DIR && ./gradlew installDist -q)
+(cd $SCRIPT_DIR && ./gradlew installDist -q -Pandroidx.allowJetbrainsDev="$ALLOW_JETBRAINS_DEV")
+
+
 # execute the output binary
 (SUPPORT_REPO=$SCRIPT_DIR/../.. $SCRIPT_DIR/build/install/importMaven/bin/importMaven $@)
\ No newline at end of file
diff --git a/development/importMaven/settings.gradle.kts b/development/importMaven/settings.gradle.kts
index 3813656..92b125d 100644
--- a/development/importMaven/settings.gradle.kts
+++ b/development/importMaven/settings.gradle.kts
@@ -19,6 +19,10 @@
         mavenCentral()
         gradlePluginPortal()
         google()
+
+        if (settings.extra.get("androidx.allowJetbrainsDev") == "true") {
+            maven(url = "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/")
+        }
     }
 }
 
@@ -27,6 +31,10 @@
         mavenCentral()
         google()
         gradlePluginPortal()
+
+        if (settings.extra.get("androidx.allowJetbrainsDev") == "true") {
+            maven(url = "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev/")
+        }
     }
     versionCatalogs {
         create("importMavenLibs") {
diff --git a/development/plot-benchmarks/src/lib/Chart.svelte b/development/plot-benchmarks/src/lib/Chart.svelte
index 9a224e2..175da99 100644
--- a/development/plot-benchmarks/src/lib/Chart.svelte
+++ b/development/plot-benchmarks/src/lib/Chart.svelte
@@ -1,16 +1,19 @@
 <script lang="ts">
-  import type { ChartType, LegendItem } from "chart.js";
+  import type { ChartType, LegendItem, Point, TooltipItem } from "chart.js";
   import { Chart } from "chart.js/auto";
-  import { onMount } from "svelte";
+  import { createEventDispatcher, onMount } from "svelte";
   import { writable, type Writable } from "svelte/store";
-  import type { Data } from "../types/chart.js";
-  import { LegendPlugin } from "../plugins.js";
-  import Legend from "./Legend.svelte";
   import { saveToClipboard as save } from "../clipboard.js";
+  import { LegendPlugin } from "../plugins.js";
+  import type { Data } from "../types/chart.js";
+  import type { Controls, ControlsEvent } from "../types/events.js";
+  import Legend from "./Legend.svelte";
+  import { isSampled } from "../transforms/standard-mappers.js";
 
   export let data: Data;
   export let chartType: ChartType = "line";
   export let isExperimental: boolean = false;
+  export let showHistogramControls: boolean = false;
 
   $: {
     if ($chart) {
@@ -20,7 +23,9 @@
   }
 
   // State
+  let controlsDispatcher = createEventDispatcher<ControlsEvent>();
   let element: HTMLCanvasElement;
+  let buckets: Writable<number> = writable(100);
   let chart: Writable<Chart | null> = writable(null);
   let items: Writable<LegendItem[] | null> = writable(null);
 
@@ -33,6 +38,24 @@
       $items = legend.labels.generateLabels(chart);
     };
     const plugins = {
+      tooltip: {
+        callbacks: {
+          label: (context: TooltipItem<typeof chartType>): string | null => {
+            // TODO: Configure Tooltips
+            // https://www.chartjs.org/docs/latest/configuration/tooltip.html
+            const label = context.dataset.label;
+            const rp = context.raw as Point;
+            const frequency = context.parsed.y;
+            if (isSampled(label)) {
+              const fx = rp.x.toFixed(2);
+              return `${label}: ${fx} F(${frequency})`;
+            } else {
+              // Fallback to default behavior
+              return undefined;
+            }
+          },
+        },
+      },
       legend: {
         display: false,
       },
@@ -56,6 +79,18 @@
       await save($chart);
     }
   }
+
+  function onHistogramChanged(event: Event) {
+    const element = event.target as EventTarget & HTMLInputElement;
+    const oldValue = $buckets;
+    $buckets = parseInt(element.value, 10);
+    if (oldValue != $buckets) {
+      let controls: Controls = {
+        buckets: $buckets,
+      };
+      controlsDispatcher("controls", controls);
+    }
+  }
 </script>
 
 <article>
@@ -69,6 +104,24 @@
     </button>
   </div>
   <canvas class="chart" bind:this={element} />
+  {#if showHistogramControls}
+    <div class="controls">
+      <label for="buckets">
+        Histogram
+        <input
+          type="range"
+          data-tooltip={$buckets}
+          data-placement="right"
+          min="10"
+          max="250"
+          value={$buckets}
+          id="buckets"
+          name="buckets"
+          on:change={onHistogramChanged}
+        />
+      </label>
+    </div>
+  {/if}
   {#if isExperimental}
     <footer class="slim">
       <section class="experimental">
@@ -92,19 +145,20 @@
     flex-direction: row;
     justify-content: flex-end;
   }
-
   .toolbar .btn {
     width: auto;
     height: auto;
     border: none;
     padding: 5px;
   }
-
+  .controls {
+    margin-top: 20px;
+    width: 100%;
+  }
   .slim {
     margin-bottom: 0px;
     padding: 0;
   }
-
   .experimental {
     display: flex;
     flex-direction: row;
diff --git a/development/plot-benchmarks/src/lib/Session.svelte b/development/plot-benchmarks/src/lib/Session.svelte
index e70f88c..25576af 100644
--- a/development/plot-benchmarks/src/lib/Session.svelte
+++ b/development/plot-benchmarks/src/lib/Session.svelte
@@ -1,29 +1,33 @@
 <script lang="ts">
+  import type { Remote } from "comlink";
   import { createEventDispatcher } from "svelte";
   import {
-    writable,
-    type Readable,
-    type Writable,
-    derived,
+      derived,
+      writable,
+      type Readable,
+      type Writable,
   } from "svelte/store";
   import { readBenchmarks } from "../files.js";
-  import { ChartDataTransforms } from "../transforms/data-transforms.js";
+  import {
+      ChartDataTransforms,
+      type Mapper,
+  } from "../transforms/data-transforms.js";
   import { Transforms } from "../transforms/metric-transforms.js";
-  import { STANDARD_MAPPER } from "../transforms/standard-mappers.js";
+  import { buildMapper } from "../transforms/standard-mappers.js";
   import type { Data, Series } from "../types/chart.js";
   import type { Metrics } from "../types/data.js";
   import type {
-    FileMetadataEvent,
-    DatasetSelection,
-    StatInfo,
-    MetricSelection,
+      Controls,
+      DatasetSelection,
+      FileMetadataEvent,
+      MetricSelection,
+      StatInfo,
   } from "../types/events.js";
   import type { FileMetadata } from "../types/files.js";
+  import type { StatService } from "../workers/service.js";
   import { Session, type IndexedWrapper } from "../wrappers/session.js";
   import Chart from "./Chart.svelte";
   import Group from "./Group.svelte";
-  import type { StatService } from "../workers/service.js";
-  import type { Remote } from "comlink";
 
   export let fileEntries: FileMetadata[];
   export let service: Remote<StatService>;
@@ -31,14 +35,18 @@
   // State
   let eventDispatcher = createEventDispatcher<FileMetadataEvent>();
   let session: Session;
+  let mapper: Mapper<number>;
   let metrics: Metrics<number>;
   let series: Series[];
   let chartData: Data;
   let classGroups: Record<string, IndexedWrapper[]>;
+  let showControls: boolean;
   let size: number;
   let activeSeries: Promise<Series[]>;
 
   // Stores
+  let buckets: Writable<number> = writable(100);
+  let normalizeMetrics: Writable<boolean> = writable(false);
   let activeDragDrop: Writable<boolean> = writable(false);
   let suppressed: Writable<Set<string>> = writable(new Set());
   let suppressedMetrics: Writable<Set<string>> = writable(new Set());
@@ -97,11 +105,22 @@
     }
   };
 
+  let controlsHandler = function (event: CustomEvent<Controls>) {
+    const controls: Controls = event.detail;
+    $buckets = controls.buckets;
+  };
+
   $: {
     session = new Session(fileEntries);
+    mapper = buildMapper($buckets);
     metrics = Transforms.buildMetrics(session, $suppressed, $suppressedMetrics);
+    showControls = metrics.sampled && metrics.sampled.length > 0;
     activeSeries = service.pSeries(metrics, $active);
-    series = ChartDataTransforms.mapToSeries(metrics, STANDARD_MAPPER);
+    series = ChartDataTransforms.mapToSeries(
+      metrics,
+      mapper,
+      $normalizeMetrics
+    );
     chartData = ChartDataTransforms.mapToDataset(series);
     classGroups = session.classGroups;
     size = session.fileNames.size;
@@ -127,22 +146,24 @@
 
   async function handleFileDragDrop(event: DragEvent) {
     const items = [...event.dataTransfer.items];
-    const newFiles: FileMetadata[] = [];
     if (items) {
-      for (let i = 0; i < items.length; i += 1) {
-        if (items[i].kind === "file") {
-          const file = items[i].getAsFile();
-          if (file.name.endsWith(".json")) {
+      let newFiles = await Promise.all(
+        items
+          .filter(
+            (item) =>
+              item.kind === "file" && item.getAsFile().name.endsWith(".json")
+          )
+          .map(async (item) => {
+            const file = item.getAsFile();
             const benchmarks = await readBenchmarks(file);
             const entry: FileMetadata = {
               enabled: true,
               file: file,
               container: benchmarks,
             };
-            newFiles.push(entry);
-          }
-        }
-      }
+            return entry;
+          })
+      );
       // Deep copy & notify
       eventDispatcher("entries", [...fileEntries, ...newFiles]);
     }
@@ -169,6 +190,24 @@
     on:dragover={onDragOver}
     on:dragleave={onDragLeave}
   >
+    {#if showControls}
+      <div class="toolbar">
+        <div class="control">
+          <label for="normalize">
+            <input
+              type="checkbox"
+              id="normalize"
+              name="normalize"
+              data-tooltip="Normalize Metrics"
+              on:change={(_) => {
+                $normalizeMetrics = !$normalizeMetrics;
+              }}
+            />
+            ≃
+          </label>
+        </div>
+      </div>
+    {/if}
     <h5>Benchmarks</h5>
     {#each Object.entries(classGroups) as [className, wrappers]}
       <Group
@@ -183,7 +222,11 @@
   </article>
 
   {#if series.length > 0}
-    <Chart data={chartData} />
+    <Chart
+      data={chartData}
+      showHistogramControls={showControls}
+      on:controls={controlsHandler}
+    />
   {/if}
 
   {#await activeSeries}
@@ -199,6 +242,13 @@
 {/if}
 
 <style>
+  .toolbar {
+    padding: 0;
+    margin: 2rem;
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-end;
+  }
   .active {
     outline: beige;
     outline-style: dashed;
diff --git a/development/plot-benchmarks/src/transforms/data-transforms.ts b/development/plot-benchmarks/src/transforms/data-transforms.ts
index c176da9..52b2926 100644
--- a/development/plot-benchmarks/src/transforms/data-transforms.ts
+++ b/development/plot-benchmarks/src/transforms/data-transforms.ts
@@ -14,12 +14,16 @@
  */
 export class ChartDataTransforms {
 
-  static mapToSeries(metrics: Metrics<number>, mapper: Mapper<number>): Series[] {
+  static mapToSeries(metrics: Metrics<number>, mapper: Mapper<number>, normalize: boolean = false): Series[] {
     const series: Series[] = [];
     const standard = metrics.standard;
     const sampled = metrics.sampled;
-    // Builds ranges for distribution
-    const ranges = mapper.sampledRanges(metrics);
+    // Builds ranges for distribution.
+    let ranges: Record<string, Range> = {};
+    if (normalize) {
+      ranges = mapper.sampledRanges(metrics);
+    }
+    // Builds series.
     if (standard) {
       for (let i = 0; i < standard.length; i += 1) {
         const metric = standard[i];
@@ -53,7 +57,7 @@
 
   private static chartDataset<T extends ChartType>(series: Series): ChartDataset {
     return {
-      label: series.label,
+      label: series.descriptiveLabel,
       type: series.type,
       data: series.data,
       ...series.options
diff --git a/development/plot-benchmarks/src/transforms/standard-mappers.ts b/development/plot-benchmarks/src/transforms/standard-mappers.ts
index 11baf19..df74b8f9 100644
--- a/development/plot-benchmarks/src/transforms/standard-mappers.ts
+++ b/development/plot-benchmarks/src/transforms/standard-mappers.ts
@@ -3,6 +3,8 @@
 import type { ChartData, Metric, Metrics, Range } from "../types/data.js";
 import type { Mapper } from "./data-transforms.js";
 
+const SAMPLED_SUFFIX = '(S)';
+
 function sampledRanges(metrics: Metrics<number>): Record<string, Range> {
   const ranges: Record<string, Range> = {};
   const sampled = metrics.sampled;
@@ -37,16 +39,16 @@
   return ranges;
 }
 
-function sampledMapper(metric: Metric<number[]>, range: Range | null): Series[] {
+function sampledMapper(metric: Metric<number[]>, buckets: number, range: Range | null): Series[] {
   const series: Series[] = [];
   const data: Record<string, ChartData<number[]>> = metric.data;
   const entries = Object.entries(data);
   for (let i = 0; i < entries.length; i += 1) {
     const [source, chartData] = entries[i];
-    const label = labelFor(metric, source);
-    const [points, _, __] = histogramPoints(chartData.values, /* buckets */ undefined, /* target */ undefined, range);
+    const label = labelFor(metric, source, true);
+    const [points, _, __] = histogramPoints(chartData.values, buckets, /* target */ undefined, range);
     series.push({
-      label: label,
+      descriptiveLabel: label,
       type: "line",
       data: points,
       options: {
@@ -63,10 +65,10 @@
   const entries = Object.entries(data);
   for (let i = 0; i < entries.length; i += 1) {
     const [source, chartData] = entries[i];
-    const label = labelFor(metric, source);
+    const label = labelFor(metric, source, false);
     const points = singlePoints(chartData.values);
     series.push({
-      label: label,
+      descriptiveLabel: label,
       type: "line",
       data: points,
       options: {
@@ -104,9 +106,13 @@
   let pMin: number = 0;
   let pMax: number = 0;
   let maxFreq: number = 0;
-  const histogram = new Array(buckets).fill(0);
+  const histogram: Point[] = new Array(buckets).fill(null);
   // The actual number of slots in the histogram
   const slots = buckets - 1;
+  for (let i = 0; i < buckets; i += 1) {
+    const interpolated = interpolate(i / slots, min, max);
+    histogram[i] = { x: interpolated, y: 0 };
+  }
   for (let i = 0; i < flattened.length; i += 1) {
     const value = flattened[i];
     if (target && value < target) {
@@ -117,9 +123,9 @@
     }
     const n = normalize(value, min, max);
     const index = Math.ceil(n * slots);
-    histogram[index] = histogram[index] + 1;
-    if (maxFreq < histogram[index]) {
-      maxFreq = histogram[index];
+    histogram[index].y = histogram[index].y + 1;
+    if (maxFreq < histogram[index].y) {
+      maxFreq = histogram[index].y;
     }
   }
   if (target) {
@@ -129,7 +135,7 @@
   }
   // Pay attention to both sides of the normal distribution.
   let p = Math.min(pMin / flattened.length, pMax / flattened.length);
-  return [singlePoints(histogram), targetPoints, p];
+  return [histogram, targetPoints, p];
 }
 
 function selectPoints(buckets: number, index: number, target: number) {
@@ -168,7 +174,7 @@
   return (n - min) / ((max - min) + 1e-9);
 }
 
-function interpolate(normalized: number, min: number, max: number) {
+function interpolate(normalized: number, min: number, max: number): number {
   const range = max - min;
   const value = normalized * range;
   return value + min;
@@ -177,8 +183,9 @@
 /**
  * Generates a series label.
  */
-function labelFor<T>(metric: Metric<T>, source: string): string {
-  return `${source} {${metric.class} ${metric.benchmark}} - ${metric.label}`;
+function labelFor<T>(metric: Metric<T>, source: string, sampled: boolean): string {
+  const suffix = sampled ? SAMPLED_SUFFIX : '';
+  return `${source} {${metric.class} ${metric.benchmark}} - ${metric.label} ${suffix}`;
 }
 
 export function datasetName(metric: Metric<any>): string {
@@ -190,15 +197,40 @@
  * comparing equal distributions.
  */
 function rangeLabel(metric: Metric<unknown>): string {
-  return `${metric.benchmark}>${metric.label}`;
+  return `${metric.label}`;
 }
 
 /**
- * The standard mapper.
+ * The Standard Mapper.
  */
-export const STANDARD_MAPPER: Mapper = {
-  rangeLabel: rangeLabel,
-  standard: standardMapper,
-  sampled: sampledMapper,
-  sampledRanges: sampledRanges
-};
+class StandardMapper {
+  constructor(private buckets: number) {
+    // Does nothing.
+  }
+  // Delegate
+  rangeLabel(metric: Metric<unknown>): string {
+    return rangeLabel(metric);
+  }
+  standard(metric: Metric<number>): Series[] {
+    return standardMapper(metric);
+  }
+  sampled(metric: Metric<number[]>, range: Range | null): Series[] {
+    return sampledMapper(metric, this.buckets, range);
+  }
+  sampledRanges(metrics: Metrics<number>): Record<string, Range> {
+    return sampledRanges(metrics);
+  }
+}
+
+/**
+ * Builds a Standard mapper.
+ * @param buckets are the number of buckets in the histogram to use.
+ * @return an instance of `Mapper`.
+ */
+export function buildMapper(buckets: number): Mapper<number> {
+  return new StandardMapper(buckets);
+}
+
+export function isSampled(label: string | null | undefined): boolean {
+  return label && label.indexOf(SAMPLED_SUFFIX) >= 0;
+}
diff --git a/development/plot-benchmarks/src/types/chart.ts b/development/plot-benchmarks/src/types/chart.ts
index 0d77b63..c5f8cb5 100644
--- a/development/plot-benchmarks/src/types/chart.ts
+++ b/development/plot-benchmarks/src/types/chart.ts
@@ -18,9 +18,9 @@
  * Used by a Mapper for data transformations.
  */
 export interface Series {
-  label: string;
+  descriptiveLabel: string;
   type: ChartType;
-  data: Array<Point>;
+  data: Point[];
   // Additional series options
   // For e.g. https://www.chartjs.org/docs/latest/charts/line.html
   options: object;
diff --git a/development/plot-benchmarks/src/types/events.ts b/development/plot-benchmarks/src/types/events.ts
index 72890d4..f98f9ed 100644
--- a/development/plot-benchmarks/src/types/events.ts
+++ b/development/plot-benchmarks/src/types/events.ts
@@ -31,3 +31,11 @@
 export interface StatEvent {
   info: StatInfo[];
 }
+
+export interface ControlsEvent {
+  controls: Controls;
+}
+
+export interface Controls {
+  buckets: number;
+}
diff --git a/development/plot-benchmarks/src/workers/service.ts b/development/plot-benchmarks/src/workers/service.ts
index 90ff9a5..3373353 100644
--- a/development/plot-benchmarks/src/workers/service.ts
+++ b/development/plot-benchmarks/src/workers/service.ts
@@ -27,9 +27,9 @@
                 continue;
               }
               const [delta, distribution] = this.buildDistribution(reference, target);
-              const [points, pPlots, p] = histogramPoints([distribution], 100, delta);
+              const [points, pPlots, p] = histogramPoints([distribution], /* buckets */ 100, /* target */ delta);
               series.push({
-                label: `${name} { ${metric.label} } - Likelihood`,
+                descriptiveLabel: `${name} { ${metric.label} } - Likelihood`,
                 type: "line",
                 data: points,
                 options: {
@@ -38,7 +38,7 @@
               });
               if (pPlots && pPlots.length > 0) {
                 series.push({
-                  label: `${name} { ${metric.label} } - { P = ${p} }`,
+                  descriptiveLabel: `${name} { ${metric.label} } - { P = ${p} }`,
                   type: "bar",
                   data: pPlots,
                   options: {
@@ -67,9 +67,9 @@
                 continue;
               }
               const [delta, distribution] = this.buildStandardDistribution(reference, target);
-              const [points, pPlots, p] = histogramPoints([distribution], 100, delta);
+              const [points, pPlots, p] = histogramPoints([distribution], /* buckets */ 100, /* target */ delta);
               series.push({
-                label: `${name} { ${metric.label} } - Likelihood`,
+                descriptiveLabel: `${name} { ${metric.label} } - Likelihood`,
                 type: "line",
                 data: points,
                 options: {
@@ -78,7 +78,7 @@
               });
               if (pPlots && pPlots.length > 0) {
                 series.push({
-                  label: `${name} { ${metric.label} } - { P = ${p} }`,
+                  descriptiveLabel: `${name} { ${metric.label} } - { P = ${p} }`,
                   type: "bar",
                   data: pPlots,
                   options: {
diff --git a/development/update-verification-metadata.sh b/development/update-verification-metadata.sh
index 28af6f5..7023439 100755
--- a/development/update-verification-metadata.sh
+++ b/development/update-verification-metadata.sh
@@ -17,7 +17,8 @@
   echo "regenerating verification metadata and keyring"
   # regenerate metadata
   # Need to run a clean build, https://github.com/gradle/gradle/issues/19228
-  runGradle --stacktrace --write-verification-metadata pgp,sha256 --export-keys --dry-run --clean -Pandroidx.update.signatures=true bOS
+  # Resolving Configurations before task execution is expected. b/297394547
+  runGradle --stacktrace --write-verification-metadata pgp,sha256 --export-keys --dry-run --clean -Pandroidx.update.signatures=true -Pandroid.dependencyResolutionAtConfigurationTime.disallow=false bOS
 
   # update verification metadata file
   # also remove 'version=' lines, https://github.com/gradle/gradle/issues/20192
diff --git a/development/update_kotlin.sh b/development/update_kotlin.sh
index a5c3673..ec61013 100755
--- a/development/update_kotlin.sh
+++ b/development/update_kotlin.sh
@@ -1,21 +1,27 @@
 #!/bin/bash
 set -e
 
-export KOTLIN_VERSION="1.9.0-dev-6188"
-
-# Download and place konan
-export KONAN_DIR=../../prebuilts/androidx/konan/nativeCompilerPrebuilts/dev/$KOTLIN_VERSION/linux-x86_64
-mkdir -p $KONAN_DIR
-curl -o $KONAN_DIR/kotlin-native-prebuilt-linux-x86_64-$KOTLIN_VERSION.tar.gz https://download-cf.jetbrains.com/kotlin/native/builds/dev/$KOTLIN_VERSION/linux-x86_64/kotlin-native-prebuilt-linux-x86_64-$KOTLIN_VERSION.tar.gz
+KOTLIN_VERSION="$1"
 
 # Download maven artifacts
 ARTIFACTS_TO_DOWNLOAD="org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION,"
 ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:$KOTLIN_VERSION,"
 ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin.plugin.serialization:org.jetbrains.kotlin.plugin.serialization.gradle.plugin:$KOTLIN_VERSION,"
-ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlinx-serialization-compiler-plugin-embeddable:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-serialization-compiler-plugin-embeddable:$KOTLIN_VERSION,"
 ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-test:$KOTLIN_VERSION,"
 ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-test-junit:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-stdlib-common:$KOTLIN_VERSION,"
 ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-stdlib-jdk8:$KOTLIN_VERSION,"
-ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:$KOTLIN_VERSION"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-klib-commonizer-embeddable:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-compiler:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-compiler-embeddable:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-annotation-processing-embeddable:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-parcelize-runtime:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-annotation-processing-gradle:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-parcelize-compiler:$KOTLIN_VERSION,"
+ARTIFACTS_TO_DOWNLOAD+="org.jetbrains.kotlin:kotlin-bom:$KOTLIN_VERSION,"
 
 ./development/importMaven/importMaven.sh --allow-jetbrains-dev "$ARTIFACTS_TO_DOWNLOAD"
+
+# Import konan binaries
+./development/importMaven/importMaven.sh import-konan-binaries --konan-compiler-version "$KOTLIN_VERSION"
diff --git a/development/update_studio.sh b/development/update_studio.sh
index 74fc2b3..2239505 100755
--- a/development/update_studio.sh
+++ b/development/update_studio.sh
@@ -7,8 +7,8 @@
 
 # Get versions
 echo Getting Studio version and link
-AGP_VERSION=${1:-8.2.0-alpha15}
-STUDIO_VERSION_STRING=${2:-"Android Studio Hedgehog | 2023.1.1 Canary 15"}
+AGP_VERSION=${1:-8.2.0-beta01}
+STUDIO_VERSION_STRING=${2:-"Android Studio Hedgehog | 2023.1.1 Beta 1"}
 STUDIO_IFRAME_LINK=`curl "https://developer.android.com/studio/archive.html" | grep "<iframe " | sed "s/.* src=\"\([^\"]*\)\".*/\1/g"`
 echo iframe link $STUDIO_IFRAME_LINK
 STUDIO_IFRAME_REDIRECT=`curl -s $STUDIO_IFRAME_LINK | grep href | sed 's/.*href="\([^"]*\)".*/\1/g'`
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index d255123..1c2c888 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -8,15 +8,15 @@
 }
 
 dependencies {
-    docs("androidx.activity:activity:1.8.0-alpha06")
-    docs("androidx.activity:activity-compose:1.8.0-alpha06")
-    samples("androidx.activity:activity-compose-samples:1.8.0-alpha06")
-    docs("androidx.activity:activity-ktx:1.8.0-alpha06")
+    docs("androidx.activity:activity:1.8.0-alpha07")
+    docs("androidx.activity:activity-compose:1.8.0-alpha07")
+    samples("androidx.activity:activity-compose-samples:1.8.0-alpha07")
+    docs("androidx.activity:activity-ktx:1.8.0-alpha07")
     // ads-identifier is deprecated
     docsWithoutApiSince("androidx.ads:ads-identifier:1.0.0-alpha05")
     docsWithoutApiSince("androidx.ads:ads-identifier-common:1.0.0-alpha05")
     docsWithoutApiSince("androidx.ads:ads-identifier-provider:1.0.0-alpha05")
-    kmpDocs("androidx.annotation:annotation:1.7.0-beta01")
+    kmpDocs("androidx.annotation:annotation:1.7.0-rc01")
     docs("androidx.annotation:annotation-experimental:1.4.0-alpha01")
     docs("androidx.appcompat:appcompat:1.7.0-alpha03")
     docs("androidx.appcompat:appcompat-resources:1.7.0-alpha03")
@@ -32,26 +32,27 @@
     docs("androidx.asynclayoutinflater:asynclayoutinflater:1.1.0-alpha01")
     docs("androidx.asynclayoutinflater:asynclayoutinflater-appcompat:1.1.0-alpha01")
     docs("androidx.autofill:autofill:1.3.0-alpha01")
-    docs("androidx.benchmark:benchmark-common:1.2.0-beta03")
-    docs("androidx.benchmark:benchmark-junit4:1.2.0-beta03")
-    docs("androidx.benchmark:benchmark-macro:1.2.0-beta03")
-    docs("androidx.benchmark:benchmark-macro-junit4:1.2.0-beta03")
+    docs("androidx.benchmark:benchmark-common:1.2.0-beta04")
+    docs("androidx.benchmark:benchmark-junit4:1.2.0-beta04")
+    docs("androidx.benchmark:benchmark-macro:1.2.0-beta04")
+    docs("androidx.benchmark:benchmark-macro-junit4:1.2.0-beta04")
     docs("androidx.biometric:biometric:1.2.0-alpha05")
     docs("androidx.biometric:biometric-ktx:1.2.0-alpha05")
     samples("androidx.biometric:biometric-ktx-samples:1.2.0-alpha05")
     docs("androidx.browser:browser:1.6.0")
-    docs("androidx.camera:camera-camera2:1.3.0-beta02")
-    docs("androidx.camera:camera-core:1.3.0-beta02")
-    docs("androidx.camera:camera-extensions:1.3.0-beta02")
+    docs("androidx.camera:camera-camera2:1.3.0-rc01")
+    docs("androidx.camera:camera-core:1.3.0-rc01")
+    docs("androidx.camera:camera-extensions:1.3.0-rc01")
     stubs(fileTree(dir: "../camera/camera-extensions-stub", include: ["camera-extensions-stub.jar"]))
-    docs("androidx.camera:camera-lifecycle:1.3.0-beta02")
-    docs("androidx.camera:camera-mlkit-vision:1.3.0-beta02")
+    docs("androidx.camera:camera-lifecycle:1.3.0-rc01")
+    docs("androidx.camera:camera-mlkit-vision:1.3.0-rc01")
     // camera-previewview is not hosted in androidx
     docsWithoutApiSince("androidx.camera:camera-previewview:1.1.0-beta02")
-    docs("androidx.camera:camera-video:1.3.0-beta02")
-    docs("androidx.camera:camera-view:1.3.0-beta02")
-    docs("androidx.camera:camera-viewfinder:1.3.0-beta02")
-    docs("androidx.camera:camera-viewfinder-core:1.3.0-beta02")
+    docs("androidx.camera:camera-video:1.3.0-rc01")
+    docs("androidx.camera:camera-view:1.3.0-rc01")
+    docs("androidx.camera:camera-viewfinder:1.3.0-rc01")
+    docs("androidx.camera:camera-viewfinder-compose:1.3.0-rc01")
+    docs("androidx.camera:camera-viewfinder-core:1.3.0-rc01")
     docs("androidx.car.app:app:1.4.0-beta01")
     docs("androidx.car.app:app-automotive:1.4.0-beta01")
     docs("androidx.car.app:app-projected:1.4.0-beta01")
@@ -59,55 +60,55 @@
     docs("androidx.cardview:cardview:1.0.0")
     kmpDocs("androidx.collection:collection:1.3.0-beta01")
     docs("androidx.collection:collection-ktx:1.3.0-beta01")
-    kmpDocs("androidx.compose.animation:animation:1.6.0-alpha03")
-    kmpDocs("androidx.compose.animation:animation-core:1.6.0-alpha03")
-    kmpDocs("androidx.compose.animation:animation-graphics:1.6.0-alpha03")
-    samples("androidx.compose.animation:animation-samples:1.6.0-alpha03")
-    samples("androidx.compose.animation:animation-core-samples:1.6.0-alpha03")
-    samples("androidx.compose.animation:animation-graphics-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.foundation:foundation:1.6.0-alpha03")
-    kmpDocs("androidx.compose.foundation:foundation-layout:1.6.0-alpha03")
-    samples("androidx.compose.foundation:foundation-layout-samples:1.6.0-alpha03")
-    samples("androidx.compose.foundation:foundation-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.material3:material3:1.2.0-alpha05")
-    samples("androidx.compose.material3:material3-samples:1.2.0-alpha05")
-    kmpDocs("androidx.compose.material3:material3-window-size-class:1.2.0-alpha05")
-    samples("androidx.compose.material3:material3-window-size-class-samples:1.2.0-alpha05")
-    kmpDocs("androidx.compose.material:material:1.6.0-alpha03")
-    kmpDocs("androidx.compose.material:material-icons-core:1.6.0-alpha03")
-    samples("androidx.compose.material:material-icons-core-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.material:material-ripple:1.6.0-alpha03")
-    samples("androidx.compose.material:material-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.runtime:runtime:1.6.0-alpha03")
-    docs("androidx.compose.runtime:runtime-livedata:1.6.0-alpha03")
-    samples("androidx.compose.runtime:runtime-livedata-samples:1.6.0-alpha03")
-    docs("androidx.compose.runtime:runtime-rxjava2:1.6.0-alpha03")
-    samples("androidx.compose.runtime:runtime-rxjava2-samples:1.6.0-alpha03")
-    docs("androidx.compose.runtime:runtime-rxjava3:1.6.0-alpha03")
-    samples("androidx.compose.runtime:runtime-rxjava3-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.runtime:runtime-saveable:1.6.0-alpha03")
-    samples("androidx.compose.runtime:runtime-saveable-samples:1.6.0-alpha03")
-    samples("androidx.compose.runtime:runtime-samples:1.6.0-alpha03")
-    docs("androidx.compose.runtime:runtime-tracing:1.0.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-geometry:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-graphics:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-graphics-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-test:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-test-junit4:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-test-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-text:1.6.0-alpha03")
-    docs("androidx.compose.ui:ui-text-google-fonts:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-text-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-tooling:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-tooling-data:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-tooling-preview:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-unit:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-unit-samples:1.6.0-alpha03")
-    kmpDocs("androidx.compose.ui:ui-util:1.6.0-alpha03")
-    docs("androidx.compose.ui:ui-viewbinding:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-viewbinding-samples:1.6.0-alpha03")
-    samples("androidx.compose.ui:ui-samples:1.6.0-alpha03")
+    kmpDocs("androidx.compose.animation:animation:1.6.0-alpha04")
+    kmpDocs("androidx.compose.animation:animation-core:1.6.0-alpha04")
+    kmpDocs("androidx.compose.animation:animation-graphics:1.6.0-alpha04")
+    samples("androidx.compose.animation:animation-samples:1.6.0-alpha04")
+    samples("androidx.compose.animation:animation-core-samples:1.6.0-alpha04")
+    samples("androidx.compose.animation:animation-graphics-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.foundation:foundation:1.6.0-alpha04")
+    kmpDocs("androidx.compose.foundation:foundation-layout:1.6.0-alpha04")
+    samples("androidx.compose.foundation:foundation-layout-samples:1.6.0-alpha04")
+    samples("androidx.compose.foundation:foundation-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.material3:material3:1.2.0-alpha06")
+    samples("androidx.compose.material3:material3-samples:1.2.0-alpha06")
+    kmpDocs("androidx.compose.material3:material3-window-size-class:1.2.0-alpha06")
+    samples("androidx.compose.material3:material3-window-size-class-samples:1.2.0-alpha06")
+    kmpDocs("androidx.compose.material:material:1.6.0-alpha04")
+    kmpDocs("androidx.compose.material:material-icons-core:1.6.0-alpha04")
+    samples("androidx.compose.material:material-icons-core-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.material:material-ripple:1.6.0-alpha04")
+    samples("androidx.compose.material:material-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.runtime:runtime:1.6.0-alpha04")
+    docs("androidx.compose.runtime:runtime-livedata:1.6.0-alpha04")
+    samples("androidx.compose.runtime:runtime-livedata-samples:1.6.0-alpha04")
+    docs("androidx.compose.runtime:runtime-rxjava2:1.6.0-alpha04")
+    samples("androidx.compose.runtime:runtime-rxjava2-samples:1.6.0-alpha04")
+    docs("androidx.compose.runtime:runtime-rxjava3:1.6.0-alpha04")
+    samples("androidx.compose.runtime:runtime-rxjava3-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.runtime:runtime-saveable:1.6.0-alpha04")
+    samples("androidx.compose.runtime:runtime-saveable-samples:1.6.0-alpha04")
+    samples("androidx.compose.runtime:runtime-samples:1.6.0-alpha04")
+    docs("androidx.compose.runtime:runtime-tracing:1.0.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-geometry:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-graphics:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-graphics-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-test:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-test-junit4:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-test-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-text:1.6.0-alpha04")
+    docs("androidx.compose.ui:ui-text-google-fonts:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-text-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-tooling:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-tooling-data:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-tooling-preview:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-unit:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-unit-samples:1.6.0-alpha04")
+    kmpDocs("androidx.compose.ui:ui-util:1.6.0-alpha04")
+    docs("androidx.compose.ui:ui-viewbinding:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-viewbinding-samples:1.6.0-alpha04")
+    samples("androidx.compose.ui:ui-samples:1.6.0-alpha04")
     docs("androidx.concurrent:concurrent-futures:1.2.0-alpha02")
     docs("androidx.concurrent:concurrent-futures-ktx:1.2.0-alpha02")
     docs("androidx.constraintlayout:constraintlayout:2.2.0-alpha12")
@@ -124,17 +125,19 @@
     docs("androidx.core:core-ktx:1.12.0-rc01")
     docs("androidx.core:core-location-altitude:1.0.0-alpha01")
     docs("androidx.core:core-performance:1.0.0-alpha03")
+    docs("androidx.core:core-performance-play-services:1.0.0-alpha03")
     samples("androidx.core:core-performance-samples:1.0.0-alpha03")
+    docs("androidx.core:core-performance-testing:1.0.0-alpha03")
     docs("androidx.core:core-remoteviews:1.0.0-rc01")
     docs("androidx.core:core-role:1.2.0-alpha01")
     docs("androidx.core:core-splashscreen:1.1.0-alpha01")
     docs("androidx.core:core-telecom:1.0.0-alpha01")
     docs("androidx.core:core-testing:1.12.0-rc01")
-    docs("androidx.core.uwb:uwb:1.0.0-alpha06")
-    docs("androidx.core.uwb:uwb-rxjava3:1.0.0-alpha06")
-    docs("androidx.credentials:credentials:1.2.0-beta02")
-    docs("androidx.credentials:credentials-play-services-auth:1.2.0-beta02")
-    samples("androidx.credentials:credentials-samples:1.2.0-beta02")
+    docs("androidx.core.uwb:uwb:1.0.0-alpha07")
+    docs("androidx.core.uwb:uwb-rxjava3:1.0.0-alpha07")
+    docs("androidx.credentials:credentials:1.2.0-beta03")
+    docs("androidx.credentials:credentials-play-services-auth:1.2.0-beta03")
+    samples("androidx.credentials:credentials-samples:1.2.0-beta03")
     docs("androidx.cursoradapter:cursoradapter:1.0.0")
     docs("androidx.customview:customview:1.2.0-alpha02")
     // TODO(b/294531403): Turn on apiSince for customview-poolingcontainer when it releases as alpha
@@ -164,9 +167,9 @@
     docs("androidx.enterprise:enterprise-feedback:1.1.0")
     docs("androidx.enterprise:enterprise-feedback-testing:1.1.0")
     docs("androidx.exifinterface:exifinterface:1.3.6")
-    docs("androidx.fragment:fragment:1.7.0-alpha02")
-    docs("androidx.fragment:fragment-ktx:1.7.0-alpha02")
-    docs("androidx.fragment:fragment-testing:1.7.0-alpha02")
+    docs("androidx.fragment:fragment:1.7.0-alpha03")
+    docs("androidx.fragment:fragment-ktx:1.7.0-alpha03")
+    docs("androidx.fragment:fragment-testing:1.7.0-alpha03")
     docs("androidx.glance:glance:1.0.0-rc01")
     docs("androidx.glance:glance-appwidget:1.0.0-rc01")
     samples("androidx.glance:glance-appwidget-samples:1.0.0-rc01")
@@ -181,8 +184,7 @@
     docs("androidx.gridlayout:gridlayout:1.1.0-beta01")
     docs("androidx.health.connect:connect-client:1.1.0-alpha03")
     samples("androidx.health.connect:connect-client-samples:1.1.0-alpha03")
-    // TODO(b/294531403): Turn on apiSince for health-services-client when it releases as alpha
-    docsWithoutApiSince("androidx.health:health-services-client:1.1.0-alpha01")
+    docs("androidx.health:health-services-client:1.1.0-alpha01")
     docs("androidx.heifwriter:heifwriter:1.1.0-alpha02")
     docs("androidx.hilt:hilt-common:1.1.0-alpha01")
     docs("androidx.hilt:hilt-navigation:1.1.0-alpha02")
@@ -253,22 +255,22 @@
     docsWithoutApiSince("androidx.media3:media3-transformer:1.1.0")
     docsWithoutApiSince("androidx.media3:media3-ui:1.1.0")
     docsWithoutApiSince("androidx.media3:media3-ui-leanback:1.1.0")
-    docs("androidx.mediarouter:mediarouter:1.6.0-beta01")
-    docs("androidx.mediarouter:mediarouter-testing:1.6.0-beta01")
+    docs("androidx.mediarouter:mediarouter:1.6.0-rc01")
+    docs("androidx.mediarouter:mediarouter-testing:1.6.0-rc01")
     docs("androidx.metrics:metrics-performance:1.0.0-alpha04")
-    docs("androidx.navigation:navigation-common:2.7.0")
-    docs("androidx.navigation:navigation-common-ktx:2.7.0")
-    docs("androidx.navigation:navigation-compose:2.7.0")
-    samples("androidx.navigation:navigation-compose-samples:2.7.0")
-    docs("androidx.navigation:navigation-dynamic-features-fragment:2.7.0")
-    docs("androidx.navigation:navigation-dynamic-features-runtime:2.7.0")
-    docs("androidx.navigation:navigation-fragment:2.7.0")
-    docs("androidx.navigation:navigation-fragment-ktx:2.7.0")
-    docs("androidx.navigation:navigation-runtime:2.7.0")
-    docs("androidx.navigation:navigation-runtime-ktx:2.7.0")
-    docs("androidx.navigation:navigation-testing:2.7.0")
-    docs("androidx.navigation:navigation-ui:2.7.0")
-    docs("androidx.navigation:navigation-ui-ktx:2.7.0")
+    docs("androidx.navigation:navigation-common:2.7.1")
+    docs("androidx.navigation:navigation-common-ktx:2.7.1")
+    docs("androidx.navigation:navigation-compose:2.7.1")
+    samples("androidx.navigation:navigation-compose-samples:2.7.1")
+    docs("androidx.navigation:navigation-dynamic-features-fragment:2.7.1")
+    docs("androidx.navigation:navigation-dynamic-features-runtime:2.7.1")
+    docs("androidx.navigation:navigation-fragment:2.7.1")
+    docs("androidx.navigation:navigation-fragment-ktx:2.7.1")
+    docs("androidx.navigation:navigation-runtime:2.7.1")
+    docs("androidx.navigation:navigation-runtime-ktx:2.7.1")
+    docs("androidx.navigation:navigation-testing:2.7.1")
+    docs("androidx.navigation:navigation-ui:2.7.1")
+    docs("androidx.navigation:navigation-ui-ktx:2.7.1")
     docs("androidx.paging:paging-common:3.2.0")
     docs("androidx.paging:paging-common-ktx:3.2.0")
     docs("androidx.paging:paging-compose:3.2.0")
@@ -287,8 +289,8 @@
     docs("androidx.preference:preference:1.2.1")
     docs("androidx.preference:preference-ktx:1.2.1")
     docs("androidx.print:print:1.1.0-beta01")
-    docs("androidx.privacysandbox.ads:ads-adservices:1.1.0-alpha01")
-    docs("androidx.privacysandbox.ads:ads-adservices-java:1.1.0-alpha01")
+    docs("androidx.privacysandbox.ads:ads-adservices:1.1.0-beta01")
+    docs("androidx.privacysandbox.ads:ads-adservices-java:1.1.0-beta01")
     docs("androidx.privacysandbox.sdkruntime:sdkruntime-client:1.0.0-alpha08")
     docs("androidx.privacysandbox.sdkruntime:sdkruntime-core:1.0.0-alpha08")
     docs("androidx.privacysandbox.tools:tools:1.0.0-alpha05")
@@ -301,18 +303,18 @@
     docs("androidx.recyclerview:recyclerview-selection:2.0.0-alpha01")
     docs("androidx.remotecallback:remotecallback:1.0.0-alpha02")
     docs("androidx.resourceinspection:resourceinspection-annotation:1.0.1")
-    docs("androidx.room:room-common:2.6.0-alpha03")
-    docs("androidx.room:room-guava:2.6.0-alpha03")
-    docs("androidx.room:room-ktx:2.6.0-alpha03")
-    docs("androidx.room:room-migration:2.6.0-alpha03")
-    docs("androidx.room:room-paging:2.6.0-alpha03")
-    docs("androidx.room:room-paging-guava:2.6.0-alpha03")
-    docs("androidx.room:room-paging-rxjava2:2.6.0-alpha03")
-    docs("androidx.room:room-paging-rxjava3:2.6.0-alpha03")
-    docs("androidx.room:room-runtime:2.6.0-alpha03")
-    docs("androidx.room:room-rxjava2:2.6.0-alpha03")
-    docs("androidx.room:room-rxjava3:2.6.0-alpha03")
-    docs("androidx.room:room-testing:2.6.0-alpha03")
+    docs("androidx.room:room-common:2.6.0-beta01")
+    docs("androidx.room:room-guava:2.6.0-beta01")
+    docs("androidx.room:room-ktx:2.6.0-beta01")
+    docs("androidx.room:room-migration:2.6.0-beta01")
+    docs("androidx.room:room-paging:2.6.0-beta01")
+    docs("androidx.room:room-paging-guava:2.6.0-beta01")
+    docs("androidx.room:room-paging-rxjava2:2.6.0-beta01")
+    docs("androidx.room:room-paging-rxjava3:2.6.0-beta01")
+    docs("androidx.room:room-runtime:2.6.0-beta01")
+    docs("androidx.room:room-rxjava2:2.6.0-beta01")
+    docs("androidx.room:room-rxjava3:2.6.0-beta01")
+    docs("androidx.room:room-testing:2.6.0-beta01")
     docs("androidx.savedstate:savedstate:1.2.1")
     docs("androidx.savedstate:savedstate-ktx:1.2.1")
     docs("androidx.security:security-app-authenticator:1.0.0-alpha02")
@@ -326,9 +328,9 @@
     docs("androidx.slice:slice-core:1.1.0-alpha02")
     docs("androidx.slice:slice-view:1.1.0-alpha02")
     docs("androidx.slidingpanelayout:slidingpanelayout:1.2.0")
-    docs("androidx.sqlite:sqlite:2.4.0-alpha03")
-    docs("androidx.sqlite:sqlite-framework:2.4.0-alpha03")
-    docs("androidx.sqlite:sqlite-ktx:2.4.0-alpha03")
+    docs("androidx.sqlite:sqlite:2.4.0-beta01")
+    docs("androidx.sqlite:sqlite-framework:2.4.0-beta01")
+    docs("androidx.sqlite:sqlite-ktx:2.4.0-beta01")
     docs("androidx.startup:startup-runtime:1.2.0-alpha02")
     docs("androidx.swiperefreshlayout:swiperefreshlayout:1.2.0-alpha01")
     // androidx.test is not hosted in androidx\
@@ -356,10 +358,10 @@
     docsWithoutApiSince("androidx.textclassifier:textclassifier:1.0.0-alpha04")
     docs("androidx.tracing:tracing:1.3.0-alpha02")
     docs("androidx.tracing:tracing-ktx:1.3.0-alpha02")
-    docs("androidx.tracing:tracing-perfetto:1.0.0-beta01")
+    docs("androidx.tracing:tracing-perfetto:1.0.0-beta02")
     // TODO(243405142) clean-up
     docsWithoutApiSince("androidx.tracing:tracing-perfetto-common:1.0.0-alpha16")
-    docs("androidx.tracing:tracing-perfetto-handshake:1.0.0-beta01")
+    docs("androidx.tracing:tracing-perfetto-handshake:1.0.0-beta02")
     docs("androidx.transition:transition:1.5.0-alpha01")
     docs("androidx.transition:transition-ktx:1.5.0-alpha01")
     docs("androidx.tv:tv-foundation:1.0.0-alpha08")
@@ -372,16 +374,16 @@
     docs("androidx.versionedparcelable:versionedparcelable:1.1.1")
     docs("androidx.viewpager2:viewpager2:1.1.0-beta02")
     docs("androidx.viewpager:viewpager:1.1.0-alpha01")
-    docs("androidx.wear.compose:compose-foundation:1.3.0-alpha03")
-    samples("androidx.wear.compose:compose-foundation-samples:1.3.0-alpha03")
-    docs("androidx.wear.compose:compose-material:1.3.0-alpha03")
-    docs("androidx.wear.compose:compose-material-core:1.3.0-alpha03")
-    samples("androidx.wear.compose:compose-material-samples:1.3.0-alpha03")
-    docs("androidx.wear.compose:compose-material3:1.0.0-alpha09")
-    samples("androidx.wear.compose:compose-material3-samples:1.3.0-alpha03")
-    docs("androidx.wear.compose:compose-navigation:1.3.0-alpha03")
-    samples("androidx.wear.compose:compose-navigation-samples:1.3.0-alpha03")
-    docs("androidx.wear.compose:compose-ui-tooling:1.3.0-alpha03")
+    docs("androidx.wear.compose:compose-foundation:1.3.0-alpha04")
+    samples("androidx.wear.compose:compose-foundation-samples:1.3.0-alpha04")
+    docs("androidx.wear.compose:compose-material:1.3.0-alpha04")
+    docs("androidx.wear.compose:compose-material-core:1.3.0-alpha04")
+    samples("androidx.wear.compose:compose-material-samples:1.3.0-alpha04")
+    docs("androidx.wear.compose:compose-material3:1.0.0-alpha10")
+    samples("androidx.wear.compose:compose-material3-samples:1.3.0-alpha04")
+    docs("androidx.wear.compose:compose-navigation:1.3.0-alpha04")
+    samples("androidx.wear.compose:compose-navigation-samples:1.3.0-alpha04")
+    docs("androidx.wear.compose:compose-ui-tooling:1.3.0-alpha04")
     docs("androidx.wear.protolayout:protolayout:1.0.0")
     docs("androidx.wear.protolayout:protolayout-expression:1.0.0")
     docs("androidx.wear.protolayout:protolayout-expression-pipeline:1.0.0")
@@ -392,20 +394,22 @@
     docs("androidx.wear.tiles:tiles-renderer:1.2.0")
     docs("androidx.wear.tiles:tiles-testing:1.2.0")
     docs("androidx.wear.tiles:tiles-tooling:1.2.0-alpha07")
-    docs("androidx.wear.watchface:watchface:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-client:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-client-guava:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-complications:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-complications-data:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-complications-data-source:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-complications-rendering:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-data:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-editor:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-editor-guava:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-guava:1.2.0-alpha09")
-    samples("androidx.wear.watchface:watchface-samples:1.2.0-alpha09")
-    docs("androidx.wear.watchface:watchface-style:1.2.0-alpha09")
+    docs("androidx.wear.watchface:watchface:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-client:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-client-guava:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-complications:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-complications-data:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-complications-data-source:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-complications-data-source-ktx:1.2.0-beta01")
+    samples("androidx.wear.watchface:watchface-complications-permission-dialogs-sample:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-complications-rendering:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-data:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-editor:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-editor-guava:1.2.0-beta01")
+    samples("androidx.wear.watchface:watchface-editor-samples:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-guava:1.2.0-beta01")
+    samples("androidx.wear.watchface:watchface-samples:1.2.0-beta01")
+    docs("androidx.wear.watchface:watchface-style:1.2.0-beta01")
     // TODO(b/294531403): Turn on apiSince for wear when it releases as alpha
     docsWithoutApiSince("androidx.wear:wear:1.3.0-rc01")
     stubs(fileTree(dir: "../wear/wear_stubs/", include: ["com.google.android.wearable-stubs.jar"]))
@@ -415,6 +419,7 @@
     docs("androidx.wear:wear-ongoing:1.1.0-alpha01")
     docs("androidx.wear:wear-phone-interactions:1.1.0-alpha03")
     docs("androidx.wear:wear-remote-interactions:1.1.0-alpha01")
+    docs("androidx.wear:wear-tooling-preview:1.0.0-alpha01")
     docs("androidx.webkit:webkit:1.8.0-rc01")
     docs("androidx.window.extensions.core:core:1.0.0")
     docs("androidx.window:window:1.2.0-beta01")
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index eabfc57..d65c0f9 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -87,6 +87,7 @@
     samples(project(":compose:foundation:foundation:foundation-samples"))
     kmpDocs(project(":compose:material3:material3"))
     kmpDocs(project(":compose:material3:material3-adaptive"))
+    samples(project(":compose:material3:material3-adaptive:material3-adaptive-samples"))
     samples(project(":compose:material3:material3:material3-samples"))
     kmpDocs(project(":compose:material3:material3-window-size-class"))
     samples(project(":compose:material3:material3-window-size-class:material3-window-size-class-samples"))
@@ -190,7 +191,9 @@
     docs(project(":fragment:fragment-testing"))
     docs(project(":glance:glance"))
     docs(project(":glance:glance-appwidget"))
+    docs(project(":glance:glance-appwidget-testing"))
     samples(project(":glance:glance-appwidget:glance-appwidget-samples"))
+    samples(project(":glance:glance-appwidget-testing:glance-appwidget-testing-samples"))
     docs(project(":glance:glance-appwidget-preview"))
     docs(project(":glance:glance-preview"))
     docs(project(":glance:glance-testing"))
diff --git a/docs/macrobenchmarking.md b/docs/macrobenchmarking.md
index 82b0e6f..11fe276 100644
--- a/docs/macrobenchmarking.md
+++ b/docs/macrobenchmarking.md
@@ -29,6 +29,10 @@
         <td>Min API 23</td>
         <td>Min API 14</td>
     </tr>
+    <tr>
+        <td>Relatively lower stability measurements</td>
+        <td>Higher stability measurements</td>
+    </tr>
 </table>
 
 The
@@ -41,7 +45,7 @@
 ### Writing the benchmark
 
 Benchmarks are just regular instrumentation tests! Just use the
-[`MacrobenchmarkRule`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:benchmark/macro-junit4/src/main/java/androidx/benchmark/macro/junit4/MacrobenchmarkRule.kt)
+[`MacrobenchmarkRule`](https://developer.android.com/reference/kotlin/androidx/benchmark/macro/junit4/MacrobenchmarkRule)
 provided by the library:
 
 <section class="tabs">
@@ -97,20 +101,20 @@
 ## Project structure
 
 As in the public documentation, macrobenchmarks in the AndroidX repo are
-comprised of an app, and a separate macrobenchmark module. Additional setups
-steps/constraints for the AndroidX repository are listed below.
+comprised of an app, and a separate macrobenchmark test module. In the AndroidX
+repository, there are additional requirements:
 
-1.  App and macrobenchmark modules must be unique, and map 1:1.
+1.  Macrobenchmark test module path in `settings.gradle` must end with
+    `macrobenchmark` to run in CI.
 
-1.  Target app path in `settings.gradle` must end with
-    `:integration-tests:macrobenchmark-target`.
+1.  Macrobenchmark target module path in `settings.gradle` must end with
+    `macrobenchmark-target` to follow convention.
 
-1.  Macrobenchmark library path must be at the same path, but instead ending
-    with `:integration-tests:macrobenchmark`
-
-1.  An entry should be placed in AffectedModuleDetector to recognize
-    macrobenchmark dependency on target app module,
-    [for example](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt;l=518;drc=cfb504756386b6225a2176d1d6efe2f55d4fa564)
+1.  Each library group should declare its own in-group macrobenchmark test and
+    app module. More than one is allowed, which is sometimes necessary to
+    compare different startup behaviors, see e.g.
+    `:emoji2:integration-tests:init-<disabled/enabled>-macrobenchmark-target`.
+    Note that comparing multiple app variants are not currently supported by CI.
 
 Compose Macrobenchmark Examples:
 
@@ -118,8 +122,6 @@
 
 *   [`:compose:integration-tests:macrobenchmark`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/integration-tests/macrobenchmark/)
 
-*   [AffectedModuleDetector Entry](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt;l=580;drc=10e32d25e9859bb5b37c303f42731015c82ee982)
-
 Note: Compose macrobenchmarks are generally duplicated with View system
 counterparts, defined in `:benchmark:integration-tests:macrobenchmark-target`.
 This is how we compare performance of the two systems.
@@ -133,20 +135,15 @@
     </tr>
     <tr>
         <td>Two modules in <code>settings.gradle</code></td>
-        <td>Both the macrobenchmark and target must be defined in sibling
-          modules</td>
+        <td>Both the macrobenchmark and target must be added for your group</td>
     </tr>
     <tr>
-        <td>The module name for the benchmark (test) module</td>
-        <td>It must match <code>/.*:integration-tests:.*macrobenchmark/</code></td>
+        <td>The module name for the benchmark (<code>com.android.test</code>) module</td>
+        <td>Must end with <code>macrobenchmark</code></td>
     </tr>
     <tr>
-        <td>The module name for the target (integration app) module</td>
-        <td>It must match <code>/.*:integration-tests:.*macrobenchmark-target</code></td>
-    </tr>
-    <tr>
-        <td>Register the modules in AffectedModuleDetector.kt</td>
-        <td>It must link the modules (see docs above)</td>
+        <td>The module name for the app (<code>com.android.app</code>) module</td>
+        <td>Must end with <code>macrobenchmark-target</code></td>
     </tr>
     <tr>
         <td>Name the test class in a discoverable way</td>
diff --git a/emoji/emoji/build.gradle b/emoji/emoji/build.gradle
index dfdcfb3..96514f5 100644
--- a/emoji/emoji/build.gradle
+++ b/emoji/emoji/build.gradle
@@ -4,7 +4,6 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("com.github.johnrengelman.shadow")
 }
 
 ext {
@@ -14,7 +13,8 @@
 BundleInsideHelper.forInsideAar(
     project,
     /* from = */ "com.google.flatbuffers",
-    /* to =   */ "androidx.text.emoji.flatbuffer"
+    /* to =   */ "androidx.text.emoji.flatbuffer",
+    /* dropResourcesWithSuffix = */ null
 )
 
 dependencies {
diff --git a/emoji2/emoji2-views/build.gradle b/emoji2/emoji2-views/build.gradle
index 1ae97c5..572be41 100644
--- a/emoji2/emoji2-views/build.gradle
+++ b/emoji2/emoji2-views/build.gradle
@@ -3,7 +3,6 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("com.github.johnrengelman.shadow")
 }
 
 dependencies {
diff --git a/emoji2/emoji2/build.gradle b/emoji2/emoji2/build.gradle
index bab57ea..4323a36 100644
--- a/emoji2/emoji2/build.gradle
+++ b/emoji2/emoji2/build.gradle
@@ -4,7 +4,6 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("com.github.johnrengelman.shadow")
 }
 
 BundleInsideHelper.forInsideAar(
@@ -14,7 +13,8 @@
                     "androidx.emoji2.text.flatbuffer"),
             new BundleInsideHelper.Relocation("androidx.text.emoji.flatbuffer",
                     "androidx.emoji2.text.flatbuffer")
-    ]
+    ],
+    /* dropResourcesWithSuffix = */ null
 )
 
 dependencies {
diff --git a/fragment/fragment-ktx/build.gradle b/fragment/fragment-ktx/build.gradle
index 975d1ec..2d4ccc62 100644
--- a/fragment/fragment-ktx/build.gradle
+++ b/fragment/fragment-ktx/build.gradle
@@ -25,7 +25,7 @@
 
 dependencies {
     api(project(":fragment:fragment"))
-    api(project(":activity:activity-ktx")) {
+    api(projectOrArtifact(":activity:activity-ktx")) {
         because "Mirror fragment dependency graph for -ktx artifacts"
     }
     api("androidx.core:core-ktx:1.2.0") {
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 3c05e24..f86aa12 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -29,7 +29,7 @@
     api("androidx.collection:collection:1.1.0")
     api("androidx.viewpager:viewpager:1.0.0")
     api("androidx.loader:loader:1.0.0")
-    api(project(":activity:activity"))
+    api(projectOrArtifact(":activity:activity"))
     api("androidx.lifecycle:lifecycle-runtime:2.6.1")
     api("androidx.lifecycle:lifecycle-livedata-core:2.6.1")
     api("androidx.lifecycle:lifecycle-viewmodel:2.6.1")
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionAnimTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionAnimTest.kt
index 91055a8..da7111d 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionAnimTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentTransitionAnimTest.kt
@@ -320,9 +320,9 @@
                 .commit()
             executePendingTransactions()
 
-            assertThat(fragment2.startTransitionCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
+            // We need to wait for the exit transitions to end
+            assertThat(fragment2.endTransitionCountDownLatch.await(1000, TimeUnit.MILLISECONDS))
                 .isTrue()
-            // We need to wait for the exit animation to end
             assertThat(
                 fragment1.endTransitionCountDownLatch.await(
                     1000,
@@ -340,7 +340,7 @@
             dispatcher.dispatchOnBackProgressed(
                 BackEventCompat(0.2F, 0.2F, 0.2F, BackEvent.EDGE_LEFT)
             )
-            dispatcher.onBackPressed()
+            withActivity { dispatcher.onBackPressed() }
             executePendingTransactions()
 
             fragment1.waitForTransition()
@@ -405,12 +405,7 @@
     companion object {
         @JvmStatic
         @Parameterized.Parameters(name = "ordering={0}")
-        fun data() = mutableListOf<Array<Any>>().apply {
-            arrayOf(
-                Ordered,
-                Reordered
-            )
-        }
+        fun data() = arrayOf(Ordered, Reordered)
 
         @AnimRes
         private val ENTER = 1
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PredictiveBackTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PredictiveBackTest.kt
index 5387810..b113b52 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/PredictiveBackTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/PredictiveBackTest.kt
@@ -73,4 +73,55 @@
             assertThat(fm.backStackEntryCount).isEqualTo(0)
         }
     }
+
+    @Test
+    fun backOnNoRecordDuringTransactionTest() {
+        withUse(ActivityScenario.launch(SimpleContainerActivity::class.java)) {
+            val fm = withActivity { supportFragmentManager }
+
+            val fragment1 = StrictViewFragment()
+
+            fm.beginTransaction()
+                .replace(R.id.fragmentContainer, fragment1, "1")
+                .setReorderingAllowed(true)
+                .addToBackStack(null)
+                .commit()
+            executePendingTransactions()
+
+            val fragment2 = StrictViewFragment()
+            fm.beginTransaction()
+                .replace(R.id.fragmentContainer, fragment2, "2")
+                .setReorderingAllowed(true)
+                .addToBackStack(null)
+                .commit()
+            executePendingTransactions()
+
+            assertThat(fm.backStackEntryCount).isEqualTo(2)
+
+            val dispatcher = withActivity { onBackPressedDispatcher }
+            withActivity {
+                dispatcher.dispatchOnBackStarted(
+                    BackEventCompat(
+                        0.1F,
+                        0.1F,
+                        0.1F,
+                        BackEvent.EDGE_LEFT
+                    )
+                )
+                dispatcher.onBackPressed()
+                dispatcher.dispatchOnBackStarted(
+                    BackEventCompat(
+                        0.1F,
+                        0.1F,
+                        0.1F,
+                        BackEvent.EDGE_LEFT
+                    )
+                )
+                dispatcher.onBackPressed()
+            }
+            executePendingTransactions()
+
+            assertThat(fm.backStackEntryCount).isEqualTo(0)
+        }
+    }
 }
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.kt b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.kt
index 4107c70..6240244 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.kt
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/DefaultSpecialEffectsController.kt
@@ -89,11 +89,10 @@
         }
 
         // Start transition special effects
-        val startedTransitions = createTransitionEffect(transitions, isPop, firstOut, lastIn)
-        val startedAnyTransition = startedTransitions.containsValue(true)
+        createTransitionEffect(transitions, isPop, firstOut, lastIn)
 
         // Collect Animation and Animator Effects
-        collectAnimEffects(animations, startedAnyTransition, startedTransitions)
+        collectAnimEffects(animations)
     }
 
     /**
@@ -114,12 +113,11 @@
     }
 
     @SuppressLint("NewApi", "PrereleaseSdkCoreDependency")
-    private fun collectAnimEffects(
-        animationInfos: List<AnimationInfo>,
-        startedAnyTransition: Boolean,
-        startedTransitions: Map<Operation, Boolean>
-    ) {
+    private fun collectAnimEffects(animationInfos: List<AnimationInfo>) {
         val animationsToRun = mutableListOf<AnimationInfo>()
+        val startedAnyTransition = animationInfos.flatMap {
+            it.operation.effects
+        }.isNotEmpty()
         var startedAnyAnimator = false
         // Find all Animators and add the effect to the operation
         for (animatorInfo: AnimationInfo in animationInfos) {
@@ -139,7 +137,7 @@
             // First make sure we haven't already started a Transition for this Operation
 
             val fragment = operation.fragment
-            val startedTransition = startedTransitions[operation] == true
+            val startedTransition = operation.effects.isNotEmpty()
             if (startedTransition) {
                 if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
                     Log.v(FragmentManager.TAG,
@@ -189,10 +187,7 @@
         isPop: Boolean,
         firstOut: Operation?,
         lastIn: Operation?
-    ): Map<Operation, Boolean> {
-        // Start transition special effects
-        val startedTransitions = mutableMapOf<Operation, Boolean>()
-
+    ) {
         // First verify that we can run all transitions together
         val transitionImpl = transitionInfos.filterNot { transitionInfo ->
             // If there is no change in visibility, we can skip the TransitionInfo
@@ -208,14 +203,8 @@
                     "type than other Fragments."
             }
             handlingImpl
-        }
-        if (transitionImpl == null) {
-            // There were no transitions at all so we can just complete all of them
-            for (transitionInfo: TransitionInfo in transitionInfos) {
-                startedTransitions[transitionInfo.operation] = false
-            }
-            return startedTransitions
-        }
+        } ?: // Early return if there were no transitions at all
+            return
 
         // Now find the shared element transition if it exists
         var sharedElementTransition: Any? = null
@@ -357,14 +346,12 @@
         val transitionEffect = TransitionEffect(
             transitionInfos, firstOut, lastIn, transitionImpl, sharedElementTransition,
             sharedElementFirstOutViews, sharedElementLastInViews, sharedElementNameMapping,
-            enteringNames, exitingNames, firstOutViews, lastInViews, isPop, startedTransitions
+            enteringNames, exitingNames, firstOutViews, lastInViews, isPop
         )
 
         transitionInfos.forEach { transitionInfo ->
             transitionInfo.operation.addEffect(transitionEffect)
         }
-
-        return startedTransitions
     }
 
     /**
@@ -709,8 +696,7 @@
         val exitingNames: ArrayList<String>,
         val firstOutViews: ArrayMap<String, View>,
         val lastInViews: ArrayMap<String, View>,
-        val isPop: Boolean,
-        val startedTransitions: MutableMap<Operation, Boolean>
+        val isPop: Boolean
     ) : Effect() {
         val transitionSignal = CancellationSignal()
 
@@ -775,10 +761,6 @@
                         // runs directly after the swap
                         transitionImpl.scheduleRemoveTargets(sharedElementTransition, null, null,
                             null, null, sharedElementTransition, sharedElementLastInViews)
-                        // Both the firstOut and lastIn Operations are now associated
-                        // with a Transition
-                        startedTransitions[firstOut] = true
-                        startedTransitions[lastIn] = true
                     }
                 }
             }
@@ -792,7 +774,6 @@
                 val operation: Operation = transitionInfo.operation
                 if (transitionInfo.isVisibilityUnchanged) {
                     // No change in visibility, so we can immediately complete the transition
-                    startedTransitions[transitionInfo.operation] = false
                     transitionInfo.operation.completeEffect(this)
                     continue
                 }
@@ -805,7 +786,6 @@
                         // Only complete the transition if this fragment isn't involved
                         // in the shared element transition (as otherwise we need to wait
                         // for that to finish)
-                        startedTransitions[operation] = false
                         transitionInfo.operation.completeEffect(this)
                     }
                 } else {
@@ -856,7 +836,6 @@
                     } else {
                         transitionImpl.setEpicenter(transition, firstOutEpicenterView)
                     }
-                    startedTransitions[operation] = true
                     // Now determine how this transition should be merged together
                     if (transitionInfo.isOverlapAllowed) {
                         // Overlap is allowed, so add them to the mergeTransition set
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
index b6ea42a..4a75436 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -470,6 +470,7 @@
                     if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                         Log.d(FragmentManager.TAG,
                                 "handleOnBackStarted. PREDICTIVE_BACK = " + USE_PREDICTIVE_BACK
+                                        + " fragment manager " + FragmentManager.this
                         );
                     }
                     if (USE_PREDICTIVE_BACK) {
@@ -482,6 +483,7 @@
                     if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
                         Log.v(FragmentManager.TAG,
                                 "handleOnBackProgressed. PREDICTIVE_BACK = " + USE_PREDICTIVE_BACK
+                                        + " fragment manager " + FragmentManager.this
                         );
                     }
                     if (mTransitioningOp != null) {
@@ -503,6 +505,7 @@
                     if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                         Log.d(FragmentManager.TAG,
                                 "handleOnBackPressed. PREDICTIVE_BACK = " + USE_PREDICTIVE_BACK
+                                        + " fragment manager " + FragmentManager.this
                         );
                     }
                     FragmentManager.this.handleOnBackPressed();
@@ -513,6 +516,7 @@
                     if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
                         Log.d(FragmentManager.TAG,
                                 "handleOnBackCancelled. PREDICTIVE_BACK = " + USE_PREDICTIVE_BACK
+                                        + " fragment manager " + FragmentManager.this
                         );
                     }
                     if (USE_PREDICTIVE_BACK) {
@@ -724,6 +728,10 @@
         synchronized (mPendingActions) {
             if (!mPendingActions.isEmpty()) {
                 mOnBackPressedCallback.setEnabled(true);
+                if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
+                    Log.d(TAG, "FragmentManager " + FragmentManager.this + " enabling "
+                            + "OnBackPressedCallback, caused by non-empty pending actions");
+                }
                 return;
             }
         }
@@ -788,6 +796,11 @@
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     void handleOnBackPressed() {
+        // First, execute any pending actions to make sure we're in an
+        // up to date view of the world just in case anyone is queuing
+        // up transactions that change the back stack then immediately
+        // calling onBackPressed()
+        execPendingActions(true);
         if (USE_PREDICTIVE_BACK && mTransitioningOp != null) {
             if (mBackStackChangeListeners != null && !mBackStackChangeListeners.isEmpty()) {
                 // Build a list of fragments based on the records
@@ -813,16 +826,23 @@
                 controller.completeBack();
             }
             mTransitioningOp = null;
+            updateOnBackPressedCallbackEnabled();
+            if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
+                Log.d(TAG, "Op is being set to null");
+                Log.d(TAG, "OnBackPressedCallback enabled=" + mOnBackPressedCallback.isEnabled()
+                        + " for  FragmentManager " + this);
+            }
         } else {
-            // First, execute any pending actions to make sure we're in an
-            // up to date view of the world just in case anyone is queuing
-            // up transactions that change the back stack then immediately
-            // calling onBackPressed()
-            execPendingActions(true);
             if (mOnBackPressedCallback.isEnabled()) {
+                if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
+                    Log.d(TAG, "Calling popBackStackImmediate via onBackPressed callback");
+                }
                 // We still have a back stack, so we can pop
                 popBackStackImmediate();
             } else {
+                if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
+                    Log.d(TAG, "Calling onBackPressed via onBackPressed callback");
+                }
                 // Sigh. Due to FragmentManager's asynchronicity, we can
                 // get into cases where we *think* we can handle the back
                 // button but because of frame perfect dispatch, we fell
diff --git a/glance/glance-appwidget-preview/lint-baseline.xml b/glance/glance-appwidget-preview/lint-baseline.xml
new file mode 100644
index 0000000..88ba6f5
--- /dev/null
+++ b/glance/glance-appwidget-preview/lint-baseline.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .all { it }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/preview/ComposableInvoker.kt"/>
+    </issue>
+
+</issues>
diff --git a/glance/glance-appwidget-proto/build.gradle b/glance/glance-appwidget-proto/build.gradle
index f4b676d..0829f6a 100644
--- a/glance/glance-appwidget-proto/build.gradle
+++ b/glance/glance-appwidget-proto/build.gradle
@@ -24,19 +24,15 @@
 }
 
 dependencies {
-    api(libs.kotlinStdlib)
     implementation(libs.protobufLite)
-    implementation("androidx.datastore:datastore-core:1.0.0")
+    compileOnly(libs.kotlinStdlib)
+    compileOnly("androidx.datastore:datastore-core:1.0.0")
 }
 
 protobuf {
     protoc {
         artifact = libs.protobufCompiler.get()
     }
-
-    // Generates the java proto-lite code for the protos in this project. See
-    // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
-    // for more information.
     generateProtoTasks {
         all().each { task ->
             task.builtins {
@@ -57,22 +53,6 @@
     }
 }
 
-// Create export artifact for for JarJaring
-def preferencesProtoJarJarTask = tasks.register("exportJar", Jar) {
-    archiveBaseName.set("export")
-    from(sourceSets.main.output)
-    // The proto-lite dependency includes .proto files, which are not used by glance. When apps
-    // depend on datastore as well as proto-lite directly, these files conflict since jarjar only
-    // renames the java classes. Remove them here since they are unused.
-    exclude("**/*.proto")
-
-    from(zipTree(configurations.detachedConfiguration(
-            dependencies.create(libs.protobufLite.get())).getSingleFile()))
-}
-
-def jarjarConf = configurations.register("export")
-artifacts.add(jarjarConf.name, preferencesProtoJarJarTask.flatMap { it.archiveFile })
-
 androidx {
     name = "Glance AppWidget Protos"
     publish = Publish.NONE
diff --git a/glance/glance-appwidget-testing/api/current.txt b/glance/glance-appwidget-testing/api/current.txt
new file mode 100644
index 0000000..4c77ba8
--- /dev/null
+++ b/glance/glance-appwidget-testing/api/current.txt
@@ -0,0 +1,24 @@
+// Signature format: 4.0
+package androidx.glance.appwidget.testing.unit {
+
+  public sealed interface GlanceAppWidgetUnitTest extends androidx.glance.testing.GlanceNodeAssertionsProvider<androidx.glance.testing.unit.MappedNode,androidx.glance.testing.unit.GlanceMappedNode> {
+    method public void awaitIdle();
+    method public void provideComposable(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method public void setAppWidgetSize(long size);
+    method public void setContext(android.content.Context context);
+    method public <T> void setState(T state);
+  }
+
+  public final class GlanceAppWidgetUnitTestDefaults {
+    method public androidx.glance.GlanceId glanceId();
+    method public int hostCategory();
+    method public long size();
+    field public static final androidx.glance.appwidget.testing.unit.GlanceAppWidgetUnitTestDefaults INSTANCE;
+  }
+
+  public final class GlanceAppWidgetUnitTestKt {
+    method public static void runGlanceAppWidgetUnitTest(optional long timeout, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.testing.unit.GlanceAppWidgetUnitTest,kotlin.Unit> block);
+  }
+
+}
+
diff --git a/glance/glance-appwidget-testing/api/res-current.txt b/glance/glance-appwidget-testing/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/glance/glance-appwidget-testing/api/res-current.txt
diff --git a/glance/glance-appwidget-testing/api/restricted_current.txt b/glance/glance-appwidget-testing/api/restricted_current.txt
new file mode 100644
index 0000000..4c77ba8
--- /dev/null
+++ b/glance/glance-appwidget-testing/api/restricted_current.txt
@@ -0,0 +1,24 @@
+// Signature format: 4.0
+package androidx.glance.appwidget.testing.unit {
+
+  public sealed interface GlanceAppWidgetUnitTest extends androidx.glance.testing.GlanceNodeAssertionsProvider<androidx.glance.testing.unit.MappedNode,androidx.glance.testing.unit.GlanceMappedNode> {
+    method public void awaitIdle();
+    method public void provideComposable(kotlin.jvm.functions.Function0<kotlin.Unit> composable);
+    method public void setAppWidgetSize(long size);
+    method public void setContext(android.content.Context context);
+    method public <T> void setState(T state);
+  }
+
+  public final class GlanceAppWidgetUnitTestDefaults {
+    method public androidx.glance.GlanceId glanceId();
+    method public int hostCategory();
+    method public long size();
+    field public static final androidx.glance.appwidget.testing.unit.GlanceAppWidgetUnitTestDefaults INSTANCE;
+  }
+
+  public final class GlanceAppWidgetUnitTestKt {
+    method public static void runGlanceAppWidgetUnitTest(optional long timeout, kotlin.jvm.functions.Function1<? super androidx.glance.appwidget.testing.unit.GlanceAppWidgetUnitTest,kotlin.Unit> block);
+  }
+
+}
+
diff --git a/glance/glance-appwidget-testing/build.gradle b/glance/glance-appwidget-testing/build.gradle
new file mode 100644
index 0000000..8d5db0b
--- /dev/null
+++ b/glance/glance-appwidget-testing/build.gradle
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 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("AndroidXComposePlugin")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    api(libs.kotlinStdlib)
+    api(libs.kotlinCoroutinesTest)
+    api(project(":glance:glance-testing"))
+    api(project(":glance:glance-appwidget"))
+
+    testImplementation("androidx.core:core:1.7.0")
+    testImplementation("androidx.core:core-ktx:1.7.0")
+    testImplementation(libs.junit)
+    testImplementation(libs.kotlinCoroutinesTest)
+    testImplementation(libs.kotlinTest)
+    testImplementation(libs.robolectric)
+    testImplementation(libs.testCore)
+    testImplementation(libs.testRunner)
+    testImplementation(libs.truth)
+
+    samples(projectOrArtifact(":glance:glance-appwidget-testing:glance-appwidget-testing-samples"))
+}
+
+android {
+    testOptions {
+        unitTests {
+            includeAndroidResources = true
+        }
+    }
+
+    defaultConfig {
+        minSdkVersion 23
+    }
+    namespace "androidx.glance.appwidget.testing"
+}
+
+androidx {
+    name = "androidx.glance:glance-appwidget-testing"
+    type = LibraryType.PUBLISHED_LIBRARY
+    targetsJavaConsumers = false
+    inceptionYear = "2023"
+    description = "This library provides APIs for developers to use for testing their appWidget specific Glance composables."
+}
diff --git a/glance/glance-appwidget-testing/samples/build.gradle b/glance/glance-appwidget-testing/samples/build.gradle
new file mode 100644
index 0000000..a5da7fa1
--- /dev/null
+++ b/glance/glance-appwidget-testing/samples/build.gradle
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2023 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("AndroidXComposePlugin")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+    compileOnly(project(":annotation:annotation-sampled"))
+
+    implementation(project(":glance:glance"))
+    implementation(project(":glance:glance-testing"))
+    implementation(project(":glance:glance-appwidget-testing"))
+
+    implementation(libs.junit)
+    implementation(libs.testCore)
+    implementation("androidx.core:core:1.7.0")
+    implementation("androidx.core:core-ktx:1.7.0")
+}
+
+androidx {
+    name = "Glance AppWidget Testing Samples"
+    type = LibraryType.SAMPLES
+    targetsJavaConsumers = false
+    inceptionYear = "2023"
+    description = "Contains the sample code for testing the Glance AppWidget Composables"
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+    }
+    namespace "androidx.glance.appwidget.testing.samples"
+}
diff --git a/glance/glance-appwidget-testing/samples/src/main/java/androidx/glance/appwidget/testing/samples/IsolatedGlanceComposableTestSamples.kt b/glance/glance-appwidget-testing/samples/src/main/java/androidx/glance/appwidget/testing/samples/IsolatedGlanceComposableTestSamples.kt
new file mode 100644
index 0000000..28a29c2
--- /dev/null
+++ b/glance/glance-appwidget-testing/samples/src/main/java/androidx/glance/appwidget/testing/samples/IsolatedGlanceComposableTestSamples.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2023 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.glance.appwidget.testing.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import androidx.glance.GlanceModifier
+import androidx.glance.LocalSize
+import androidx.glance.appwidget.testing.unit.runGlanceAppWidgetUnitTest
+import androidx.glance.layout.Column
+import androidx.glance.layout.Row
+import androidx.glance.layout.Spacer
+import androidx.glance.layout.fillMaxSize
+import androidx.glance.layout.width
+import androidx.glance.semantics.semantics
+import androidx.glance.semantics.testTag
+import androidx.glance.testing.unit.hasTestTag
+import androidx.glance.testing.unit.hasText
+import androidx.glance.text.Text
+import org.junit.Test
+
+@Sampled
+@Suppress("unused")
+fun isolatedGlanceComposableTestSamples() {
+    class TestSample {
+        @Test
+        fun statusContent_statusFalse_outputsPending() = runGlanceAppWidgetUnitTest {
+            provideComposable {
+                StatusRow(
+                    status = false
+                )
+            }
+
+            onNode(hasTestTag("status-text"))
+                .assert(hasText("Pending"))
+        }
+
+        @Test
+        fun statusContent_statusTrue_outputsFinished() = runGlanceAppWidgetUnitTest {
+            provideComposable {
+                StatusRow(
+                    status = true
+                )
+            }
+
+            onNode(hasTestTag("status-text"))
+                .assert(hasText("Finished"))
+        }
+
+        @Test
+        fun header_smallSize_showsShortHeaderText() = runGlanceAppWidgetUnitTest {
+            setAppWidgetSize(DpSize(width = 50.dp, height = 100.dp))
+
+            provideComposable {
+                StatusRow(
+                    status = false
+                )
+            }
+
+            onNode(hasTestTag("header-text"))
+                .assert(hasText("MyApp"))
+        }
+
+        @Test
+        fun header_largeSize_showsLongHeaderText() = runGlanceAppWidgetUnitTest {
+            setAppWidgetSize(DpSize(width = 150.dp, height = 100.dp))
+
+            provideComposable {
+                StatusRow(
+                    status = false
+                )
+            }
+
+            onNode(hasTestTag("header-text"))
+                .assert(hasText("MyApp (Last order)"))
+        }
+
+        @Composable
+        fun WidgetContent(status: Boolean) {
+            Column {
+                Header()
+                Spacer()
+                StatusRow(status)
+            }
+        }
+
+        @Composable
+        fun Header() {
+            val width = LocalSize.current.width
+            Row(modifier = GlanceModifier.fillMaxSize()) {
+                Text(
+                    text = if (width > 50.dp) {
+                        "MyApp (Last order)"
+                    } else {
+                        "MyApp"
+                    },
+                    modifier = GlanceModifier.semantics { testTag = "header-text" }
+                )
+            }
+        }
+
+        @Composable
+        fun StatusRow(status: Boolean) {
+            Row(modifier = GlanceModifier.fillMaxSize()) {
+                Text(
+                    text = "Status",
+                )
+                Spacer(modifier = GlanceModifier.width(10.dp))
+                Text(
+                    text = if (status) {
+                        "Pending"
+                    } else {
+                        "Finished"
+                    },
+                    modifier = GlanceModifier.semantics { testTag = "status-text" }
+                )
+            }
+        }
+    }
+}
diff --git a/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTest.kt b/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTest.kt
new file mode 100644
index 0000000..c6282eb
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTest.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2023 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.glance.appwidget.testing.unit
+
+import android.appwidget.AppWidgetProviderInfo
+import android.content.Context
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import androidx.glance.GlanceId
+import androidx.glance.appwidget.AppWidgetId
+import androidx.glance.state.GlanceStateDefinition
+import androidx.glance.testing.GlanceNodeAssertionsProvider
+import androidx.glance.testing.unit.GlanceMappedNode
+import androidx.glance.testing.unit.MappedNode
+import kotlin.time.Duration
+
+/**
+ * Sets up the test environment and runs the given unit [test block][block]. Use the methods on
+ * [GlanceAppWidgetUnitTest] in the test to provide Glance composable content, find Glance elements
+ * and make assertions on them.
+ *
+ * Test your individual Glance composable functions in isolation to verify that your logic outputs
+ * right elements. For example: if input data is 'x', an image 'y' was
+ * outputted. In sample below, the test class has a separate test for the header and the status
+ * row.
+ *
+ * Tests can be run on JVM as these don't involve rendering the UI. If your logic depends on
+ * [Context] or other android APIs, tests can be run on Android unit testing frameworks such as
+ * [Robolectric](https://github.com/robolectric/robolectric).
+ *
+ * Note: Keeping a reference to the [GlanceAppWidgetUnitTest] outside of this function is an error.
+ *
+ * @sample androidx.glance.appwidget.testing.samples.isolatedGlanceComposableTestSamples
+ *
+ * @param timeout test time out; defaults to 10s
+ * @param block The test block that involves calling methods in [GlanceAppWidgetUnitTest]
+ */
+// This and backing environment is based on pattern followed by
+// "androidx.compose.ui.test.runComposeUiTest". Alternative of exposing testRule was explored, but
+// it wasn't necessary for this case. If developers wish, they may use this function to create their
+// own test rule.
+fun runGlanceAppWidgetUnitTest(
+    timeout: Duration = DEFAULT_TIMEOUT,
+    block: GlanceAppWidgetUnitTest.() -> Unit
+) = GlanceAppWidgetUnitTestEnvironment(timeout).runTest(block)
+
+/**
+ * Provides methods to enable you to test your logic of building Glance composable content in the
+ * [runGlanceAppWidgetUnitTest] scope.
+ *
+ * @see [runGlanceAppWidgetUnitTest]
+ */
+sealed interface GlanceAppWidgetUnitTest :
+    GlanceNodeAssertionsProvider<MappedNode, GlanceMappedNode> {
+    /**
+     * Sets the size of the appWidget to be assumed for the test. This corresponds to the
+     * `LocalSize.current` composition local. If you are accessing the local size, you must
+     * call this method to set the intended size for the test.
+     *
+     * Note: This should be called before calling [provideComposable].
+     * Default is `349.dp, 455.dp` that of a 5x4 widget in Pixel 4 portrait mode. See
+     * [GlanceAppWidgetUnitTestDefaults.size]
+     *
+     * 1. If your appWidget uses `sizeMode == Single`, you can set this to the `minWidth` and
+     * `minHeight` set in your appwidget info xml.
+     * 2. If your appWidget uses `sizeMode == Exact`, you can identify the sizes to test looking
+     * at the documentation on
+     * [Determine a size for your widget](https://developer.android.com/develop/ui/views/appwidgets/layouts#anatomy_determining_size).
+     * and identifying landscape and portrait sizes that your widget may appear on.
+     * 3. If your appWidget uses `sizeMode == Responsive`, you can set this to one of the sizes from
+     * the list that you provide when specifying the sizeMode.
+     */
+    fun setAppWidgetSize(size: DpSize)
+
+    /**
+     * Sets the state to be used for the test if your composable under test accesses it via
+     * `currentState<*>()` or `LocalState.current`.
+     *
+     * Default state is `null`. Note: This should be called before calling [provideComposable],
+     * updates to the state after providing content has no effect. This matches the appWidget
+     * behavior where you need to call `update` on the widget for state changes to take effect.
+     *
+     * @param state the state to be used for testing the composable.
+     * @param T type of state used in your [GlanceStateDefinition] e.g. `Preferences` if your state
+     *          definition is `GlanceStateDefinition<Preferences>`
+     */
+    fun <T> setState(state: T)
+
+    /**
+     * Sets the context to be used for the test.
+     *
+     * It is optional to call this method. However, you must set this if your composable needs
+     * access to `LocalContext`. You may need to use a Android unit test framework such as
+     * [Robolectric](https://github.com/robolectric/robolectric) to get the context.
+     *
+     * Note: This should be called before calling [provideComposable], updates to the state after
+     * providing content has no effect
+     */
+    fun setContext(context: Context)
+
+    /**
+     * Sets the Glance composable function to be tested. Each unit test should test a composable in
+     * isolation and assume specific state as input. Prefer keeping composables side-effects free.
+     * Perform any state changes needed for the test before calling [provideComposable] or
+     * [runGlanceAppWidgetUnitTest].
+     *
+     * @param composable the composable function under test
+     */
+    fun provideComposable(composable: @Composable () -> Unit)
+
+    /**
+     * Wait until all recompositions are calculated. For example if you have `LaunchedEffect` with
+     * delays in your composable.
+     */
+    fun awaitIdle()
+}
+
+/**
+ * Provides default values for various properties used in the Glance appWidget unit tests.
+ */
+object GlanceAppWidgetUnitTestDefaults {
+    /**
+     * [GlanceId] that can be assumed for state updates testing a Glance composable in isolation.
+     */
+    fun glanceId(): GlanceId = AppWidgetId(1)
+
+    /**
+     * Default size of the appWidget assumed in the unit tests. To override the size, use the
+     * [GlanceAppWidgetUnitTest.setAppWidgetSize] function.
+     *
+     * The default `349.dp, 455.dp` is that of a 5x4 widget in Pixel 4 portrait mode.
+     */
+    fun size(): DpSize = DpSize(height = 349.dp, width = 455.dp)
+
+    /**
+     * Default category of the appWidget assumed in the unit tests.
+     *
+     * The default is `WIDGET_CATEGORY_HOME_SCREEN`
+     */
+    fun hostCategory(): Int = AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN
+}
diff --git a/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironment.kt b/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironment.kt
new file mode 100644
index 0000000..674c8c5
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/main/java/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironment.kt
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2023 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.glance.appwidget.testing.unit
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.Composition
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.MonotonicFrameClock
+import androidx.compose.runtime.Recomposer
+import androidx.compose.ui.unit.DpSize
+import androidx.glance.Applier
+import androidx.glance.LocalContext
+import androidx.glance.LocalGlanceId
+import androidx.glance.LocalSize
+import androidx.glance.LocalState
+import androidx.glance.appwidget.LocalAppWidgetOptions
+import androidx.glance.appwidget.RemoteViewsRoot
+import androidx.glance.session.globalSnapshotMonitor
+import androidx.glance.testing.GlanceNodeAssertion
+import androidx.glance.testing.GlanceNodeMatcher
+import androidx.glance.testing.TestContext
+import androidx.glance.testing.unit.GlanceMappedNode
+import androidx.glance.testing.unit.MappedNode
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.currentCoroutineContext
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+
+internal val DEFAULT_TIMEOUT = 10.seconds
+
+/**
+ * An implementation of [GlanceAppWidgetUnitTest] that provides APIs to run composition for
+ * appwidget-specific Glance composable content.
+ */
+internal class GlanceAppWidgetUnitTestEnvironment(
+    private val timeout: Duration
+) : GlanceAppWidgetUnitTest {
+    private var testContext = TestContext<MappedNode, GlanceMappedNode>()
+    private var testScope = TestScope()
+
+    // Data for composition locals
+    private var context: Context? = null
+    private val fakeGlanceID = GlanceAppWidgetUnitTestDefaults.glanceId()
+    private var size: DpSize = GlanceAppWidgetUnitTestDefaults.size()
+    private var state: Any? = null
+
+    private val root = RemoteViewsRoot(10)
+
+    private lateinit var recomposer: Recomposer
+    private lateinit var composition: Composition
+
+    fun runTest(block: GlanceAppWidgetUnitTest.() -> Unit) = testScope.runTest(timeout) {
+        var snapshotMonitor: Job? = null
+        try {
+            // GlobalSnapshotManager.ensureStarted() uses Dispatcher.Default, so using
+            // globalSnapshotMonitor instead to be able to use test dispatcher instead.
+            snapshotMonitor = launch { globalSnapshotMonitor() }
+            val applier = Applier(root)
+            recomposer = Recomposer(testScope.coroutineContext)
+            composition = Composition(applier, recomposer)
+            block()
+        } finally {
+            composition.dispose()
+            snapshotMonitor?.cancel()
+            recomposer.cancel()
+            recomposer.join()
+        }
+    }
+
+    // Among the appWidgetOptions available, size related options shouldn't generally be necessary
+    // for developers to look up - the LocalSize composition local should suffice. So, currently, we
+    // only initialize host category.
+    private val appWidgetOptions = Bundle().apply {
+        putInt(
+            AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
+            GlanceAppWidgetUnitTestDefaults.hostCategory()
+        )
+    }
+
+    override fun provideComposable(composable: @Composable () -> Unit) {
+        check(testContext.rootGlanceNode == null) {
+            "provideComposable can only be called once"
+        }
+
+        testScope.launch {
+            var compositionLocals = arrayOf(
+                LocalGlanceId provides fakeGlanceID,
+                LocalState provides state,
+                LocalAppWidgetOptions provides appWidgetOptions,
+                LocalSize provides size
+            )
+            context?.let {
+                compositionLocals = compositionLocals.plus(LocalContext provides it)
+            }
+
+            composition.setContent {
+                CompositionLocalProvider(
+                    values = compositionLocals,
+                    content = composable,
+                )
+            }
+
+            launch(currentCoroutineContext() + TestFrameClock()) {
+                recomposer.runRecomposeAndApplyChanges()
+            }
+
+            launch {
+                recomposer.currentState.collect { curState ->
+                    when (curState) {
+                        Recomposer.State.Idle -> {
+                            testContext.rootGlanceNode = GlanceMappedNode(
+                                emittable = root.copy()
+                            )
+                        }
+
+                        Recomposer.State.ShutDown -> {
+                            cancel()
+                        }
+
+                        else -> {}
+                    }
+                }
+            }
+        }
+    }
+
+    override fun awaitIdle() {
+        testScope.testScheduler.advanceUntilIdle()
+    }
+
+    override fun onNode(
+        matcher: GlanceNodeMatcher<MappedNode>
+    ): GlanceNodeAssertion<MappedNode, GlanceMappedNode> {
+        // Always let all the enqueued tasks finish before inspecting the tree.
+        testScope.testScheduler.runCurrent()
+        // Calling onNode resets the previously matched nodes and starts a new matching chain.
+        testContext.reset()
+        // Delegates matching to the next assertion.
+        return GlanceNodeAssertion(matcher, testContext)
+    }
+
+    override fun setAppWidgetSize(size: DpSize) {
+        check(testContext.rootGlanceNode == null) {
+            "setApWidgetSize should be called before calling provideComposable"
+        }
+        this.size = size
+    }
+
+    override fun <T> setState(state: T) {
+        check(testContext.rootGlanceNode == null) {
+            "setState should be called before calling provideComposable"
+        }
+        this.state = state
+    }
+
+    override fun setContext(context: Context) {
+        check(testContext.rootGlanceNode == null) {
+            "setContext should be called before calling provideComposable"
+        }
+        this.context = context
+    }
+
+    /**
+     * Test clock that sends all frames immediately.
+     */
+    // Same as TestUtils.TestFrameClock used in Glance unit tests.
+    private class TestFrameClock : MonotonicFrameClock {
+        override suspend fun <R> withFrameNanos(onFrame: (frameTimeNanos: Long) -> R) =
+            onFrame(System.currentTimeMillis())
+    }
+}
diff --git a/glance/glance-appwidget-testing/src/test/AndroidManifest.xml b/glance/glance-appwidget-testing/src/test/AndroidManifest.xml
new file mode 100644
index 0000000..f125c7b
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/test/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<!--
+  Copyright 2023 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>
+    <application/>
+</manifest>
\ No newline at end of file
diff --git a/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentRobolectricTest.kt b/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentRobolectricTest.kt
new file mode 100644
index 0000000..514826d
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentRobolectricTest.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2023 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.glance.appwidget.testing.unit
+
+import android.content.Context
+import androidx.compose.runtime.Composable
+import androidx.glance.GlanceModifier
+import androidx.glance.LocalContext
+import androidx.glance.appwidget.testing.test.R
+import androidx.glance.layout.Column
+import androidx.glance.semantics.semantics
+import androidx.glance.semantics.testTag
+import androidx.glance.testing.unit.hasTestTag
+import androidx.glance.testing.unit.hasText
+import androidx.glance.text.Text
+import androidx.test.core.app.ApplicationProvider
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+import org.robolectric.annotation.Config
+
+@RunWith(RobolectricTestRunner::class)
+@Config(sdk = [33])
+/**
+ * Holds tests that use Robolectric for providing application resources and context.
+ */
+class GlanceAppWidgetUnitTestEnvironmentRobolectricTest {
+    private lateinit var context: Context
+
+    @Before
+    fun setUp() {
+        context = ApplicationProvider.getApplicationContext()
+    }
+
+    @Test
+    fun runTest_localContextRead() = runGlanceAppWidgetUnitTest {
+        setContext(context)
+
+        provideComposable {
+            ComposableReadingLocalContext()
+        }
+
+        onNode(hasTestTag("test-tag"))
+            .assert(hasText("Test string: MyTest"))
+    }
+
+    @Composable
+    fun ComposableReadingLocalContext() {
+        val context = LocalContext.current
+
+        Column {
+            Text(
+                text = "Test string: ${context.getString(R.string.glance_test_string)}",
+                modifier = GlanceModifier.semantics { testTag = "test-tag" }
+            )
+        }
+    }
+}
diff --git a/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentTest.kt b/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentTest.kt
new file mode 100644
index 0000000..a1449d8
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/test/kotlin/androidx/glance/appwidget/testing/unit/GlanceAppWidgetUnitTestEnvironmentTest.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2023 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.glance.appwidget.testing.unit
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.booleanPreferencesKey
+import androidx.datastore.preferences.core.preferencesOf
+import androidx.glance.GlanceModifier
+import androidx.glance.Image
+import androidx.glance.ImageProvider
+import androidx.glance.LocalSize
+import androidx.glance.appwidget.ImageProvider
+import androidx.glance.appwidget.testing.test.R
+import androidx.glance.currentState
+import androidx.glance.layout.Column
+import androidx.glance.layout.Spacer
+import androidx.glance.semantics.semantics
+import androidx.glance.semantics.testTag
+import androidx.glance.testing.unit.hasTestTag
+import androidx.glance.testing.unit.hasText
+import androidx.glance.text.Text
+import kotlinx.coroutines.delay
+import org.junit.Test
+
+// In this test we aren't specifically testing anything bound to SDK, so we can run it without
+// android unit test runners such as Robolectric.
+class GlanceAppWidgetUnitTestEnvironmentTest {
+    @Test
+    fun runTest_localSizeRead() = runGlanceAppWidgetUnitTest {
+        setAppWidgetSize(DpSize(width = 120.dp, height = 200.dp))
+
+        provideComposable {
+            ComposableReadingLocalSize()
+        }
+
+        onNode(hasText("120.0 dp x 200.0 dp")).assertExists()
+    }
+
+    @Composable
+    fun ComposableReadingLocalSize() {
+        val size = LocalSize.current
+        Column {
+            Text(text = "${size.width.value} dp x ${size.height.value} dp")
+            Spacer()
+            Image(
+                provider = ImageProvider(R.drawable.glance_test_android),
+                contentDescription = "test-image",
+            )
+        }
+    }
+
+    @Test
+    fun runTest_currentStateRead() = runGlanceAppWidgetUnitTest {
+        setState(preferencesOf(toggleKey to true))
+
+        provideComposable {
+            ComposableReadingState()
+        }
+
+        onNode(hasText("isToggled")).assertExists()
+    }
+
+    @Composable
+    fun ComposableReadingState() {
+        Column {
+            Text(text = "A text")
+            Spacer()
+            Text(text = getTitle(currentState<Preferences>()[toggleKey] == true))
+            Spacer()
+            Image(
+                provider = ImageProvider(R.drawable.glance_test_android),
+                contentDescription = "test-image",
+                modifier = GlanceModifier.semantics { testTag = "img" }
+            )
+        }
+    }
+
+    @Test
+    fun runTest_onNodeCalledMultipleTimes() = runGlanceAppWidgetUnitTest {
+        provideComposable {
+            Text(text = "abc")
+            Spacer()
+            Text(text = "xyz")
+        }
+
+        onNode(hasText("abc")).assertExists()
+        // test context reset and new filter matched onNode
+        onNode(hasText("xyz")).assertExists()
+        onNode(hasText("def")).assertDoesNotExist()
+    }
+
+    @Test
+    fun runTest_effect() = runGlanceAppWidgetUnitTest {
+        provideComposable {
+            var text by remember { mutableStateOf("initial") }
+
+            Text(text = text, modifier = GlanceModifier.semantics { testTag = "mutable-test" })
+            Spacer()
+            Text(text = "xyz")
+
+            LaunchedEffect(Unit) {
+                text = "changed"
+            }
+        }
+
+        onNode(hasTestTag("mutable-test")).assert(hasText("changed"))
+    }
+
+    @Test
+    fun runTest_effectWithDelay() = runGlanceAppWidgetUnitTest {
+        provideComposable {
+            var text by remember { mutableStateOf("initial") }
+
+            Text(text = text, modifier = GlanceModifier.semantics { testTag = "mutable-test" })
+            Spacer()
+            Text(text = "xyz")
+
+            LaunchedEffect(Unit) {
+                delay(100L)
+                text = "changed"
+            }
+        }
+
+        awaitIdle() // Since the launched effect has a delay.
+        onNode(hasTestTag("mutable-test")).assert(hasText("changed"))
+    }
+
+    @Test
+    fun runTest_effectWithDelayWithoutAdvancing() = runGlanceAppWidgetUnitTest {
+        provideComposable {
+            var text by remember { mutableStateOf("initial") }
+
+            Text(text = text, modifier = GlanceModifier.semantics { testTag = "mutable-test" })
+            Spacer()
+            Text(text = "xyz")
+
+            LaunchedEffect(Unit) {
+                delay(100L)
+                text = "changed"
+            }
+        }
+
+        onNode(hasTestTag("mutable-test")).assert(hasText("initial"))
+    }
+}
+
+private val toggleKey = booleanPreferencesKey("title_toggled_key")
+private fun getTitle(toggled: Boolean) = if (toggled) "isToggled" else "notToggled"
diff --git a/glance/glance-appwidget-testing/src/test/res/drawable/glance_test_android.xml b/glance/glance-appwidget-testing/src/test/res/drawable/glance_test_android.xml
new file mode 100644
index 0000000..49a3142
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/test/res/drawable/glance_test_android.xml
@@ -0,0 +1,21 @@
+<!--
+  Copyright 2023 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.
+  -->
+
+<vector android:alpha="0.9" android:height="24dp"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M17.6,9.48l1.84,-3.18c0.16,-0.31 0.04,-0.69 -0.26,-0.85c-0.29,-0.15 -0.65,-0.06 -0.83,0.22l-1.88,3.24c-2.86,-1.21 -6.08,-1.21 -8.94,0L5.65,5.67c-0.19,-0.29 -0.58,-0.38 -0.87,-0.2C4.5,5.65 4.41,6.01 4.56,6.3L6.4,9.48C3.3,11.25 1.28,14.44 1,18h22C22.72,14.44 20.7,11.25 17.6,9.48zM7,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25S8.25,13.31 8.25,14C8.25,14.69 7.69,15.25 7,15.25zM17,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25s1.25,0.56 1.25,1.25C18.25,14.69 17.69,15.25 17,15.25z"/>
+</vector>
diff --git a/glance/glance-appwidget-testing/src/test/res/values/strings.xml b/glance/glance-appwidget-testing/src/test/res/values/strings.xml
new file mode 100644
index 0000000..88a0850
--- /dev/null
+++ b/glance/glance-appwidget-testing/src/test/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2023 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.
+  -->
+
+<resources>
+    <string name="glance_test_string">MyTest</string>
+</resources>
\ No newline at end of file
diff --git a/glance/glance-appwidget/build.gradle b/glance/glance-appwidget/build.gradle
index a8e7d1c..7da47ab 100644
--- a/glance/glance-appwidget/build.gradle
+++ b/glance/glance-appwidget/build.gradle
@@ -29,11 +29,14 @@
 BundleInsideHelper.forInsideAar(
         project,
         /* from = */ "com.google.protobuf",
-        /* to =   */ "androidx.glance.appwidget.protobuf"
+        /* to =   */ "androidx.glance.appwidget.protobuf",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
-    bundleInside(project(path: ":glance:glance-appwidget-proto", configuration: "export"))
+    bundleInside(project(":glance:glance-appwidget-proto"))
 
     api(project(":glance:glance"))
     api("androidx.annotation:annotation:1.1.0")
diff --git a/glance/glance-appwidget/lint-baseline.xml b/glance/glance-appwidget/lint-baseline.xml
index 87160dc..79615c9 100644
--- a/glance/glance-appwidget/lint-baseline.xml
+++ b/glance/glance-appwidget/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanThreadSleep"
@@ -29,6 +29,465 @@
     </issue>
 
     <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/AndroidRemoteViews.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    lambdas[event.key]?.forEach { it.block() }"
+        errorLine2="                                        ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/AppWidgetSession.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        sizes.map { DpSize(it.width.dp, it.height.dp) }"
+        errorLine2="              ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    }.minByOrNull { it.second }?.first"
+        errorLine2="      ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            rv.setContentDescription(viewDef.mainViewId, contentDescription.joinToString())"
+        errorLine2="                                                                            ~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/ApplyModifiers.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    manager.getGlanceIds(javaClass).forEach { update(context, it) }"
+        errorLine2="                                    ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    manager.getGlanceIds(javaClass).forEach { glanceId ->"
+        errorLine2="                                    ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            }.toMap()"
+        errorLine2="              ~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        return receivers.flatMap { receiver ->"
+        errorLine2="                         ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    val info = appWidgetManager.installedProviders.first {"
+        errorLine2="                                                                   ~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .filter { it.provider.packageName == packageName }"
+        errorLine2="             ~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .map { it.provider.className }"
+        errorLine2="             ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .toSet()"
+        errorLine2="             ~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                toRemove.forEach { receiver -> remove(providerKey(receiver)) }"
+        errorLine2="                         ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        if (children.any { it.shouldIgnoreResult() }) return true"
+        errorLine2="                     ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/IgnoreResult.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        .forEach {"
+        errorLine2="         ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/LayoutSelection.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        itemList.forEachIndexed { index, (itemId, composable) ->"
+        errorLine2="                 ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyList.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyList.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyList.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        element.children.foldIndexed(false) { position, previous, itemEmittable ->"
+        errorLine2="                         ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/translators/LazyListTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        itemList.forEachIndexed { index, (itemId, composable) ->"
+        errorLine2="                 ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        element.children.foldIndexed(false) { position, previous, itemEmittable ->"
+        errorLine2="                         ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/translators/LazyVerticalGridTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    if (container.children.isNotEmpty() &amp;&amp; container.children.all { it is EmittableSizeBox }) {"
+        errorLine2="                                                              ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (item in container.children) {"
+        errorLine2="                  ~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.forEach { child ->"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.any { child ->"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.any { child ->"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.forEachIndexed { index, child ->"
+        errorLine2="             ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.foldIndexed("
+        errorLine2="             ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    fold(GlanceModifier) { acc: GlanceModifier, mod: GlanceModifier? ->"
+        errorLine2="    ~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val layoutIdCount = views.map { it.layoutId }.distinct().count()"
+        errorLine2="                                                      ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteCollectionItems.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                viewTypeCount = views.map { it.layoutId }.distinct().count()"
+        errorLine2="                                      ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteCollectionItems.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                viewTypeCount = views.map { it.layoutId }.distinct().count()"
+        errorLine2="                                                          ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteCollectionItems.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    if (children.all { it is EmittableSizeBox }) {"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val views = children.map { child ->"
+        errorLine2="                             ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    Api31Impl.createRemoteViews(views.toMap())"
+        errorLine2="                                                      ~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    combineLandscapeAndPortrait(views.map { it.second })"
+        errorLine2="                                                      ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    element.children.forEach {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    check(children.count { it is EmittableRadioButton &amp;&amp; it.checked } &lt;= 1) {"
+        errorLine2="                   ~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            element.children.forEachIndexed { index, child ->"
+        errorLine2="                             ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.take(10).forEachIndexed { index, child ->"
+        errorLine2="             ~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.take(10).forEachIndexed { index, child ->"
+        errorLine2="                      ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/SizeBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .map { findBestSize(it, sizeMode.sizes) ?: smallestSize }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/SizeBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    sizes.distinct().map { size ->"
+        errorLine2="                     ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/SizeBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    spans.forEach { span ->"
+        errorLine2="          ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/translators/TextTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val layouts = config.layoutList.associate {"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/WidgetLayout.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            addAllChildren(element.children.map { createNode(context, it) })"
+        errorLine2="                                            ~~~">
+        <location
+            file="src/main/java/androidx/glance/appwidget/WidgetLayout.kt"/>
+    </issue>
+
+    <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in method extractAllSizes has parameter &apos;minSize&apos; with type Function0&lt;DpSize>."
         errorLine1="internal fun Bundle.extractAllSizes(minSize: () -> DpSize): List&lt;DpSize> {"
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt
index f667413..a1d03ba 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt
@@ -23,6 +23,8 @@
 import android.util.Log
 import android.widget.RemoteViews
 import androidx.annotation.LayoutRes
+import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope
 import androidx.compose.runtime.Composable
 import androidx.glance.GlanceComposable
 import androidx.glance.GlanceId
@@ -194,7 +196,8 @@
     }
 }
 
-internal data class AppWidgetId(val appWidgetId: Int) : GlanceId
+@RestrictTo(Scope.LIBRARY_GROUP)
+data class AppWidgetId(val appWidgetId: Int) : GlanceId
 
 /** Update all App Widgets managed by the [GlanceAppWidget] class. */
 suspend fun GlanceAppWidget.updateAll(@Suppress("ContextFirst") context: Context) {
diff --git a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt
index 1428527..df0e178 100644
--- a/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt
+++ b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt
@@ -16,6 +16,8 @@
 
 package androidx.glance.appwidget
 
+import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope
 import androidx.glance.Emittable
 import androidx.glance.EmittableWithChildren
 import androidx.glance.GlanceModifier
@@ -24,7 +26,8 @@
  * Root view, with a maximum depth. No default value is specified, as the exact value depends on
  * specific circumstances.
  */
-internal class RemoteViewsRoot(private val maxDepth: Int) : EmittableWithChildren(maxDepth) {
+@RestrictTo(Scope.LIBRARY_GROUP)
+ class RemoteViewsRoot(private val maxDepth: Int) : EmittableWithChildren(maxDepth) {
     override var modifier: GlanceModifier = GlanceModifier
     override fun copy(): Emittable = RemoteViewsRoot(maxDepth).also {
         it.modifier = modifier
diff --git a/glance/glance-template/lint-baseline.xml b/glance/glance-template/lint-baseline.xml
new file mode 100644
index 0000000..8a73870
--- /dev/null
+++ b/glance/glance-template/lint-baseline.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="cli" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        textList.forEachIndexed { index, item ->"
+        errorLine2="                 ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/template/GlanceAppWidgetTemplates.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            actionBlock.actionButtons.forEach { button ->"
+        errorLine2="                                      ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/template/GlanceAppWidgetTemplates.kt"/>
+    </issue>
+
+</issues>
diff --git a/glance/glance-testing/api/current.txt b/glance/glance-testing/api/current.txt
index 51dd245..e46a742 100644
--- a/glance/glance-testing/api/current.txt
+++ b/glance/glance-testing/api/current.txt
@@ -14,6 +14,10 @@
     method public androidx.glance.testing.GlanceNodeAssertion<R,T> assertExists();
   }
 
+  public interface GlanceNodeAssertionsProvider<R, T extends androidx.glance.testing.GlanceNode<R>> {
+    method public androidx.glance.testing.GlanceNodeAssertion<R,T> onNode(androidx.glance.testing.GlanceNodeMatcher<R> matcher);
+  }
+
   public final class GlanceNodeMatcher<R> {
     ctor public GlanceNodeMatcher(String description, kotlin.jvm.functions.Function1<? super androidx.glance.testing.GlanceNode<R>,java.lang.Boolean> matcher);
     method public boolean matches(androidx.glance.testing.GlanceNode<R> node);
diff --git a/glance/glance-testing/api/restricted_current.txt b/glance/glance-testing/api/restricted_current.txt
index 51dd245..e46a742 100644
--- a/glance/glance-testing/api/restricted_current.txt
+++ b/glance/glance-testing/api/restricted_current.txt
@@ -14,6 +14,10 @@
     method public androidx.glance.testing.GlanceNodeAssertion<R,T> assertExists();
   }
 
+  public interface GlanceNodeAssertionsProvider<R, T extends androidx.glance.testing.GlanceNode<R>> {
+    method public androidx.glance.testing.GlanceNodeAssertion<R,T> onNode(androidx.glance.testing.GlanceNodeMatcher<R> matcher);
+  }
+
   public final class GlanceNodeMatcher<R> {
     ctor public GlanceNodeMatcher(String description, kotlin.jvm.functions.Function1<? super androidx.glance.testing.GlanceNode<R>,java.lang.Boolean> matcher);
     method public boolean matches(androidx.glance.testing.GlanceNode<R> node);
diff --git a/glance/glance-testing/lint-baseline.xml b/glance/glance-testing/lint-baseline.xml
new file mode 100644
index 0000000..4c206fc
--- /dev/null
+++ b/glance/glance-testing/lint-baseline.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            return emittable.children.map { child ->"
+        errorLine2="                                      ~~~">
+        <location
+            file="src/main/java/androidx/glance/testing/unit/GlanceMappedNode.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        for (child in node.children()) {"
+        errorLine2="                   ~~">
+        <location
+            file="src/main/java/androidx/glance/testing/GlanceNodeAssertion.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        return matching.toList()"
+        errorLine2="                        ~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/testing/GlanceNodeAssertion.kt"/>
+    </issue>
+
+</issues>
diff --git a/glance/glance-testing/src/main/java/androidx/glance/testing/GlanceNodeAssertionsProvider.kt b/glance/glance-testing/src/main/java/androidx/glance/testing/GlanceNodeAssertionsProvider.kt
new file mode 100644
index 0000000..624b529
--- /dev/null
+++ b/glance/glance-testing/src/main/java/androidx/glance/testing/GlanceNodeAssertionsProvider.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 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.glance.testing
+
+/**
+ * Provides an entry point into testing exposing methods to find glance nodes
+ */
+// Equivalent to "androidx.compose.ui.test.SemanticsNodeInteractionsProvider" from compose.
+interface GlanceNodeAssertionsProvider<R, T : GlanceNode<R>> {
+    /**
+     * Finds a Glance node that matches the given condition.
+     *
+     * Any subsequent operation on its result will expect exactly one element found and will throw
+     * [AssertionError] if none or more than one element is found.
+     *
+     * @param matcher Matcher used for filtering
+     */
+    fun onNode(matcher: GlanceNodeMatcher<R>): GlanceNodeAssertion<R, T>
+}
diff --git a/glance/glance-testing/src/main/java/androidx/glance/testing/TestContext.kt b/glance/glance-testing/src/main/java/androidx/glance/testing/TestContext.kt
index 1399349..1ab76a3 100644
--- a/glance/glance-testing/src/main/java/androidx/glance/testing/TestContext.kt
+++ b/glance/glance-testing/src/main/java/androidx/glance/testing/TestContext.kt
@@ -23,6 +23,13 @@
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 class TestContext<R, T : GlanceNode<R>> {
+    /**
+     * To be called on every onNode to restart matching and clear cache.
+     */
+    fun reset() {
+        cachedMatchedNodes = emptyList()
+    }
+
     var rootGlanceNode: T? = null
     var cachedMatchedNodes: List<GlanceNode<R>> = emptyList()
 }
diff --git a/glance/glance-wear-tiles-preview/lint-baseline.xml b/glance/glance-wear-tiles-preview/lint-baseline.xml
new file mode 100644
index 0000000..d2965f7
--- /dev/null
+++ b/glance/glance-wear-tiles-preview/lint-baseline.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                .all { it }"
+        errorLine2="                 ~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/preview/ComposableInvoker.kt"/>
+    </issue>
+
+</issues>
diff --git a/glance/glance-wear-tiles/lint-baseline.xml b/glance/glance-wear-tiles/lint-baseline.xml
new file mode 100644
index 0000000..5a135eb
--- /dev/null
+++ b/glance/glance-wear-tiles/lint-baseline.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        curvedChildList.forEach { composable ->"
+        errorLine2="                        ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/curved/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/curved/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/curved/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    children.mapIndexed { index, child ->"
+        errorLine2="             ~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    toDelete.forEach {"
+        errorLine2="             ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            children.forEach { child ->"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/NormalizeCompositionTree.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        textList.forEach { item ->"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/template/SingleEntityTemplateLayouts.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .setContentDescription(it.joinToString())"
+        errorLine2="                                      ~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .setContentDescription(it.joinToString())"
+        errorLine2="                                      ~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            element.children.forEach {"
+        errorLine2="                             ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                element.children.forEach {"
+        errorLine2="                                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                element.children.forEach {"
+        errorLine2="                                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    element.children.forEach { curvedChild ->"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            curvedChild.children.forEach {"
+        errorLine2="                                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt"/>
+    </issue>
+
+</issues>
diff --git a/glance/glance/lint-baseline.xml b/glance/glance/lint-baseline.xml
index 362729b4..d2fb308 100644
--- a/glance/glance/lint-baseline.xml
+++ b/glance/glance/lint-baseline.xml
@@ -20,6 +20,87 @@
     </issue>
 
     <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/layout/Box.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/layout/Column.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.joinToString(&quot;,\n&quot;).prependIndent(&quot;  &quot;)"
+        errorLine2="                 ~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/Emittables.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            events.forEach { addAction(it) }"
+        errorLine2="                   ~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/session/IdleEventBroadcastReceiver.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    fold(0.dp) { acc, res ->"
+        errorLine2="    ~~~~">
+        <location
+            file="src/main/java/androidx/glance/layout/Padding.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        it.children.addAll(children.map { it.copy() })"
+        errorLine2="                                    ~~~">
+        <location
+            file="src/main/java/androidx/glance/layout/Row.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            .any { it.state == WorkInfo.State.RUNNING } &amp;&amp; synchronized(sessions) {"
+        errorLine2="             ~~~">
+        <location
+            file="src/main/java/androidx/glance/session/SessionManager.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val mask = decorations.fold(0) { acc, decoration ->"
+        errorLine2="                                   ~~~~">
+        <location
+            file="src/main/java/androidx/glance/text/TextDecoration.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        return &quot;TextDecoration[${values.joinToString(separator = &quot;, &quot;)}]&quot;"
+        errorLine2="                                        ~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/glance/text/TextDecoration.kt"/>
+    </issue>
+
+    <issue
         id="PrimitiveInLambda"
         message="Use a functional interface instead of lambda syntax for lambdas with primitive values in constructor InteractiveFrameClock has parameter &apos;nanoTime&apos; with type Function0&lt;Long>."
         errorLine1="    private val nanoTime: () -> Long = { System.nanoTime() }"
diff --git a/glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt b/glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt
index cebf899..d5f6d8d 100644
--- a/glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt
+++ b/glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt
@@ -17,6 +17,7 @@
 package androidx.glance.session
 
 import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope
 import androidx.compose.runtime.snapshots.Snapshot
 import java.util.concurrent.atomic.AtomicBoolean
 import kotlinx.coroutines.CoroutineScope
@@ -33,7 +34,7 @@
  * state changes). These will be sent on Dispatchers.Default.
  * This is based on [androidx.compose.ui.platform.GlobalSnapshotManager].
  */
-@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+@RestrictTo(Scope.LIBRARY_GROUP)
 object GlobalSnapshotManager {
     private val started = AtomicBoolean(false)
     private val sent = AtomicBoolean(false)
@@ -59,7 +60,8 @@
 /**
  * Monitors global snapshot state writes and sends apply notifications.
  */
-internal suspend fun globalSnapshotMonitor() {
+@RestrictTo(Scope.LIBRARY_GROUP)
+suspend fun globalSnapshotMonitor() {
     val channel = Channel<Unit>(1)
     val sent = AtomicBoolean(false)
     val observerHandle = Snapshot.registerGlobalWriteObserver {
diff --git a/gradle.properties b/gradle.properties
index 17b7b6e..bec21dd 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,8 +18,8 @@
 # .gradle/.android/analytics.settings -> b/278767328
 # fullsdk-linux/**/package.xml -> b/291331139
 # androidx/compose/lint/common/build/libs/common.jar -> b/295395616
-# .konan/kotlin-native-prebuilt-linux-x86_64-1.9.0 -> https://youtrack.jetbrains.com/issue/KT-61154/
-org.gradle.configuration-cache.inputs.unsafe.ignore.file-system-checks=**/.gradle/.android/analytics.settings;**/prebuilts/fullsdk-linux;**/prebuilts/fullsdk-linux/platforms/android-*/package.xml;**/androidx/compose/lint/common/build/libs/common.jar;**/.konan/kotlin-native-prebuilt-linux-x86_64-1.9.0/klib/common/stdlib;**/.konan/kotlin-native-prebuilt-linux-x86_64-1.9.0/konan/lib/*
+# .konan/kotlin-native-prebuilt-linux-x86_64-1.9.10 -> https://youtrack.jetbrains.com/issue/KT-61154/
+org.gradle.configuration-cache.inputs.unsafe.ignore.file-system-checks=**/.gradle/.android/analytics.settings;**/prebuilts/fullsdk-linux;**/prebuilts/fullsdk-linux/platforms/android-*/package.xml;**/androidx/compose/lint/common/build/libs/common.jar;**/.konan/kotlin-native-prebuilt-linux-x86_64-1.9.10/klib/common/stdlib;**/.konan/kotlin-native-prebuilt-linux-x86_64-1.9.10/konan/lib/*
 
 android.lint.baselineOmitLineNumbers=true
 android.lint.printStackTrace=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4718b38..669b6d7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -2,13 +2,13 @@
 # -----------------------------------------------------------------------------
 # All of the following should be updated in sync.
 # -----------------------------------------------------------------------------
-androidGradlePlugin = "8.2.0-alpha15"
+androidGradlePlugin = "8.2.0-beta01"
 # NOTE: When updating the lint version we also need to update the `api` version
 # supported by `IssueRegistry`'s.' For e.g. r.android.com/1331903
-androidLint = "31.2.0-alpha15"
+androidLint = "31.2.0-beta01"
 # Once you have a chosen version of AGP to upgrade to, go to
 # https://developer.android.com/studio/archive and find the matching version of Studio.
-androidStudio = "2023.1.1.15"
+androidStudio = "2023.1.1.17"
 # -----------------------------------------------------------------------------
 
 androidGradlePluginMin = "7.0.4"
@@ -38,10 +38,10 @@
 jcodec = "0.2.5"
 kotlin17 = "1.7.10"
 kotlin18 = "1.8.22"
-kotlin19 = "1.9.0"
-kotlin = "1.9.0"
+kotlin19 = "1.9.10"
+kotlin = "1.9.10"
 kotlinBenchmark = "0.4.8"
-kotlinNative = "1.9.0"
+kotlinNative = "1.9.10"
 kotlinCompileTesting = "1.4.9"
 kotlinCoroutines = "1.7.1"
 kotlinSerialization = "1.3.3"
@@ -59,7 +59,6 @@
 skiko = "0.7.7"
 spdxGradlePlugin = "0.1.0"
 sqldelight = "1.3.0"
-stately = "2.0.0-rc3"
 retrofit = "2.7.2"
 wire = "4.7.0"
 
@@ -265,8 +264,6 @@
 sqldelightAndroid = { module = "com.squareup.sqldelight:android-driver", version.ref = "sqldelight" }
 sqldelightCoroutinesExt = { module = "com.squareup.sqldelight:coroutines-extensions", version.ref = "sqldelight" }
 sqliteJdbc = { module = "org.xerial:sqlite-jdbc", version = "3.41.2.2" }
-statelyConcurrency = { module = "co.touchlab:stately-concurrency", version.ref = "stately" }
-statelyConcurrentCollections = { module = "co.touchlab:stately-concurrent-collections", version.ref = "stately" }
 testCore = { module = "androidx.test:core", version.ref = "androidxTestCore" }
 testCoreKtx = { module = "androidx.test:core-ktx", version.ref = "androidxTestCore" }
 testExtJunit = { module = "androidx.test.ext:junit", version.ref = "androidxTestExtJunit" }
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index fa09465..afcdba8 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -1,129 +1,2028 @@
-pub    1861C322C56014B2
-sub    9A347756830C4541
+pub    80C08B1C29100955
+uid    Jake Wharton <jakewharton@gmail.com>
+
+sub    CF771F914C2A4A73
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEGVK0ERBADwhGhmOMvSgvGaqHW3ial0NS80ZXyE1EeNL6ke/WrXHB4dT6if
-inoAuUgRz3v9Na4rjSQ8YVFjn3NaZq1i8RM2KJOUU8ZkJ2AsrH6fqStjofLTd5ng
-iQaq2wLM5rTQfdjLsGQb1iDNDyCXU56+/l4mFZ2JiEGCq3Re9EFHelRBKQCg/7k0
-BIfyoFVTHw39PKaDBmCYF2sD/3CMD0J/WldhBM7gLOndH9/YEQaEMy+PJNXcfTWN
-WLygGPSOQdNBulyLkvcFIZjUTxFVakh7FbjMq3dsAP1oqthwmK7L8A1zsvRgp/TI
-4YMHkZSkgcs0PBBby+h/lpgRrWmtwjTPzql/K5xX4VSRS+umHye/7R+4ZEH7mABa
-m/ZABADkPGG2ECvfjNosPQDHZVFuF9oVaske0OjzxI+rU6sR1fJKtbOPl9d+bgz+
-df7rZ3mwppkPX2r/muUbd0CM1Se10sK7ZAoPYmWqHX+vB/oj3Jq+iqb6M5mDZzEz
-6h4hdnaGERyxbktZvhRV7Psco9CGi8o7RFUQTR79Y5ElnBavqLkCDQRBlStBEAgA
-9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt
-90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcw
-Yc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZr
-M2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEs
-tSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8
-vYlLIhkmuquiXsNV6TILOwACAggAw6kL0PhPZ/EPI0mPfmIYeaKUgTB8q47nDKY4
-6wDs1l/msVJHAVwGEBHuxmbC7r/qfAgfSW+/Lj4XbSLCqaZIWSu6lfY43IOIYXD4
-pe5cCnWkQij+h3LxRR6uDmBr5cwheHEuB2sMFU5lJiiQR1+eXYkPNK4FgVQpHLWe
-boODAlTf0j8gRR+aTs5eWXqfSA+UEsXpn6453bfZKELXkRmEznb4xyGWJaLW2Mlm
-aRlauYvc61M7FK8z15SSZbq6oictpnEcfkgnBxcNza3jZQV7WOWZ3BlD1nKQ661s
-bmS81/nLnxbov9ASs25K2olXBsHkERhjMnERedvv7avlmBwi1ohMBBgRAgAMBQJB
-lStBBRsMAAAAAAoJEBhhwyLFYBSyGTQAn2u/CvPzKwRv1FUkPYR751j9PGwDAJ4k
-Pt2uco8an9pO9/oqU6vlZUr38w==
-=alQS
+mQGiBE2fCWARBAC3v9wYo5kmynmVP+43ccamidflSLQjjpsXpSDLPFokGxeuw0OC
+QJy46m8b5ACoCqRlfwnRRcEHxiSlaBATJA6hi7NRO41R39C62JXsIxNJR16JNQ5k
+oG/NOAraw0E1RQIFslznQexfxPg4yFIVrsFp1wkpCRrCklatPMNap2DuNwCg7PWJ
+1vV93YIsaH0O2fnXz3E+6zsD/3cTzUWuySEDiCLNO3JYJm97v4NDQ93encP1Ooxh
+n+PSIP4GvjrAObh3FfWUucv8UGqcw5bAL7dA1z8SgKeyFk/afs2XofXdvC+PhZqC
+DwU0NiE0D/tDWqX0qIG4ezTU2uk+5dE/WVl3R10nOBgquQdWIdYKGfV4FNTiEduD
+Uw7fA/0XcwFom7eyR9eBonQmgIadljztm4gkv11lY33V1ZfJNndPKNzwevDwX+om
+/VEHvpEfPx5toD4H523BPx55ZtfowuMtFHZI718alpCo3h6xaDhGwXvsg3s9k03k
+rfxzCjf9qcJX1gb2JVZ2+2jCwUDQZeEwV2vivjGNiN9rShWW+7QkSmFrZSBXaGFy
+dG9uIDxqYWtld2hhcnRvbkBnbWFpbC5jb20+uQINBE2fCWAQCAC3lOHYBShJ/G9x
+NS1E9ubL71FF9pLlS0OU86JAus41kKz3oTpbGMfnsvEUjf+gOawS7Z9c++a6Kxd/
+rzeZCzwM/Mdk4egsXepb59w0B37wy9GB5adAGc4R8eaIMicXWqsMzctCVsWr2hRj
+em/G260dTX9PJKv3eXTXvjRlXQV3LqlKOo7dVvrZG57ZJUuXvgff0P+C/HWJJfMV
+0SDALisOofI+CxV7HusZ3VnlrUyJH2SJs9H+3C0FeV+0Er/dItSn80/YS4lI6cKj
+8nbUzbgevoHWuuIxTYVXL4FvoezB+hU/80rLNiYdng0eBxa7+xCUkvHSgrz6McvB
+JfKUDBv/AAMFCACF6vq8sOOL6B/yHW700LSuLef5afzo/W+0KzEd7v4kMTOCt3au
+61GwPIY3TDN4HzLtdweKcxraXH9uW+DSCEJIREvfglA0A2BxfoMJK8BGrHG3X2GY
+iwB7XDI1tToPiIU2PMA7iU+CNaarpks1lfFMVSXLajVE2NnlO9efKA+fqa3QnHkC
+288aChbbtOepGdvuOr+mwJfIP8PFqFTkVLh67rryqITFTx8DUMLOyhwhcvWAq+Mi
+EH6gvIPKCE6pYFGXGWl8eivjZ3cAOiwKFyS9HnWmTmQbhauR+xZK8NO/jiEBai0x
+nBaUddgMw4fZZrciUPJ1X2+iIwDksAT5RGVkiEkEGBECAAkFAk2fCWACGwwACgkQ
+gMCLHCkQCVXefACdGAPMb9FOTnZvLttQb8sYxkt7QWQAoIBej+io4VD6SAGE0ur9
+07c4ZCXa
+=7AnO
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    571A5291E827E1C7
+pub    82B5574242C20D6F
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBE9iFawRBACJb4OMk3zqMDNvSJKYZ8fGYrPq7yCcf/ykKDkGb2dtPnAZGkSp
-3mmNlTsU6s9ARn7BtkhIuM5TdbLs+z+okX62h3F0WW3h+CpfIXyKSgl7uWbhZ5G8
-RSCCRr7A8m6y83npkTVDW6m2oFN2cjFwPLm/vxg1gu5pO+NCwz5iBRHdewCg1idO
-Gl6gBAZVNteCRMVnGnX4EhMD/RaYBO2j511h7gR+p+6BBeJTEIA1+tsi+GhTBkS9
-mUMGuD9Z8PyvwL7quGQyXJ/kTe3eB6iyDFn0oemB1w736FQe3vcIX6eePOEiDZs5
-1Uepv7bXI4wn1i3Z3kzynXNKcjCd5ZxAmML5VlQ0zWeE0W18reCjt1P5q5xxBFjw
-0L8WA/9aPi4d5VPakzuDvxfKK29BogScTLn2C3fpEnqWsTfpoWSkNXkRsoB4jUU4
-oIqRFMTxwsjUmjVUPOG+YqoeAaVpj+RBpp+V+CqgfNWpnH4caxzODE9f+6RYRCGm
-LSq/6OmgZg6t38M5XWVpvk7Ixygs6Vrd99VZyIQPJwSBM/pvAw==
-=dENk
+mQGNBFC1VWUBDADZwqBEEmSjwy2JADG0qCpvVQzC5KszL0CjzqTLPMBmLKNuc/36
+26MU4yI8Y+pcCTnC3LN9hrI0hxiP4zFFFyLYKkUWCZRAwj4OQlnyTDKa9frKBMed
+PJtihlQAKeCtMh9AOXNa+hZoAAEG/dfIOJhLyZB7JEuuwkil65R4yLrdnbbhPYMi
+1k0GJsaxG3IhkR/XQMO6m1KnThxyk2GPQNLFHUVSN+Gqz9m6u7oUxhhFjwUj3DZb
+8oGcQ08JR7IGdB8qV+XC997MUGjbRRu05hfWJecR0Z8xkprsdKSbFjuw24lZtsfJ
+w8advblczq//NvaUj2g/U/McoTPKoWXDFSPtw0UydazGtBUEM7SFer29upgyxA24
+oHoT4qUj3+lelhBbsf79YuI2M+q6OfeWXfOEO6xkcw54SmcvfYYatGg9UBiZq9PK
+oUfyn4IOKhxPY82N35tDfoeBXDAwr8r00NkFJl2vHv8QkIKQFF4HWLJw/aElij5t
+T34qVUE12H0+oikAEQEAAQ==
+=Uua5
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    358A4ABAE72947C2
-uid    Jens Nyman <jnyman@google.com>
+pub    840B2BF6DA8ED8C8
+uid    Phil Weaver (Software Engineer, Accessibility) <pweaver@google.com>
 
-sub    B8EB751F2C19011D
+sub    43115D7B115DB0C0
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-FFbW42hpI8TDRfB4oHWyTsM6zYXNXw==
-=zYIg
+mQENBFSR0DQBCADw8XL+xgFg9WVPknAIqqb0sUIZ3yNNr8LkuNtwQXnwAcSJkHSt
+C1k2CIKwRPPfcLsb51l3SpxFTs/s5yhyiknDfjqP8IFtLocBSsn3kD4VRjcxFQhc
+0jjgsTr9ZP/ZAWMBRIuxaZtpe7bpqbLbV9lvqjbOnJzASLKJoUngZAXvljGrWGfM
+3+A9z7SdrilRlA4DOZNqPoxN2RNY0QOwHh8Wv7+R97K/VQoAbvN3tQxlfn5B2scf
+WL2nWoGRS6OuO9Zp5/W1twoVdf4d85FlpNFFM1xzT8f5FpjF5QRgQD/Az2XHnObn
+ukG3ZPEhgwBIwx1Uw/Y9aOceXke9vaGEsDT1ABEBAAG0Q1BoaWwgV2VhdmVyIChT
+b2Z0d2FyZSBFbmdpbmVlciwgQWNjZXNzaWJpbGl0eSkgPHB3ZWF2ZXJAZ29vZ2xl
+LmNvbT65AQ0EVJHQNAEIALIuFrzu8kQ/fFJ2FA51e+ULp+dy1ZYrZqJdTF5pMdZI
+d711/zN9NExsTIxck6Vx9PYYaTreaquTkRIKnFD4XH/Q5MItEiiKHRtwdyhdFqCK
+SHaaNSGqldFwWZK2zh/x7OPk0ybn9L46E4+Eg9Ie+4WdyTxDKoeYQYl9asjtZPtf
+bNLad3UBvGAeyqc2hbePSxiNifNecTJqzBpW0voJ85vTkuRa/Y3wBdkfyxRPRofA
+IjzwjyIXCLQQFSel0ok6aV8nToOp/j+HST4L+TVnY2vYDW1UWQP3y/suCp0jtz7/
+ygEyTie+6P/LEgLfp8LKri0jJqxiRUXA86tgDiy8x88AEQEAAYkBHwQYAQIACQUC
+VJHQNAIbDAAKCRCECyv22o7YyDOiB/9mnGjQdqXQ3NWMiqAliYnPEHYuNaP1UnRW
+rXpAHpRnQ2L0mWTHrAW/f7P6W4isl+oUKbURBEItgYY5f4/nIfp6TMrpD2ej91Q6
+3gQw8KLL1x5CpKKLrv27w2SzE3ZGc9PYRuvW5rPqIXAdBYpznGKoowszWlRsgpw2
+XShuTEeiM2xLghmb2gSnU9l5wXFzVSa0PHvXoUIV6YeO1wym9bvRdvmAhf1Aimvy
+Olpyk826vmI65l0OSbx30N67RaTik2eHYk1uQ1WlnmgeRB1NfTANUMvaDbrFsbOl
+iPJm3ncc9eGhJ74hzl8WGUy3SseSYYRhm4MK4YpKCJtCTWxKdYj9
+=Fqd4
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    F1F111AF65925306
-uid    Luke Hutchison <luke.hutch@gmail.com>
+pub    858FC4C4F43856A3
+uid    J. Daniel Kulp <dan@kulp.com>
 
-sub    EF375EEBBDEFD775
+sub    594E23256A36A392
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFS2J+0BCADZI8RYk32YeO9gnEkY9RN+4dKb+H1AR4v+IGxmy0UYy+O8bo4m
-YzkQHTlPpEPGe10/quKk1embDifEfNa9mwcSJl+XUPFlTrSA97SR31mdyK/Ua146
-GKMW0F6v8aCgLUlm9BCJo/OmOat2jsc94SuKnPiRRywhmapte/8o9t7/0GghqLyj
-X+Ifz4WSKyKZ8oe9mRFg1ZIA+z52a8QnfyI8WS8bpGHM/dXkBXZpzIDlrfKvoZYb
-I2DcbOotJK/ZzStAZ81e4E/q2BEw96NUKJC5X+G8qahEFNJDcJz33UAxLiTFqWmw
-iKLqy8oL8p9qPYlx0IAXoW/GxV7E0rBoA95pABEBAAG0JUx1a2UgSHV0Y2hpc29u
-IDxsdWtlLmh1dGNoQGdtYWlsLmNvbT6JATgEEwECACIFAlS2J+0CGwMGCwkIBwMC
-BhUIAgkKCwQWAgMBAh4BAheAAAoJEPHxEa9lklMGaJIH/jjzVBHF28G+gYmktFGh
-zhclmHsEvfqNEgaWkjyUOVTlccA5Ej+8GWrumWqX9PJbHoZVJWeVikkjFsTltspx
-bQkIv+hygvqIyMBJLks32pLUCXlWrxOnTFTljWzPhy3TMeBzE5Zgt8YhHwyuLGRu
-roOnYz/1VDY5SHB8ST37VAr4lZdwslAwW8RLXAXfQfbKnMCwjNBZf4FmllZk6GWM
-3YyaTuWtQN0qEJ7y1BZJYZwKC7EFGk4viTuoU3gFC5uI6idcmFFBWxgYmnkbQilc
-akbBGU7qhsTyyAWxPlKZg7ldQoLFrZgoO9CAdmLLzbCyPM0w3MpPa4Szw1nyJb5r
-Qjm5AQ0EVLYn7QEIAMde+nVUcozJy9dzLCUpn91SCoWld/wTaSckxTnVMcr4uNLl
-JI/2PFjMb9ya91grr1yuwqSG3jE8P0Qdk9Bi6t6NkMIGUSJuzyIipsDDWaiCfjWx
-s7seFd9c+rgcH6r9CaUbNRfUrPqEZSeL+RDwIIz1gQkXmosF94DjZHP9abZYObH1
-/Or64CSRD8Ocf6kTRndwJOZkRdDtUX5NPFSiU17E/DoEkyryuXMR+Ci0b/hjQ4Jn
-riGeyy6c0StWQUW18SEYPV0j3VyRRUcOLhJajEu8KU4Xaaxgb/2X7o/BosjjQ8BP
-PUdTz2wRluU/1tKUQ8D+O8QH7dCR3lJt76kKWbsAEQEAAYkBHwQYAQIACQUCVLYn
-7QIbDAAKCRDx8RGvZZJTBvJ/B/9vrvZR1pFqDfux/ezze7ovgYF3jkxfQj3Hqgx1
-GvLYdvNacZiJG1bfGRuoEvLPv8lPIfEBTSqJGxzRiEl33eUUXlatI20Dh4oeRYUE
-70hCfqRn7cqITJ7nXwctMZGtwSLduNa4+cjKdSaWq6kffpQVSLrjvJYyxk8td+Nv
-CLYiTDnyybAmSGge44RppDjwGsQ+9X8wyd5b9hwcBQOY4UTm/6RPDJF66KPlPaU2
-qy8NeQB5AcO6goAdGI9WwOJuxg9IzULwpCvRYB0chLKkGOBh0vuyQbHoRmI6gs2K
-/I3i0q8Df30ObL7oBALsr2QfkkKatq4qx+xU7QMdeMs8STRj
-=CCVw
+mQINBEqQOcwBEACdPSfBAkHm1b2GdOjB3gGerx/JDn3zYNnNpcQrM8Do0bxDwlfT
+qwLA0P9ju4mzTfHU5kEvm2lrXz8QCZPLe9eY6GxzzSbeXtt+4fP84/YGmsK6DQTy
+eY0Ly5P0ml5IQGPkKAJ8clQy3q3VYsbPme238qbiWLsGNR6dpd5plGogFsaxvMTr
+bwnDQOBfHPxMdTg78mBpA1IYsyoeanmasmag7yHPGmPXiO8B/mN99BIXDshvm0VR
+TG4rEM98TA5hGSQN94wjRrmd5OZnQ4ofkrFkalyUmbmXQvfZd1B+0N/Rglrh7VdD
+LneV+vAZYi1oD/PXSqYEydPcrCRcu2saDMECIQ0EQDdnUuyrfk8t5jmJLweqWDz3
+gPevGArKYcwBY1jXaymBLKA6Qzx6NH02LvvhpOG/PyzeZEvRDUNuV5xMjl8WJ0Zs
+YCaS/RtHOea+uvzsO1DeX1AbJHSs6oWLqMohAcw1q9MPYMdO5Q7Q1pfr+6jNNyXu
+TgywqGif4DwgudCLhbrcCKR03Pfh1oQfeH2eM1pkgBJsXZDQ5FWWCM1i4AniHG4P
+L0WtoTciEa8ZqsNXnVbcEfNxOjkfJ3xFk/kV2gtiq1WB3RqsJxV0WzBJU/eXdhR9
+rpoR8TE/DaoSRXHn3NWcKAnorpRi13toHDMxJXSnaOkGuJCwh7PWt/OOOwARAQAB
+tB1KLiBEYW5pZWwgS3VscCA8ZGFuQGt1bHAuY29tPrkCDQRKkDnMARAA53uwLarB
+b1652TGHJhG1jiiU94UusXzQkRpSysZklH4ZLx0khOxLu0tvAx+j1DdfFJoKMPfd
+9Xcv5n2VcmVEL7C7MMqNZP9/7RShyBFHiTNqSbQ0XPGlCNu9G3gT5gxgRaO3giJh
+sQqMyuSi5HXuXkRAZeYZQhPlMWFBytZuoV8Hn5zRLC9gmDm3toL39e1QkzXP73RQ
+i8rbWGy2P48J50TuMqimWO5oglD0Wvx8ZYQrpLR76LD4ob/sytfjoUc2rUhpCOyH
+7dtn5eOCIhvzi3HzRWxRRUmzUJocqJaHMv+iq7IrqmrGfNkSUTJFed10x3UbB53Q
+2CvUNvjrrbsoN+ini24NrntlFUegiWIsGKxokpncPzEHJNdTgc5/FSkIInnkbWw2
+moKZGJNTfMg1hOycx0PjzfLRs5eak7m0Jdxsw0prneI4VBuKLo0smfqloiD33+st
+BoAD7u1otkqZzWPFlS6UFk8E3SVadMX1vTdequTBfrgilCFi03pbqSpHogUPof5e
+Shl9VDJ+250pBlL4Ok+jFxVWs0SrEi0Z2GgoWlD9zxF33wLsPYQFOXee30fOzLoy
+75oT+//5iW82/Oo/57KC7f1kGVxRnzGBUMly+oU8BnUqWTLzKo/ZNI6qM9hIzQgh
+LCUf7J2IzYP6CpD+ZJo37l872Ct8XyFjGHUAEQEAAYkCHwQYAQgACQUCSpA5zAIb
+DAAKCRCFj8TE9DhWo+03D/9qYFDVyjrOs+1j0QvKeeEav5bXHBOxLGhJJjmhNfS2
+Rk9zs9g882vl7s2scytcmbcxgnlFNTS+U1AE3QPotETPEwvgr6fX+4EnF8kCwWLX
+PP+AdRVRRiUpgnAds90iM+nmpcOtkXAbQtE1H4R1oQI+CnxhwpHcI6eq7w7qdsuM
+SCv4h8YoSZ0eXWWOAGPxqf1m6t2T05KUkkB1bSest1wrBBbDhHqvZZgvysv+OXA9
+68RlX2K3Qj2pYxwgtuqt28Ogp3ix+5uR2TyBCEYE7gsigwZ4tESvIUNX6nHUClqS
+Yen7tSzlf06RF5iXdV5Z5Bo2g+buty5gEoE55GuvjzDQSq0Dl1Jc8PhgCTF6LZ8K
+On5Q64Dbh8sKm3ckOwYxV+FZIXlEboZWr/8oPFrqT7y5b7WqxTsNlY/evdAqBX5Y
+mjrKFQ2fDQT4dNhOVevscgmihYrUgYuVsHQH+KHRX/vd6TShPNScc3qwS5VRjtzA
+OU1T+/LZesxV5T7RGD4Z4LixasaVQMfkfUE20naYyExVIo5btDA79kMgyMe7lFQZ
+Q7ZpkhkE/wfyYzEUNLhfyvBkIK0lgfBct87TKiu3VGgR4wp3VzpVpuf7UjNU13Hq
+8XBubxdyltqZ3dYQx2q/id7vcQJmh6hYxSPHSAfGm+9ofMko2nhHfZFfegchLaZt
+PQ==
+=by2x
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    85911F425EC61B51
+uid    Marc Philipp <marc@junit.org>
+
+sub    8B2A34A7D4A9B8B3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+PXCe8La72ukmaxEGbpJ8mdzS2PJko7mm
+=Xe8l
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    8614D6AB265B4C63
+uid    Antoine Levy-Lambert (Apache Ant Committer) <antoine@apache.org>
+
+sub    8832A83FA3060393
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBD9AzmcRBACMqgb7IFvC/nLxw7mUAgHENeZXY3JOQJ8wVBevIbbMEeFvzHE2
+diFydqUXocPexduYr0ahkf033WvWdAiNqDLfVW/HFOsc1TpjbHkqPUHtJ62Ya5tg
+nH4UGN9BYZfMbfVDOSz41lYwmfK5HYgpZN/sBQBSKf2qgoFB+LxYaae8YwCgrWlu
+fYhf7fkKbbdSf3BGS67ggNkD/0VvkXkw1SEnPaqrkKGkPKomCTb2auGxcYYI3/rP
+1m+SGRf0gE1NtocmIEitiR6WvfKUjoMAXSCp5KdnUXmO9rwzkM002KCA7K5CY+e/
+2bLDuiQ3rNiD4mFfG6M+UnmZ+GMFba1p9Cp4PqLNLsCHz67t7hEsscTZQ8mZ9xKM
++GCsA/9P+XFM7JDn9MLhYab9qo1CkceBkthUP6jWGjuAZ00elmBCkpkzNv5aIzss
+xih2GpaU/tmcMjw8FGp0dTwzqdpmbZBLjunRnuBTir4m4l5G9rwl4JbfK1PVqk4a
+VKkh9W7/yqBcEfNcsfJO9cqaQ+PzcnCoDiD9UHEBYzUhrCKwhLRAQW50b2luZSBM
+ZXZ5LUxhbWJlcnQgKEFwYWNoZSBBbnQgQ29tbWl0dGVyKSA8YW50b2luZUBhcGFj
+aGUub3JnPrkBDQQ/QM5pEAQAjaQX6otj8HqMwrcaFz6synUQyqgsO0zqw0epWz98
+/6L/9UjeVXNF6jcwUhqsAXJhlrZ3gAZF+5+LsyawucL1/02fw5DL8qT8njVTLvv2
+TJc3W8dOjlAyq+hcvzbWiO3Dda8PiIMr9tkPIpYYYLP+UXY/OBLSZFkI1UZpesF0
+gGcAAwcD/06soTguLAOWK3j2Bh/IuOodElPXV43xBSYowvL12fgTUB0FSt34xF3n
+WS/Gb76dW7DLuzLs/UjJ6soDNbp6djRsS0Xf/d9eaUIdFUrWCp9Matd8mziq9BrM
+secspdzc5bv9agEdHrP8zeI1e/yEIt0dhjr3s3KR15pG7GImQIbtiEYEGBECAAYF
+Aj9AzmkACgkQhhTWqyZbTGMXLACgkiSVAAZV2JywY2/lrZgM7tCY2TQAnRSeCiAE
+yQyv+WoxaufoqzqaHaB3iE4EGBECAAYFAj9AzmkAEgkQhhTWqyZbTGMHZUdQRwAB
+ARcsAKCSJJUABlXYnLBjb+WtmAzu0JjZNACdFJ4KIATJDK/5ajFq5+irOpodoHc=
+=HAo6
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    8671A8DF71296252
+uid    Jesse Wilson <jesse@swank.ca>
+
+sub    51F5B36C761AA122
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+RdJ+iwaDdWhzYdcKIgRuZ2bcN3HPa1XQ
+=qSXW
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    86FDC7E2A11262CB
+sub    59BA7BFEAD3D7F94
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE2kzuwBCACYV+G9yxNkSjAKSji0B5ipMGM74JAL1Ogtcu+993pLHHYsdXri
+WWXi37x9PLjeHxw63mN26SFyrbMJ4A8erLB03PDjw0DEzAwiu9P2vSvL/RFxGBbk
+cM0BTNXNR1rk8DpIzvXtejp8IHtD1qcDLTlJ8D0W3USebShDPo6NmMxTNuH0u99B
+WHCMAdSa34wsg0ZpffwQmRxeA+ebrf2ydKupGkeZsKjkLlaXNkTVp1ghn5ts/lvg
+KeHv1SJivWKCRmFlbPhBK4+mxSUSOPdoBNAfxA51QzZoPizSk0VbRz3YufYRVLFy
+9vqPSorDmYJhCvn3f6+A38FS/j8VE+8obQ2rABEBAAG5AQ0ETaTO7AEIALN4amR3
+pf/FN8oMFa9eAc44ognamG31ea1lkqIiPssiJLC9J2z9mShkrECbsBj4o+HxeN/3
+rwW2hQFAm8cAbitujASpPs46slp7Ylx6cfmrNqh3tOkg9BW/5izPwjXAuULovMpG
+PVf30eeDpf6huwRqyc9uYQSS6Jn9KCLi9ULxIeQOZi3UPHyMOCbnehR5aQQk70tI
+jbNytmFKC+DXFrhDiBjlRQruATgtuYYKMWUBO65b/SyvLG7zPGmHXmCSfg2qCTQI
+8xKN6wxgQY6x0PN9BeXa1du3497qYGhaHrsxnW/nM6rcQO2hKoOlY/GmicB5oK40
+MMVfji8aN/EYTS0AEQEAAYkBHwQYAQIACQUCTaTO7AIbDAAKCRCG/cfioRJiy8Qw
+B/9UbKogRzDhPYPeBlnchOR6gF69B3EFP/bvE2+hY5nIZLMZiVFtFCuWj65myN8x
+z0w29pKbHLLiAtVtx29Cvc8X/8bGmEn3xbymT2X4znuN/IeecK6afsw7ij1535a6
+KA3mh640noEird9/ajUOysS8MKFg4kQ54W5bG/67sjYAEkl6ns1sHIzaf08Ty+UZ
+TfNQGBZQGyTqNP6SUqcTIcTvpbN6A8vPeO0SVO7IHuNGGPJAm7XKIkQxuzbMfxok
+Y5uLl/wm6bi0gtm4QB2gjQzdzdVGrXZzP+8vL71Vdr+z//wiwafzySPLJio7LxYk
+SOg5cWH752laIzudmSBBw2Lk
+=HHpt
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    873A8E86B4372146
+uid    Olivier Lamy <olamy@apache.org>
+
+sub    1AFEC329B615D06C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEdddbQRBADRgstdUZq7ceq3NYcR5kpoU2tN2Zvg1vptE9FxpDbL73gdLWnI
+C7IAx+NNjdG7Ncdg+u10UZv6OSmhWAd8ubWcD9JxKtS4UXkNPHxhHFHqVPHuCwsQ
+q2AaCtuOk6q9OtthQX6LfOuGqwbv9uH/KLUDn91PrgKuHPVfVveiF30ZvwCggutX
+D0jTGRHzUJl7F1wViuckHJcD/2z76t0ObSuTnENi0IUjF3Toe4tv+qO+Ljs0knvK
+tu1b8A5Bs+kxNcbEqV+zdIph+6gCL9jy+dB9J+t6uZg6ACJexbIkDPsutNtbAVDV
+w5AtM7JR8930dRHfEt26ahFohFi+73V8RiA7LrmMjA8rX4zuo5Pr48xt/RR1Y/VE
+8ohCA/wOqul9eHHevxeEMDYoGVjGl2EiuIThg4eYuQDDSisBNb9a6dhE8ECQFFBx
+mGz32+I8gXSTKFAkkQUI4HmJmTX35nGJql6E7Bn5yM2OaOG04PV+xkhScJll5ZxZ
+BNEccFDL/aI4N33cwrLHyk+wFNZHBL1hnHpxpjFZYv5xfEBjmbQfT2xpdmllciBM
+YW15IDxvbGFteUBhcGFjaGUub3JnPrkCDQRHXXXPEAgAyqEz3eBEKiZ7VbAj96Ht
+IvGufKTdZ0ERJtrdPO4FUGVBcXpphtnPn+JOWomszUKkKLO4x24OaDCG/SENsPy+
+Ned4wjBB+4uV0YEc5Xn8gts3g4Z5p+YiVu+aWeYPPC5BPU61tVqc996i9ZYkZiYO
+s9F5Z+dKozk3KwVcijaCr0IQMjAtJ/N70zcciP23KhrN9Z3Nn54Xm7GezD0nxTUG
+P8gM79zKHnVhDBptrxIT/adCzU9/UX3UVAQcdq86FfzTEpqFG3TM75HBTQgHihIk
+kirzurE+ivh6aaF3UJwmDBe5Wu3gvxF6Rl0Ja/YBNkkCiOXngXSxwvUUR8KJO07R
+GwADBggAxOFV2DfMHsTBu++gKJ94L6VjETfVFEYPo7e4tO2Zn2Unzdxz2BoTJcQY
+0j6/M3Tl9hCwhOSVVL8Ao/wp1ykjgXnwV4vz0be4d/ZML+KF15x+8730H7Th+aR+
+Ug6K6Khsp8XIypmLJcYgYLD02PlSnDxCq9Fbv0JDlbr6tbsJiVzoRjg+WNEIB3II
+rJbTIiOFrRBhloinYoot216QJ1rI2nQpMEBlSuX6f4jYF6F7X4dAY4V4ohjFeJCb
+6SYkKbj4caqBA9OVrj3vh8v/vAUKDB8pqVhpaZicFpMd2pEEYVMEU4i1sLE3X73y
+9RRuaJOvPAx2HHT8MlWjsDmNdY2Mg4hJBBgRAgAJBQJHXXXPAhsMAAoJEIc6joa0
+NyFGZKwAnA7QdwrbR2IBqxd9SgqHF/4MAomBAJ9fA/O+UMDa7hOEJLf1tEYcv0ES
+GQ==
+=/u6C
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    88BB19A33A18445F
+sub    FF59C22B07640A16
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE//SjoBCADao3lh/I96fWIY2ZU49ljtHR4Vnzmifm3URFNuv/c8McWGxxCy
+Y1+oolgVuJcy4hCqcgbkwTiAfBhjZSmsC1QK/2Vs1awFzGccPcgTBakFw/TUav12
+6Zb8y72dH0VxxcN/HUGBUOSgZg9IMe7AmmVnxbJ2ED1I3/opkC6ElPXFOl8EJdgE
+Wvinp4ok3mwBGMIexQDyEN4DviuqvmB4K+gYCjS33HtHh4OrkXkCO5pDNUDgkAZK
+1uG3GfmxGBjdG6nPWgIuDMEL3j1cW9r5D6I5obXsFlg6bX8mBs91jAtmfTNv+IAB
+bwUOAJC+9C3ZEIsZOcBSSdUIXmuRPa51oP9nABEBAAG5AQ0ET/9KOgEIAOokxMbt
+TY2zLvdAWD9xPHj1kZPThN7o52A9Atw0zKjiNFl9jy+IFarPNdbMzwooQWgx5Y3S
+bKdSCSDlP74psEMOttEdw/23wt3oG70I84RveLuTs+dTDRAd5w8jxLXhjm+QxhiE
++z+peVhfe//u1+kn2vzesXMIRBdQTikjIZ3W5TMgu+RV7Fgf5zUWTEUTns1kmM99
+XPhOVh5BIr1kkty/Fyg/1Wg87leM3WZUoe/7bnWju+YSgjWvxwv8HEBYPKciNG5n
+0oOPoU3jkyEugJafmlhAt3CAgmFbfrJgkncXPvow2xK312iy0xIslAqm0dy2+E9j
+hYLlS3p3J8TLPGkAEQEAAYkBHwQYAQIACQUCT/9KOgIbDAAKCRCIuxmjOhhEX5s3
+B/sFcywEwoA4ylzSSsVctp7pjDczczlD1MnvCNP9ldzzU2oOGAduvF+zzJNL162J
+qMd1TMYnYROoZhIS78He+LriBSjCsweKDqEix12mtuWrAICpF3UcY8WLMB6SXgXP
+qnZS1cw+Prr+NVnuR+0G/cUJieVdKO5rcYuwrs4OGh2rEMRCksAY5FAMe1lSB4mj
+9jIGKW0B31D3/AxNlQuN1aRzGLj72k6d7Q91OrbQ1+yG12CLwSd6mS4kVBFjppUD
+JCKN+HD8NGQ9EtyiVpx2/gmqshFVdwUgAqQ4tKtFI713bi8xz/oNiHkOfclHdgMM
+E1GU2n+gEnCLRpmC3Qqmeb0n
+=2JQQ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    8D7F1BEC1E2ECAE7
+uid    Tatu Saloranta <tatu.saloranta@iki.fi>
+
+sub    E98008460EB9BB34
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF8kuOUBCACo8/VYVfmglgTgmai5FvmNzKi9XIJIK4fHCA1r+t47aGkGy36E
+dSOlApDjqbtuodnyH4jiyBvT599yeMA0O/Pr+zL+dOwdT1kYL/owvT0U9oczvwUj
+P1LhYsSxLkkjqZmgPWdef5EFu3ngIvfJe3wIXvrZBB8AbbmqBWuzy6RVPUawnzyz
+qZTlHfyQiiP41OMONOGdh/I7Tj6Ax9X1dMH3N5SkXgmuy4YHZoeFW2K3+6yIbP8U
+CMxrTNLm6QfOIPsvjDDnTBpkkvEZjS24raBiHW5P35ptpNj5F1oLlOxZ/NRCbP3C
+PlEejUkh1+7rOwrRkCrDnNFIQYmWF2Mt4KlzABEBAAG0JlRhdHUgU2Fsb3JhbnRh
+IDx0YXR1LnNhbG9yYW50YUBpa2kuZmk+uQENBF8kuOUBCADQ7CJbwnTEKfq4sV7p
+5ttwHGS7IM1u/Nb2sD5JPA8N53kKk463HfNVvafoko0AM76tHVuj0MLUsvvpzrci
+KVPidXHwLNScYt7JrONHL6qnHEkJM4yVLPe386NXGqc5X9PTZjZ3B0gqqngGVOyf
+lp1DUgXedMiy03376NZTu7LyxXLr2jvGovl6HmM08ZuqWk+L8s3B/vYZXsOpzGn5
+jA4w7AJG2uG43F4aQpEvSYo3Ove98w4xXc6X/mLyrb8ZLUVnw5LS2DHU2lZvujAH
+xbm7Ps2YzrjB3O9l4IqiO/Pc+ATnng9R485BnywPW36XEthrNPutzYg1yGNq09A+
+9SLnABEBAAGJATwEGAEIACYWIQSKEHkpgwI9XRTJO0iNfxvsHi7K5wUCXyS45QIb
+DAUJA8JnAAAKCRCNfxvsHi7K520oB/9flstx9P79JmP9qotnKHdvjT09oukQSfi7
+5FvFs6eKCK/a0Y2eI5WV0wLb3WOT1XpZSAM7a+QuuUHMIvmkcw0k52vhQ8yaCDCK
+jT7mkFHCixha6VFBb54PXkZ4e+9wPOvFw4i7R4qqdQRp9xe4OgWZjeH26Zy/lwGl
+uaIJmXfaVYHLQe2+evPgtBP3dFNI/WXx9Q3iy8K6bD/7xryK7frastmCg8yVtPKo
+FFknP5z1nHkLOpYTvz9RRYHcexiDSvhxvObWkNdfWM/gnSw/4+AKYWBH4m9rQzOt
+KfGcgIYM2uIHlATC0ILt7gGcAWmEj7bXEzy9Jqg9YirnHcrlYF0r
+=nj/W
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    8E3F0DE7AE354651
+sub    D3047B0BA4452AE1
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFMnpeABCAC+vckg+AqDG5Sg+GKbA5t2knu72aD000Qle1X//SjTvPHz0L1v
+rUNzwrqlmah17usczZHOoOCaGjSUFl3nPmBEOlLBh6L4+e2Av8PSbP0qUneaQVgi
+TQfbNgRB4v4H5dtKIglK1hZwCeqFazuRuFDWLHl/IG4ymcMwy/86y96BJKWrW+Oh
+4vK21DF/BRhyFGaIGwN1aPYRofy3ERsUfwe9WiPXXuYb3gvG++QuiS4V7UJwcAkx
+5TGukoatI4T1PVmZPk2zmeM2pHQRisHAScRt5YJ9bswgBphk1xHoENVQ3BYhzrsu
+a3hFDY5hO+UQiT+eIE38noOuKuSbRalSPelvABEBAAG5AQ0EUyel4AEIAO6MSdr4
+Sp59Gb+J8t5o5g+f4jMJPm2v7BkJzldN1JISoEWeo8iyCOVcM4D83coihMfN5Nwi
+7Tuc4tnZH00+XxYFkHMOLMPtCE7l0Ai8mVhFqE3HraCVnk7gRzNCyXeJRu+Q1TSN
+4QbiIEeonBSoGsAYafkAx1evBJtGmrDv0Y42NdocnACyRPZD0usxMARk2ZwQaqN4
+Ih5pL2MGXqMeo6uEW8iIIumnkMywXyZ0jbAcZSs9Smi3AdU8P/eY/Afpu4nyYVAU
+Sdm79eMjcBHRluvuk7db3mMzQPAepWQSYOgsbWq2BS/0rMq65M+uWo9MNpP1ZH2w
+G87qh+7nFIk38h8AEQEAAYkBJQQYAQIADwUCUyel4AIbDAUJEswDAAAKCRCOPw3n
+rjVGUXwWB/0Yq3UknzRomC9wi8sCh9Nv4erqjSP/JSoNx+rYNpwJX74jVmUA4u7p
+pzywCwSFKyE2L6pkgKw0y+KfE4cWsotlfO7E6VQQi/+cCb5OCxqf+gOelupuW4Co
+MSHKkPWXI/dhM1NMIW77+bLiiHfaOW3Wa9kBSKujiuFSp9tIq2gjTf/2rKQMbywK
+szhlBICdvYzji8t79C7tAJ0xNgZJJv0QHP+5MZJfMAARKrvtRP0I5OB1HYVJrH0v
+RbO9Y8PoYrPxeR5zQYxAyt36/DE+PM4CpEcCZ2D7Xrtk/GKe3Y/jU8FBifEebuhE
+HdZk2xusuOEx27cIovRPHwvLcgY+4u3j
+=oNWb
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    912D2C0ECCDA55C0
+uid    Emily Johnston <epmjohnston@google.com>
+
+sub    37AE8263DA3084E5
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBFu8+5UBDAC74QfHuMgQVUqSmwgE+zWX1YKY4w9a0vKrj7E4tRY8JXaX6GtH
+TWnOkAndsxK3kpUyRx8S7f4HL4Sxf05Tar22nrNkuiQddKjLsdlH7VIolGW1eFm2
+LYpLdChd3QLimsMzIQUND6YXAEGBYwJwMakxHCSuB7ExwRIb0DnVMM+a7LhsLqFq
+gIx4IrpgRuSSKRxNbgtlVYGqZa+jeJPjJzt6I2XouISHou43X82IurItzmqzg5B6
+UXNQqxEUUJBf9GWIA57MjEeyipzEBAHT2oR6yNj1dB/RuMbYpo1eq+QUIpxSvtLL
+1/krVeL2LU/z/weB+hCstxOcHPocjO3FpjY/jCF8K7j7HxLhPFO6taJZRKDs4tH3
+ti1d8cHQMu2JwK8TLJPaR6A/pRlRK3Z95pchTgW/ZeAfy1INSQxc2KfWSop6X4Ib
+PhFDaRHOJj7jKjQ59k97FAJN3UinH1ZB0olt/7PXtMBihZvvk4D7i5KNBj4MjDKU
+6P/727AxEERSOBEAEQEAAbQnRW1pbHkgSm9obnN0b24gPGVwbWpvaG5zdG9uQGdv
+b2dsZS5jb20+uQGNBFu8+5UBDADRdVG7GKTQp0fnj34zpntbfzMxImRrEZ4l0Ilm
+jkmmChTKyt0XbrfpnUUlFnQwaaEWQZTt5OUBU+VqA2G4H3ZnLyjdI76E7iURzAHt
+JXHpF+fo6x/ouDMC2JlXUveReR2o+5WO2WNw0mN3nmXX0vykibl/20SUWZno7DNi
+xeq8DUYZQAXMiDFNWwUQkKXdTYApD3CqGco3gnOoV3zFSLglIQiYFRMNgjjsMIGJ
+vuYyji+koVeXo5OuDZIZhl+mcQsbs+adpg/FiT2tu5YDRggFuSUf7DFzorJgDwH8
+AXsDAwbNQ+IW7P4sDEn2GglttzMXmmdQwPzHHKKTHC4gf62MFeBuqVUOQBWCgKdm
+N60vCf+Cz9r+1DBctkPzQVLj0VfApV/UnDxF/xoRKWLMiFXffDf5BBhmGAu9xxRC
+ygoYsyQN0teFvbqYX/S/4BD5maVDLGY6VE/PQnG5xwV2rFIgoEPZyJYCVS/mVczb
+Y9dHjBEJoi5M9a1XpNsLkO2ALtsAEQEAAYkBvAQYAQoAJhYhBFzjJZlqNSEzJq4s
+aJEtLA7M2lXABQJbvPuVAhsMBQkDwmcAAAoJEJEtLA7M2lXABgYL/i7OMbPiMydJ
+NpZK09xZarK0DT6+SkfotP0EcubvNrWJyEpyjQyFV+XKnZ3qgYEpanPnX4PJwmsW
+BrJJIVNjWt/8oJOqVnUDQ+aFHN9cOGHaOZ7kvxi6WeqgmXrs54VHYrebovdf7Aj4
+eHCBFk5jzSfFYyR34cnrbLkY/DyiRK1PPSIRnMW2+8YIzVZtsXD5ua4tEMLpIjb5
+qrpZH8Ahk7L7UVPlzGzx/JJDVvAbgnrx95DqaxWTYJGQCIFeeBQduwtUwhVjPgFH
+GatJdZ3HO6lZmKAzB5fD9yXgeJc8+40CeOV3QvOfvv4hdgsrm5FcsRSiioHQf3CS
+J9UGacJShxG0C+0I7BKdhPh1PWfiAeIeHywEQ30tferUPv/iyyGI0eZB3yQyezJd
+6XlB+HEk5O1oJYL1t7aWV+z2lUHnimg5F8PlawWf70h3RptfxxGymOiXvVQBITsU
+282nX6lj73aJld56jz5YEl6wbOtdFkIeOAWOUx/hzMmSQXxEHCKqGA==
+=xtno
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    94B291AEF984A085
+uid    ReactiveX Admin <reactivex-admin@googlegroup.com>
+
+sub    9D149DAC4AC24632
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFPzzfABCADK/wEIRhUCUTj00TcBOxGTPs5ad8jn5D01P7P5ILpLOgmnUp1I
+E3EYy54PQYjDIeOFvEmEywvwMRV8yCVhhYGpOPqbegKwcebXoiMGhJjuRf2nPbdZ
+PSB+S3/WAsdydiPiz/2Xl6hhlaKIQSnSOgYPOQjbDjgfU7B0vYGPohYR50fbOd9D
+QLvwsYxQv7CCdMM1M+tx4HevvYOKrceAwTe6yRx9PEhmuXYRCes/AKOs7yODvNm5
+SFFlZzBrYMxh6LSmCAGfYrSGWJliJUuFMQ9U0R304nmVUo3rrCj3tD25Kdr7wj+z
+WjtJVBdWVFTq2/Zh0QnF7mbIOs4bYxLlKe+HABEBAAG0MVJlYWN0aXZlWCBBZG1p
+biA8cmVhY3RpdmV4LWFkbWluQGdvb2dsZWdyb3VwLmNvbT65AQ0EU/PN8AEIAKo/
+Zv3JTODzEyEcEZA263xUgE2c5zMYFHvozhkW2YHphHdC6Wtg4K4atYXfIzkIJvrL
+gio4SYteaChzGB0ceN+XBPIL3VvwvEfk/CMHfgnuSLmkSgYrIHCKQnEgW2g4GKhr
+I4Tk/FuTf04KqG3q2tlr5sAxp2nSDfNkUJLx/UsqY9nhci7hVJNcSCgktuWuthGK
+9T29v5jcB74BI5LMFnqFkWvAOsUHr763Hq3I/2uHWAfJv0UEIXWqaOCd4IfwUMSS
+BwL41ccVsi38jiHZ1drZBgsrJdeeEdMplRyE/31yC55FDyTXgEMyEzCI21ehgFJJ
+Va9bI7XA6lzxwJePQwUAEQEAAYkBJQQYAQoADwUCU/PN8AIbDAUJB4YfgAAKCRCU
+spGu+YSghc99B/wOCPRQuZFOYqQr+IqnO+3oAnpKBvIYZtA7VXVqyjoCcG2siEbM
+ggfoSEp2abevUMmYuYgNpKyD2cdEqtTa5cNpT5b/Owm63g8ue73bTHRRBUB1tM0W
+xTflymdJ6BUBmMRv9S8j0eADoPspARF9PYJ1mB8FDuse0O9zkLPPMuSTrqxegOIk
+Jh+52vUM9gNGD1jSkPrZhTBHIsqZO/2AARWa4PvRHc/01sjfNRBEYSTw5Mcx5GC5
+vHy6ToZ0Dzsg8bs7e34e8ocv/m9wfUE+Ar9ch+9w2CHyVt47bkA3Zr7U5OhuwXRM
+wFrnxlbehImNdKa+M8n6XXmkksmKDvIjFicU
+=CNKV
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    95C15058A5EDA4F1
+uid    Eric Anderson (Maven Central) <ejona@google.com>
+
+sub    F57552EA2A2B5F3F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFUITeIBCADHIijQBuGmC+Oo/XE5qIXxzZ2cK26uD0tlDqaPhRLWt5RP3EbU
+b6X8ZLE2AlmawFzU0IqndrCDxSyuo9+ZFQRYT+stf+qHFjtvVQJh2+4L2LpcPrnf
+RK9QmmlDpKsTeS6ED32kYLDj7vwqrU+sdJcMxPViQ4TBq2AH+/pXoPJ9VBW0hg5Q
+WNehQ5yKireszStwEceRvNAnPffVJ3QVbOqFWQuxMboxZZnEmbpCot6hSCDTM+Kq
+3cyJkZTLm5ew9jHQGRmQB4sM8krQomokooSqUCb6YjPf5CmN5a4sB2z/YJMGbINr
+GOv48A9k+GDXliESyGyFUdrbZH+SCjU/LklfABEBAAG0MEVyaWMgQW5kZXJzb24g
+KE1hdmVuIENlbnRyYWwpIDxlam9uYUBnb29nbGUuY29tPrkBDQRVCE3iAQgAxVBU
+2DoqqDWlk1xp++bwITAmidoiSYfzZSbGyXG44/bc7uyjfgI9g84yAdbrB6tdKeOY
+bKThfUtY557GNsjVV7ugb/OLHLgZO1hJPXgF4Z6UAZgQtzgK2haUnpKh0iP/inK5
+l3KtWOBaVYq8NLTAvQy/S1F8/eHps+QTVPh2wJWvc7f/+oNYEWs8oKVYiPyA+JBk
+E5ktYzCNrowvWvUoH/Nbz2Yaz9k1CouOdd1KdLsNvgzOfkLQkWuFsiGLU8gItjHZ
+rh5b5lBYCtspBhGD5pJEZkRQXJiWjAz8ULW3xw+LHsmc0Pt9Zj7T68PIH52k9Dvl
+UfmscKlgRQhnM9QiqwARAQABiQEfBBgBAgAJBQJVCE3iAhsMAAoJEJXBUFil7aTx
+pjAH/2yGt/eEskSctj3Hs/LnAcNspHDnd6n9Nd7modwfWJIKUwQidERUTiO7wgeM
+4zRSw8rFNP9cNn+sNeOnx4ljHr5+0l+TdSzwufFBVxkY7ALi07+wGnL5nSkikriT
+I/NmPLteMQM9q4LvcDUGu0gozzs29rNXptvMxzntECLDOKBUbBKSqu6vw7gf6x4n
+pi0z6tVeXQPurllqFc9Bxl0KwBPpRhDFHi/HbwvyTjRlMDH+BpPhJFXa+42bXiK6
+MCAztF9czuXgte3QcJpliqK2DeOoUSC1tfd/vlTPvAearWZjwI2OWd3ZNX8211LM
+F4bF+wJcwQA7BYn2shYG64BjbaU=
+=LDsq
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    96FB9DB219F3338D
+uid    Trustin Heuiseung Lee <t@motd.kr>
+
+sub    684EB33FB007E676
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+RGI3BDe70Q==
+=ZoS4
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    971B04F56669B805
+sub    D3664677F6280E44
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBEzZjwMBCAC0ecfE/qkdgq8uJv1c1ZlzegeWH/lxW0W3SWK2RwaHx7LrfpiN
+WhxLkXbK6fkf86FN4579W1+9Qef2yjZCwTfLe6bqj3zZGQWSu7HPw1mmhf9lbhJ9
++TlxlczRt7m20fpSakGLIs1Jp7L4WJq3N5Ti6IsDFNOZdzGCpuiezzvp08PAD/f+
+eYABnWskOOarCOUrRJ5hV4FFj+9w+OPL25iaaEvHaAuqxvmahHzIPaT5v5Kr9Qiu
+zx0jdNaoq4/wJOGQ8rfMnXSjmuoMNgzTEs/H9ElNdBRfH50xYG6MACnVrZ1kGiCy
+z8BYBZzNUen+I0ek9SlMQDvGr0vRe4AeqlutABEBAAG5AQ0ETNmPAwEIALb8q/SE
+92Bg1UamGopUJ7lbqyebdVx0Fjf8T9MkEnteY0kvpEvluDaUWty393w4QRFPFCen
+Qtn5iyIiE0x+/xF5WlfP9kBMS03n6eXTs1pxgQ0YZ73qvzyZdOzg71isigrduA4r
+yXpoiTlWCfeStapimSUUgXxtsxFLeRVm14j0Xht1cvFCKpdxVZ9+vXIQZlyP2QqU
+zN46bwWwK2lNkKehkdSUPgUdEli/jw3L8rdASs6d8RqO/aiQN0R2kc9EA9kaRaQc
+mBboLsuZwoOCbyxPTpIZ7836b/KRuCM0sBy+RVNem1kv+905yWWJF32lZij/M01c
+OUnlnw6TVDJW5hMAEQEAAYkBHwQYAQIACQUCTNmPAwIbDAAKCRCXGwT1Zmm4Bac3
+B/4umKNZuUFKwTD+FTu6kRUOO2Rnsmk6WBuPm8h3ov2g6lW+2NjeeBib3fl+ehQ3
+IeRebLaxa0ZNAiajxbiMW5LNVC0hvqlsVAxP2Rv+DVoznI6L4I8vNEfa8ysbMY4T
+musAds4kbni7oHTUGA5bzvFgQ0ifDaFxFRvbn9ycDYFfatwDEbs3xgjewy1611zQ
+ef74Si6NR86Xit6v+056srmhZyV53e+pxGAVMw/qR6ROiMNrgLl7CPhtTwSYmSZE
+zQseNBFZpHUb7IGzk4B3ulwlhTcLnb7SUo5DhrBz5Et7XcQ/2mQOH1SrSEmoeyoq
+UfbLkuGneZv5H0KIMZ/5pV4H
+=3VLr
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    98FE03A974CE0A0B
+uid    Kotlin Release Key <support@jetbrains.com>
+
+sub    CC3328A2F49A80C8
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFhlXQUBCACoN2nTeSRVZnGoktKHyiCgeYQ/hEKKKDDAbWubnnQwonCTILaN
+Qw3GmIT6plmi9iy4rl+rJprSzDeQDZngQCx1KPYcXCrrc0pnjERDaogw9fC3c3z2
+B6+90qT6UJSTNmxMs5zbhgzKDWb3eaDmVDqVqzsM5xz9GxX6zo83o37fTFSbVbtA
+9+c100+KaAldVL/6uLeGoQsAIxtMH8GiOPiSjrw+XCQ5mbP6e+oYYBKxEyAgu1XW
+8jP4bF0rz2+1lkIGfWfYHZmMbmSutDxXqOXA9cZomhOayOSe+iczoxXkVXkQzMxq
+bG4ru5CHxPh+RSfpwA+9StLvzLeoFrBUlqW3ABEBAAG0KktvdGxpbiBSZWxlYXNl
+IEtleSA8c3VwcG9ydEBqZXRicmFpbnMuY29tPrkBDQRYZV0FAQgAo239WGQjltcz
+GgzZdgyH0w/PruwBqpz0SLFqf8441+3JxK05UcHRiF9D2Ww14shvqpC+96yS0jV7
+G/XzDFKk34ATCugwYNIN+LGGmBp44bOPyiZc5MFnsG/vcD7h0JV6hDUX+yzg6REr
+snHmMsztO5jsgbrhdJjLoPpC8w6gjEp2oHzV/olgPNXCzMW9RRsOpVAh+Fdy4IsB
+tjG0lVXMCV0YFZH/vZSrycTd6t555mMeeIANrBT5dHYSC/VowO8/zNSlaXaZHM4o
+D7VInJeEDnr3jfmzrTg9/E90RKUqcxiWKdZk28vmutFXXm9hhTa7n2iX+DbsM4XL
+fdQKsKBngQARAQABiQEfBBgBCAAJBQJYZV0FAhsMAAoJEJj+A6l0zgoLY3AIAJMK
+WFxboZuxFpEfNJ2dcM9Q2VZ/RQM/PRqY2nyZDCzKAv6NbRrC2t/HFKpu/7WbIxAH
+uDq0sUZxMf6Op+QOw3aulDb9yetRWa6cyOQKehLKGuqiVK/2jDQvsr4URGbGrlAa
+isT8bJrzugrfyi9dmYZSzv04ZK0B4SddeS1r50OVfefJMYznYcRpps8lG/94yivJ
+k+C/zpqFqMxTFtz0t2OR1WfCP7FrlTHplW48Yd6h2r4xZNm4oz/+pP25ds6yCIpY
+nUTdg/LginuRzid73nRYad3O787doGV2qzFSy1DRptle0BWPWPYij8mC+31u0T2L
+Syx8ZPwcJq0wXCx+L3w=
+=9nKv
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    991EFB94DB91127D
+uid    Antoine Mottier <antoine.mottier@ow2.org>
+
+sub    C327DD2B96A50E1C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=QLy8
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    995EFBF4A3D20BEB
+uid    Ktlint (ktlint signing key) <ktlint-admin@pinterest.com>
+
+sub    B89991D171A02F5C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+bZRG
+=N23Z
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9987B20C8F6A3064
+uid    mkruskal <mkruskal@google.com>
+
+sub    80CFA7C482552DC3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGJGMxoBDADF9xkWwxwN72wRh0al9ARzTTIHpcVBIjDij1Xr768zMMRdKOsQ
+aEHRTBKArAfGl6Xt6CfYnu3wMgEDUfh50s9NPOKvhpKtqdIlUxZLEJ807ebW3MD+
+BnwoRUe0OsTItUQA+vLH8K2Uywd9f3OV9KQnqItUFMptaFhUC144hZhj3c0xhITS
+k45zucoXLKO9yqA+tlqav7taAJMrWbhRcRWXizK1wOZLyhu8NdIMUSL4Ei0blR90
+uA9i62XlOhpyvfpaC7oRh+jXHOCFK9sXe2vnvnTtJ1yqdXH4EOCYLjoheQN1R0u4
+6f6XoAy9c3tOSOZM9vwE56iOZJwv0bca6ZENnhHnYwWhbQwrY0JMIon0sUpx9RB2
+w4E7AeU8/maQG9hdB7s7vrAJFarlFQvc7kJ5FMTKFmWPalUTcT6yXntIQ3+xiH9l
+Oq0jGlAmQWYUvzHJ0SFjz1xJGBDM3GH9KfHbeoS3Xz5Emmw8YwEDUe9gt9po8bmw
+8qnA85uMZY2puh0AEQEAAbQebWtydXNrYWwgPG1rcnVza2FsQGdvb2dsZS5jb20+
+uQGNBGJGMxoBDAC1ypgR4chf/OzOM3IoPIs42hmmEjJ59iValutsAWDCAlURaIhY
+ajUO7R/k/qDenb1AP3BImtnanPxNTBQiHCkLEDnRx5M/MReLnbfOepaVeY7B0G5X
+peMPsGLRkQuD5Cu6Zl9IOUAZvt9To7f1OjWYOqDdIjWPJsGTo46U9h918gjvbP7W
+yYRpSKQ6ld4ludfCqQBoHyNAGAaKRyIAJWu4/yMxHAQ6nUlwyPWFM4yOxs1hjHqz
+c1jw48m+D1GpZ9YALVXp+wQERKVhWfDchTmwwnPD3j2HrRu2oUWOCDoYOMP1eTpE
+lCMhm2L1dBWwg4CzBDa1QdiPsqaNf/mHpT7GZm0VFhKQ9cwCOPurfW3f4uPtWFyb
+gVkaJ1jQDDBkBAs/q2JHatwS0nYTXFeqYAz2dPXl7JbB85WH9VW5T8MNo6VsFDKr
+CVO4pjEKPhTJYZVWqBLAHIXNiloqRbD3VFfTTx5P3iP2yP6bdWp7lDxVPeVHCO75
+MFpDPRXpn+QqAmMAEQEAAYkBvAQYAQoAJhYhBBhzZqP/5r+PlLkTapmHsgyPajBk
+BQJiRjMaAhsMBQkDwmcAAAoJEJmHsgyPajBkW9AL/j9CucsaDsKdb8wjEfmJSjQk
+XEriC7PDd/80aIzM1y6BTggiwCkyL8mDrL3DGoae2jcDfQ2JUM0keG05mH4PSk2U
+B75/adKukDnNk3fhUeEDaQ2tUWhD3uljvjqvrI2YzwMuWFvvpaOkTxnQbfLQDXR5
+iNloZJ4zY5/XFS7v0rnYPdRUljwRWAsRmCLJAzIPWRJvFr7rFW/cORtATlyf5EkG
+fCX+ZpgG3zPkS1sCmONjxR1/hiBa+sYfMJRQY+AvA0hyCz+fC6S68TvToM1LzSb0
+EqsoM2n30am2UhVjLhFhp9Xj2zhng67MddOSBvb6FrObk8lDIvO+TSKAuZ50HzB3
+EWrOthmYo9Z7lqLhPl+CA4HNVcqvw3RfoSvEvfzrnnsmGUsXY2IKQfqjg2XZ7P8Y
+bq6FPZJMgigvJOCtTFvzxw/QUkgP/XZE0KtHq5kCdkdkbLNA37l57/+6EGJjmh5e
+1oqRDHgAffhmvyMjyB4YL48bYbjwFEar/jLCQJj/Dg==
+=pXEQ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    99CE9D9F22DC5C99
+uid    Benjamin Gehrels <benny.gehrels@gmx.de>
+
+sub    6C907406A9482E08
+sub    B2581403B6FA2318
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+db8iPkZR6t7XDKebY6X7pO/h
+=VZq2
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9A259C7EE636C5ED
+uid    Liam Miller-Cushon <cushon@google.com>
+
+sub    D66472CF54179CC4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+cFYKw6eZhSnlf3dtLjLzKg==
+=hIWn
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9AE296FD02E9F65B
+uid    Luc Maisonobe <luc@orekit.org>
+
+sub    2F3C9EEB05D1D1E3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+yfc=
+=h3vZ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9B1FDA9F3C062231
+uid    Brian E Fox <brianf@apache.org>
+
+sub    458AF764D812A037
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEWjofgRBACePEiXmSvjcjUgWkNAFQ/w7w2VSEqe1vuTCrta+ER9JsvhwipP
+2/BEHigFf99TlU0p1UC591LMeYP2UXfQnb3jiyEPKxA06aj1fTGGMoNMAilymvgd
+pcixjlSJBvsmyFYuUdYK20UghL7fAU1lD8Y7TVXz0XT0n1oMOwf78qB4vwCg/bIQ
+LlFGTwqgEBBJpFJnaVk66hMD/0wMKe5Lk3rfdm/9Ku56ddZ6GTjyuNFI6sc9gOIJ
+XWuRpZUO4d7LKq7QaKLKBQeAI1NqqZuB7gtdU6ILy7OjI2C38KTCpyu+8lj97CNQ
+gJqFh26lqhtFfMOUwKvNUUsEABDy+vnI+VCW32ZT/E1xjA+nVTSjGM9lyv4Gls7M
+8pd5A/wJ3rD8XDiriM3ZV1Sn7/pt9OBxc25YHhfbTinIQBYCBhTw3wbS3d+PLQOL
+/TmkeaZcuFA0KQW5hHEjTIY2YbOd2lPNa9ynq+/1OvJOGAseCWL8uorYAmk6ztkc
+Sy4UZuNbupNSPGOt0hZixQpSB3Tv49XlFyupd7rPnYi4F37nPLQfQnJpYW4gRSBG
+b3ggPGJyaWFuZkBhcGFjaGUub3JnPrkCDQRFo6IbEAgAoPx5Bm4+wUuVea7pqi8N
+Ts/CkhAdAWgNnsj6tS/YzyncXD6mjc9Sx12Y6DRCkzC+ZTvy89nt/IHOvbaCZ8et
+LuBonv9PyYXu6HmGNihqg8rBQzXUlbIPdZD/1GeVwH3kO2DaZ+Rt1EKjnloXlpwL
+GMnn2n9isWUCMWjyWSZbnNBca30tooXp+cWGBnClv+Ayez3jvroWCe9vVbj8/AWM
+2Pn5pB6Ewzw9SLmC3kgcq15XXBTgeeEZohuTvrmsNOHGNh9HFEp+Y56JD8ufPOsN
+ayRHW3ex8btx4sZhLO2Ixj25cOjDfoKZ2aj8ByCsJAsNU1qgWeyn/QTrrHavOTLp
+mwADBQf+K5Fi7IcpD+doMksWWpu68+2F4sDiHybwi1srkV9oy/R6vG0SkO4DuV2/
+k9rCquavHQSW7jXzfZuOoY/ErK/6/bd3GpLjZNR/K2ZNT2aOcHVFJoQTQgKf3GDl
+SmecNuskHpe1pUhbaY+zWKx+DMEjcwThchArABW2djcyTk0YRygxQwqWBPGI8sjq
+uxsrqKKrjallTVokbx9rr1VwCLcxg3HFI+GJjhHkjmYXJANSqzaPyIamcfR8wBQE
+V9+IiGx/EdRTvASx7uveg5119pPtwb0g0r95SlJpoYQe4wiTAagxkwwSb3qWktA0
+6gWykX5NQkMX0VK6lsNvP0tAOvY134hJBBgRAgAJBQJFo6IbAhsMAAoJEJsf2p88
+BiIxBmoAoIrGOelJKnwyAjageLevUw4Mu9J6AKCfO5KKtBZLsV3Wq6hCI55+iA35
+6Q==
+=L7x9
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9C4F7E9D98B1CC53
+uid    Benson Margulies <bimargulies@apache.org>
+
+sub    32E3DF6FC5E91334
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+Ushr2RLwEaWfWeQZ4Q==
+=9qBu
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9C538D5A79281639
+uid    Alec Strong <anstrong22@gmail.com>
+
+sub    81176177BB514041
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF3xPHMBCAC7OXU5uXXKttUU/BwWm6q08NBC3ybk0fNIfoITWiFA1RtxO7S3
+K4ijImBnLLb7ivjpTtIWzUwFAfSZHc3LgS/TBQJQ2PGsO4/AdaMAcs69irgfoPYY
+1sJkR/Iw/C1gi7KV8PR/vwIE5N6wVll42FMGjBvKl7wTmvuHDou12tANXWJp3X3M
+5qj4eMK5fIv11u0vPIsmBHQTPzZN6prxAEp8Dm3XDT7OCZxfCYsy1Rl6zUIY01ai
+/lOk6YAg6IjHqGyChlJnhQbmvu4kNrRiKRSElikiDDra1Ltj66AGD86O2yQ/21ha
+muWwm0GWkl1gd3k3BOy7EhvDTAE3RFi4f6TVABEBAAG0IkFsZWMgU3Ryb25nIDxh
+bnN0cm9uZzIyQGdtYWlsLmNvbT65AQ0EXfE8cwEIAMYm7+OoR7n96i2hLdipoEBN
+A9nIqBiKzID3gi+jlmtEbBUAJbdpZvN4Z0YavcBrNaa+F8yi9Knki5zIVO+MhDCU
+160Bce5lSLmw3gjyjSwM8RHtjZGoF9ly9T3wKBPOIl7zmITLVXHQ1Uk5J3nll4u0
+SN5BsXQw2WOtTiPiOq381HbQLQOsn62Afi0a6jufcBaYJLDOhdGvMQl2Sp/0hZfD
+DbUyOY5gYQ5IKVQD0vofF5Wtlfwhq5XV5V4M3JNRsLl5UCFXj/xOIwzopsFFSw/N
+bpNdujYdMC1E+y/MzaywLdBZXhpp8sE3sxp0rnVkoPVl42ds+/EZastcNVpcNm8A
+EQEAAYkBPAQYAQgAJhYhBJu8HD5AjKCc920aApxTjVp5KBY5BQJd8TxzAhsMBQkD
+wmcAAAoJEJxTjVp5KBY5k2sH/RRu0NdyOnN6GRHvddzx2PwMuDAwA2Hkmv90d/9k
+Q1c4g5G43a5aDQNqLSZn6A8LSNvao0rQx1NsdE0c8RxLRRfrAMFfQFwFxtbed6xB
+e/gtgljYM3xDS+3GPZFr/gV/FP6VmfcDcGYdG74Cmz2eYmgY6HTpOE577op7Medi
+aajwgPNLcm7IbPyZrb1B6bvVUMAyUs2DRBQ3dElzudIt3CgtQMlaamZZeY5HUkPS
+J7DKO5KYoe6LNE881UxuD1H54w8X04QKF5H4+x67ddOoLKp50QMi3BuG3LAFlpF4
+iTETdUiEzsIQj2CxUBo2Ch7pDsFciTdYwOmje3olY5EX88Q=
+=Z1yw
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9DAADC1C9FCC82D0
+uid    Benedikt Ritter (CODE SIGNING KEY) <britter@apache.org>
+
+sub    923C08F9417B222D
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+zW9k+nXG/umtuGWBaZVODvhr9hDoUpp2+qte
+=sNEF
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    9EB80E92EB2135B1
+uid    Slawomir Jaranowski <sjaranowski@apache.org>
+
+sub    E3F6790A5A167F5A
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=0Bx1
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A1B4460D8BA7B9AF
+uid    Mockito (http://mockito.org) <mockito.pl@gmail.com>
+
+sub    BA6D22590B3F9BEA
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE4waOEBCADHDHNTq1NRR5TSooIrKY0BTQnaLfjKZfcJOwp+btBJrOUO7+e/
+V3M4DZQclj/e8SBiVmRPK8Oyrv6i5B5+Ee/qNlLjWiO10AJ/PLRjYdoW1V6PlTm7
+2aUxQ/wNXxDcOoH8M7Y4fEqZJ3rFuta8ogeIYnkUwUk3gc5YKk7KJDbiOXQfRxlY
+9MeVKyoYfj+2Szaaz98W097Pqf9+7i3WjB3TKR1pnWlzF6rLWIGBJqcJuTGLWUAB
+hwOMoNiIBAqyGu8E4rT8pP9OueprOeIjyKgOBWV5yctIxd7uu51sGR47TM2wmMmm
+r/Kz8FkMr1efof7Bx4mJuup6wQXonRMVBqpLABEBAAG0M01vY2tpdG8gKGh0dHA6
+Ly9tb2NraXRvLm9yZykgPG1vY2tpdG8ucGxAZ21haWwuY29tPrkBDQROMGjhAQgA
+xDjlr6Oakgs+5d5NcIYpJ/8S5BIUaVlmjKoaFJoAy46WzvvpaTC022js1ZSvrM8w
+lSxSk+kD6/FAJw2pJwRgVrolOYJQmqLqgTA2QSN+leWo0x8gC1+QXzrquCOd7m/+
+h8FHUDaxc29XQ+7+HtNvsSxY9dtDzgQGXjPXSppVCSiDNy1IuIAxmEAFSxok12Gl
+xq/n2DFx6OnVB+5vvt0C8nQ6w0hQAQKPUmO7fNav5lZMfKgR95NrvF1Hu5V6DZvp
+bXg6+NWfA8LsCampARrou5qzy67hb/+KKGHTDMOvZZlGw6oSnPngqmh06QqY7P4P
+KVkOo3Vb6+02ltyZ95RgmQARAQABiQEfBBgBAgAJBQJOMGjhAhsMAAoJEKG0Rg2L
+p7mv2b0IAI5pDzLtBGxYhmO1rSDgY+JY7ZAr4srW/7K6Zc0RmWv48JsZOf7T78kI
+rif6jrF+ZwBLrdP93umMr9aJ/mJglr+0oag0ZVhEW6Jb7dgiRn8F9+qcCs6lyozA
+G805oW2lULkwqSJ1xNs79v9RtOWlI5ruLVbS7XhGv0qH+ly1xpIuYOzNvpOgj1pC
+3Pv+NuL2hrLUZVg1vM9eCM3TDVbDyJZrxKdMemMSGHHsXWHtn8t4BT88kice4weD
+q8GBl1Dx+ApO1+iHj779nMX1DrfaxtJLTRqH9fhHesISmte8fPiydGT/HCA9quKU
+uxyN4W6Uwu+Uov12cGV2sAI+H5qPhF4=
+=92yh
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A2115AE15F6B8B72
+uid    Stefan Bodewig <bodewig@apache.org>
+
+sub    6366592024774157
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBDsSIk4RBADSCj6rUjV64tYCGT1DYKYR7GthyWpNdGHSYLbETBcDatAe1dzQ
+5NsCgfrlybfyeY+y1lxr3T9bqf6zJWDw/718wff96qmmv1qzexSYtmIrj+h53V82
+EXwWOFuYMJisuxdT940iQzosm3GOv4MJdEg3oI2SgfEyRQQ6vO4Ob5rHDwCg5taZ
+nrHOrXx2dIGHxpxRZ0SUl30D/jmtttFjYOQ3LBMriikz5mh2sK3ZnoSRF4o5O0zW
+Ve6e2SFXOEjVjImKsH6KCbdQNelrAdgiyOoXClyQKsQ27pncbdWo6bO0E3POJZVm
+XaeW7iudHVr63rU5PViXObIQrdQl0D59j5brKj4vdlTyUw8kaHPvbKPDEOwvZq4Y
+LJQ5BACA1YilTeXRJqwFsNlpcxCHwlULD4QUVP496prQWf1B7Z6g0KvLGrQsO0Vn
+Jcn+fEqukysTJixSXCPebosltd4RalJIupVYkp4w6MJ7biaDAlLuNhDcI/AiXTmV
+dXUedVXIaM8I3Ne23gucwbAyc0Hvb+3cSAKRhl/azFQhuHBvlrQjU3RlZmFuIEJv
+ZGV3aWcgPGJvZGV3aWdAYXBhY2hlLm9yZz65AQ0EOxIiVBAEAM1SlkvEK5MrMnW0
+ybtv9eMCG89gqIvd2gBnpcAsF0sX+dCaWHWNy5HL3dBak/G3BJ8+NzAksfL5Srm0
+LVKcfVjBiG+IsbUoSyeJQGuhSZXYcnIc/3Z8Ujcs+TfFurG8uHU1cWnNK5aMYwDr
+qxmp4Ru0zLYHw4tHBBKF0cgFaCsjAAMFA/49aSZuDaatppSaBOzCt7wIYCsGBxX5
+ZibrJqr0gLUbhXU9eaWzCawOWwCvpQN0lTjoYVkwiLZaYUkdqsSQgHAU3jjKlIua
+IRXApEkTb8Jg7R/vNAdwXoZRLBCjZPGd5qGtnIezsZ2+lxFx+bRieUL8fUInemXw
+Wl8e23PMisgm+IhGBBgRAgAGBQI7EiJUAAoJEKIRWuFfa4tyDTIAoJ3NtpI/E345
+LVOruElFKrnduWWXAJ9Adm9Mz4yoxrosHSkp5BWzXBUt4IhOBBgRAgAGBQI7EiJU
+ABIJEKIRWuFfa4tyB2VHUEcAAQENMgCgnc22kj8TfjktU6u4SUUqud25ZZcAn0B2
+b0zPjKjGuiwdKSnkFbNcFS3g
+=JKwK
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A40E24B5B408DBD5
+uid    Robolectric Developers <robolectric@googlegroups.com>
+
+sub    6A2038967E03726F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFRdA40BCAC0zSALsOjfjr+gO8q+HV4qPWuIRB8S4z//jCEpKypyCRR9sA0W
+IDHG6OqG5fO1bP6VsHvSx32E8YUf0bi8eGgpKj5gJ9jmausRvRHtUHJ0pvZRBw51
+z4amYVr+NdVoyqLXBgBYeFlEYI04rQH9W8r1bCk8RKGJFNvO6ikTN9opLRkvZ7A6
+7VKlQGMd0sSJ3MAhzKUkM+ZWeCb/TG0xSrhJHcrFUORdV5zaX61anOTSst4HOTuL
+ByIZq1RMxKP4UJIWH2NYVUC1Bdn5CbY5mJysqQXjobPwG/cNAyBjsDBCh2VMnFY6
+geCHL3BowNd8gHUr0wjGKOipRmyfOJoTspMfABEBAAG0NVJvYm9sZWN0cmljIERl
+dmVsb3BlcnMgPHJvYm9sZWN0cmljQGdvb2dsZWdyb3Vwcy5jb20+uQENBFRdA40B
+CADhMeWEVcUNBLRWDatdlvc7q3jZEyejhSl3zw0I15yhoBbuW+ZnOTG4fkIr9SRo
+4whm2NZ7eemEnQ6tuGhVXUqPIxWAwBteY0ZBhwNGhMql+IIdOE9WIo82yV4gj1Lo
+2rjxaxG4Rd7FQnys5f+XyFZ8vaXpmpH9VeFjc1Ls550DUP8iVvIoKI65Ve5RMZc9
+e3AeP8FZqJpc3q+Al2f/FAO8+tiD/J849aP4aqUKiwvHk/nxle8FwepQyvXRrSpF
+Nz2uK5bgIXQrxgcKLPjl6s9l8SKnTwg6ok0EcJjGuHjzCeFNp/WFpAeJAxmAZ/qU
+br0TBp6jxXoMc/RqdO79MPX5ABEBAAGJAR8EGAECAAkFAlRdA40CGwwACgkQpA4k
+tbQI29WOzgf8D487fhQSsH87OJfpoSPf9p2wGzgNFAc+sb0gUy8rMmc/xySKGfZ2
+BZFT/CAQsOzGZ/KSM3og+FFgDcm8GWpSfZNymXnmM8aCaEyNj4arENxwhU4BEnKY
+Ff8PIDoCjAqBbSWuTa2RzaWlawEEg4hItheFmw/My/tbo62N4zn98IYU//50PNDu
+Db1lvOi4SVFglXRoM+jS2X6E9R3Z7sYceClr2EDN2k+RbvB6ngOiu52FvC9ZZPJn
+fK9/XHFtKcQ64yu3pbeXwiuqyr4TSpzGJNm7czyVylHZfvkZYVhmZCEG9xQ0lzHs
+haXmkfqi5ZJMEtXwNP1dWIMhIGgY4aLehw==
+=scg4
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A41F13C999945293
+uid    Thomas Neidhart <thomas.neidhart@gmail.com>
+
+sub    8183E80D264EE073
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+FaSYF1lb13TNIRT1q1My
+=MTP+
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A4B1A03FB9C2CE23
+uid    Pierre Yves Ricau <py.ricau@gmail.com>
+
+sub    21200D723F53CE38
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFy+swoBCADGyV4k02OjVCrziziYIvIO+qDm8Yqxt4KVd+ISw2DvmKVcP7lx
+z5WVGvxVdAl+Xy7FdcrIJYFCsYfFFxPz+BM6+np2c477HkdIcDwBWiHEoOqMehax
+wlEBhJdJUVCjTKvpMgqs4/a0PddNcp/odYx20HzDAK+X6/EgL1McZk03okfMSn0R
+TUvZeh76SbU0aQRXdGlSs5IUtywn2f+5jUNLht/TMd/bbAXWA2EQo1UallY3+dj8
+I/Y722X5Yu15rLu8u+pcVE/pMO9CHeX78mgPU2xU/xwDSGtU5lxwNXnYpHMUdFB8
+YtG/ofDtZR9+9Dcjhb3xSIv6Vlui9HgOgvctABEBAAG0JlBpZXJyZSBZdmVzIFJp
+Y2F1IDxweS5yaWNhdUBnbWFpbC5jb20+uQENBFy+swoBCAC9qndT7RGPdkVK2Hy7
+0CcKsmsKVs23KwwRiakrQmCI2loINvDmU+/vInJM+OcZMtJLarH/4LbYGaXpvuVX
+YmAJcDnin2xr0mnDkyKWLavH/rYzRWaowI1mLS8LEE6WPj19KnLF8qsgnx43Bd39
+dseXS4qb4BgImC2YETj4StJva0neIQ+pEGr29heebUsohlUofNmvUbAtLTf1R8YE
+W2UKEXsQPvBDhe44ObPl3H3a2Qjqy+q865dlpM/U8NOq7yXn4TzJ3eom+ieWgeug
+sptMMS4K2mfiMNI38tnULt6RG706MviAKG+z9Mmw/CRWRr+vDg5YQ5EpB+jaK/ri
+Dg2NABEBAAGJATwEGAEIACYWIQS5zKE8WfIcbOhBqNGksaA/ucLOIwUCXL6zCgIb
+DAUJA8JnAAAKCRCksaA/ucLOIxKQB/4vqh53PXrATQXZlhzhQz4nVt+pLYcR6wHt
+gZPCdp+LXjFFCiu8U4n4LF/IOeX0cYJt/CqJ7XA7tU1C6SFaX3nAlJw6vU2/dc+c
+erpEqkFCshHT16CB96B/U3rseaithGR8Dbl/B70qZs0BR8+IprpXKvHqG2JQgrVX
+sCspVfAEvSxpq106fCvE6IcoFvHLLaPJmC36sco1QWZAuKIi+qD6SuGxKSxExjOM
+bdj3pabQr8gfRdy6JCRVoc85hISo4PP6aKJL89KpvD5aF9I210p8oPE5LqasycWW
+6q2EnTppcHP5GZcY+3Mm8qcjYs3uXCgZeTnPKdkrwBelM6lYQPmj
+=5pkj
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A6ADFC93EF34893E
+uid    Tom Denley (scarytom) <t.denley@cantab.net>
+
+sub    9C4C23E6FFE405BD
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE+xZxIBCACzKctn4ez8xOC0pGThhAwjYWGkzcwK4HNaC1usHThBFz3/t8JN
+OqUXRixLyi5wELN6GHlsGVUQS3IfB4JtuhScsieSB8PTree68/knMq6JI08mJqZr
+9nFrAB4eDW0UMbSL9kPmclUm/yN+qcCZBrsVn0q6CWb/Kcd8EEXEu6sGILzOGqGe
+d433t5O+tGXWL2TjAz+Scsk2Hf4zcuDeQcxELAMnVaVgKuGuEZvibrjsdIvJDGI+
+0BzWIu8ZP8ldBl4SVtzGpEVzLvDUo3mOqBeTkj3rP7xLtFDN/3AFtowbLfL7L2Pg
+SMcTnKK+jfFHRfbHP1Ih3rQ4ilLzhCnY/QIZABEBAAG0K1RvbSBEZW5sZXkgKHNj
+YXJ5dG9tKSA8dC5kZW5sZXlAY2FudGFiLm5ldD65AQ0ET7FnEgEIAM3i3e1sjwrx
+2PN8XYMPQWG+/YTtw1BYDl2+iYE+LaZvtq1hpbgeCLgEVwXrCJ4spLP1rFXogWqK
+rkJ0LRjlpdKhKBvyH1ex4grh3cWN/bIDJcJ7JA4I/Bhqhlh8hYycS9pGFeS+MR3a
+FIsii+vadrwYYvuVYGeWvdZhB7mJKYevj5Ms0OpYTfZd95Pzo4o//lNpDnrG7Xd3
+tgTNU/fkpw6rFB/2Ib1Qlk+Kz1z6JNsp+tOPGGCBrzwfwglcikTuqS+xyRgC9cHh
+5eCol11uSoWPKcQR2Ar8Eo56nxv/UApdu15iJ7R8cA5guKeeS4jt0CGCPs2Phugg
+DxI73Xvl4zsAEQEAAYkBHwQYAQIACQUCT7FnEgIbDAAKCRCmrfyT7zSJPuylB/9i
+wtIQeexMWBmQNdDe0md8HLulDfcujPtklrvYHtXMJQFaGA0Vafq0oT9MhBfb1YCP
+79uF0qgswSxINYCOJx4nTPIP9BOdTwqfGo7ul27REgNq4lIUW0GkMgZAUA2ft/vc
+0u/I0PqnhKCi4Pq79hLIx7eiX2ySfXfYfLXRVzbMWKMoi7lWXseQqbM0RvCA54J1
+qAi6Ew+JyoYGQ7OvXdL5Eh5Tkm2cpIADyqCkp/aFDe5lqZiU1zS2fU6mpOf/o0co
++GoYkieIxxibDCmt3BioLgmyzpGUsMNwh4pAIQUGkcxd4spC0KIWdDEvq/QJEEIh
+ZlI/ojefaZkRseFrtl3X
+=qnqR
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A6EA2E2BF22E0543
+uid    Tobias Warneke (for development purposes) <t.warneke@gmx.net>
+
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBFJQhigBDADpuhND/VUQwJT0nnJxfjAIur59hyaZZ3Ph/KIgmCneyq7lzYO6
+xa1ucH8mqNBVNLLBhs4CjihBddU/ZKTX3WnZyhQKQMZr3Tg+TCNFmAR4/hnZ3NjZ
+N5N5gUj/dqVI2rIvypIuxUApl88BYMsxYpn2+8FKeMd8oBJLqFRJ3WNjB4Op2tRO
+XRWoxs1ypubS/IV1zkphHHpi6VSABlTyTWu4kXEj/1/GpsdtHRa9kvdWw7yKQbnM
+XuwOxtzZFJcyu0P2jYVfHHvxcjxuklc9edmCGdNxgKIoo0LXZOeFIi6OWtwzD0pn
+O6ovJ+PL9QscMdnQlPwsiCwjNUNue20GBv3aUIYc+Z8Gq0SqSan5V0IiKRHMJkzd
+FAhnpkSFBvHhPJn07BCcb1kctqL+xnLxIdi7arq3WNA/6bJjsojc/x3FdIvORIeP
+sqejhtL8mCBvbMAMHSBrFxclMp+HSz2ouHEEPIQam0KeN8t1yEqIy3/aYKMzHj9c
+C3s8XOaBCbJbKpMAEQEAAbQ9VG9iaWFzIFdhcm5la2UgKGZvciBkZXZlbG9wbWVu
+dCBwdXJwb3NlcykgPHQud2FybmVrZUBnbXgubmV0Pg==
+=q1C6
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A730529CA355A63E
+sub    D5A25EF82542C54A
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEUQYOcRBADsCu4zTVaB4TOhV7NyTvHhG1bqN+3Va5t4vpGQJg4M4U0Yu0ut
+4bCZP8I6rlXGj+TqDKVUx9kfGpIKX6Kw2TvZUYbHIDWh3UhQO1hD4xy4b8rOak1w
+3vDAMYA5L/jsZshNHp++aTgmvSoXGS5S1xsjrbrOics6iTtHXMV9TCRelwCgkwGj
+WHzPJnlSj0z4jAlRG4ZubAkD/3LOfrXtti1oirfDTnBZcxhvldyCT2yiE3LRe8N2
+ijmtNO6fl2fqXSWuP0L125ytlOvww1r6Gd8sVXiVwt2oKZVQ+A5028BbHa0u4e3y
+54nA21OBKLCC/hJvyOkPf9/kZk6S7fV+Tour/auixX4WqUg+siMRe/EwHw6bQDD/
+1OK8A/4rVPPCDTLvcQbT+B3z0IEfryMkivJMu7dEoENDXDK7N5KginugnCpJd+g9
+GbYgTYI2YPNB6A2eaR4lH8yQCMyDXC5+bGL+1NL3SP1qR4JE//nUcbx+iMTYR5uX
+kwmaGMXRl7z47OgtaWM/dVipNuNaqkD9WkuMGb4rdSNHrI+amrkCDQRFEGEDEAgA
+pH7D8VkxWJgH5zCO7I1m2ITBf8pu/McMCvpCHR7qgQp4yvLBiQ+AXkbQPRPnxO8v
+QNlSL7wODfYI9hKDkoi5pFNlzhBI9ivehUrfdx3uMIjowZk+UMBhaiH4Ppazkw3F
+V7JhKm0rA9VX5HnujGmZjWymE+yVRJhR9dy0XQo+b4691Ve8Ce9L7j0j8BzCcCwA
+hTOtEKxBnion46KLgr0caDa89C1HG8QJCqQrN+HRbfj07Zs4HjJl2CuJY6ql/f1G
+lGxJYZT0FxfIst01dAdNFppD8JJ1I+PYErWdgkm1rQDkAZXEN7rwtihHj6A0EEqr
+s1ogkXzyXs05fJurUtI5/wAFEwf9Hqv0J5kyzSA3mVhSzSY1pOheiVP6pWWKCsZ6
+xLM90PWekAHsENvvF0mtoAAOS6HYKog5qDHJme7jr10wdalynSfgCDCzt1qm2dvX
+vEk69j7vqLmqAkKEir//1XaPlGKxA3EYjl4U8HxdqOhw/FApWRmJncezqeE+R+uD
+4pMugi7DLnVa90hlPvRNYfButXXS8p7dhuiCa5ebPxclvcW6F/mf6ZDwDSuhkddP
+Du7OD36ebmiD6RHJwsfn/uOz4sRG5ogYNqiB5OOkKO5zBVztgcmWc3ACzNCbykin
+DmNHnAaeiPWR3xTp8ZwNa0BDLGBX5RUsUhP57nhQr0ifllubsohJBBgRAgAJBQJF
+EGEDAhsMAAoJEKcwUpyjVaY+pVgAnjLQPFKg6QdrUiYYCQactc2Gx9OlAJ9r5x4Z
+Pk/ZgTDkz44EfZS63bJ2IA==
+=6Dub
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A7764F502A938C99
+sub    F20DB7FEF61CE1E8
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFc7oMQBCADaIPEUzMrwF9gnEC+PRn2cSPG8OV4RxXxa88TZm0L7NF7D+F5N
+MNUAZ58oVqFUW+ytgb5iey3X7KjlJXZnuqES4m2Id4N7FlnvrmpeOg7MUc9VmNkt
+E7RH0O5GAo3V3o/Xp5nATUoaQ7v1WaPloB78ucyWLnH/iANw8YuxYuYUTJ0f2b15
+1oY1feqkpibbbO39kdMY36FH5h8Gsv0vvGdeS2O1p9vbzDHXEMLkNyKfcILLjbNU
+O/n2FzDL1y7hHXcFKDl6z2G7rKJCAsASH+r51YX3dOKUepE3pFcUbMAXGeG//n4B
+T8cv9YOhsYGaXBdbOMjy1WsZMvizbp0p6yIhABEBAAG5AQ0EVzugxAEIAMxtJLP4
+EGHrf/bnRuJHkyMqd/LEIMR4KszUl1AU5oeCxah7ZsK2MjwAUDD2UeLAIyANmKq+
+vXtma2wvQeOzo0QDMnxLqADSQ4xqUUcgbn71rjMq2O/T06BI9Lr2BaXeuYYjifA+
+loWzCbOHcgz78p8RRmxlChO5mWWlnrznDbUjV4Pih8M1LR/a2bUiU/Ftg14GPSrh
+ct9D3b5CjMIa4tqWMpvI+6jOjJm/ZD3Ux7WbzlHB+B9/yTw7n3pLSMXj/07PJKrp
+tUeJONprdN7V3wg1fnVS8CuQmLKoJhU1kLnucgnCFQMaHThhjxdaBMr6Mlq3urT2
+BSw970AB1qV4Wg8AEQEAAYkBHwQYAQIACQUCVzugxAIbDAAKCRCndk9QKpOMmUjO
+B/9ByOS3hX9yJysA/IDbFWonYmlo7p2hQbR1tiQ03QpbXZXCPxkSknW2uHqFLxd5
+eFkR46ExXINqFzMO6V7+o+soj7jUOK2rxQUIvdf423rhjdOU+TGXSDVKfNhBc/P+
+z0xQX7TkOuNwrcztgsmoSI/5K0rbF6+Yx3Thz29ZNFPTTkdFGiq6GfDOwBOp0VOv
+NyHw7mO4x4/5gdPKJ7zsMTT1OgBY+UQ9msb/ae47HvAEIgFg65OAamU+cWe471PQ
+uo8MEmeRKCsJuZlYjHcwqvqcVOcHJ9XzjuiCPn4N7aNkSTvoOcGvBWaAmBTxWVRM
+hvtJrydlnWJlCJiPfZvTePUR
+=IsAk
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A797295E9D87BDD0
+uid    Aurimas Liutikas <aurimas@google.com>
+
+sub    FB4C179C9305F3B1
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGJZox0BDAC/pjQlGW0w4nlUz/pJo69HlaFXNcTw8B6oGwIAhzer/iJIYaPM
+OYM44uifatxD16n4eFk3ZLHkIYbU+2wfprLlfsMhBuh+esY5qIHqFlhos0yQATGE
+8tEKYrCSh5umHPQ7lY7B8D2ReSxbvXkjHKaEKaiF5T5Bwp8cX7mS/N0J4Z0t4fLb
+WBsYfypnVD5w15YJlIugr+bKreoK1WPheHrnKTDZ0oJ8Gov61KR3ryTq0JdbUdBl
+1XqARj19J1ia11uglyAPwsbb5cw9wx9TXcRrzvGBSrACrYGaKs4F6jIbPWorP4SZ
+CN4z8Nzi16cOOwztSrDR2+9u1evHlyvgXgUGohp6npIHxI23FFXCHLNkifZSMA4S
+4xQeYQo3zWUJ2G5mda/JdPtk3jzNGuSltNsoh7pBfernrBqGdtZcahc3rP5YFODF
+B/vQLZHLPvs/8W3P5pXG6avtkQRGIIBHe0s7k06JThKWVhW/EdEtZ26Sg6w/YbzA
+VxpsNyu4kgWddwkAEQEAAbQlQXVyaW1hcyBMaXV0aWthcyA8YXVyaW1hc0Bnb29n
+bGUuY29tPrkBjQRiWaMdAQwA2KxuO548cX/8k+MWzl/K1VZBixgcxJFcGreHMW3j
+M+8DRJItB+Wo1DL+EUoJ8LZ5gxvM2qvjE3Y8X3rV/zbSz8iPIWHMfHliWZ8VXjQQ
+lGuKaGfnCQmXbR0jtJdWKFpMck08k6RDo5NPmHm/hldEzT714s6GjM3M8uZgjoRr
+eqkekdyIvFl0yJh3RHs76PEWV4m4knkiqocHFqH9ZUb3vJqnl6gnBVXQCm7/uTv0
+0il83y06zEHePZIKPJC+JnILXHINP9RhVoRB/qkqhxPt7KNKnXioZfwejoMjOXcU
+Y7vIo3LYDz3EM+G8z4EBkdr8bGBlDKzMDmqeK9EG9OJg6RzxfTZukJ/eRAWmV8zg
+aFXaeYnhR5zgFuqURRy9ftSwOa+736HDA3+ler7ZfD3+cuzuBZo8WhKISoOrG43s
+O8F3LG2QWLwzLFnGmPdPYKijVNyXsNR+A3G14JaafSk7ZSkL29SpNatkIc4KN6jE
+H8d1zAogHszdcc3jBHUAyKuxABEBAAGJAbwEGAEKACYWIQT/RgrPMmb9zo64/jun
+lylenYe90AUCYlmjHQIbDAUJA8JnAAAKCRCnlylenYe90HLLDAC0bPZ2rQfb3FOY
+CUcfEqqKofhuJyQa/geqgg0fBJjSpFNQOzC7LswV/U7nr8nnVXOTbISmC+GADLBa
+0Bmu88oeCySYdlEfVZGI6p4CQMpcx4Vo4cOhR9hhL915Wv/G6++nhUKoexrvHquA
+t29NbZ7epqEtQdmpgWqZ+1wN2uxnpzCV3g6X94HUy2Mc9T1H3RyA3iat+B9QVU9T
+8xslhUTr7B1o4b91Dc8Rpi95MRy7Ht7g6De6QczEJ4wJe0jCIWcl9aPWlpFWXK23
+iF3YzchB4IK8aSs3IgNewHwl01LSLc5rQxrky4DQKPFqTPdLX8K4ujxMg3ehSE8g
+CVSIHZRjyQtFjc82r8oGFBZQi71TwPvIS2BgbJprjAqG7RaIN3eRGCuPfBdcKzge
+/M5TKuKuf2yupMhRQiaGN79lt26XU+tbwWftHrUq4LlT0Ir9eo+G6yLs3x7Tl0lb
+jhmgimdBlF7Gq757UsGg74eHTP6IdA89lHXL6F5cuTBcMM+tIu4=
+=YJoc
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A7F5ED0FA05D64B7
+uid    Kengo TODA <skypencil+github@gmail.com>
+
+sub    4044EDF1BB73EFEA
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFELz9cBCAC1cr1c5jWUreRdPYYvk6DK7DwF6dgt7iN4rN2QT75M6ob9Yxow
+QeO709C7V0JXpVCOJ+7gCxnllmktpchRpj7hj3iDdvhVuKMEF4pl+tDyoyzK4Xvh
+HwDgaA7nXJLzxOE1Zn3cNqJPp0siXa76ADFvRQSGEesBvJ4U2dTGczIxIXBJAsm4
+s03DQV05gSqWsHr3iyHsFCwgE1Egy2+tIMfMTKU+wQ5AVb7AlpF5ByyeAA1jUG3n
+zuHQ4fCe3HZrBfY2O4z8WCZRSo2QnFoAGZ4mmcEQ0rZuiEqigjCHiqLdp/BoekDK
+FyvY6nOUED7x3qWx3WS9SJGpRf/2CcfKkuVxABEBAAG0J0tlbmdvIFRPREEgPHNr
+eXBlbmNpbCtnaXRodWJAZ21haWwuY29tPrkBDQRRC8/XAQgA5X3hUrVHhWo/8/9o
+HTMyCL6+yOtZjW4E/TXN3lOuqU7W3eiHC+ocVuWXqNQ8KT+XdEzd2xhJR1IH0myr
+gBrGi268k9gKibdeeOM+x8rpdQcFJIdDUJQOWc+1lHyNo0t8tJCsnygdF5svrFqJ
+13/xf3lv5qoRIRUGvaGk2ePjsShRPpcGoSC/sZCegbbb3HHQmk5qiQ5Y7gD9615e
+cbsNTJhi1jCnUs52+fOgalx9qy2IWmyjmLLRItutJC8ez17DJXKVG3zQQALZn/2Z
+bzDxzefc5o0db9tmSL1ieLpLZmU3DsMpQu3kFiD+rsw5PFPHUDfTTvU6eXvuFhav
+/cA0iwARAQABiQJEBBgBAgAPBQJRC8/XAhsuBQkHhh+AASkJEKf17Q+gXWS3wF0g
+BBkBAgAGBQJRC8/XAAoJEEBE7fG7c+/qlg8H/13MgQNgNOSt3iDvy58MSt3+Jx0J
+4Qfz77LOHo+IiYG5jJnciHtFHTDzvV0jf87l50F2H698KnMqgeL1P/wEikXG6Q5M
+NMBFJUKYkIPDRCAfCWug9p1eoUm0Q0Zec7WNWY2QzRJW5syhDk6edtMt7zt+8Jrz
+5jejghbtwYyjPrHO3W1VgByMOObMH9UgVLgOi9xyrqWdjSWr0yhhprD3CtzXlp31
+exLeUmOKZBIsTZwL/X2FkxUagc8Nm5BDCMICmDkBU41mBpEW1JwCYpzOd8hNpqVF
+hxZnxMJ5xyiB/Ir0Vl7p8waLynFjl8/uK83vC2p0VjOjXyXizk0n7q90j0FKzggA
+lEhfdBO/K/q9zIL3NdA9tugexpcJk8O0icxXVQvMAg/J/uxRUTaW/l/4Sxw9rOZq
+IzDGXk+jWzanjKnF0hkvaIE3+xI2HEeMcJ8wmi5Y12XB3lYJD7JVhmHurAKIS+y6
+UQj2maSxBtfwIBDL5iYRGsv63HPDOGCnUxfy2aDpOTk1e5y9vchEBTY1zNoTVNFL
+WyX/mKLrykAk6jJOfZYmtFJorkCCyvVIaPUIGGNmyyBJurzTS9KL1a9yZmMgdYlX
+1HqW3SpzYEXqajjOX8KwohA9yDpSKlmKMIRTIIiPcdXiRP5TrCv4mGCMccYhk6ap
+EQ/G7qbJwNbQ7xLUiTbe6A==
+=p4ms
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    A9321EDAA5CB3202
+uid    Werner Randelshofer <werner.randelshofer@bluewin.ch>
+
+sub    D36DB5C489BAAC5B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGBoC2ABDACyCWLqqAo9NeThE90hBoYomtgLci5I8+7PxSYeQfzUYjXzZcnh
+6d/zHaeC0zxGhT2LNe5i3p2e36xSeFDobjG2Il/nv+4jFCgbn3TZ2hEingPuPsg5
+isodOXHBSY9iHPTKInpiu+J79MWP9GVZ6GeOOgQaNSrNN3uDE1w3rukB2SrXGdfT
+/6YZIOtwWZVzc2m9lalPmOAyI4KLI/s37C8Ozfv3c+Bx11WRVzWVpBTo94fU4DPu
+Yzkx2Wxuc4TT5k6bQJI/GHi36M7xkUauXhkRCNvBz+LFVcFjtsv6S37L6RZib6mz
+jZTW+iyD4h66gqzg3hSRxv4YzHgR/Os26Br2ioZNzH6hJFtNktR4oN/2kydmj5Od
+WYjvdMmd/dMbZheZE3f8sziUKCyvWMIddnHAM81uDTXgWcMgYSa3npOGZhfk41z+
+w9o2f1kXIfdurqlA1n8np07PLw5Rfpjvbs7EZxPTJwcc1enaNyL64fb+YIUtFrcW
+Dt1zUMEDkbcZL1UAEQEAAbQ0V2VybmVyIFJhbmRlbHNob2ZlciA8d2VybmVyLnJh
+bmRlbHNob2ZlckBibHVld2luLmNoPrkBjQRgaAtgAQwA9dZFGqc0/6pUKDUsT+2h
+Mh0z5mISLc+x6v4wbAqiEcBE9uoKf0LniRfVeehmuJpiUPgOf3TyxNbxeWiFuJEL
+ZbnrYztAeRE66Zxk6i2Mv+207fdlj3mhphdEWh4f/0AJa2PAmiwlcxq1O3VJ/Wfn
+3huCqIU5cmqnmGKH9LPaW1aJBxWl9+x6mmPVySxpTaQRrnNnumZf9K5lwGEsccvp
+kLP7J1Nlv7HLO8oliPCInEMcsrVqfiKU/bybxNW1wzPJxp8LNLaCNxuLNl4RCp7t
+PQuZgjcoCnz+JwcxnmNGI+FKqSsFXBZyNTWiQJuaFUQa0QON/+Qj3p+OyW15f+Ff
+LjHI/BkNAi4ncNeeazAwuLCMJGMS+dLarHMbbAKLaH0UI062ch3Aq2Sa3io1gU6v
+YHvoKNMNfYdNwoGX85EkzX6A9fm9jBviios1RLkpfO70MoxpWjl/rwHG57GOItWZ
+7O53ebs6HrFPdUYQs0Gz/lj+BaQPwDcMxADfYtGnYMepABEBAAGJAbwEGAEIACYW
+IQRurXUrPis46OIjbXupMh7apcsyAgUCYGgLYAIbDAUJA8JnAAAKCRCpMh7apcsy
+Aj39DACMEaGsskfZBBbF9BHklmN9OHbGKK4qfwY6f3Pl+QEC4m2y5Uaxgx4n0SJZ
+/p4YdVopRj07cdVYEkqJC31co0XPvfbjyBfhcH1BXkKQiYAZMUTqc+ILGHrY/vzP
+27Je+vck6M+ntQ/2rBBiPtD6Bj2RcuXupr6MiGavF5U5vzLUkYm49Oq2Wi5gIuBF
+8+6ipjnzrVl4HqGUlFEt8RK3W4I/ZWTJBlwxaIWoAIfkE54FtSqN4dY+LoNllMKb
+zjFBemXfZXHAFEH9cjNh5EvFKm53ff8X+WNgodiVaH+qv2VMZZngEtmj2Y94v5x5
+z+Q3vcoGH6FUdLjefYm5uwEhhBsTyz8gyBmoj8cBBnw3DZexyOPLGDj/3FSimww0
+HXf8RIR7Msc5GGMLXqSZ4WVZM59pFsqjmqfgl+C8WYWMLAt7sXJGuyl2LQoAtR5g
+pkPZqA0wQiIXe7/RgIs6TpqdS4uLh52KzW7VUXqywr+qH53RFujkS0KijW96Lbbl
+ENk54Kk=
+=7ZAG
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    AB2DA4527F6FFC0B
+uid    Egor Andreevici <egor@squareup.com>
+
+sub    1A94B14C6A03458D
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGI8r9sBEACZJBV2TNUSsLRo89uC4lfmQxfNDqkE0uZghfFY/p0fr6fkBybO
+WDkPFskAPD32fzrWxZd2kkyCRyUrOmAUC22q8hw96t28+RqZymvetIa0f8GQGgkO
+/ZTiD6Nnv4JoeSfUkJConDk2J/2a0pdxcC/MWLB2I0X6pg4znRHtNjgGsyDe8uW0
+xGK4cyRdQH0A9T0TynKjdB4tBNS6gB7uI4GE+J0jFb56QxzEZ2+t+vaN9QornDgu
+yNqZMAp7Fnou1AjmsMalkC9bTO1JrF6P5ndsBPiaLKJHeqHvssC78SGM2CvPjRnS
+YVM/pTmcgEPX9590p8WLM050DFMbBMejPx5UDDf461rDcbkatL4XgqopLGDN/+Hp
+As7dkGxc5utHm/qrXspaLVpRGaiZ+UiI3m1PJDcOozWXuGSrI2fGw/i0HKY5VHmI
+6IVtSrjMu24Fh+t/GK39Li+xZZuw8jZcuL/28kbwVFeeBigz6AKnqvK041iBYfLM
+J9y/7B2W1yVr4rvCgBahVvMhJfhnXzNqstWEp+zVLtF3CdNti0eAvJHnoxW8Pu67
+Lx98QyaWHHw+S9sF380O0sQiipldY5X80brrI73MmMnW6bYda6F/57JJ4ae2Hq/Y
+Bd9uc8fuInkpBld5uwc698ndl4fB94rm3Z4nFCIv0mKpmEaSo35luiKS6QARAQAB
+tCNFZ29yIEFuZHJlZXZpY2kgPGVnb3JAc3F1YXJldXAuY29tPrkCDQRiPK/bARAA
+u5QxSoH1Yn2McbB6GIuplKt1aIMaZg41melisR1EnriOoNnbw3iTI8dx7p7JBIJ2
+gMCNxu/mct3GcAIaBgj/5Jf9XYVF1bHcazv6RPYsvVBYDV1GVaLitG9wlDS/y0wt
+b3SR7xmhkrwIRJQAjSQtqvRB3lRHguTtatEkMpTscjgbDjAvzsYx9vtF3jM3dXIK
+/1rFrC0kOweUZAWJYCNxbdAvJWioas5fKbTKe4s6KXKhhVVIp/4RIr2dByg5mAK9
+9ZuVyKGhtFE6y0uk+BU4H2ZWXehMPfm9Tjk7oqkMC2OqEB1t0Ep9xCQtvzbqCxhN
+FPuHU+OWTBy7ARnrNKEkh2Bppv607jjHOHxhJW3sjrl9sH1DAQNR2ZKob70ocUoy
+qDT4FNG9/H+CjbsZqzFqmKcbAQA2fiIO5NTwwOnfbcRlmHuY4qrZ5LmhSGnlkrHs
+9Uld4mosJZXOb69RXIL/d1SCih0wPMBbLl0TI9FfJD7YDBASxEqN0lmYHGo8qu9V
+g5KPSVQW8Fg9Tmig4aPSgpT6nHyqiuUcoZyOnICX9TMraPXMoXBxXiWrzu8Hqtsm
+zFPpqOmWfvg97X6nco8obpJRGMODUQQMYjeQ48SBbGVe1utEZ4Yt47ArxLKmh9jp
+1jdoGkLT+8T0Z1FQEnS1d4/xGPaCFIz4+kXGQoaJdOkAEQEAAYkCNgQYAQgAIBYh
+BMWqV/Sjjrp7f5FW3astpFJ/b/wLBQJiPK/bAhsMAAoJEKstpFJ/b/wLWUkP/25L
+1N5zJdTsoooTjutFAiVvy8IbXx0XGm0F10pBMLAbKwkyDyOvZ62DSc/xwmXvZE4G
+fL+dpvmZUIwmtReYDy4byrMbdF+Yw8xLmnp2xeoKsrh8VacVniEkPbKKrVFjBrho
+V/oEGHi+ilKq2KeftWHm8mLk/QQ/AXGuum24wBmRBBY1NPCiPk8+HoRFY2qrz+cb
+oK5oAp3agCF+LmOBFKUBkId1BxvQZViQGKkm2uoQ0kiFpy4TlcxWwATtFvaE/d6w
+/RqdjAwYpZcnbbAh8HthSE1ogjZSWkypEdwr+EmBlHWaXWxVHsJghB/YVKfC7HS1
+6IalHw8aGxdXsrAU9rnOdajY5NDwdRJDTH5TM9VsHSIEFOkSr0HBcQ+Ghff9H4Qx
+feiEo6UsuSZB3ZaRk6VE1GYFRj06mmPB0uv+C+6wl5znv6chfQzFPf82KiHO4kxg
+R+UK3SoxSilCWFh46YXv0IWkg7jeFtJZWLN+LGmDS2vF9haurM4dwlz2IOFm7CLS
+VixCaDPqpOh7OqnwRVHznBy7/DYzmaS0lSAuTFhh5mq+ofWaIpmdlGiqxuUSkNg/
+Zj+HBxG+AyH8Lhi9WGUafgJeZ7fKBJbtw6JpWl9bUuiEBpnRFkn12RBe7vkyfZGD
+R2u/WbxTrhDdrrjoFCFo/ZoYzRY46LR+HdytaEmE
+=EiTD
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    AC5EC74981F9CDA6
+uid    Cedric Beust <cedric@beust.com>
+
+sub    501B5ADEF57CE6A3
+sub    5D9FFE7B8E3DEA8B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF0YzcYBCADmNIEEzvSsnJnxH0u89Hb5vCCkl+45dWHyCMsCLNty8yL214LV
+B35gnU+6BvRXN3DmTpreCV8/wgI2h1eq83dTO2AsnJTxTjvYpiwAtWhONxWxCU1Y
+WlH8Fsvao51CJWUwYY2HzFr9j7h7EOnm6gj2pnUDdjHRgou9/OxIk6q3M6hrwwh2
+IXw6PXFmkg4wRwlqW5FiC90I8gd3ItFCzqx0TR7DuhOFhtvOheWMlApPoMOUY+6u
+C5Ek6kVW5w5xshKafS7p2s0WOsXkOnH76avFtkBtcsPbHkwWTal4xivSMMsCpdPM
+cF6Fr2p5hF4khQ1r5pdmHeYNoXcC+hSnPM9tABEBAAG0H0NlZHJpYyBCZXVzdCA8
+Y2VkcmljQGJldXN0LmNvbT65AQ0EXRuFrwEIALRfZmZr3bGWlhfruPm4BA2UPM81
+MFK5p2bVvyvF5Xuk/+Cmjo4gQ3omOPCBgHFdtaChDonoGlcegFpImfv/Hfn3i6H1
+lR8JNBhOzH6xJ4nXVRdpqhN53l0qy5/S++O1g4T/T07ZEkkC4+dt6guSWiFJFps9
+BaHyuRr8Nk8iK3IVD7ZuRuK72M7EqJkGPCPnsmHj6pw/xbKFJb3eBYSg7izlNO0+
+jsaLotrNxFqK5yeZZSaIIU9dUPGZJ2V3Ox1GHRdBsylhnm0c9bCGh+zg8vSyyr4J
+iSRF1llX1A0C/k9y40XbDVw7r57A/aguIhEpZpus5cThLTqOexFYyQVR4dEAEQEA
+AYkCbAQYAQgAIBYhBNy6Azge9siQlqzZhaxex0mB+c2mBQJdG4WvAhsCAUAJEKxe
+x0mB+c2mwHQgBBkBCAAdFiEEMdTLL7cMsnerBSNxUBta3vV85qMFAl0bha8ACgkQ
+UBta3vV85qMwywf/eg7CuVC8z+smF4cJa7KKg53ByMZKcGJ801sksGnG/uvoZWKV
+6x664IO/pc0CRpIEgynnabq1loBHFH8GUMlQJws86Z7AFxnzI7E9gzWR5RKh6mjh
+W5rnSXnuVFos0udjsYgEaD39tksIor0UNueLusO8KZzTjgF8nu38yI2SzzQ9ZmbN
+W2WvGxHFHmG11vuKUr2xsMlrHJWKBEUljwtTgg2TuKUGK0F27B6psaacZyGjVSLc
+bgU/XLyz84LaNbml6yrwbQqRaTNtO/fs6em347FryU6A3sSqgGJ5chTRmaREgG7p
+xRYV1sQI2DqAeBI1drrjRtSelyvSEaCEXZ40u3fACADZGY9lTiFi/J7Qa6T/Txue
+OFJXPLDQYwISvPiQXMVOvRvXUWefusN5W7DdITekD+9TXUWMhmALtm12XPGmu4mO
+PFiEnm6NU6YeaFka37ECwJaPBrOYUl0pDGbwQCAZqMnsSeo4o+u8Lw1y1u9AOHE8
+SX6OGc5HJ/NdwO8EqDTUahGm3EAxuQQCZphWux4sIGh5OKafIVVFFp85gj2VM/cv
+GW+41jSt18QCq3+olqM9JKOT57vZSzMLtLO/7i20w5YfecWsr/71Gaf7Gf7tkNu3
+h6jAbWHoWKr5df9NyIHu2yWZ5qPjoXaakCFSeSFx+N2vFcFGte/O054IIWIYDJQy
+uQENBF0YzcYBCACmu7FGW89IMsiRtCfWh5aPwLzmWaczLXeUhcrlcl2GHKiy//zM
++1PhFj092Tl/WCif0694nXsKrlx9PO0q6ca9LSyHZqwAV8AbLHyxkl6mQs+HH5CH
+EMrT/FpPLCfTUCSyNRyuRJWkbJjCeMkAmB+eVHHQLfaRRHVTBW4EfxCHAtwLfys/
+0PO82+aCHwCgUh7vTUara4krPNHV+7KfSbqCACk3b0ebY53cAva+p+BZac+vJ58C
+g9MunvURigd111PZOkiKlAx6xwcq1Z2HcJFTj+jtTGwaeXJErusPXhW1NxiUqCeK
+e4o9Iw+D2pYIqqahVGKnqPYDYY3dBMU3GHiDABEBAAGJATwEGAEIACYWIQTcugM4
+HvbIkJas2YWsXsdJgfnNpgUCXRjNxgIbDAUJA8JnAAAKCRCsXsdJgfnNphXkB/9/
+M1DqpV/FBRhPYMiycj0L+qKXDjJdMSlem8a7F59PEGkB0oStEUC0voAeO3hPLvgm
+0MVAsX9ULtWHlPG+uDYG8/CnFla8BaFAkTSlTQsmE0/0j0XTrR4uO5aJBRR+yDKG
+eR31JyWGecE7UfwQPMxSZENLVft0oZUURc8vLNBn7Acl/kbw1uKI2ASVmIA4cLYB
+uYuI14Q63EZQHlGQ2AviuaMR23qYRv4Rq5sRu1RJw/fITZzwFmmVT0MJvkW3y0pE
+0VAA7aGfx5ycnEPmNlqS4Xfjk+i864g1NjcUKpxv5QIn/p3P8XLKVJoUXU2y4MiJ
+reUxhQI8ClVBsDh/Q9pr
+=CeAD
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    AC7A514BC9F9BB70
+uid    Punyashloka Biswal <punya@google.com>
+
+sub    7B92B768F9D37337
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=XaPu
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    AE5A7FB608A0221C
+uid    Robert Scholte <rfscholte@apache.org>
+
+sub    38185785755267BD
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=Kqmv
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    AE7AF7AE095EB290
+uid    David Saff <david@saff.net>
+
+sub    C707929E5065E0BC
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
++m8eLmJ886WnrhCrcCVkjpDhAKT0Hg==
+=1BOD
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B0F3710FA64900E7
+uid    ?amonn McManus <eamonn@mcmanus.net>
+
+sub    7892707E9657EBD4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFdbSfIBCACrFI0ai/abnV2U2Wa9QQZwGk3Fegc8laiuTKc0GoYdyptd83/H
+hD5S61ppdkOugBjVTHdgda3xJ7zBZdnwjZvV/TyayQltbh6hU+BMlEolzXLgyvY7
+cAzKE+iKWbLLwfhRn1iuC7s5l1NLPsh44IUt3xDaFXNQrPO5OnRz8bqsGFVawxmu
+2bPqIjkhxEiYpxwaZZbDkgBR6rbBth6A7QOadQcj/9wNdekoM9dyg+olOUmnLrtA
+nMBhrvvbm2fZxTps3SZHlLV7+iSu71B5SqU/kT54/49n8vxrQiGvzp9K+t7c7EP2
+w4Ax1nYpRkCxYdHOX3YBdayUiP9ZaYH/YHtLABEBAAG0Je+/vWFtb25uIE1jTWFu
+dXMgPGVhbW9ubkBtY21hbnVzLm5ldD65AQ0EV1tJ8gEIAJVavNan4WxxlwLwvnBj
+3/wcEWqN+kfMHENMSjmRWOYSmC332hhGLmTDi++BPWt2OOvHUusJV8dZP5D9yUBR
+FsKozIpyXyS76C5VYGMY8WZ6kyqn/mLCiwmnkOJ24kXLaaHPsQjv6i5f2KliDVhA
+GUHmNMJgH8o/GL7zZ03Mb8ZlKFZobp0dn+/lxoOtQSzR+cBz8NvMBkOKD8r4PJA6
+BxCR1HVEHsq4xSnjr/UZOYvh+Kaxfnop7Rn9in5MoY2rCY+PV59Xbx4grqNpjupy
+HEf1MHodJRj85JiClnLZk7dNJ/kr+zggwbsd12/GHkBt/pxuWhe0eFcAOJmvqC3c
+4pUAEQEAAYkBHwQYAQoACQUCV1tJ8gIbDAAKCRCw83EPpkkA54FACACFZB2Tk96F
+Qkr8+WHOz93CJs4UD88PosLaKmiXKP68arjH3y5jhNLBzqteZo0Crfw75DYWIZCh
+df5uLGKCWXBEytF4uoHOy9Lv/3emoSeenluFVcNjL7CIOQDRmqw1t/LjnsLbgvlw
+Hix5f7I6Txu/J0HKJbq0XpoTqCzFK6sxEPHH3gZto+XfHk85haKd73SOM4edkmJx
++jDXES1wb3K3SpYibt+uPVfLYXWxK7xAaztESTIqZ9RnYHzd/7z6DO4z//lfB7IV
+AqvM8ga7Qj58ObeqZxx2iVit5WUZ4cE30crNGyXH/HKlAp+B9EvENnwr++TI1CGY
+thPLFHFc831L
+=obUO
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B16698A4ADF4D638
+sub    32784D4F004B405B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFM1v9ABCADD0KoXq2ZKlUHeIVovQy3gFmW9oFAaraV48ouv8cYvqdf+s91H
+NyqeyNPT/ihFeNqZJUAMyPdwN5xrWD6gxMrOCR7BFhA5kLmAKz4HfFCQ05ViyQdI
+/HVNFvTdF8LNnuF+a5aNgg+jjLvFwzkyMFkuiPGuUDFnqEGxC+z9J8t40tpOTOIw
+tPjSzkDN41AJDpUK/simKC5F0Im78nUbwMalE5z2IsZRWpYZyIhN1HhEdDvaDIh7
+3vENjH7enAjWh0iGRu+GTP/fayZnX0uhmausCCwMMhsr489e63ZOaJrqeC//wWrX
+dtEJjcmvRmJ2hwLmgwMP4zSNKsnLGzP0sh69ABEBAAG5AQ0EUzW/0AEIAO62SMbq
+gIzEFQEHlxNN5pZHd7msqDESILFYFkI1mxlkD0twFWMbk4nMH2VXhiuT3ulqKBOU
+UUNQrO7egtfbGsgVv4bWbUHfeZkfvoWDlmbrvi1YLlR/ZxzGpCNc8e3aOcN3XKHl
+BwfUaco6pcTBvLpKPA/TAjkTOtK4A5Azv1CSwpzSJf2bVVbrn7mi/rw78SmZAV2/
+rtiOU5a9S+3fzswLk1PO/z//d4VoCcL2s2WueVO1Q99kejkE55l3lYwEiBzVuAA9
+8Q0a5wg84vRGFZQWLIw8c20On2+dZcTLZc61ZjnsI1LSnLUUyQ/fzHQ+BynQF9l4
+3ZCPKFIl125MGikAEQEAAYkBHwQYAQIACQUCUzW/0AIbDAAKCRCxZpikrfTWOJel
+B/9vDc3G/mrIHB1P/zl0Fdl5wQzaSVc9JB/ce0018ptplL711af0ZDvWqmZkJNkY
+u0lHgnniaXB0l3GGUPIa/TZzVgFSRPj65FWTMkBbNnhGIwV5IVOPcSKSyDYn9/nQ
+PpmWl5fDj8xiv6kKYxA4hjjRbRGuUXiI2dnyFHuFpacf/Af/Mc0U/CDDuz5a1jS4
+SYuYM/HFVL93POZzwLUR/+GDuVJFnm12rmjGnJVgR0rWcJKJt6vCsBPVfIamfl6v
+G+N4TWQ9euj8Rd4hjsYPOwDfgVIUGIhpTUJ+fz046fkz9MWnX7RJh6hqLAXT7Hbc
+0FTFsKYAbLJbm3Q+rU9jTdM8
+=mDDW
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B341DDB020FCB6AB
+sub    315693699F8D102F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEowbDsRBAD2jx/Q2jNuCkgiS3fzIj6EzDP+2kipIKH2LEnpnTiBlds2PFYM
+xYibVab/grgQODxTdDnAKifbJA/4h1/T7ba+OV+xIUoSI5MbgaF3USidiDHPX0pY
+qvG+k3hKECLysQ2zoZpcC8c2ePiZQSVC2i5BRqgs0xZPz3kiT5U9WPozTwCgtasB
+TgHhkOGhZ0SOUuQ4dL54R9cEAIaDjdPcI7LxyOMvvGTuW/SaS9JyP21Kch+Vf6I4
+vKWWqXEaF0So8S088zHnBrcBKhu9D1sKIHS64EoYCrznfMUtoENPe4sf5QuJmZ9D
++fBuFcudQIpkx8L73q+E3fmCK0uX+anqipJtS8mgpMeabKda4KkjDsZkiaNl7OBI
+0H09BACofK1HTNHNke2N0wXN1GyG7IAqprKl4lBbu5aRXvfKQ2tDj8s5webNQ+Se
+Om/Yg0Bi+CiONLgUjiwYe1wNls8zkk3LwYFeKIJ1AjAY3auBRWOI0/IFFzwTkV8J
+YPHa3Dl/kmYp8NMMwA5bgrblggM0Qhnp+k//xpb0FYbmwHMwUrkCDQRKMGw7EAgA
+5MMlt89bomqE0TSq63JnPaSeEKsAx6A1KaXaSg0LEI7fMebSQcAdVdAFBo4HaR+j
+NNGv5JGTvAObLrqxnn5mU/+qhdTw4WCf17R4ETEKc3iFN3xrpxz2Vew8ZWpw3PcE
+gCe27ZN02J6BgtEqhT9v9f0EkAgRHIkcaFCnxme1yPOFN+O0/n1A+59Ar8rmwcHG
+opSoZlGDEdEdqElx/shQjqq6Lx3bWYXS+fGzSAip+EAX/dh8S9mZuS6VCWjLx0St
+a1tuouq9PdOz5/4W/z4dF36XbZd1UZHkw7DSAUXYXfwfHPmrBOrLx8L+3nLjNnF4
+SSBd14AfOhnBcTQtvLuVMwADBQf8DC9ZhtJqHB/aXsQSrJtmoHbUHuOB3Hd8486U
+bZR+BPnnXQndt3Lm2zaSY3plWM2njxL42kuPVrhddLu4fWmWGhn/djFhUehZ7hsr
+Qw735eMPhWZQpFnXQBRX98ElZ4VVspszSBhybwlH39iCQBOv/IuR/tykWIxjPY7R
+H41EWcSOjJ1LJM2yrk/R+FidUyetedcwUApuDZHnH330Tl/1e+MYpmMzgdUGpU9v
+xZJHD9uzEbIxyTd2ky2y3R+n/6EkRt3AU9eI0IY1BqUh0wAuGv/Mq2aSDXXNYJ/p
+znXSQBjmy2tvJlqXn+wI1/ujRMHTTFUBySuMyZkC0PwUAAnWMYhJBBgRAgAJBQJK
+MGw7AhsMAAoJELNB3bAg/Larfc0AnAmQbEg9XnLr/t0iUS7+V7FcL5KpAJ9k3LS5
+JI97g3GZQ2CHkQwJ3+WcPw==
+=OasT
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B57BD58EF6D0A713
+sub    781D1F35916E0113
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBFsZf3oBDADUgeJsq9asQLaUajkGON9KmxKBtJS+IbGa0jgvx37T4LDigKS/
+wh4axvdJ0mE31uXKitBVDkr5TptyxA0jojYwlt5YLXsotnskdHrIg35Q8xpMp72K
+BfBsqtnfdmBUd/oBZEKgxMM2Pl/VZ+1wmF+KnyToSWuy4Q+9d88ame+8Jdq5ELJn
+zWZWYhwE3c2Y8t62VGzXeZg9Zz747Qt0ITl02//ufoR8aLdb+8uLuidNktyoqpt2
+UG8oLr8mgOAaOn6npN81FbteIWCEcuGewCjiiYTHGpA13JmToDDUfopWYGJirkSI
+dYjP4fZBu4aryHKwXt/zsiD7rzbHrn821CAAZKGptVVu9IfqD3jCBhJilGmkWw+j
+IozAd33hLvlCnH8miXRnGPyNT5T481qbi09wOnQEUYrXBe1zOvBAEVxwSLcNcxe5
+/2gRDbSNU9NJst994hzofSyxA/3X/CDiOSHDKdAcOglgqfpistQIS68FqDGo4eIS
+WeR3S583Two98+UAEQEAAbkBjQRbGX96AQwA5IIECRfqpRDQKsgEYdDMzEYED5i4
+w8GrkqK9Bl2KErI6WQmuBnZaHr71bMrYFS8duUOYetasTKCxjU/Ps0THuOmTnuLv
+Am6PCkpzJ+qBNM4jf5sxHflcb1jRUQ/R+qoWOsWcwJhOw2OgNONHhW8/2mAs+5Zz
+ThWe4cL62YRK3CeWdWphwcUSGx+zQo5vYBZzIbdQ+E+c7aRyc4qEPfyGNccAJRdQ
+eW1tAWydmf+QIYGMbANWNPXm+g80wE5xCA9wwU7N26Rk0zn6e9+lSy8e+l6+hsNh
+uNxWxDDBubF8YMuzD4q+VM4dOOsAJARtp6HW/0mBTcTD5BEOqnDd/aRsNOrR9Cbk
+K4nU1aSrYOeOby8jc7Zu0SnYC6g+JXalt0jtDEGVaxY9IMIe6AcIJhSXlgllK87b
+YX+t4uVXYFb10QfxRj1oduBQEHJkCovsi3EIIl5a4XyoGdNUGn2IgWg+C0RXrcb/
+KDrg7iakp9SwXP0xBSbcNiwE/3C3Xom0l3ijABEBAAGJAbwEGAEKACYWIQQit59F
+awb051uLV521e9WO9tCnEwUCWxl/egIbDAUJA8JnAAAKCRC1e9WO9tCnE/ydC/9g
+6xJK/aIvvKLSraYfS90XamIyUqNgAyXgivWn0jqaTwoz27HG/hRgWR85q72vZ4qV
+vYwx06S8WHMijKMcI5fBtEL318c9V6Y8Pl7jwSOy5yN0k8IFA+TzqHGXVvPcuCwH
+TQAvvP/9v2d7ZrOiH7urM0eoRDXj7Tq+K4rLjeVIHALLEhqBT8w8LGBOEZUAwS7t
+aaGrURVuhO80QW2gJAoG5AU1qMUkzFsTXBsRTcwPP25FIPYClXPNsMR+2iVZAZ1e
+3yBqQkwRlymU3gPGY3M+TOyplfoYIJy6oT2ri0wYa2jeNdo6eEmLUjNAbpdiIEop
+ruzQLLaT7PUk+RU1UFVHjV0rgrXrTYvdgKyI4dX2yGlTTmnq94eaxMOsMxkHAGBh
+GrOJpBDWzJKXX48WAdi/4WpnhOD6N1BOrvWq9QWIU2374WutAX09dt1kBG3m4kGR
+STHuixCePH/e8n89lWDXSsqkV/+imzi75cTN9RWBT1mRltc4jNQ0B2WwUgrTSPo=
+=yiE5
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B5A9E81B565E89E0
+sub    28FA4026A9B24A91
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+3JnT33a2taNG0TUPdkSq3adt
+=QSEW
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    B7C3B43D18EAA8B7
+sub    02A4A6FB70018AD9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+xMHQYSM2kcHogpDcFph6wXxGhRjYldaB
+=VHs2
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BAC30622339994C4
+sub    FC9BDC25FB378008
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFlMExYBCACmdTDSXPwSJeYbfYvHoDl5C7vx/0+LOTunDGJN38pNQHYQAZnv
+Gyoc9ZmChrhLoim7z4ILqmNo8eegknepQ3dGdUij4NVIhR+m+8irayTbsNHvo3UG
+9y7eM5tTSjyNYkyk5fAVuT7OhzIzMA+qtc3GRVxNYRKnaHajt+pOSqr+uoDtMG3n
+6eAMHCAnhgh5Nd+dCFcNT+syl3zCwolA1wrzGxxOaif+xi5wwXjmF/lAt4PDIuDT
+etA2/AqPM4zAC0BtC0iqVgVypjFV3EAexm/g0LNMiG/M/krzwjPq5gf1DY/57jU0
+02FpKd79HmR7bHdc4e2olEf9NlHxfbPXDDsHABEBAAG5AQ0EWUwTFgEIANmMpV3N
+K8aLrLgQTyh5++det8C3D3T5tkEdljHOuN31/qdKNge8H6uKH8zXRZsj5pd8adpW
+kD4TzIMvzIwzizsGw34O9hf1E2XPoDqvQr39p1sovX3PeDvRJY/7JFNt9DsphVc3
+xWQfNkC7JdMPa6JRiFHd3ynfbQ+wplf4tfaDVn1JXAWp0NSGgMtXfn5i19hHQWjm
+RNAKNQLdVn8UczI8XdVM7bS4giDpQMukSyjsjgAo466iRK2+8f8BwIRe1JRvF37B
+dnbvTg/dzoi1/E4ukwVJD6YE2LlDwzdGno9KxPlRsuY3nnheVgjbrGJ2XKRJkIk8
+7cMGh41VKw6L4usAEQEAAYkBHwQYAQIACQUCWUwTFgIbDAAKCRC6wwYiM5mUxEiH
+CACQViGOHi0BoZ78ZJz6L48YNMx8fSdSv3YJ83Ih1n5DWCJgrDV5S3/edYinkoVI
+0Lusy3MdftRg6OWaYOuOTf6MYcddO/mY363jiMByf9Uh3Dqq4sKqVLRnZbAqgD1o
+dRoj2NkEQfgEH/H4JRVrxquzAKoWwJh3MhY+kajYJRJyWfc1/Bm3Bj1tcMGlGeIQ
+fgWheeMg3kxrxJ9TXPqVi6VVPaPKIU5i8l46S+Wg3uvMs8vC3XzOIvhY6cwguJv9
+UkjZwGDSI952wLqnREMy0gFZ+OAB0qJpYM3nDEekWZP38G80kojnN61tZjRThu9I
+i8/b+PwSW+nW3EpQZdLqZtOU
+=2H2i
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BB2914C1FA0811C3
+sub    7AEAF265B448E2F3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBFHwyNYRBACkCXpipiMx0lCEccXXzv0bE7LHHbcQYtb1vT/o9WXYoP8JMChJ
+cvuAe8Tvg+s7EUjKHJRhu7I7kie+IJ2wtH5uVARkYxoP2OslYN6MSXa/bmwU8fwQ
+EFkVeFV7q2UFvH4cqpa7UKWggKcUzvB7z5spg/iKuMDQ/aBkxpmUcrpefwCg4/IC
+Omi4O9ROfzJ5Q1YHSrr8A0MD/0OTgJjkBPPBcel/pFetsWhlqA6dkYINT5qdlht6
+d+aye97QFUccg3ODnCq4fnDPHK9PMK8cTGkrnoux5XY240XkWX95tQDyrssGqldC
+zOLxoii4/gsw5s6j4x/AjycsAI8DxaecQb3/sNg05V30ZNm2+kQNmGGV+0oERpo6
+DAVQA/92UVwQdZjMzCs/6NTbsq/2tRX/XXiIxTij6fpZUeHvR4Ek3meuaXs9PPwC
+o2f/90aO71bNKjh0LHSI0CEuMWbnixmBgOEQY1yv0HvW1OB7otXrTS7EI1m+4k4c
+WlwidtR3XjqqgXTjFz3J/ipT8j15a5HOtoIwP5AHw4e+1cEmCbkCDQRR8MjWEAgA
+mqaIVMeh86G+K7uq7m6m8F9s4WtEkmYAYHdk5FXOXEJ+uOSiUiYLcYSBYRkahk9Z
+o7QSv0bWRmqCFI96Jvo5f0MBLkwR9hxYzrr3vkkJyreMsG7ybyXA0O+ga6ex1091
+bBm0f1vekvT7VGdcTtjWhpDiMBXZgTJDGUEpzz0Z/8MxYEfTsk1P7TNMMAvm4AOw
+vRk/xL8Rc6Gapr5EGMLhKRADwvWU3vYIhRjXApXZUem8tNq58cmR4q6EEsmedDri
+LuufwVBPT98/+sxEPMgPFnSoLPDc7AB7vD9s0Ip+8jG5Rtbc39Phz4GDHmCUwJ01
+Mo8k7Sr+jguGb0fthSfM9wAEDQf+LRyfjdWJ6CW+mGSYFsW1ivKzLujvfiQip3CM
+y68Si8BmUJvN8aPWS58knZY0ikXOai+m7W+4yVMkdNLm8JpJ7SX9NevZCYAb5lOg
+mE7kvHoGFar5oA9ttUIV6RZXbQi0fXtksKse3c5gWqMTmEzTV+7thtQ3V6UmXpIv
+OHKvLJdocHP5T3yDgnKwr1ajw7028XT3wsaiUV+sgjtc+1KMME9/Zhwa1jWSzuZ4
+Pb0kxVIjzebsTr1nMdtQqARg+KKc+R8Gc3NCP9MZ/s59NUFyfCkg3TqazsIXQ1bi
+KMv0GppFbFMnC/ifijqtl9g9phuoF3N6/Cs38zVlRHneyHRAG4hJBBgRAgAJBQJR
+8MjWAhsMAAoJELspFMH6CBHD4SEAniBrVdd83vjrwn/3vXYTuZrmjIO/AKC9Ib56
+Z/+UEC1v8wCMk2365rUPKw==
+=vlw0
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BCF4173966770193
+uid    IntelliJ IDEA Sign Key <intellij-idea-sign-key-noreply@jetbrains.com>
+
+sub    C9F04E6E2DC4F7F8
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFKneXIBCACtnX3ZQmPujf6ocvdnhsBheze71DSl34TfebyW2Qt+g9NhMxo4
+DaJy+iFNnsaMwLZRr6k/qf+ISE3A4opWAQlbk+Wb5s6DPPA2cHH6W4GdkxtuJzqt
+tFn6YtkFhA15Aahr/vz31NBjUJlBmO4PwvkyxiF/MYP6TQ/AHar4xP1RxSYEPcCi
+dIQczQ8nXzya4OqOyTfibeGz/eiHHuwTLHi3Rd2kihQnlRQdhE1rmm8uTyzFe1H+
+P7WW7kQgygW6yxQ3J+DXrG8kG+nbe57ZY1oyv3F/fOBxzn/kuoKHZ3JJEMJmTIrT
+Lr1ngCZApgteAynRHk4t/SYZiyoyqZCuBcwHABEBAAG0RUludGVsbGlKIElERUEg
+U2lnbiBLZXkgPGludGVsbGlqLWlkZWEtc2lnbi1rZXktbm9yZXBseUBqZXRicmFp
+bnMuY29tPrkBDQRSp3lyAQgAvc8Q7O0gVSJsHoVgSQ5tWGwNsKcfD3I7kwC8BYHr
+Q6F/UnhP1ArreNnn8KKpwOvD65pv0j5G7P9KAbIVLRRcCTB9MgJR2FPmRTNmYbKi
+Pa6X6IUM/25R0SBKDJddqSvEFsE/M1ozHz4bIhdFUXJFMfv7WBaA9Cx03WwZg6Bn
+5/xMzMC/qzG7QlXOMpcABtd2JlPImH13qHWNLkhyKW7y9HCfdBz9nOy0FGT54ttv
+r3BL1gahSXNi8MHP7m2I3C8dSuIpzrNVPgR2eByvSYpZN28P4Cy9l99TRcr6/FuA
+y5FaL/nWpv5WAraAV4Cx5Xpr4PXTn27b7k+feH8W/+9EAQARAQABiQElBBgBAgAP
+BQJSp3lyAhsMBQkSzAMAAAoJELz0FzlmdwGTSqAIAJ0/yTJRlWp+dwDZGxAffw0V
+iEHPkwAQ4iEKburA8LpcbTwJRl+k9d1RvFkZSWITq+F+Putlu9QooeVwcM+ht1Mm
+oah/aO3Yx+yMnXwljR7FJa5VOY2aoALeCyIx8QYiqNAVaid+bQ53gC924u5zRM+T
+J+vSChtqSBi+EOOTt5C+ALVB8qWTqEcD84AVbvvippCzKsA2sV69FrsIFAShvpXo
+3xpXW83GCXxrp8nM9M0E46Y/SarvGTqfKRC6phNUXKp9c3SnVttPEcGhb9+92LOL
+vMxKy4GRZS18bXDI3vS6gRDNJDCqBYIhp13Os9k+ZpnwK3PPIHv4l1I0i0EHZKk=
+=WJEa
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BE096E29EDB8D141
+uid    Eric Lafortune (Key for signing ProGuard artefacts) <eric@graphics.cornell.edu>
+
+sub    E05A9780475FAB55
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFFGZXQBCADeZK9xuCrDwJ7v37y8RITlchzBfJEWv7cSbrSIBlFNAsUUoshW
+Y8U6xYKe0GdiLVta2F8bzs0Si4LcDeglQNi9Fxvh3/jfs0MEJUfSeZ4z1Mn5WY35
+utbdlHe6i+7qvhpHveREwWoWuvFGKeSCV8SioolG1mzxrDVLkQefPZ+Kr+xd2cYZ
+SIkbjdhCvJHcUkD9gs8Wz9q9eDyc7dGJmfBYaQ7Xa6lbd852qj8LjQ7Gd41yHU6T
+U3oo0kKfAPFkW7rX4zeJEBgpncK0i4ertd5to/y2hauqPU3VMExqNS0/L2GqKNmb
+Q2Me02pBSBCrLLCUJkm8jZorPNxlQxHpFLHDABEBAAG0T0VyaWMgTGFmb3J0dW5l
+IChLZXkgZm9yIHNpZ25pbmcgUHJvR3VhcmQgYXJ0ZWZhY3RzKSA8ZXJpY0BncmFw
+aGljcy5jb3JuZWxsLmVkdT65AQ0EUUZldAEIAL0CmXXJLZWMbKXEROAYFnUqQ4eN
+LUcLY1NfL9xrF2KP6apMXLJdftwzJtcenfD5vra8w5JJBn6cvY4Dr4zmueDSsN3C
+pgr7c0trDNspAQMyUGmg4Cw7lAMruIX2om1TTa5ALsQ1PfupnLFLFKbYd2MmfwEV
+HgEBAzqmr89RoG/NnlV4uxvWumb/OrLzzizGLHdLFjnq3Szl6wQPJwmxCtWHvzW/
+Y+HYclm+wp0sufvrXJ/G1RrHKxwhxaDVyLKsb5wkUC6SZmE477SP6ZCokoAGHqEK
++5JnM9MYXreQ7N6NggRUseCokFaqckze5wVBXmPuVAg76ScPFQd4JzLkGzUAEQEA
+AYkBHwQYAQIACQUCUUZldAIbDAAKCRC+CW4p7bjRQSkUCACPWdIvMXPtSQFnFR8o
+UIGxvcp9MYdealHNYkf3qgJTuWbHTeD8WpE53immju4hitOq/qDevKOWhcfSaLqC
+tdRyYQFFDWQt4SsiGdWfCvKiBMSMnrDQI9f+XCv7J3ute5alyMgv9Uo1XLyyiwhz
+9kJ9mzg+ENvy152PucI4TN63qMRQMQbkAenrTzIer+5Q9ZY4TILC8pVVAIPQjTHu
+hdh8VMclTdkHab2PCFC57/3djJyY44PLhN3hLI4CElAGLUwBZLRa6OFOvwW5naiv
+wgk0zeeTqq/jTOWPYiy2dyyX1pRX8bJh5et4mXyM7HLHRp+FblgWxpFWNvMCEpxu
+jLsG
+=C9rK
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BEABCFBEE059E4E5
+sub    6579F3D193AD0019
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFOv78cBCACj4w72ksYDdLAY3GzwpRa1fo6S4aF7r96PitlETY83ct7AVF7j
+XaBGk5ylNAZXan3vlsSAKtxlI7skZOE5iKjqDo7SUfohs1WXdmL765mUNsSmkbG+
+WMOwDneg7Z6+licSC780OUFbifiPOKpgzGuaj91vrNigOmtyA+cbIHckhy+t3/PQ
+w4fO0S3RyJvQM/aQeDsyvhhBf2QzrUN7RQSfS69n0gtlVcu8usM7FZwOlBDGVPqi
+2Pauuj9QEyQIqnn07uWAUTzKrWF/WtcAXmLMxs59VuVRC3xnPVxekQTcJeCKas2L
+Aaic1HKp3AfTOT7+Ao2RRg4GpIiFhaJpul0dABEBAAG5AQ0EU6/vxwEIALyM80xq
+kaopZN0A1tNL6KUnoLZx/Tme1qp10JQ+AtYP5eFqPpM2yQIkFgWoQFFRZ3saPsqE
+jYlAAeyrRLOJ65PGRycHckckdhyEmGFCbHl4bJl3qnfJZuAqOSUlmxMwvhFTi7Hc
+BCOcWOqCBm99Y91IIy6NGeB+D5Oe7RGox4a9iDDh/NfyYCTTRo1vR6GW4JK5y/oJ
+GfWGx0U3CkzrwPw5efhCgSXmo0U+tQyUSWKl+J9DtdR+kP5mNoWOOxYMN3w4D68A
+IDXdD9ECEAXZKcKAlEXQ3AkVQ+Gfi24S4z5ewsHm8he6HFOsYb+FYtEByeydskWl
+U829LN49xrG2sm0AEQEAAYkBHwQYAQIACQUCU6/vxwIbDAAKCRC+q8++4Fnk5S9M
+B/wLDuqtJf1ANTTf7pyQBmjyeD9QE/Tzv606tnLxZwkZKqtEa/+3EJuPJLYOVHkn
+XpWl4VlMdJv6DEg4DrOQuJDEvv0R7YrIRqKZcZNRn+9donI6PI9jqrbY+8ZWsoA1
+kom+hU2VEoutPgxkZsZPHMj3LfWTGouTa3/HEOP5cxi5leiqJmYLKKBXJs4iMNBO
+BsqNQQjD/0rLeyh1JlVF/bpsapQJJ2kijowt5Yqg0rPOC2qq7EQUV54EVhiq4+40
+iyn5JNPmXaRHH8lFCavNWLNUh9HxNZHUOb7/UmFG9T77reY4ATTl0hZUYKdCYHeX
+eOq2bxXEhHlRB6yktjak7zk8
+=y0Hp
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    BEDE11EAF1164480
@@ -142,70 +2041,25 @@
 dYmmabxN6F5O3v+TNndEW7wgP0lkbsOWZ6YNmFhvoEtd1RxZiSNov5CxokYUrug1
 cS+/vsa9oIecUwxYOG2D1v/pwYhQnr3qasYz4nEEBWHnnkhyr1BbUSuen7w2SiK+
 64cQn6V9aeZYi6cAEQEAAbQfSm9lIFNjaG1ldHplciA8am9lQGV4dWJlcm8uY29t
-PokB1AQTAQoAPhYhBOOp+VB56EziAffPYL7eEerxFkSABQJb9RBMAhsDBQkDwmcA
-BQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEL7eEerxFkSAmfQL/A/61Wy/2XWE
-EsHGFhBFIGA3Z+MkEG+wtIZSs91Czz11n8288zt4o6As+7LzSnNj73VCw3wPTGFa
-+Tx/jj/459p0AeAxiOWBz6uQYRIOT+5j6za/3SvCrPf725UKpKVy6kPGQTfDg9ab
-Fyk16hj1nr1I/UDBeTjxnzWkGFw8vgSrFG+qVDJyZP4rNFeFNyG7VAl4kSukwRD0
-TAMyQP0HTo6Hxh1Zk6fYfVlqiSwsy1vzWAyLgHIImxQkE6KLJ54cd77Z6ie+WstE
-ZZKia6KHzwtGrYAq2Og5yEQnpMuWd5MCQa5xbLIB5MhcgV2EKVy4ad2ORIjyz+wy
-sFG1GIpRoqw96UcVfbZtfkyb4fmMrCtaCzteACcPmLIXHrNPvv3JLSJQ9j9Dn0+3
-jMA0whzbXcQWdqfF9Khb91U8PNUczuSfTTo8JUPIK7Wf52avk+iG9ArMYHGNn94g
-KcAzu0OCuZAxGCCFGHE+xR/KwtIRCojvWB13Q1aoxSfp28BpyXcSLLkBjQRb9RBM
-AQwA7UCAsQ8KxX8nYO4Sy2pzlh9W5FMPwGluuokPA2A6g2Fz3vF62RqeaE4HrRQM
-pijQCsN3JTJVwDid41X84XCMItkdAxMjmn5zeF/yCcRuHe2Ci/+ae5BzrBaKE/VW
-RAkaZSZWJ1MoDdpSxJhLHNFnVrwTkM/SeSNUBk9ZDEC+43b0hciefX9bFlc6XPHg
-V+yr5ohhwcNcrZ/gbAhhN3/xIVmvKoibmb+ZIajhiCP1OOH+GpZAPT93w9qZWq3+
-2gvP4ZZ7bO+8N8Gmz24GL3/0eYI6aMUMwWGjy5J+iRiFjb6E+Iv/zToyZFWm2VOu
-OUqy5t4u+Vyk5bl0hATpJICmKa5OFtQwG5Uvfztk6rujjat90xv8yzsBvoEUqKqz
-IzjHdN36qop5hLMnBljdLdFY+Rk9CHdF7MW8Nf0YWbP/3uUk19utGW686Lolt8gv
-BQc4B5N7VtNoXFCKM/I3ufgnHQvDlf8pgdJOcyx/a90V/DpUI1ANlwg6IsmFZXbB
-Qw7tABEBAAGJAbwEGAEKACYWIQTjqflQeehM4gH3z2C+3hHq8RZEgAUCW/UQTAIb
-DAUJA8JnAAAKCRC+3hHq8RZEgEy+C/4lsgrKCmq2Nc7eTdN1AxwMkj28XQFmkqO8
-orfJm1hAtVK1KRizkX52RNeRN6QX3pX9s1e3DjJi3Hpa1UWqeicPA0kKTi2ytUlx
-R/iZDkaQkLyCCZtWnGHr/eRBdOjblprl5O+v/tcyrmQGC04TqOntMumuk7JNjZ0Q
-AVkZUxdmfi9bHaF5W5vlcaFYT5gdWpkOQ0YaWXXw5ynh6Ookjhq0g4pZNjl2rdWW
-yTC59YIvC9THx0+vuyN7xnSWIb8J1IjEEYvPqRfpd8s1Vf2AA0JRPjUG2UV8MZqu
-8k8x4iC2gbdji/vyg/ycdlRT/ULyNprz1nTLMfhBT0Wmy8B5lFVme3URmld8T90R
-Pln6Dy+c+IKb/79z3FPujuSbipXzx3QvGwVYyP80JFn7CJluOl/u8vxi2EVFN6aV
-qdzwoswFE3+0W0AfbpHUUT4oeBW5OBTJ5i1Qb0DT6WXk3Y2j1Z08xxhY1RITnc2C
-33wjXAW0h+qq7/7Yq3w3/7ncv9sWIzU=
-=NtIH
------END PGP PUBLIC KEY BLOCK-----
-
-pub    7FE9900F412D622E
-uid    Wouter van Oortmerssen <aardappel@gmail.com>
-
-sub    AE6B5325E74ED034
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFnyVlkBCACe8zGkIlDV0dUKmk9PWe2Hw8qM9DdPbtpUOpmUOidGY5svQDL3
-eqvHk85TbxqFEe3Qbjjt+R+iApFuXy5kmueXTvwCm7nAU+k/pZtPuzHyhDs3iFFH
-8LCI/dOpd04LXLpuoeLCjBqPlOM+Pxiiu9h9tEnJaJzuXcw9SY3I/puj7qIEwxsJ
-W23gdPtYij9If1ht9gtTsDq9s7VbCM5vL0ofM8JVPilnE4oWuw9hjgIfT/QotbuS
-wPo+1ExZUfaKYPvMxi2kY3LZU3hlp6P5AxU+eI31yaYjtL+0lu66jTD6s8lwmF87
-QqjjxiHwic05//tp2Pk3PIZCoQurfEL6ZHhhABEBAAG0LFdvdXRlciB2YW4gT29y
-dG1lcnNzZW4gPGFhcmRhcHBlbEBnbWFpbC5jb20+iQE4BBMBAgAiBQJZ8lZZAhsD
-BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRB/6ZAPQS1iLtSPB/4l5s/avevY
-mNnuEp/97qiG8kWOvFfz3C5QP5lVmsj5hiK6Hllc1zjZxaS+TCdrsvH/zKZvgmv5
-9oy5nNHIu/sZB36JnLbE01ieM8hzoW5H7lADJ0JDI6wRbhJc9oXGA/1ZAudT+Jt8
-K2Ijzc2XOzHqE4j5vF0Sc9NWEM+OnAwkrbnIgK98ZiWTF807+/uobtanAUEWbFjb
-0wSNgSX8IvEj3rr/ZaIbf0Ymp/YObY94jVdBqFE1B1GR2TRp1YiAy+2BqoFE599v
-pmnWjZiT3fKL7V6XT98tyk9+XCFlQT7R5v+T4e+1Ad8j0RxsXUFKUScBPySrqEFl
-gMdy83QUeyhQuQENBFnyVlkBCACk/9GoJK23GwRKF8kx4h2oOkb63mP7DSPmsgBG
-CxvhH04oE9Rg+SPWKTjx7E0XFytyCuBYn9BoyGVPp45X5k4Vvj6sNJsSuyW7ExJf
-1AA7Xqa0mo1tjsUPSeAWyhruZCTaHGmnY6ClA3Bsy4E1C8sC0UapW9dNAf66SDp0
-jWeEkU366fa0RZexz92nIDCTQv4YZkYROX63P6Se7hNtontmKA6JajD+46OLGgNV
-gdSKZpO0PMyD8VMg5RUN8PXHqZ68gJ1ihjUJ499sXFuAaXKcxkbb+ajD6fYPQ2jy
-4S1tQpUGmBKAdvthMenEShmwk6lsTN86yH5q9tTNwMWjTbqFABEBAAGJAR8EGAEC
-AAkFAlnyVlkCGwwACgkQf+mQD0EtYi7nngf/aPDwJQG7NICIuMue/QlWCUG4zW2F
-ZL1iCKMYhfVnz29lM/5AG4Y0SlcRkgEigizBQUkeLVHaj3obLlxr1I5yrjaOwD/f
-ruk3roC1pi+1i0sv0/eZJvyVN3Ta3pjzYDT/Qw09Ao5py7HksJsvAM8tIbw5hnmx
-q091M8/zdgIi/H38QFBWKNYaPkC6WMxWv0M47Kttcfv1DBF/NmsMzts45BDoE98C
-VB/5M2eLVVrbHlj4QqpLDTeSYwcTb7JVSKrNbyp2Ws27l1oNhMexztBivHz1OLxG
-JY8odrCtuxK3JMllDdln/HHdwrp6h7SDRdxR6llX74zIdctZVsii8eJHvA==
-=o0Pq
+PrkBjQRb9RBMAQwA7UCAsQ8KxX8nYO4Sy2pzlh9W5FMPwGluuokPA2A6g2Fz3vF6
+2RqeaE4HrRQMpijQCsN3JTJVwDid41X84XCMItkdAxMjmn5zeF/yCcRuHe2Ci/+a
+e5BzrBaKE/VWRAkaZSZWJ1MoDdpSxJhLHNFnVrwTkM/SeSNUBk9ZDEC+43b0hcie
+fX9bFlc6XPHgV+yr5ohhwcNcrZ/gbAhhN3/xIVmvKoibmb+ZIajhiCP1OOH+GpZA
+PT93w9qZWq3+2gvP4ZZ7bO+8N8Gmz24GL3/0eYI6aMUMwWGjy5J+iRiFjb6E+Iv/
+zToyZFWm2VOuOUqy5t4u+Vyk5bl0hATpJICmKa5OFtQwG5Uvfztk6rujjat90xv8
+yzsBvoEUqKqzIzjHdN36qop5hLMnBljdLdFY+Rk9CHdF7MW8Nf0YWbP/3uUk19ut
+GW686Lolt8gvBQc4B5N7VtNoXFCKM/I3ufgnHQvDlf8pgdJOcyx/a90V/DpUI1AN
+lwg6IsmFZXbBQw7tABEBAAGJAbwEGAEKACYWIQTjqflQeehM4gH3z2C+3hHq8RZE
+gAUCW/UQTAIbDAUJA8JnAAAKCRC+3hHq8RZEgEy+C/4lsgrKCmq2Nc7eTdN1AxwM
+kj28XQFmkqO8orfJm1hAtVK1KRizkX52RNeRN6QX3pX9s1e3DjJi3Hpa1UWqeicP
+A0kKTi2ytUlxR/iZDkaQkLyCCZtWnGHr/eRBdOjblprl5O+v/tcyrmQGC04TqOnt
+Mumuk7JNjZ0QAVkZUxdmfi9bHaF5W5vlcaFYT5gdWpkOQ0YaWXXw5ynh6Ookjhq0
+g4pZNjl2rdWWyTC59YIvC9THx0+vuyN7xnSWIb8J1IjEEYvPqRfpd8s1Vf2AA0JR
+PjUG2UV8MZqu8k8x4iC2gbdji/vyg/ycdlRT/ULyNprz1nTLMfhBT0Wmy8B5lFVm
+e3URmld8T90RPln6Dy+c+IKb/79z3FPujuSbipXzx3QvGwVYyP80JFn7CJluOl/u
+8vxi2EVFN6aVqdzwoswFE3+0W0AfbpHUUT4oeBW5OBTJ5i1Qb0DT6WXk3Y2j1Z08
+xxhY1RITnc2C33wjXAW0h+qq7/7Yq3w3/7ncv9sWIzU=
+=3nku
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    BF1518E0160788A2
@@ -237,168 +2091,348 @@
 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
-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
-=v6l+
+YmFpc2UgKEFTRiBLZXkpIDxraG1hcmJhaXNlQGFwYWNoZS5vcmc+uQQNBFT3VuYB
+IACYmSu8e3gsb5h8CBt9xPi8RDfMWgOAhDCWV8trJwycStlhSh1hUQ0MdH9CPELX
+oi7DmKo0SG/+zPQfJ26zLumKUB9j27UqgHZJRxXqyYFaVizmo+mWrOtiwR2dpF1g
+P37VT1OsELcLQYl5YKaJFLMCapjoZhUXZ7wleUY5dYijoaH74glU2TdFvcN2u46p
+O0vqTnWe7YdANBPfVs1lrZr4Mml0OEVVGuUnBBxIAtuvIi6C/Sgbzd7AL/kXUJD5
+dqtWtXwO0OeBASBPjb5PfStjN56k8qJ8H4M9PflBc2jy+982j/aTZGAVsXw9hGJK
+wwI25AI59MAKHzbuiqs3Vfm2xNqZ6PipvkhQ0HdlnKkMIkUsyr9sdQKWsF7JX5gS
+cQEJ2jFptIYsD4548ijp/kMS7Lt2/DW0gh87S5HODy4VAhcUTLSzXMdsy9TYktJy
+/cRC1cR9yNMp4/1mF9McdBvcQimGmF2Atlwr9OGJsF8weX/pQCgV4lFv7rLo0T/k
+JzEa2bOSJrs1mrm/XHdwcyVEBA4rHXwQShOXyEym6tBWg0C4GhCdzCsjZTKtkn+8
+wAcyDx7V1z+jhMICZOtCNJCdcSV3OEg76b/vpYsiJxncEu6KG6S0ej/BY9U6laRd
+Zx7ShV/9mLlOHgFHBZ6ZFT7ThpDU9SUTAtty/N/60jgDBiXzItIiOADU0eLw1+av
+5bFGCoTI1uGqJkd5PHvTU/UT6zokzcEbNe1VCj16slCaalYIZMA1xjoBcz+fXM1D
+JDTXCR4omNN/S9jlBIQ6frs5easBbIwLPqVYjh1oGdqvC16qbycKVYoYHBoWZMrf
+EWjUcimYhL7fQOJb4aM3eBk7hXzdK80yVelkXxEjEZUGK3n5nO7z63rr7eXXtltA
+FwtI+0s/QUpv6FeuWltSwEUH9FMWESsNgtkGhSM6VLOTx81VuHprlYL7IszZc8rH
+od07BeQBnRaw+w2gp8+HRssYpK8nYaDp+jKC/94df61h0mlhzCe+QsQOGY+QZ8dA
+u/z5pbVvGMRMpIsxvX0o2vWKNmRSmazdFKg8GoyWDOYIf42gGZuBGOaaNLCcviYS
+MXp/1nwhcgoLEhe2kv/jrWT5+VhyFOTBzKEAfLNdZIiMHaxB7gjuop9zuwZzWuBl
+6VwWYYFm+cGlBHaSn45R+Iy39Ol7SlthH4AdmeQLFNY6iiTzSIL7LcFvObJGRq5s
+Q11DYERDheIsGmDqhhLwDJEWezCZbpcjbV5VfUik3pNB74ipJ+jBisd/9xcwgWKi
+niLH1N3el95Ll2AqFj7qIFoUuL2NvMoD1bi5/e3RU8n3G3BIOhph/s5Kz6Sh0xgB
+HbooL7MVqe/vHJwcrL3cve9pABEBAAGJBDwEGAEKAA8FAlT3VuYCGwwFCQPCZwAA
+IQkQvxUY4BYHiKIWIQSunlP8KP8qsQEic9C/FRjgFgeIomCmH/sEtcYzJC3qPx4R
+IAqw87ODgPWpDDCeuizLRI1Z049h17Ptllq2uCXDBJeOx1tHh78SFF3bLreDN1qO
+kuSL/uc3KD82SIpVQoh3xIoY6WeR/HijBTgNWNuy4ub+azUG/zeM1edaCEKOJvbc
+o4BI+NRqFPD9Wk2Is/mBZ2cjAbhPGguzqJgsdf96U4+s0DTI3PnkixTEQ4fa54g0
++XtoTXlNQ8iN+gQKrobye2dr+G2xJBDA80Bn1bKSc7jqCB/MrOlChBLcJBPebtnW
+MR320JpytJripcanEpZVshg11ZxSmXpUZAfl+UPeVOqJJdZbl1T2DxkojYnvKSL+
+w+9ocfXXBgUasbLL5nVEQHJcBLfI4eb9l2jdRR3DdBvdUO0xC09Kwz6pw72ptNg4
+KQHu+to6eq96sdAWTfAKHfNyB2MrJhsLtRVdV5tjDe7mpONbW0EArL3LC/TyEH1g
+W9XWQoYQqBpGC//OCkIg+Aah+mwJP8HtoWwPcrSZprrpDjOuIwCTh6QHaAL+P9RO
+hVg0Eejniq59jvb+aJDuSwEAMGKA9M5v6CMnHNRb29Ul7xnx9BWH82SD8uilAYIq
+rtn/7FCQaFoL5h65xtJHtbm9fFvS41llCvQ4ts59x8opcqrkKBUcCQdJYJIuhauE
+A8a6dwPAqfuZQA/d6/R4R3ixuGSjLsJucvEiY7mc2znLcJ8oaK/UjW5BN6aC16eJ
+6KFeN6gFezmsd7cJpcZ52JVMUXaMWbpCmZwxPqZWUndZG6wmShSghwy/ZJci0mFU
+T9mM02SET2imuM+duam6ISnRS9lnf7Zh5IEnjViKTgwZWgApgw3rUxKrhlJhSAQ/
+8OP7DEUWFmhoRi/CdE/jhKHw4ZWBk3T3u3QJp76tFODqslVq3H9jM6Z266dpGZWS
+yU5a/P4HBt/XQiJITGe0ljqFXslQaRyiGs0hO7XhPkDT/bH9PJnzC2t5OGzZufId
+Tgw5FthEN5CW2nhQ8TfEoiM6FxnvT8cz4SbeJ71SysAf063Renq/wuBo01FGyarU
+thanrfQq7DebLUIK3D9w4V9Up/AQUHUt/LtZk9T1bN0r1716ym0joXq66rQDbBj8
+b8tjKcTDJB/BIynsgjKuM9PM03OFYbkjfcDk/UHbhXnr7+0o4naEWXOeBs8WLscr
+Pz0ceeJiw8iAc2TsqDQSDCIGQdQiNfSXaxFh1ZHC5IlR5Rvm03meVlPqjBfVh5N1
+DjirNire/h1uiCIg+iQt4Syrb/Ev9A8zRmsVMaZ9LRTEq2m4UENd21UclLmDU369
+q3x4Gr+2VwUUVJc3ErUZmhgwUDQMOFdU3MXUVViyjGTpI/YS12D5/mppKyqICYAc
+v7q0QO7B
+=pkKx
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BF984B4145EA13F7
+sub    84761D363E7B0FC4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF7rgogBCADU9OwoEFdIgN5U0JU5pI7s3T1T1LeDMzAQ8l2Hq4jFrhnrjcEA
+ieDSut1YIv5NTBoZv4CrklaKvvQNUXPvKrFImA4OKhBodKV3wsq2efCATDGa1JAw
+VEJx6nJxxMsCLCJvmZsD+YE8/DIBI6jjnjh8jagZVkxkSRPvUIxlZCxytIyqXI0t
+O8pLh8+8p5e0PgGb9OoszxEQZdBavsixdpe+0feU9cz0l0jJYx3W4ErZeCGGwNat
+UUiW0ctb3iz7BkNhhoV9zepxkSLzCf5zBeyA+WfD34028pAfPpyAfDYXF4x55sVP
+/3MdWGB6eU6KzPG2/QV/6or5E+C1yCMrnMy1ABEBAAG5AQ0EXuuCiAEIAMExiS4A
+u6FPSlMyjCaT8EfxP05ey79rYSSZd/ixmqyVzJkXYbf/SJCBeX9+NtWU3LEuL0L9
+WXgAA9Ys18NaJzBMC4kiQJfyXK6Kak7sUfZWWvx3Ad3It35X4svJNuR9GoqgsOvC
+D1SPgK7MfTcAF8e4j2UUqgRnjM5S6dRa6AH2s3bCj8GE+YSH9Ag2osNcKBgosNiv
+w04tYh+sjx8W5ehKaOEMrBDO8OMYVeiIEOvBIjsCZpJgAnOBPh/7zIQ72tPa9Ou3
+nAWBwdiPBgqv5FTIVmHWMfAJKRRCW4ri2hN6toHGrjJMgobtwW56vTibb82EGLdY
+3BF41DQT2MEiM1UAEQEAAYkBPAQYAQgAJhYhBB0Ki153xninxyREWr+YS0FF6hP3
+BQJe64KIAhsMBQkDwmcAAAoJEL+YS0FF6hP3VWoH/1Uhih+Q/iJIddvBatWdzpgO
+e03ppK9pCWZ2KepukILbR8bpX3cqUiTbFD3W+ybrrY0k4Oe9hXcm3re0N2GAfEWf
+tRknxXH0TMeyWoBlldfSM5DjrljM88XAIkk/T2wcARv1PC59IIZGKOpixItF5Pps
+YII4YzlripU98sXBTSlJLU1/UZaT7XNOZ9O1/PVxADpVIeH6MVdWh4W7AV/dYZ5j
+d31NbXDTtyDJBUYoiq2hu10+RNoqq28WmJQGD8aqIuKOpeBA8EirLcRoDGELSqYT
+lQyC8nl8P5PgkEZ5CHcGymZlpzihR3ECrPJTk39Sb7D3SxCW4WrChV3kVfmLgvc=
+=WqT9
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    BFFC9B54721244AD
+sub    788E173C196BC673
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBFRRGVMBDADAQcmG+x0mHZwJ3uKgODjUZXkGRkuz7aP/qRmuQVn93tl8DmA1
+lgvXndvChUjzYt4DJnQhRsapAXEmP5/YYIkWOzuk9EpXGtqUieocylvNXP9eDF9y
+4mRbGbCUmz5W6Y/3w7wIsrz4kbCC5xij7cavCxxSGGg1IsyDHYkOMpcQyZH41vXJ
+IPMyDvkJUON2/YA+xPph4XkmNA+hJZ1fEa+06Cd5P4j8GeTnpibkkgzqzjuiUlo1
+PcXMXUzkGnf5IwMQOdDYbmDC0K+QUKEPheWY6NsmTdZTuyEdD7BunWA++mUlrqZW
+n81HMNijG9fQbipvuGiOn7OfmVF1eqfH+NtP9csBCjn84ZMUHHArzsWgb9LWpoki
++vQyc2K+egdykeDJG3hFZ0Ztbz1YPQAUy8BN3r/OmKuSwJ33cleugxyDe123kyUX
+KhBdGEY9pTZ8dbBKn6PfA51XvuWQSVPJRjG3bPFphLPDYNJr/MUuYqo3TSTSp1O9
+EGUz6yVG/S01tJ0AEQEAAbkBjQRUURlTAQwA5QjPD3Y6kiGacT7lXdhYYN1m0iHV
+ddk6NpERbQn7NAncLI8yx2kWCtF2bBYujv/plSfMKZmKSR2VUx3NXwmG4QD0Wr0G
+AjhS81jrmAjEEs6Kf0fvihJn5Z5fJAyDB0BMYARhCPtQBmZ5g/mLQWqPEj00kaXc
+vZyPaMwOvkFpNowItAdj+oxt9v2DS0zYSNQoRtF8WkX8GeU5j5yL8l3+dgu9CKlS
+CM+DqnbpMDiXDdDpc56Ca5jSuI85+c0TYo6ZIvn/34nmWMD5dIMQ2504Qr+Cuc9g
+u3zIJL9Op5TPpDKLMhiF+Pdes51unoFMnuLKMmbPWtIAIXkphd1QkVTnhr/yiqh6
+gGyGD3520FLTqR+Aq44CUUINWN2nBTbgrAaE42B0PRGVjtmTqoYJBziig0Fbqt+m
+BPwvT5+qRlX9fttcV4Nkhgan7JNH2B7xL07mWXAOifoGmkAeCH5y5TKvxJOCGTw0
+17NN05RCsQTHsL+0OhjU32hvhRGrbQTNq17nABEBAAGJAaUEGAECAA8CGwwFAlRR
+G/8FCQHhNh4ACgkQv/ybVHISRK1gaAv+Lg3GF1LFbHQlT0DiF8cAJ7f0VTiEgpKR
+SHh1SJ9mwPJYM+60HNHr2/i6+8aMML6VVy8goOvYzSW9BPgTY7wPF5HJ6k09kzDP
++R/tG74XjrZNFwZfRQ9rAeAlMVYXpPcUfo2FpM8tvR8HKAvJJNZfPGEtVkIJnJSz
+pZcqLX7ScOdKyWu+byo7+UoINF0vWvHorWHps0iMNDtrCL1QiNWxGMYH0+vK+a0C
+zGM/C2JllP8hzLc8anJjjtcF2xIZGL/roQnal6g2+OlKmtXSgdDwGOzEFPIjMHU2
+CvsjRPX2RbdzKOjIo/4ybjKtbvrbiXPfUORyb/aQ8PHHAZXaQ6yU1LRTCI+qA+gu
+sFCtKpk7RvXQdo6sIcrpqvLfAAWL7SB6zV0rtIFqPHh09NlLJ3LIl+2UK43Sa7gT
+j88XfFZYef0bm+IZjSGmEaZVEiXHB79AXyD3DZDhHX8fmcJIvvaZt+6V34ZOaKIG
+RATW8oAGjGserAKr1rvL3gGRF8LiRmBx
+=oggK
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C1ADD37CA0069309
+uid    Spdx Gradle Plugin Owners (key generated by Appu Goundan) <gradle-plugin-owners@spdx.org>
+
+sub    3F078B16810B4EA4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=wfpM
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C1B12A5D99C0729D
+uid    Valentin Fondaratov <fondarat@gmail.com>
+
+sub    606CC6C4533E81A2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGAic/4BDACtIv4a32pL+84jJNhJ1yb6GFgoWknJSJ6IELIL0Z7m+FYsymRs
+lTJ/QwBgjZlgS3HS7IBhEl5o+kEt2/U5lPkz/krP8By8EvRv18PpfBzmXNT8rGqc
+3Kq6CSye+aLfdtY2yP60yZCtES/E8s3gIQWV+yFbVm8K8nhMTUnHRxYEcWfK7YI9
+FwjRkSVuOQHhOYJKYeSxRvmARd8i355MN8unPhkuY3stBuWoZYNjSuXXE8fs4DBL
+0yx0lkzH5jI5E1lagp98ChOjbLQuACvVLxLP326ktgQjeZjO5xqe+Rm5h9iV2ETw
+UUJhigrsOMhzl6lk+9JqqNxKiEaoNcsW2NL5O3Jd6ta/WPSQtQGrElKBcZnltf95
+0SAJBKa/+B9our/SuNSe8kwKAK284ecwVo4AwavdPd+s2UR9ECcytDXFDs/QGQD4
+TjZ7sGgpFrLaoXXu4OqR7w1085I4RNELrfR/p5kRBhpU41Ey/UXpE9KGMztQ/tA8
+W0JEQdCUVgc6MQEAEQEAAbQoVmFsZW50aW4gRm9uZGFyYXRvdiA8Zm9uZGFyYXRA
+Z21haWwuY29tPrkBjQRgInP+AQwA3Ec9GNzLiMlTBn0x6EJL/sxRo83VrlAQcR2W
+ulDV7e8zFeCVB/jiy1yFIdJ5VyCXeVzsSs/ceEBqjEnz4MvWX1lnzX9zqcRArx7a
+SaPfB4Hva8Z91f7sTcNQAbvwNw1kUBVJZU8UOfDGMt+fycVidWO7CQpvuq1ZvL3n
+dApXLXHD2YMvOqgVg1jtaFPlaVSOoWkXyMg09ECof3p+JECB3ZJ7lht0JA3MHOk8
+gObcdsDxwwb3A+dS/Zw5Q/8zopHqGVmldiF4tG1SYqzc/i3Az58EYNZ2Ul1C2OI+
+tfh4FS2UqkwuRPspfPCfc89NXoyO00ArJOe/87xY5HvVm6BK8azL9RaogEyFmCxi
+EuZo9yC5NZhWD1CEEO0J45ZsTpxitUhKwoGgGO86yRJqiFuCfYHzRtkGqgDBQGC1
+PIE1/thSwdVYwt8ym5Bn9iNvSctoXoVYfsCw0gcTpQFTgib7S/kK1Gryq/vyQLg/
+KNV99TstqIeuT4w/BmT1f1yQH0fbABEBAAGJAbwEGAEIACYWIQTmIjEzG8p+Hyks
+m4jBsSpdmcBynQUCYCJz/gIbDAUJA8JnAAAKCRDBsSpdmcBynQaPC/wIP9hArjec
+DiSx6omRgFBaAILsQG7eKPwXCjob4GE2jtnWQi1jobE32GuXoRO/Hj2gz9+Ipsvf
+vWKmyMzJ8noPkCNsvVehuGwp1FQyyk+c6MHww4vLa3abr2e61EEaqVUEyXQ99m6K
+h7+FQq8apyCp6L41AN4mb1/g4hWzrCv/18evLzxZ3sC0sTZfrx8ECc7iGhsOgkI4
+Ls+ME48vYt5c+8Vmq+Gae/IZgQQKupRTxCqRWGTqwDsXOfXIwxcJ4eW8cNWCa+V/
+MIVSBri7/6jRXufu3lYEby3rYjV7JHaWE9ZFQrpwvxk2riyNd/6OJdJg8mfuGVF0
+78KBRtMCorx0t3tGqjqhZz2fftFJ94VXrvjm7dvPhP69u2bVVFeA83B7pCNu+lXu
+30d8b5D319qJCx6c31wQvj4SvQuB9uBDDNePl6Bkn8QeKcudTJJUPB+dS/lTVpQO
++b//JnTWDaGUkhM6IdLK+pJDxQwFRJBJfDHZj4y10zQANp5u2nyyg8Q=
+=T2sw
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C29B11246382A4D7
+uid    charleskorn's Travis CI builds <travis@charleskorn.com>
+
+sub    97149CA7141687A7
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+CmA=
+=4Ype
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C4C8CB73B1435348
+sub    EA2A558279B36E6B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+4q5nL0cFWrpYBtEUxDwWSI3K
+=qAlt
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C51E6CBC7FF46F0B
+sub    4006CBA6D352F1FC
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFbgSbABCADGGENSy3oWLjW7zfYMSsR0pm3l3eMA7ptyU5C0U/MoIYjbXwyX
+XtlGwKnNgngATh1SMpX4WDbD8tn6vdeP4uHQsDb40t0XN7/HISFcLhV5pCgz2wNR
+t1dZbreV/EaZn3f84Vnm9s6TU7RHuPP9qBne1YLbB+LKKZUfQGavqGR+n322DhrR
+NqLdC3zFNtSmCVXS6GZ17IV/B+6CiNdbmPVk0o7zZexqZCNMXxv1IFzHV1/Y8Htu
+WQBfZ0zWwrX85ZKysU7UDdoyUw2aa8/+YpZmKwo32N8GpqA6azBeUjjVXGuqktMy
+l6IcHbLlgymkkjK7TyAKltuhvp6AlBTzp9i/ABEBAAG5AQ0EVuBJsAEIALE90/PK
+unEOu2B+QGGV9e0jJMlW+rs3BV6NI9ZaRw0Uvy0xN+jqhMsyCzB8P1joTZKUsmK9
+ptaPlMuKrTaQ/0GYPi6cP5EamphyvjK8ljLhhQuiAxt7zwv78vX7CGqRUEcAszsK
+8FPBAXERsSit661rjp4Ai71cyQg8YOXDjhissHWmneF8TJ3yItocj4KxDKLxoY+h
+F64epbkjIkpfrZ34iX8zdZMRCNJlh+oTHe/xulYLQDbgkgQa+Y6gnKmUZi0QGU01
+k6eWw/U3yOC69++ehiYcZYS0dWpPE/H51Rizn7QipFeFfTsia9jkGjzMyKHGju66
+URQ8okd4E6ev3N8AEQEAAYkBHwQYAQIACQUCVuBJsAIbDAAKCRDFHmy8f/RvC1c0
+CACy49b4H6ZzY71Ao9JHRRpQZ2VSVk+6xPblr1DOoytDC/zhVKekerE7OBEul0UO
+qzUyLNwkDiHy+5PRi6ZquZr85PlaVV5j6DkuZ/0lcL3ofsvtQi1Dwd1q/9RzedSU
+jjY3OimPWDkDBIGyBXohxx1BxRIAvlRnk9agapfbAdwtv6cjYxW0TDcPx4XW839n
+MN3CMEWtlI1GhKGYi5nsUw73ctpSq9dm3ov85ykFOqB/juvTcPoiOwPE+6o0OCTZ
+o60VwPUfv7uoXtkrLVJ0B06mfKiUgZvaqppYDi9IrhcHarOz8MD2OrUS3z4riTsL
+VEPwY+Xd06QyemMynHqpcDpm
+=1WLL
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    C727D053C4481CF5
+uid    TFLite Support <tflite-support-github-robot@google.com>
+
+sub    29E792953D515FC5
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF8pVB0BDADcwRGpJUDe8eVSlJ0yPQl/CyeYc0RWq2f1seUMQO0xFW1xPIeL
+IE68D9VdgarA88qDLYesfBqzn57/r/ztj2aLEKt8IRunJzd0w0G2rrgSCZQ8RmzL
+b6qNocE4EqOluhuzHBI+1+tqoZfVTkfhqKQw0RjP6gHPrelYPuxmzXX3dbpf9eam
+yDdr1tztvI8iIwYvHoy2HNmkXMUJwlzKsRrU/x3SMnEqTIFqGDy32zQ9QdnMtVbd
+lCc9IWnleospZN52+jeXoMhRJYc/pSHSMu7DSo+rHs9a4NxHfaPnuOsw/Sn0450R
++XbBV/4oeWuJ7g+MXvLepB1LTC8tETWwYFPyA+qmFhbFnir+i7JKEEYO3TJJgkLG
+xlXlM7DAhHIky+jokeNl1n2QhSSuQ1dq9KCLlrpDrSGXaBvtonPyBT/Ik9YGgR4/
+ARctQLaQ5AucEPHuZZl/d71499y+IP//ui6SOH3LBIs1nqFmTGXMoEGHbIyEZvjk
++wLnG2YrlcpLtl8AEQEAAbQ3VEZMaXRlIFN1cHBvcnQgPHRmbGl0ZS1zdXBwb3J0
+LWdpdGh1Yi1yb2JvdEBnb29nbGUuY29tPrkBjQRfKVQdAQwA06Zqf4RRCqPtmx4n
+qG8wXLUayoWq4hIQpkajt7UYBejFrScJZeE7Oo8HwiQzPs6iBMUQQeZBn8gQU2/C
++ZvTD9WjhRFqI0CXcCS2VL7nciR4yMwKrrlf9LJAhBjKfw+07VEF8D/xDTcYuGXF
+IuDtEu3Ncq/t8C6ybjVOFGtNFRsGABiMm1PKIA3496f6GQLo3oioU5jizCrgouk2
+6Ak2hK98i3+utOjVYBIcQ2Y+tUxV6AucSAU1zLVqVj+SY/kVaj7hp5w2sGVn+4r5
+dsGIUG2K/VjIPXOfmpMtsuOLBN2z80RtO/b5OjHJCftjI9KqnyAozw6LpbNkmOhR
+nfAPaslfxUyxiHbRg+RJ4eA+4ZnbAZPzNvBt9TLervLhYeh42d4XGA/uicCCwMyF
+UxztOQ+oWpY4fR3qhUoGNKmEetBcJtK5z+LQipd9GuRKpylJBG9eU7ecimrmI5pM
+LnNjJNkyvd5VDCoO8WbX0AO8MV1s/08sduAnHul9W1u+bkADABEBAAGJAbwEGAEK
+ACYWIQTbBZfjFENCJWvIHj7HJ9BTxEgc9QUCXylUHQIbDAUJA8JnAAAKCRDHJ9BT
+xEgc9Se7C/45UwrGhyd7CU4dMNgpBW0a+7cFcbjfyjSNOgPDbn4P5B3G/o3sTOf8
+K8O3nMgMnQ0FH7TeLwTxc0vF7r26jG6E6YCZU19yMef5xEJa08YqUNJkJ+2Fopu4
+WhS0mEbpII5o9fMQ93urEEj38hCV8lUyPLUPQpWrmyvS0Pta2Y9xDpYKy+bKQLMl
+RGPna8MVNXWFUd4AaOY+us8/rbRTWURB2YuWyPyetXw8veIWLJgEmbRijkZbUVro
+UJ70OXB46dOEVktUJ03N9zX2SpiIJ2Lg4OAdi8tdp5EklrT8Sp1vGZOcwA7r/Bbp
+WesIqbHNftRMjxPuWZ0ROY4m7xzhexeOAn0HQNg6INswfXKuAJJNv+DEe9nTxpi/
+TkO8Ol5MYDILvKyZs36osPk0L6EEgVzrqH9zUKTiq8toczTtb0uW8f9Mru1UDtme
+13f1tnq+z94ZcR19NEV8Rfs96NyYYUvfC+ro4to0pXe2n4X3BixeaBmNdHWd9YYg
+XjYxnM4pLyU=
+=QmNQ
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    C7CA19B7B620D787
@@ -417,330 +2451,95 @@
 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
-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
-=H7JA
+b25ub2xseSA8c3RlcGhlbmNAYXBhY2hlLm9yZz65BA0ESuDUgBAQAMJcjsRrUhLv
+q0vxeuDhSL61Hz1LtU47Q0npuY3xyKCjBPc57UA8sUsXMzPdMBgeX58RVlrhUEHc
+i29mkt6ZpKEW7QyK91kxTAX6Ic4xFLMS48uudV6JFYe79cyRaam/dvlTnh1euhsE
+SkFhwk8ovORv+puEqQxBTjqKWIjt2mGLNMijZ1MoKGUFF9A9GBjTnvJEvC87ot1V
+8ABQjVjeyYf/230Ap2kdwlBk1jJ1BOjVzGOpG/H5eWgTGs94LijHa/gZEXeXLku4
+tqNpE/I7Mfz9WoGr5BQcmDu4zETm7JDK/il/+5cLzYJwUua+H0VcwLCTD/TjEPmt
+aOnUMD27Kpn9MMxiUx2PG0qFmuo+otx4l634c0huG4EQFqkEIEVQyri8Os4NJRRI
+kewjNxjMjV0c/45ki5dHvzVYV29Uq2MOIz0oh8RX6v603SEzWJ7sBVF0J1pjgJEa
+jRohFTSH4YkequnSBb2G4VAzZi01YLJhk97KQZ9NRWCO4zurk406TGqOBmKKf0A6
+z2qVGgRs2MXyOi+YpGUNxUUMFHU7kBweRS5l6k5D4posE6RohYXs/CJowLxN9r2Y
+giLEbpBhPJyRa0amiTC/X1sJ5DMwNAgIhMcskJAys88ZGKOGMicRQ8gHdgJOed5b
+JkwKY0A/r98jzCVKj2yl4/sscdGmulaHAAMFD/0RN53mDdp8tBIQWU12PRWlwPx0
+fIMqHc0MQFncKQxGUUC+j1uq6gCoqNOXXKlXA9c3kL1iUTF+2n9wkFalnUpYhUhL
++r5SIDudFYwwnaCxfhrehMdhGc0wYxUqHLE3zx4qnJwMJ73Lo2u6/+w8xfIyKehu
+rSIQxnhiSU8gZOuerHqksvwNFjxURbGw5OydXl/vBeciYAFUUOmV0+/bWZb6D+8w
+qzESDuxpjuOCfP5MbGBBE1IBjElPo1VZqcKgdRW9VYMIHqttiVChU4hH8gmNpN4L
+eAeHnuAgchGD95HmtkwhmRnr6sbPg6QQ+zM3NIq4BK5hGsTXWjzHPnw+7e1MbIYs
+Oo1SkFe6LKNfgMfS4CoZRVHOV+FN2AWFh9p9Gbk0b6Zp9S+Jz30ZBerAJAlgE7x+
+AqzwVn651fyU6OpqjXJnDLbk2SAsOdtcqWG3TzTTsS6P/9KoO7ESGcjhdCUj4rxd
+DdHR5CRrOF8Wflyjwc5SXq98Q54jKn0HbYbTLidJEpocFS0Sh8DUviiZMQ94MW8o
+IHqGRSw8ert/P0yQAvvgdRF1+EcZ8/rs7zMvJHTe6SRyoND39V/CzwuAU2BgYbJH
+X0hXPBxWF1c9QcvE9H+MdnU8oIfcVo/D32gR4Fdre4IuVKiBW7QhQLo9RkyEkh7u
+wDkgbmvLFwh5el1o3YhJBBgRAgAJBQJK4NSAAhsMAAoJEMfKGbe2INeHLcAAn0o+
+lXUb2Mc5eHXkbkTBofl4tYxdAJ9EO0kGWS8rPdGU/dAyHRCoHM4/FIhJBBgRAgAJ
+BQJK4NSAAhsMAAoJEMfKGbe2INeHLcAAoKCttVyQMou1JLwo/NFNrSiMyAlcAKCT
+wRo6LpahA0hXIR/dwnekHH7Faw==
+=sl+a
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    6449005F96BC97A3
-sub    D3DBC823BE4819ED
-sub    0162FE0CF6E18BD4
+pub    C92C5FEC70161C62
+uid    Herve Boutemy <hboutemy@apache.org>
+
+sub    64863FF4D1BF1809
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-FPjHFhRiWd3YGlydu4Dtzwfkmu43CTGp
-=Pq8A
+mQGiBEdUhrIRBADCU9cuKc92CWQlZxwtRuSIV/36Qmj264YD+Lix+r1Qe1PqRr1I
+/MObOo83ulorWigSkx1k81Mnr56NwmIeo2bMhjmgRgf7EG6XEbKdRKfJcJRR1lDV
+Ml4ru40W958M3PX5fsi0m0g2TuVrAKIS4vscUt4L/Cf4IT2/0OhaT6bWswCgsNws
+Qq6NtCkLkpWSBNYGT4zb6yUEALlhHMnfzPSDerKjDOaYHTz3PRc/GGUDSBTSVj6W
+hQIDrgTqrPxoB5JMnfUz8BLSayk0d6HiwspJ4Wnxe2/jdIT+6xhX9xBYXVHZVs4R
+cr8zbBNcW2kwFg5Mqy7TiAPzakzCslKAAX+cjAKSOWyRbmkEYnNgMlctdyENOR9+
+BpP+A/9anoVEfULqoETShmgWdi94gx713qymhNBpFZnPpm4j4JuxKopl/unQmw5i
+Jwtu93cg38UfaOMJjTi6tJ6F6SE8xXv43nKs3Xb+Ll1MpTgaGUXEhCOeTZl223Qe
+NBUp8kvfcys6aVX6GT93dmWxtMewlc6gc7HVQnUnyCFsVeoy/7QjSGVydmUgQm91
+dGVteSA8aGJvdXRlbXlAYXBhY2hlLm9yZz65Ag0ER1SGshAIAPzs1unq2BMWlk4y
+O8D5w9br9S3qtlkYRtSOWH7ilOyvdUzIpQZvC/qgphdUBIO8hepmLXcF4zogNGKB
+jlRHjSRC4SRSmTqHmaG/kdwwtOblLAZe8YtzYAfDLGoLOTeKvp6mUjGWhA5eSUeG
+QIWAmQcucQZp75kT1C+dAgzdiASsR1TmlJZQSGQ7XbVR9+xsGlc17oT8bC4gDnid
+vVtbfEayD/U40JT4c8Luz/Rat/yXApoRfMTpnJ98Hwmf1TLXhVafGk6+GjuLqNDv
+x2IrG0rVMNmAxnv0Zl4jTg/AlxxToNP3OLXrbUYbZ5fDjt4UOLK2OXspgRuLZ1dN
+pd/2NgsAAwYIANouVBiqlgyeOi74ktazcwSyxz7+xgEhYnEGOB8TE70RHQSHW/qd
+vO2s6dJdIsWi0Dquh4EjGW3sURvw3Q0mpMZTq/pIpeTSZx5mfbV8xppyz9VqMUBH
+NhVXRv4yk4OoM9sfQs9aUTMcQBzejrPnO4cWCmw+uPXwWxj4GTz9Dgo8Kx1X7t1m
+jGnpONUMZxX5ObPmDRDZcvl33l9j7mC8CsLlZGCX7aqIVPW0cdKYXQ4EFmyGTFc4
+oca+ck8X5Ar5h5ayx5/pQDs9zd8YdEIfw6H1hAwHnvLpPqW8wl0jjdr+IjvZbB4P
+sF2C0RAR8XRNBK3mbtlcwRWvYjdp4bSZ7kyISQQYEQIACQUCR1SGsgIbDAAKCRDJ
+LF/scBYcYnKDAJ9NS1MPppAX0CRbDC3QqcfjjkWDzgCfWEb3wKP15906jEy3qUAQ
+dfV4cuo=
+=PKNA
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    09A79E1E15A04694
-uid    Torsten Curdt (Code Signing Key) <tcurdt@vafer.org>
+pub    C9FBAA83A8753994
+uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
 
-sub    5FB8CE6F93DDEB23
+sub    AFF3E378166B1F0F
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-OGftXcgLz7E4WnOPNLnr
-=++aH
------END PGP PUBLIC KEY BLOCK-----
-
-pub    59A252FB1199D873
-uid    Tagir Valeev <lany@ngs.ru>
-
-sub    92BD2D0B5B21ABA2
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFUBG7QBCADRWXf0Fw05qRhM4cRnGKlOW1ecue1DCxHAtFwoqmAXyTCO+tI0
-MEW5SyXUkX6FsWLl6A2y+KgOs669ogzfQ0rnZMEt4HisRp8wpgk3GWR1/9aKYz/c
-ymy2N3BP9cz2fJ9+3PpBccUPL+ydFKpcnEnIwiQK+p9JjEWzJBlrdUc/UEJ0R+n/
-5r/+0+BHiTEMvjAF6/SwyntpTWpu7iEzLv/pfdCuhFKa4yn+9Ciwe3wGtSiue+dh
-tqKcd4YxED3oAswObBca3CC2HWWsUEH6EmfT1jUdfy1cq4X5x7AZ26oFYfG+odqW
-W5dcB+13VkJtJRzQTO/2HKtITJYC65a1jKt3ABEBAAG0GlRhZ2lyIFZhbGVldiA8
-bGFueUBuZ3MucnU+iQE5BBMBAgAjBQJVARu0AhsDBwsJCAcDAgEGFQgCCQoLBBYC
-AwECHgECF4AACgkQWaJS+xGZ2HNZJQf9ExetK9g1IbC/4L5qGhVzfyNik7m9DJ/m
-/fHibCK6pnAP7wHl3QStpcGfWwTDTnY079tdZKnZFk8OOtendA0WWdS/9OO1DZ8u
-kzI3PusfDOsIl/9U35dTgfQmFs5Nxi3/xYBphsNrzafEW+reUImADxleCxHhBGM3
-U8zAgnBGVQO+oBGQ/XLQ2xpGEW3lxytDgx90eCryFKhlqvE0Gv59ofHTcNjEkDcg
-9ki+dx5B25jpcMD7VzCgSaETs031gDlp7jdiEgJa6ot7o+chhcUlD/1UMZnHgT8h
-806xh4+ddiHD6WIXAwiFxsOhJO7o3Ovv4g9eg3VOW6kp6zjhfxrddrkBDQRVARu0
-AQgA2wgu5T1wf8QgQv46nAhpyv/Lf/osb6iTxIoMciUXpxKm6xKxYzov5EZxmC8I
-NHRLQQSJ3jjLLzAUy+hhKWxccs3hKof+ukshzgIPwN0ItatoppFmuG2rM1ZKxjES
-CqjufXE7r5yxTXtUkCuemQY8egDuihmVoatzTL+uWRNcf74sqqHyeI70NqnjqksW
-t2C+7IpurUHp9oB/YkxHK+rLb5+7B9UZNzsMRRQW3AaDsWeIMXTOX7esUbW532Qf
-xRbP4bALAVPqqFWCWA6a0mDDUJJg14OxC8MHhhMk2cyd4xJ0zoKQRxGEunb6XP3T
-7BHQr9r1AETU0+5sBpEHa5BHhQARAQABiQEfBBgBAgAJBQJVARu0AhsMAAoJEFmi
-UvsRmdhza4kIAMccH8GZzjxh7XGXpPqds0SIwJ2akhtr4k0WcRZy56rjGTTGhddR
-KkGeMtpY9CtVkodd0zGaZHcGOG0W+wuB5qPKktSRUOUoyR0ZC2xZcvRpuvhw2gwO
-JdRHGVteDFnz6Eiz+spJYq26usIPZXgxcuxBXjECuHV7OQkUQMDe1EbOOODODkzC
-auYvsfk9x3q9XUp7rQGa8Vi++NHBPhTDU4PReW6485pqJOJuE8QJznMvEHP355FK
-xFvFxw0TM9glLxeX36EjDtjs53Xzhw6h7HF2gj8rnaQfsDnJ8SPaRcJmbm1jKXIq
-+AalzNZ1m6hXe7XGD63v9CWCFMygkADQfkY=
-=P9c9
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9987B20C8F6A3064
-uid    mkruskal <mkruskal@google.com>
-
-sub    80CFA7C482552DC3
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-vyMjyB4YL48bYbjwFEar/jLCQJj/Dg==
-=Mtq5
------END PGP PUBLIC KEY BLOCK-----
-
-pub    13D979595E6D01E1
-uid    Maarten Mulders <mthmulders@apache.org>
-
-sub    8B794AD8CE1926C6
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-EFdqDmDrjH4tGHiSRQ==
-=uxEi
+mQENBFeWvEwBCAC7oSQ7XqcGDc6YL4KAGvDVZYigcJmv0y5hWT4wv9ABP4Jhzr1H
+NDmmGyWzhzTeMxwuZnc9vhxCQRwyxj3gGI5lYPEARswbi2fWk//78/3Wk+YMHJw3
+/1EO3VqvvDUt39gbaSqMCQNHctnFdb2QYZ7nRFTQeCqG/wyMdB05beqEnWEXzjeP
+FDF9y6gXkELn0lxUm2TKO8tU3h96TCuutDKJ0aE00lOeh/MbEaGHEbIU8kdfui6U
+znZ1X80EWbkCY8cKxEZHKD0aONSVHXwE6nETvFW9/9+K+sj/I7ytlyxwHsaQpi1H
+6aRGnq013VsIECrwkhmXBsLLXNjmhER+LkcDABEBAAG0NVRhdHUgU2Fsb3JhbnRh
+IChjb3d0b3duY29kZXIpIDx0YXR1LnNhbG9yYW50YUBpa2kuZmk+uQENBFeWvEwB
+CADfbjqRN1GvSf9VkjDDWBqX3hILiPx3DKPiSFmSsAoiLSEkP8gRDBDy6po/Oez9
+q+bgb9Sk+iGifJvbVNZr7+88LSxQECsrVL+ZgTAZ2LkqABQJ8XYh/dTO6BMJ5rSL
+H/YN6bO9V4NjYod67W5uYox+aCp6keE7ia7eBHck2wyqxikCqvVzmAduPCkkNSRu
+OwLkOguduXfwb7Cg1RnacMMEfDd9t+a6ytY/8JFu01G++VVxFHO3vs//RINrm0O4
+xKPkT1+Ocd4+h3DlhhRvRXvI+MKeM0ud0OpUVCBKCZqbFKTVgoRpsKC925ZRUSqb
+myBcIkqyYjzD1adaZdkq4PLFABEBAAGJASUEGAECAA8FAleWvEwCGwwFCQeEzgAA
+CgkQyfuqg6h1OZQ6swf/Vm0ndBcvdK0qCoubR/WOsynS1wdQ2rGKJC5oVsUN4YVC
+Zhg9OMhwMSO3EOBPdxtq4A8bSZp/8ZWmHLohE8QHD8AgaQBtRZyNkvMRiN157XGk
+PEBRWdHw6XAvx/lE31W+19qFRnAE8BbERE3gieJcG4CKWy5CyzXnjSM+znZvDQ8J
+7MfG+LxKbr7zUHQH9ZWsk8V9D+GXDgpuyZc4ct1tNDLcn6784FubcdrD3RLMiOAY
+SSgKSgoELRzB8zZds+WKFuiAYXZSdzCbjJJ2VqnJnQtYHN7Z5r3ySqbG7w3rRen+
+Ett6PX9Hrvc1MTy/UUdb3s08C0wD0x+ZzFzqUXKTZg==
+=Yytq
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    CB43338E060CF9FA
@@ -785,3253 +2584,6 @@
 =/Ri5
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    586654072EAD6677
-uid    Joel Orlina (Sonatype, Inc.) <jorlina@sonatype.com>
-
-sub    2E74CACB6918A897
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBE1VSkkRBACkCgvt26sMi+0X+EOJDMqdK0Sziy06k47LJf1jOg4tTZ2T9QtP
-OZ8fD+va/O5+q8Kna993jzcO5n0Nv+R/K3+MvUqSmdITshCIjBt3cC0n6FWndGyl
-jY7rOmzdNnvSkMGE3V2fQ18stkJRleqk3EuWwv+EwpxcYeVfCO+UCJGz5wCgtqnZ
-JYdRHcDkDYaIZ4eizpbV4d0D/3cgBdpcbSrwIGtft+lDxacaJrWpT5Jh5P0gLlYu
-+6PFz8ZIC4+/aOSi4S4mgZxk8dBL8ZBqLqcW9rc//CYKNtPq33sdf9vxcusMIXvS
-PBODjDpoOsTJwy51fgCEL14qnp0v14y9p7ejjN5+GipiNY/JHo9S9kTdVhMYqt6x
-6a6MA/40vMejIbZ4q3Ia63jbHPi348fLDq3Gp8Wos7Sh2HnLC+pRdC46qX/5wL4t
-Vzj78yW9FdH5yeeE6nQLOBWh7PnSfMt2wYHoarEnkkkycP7WLpRME7qsBYqkNUNa
-2EQZSy8DnGiayYDij1YPNUHI9kpK6H/e3puhmgNkzrZj26T85LQzSm9lbCBPcmxp
-bmEgKFNvbmF0eXBlLCBJbmMuKSA8am9ybGluYUBzb25hdHlwZS5jb20+iGAEExEC
-ACAFAk1VSkkCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBYZlQHLq1md1Cy
-AJ9Vwm/4tCSR2iaLU6fCV4lnJgDnrgCeIDEdpte6HmX4eIWPHHxULLLP4Zq5Ag0E
-TVVKWRAIAOsb3rg3GoeIBQtJdgRUfULCVNEguSJMESQv9xnKgEGeQX9ItVfdMLrv
-Lbf4ySyIJ1ShBR8k80Xk8M6C2XA+c14AVUrtPUHmseO53TY0n2VjZD5ms7TOY/cq
-+DheTBLzlxNsK85q0jZXOK2+Sliv9aRBIl/83c1iS5kBM76fzLWZqsiuqQsLUvEv
-oCmUI2WSzhJ3s4s3nCHHtq+sQkcaLap3FMH1IPozFFJWSlJSsIeE62AxR4XrfGs1
-y6YxA9AEhu/6QWA20T55loV9TT4geDLywxE68eu2rM867Bl2cfU6+tW4RW0Ssg2O
-Ymv/+dNe1YErRgKm5JAjWRxp0Jzc47sAAwUIAOgOfDKe+6VLQrVYXwUZ84ipBGgp
-/JwqajPzxa8YodPH0Cd8bfw236Qcd9R5MuyjNbi4M2RJ3pLlNGasICt2qloPNJqC
-miTcVGXXeaK3haG7Du6bXo7eaJl+pMXRoz3JTrdTPLHOhPgN7EeWtkAv/QbbONps
-nNcyiuvund1KX1JaoGj712xk7IrDO47eA7Vc+ply08owIlnjtO3XG0o4GbkZx7Eg
-iaG805jbRUz9Q4FHnIE3Ditmo4BrLsy6pG2kJyv0YkSM6pBSFpc/K85WDV4fEwPd
-AS3hl0rlThFuxgSHPH1Z7OqNdDnbAKp8xEKnAmb/3hx147fU+VoFd3qcudeISQQY
-EQIACQUCTVVKWQIbDAAKCRBYZlQHLq1md0BDAKCz+pK77m8VG8F4ZWyDthIjE4d/
-zACgsgdtDggyRGK8+BKm7HDnceh97sA=
-=7XCx
------END PGP PUBLIC KEY BLOCK-----
-
-pub    0F9FE62F88E938D8
-sub    BF6D15D3F1BF7BCF
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBGGNmd8BDADSpbdIfqzkUNAeYlP0nUw/HFU/v+/aydtjUioAi/KxYt2FOMi6
-gk1LOJzHBubv8bF79mlN6sXrnq2lV/MuqvN9DrTAQ4u4Dh0pgbLK6jbxDWPGrYIo
-ov24dU+1SXCInq/7X71M3RT3/1L1kTL5WNCqKkhxLNi0bwjyAHR+xOdhPqkeTrZK
-xZB4KvIzI3cIYoSw2tFn/iAlzzaUyQY+JkqBbcObbzyMt8ai7TdXKHM5mAiuMt8k
-MkfE/kZqTWHimPYrl1+c3kXqn5iTFfJIRklXqnXixz9qFYhvUqWS87fFRUJdPCz9
-Iw4/UrnJi4qzEN8vrEJpnDgfS5Ey+io9xcqd9P66dFbVHvMl4uTo4hLZVz8dkWSt
-CkCtAfntHAp4Zf+1vIZzbAgseO52D1mP7wO0QccgqdX0w5Jboc2kkM67VsWskRXL
-FO+c25gXdtZk26d0P3f1j3XuDm3pPWbgAk17HMyMpqla3xBQiLA7J2l41YwblV21
-uzJnqAoChPJhP6cAEQEAAbkBjQRhjZnfAQwA1bQfDtbglXMOgziqSdWAQ5jsNWuI
-cTAKcJ6Bg1d3a/B6sm2IvCJzae007hnGf66RgkiDBKpqsMjb5yXyGVL9lq+KHgPw
-3H8TMRiVKxXqr+Q2s9Y00PR5PgqccZLZuUrbBJwK73u3+vfhG4ugubQPnRd8sPwT
-X/OPXuuq25FuZb5T40Yh+ZjNstnBOEpWZ6bq8h2kMWm67zrYwKdBOoHRU6Nnu2fO
-8CuL42lQmkvpTIu4ttjbLyYZMYjHnO+OpK014H9B3DsRvgAQT7Qn5pgyxwF+AuiC
-qdRP+vFzO78gvDRpUEQp03ZsBK3LJVXqQY8Nk9zCPDz0T0/1zL5ZHFXdzpxVPxMI
-9cpugE0Qr45qh5hktz+cjE6/DYbGu8W/bqDRzXjxz9FUA5A/sv/hs+PZ0QVRFARR
-cooe/arzitxxEc1X59IBCQieH9xVzC6gEeI6jPgiWo+gEBItQt/1Uf4CXOgStTbp
-zM/GCJdB4VSQXehMNKI0zBCsEtBWgDPgAlwVABEBAAGJAbwEGAEKACYWIQSVEVGX
-xSJ8CIcpnQAPn+YviOk42AUCYY2Z3wIbDAUJA8JnAAAKCRAPn+YviOk42NADDACt
-BHrDFjhuffic4gBoMkgSHmG2xfWrSo/jo568hJdUvwUKlLix9o3iqmPGy0jLkaGZ
-4w/t3eFrTGdNPuJd6zQ1fDNm7alCnyUYzoxct4yOu7mmI107HPuxANGvmV9hfyH+
-UYJtNwM6XljTIhnKdYa6H5j9jlwMR7pw8Y9QACVozBMsaPQygjQhli4FhXA203g3
-lxidoGZUi/xrV4vO3Wlo+7VC8n9WJZrYq4jhlD6Ntdhbvf8bEb4L0cn0ybgREehE
-7THETI9Os8WQVGbU9sS1b4YdOXZEOS4WS8NQKRzLemo2YiUNIdI6QaRWCvJyZCfE
-eWWoEJoPMKZldSIhU5UMtTaM7f2n18sCn9rXBscSzeO6MlcyaUQnMI9Kai4C6+t+
-TrIhZrSJQQMrR9lF+zP/YJKvW2wJBw8jhJr04dgXt4G7VrmhS4/HbtmLjQsl6bb7
-y8VfvPmrEviA+o1KeRSeIsx+lPdI+IogX6iLvlBMPtILw/k1aqanI+aTZYFOORw=
-=NL3+
------END PGP PUBLIC KEY BLOCK-----
-
-pub    C727D053C4481CF5
-uid    TFLite Support <tflite-support-github-robot@google.com>
-
-sub    29E792953D515FC5
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=zvsL
------END PGP PUBLIC KEY BLOCK-----
-
-pub    0CC0B712FEE75827
-uid    AssertJ <assertj@assertj.github.io>
-
-sub    A9E4161147556D82
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF+EGtgBCAC/KXNQAl1rz3VBbqm6ssjzR+5Su1QWHI7oYDS+YHCLOaqfE3jO
-zQd+8iNgniVNtX2n7bt1hido5B94VmaqD+zjjSu2UV/eZoYhCOQ5NgvxIr7WZe9t
-DkhOppJoLqZJxK0EcTWMhOdJddIiXvK1KsC+pohW38+AXEamRKgKyFA/7F9G2c4U
-ZPB1+t5tujNn7RGq7H1N7ECV10Aou50DQBc0RaJmXVamWTUuQsWr/762yn3ZS/uf
-kFBZnXiQWJ5AL3pFGcmj4gQJhG6E5nmZsvUxVGSNftaK/fOX5Njv9EQUAsKYi8Iw
-1vf1Y/CgzM8FfWY7hHtk1QlCUq2CSg3ecNPFABEBAAG0I0Fzc2VydEogPGFzc2Vy
-dGpAYXNzZXJ0ai5naXRodWIuaW8+iQFUBBMBCAA+FiEEvmhRMq/SdA2QlfkEDMC3
-Ev7nWCcFAl+EGtgCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
-DMC3Ev7nWCdblAf/ce799ep4iw8iuAvCuFOXD8SgQoq93IW+3DhVSvitU5KUNOYP
-WeoqYBrVCg2ru8BRoyRBw94l8cN/nZPXQdotRsGxgN14zJDATsYZtJAG3Dx4RG5t
-5wlGt9mFevn+/iGy7fkI7F7C3/S8P1+u8VBx1dXqekYU6IGg17Kwu66rQ2t7Cdfb
-/aJaeWQk+Cu2JasNSX5v3mCBJzNuJ5ndIr0IrpxefxDwy/T1C9pHMHu7y0tpyLFZ
-+zY+xFzZrj4oW2AbO6EdJSqNIHu5B6vu4vMiCHYqi00+nkLhBFrZDJw3CJKhkmEg
-Jjo01Tq6pTNZ8qfeS7UbuENC4QZEPYn9sBkjT7kBDQRfhBrYAQgAxWYnUkMDpaaA
-4JD+4j4voJo8uDC+o+vV98zJI6Ifoj7FGKUpxJoosokIq/otELtD4zA0E5hYDSxQ
-C7bKKPloKUw1cKZiSzkQ7D4kadIWjWc8u1WDKuRW5y/K0j/isiygqH0gp5hkckul
-6svR145DDf8sKDlPK0T689Hrq604DPpoFy6ZfFUZpDNQQQANKK/wSIJcvN8EUyUt
-EP92j6/J3o0deDqy4MsLiyrN4wwHNp+S9PeKS9ptIYCD6O0h0obos6LJQGAU9hWy
-W0ExkbuvbuNG53U0Z3wKXeakkNMcUMSImF7Z/4NEtw6VXyltrQ1XDc/GZt3okXNG
-7CgxdFRudQARAQABiQE8BBgBCAAmFiEEvmhRMq/SdA2QlfkEDMC3Ev7nWCcFAl+E
-GtgCGwwFCQPCZwAACgkQDMC3Ev7nWCe3vQf+Or6z9TbStAdD5WNavPT9Bqlrb3kr
-13Hzb5y/Wg5HQuvDfnDmnMz+D5UlzbfEeUTEV0kS9JNegRI+8KhDZset+NuNZ0i9
-Oyq1nKRenlPS3NXR0sVsTuAhOWNHNPnLrSJnZw7iIdBehk6pTunWBEuv3ZTViK53
-K+aENoaC+ODfVAZWoH4TIsh37fzQ7ZHPibEd6AmC3Q7iaiPn7cEeRPKhMnxtBPIj
-bELkQZ+hoUCIC5Xyztnz0+eyU3SrtDV0HDbmmYIm3FuTmY3eNBc+YVKolRKXAzFP
-C9huWCZN1CvesEtUVkh7UJ9c5KCeuno0IAm24ivH8EDjFDqOeDInez2wxg==
-=+MWL
------END PGP PUBLIC KEY BLOCK-----
-
-pub    43203BE58F49479D
-uid    Viktor Klang <viktor.klang@gmail.com>
-
-sub    1364C5E2DF3E99C5
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-4g==
-=dPSa
------END PGP PUBLIC KEY BLOCK-----
-
-pub    873A8E86B4372146
-uid    Olivier Lamy <olamy@apache.org>
-
-sub    1AFEC329B615D06C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-875QwNruE4Qkt/W0Rhy/QRIZ
-=eBqU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    BFFC9B54721244AD
-sub    788E173C196BC673
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBFRRGVMBDADAQcmG+x0mHZwJ3uKgODjUZXkGRkuz7aP/qRmuQVn93tl8DmA1
-lgvXndvChUjzYt4DJnQhRsapAXEmP5/YYIkWOzuk9EpXGtqUieocylvNXP9eDF9y
-4mRbGbCUmz5W6Y/3w7wIsrz4kbCC5xij7cavCxxSGGg1IsyDHYkOMpcQyZH41vXJ
-IPMyDvkJUON2/YA+xPph4XkmNA+hJZ1fEa+06Cd5P4j8GeTnpibkkgzqzjuiUlo1
-PcXMXUzkGnf5IwMQOdDYbmDC0K+QUKEPheWY6NsmTdZTuyEdD7BunWA++mUlrqZW
-n81HMNijG9fQbipvuGiOn7OfmVF1eqfH+NtP9csBCjn84ZMUHHArzsWgb9LWpoki
-+vQyc2K+egdykeDJG3hFZ0Ztbz1YPQAUy8BN3r/OmKuSwJ33cleugxyDe123kyUX
-KhBdGEY9pTZ8dbBKn6PfA51XvuWQSVPJRjG3bPFphLPDYNJr/MUuYqo3TSTSp1O9
-EGUz6yVG/S01tJ0AEQEAAbkBjQRUURlTAQwA5QjPD3Y6kiGacT7lXdhYYN1m0iHV
-ddk6NpERbQn7NAncLI8yx2kWCtF2bBYujv/plSfMKZmKSR2VUx3NXwmG4QD0Wr0G
-AjhS81jrmAjEEs6Kf0fvihJn5Z5fJAyDB0BMYARhCPtQBmZ5g/mLQWqPEj00kaXc
-vZyPaMwOvkFpNowItAdj+oxt9v2DS0zYSNQoRtF8WkX8GeU5j5yL8l3+dgu9CKlS
-CM+DqnbpMDiXDdDpc56Ca5jSuI85+c0TYo6ZIvn/34nmWMD5dIMQ2504Qr+Cuc9g
-u3zIJL9Op5TPpDKLMhiF+Pdes51unoFMnuLKMmbPWtIAIXkphd1QkVTnhr/yiqh6
-gGyGD3520FLTqR+Aq44CUUINWN2nBTbgrAaE42B0PRGVjtmTqoYJBziig0Fbqt+m
-BPwvT5+qRlX9fttcV4Nkhgan7JNH2B7xL07mWXAOifoGmkAeCH5y5TKvxJOCGTw0
-17NN05RCsQTHsL+0OhjU32hvhRGrbQTNq17nABEBAAGJAaUEGAECAA8CGwwFAlRR
-G/8FCQHhNh4ACgkQv/ybVHISRK1gaAv+Lg3GF1LFbHQlT0DiF8cAJ7f0VTiEgpKR
-SHh1SJ9mwPJYM+60HNHr2/i6+8aMML6VVy8goOvYzSW9BPgTY7wPF5HJ6k09kzDP
-+R/tG74XjrZNFwZfRQ9rAeAlMVYXpPcUfo2FpM8tvR8HKAvJJNZfPGEtVkIJnJSz
-pZcqLX7ScOdKyWu+byo7+UoINF0vWvHorWHps0iMNDtrCL1QiNWxGMYH0+vK+a0C
-zGM/C2JllP8hzLc8anJjjtcF2xIZGL/roQnal6g2+OlKmtXSgdDwGOzEFPIjMHU2
-CvsjRPX2RbdzKOjIo/4ybjKtbvrbiXPfUORyb/aQ8PHHAZXaQ6yU1LRTCI+qA+gu
-sFCtKpk7RvXQdo6sIcrpqvLfAAWL7SB6zV0rtIFqPHh09NlLJ3LIl+2UK43Sa7gT
-j88XfFZYef0bm+IZjSGmEaZVEiXHB79AXyD3DZDhHX8fmcJIvvaZt+6V34ZOaKIG
-RATW8oAGjGserAKr1rvL3gGRF8LiRmBx
-=oggK
------END PGP PUBLIC KEY BLOCK-----
-
-pub    F800DD0933ECF7F7
-sub    592C39141EB02A78
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQMuBEvQhhQRCADQ2MH2FpQD7pbCTDJ4uvPSeaOz0IUhkX9bK4sKvIISx8MbHhR4
-k4sXi+vVkLngWCMUV4nB4WcCibk2S184SzL0TstTDrudxe4eJFVbmZw0GrgASugQ
-aD+8daVhMgQZEjvEB7kjaYzMyljzVRE/o30AaizHPMVytZQpIL7GTsaBcGtxLkyq
-JG+SF+fN3WAKiMyKCUTaji1owY5SyZIbPBBHqcIQVdtCFRPXhLDNnGHUz/ubI4Fn
-U5sN9gEe7raXQfvZzwS6fW2SaxhxMXDNVDEipY7okuRKQ0wPWqcanh9dri8qoTfI
-7MOqfWWKL3NF1hnjuutyGTTKCllyTWEW4MfjAQCJBTUh43abqyHej9Dzcc2lSgLn
-xeN5iM48tYZRv+aYxQf/b9rWigbReKL7iYmCTqd+hLfh0YDmaJbZ8ZZM4p/YZ5tL
-NdkNJR5TiWwH9ub0BvXYOtYUwclOaaD85CKNN8IU+A/YcrWP2O8fBQw5lqARuGx+
-TjG7c+WRVn+fLrTzrzbUYh+/Jg5UYCbDYh6H2kLKnPVQPzSjDScJNtevFnX+IRjT
-7woB/WHlrfvowZGO1kclypZZS6nDiPYhEk1isEU+nD7OvvM1fQN1rdl0QhkLUh2w
-qKiM3xvY42LGicnJcxyMSODkYlG6J6OE2sFDBJ1axa90+S8Jze1fBlbQVb7OF6ma
-31mhOedb6xiqJ17/5Kx9gPEUpVMpkrDUVToIv18c6wf+J2TJ1sdMPqUsiuKHDQq1
-elTxtfq5ELQoNlnuK+mRrsSMfa1I6jE7QbZkCcoTNnD5ikOVmkHJFQlEZsmaKCrD
-oUpEyELdzFy1ghfGDPbvv1a5AoGVsR+sj39XNckBgZS+25vZupBxWvTd8Fj/KY5l
-a1aQlPUyMgqmo7rdE3WEzv7v11xBy6wQMAoGu6lp9tnaAE7sPEy/UHuYSexCO3Ar
-83sZ9o9ZQa+z33QU5Z0guNz+efCkFfG4nqjHjZ8ZY5VvWlw0W2gxNqzNCeQR7m14
-C4J2TNNn/F2nGAKEpKEgp8IjpEXYZ6kF9xoSkJ07bjujvf5vtvAm10h+ZEumKSiS
-mbkCDQRL0IYUEAgA7Ci1jY5JdrLs7pKjhbqP1lkZKDRn+0fDgix9y2JP2O0lJ6Am
-SAVUE6Mi+izqV97q3vMmOkIuDFLoBP79/YOaDlMWAj9QelNWwz30yT6LB5Wgw0c/
-Tpi5lQD5K75L84u2vAFjoOwvnLx3cKjC7TG2h7zxt9EHEtLFAFP2JBtsMvcmpFPP
-Ucpv0+/RFLhRV6JPxEUKiVbz52pgBLSa83vtZI4d6CDu/W3QXvCw7uYoTWx7e0+K
-rrZj3LE7KUzEa/Vazsn6Nwhi7VL0irNOZJGALdhrxLA8iGnPYDys78vPBWB3k4VQ
-G7rgvdVXiAldMNtoy7sNuhtI8Cicgl0JG/6flwADBQf+O8kWSrda5ezDK7vWAhBh
-r3tEMIE08eL/HPErE3DOzud8oyV8B7Z89ZOjSqzn/6EQdnEGnVRr/isOJcmgAXQQ
-RpJfFQ4dnpEeestJ5y5hzrtbMvfZ/Wms3WFgjgfYl5+TAbSF3Gz9VNn5AmaeA18i
-d8qzNVQ/e8J9zXfLV62qRLzbAS74K6rzGpYaZEWFAid1KLTu0S+I/ZuvQfZ83jyq
-oenwS0iYawM824w5oCDN/+8cDzLcHipN+B6g6S+X9m8s5E3RZGVKqUjd+fTRg0LY
-JkkasJwQa+20AadpCE0RZtR82jrbyLfNY2FFJT3TKYnaVhYcjpPBqffevhwSRIEs
-KYhnBBgRCAAPBQJL0IYUAhsMBQkDwmcAAAoJEPgA3Qkz7Pf3m+4A/RghXcZwWrZB
-/vvvAfhkYQeQJjPmYluGNebJ4wPi5ZI8AQCBjv2b6yDTWPenmPNeSB88HWjSL8/A
-mimEzF5VTg7GrQ==
-=Q4rB
------END PGP PUBLIC KEY BLOCK-----
-
-pub    4896F7312A5ACE4D
-uid    Chengyuan Zhang <chengyuanzhang@google.com>
-
-sub    3EA98BD451E4B457
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF36fYEBCADU+1b8TH2AhJuJXebg5D3UbR9rk8/9kEfiF7ifbb3nCB9tnF5M
-7NnNocEdAq3XezNuSj9LtEpWUu6P4JdpXcfZiQO6wrobzSJRUWDc7X8D8NyhGpd8
-/7EMbAHH8MfMrwb1+00wdCeDXRpDtH8e+9I/mvdkkBgCrJwG2IG5FMSdQkMa44cs
-asquM705q5349n38F6zOFbS2CHtRw+dsGym1xHWX96E/kuAMIh0rlAK1vIh5hlmD
-2d1VQyx1IDQuAMR7YvByzpXvhwGm8neMaPgKvi3EHoySE8goFfo3UUotZBBv8h59
-h56lu4YfV0EOT3rUESOes2bZiRdLrnFPw9ebABEBAAG0K0NoZW5neXVhbiBaaGFu
-ZyA8Y2hlbmd5dWFuemhhbmdAZ29vZ2xlLmNvbT6JAU4EEwEIADgWIQTIiLmVWBXq
-g7SFMXhIlvcxKlrOTQUCXfp9gQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK
-CRBIlvcxKlrOTZYeB/9Gb0MmFCMawEHvB5RbLvkQggZ3a5Ac7WCA4qy4p6B2r/2N
-7S4soaAB0iU3iutF1KzR4EaZod7C/DOJgjY7ZJ/ufoU+3KyzdoEr7b9QZktD8hUm
-vPS/hygpU6eY5gfyelFPtJU4+gTNAvls0/9oTq158OVgh6Kd3lmGpktLe/OFcXKE
-nRZC2+Vv7AJx/PboNko7uYpMml1cHDfi6cqRQv2L7DKvCGXnDseLi2tqfzWW6lYI
-XFJHmzWVk28SjUUFygfPN49kEkzSkQ94I0veC9Jxb8YqPkGD9r1gU2x6O8+4NsVC
-Iv2GnefwoRjDMgVvh4GzRhfGKuWM1+7OvjoC9QpnuQENBF36fYEBCADB55Q7spxH
-PFABiTlWY7iWlZ6KIJYdRm+yZGrWALYq05bL+UGfO1quXeSPoZapkNOp92RP3FSn
-xJ3S2GFXlv8AqjEuB3rUcWq+0g0f/cPq/MOYBPT9RgzYU+2BSmtnOoO9jEmsDBPA
-A8g11TIb/YglHmekEw7O3t76iebol3QYExHZ06IihKbH7kMQlgOGeWIPR1niJbvb
-E+VfFRhNzl2xjIMEcg8cu3nCK7xz4SwPXJTZJQjjJrUoenl6WFtSLVzzL9KQO0vH
-yzRv9cEUUU8npWz0NvNMA6weXYVGS9ZbjaAMgZ04PAMpEuiiYmsENFpP4F3S/yc6
-8o0dFeE3ZqUPABEBAAGJATYEGAEIACAWIQTIiLmVWBXqg7SFMXhIlvcxKlrOTQUC
-Xfp9gQIbDAAKCRBIlvcxKlrOTVN0CADGnC+XyF5FORZClBFtjzDI5WyRhqK0eBv5
-YDfCiBnH+vCrpRzks6ylsoHeuRkLBMyyN/GDyi3vLa/4zb65ekZzsDWROR5zzpiB
-hI5sKBekS3XLEd81cYb8mDVFqn4cgrATUeGz0UpHY0wm5bVel3FGpwY9NpZKHfhQ
-9UATNm4OJcJywPNNCPMjFUyj/XrXwqJDDsPafVewJ2qOziflSXt75TEos6xmi0YB
-zeYL7RbX07QsknYF+31TjsqbAgZsxgRKeexe7DsSL97BvSaUyB8X7Ghxw2UwE+9O
-w5dkCGlkxSnKE7WTKi1is1iziB4eYHLMW1BKVazIeudpCfyKmmhz
-=Zhff
------END PGP PUBLIC KEY BLOCK-----
-
-pub    29579F18FA8FD93B
-sub    9DF7F2349731D55B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFYFiMABCADYpblWssqGxbjTwsyroPh48BwdSKl59zbFKoEHDw87NeWq7fik
-h95RkbdeWsQSvduXWgQZsUDq9cLOkuS/ChAMkAAd3MPp1NMdFmAqS7BX5wU5s5I7
-XD+/p51SWLMvgrLxoenmoE04EuQqQiXd4DbU+HGPseiNx+mN0cxPssaZMBBsmi2r
-RjwcQrFTaC1iffzh8FKLQvoTDzci//b5bWcxCLbsY9dYcUaDCbBAkL8HzyZUKNE9
-XwXh/Rq8wDakI/VEg/905a9c4xq6Rss6Yn5E4V2SAo2+B3hYmvHFsefaM9kkqvXk
-MQ6zjx83LAtzavOzmthjhhPIgCAfoQ5Q5oDzABEBAAG5AQ0EVgWIwAEIAJ29KWGH
-aEt7gXV8EweJkrYd02nwjc1LyjUT2TRwEzZ9N9qUiVqfpkgnZn4mpHCToxFoqkHa
-iv/QDfj7cp8jbZJa2wjaUkDbH2pZqLBGJ0sUUBZ1KNPM2uhhWRzAnmF/bIo3+Yfl
-hGINLNqoevkYoo9cdelP3hepef4+PUuPmKmeo856uknmaWQ89LPwLlV7oj6wiqMY
-p22sHqTGAgXeR/fSLMK7d0vSPm+57LZed5ECoRMeqYFUwSMV64RjTMkKPsvFBGvR
-hppJ+uWQiMjFFuFq2DFeNBVtueHSdgCHx1TP9i+x+7JmYsmFFmRwnEdbxO3THFXa
-gFQGr4ima+oOjLcAEQEAAYkBHwQYAQIACQUCVgWIwAIbDAAKCRApV58Y+o/ZO+ZZ
-CACL1DlaVyRNjNxzC+30X6xGykPwCdwMRF3CRjoeIicss2pBJRaIdTYFpg3bCZKJ
-J5KDC6s+03zmd3ddnKEq1fEfRcoLZ9PNBYF3IESHnNPlR68RL2cjMgq6segbhOxa
-v13ZcOIOnyrWzgbVw0ZgN8P3vCllFtifwvuF50vTshIRY11G8Gluu+GZ7tfSkPww
-Eo+pRd8scdol62aUUo6a71rDOMg2XPULz0l2hxKWfeUsksT5EY03seZd3CYqOacL
-R+jaHyOc5Nh6R1MzcRz65YTwzVbKplXtZjOghMh+rS4eDIjEKlo456M4spKFBbTf
-Ub+QS9kCkBU8csUzwF0nk/oP
-=SZ35
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2C7B12F2A511E325
-sub    10DA72CD7FBFA159
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE+ZO+EBCAC3fZOOuYKthr0GcUge0PH2bh18sbM9XUmPKQz/W15l1NA/2ARS
-2gUXM0R+SunMlun9KsqjnojJ2ObVPvbm1Hg/66JSRgR3JWfIpSlJxLicpfu8rCfN
-bOjh4v9ZipD+px8w3o/RNrnZH/KRsoJg9yER6pf+pUZqTJfdg5lXezc1WF+/1qVo
-ypldMGfrkfLsPrUZTT689ubbig978e7eYmJEqldtaIwaAzHQnB70wIJyg/rEwFUM
-ldsvs6t6czSuJ4zPMvmh8TMpTg9e6+DMktPl1CWRONl8RPpgYMIC96gb4OnfDDjk
-Ex6clSCwgbDwdeAyOjjR6pVq+pCNTo1Pcj5jABEBAAG5AQ0ET5k74QEIALaxogmJ
-1t7arw82krV7ILlcOu6aLuuXTuy03K1/jU73oyWfUqwvPSbH4igcLb8kt1/6ogfk
-u0T9tTx+0mDsvqK8A8NZ2nDTXok3T58UAg0FTXlqUqZmy5QPtG+it2j3/xGgip3V
-5p0Ml1TqEl2SfW6gHtLptDUWzuzPi9SgK1ZFlueprPg7xwHmWhp0gwx0KSSOYWlK
-oEllj/1aDxFNcdKogWcGN5aJEsETCEguBP7olL75u6732wc3zola4zTy5bFT4kEY
-Dk30Du3VGQJrdsqlibdQpZYm8uH4AVXDmFMdEAjIs/DGRrUgde/oUqwtgm9U+p9M
-qcbmMoeLFdi7ajEAEQEAAYkBHwQYAQIACQUCT5k74QIbDAAKCRAsexLypRHjJV9F
-CACkvuGQCqxhvY21n800w27vc85F4Fdd7LjA/l3Bs9dA5HZbk1AV4/MFpadvPX1z
-ZuBOPYqbDSvnXGfoDgE41L29S5Yeg+mx89UDO6JcQQnlNn3k5mGCgR/BmGPSWc3w
-FzTEIXDYoj4/p7Wanj8vxBQOLmRzO1nu75dnOwgXAwKtTTXhHM6NCrxuwFrekKGj
-FZm7wNeBCmnTc65hMvWqZGoNQSr8M1yJ2AryBzGvWaonDklHCOUAmLuU7n7yBOxK
-tyoYdhMdRYjmhAPueyzK7ejbEil6wfCTWGyOaahNa8SV2Z2Lcd2aTwABHy4z3YtQ
-DpFob4bKD5ohhQunm2EOXlWy
-=Y1SU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1F7A8F87B9D8F501
-sub    7D1BE4480B61E2A7
-sub    C2148900BCD3C2AF
-sub    CFF46EE3C17E53E9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-Lx/KSjFhpjYYPWtx15xNpdqJ8g==
-=Le9W
------END PGP PUBLIC KEY BLOCK-----
-
-pub    96FB9DB219F3338D
-uid    Trustin Heuiseung Lee <trustin.lee@databricks.com>
-uid    Trustin Heuiseung Lee <trustin@linecorp.com>
-uid    Trustin Heuiseung Lee <t@motd.kr>
-uid    Trustin Heuiseung Lee <tlee@redhat.com>
-uid    Trustin Heuiseung Lee <trustin@gleamynode.net>
-uid    Trustin Heuiseung Lee <trustin@gmail.com>
-
-sub    684EB33FB007E676
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQSuBEwVyy4RDAC9hprQuF4fCPCYdtMlb0Mfb+6G2TqerT1MebLm8/KHCRnPbFLg
-PwGgcyynLX5R2nXUb6oBZQByDN/Dal0UMuC19KeZX83LTcFE9vr516BMXLXXKmM9
-Hz5kygsu1iwP4oqow8U+ih16rxdYDmM3KUGhPqXYExpYH777NxaxxCyPJn7Mz/Lg
-QdPkO0awyl86sex6THr0fYJqR11XW2BkbK6Pfs5ubfxrMZxy1JujUw0UmzzEkQqU
-1+lncxecrevglH1R2WdIHx2sjkHQtwqT2rcsk9gJ8ISL4gKJ7LEYfLooKRwro54x
-WVi8Eu/XZ7OHfQfgF4+JDofIrd7zN0/Dia0qKpkZWJTrYhxj6ouvYqMPr7+XEBub
-eHFU6S7Zzo62zkm4dv6bAhvT/M1WWKih+dOvYJ6+qhBt9RsHJdUePAVYLOjTcvl1
-Dn7YKRczBpeiGQTGaquSkWh3HPCw9Eom5wPs/J1L5eeLdKoqyGUQvdGMJxuFLpSM
-BVN7Q1Voom8XBt8BALG8oGuCkFZUN6ukJQn1SWXGeBr4IUbFU9gnfZUVeLMpDACS
-erCIYBhSRHK2XaHWxPppw0yMm9e/eO6WWpVBZLd/cbxtxwJUandSfOhKn5bGRsGs
-phhWXjmT4w5DF3cngfe9aMSAV6xTwfnzJ5nSBwejU/UYCiKTnGVqVkMV1N546ZoO
-XCEJLRK8GeHzBXf4bvPW+4DVhfx/LBz3h8VJ0vy/cjkEqVWPCvb05WqZ7bhnk/kc
-N5F9NzHzCnze3fMfOtUnLgPCaAwWN3S9fJpKumhwAXdkp7qZv6CuvKsXsETmAPYe
-j9GYWiUpbL4bm4C+QEC18F9VkDs5BA3PhukNWutFcYJuRoJ6gYyUaA1PSqvcTaE4
-RM7Jjn3/fbMC+PQTNOYdixN5u+ASAsgjEDDaQJYj0Nzm8hy4uDbFH8TIqU/RLs6w
-pK8oLonItiu2UQWPnExvIN+iYGCfeMWDT8Lcx9cDxpshVZTEyjImPMlQBD3dE9Ov
-Fhh1nVjAZhyVvPbfshtBC+FphC4///lHumxAVJqu5oWdVj0cTlEqEAlOMNHBzJwM
-AIwXYkRklTogkJUCSZb8g1FB+fn6DJCu7CB4Fjd596IJn46fkCZKyxQ+L16KNl6Q
-g+oEhzsGWrpiHcBDZk7Oo5II4Ajjs2IiNhEkbUKbKn1aF3fdnpByOR07Qs0fKYCD
-xuUIgoW9aLtkJiXnQv9ddgpOvNpiqyBVs9dw4c9wWJon6q87dSRv3ZnvR+x64A0I
-82gtiE/gWnv9T7n1ri/P8J0/wMN9G4mL0bs7wTSSyd/rM2dDruYysYQ+CtMD8oIl
-VhV53qEB+5/IGb24OVileRPCVW7jGSdfWLbrV93C7GOh7gLsm+M7sZYqDTLgGkq/
-JNZSiVocTCxnZbi788kT+S6LsDdjYzGwqTqrdH/kOFToxMaen2mG37vB6BjA80t5
-lg79qALXIOKWPDI3UJ9LMavq8MXILghSbgJD78QwmPEROZh+ywN11cDw6yc1HSFw
-NrSZZuKPnj01amo5/Z2N9VMw/DWCYVA0HkPGnnxLsyboIA4tE2JR/QdNuy0CGrmn
-8LQyVHJ1c3RpbiBIZXVpc2V1bmcgTGVlIDx0cnVzdGluLmxlZUBkYXRhYnJpY2tz
-LmNvbT6IkAQTEQgAOBYhBIhY1FvpsnaAIxgVW5b7nbIZ8zONBQJgXoAqAhsDBQsJ
-CAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEJb7nbIZ8zON6NwA/1oYHd9ChpQGGO/D
-lKwqijmomSpy5eEz/U8iJeq1eF8JAP9nOLHArkcDUvLqXxwPyY3SD2GE19khrbRD
-w25IWil3qLQsVHJ1c3RpbiBIZXVpc2V1bmcgTGVlIDx0cnVzdGluQGxpbmVjb3Jw
-LmNvbT6IkAQTEQgAOBYhBIhY1FvpsnaAIxgVW5b7nbIZ8zONBQJan8rAAhsDBQsJ
-CAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEJb7nbIZ8zONyTkA/3PTaqRvtsm6iKSU
-FD2qe6805NtersLkzPJkChAHCp7SAP0VOOoX8tDOc7f4kkBDTnSwIYdLexqaWuwg
-7HUowhiSLrQhVHJ1c3RpbiBIZXVpc2V1bmcgTGVlIDx0QG1vdGQua3I+iJAEExEI
-ADgWIQSIWNRb6bJ2gCMYFVuW+52yGfMzjQUCWp/KjwIbAwULCQgHAgYVCgkICwIE
-FgIDAQIeAQIXgAAKCRCW+52yGfMzjUO7AP9nd0SjT5u7bVzZ7WIDNhKc3ux2nOv/
-ixSKtENArECA0wD8C9b7o0lW0bODrhoPWyi2GLhcy3M5LD5sDTZ9LmTugc60J1Ry
-dXN0aW4gSGV1aXNldW5nIExlZSA8dGxlZUByZWRoYXQuY29tPoh6BBMRCAAiBQJM
-FcvwAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCW+52yGfMzjURTAP41
-zJKS3mNA0J2q0n/pAkqMd7EZ4SDGp/BG0lyKZvZyEAD/RZmkvpGWHemaNTRpuhed
-rHv7M0LnjMftrIVSpoyDynq0LlRydXN0aW4gSGV1aXNldW5nIExlZSA8dHJ1c3Rp
-bkBnbGVhbXlub2RlLm5ldD6IegQTEQgAIgUCTBXLywIbAwYLCQgHAwIGFQgCCQoL
-BBYCAwECHgECF4AACgkQlvudshnzM42ERwD6A6ge7K7+/QokKj/wFdTzgxOfocpV
-ttSqLxEsmhG04WoA/Rga2VZAQ6gHxgcCIx4Ot5XJJ1S/U6duv+jlYf1OT9HjtClU
-cnVzdGluIEhldWlzZXVuZyBMZWUgPHRydXN0aW5AZ21haWwuY29tPoh6BBMRCAAi
-BQJMFcsuAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCW+52yGfMzjU1P
-AQCAhboUjDQx18iRbYdtpgeMZa2GP0Go25Ms/TsyKOx/dwD/YmAwU8c6cO1qf1vM
-UgqdOMpCjxTo+qUcbU8nIwrisJ65Aw0ETBXLLhAMAP43xB9VDluJa3m0EBTwOswy
-MgHbCJL6iK/MwvBGrTbwdu93jdhNBfjSUsEExMV3YsyIK/0oBDf1s33o6y51OZFP
-UC/NrUmx+QycHcSL8D75+D4M7324T6q3dqNpg0+jFTDixHi3FmNpj8NY+7iIS+Wr
-Q1qkBCfBbKkGrUe6lxgXksenvRoDQFrBndxlZ4JLKNdmY8UL8hhFDVO2ekD50iKL
-cXGTgRaFN3NlU2BLunC+ja0iGCnTVclvAznhmtw4QL7S9aqQIo00LhZlxfZyEQi4
-ljpSrB6aX1eu6VFCrsdldA3vJ31sCPhykrJhoEph6A92a0ewW94+Eun+m7YSVoU5
-noZj5IQlQ1YZ9acQN+7blEAqUBoresm6XJMo/ago2VooTt3bUQlKyoNJhZKfQBwX
-rQr60oskczUkVTMxy2KBTKqMV4BGWEdrkPrrs1wFXUXq8adNUHJ30X3y00Iy58VU
-aRZqLx/J9n+40LsERil+9YoajUMaxa9Xnl1eATq0kwADBQwAkJG2ODt7UZPzcPms
-4eE3az26d+jSPDqNnxgZPYxeW2pidwpva7homwLdIbMT6D52WU/DC+N9LNtuo/2h
-35hnHJ7fasEhXax+ArUzWBkdi61PxP31vM78fV5h7xxFJ2JPv4t6Wmqt2i+d9GCQ
-911lHGwtwV/iAVk4FY3i4f+bs0dkJs+yNhUWsVRzSd87cfvxij2jB7qtIB5aPWdc
-qRsZtSd5T51NtGmGtIrhVr988svcecOrdATU9qBBDTPDW5AacFIWu537nultWrot
-x6S7Wwm7mU8KnOP14b7BVB4rMiQJclSYjduBe+aWHNSxOJeZmAq0JBLdgIt+nerQ
-FeMr57q0q0qqooPIVvrVlxFxzXHZGISIt/JsrOUPJFkI95T7+2huRzNUHFmfHE3A
-eHrcLTsKRMe5nx4OYw/FDgk+qgFfUtUpu6RqH28WTlGtPW/6cZIkCyzc2wtAlpkp
-iiUdIA933CtSpEQ/KiDOj+gKsdtaZb9tiBkhke+OSd7JtoThiGEEGBEIAAkFAkwV
-yy4CGwwACgkQlvudshnzM41tWAD/Qq8DwaDw114pXn00eXN7Qck0v5F2xGpW5ktW
-CO7Aci0A/1mTmMrlJszx6YZuTkJHvAVGLVGR2/uo53VEYjcEN7vR
-=PCTs
------END PGP PUBLIC KEY BLOCK-----
-
-pub    86FDC7E2A11262CB
-sub    59BA7BFEAD3D7F94
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE2kzuwBCACYV+G9yxNkSjAKSji0B5ipMGM74JAL1Ogtcu+993pLHHYsdXri
-WWXi37x9PLjeHxw63mN26SFyrbMJ4A8erLB03PDjw0DEzAwiu9P2vSvL/RFxGBbk
-cM0BTNXNR1rk8DpIzvXtejp8IHtD1qcDLTlJ8D0W3USebShDPo6NmMxTNuH0u99B
-WHCMAdSa34wsg0ZpffwQmRxeA+ebrf2ydKupGkeZsKjkLlaXNkTVp1ghn5ts/lvg
-KeHv1SJivWKCRmFlbPhBK4+mxSUSOPdoBNAfxA51QzZoPizSk0VbRz3YufYRVLFy
-9vqPSorDmYJhCvn3f6+A38FS/j8VE+8obQ2rABEBAAG5AQ0ETaTO7AEIALN4amR3
-pf/FN8oMFa9eAc44ognamG31ea1lkqIiPssiJLC9J2z9mShkrECbsBj4o+HxeN/3
-rwW2hQFAm8cAbitujASpPs46slp7Ylx6cfmrNqh3tOkg9BW/5izPwjXAuULovMpG
-PVf30eeDpf6huwRqyc9uYQSS6Jn9KCLi9ULxIeQOZi3UPHyMOCbnehR5aQQk70tI
-jbNytmFKC+DXFrhDiBjlRQruATgtuYYKMWUBO65b/SyvLG7zPGmHXmCSfg2qCTQI
-8xKN6wxgQY6x0PN9BeXa1du3497qYGhaHrsxnW/nM6rcQO2hKoOlY/GmicB5oK40
-MMVfji8aN/EYTS0AEQEAAYkBHwQYAQIACQUCTaTO7AIbDAAKCRCG/cfioRJiy8Qw
-B/9UbKogRzDhPYPeBlnchOR6gF69B3EFP/bvE2+hY5nIZLMZiVFtFCuWj65myN8x
-z0w29pKbHLLiAtVtx29Cvc8X/8bGmEn3xbymT2X4znuN/IeecK6afsw7ij1535a6
-KA3mh640noEird9/ajUOysS8MKFg4kQ54W5bG/67sjYAEkl6ns1sHIzaf08Ty+UZ
-TfNQGBZQGyTqNP6SUqcTIcTvpbN6A8vPeO0SVO7IHuNGGPJAm7XKIkQxuzbMfxok
-Y5uLl/wm6bi0gtm4QB2gjQzdzdVGrXZzP+8vL71Vdr+z//wiwafzySPLJio7LxYk
-SOg5cWH752laIzudmSBBw2Lk
-=HHpt
------END PGP PUBLIC KEY BLOCK-----
-
-pub    218FA0F6A941A037
-sub    9FF24F51B06DCC19
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFjDR2UBCADDfzBacBg664xalF55ghVkhxxwLaTNUdvTJ9o0IH+cGTRj7EYr
-7QvLVa68PKigj0q7SVVwhPT7fzBLDosGjHef0UWap10ynqACBoAYSFocT9m3Www1
-nW4AGT/5chvzYfNPpN7YZ2Hkk6DUpmSzS83+6nIYdCAgrcZ5XS0Vg40vUL34TJPy
-IxJinqWxt4A14ZryqSKWbWxRcocmpCAeRLMLNxbQq5rKjjxFksTYR0Sj+t47DQsB
-rqFmnPnZFExP+Q/KG1dKQ4UE/LyvzoCzCqynuMg7gIlMuRBzDv8QB2f6DgViAHdC
-vS6m2YCTGURCQufBdJOGuGplL1uxqoEW54G3ABEBAAG5AQ0EWMNHZQEIALwz8m2S
-GdANvkFLVqXdvmOZ1RjrbrzrIP/iOjs1Bo+sD94L2qUagd+/cKjvGR2cFP3g7Zci
-YBAZVCWZpgmXTL4tL3PSZg3NVvkuXut3MU+23ksjlkl5Lfzlq0Rmidu6I1TgBsXc
-CyD8Yilr3QKtQkD0l94uXX9+Ex2PuBO92qFpNqib567wSt8druTewYm270WlAVSc
-YQ3rJzdmzJD4WT+PyKm15NSLID/wzIHxbgloe1SVs8fNmNfXP4tq3fyOY6wUnsTO
-lj5hfBuEJRiRZj1H2Fch5iFtyc7kw2pH7jhXvOHoCbztjXgA1KgAaoVixQhOHMWp
-NZMy+qDbDlmblV0AEQEAAYkBHwQYAQIACQUCWMNHZQIbDAAKCRAhj6D2qUGgN3HV
-B/98pHsmnqNOu8pflm+0oRzh9zQypjCcKlFZM0WQ7jIRghOYpIKxy+zCj3HU9110
-U64JK/PO+AAOAqHnh1XXqXCooMIapPtoPV7Wn5rvK1agsDHUqeO5yJKlZMbj60Be
-f6qR8iuLK07nZ+GJcal2NCRq/t212otXD7f70rfD5ut07MDM3ifmZFdp27eEGxCO
-TaDf+KzZhP5KUFtAcNGpuXXAEW6t/JqJ+6h9EbpddQwgLsSwoWao4p3FRyu69ZqL
-CeGx/iz2BxYeUH+oNiFh1u6Bio4Z98zze4eGD5fT4RzcWwqMvyLxWjvEjVyucG7I
-hd8aQ+J7j0jtofr9xasevdRn
-=XE73
------END PGP PUBLIC KEY BLOCK-----
-
-pub    858FC4C4F43856A3
-uid    J. Daniel Kulp <dan@kulp.com>
-uid    J. Daniel Kulp <dkulp@talend.com>
-uid    J. Daniel Kulp <dan.kulp@sopera.com>
-uid    J. Daniel Kulp <dkulp@progress.com>
-uid    J. Daniel Kulp <dkulp@apache.org>
-
-sub    594E23256A36A392
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-B8ab72h8ySjaeEd9kV96ByEtpm09
-=OErs
------END PGP PUBLIC KEY BLOCK-----
-
-pub    F3D1600878E85A3D
-uid    Netty Project Bot <netty-project-bot@users.noreply.github.com>
-
-sub    1C9F436B883DCCF6
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-eOotdxJF6J5yWErznxlExP5YBIHvIQljCyU=
-=WKVz
------END PGP PUBLIC KEY BLOCK-----
-
-pub    36D4E9618F3ADAB5
-sub    C4935FA8AC763C70
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBGGiftwBDAC94Yhhh/5yO8jYFkg01MPnooXKZEPwxAbAg9wn5iM0tHxhEpkU
-zJVYZ+JYq013+Ldp8Of7A/d6hKTtZ0xwSeY7S/WFykIk6tc0P5j0sfFS3pGPDk+W
-D3DwUa+8m0PriF7iA57vCOE51znO/IUIA3PG2YAK6jv2/i8MDXOOq3qB7VrbvKGB
-kIPubp5PbjvP+LFhLuUReU9m2y/3q9lNFXdd9kE2iScqGmu3FDhRJxBK/WQ2kqiv
-sJZjAYeHEVNcc88Ah6vXI73uYrvWVGCErzswYy9UrxCAQ/x2OxUdLw7NTHwjZSYC
-JvH5JPPTlDxMgfwTIsmaECtw4QgiVmvDp+RVa9zyrdI++RNr0InsXv9gWMv3p3yf
-TF20ZL8znFYVUi6XkeQhZjT4fHwDqDVnxhSAFe3E0cwHFJBQe2EFLljwNy6VYnio
-wBr7HrAxczRRqlUy4a3bH5KwiNwwvxgqfdMj9KTVpP9t98/TA36bIohwGFRWB7W4
-i395S90NsTbCh/cAEQEAAbkBjQRhon7cAQwAtPmKcM1/z8sMJnt4sHe3ndXsOdSq
-TJbRkAcdyDO1F4qgj5z9wkrlVVKGuVtmJS3qmR901Q+oH+JqM6UeGqhNig4IQvME
-iQjjelvKXMX9PPVzlP+ga5Y1/2mnUmgmYXK406CU7aaQ3hs7++XDonnQUt5nWF9d
-XT+xK/SDLYMk5i1TNqPVFZBPm44HpIjKGNJXD7Vv/5z62+hKswpLXgYt8Rz95ByG
-ncjQ1Lo2M1T1Y/EuwlRoc9RTdyABavSQWVLKIz6kKM4LejajjRvLnybMUug0CJl5
-mni4cHXx9t0pMlG5DE2O3mZLwTgWcJ8cu2CtPxA9iLfVvFAThxk3ZitkEhChBtG9
-/V8D4DiTIht6bd49xkHP5pxtB/fuo9lNb0axSBaOAeant3KA6F6vki+chnGhOFqV
-1KJHcxYG7VsG1hYhy5IbZsg4GdcXfTwwF1/mq8kvHfyTkBy6HMDGwpr0ATNnrxO7
-tJTiVqDuxfviGQUjqJIQDns6fM9BI4OfpXyjABEBAAGJAbYEGAEIACAWIQRH62g2
-JF0tQOid+0E21OlhjzratQUCYaJ+3AIbDAAKCRA21OlhjzratRBcDACCfhsaCFvM
-JTls5lT/dcTqSCYJYZyDj95DlTiaRNkXnAGrTyE45PnmJLv6FFZzSZdu/eLE8ls2
-MY/KWqnZYYV2Mct/pwDDLSjdAN/NSRe9HeAh2OS1kNeN2SIcoL55gEodKBNSMisY
-9N3ylLMxHZPa5LNBo+j9wftEaVi2fTX8LDJFQvUOZ3f7cz3f6u42FeHUqaLm2alH
-QSkfTB3yIu8Hmo2EXHh4UfwTmS55OBGLQ91d8neu7PcimqCeadeHW+qY5g5hr5NN
-LxMA+n+vwPGcQNxg0lH2XBdlFBbAELEGxMcKbW51QL2h+EdwGzT/nK3Iia/qm3N5
-0Z12j/hhzohlf7TQjhzB43Wbxef94JbKacvng8t/hG3+n8UASQzizCSn/oMkXQom
-XdQe5JFgJCroU2CfrdFmZfbkkq9mAi80BLUEAGNTUQrg/W39VX1/klGiXiWtpU8g
-q/tSGRQHXTwG53qejlUtKI315ZizOhJiniSDx4fZaK2zB9RlZkrnd1Y=
-=KPJF
------END PGP PUBLIC KEY BLOCK-----
-
-pub    BB2914C1FA0811C3
-sub    7AEAF265B448E2F3
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBFHwyNYRBACkCXpipiMx0lCEccXXzv0bE7LHHbcQYtb1vT/o9WXYoP8JMChJ
-cvuAe8Tvg+s7EUjKHJRhu7I7kie+IJ2wtH5uVARkYxoP2OslYN6MSXa/bmwU8fwQ
-EFkVeFV7q2UFvH4cqpa7UKWggKcUzvB7z5spg/iKuMDQ/aBkxpmUcrpefwCg4/IC
-Omi4O9ROfzJ5Q1YHSrr8A0MD/0OTgJjkBPPBcel/pFetsWhlqA6dkYINT5qdlht6
-d+aye97QFUccg3ODnCq4fnDPHK9PMK8cTGkrnoux5XY240XkWX95tQDyrssGqldC
-zOLxoii4/gsw5s6j4x/AjycsAI8DxaecQb3/sNg05V30ZNm2+kQNmGGV+0oERpo6
-DAVQA/92UVwQdZjMzCs/6NTbsq/2tRX/XXiIxTij6fpZUeHvR4Ek3meuaXs9PPwC
-o2f/90aO71bNKjh0LHSI0CEuMWbnixmBgOEQY1yv0HvW1OB7otXrTS7EI1m+4k4c
-WlwidtR3XjqqgXTjFz3J/ipT8j15a5HOtoIwP5AHw4e+1cEmCbkCDQRR8MjWEAgA
-mqaIVMeh86G+K7uq7m6m8F9s4WtEkmYAYHdk5FXOXEJ+uOSiUiYLcYSBYRkahk9Z
-o7QSv0bWRmqCFI96Jvo5f0MBLkwR9hxYzrr3vkkJyreMsG7ybyXA0O+ga6ex1091
-bBm0f1vekvT7VGdcTtjWhpDiMBXZgTJDGUEpzz0Z/8MxYEfTsk1P7TNMMAvm4AOw
-vRk/xL8Rc6Gapr5EGMLhKRADwvWU3vYIhRjXApXZUem8tNq58cmR4q6EEsmedDri
-LuufwVBPT98/+sxEPMgPFnSoLPDc7AB7vD9s0Ip+8jG5Rtbc39Phz4GDHmCUwJ01
-Mo8k7Sr+jguGb0fthSfM9wAEDQf+LRyfjdWJ6CW+mGSYFsW1ivKzLujvfiQip3CM
-y68Si8BmUJvN8aPWS58knZY0ikXOai+m7W+4yVMkdNLm8JpJ7SX9NevZCYAb5lOg
-mE7kvHoGFar5oA9ttUIV6RZXbQi0fXtksKse3c5gWqMTmEzTV+7thtQ3V6UmXpIv
-OHKvLJdocHP5T3yDgnKwr1ajw7028XT3wsaiUV+sgjtc+1KMME9/Zhwa1jWSzuZ4
-Pb0kxVIjzebsTr1nMdtQqARg+KKc+R8Gc3NCP9MZ/s59NUFyfCkg3TqazsIXQ1bi
-KMv0GppFbFMnC/ifijqtl9g9phuoF3N6/Cs38zVlRHneyHRAG4hJBBgRAgAJBQJR
-8MjWAhsMAAoJELspFMH6CBHD4SEAniBrVdd83vjrwn/3vXYTuZrmjIO/AKC9Ib56
-Z/+UEC1v8wCMk2365rUPKw==
-=vlw0
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5208812E1E4A6DB0
-uid    Gradle Inc. <info@gradle.com>
-uid    Gradle Inc. <maven-publishing@gradle.com>
-
-sub    33AEBC1F01C98081
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-bMFjyklLBAm1WETBiqR+k5uwXmJ8
-=RGVX
------END PGP PUBLIC KEY BLOCK-----
-
-pub    4DBF5995D492505D
-uid    Sean Leary <stleary@gmail.com>
-
-sub    BE0F021FCB5F68A0
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-nGg4NAU6QuXCv40L42QGWo2w0iHMVw==
-=84CK
------END PGP PUBLIC KEY BLOCK-----
-
-pub    59E05CE618187ED4
-uid    Taro L. Saito (For GitHub Actions) <leo@xerial.org>
-
-sub    8857595B73BFD468
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mDMEYuRVGhYJKwYBBAHaRw8BAQdA2Dp4m1Yhtb1g94pQzzL24FuP6b9KXF8lP9Dh
-hZnynhe0M1Rhcm8gTC4gU2FpdG8gKEZvciBHaXRIdWIgQWN0aW9ucykgPGxlb0B4
-ZXJpYWwub3JnPoiUBBMWCgA8FiEEwcunXsm9C6+AYZNUWeBc5hgYftQFAmLkVRoC
-GwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJEFngXOYYGH7UfPwBAK7x
-TVRebZeWcAwmGaMUsbg7SgJou8xnkhByObPLUC/4AQDPsZeYmi4KXyXPzmqhCicd
-Y+ZSJWIDQqitK2ujPDFXA7g4BGLkVRoSCisGAQQBl1UBBQEBB0Atu9kejBi+6wfO
-T0a9z/LYEEdNXM/VX6xt1onKToPPdQMBCAeIeAQYFgoAIBYhBMHLp17JvQuvgGGT
-VFngXOYYGH7UBQJi5FUaAhsMAAoJEFngXOYYGH7UlMABAKyRCazhVyUFg5FOpAnm
-ckBY38CaMGPPLXVyY8Kr6dYFAP9wYLu7nsDZCOXkAgS+et4Pk1WZCggoYUkxsX1o
-0KZXBQ==
-=416A
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6525FD70CC303655
-uid    Stephane Nicoll <snicoll@apache.org>
-
-sub    DCF4B49B4D5845D2
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-LwCg0goAeKquoZuBm9KXUWlDeLuHu6Q=
-=WF0r
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1669C4BB543E0445
-uid    Emily Johnston <epmjohnston@google.com>
-
-sub    5F6BA89D4B0869B9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=wp39
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1A2A1C94BDE89688
-uid    Michael Osipov (Java developer) <1983-01-06@gmx.net>
-uid    Michael Osipov <michaelo@apache.org>
-
-sub    A3F393B5D034A0A3
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=GKWd
------END PGP PUBLIC KEY BLOCK-----
-
-pub    99CE9D9F22DC5C99
-uid    Benjamin Gehrels (used for *@gehrels.info) <pgp-key@gehrels.info>
-uid    Benjamin Gehrels <benny.gehrels@abi-05.info>
-uid    Benjamin Gehrels (My Jabber ID) <benjamin@jabber.gehrels.info>
-uid    Benjamin Gehrels <gehrels@informatik.hu-berlin.de>
-uid    Benjamin Gehrels (Used for *@gehrels.info) <benjamin@gehrels.info>
-uid    Benjamin Gehrels <benny.gehrels@gmx.de>
-
-sub    6C907406A9482E08
-sub    B2581403B6FA2318
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-vyI+RlHq3tcMp5tjpfuk7+E=
-=gZhQ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1B2718089CE964B8
-sub    A182F48D9C2C0825
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-yEpqZGNE2g==
-=OLRp
------END PGP PUBLIC KEY BLOCK-----
-
-pub    012579464D01C06A
-sub    CB6D56B72FDDF8AA
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFgnlA8BCACVtx3oLXcanfvwtMRwal6pLQ8IVMG9+fr4xGdbSHXCRNbosDa5
-agU7WeQMPhusSxJGaA3w7NOdjAwD/LeHADhDPeI6llJg1Fb3EyqH0NZaODKU/Or/
-dID/i1onAX1dE914J4lf3XvIAxGiAjmr3UvWO9RiFxRUkecMAMlCBp2FuHuvxkcn
-Mk8q9dP9Ef360wu8X5rj0kgP6vPhgl9/RhuPsUxlazb2Kn9Zxi/RmDKDiH/vDuwy
-WdRGFOR1OPV7l3Ws01nrs4vKd2v5rsUmsjvQ8ldxdrA1xzX4IszHRDgSC9PI8ItZ
-1VlbaKjE0L03acPfFTg/wRFSF5zsrGNbTmq1ABEBAAG5AQ0EWCeUDwEIAMGWqQT5
-ccT/Q1OypoOQGEZn+oRkgEdnzt8mjo7aOXd6pkNTkt3+LCkmb8Pp3/a3iYEfvSvB
-Zbb2JbY9xnmM8jBucWnow1iwEPxGhUuu3jlIpRsCwLk+utLkMALRkooXqanDoVRW
-xuVeFYN0as8nndgWiJT30innN4vfaR3x3E6/nS57zp5IggxZYsXTRHb25kaof9lg
-lHyXeypW7quKOP4SeES70PVVUnYZBlLpnX8a2msRtJiouWxCv/kHnYsjW62vc7nq
-vWAsSsfBT61TVx7yI9CckVFBnkpG1I8C9WpfcR+j9yauptgUMfrfDTFg3Aip7czM
-SoL4Jpu7jBcXy9UAEQEAAYkBHwQYAQoACQUCWCeUDwIbDAAKCRABJXlGTQHAapGT
-B/oCoCsuJ7617gpcuEAXxWTBfcXKo4z8ObBek2RUh0AY9aXjRYSzwwbtVFRC01Es
-r7R9b5ScY7W1TDQBKL0OSRZ3jwy7/hA7k8P7xAp3mC4+FdHaHMH8nGz2IbUjGWl3
-Yp01NRn4jc8gcnHnqcUff7PXsRMUtJ3dnbsIYOrBAbWKld07RVEQUyafgUfdF9cx
-e6P/slSZxATJrlIPveB5bgcVDMMw1UQNqJL9LWP2IM7xcljOBHY7jqwqnQ4pRER9
-2VzhLdtsdwF0H1SuERpDxBAuibchMoCfQ3HER+K2mTUoJ04xog7MQs2aaMwSbem1
-LMvNBZ/mfF7QMYfMV2n7rbIk
-=PoPV
------END PGP PUBLIC KEY BLOCK-----
-
-pub    0315BFB7970A144F
-uid    EE4J Automated Build <tomas.kraus@oracle.com>
-
-sub    7CD1B9BD808646B7
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-ov8fTyW5CUsFo9wQlCvfBosOf7XRtyG9cg==
-=qap1
------END PGP PUBLIC KEY BLOCK-----
-
-pub    4DB7BC57DFDBCEA4
-uid    Timothy Wall <twall@users.sf.net>
-
-sub    25EB2A6CB1459233
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFBm+zUBCACsrBpO6mOsZ/B6PdPPV/Hj87m2GHeEYEHt2o2l8X2BdbZKbVW1
-FIKnpYe3+TsFCe/qNxlR6vk0Jpy3ChD3nW/J0rmU0ju1SZnS7rdSMj3AI5M5xxpy
-Vn03vCbYyFWw4Bj9avYmiz8kC7yImfGfTLv5XPmlHhUQaxW8+s+393n1mHZsIZTt
-+luPftSLCkcmKGHn+PUkFaHHD+q+TTaG98nDkkaCXS0JwXzujYDJDQgV+6HB6PO3
-gJJW4QcUHWa5uUY4CfqGcYGBvzlfII2psyKFIHqrx1uHxbhjLlIwif6I+Q9OFcdq
-qq4JgVnWti2dEBgOVunb5S0KnN40VcH0v3VVABEBAAG0IVRpbW90aHkgV2FsbCA8
-dHdhbGxAdXNlcnMuc2YubmV0PokBOAQTAQIAIgUCUGb7NQIbAwYLCQgHAwIGFQgC
-CQoLBBYCAwECHgECF4AACgkQTbe8V9/bzqTc/wf/ei1o1L2puKVUpDpM5WC7LIMn
-mrSPmvyUM+OJs1wGHJUymmDOJ1y7wIO7gOPpFqTWn1qK3GajdmITG9vIxzi49xQ6
-1KYCK9bT/cTDC0ky/81ft811dOfqJsXG9alGf1mparS2rq09oWGfSicFWRNlTPQD
-vgMOe9VV/TcvvLpEce6iw41BDlUWkX8My2ES2Z0ClSSm1oPuwAdr3irZnQ5D9lKw
-FHK804nIHv13EjOWT/ppN5jFQA8Y+0idiJ5UZZM4WGjpvHujDeO3FyGpRmWyz15S
-XnVB7UWxigbxj/YC1Zuq1usLkbvnvYkGnbFjZke651fkF3uemthz3w4yskHHHrkB
-DQRQZvs1AQgAumH3wbBy7RYBaRjaWjN90OKcpXuJ0MTIzkgC/JtNexIVtzFdrfmH
-POEZESYyLVk0E5YU5i3ux+K9ARi+bWrst3s1iiPfebeNCRU0lmxI7fih/r+PxcTT
-dJnHAoZUNBK1ZzjlTgXacradjS1LGFX5+52gTgFVNlYXvI3qPKQFb+Vfz3x4LwOI
-10ipnqZK61D/FC96JD0osEFJkmFvI5n00VwwXXRoeefN44Guvs58nf6MNi9ZA11i
-QlK2a8CswAuHJTndkQejVq5D1+ejVVmt27mH5RhG1xoNZ6FSkha+Y3ImTpxQMJzd
-bkOtMzj1S2VIt8ZcrV/6dt+yCAskTFW/ewARAQABiQEfBBgBAgAJBQJQZvs1AhsM
-AAoJEE23vFff286kd/gH/2Wz5zWkcvk8ReH1Ke9vYH2gee0qtXIrCjtV1WBOTy0N
-Lm0S4Bx/uFjbFUbqNK0nKjTix4mAe9KrVJwN47mXVGxG5N79KkiS8lj+YM8WOUIe
-5tkDovzEfqFukzgpHBY3CXjiojugxVv6cEe1GLnEEOYJlezZj02HS0D1eEeIdu7a
-V6f6xPFAo2q94aavz8cC01IXrnccUfuDtBJEVqdZmVoc/5tUZf/dU2m5ga62U7ya
-VbiimP2NXIL2tzGLgyUaT73E3e+EXzfcpJaOrBqbcs+2HPfAjBm/km/0EC3ET0r2
-Vqoq40hP3fQqLSC/LYK6Vbuc/l5M0I1QxhJ1njCEin0=
-=lajw
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2BE5D98F751F4136
-sub    C7FDDD147FA73F44
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBEwMV84BCAD0u42clJ3hghKlMGwFA8PPlPgSEZjyvs2dRCF+dKWBaPUnR88K
-kGfWB66jX6PBtHzeiVRa078lL002S1lSth2A+s1UfYGS5wVbE938wO6PCMwgoXJ6
-0MCLsTLP54MDlly4tq5qV0Zme1wH+9n/AC0fbKkLsEWbqXhNJLJ7F8TUh6hPziko
-mLAZCb297KeEDJ3tFN2zkzjx7V79/nkA1sKHQC9INdj5jXxkglTwZhcJgPbxYzCz
-nbGeczPxwzNrN/elx0DDnKEpEms/nURfXETsnd7t2xuUuAYhpGIadZOM+LojhP/A
-Wp0KDHsiSc5tQ0oJE//ydBksCEKid0Tu2bXPABEBAAG5AQ0ETAxXzgEIANGJ24GM
-VmW0QcuT6ykJXtjrgXW4HjOEyylQ6LQJZcCt42tNA95ZhAAiNgB0CBBUuOne7y7H
-5IW0wxnrO8qOStqvjbkUWVheqA3G0AlokZVWQRk1LjmBlABJVeHNBle0248pwrXe
-0lY3NVVywxPE1ol9DOasldSv+nKyMcRFgkZ7rPFnVaLRLoozuAIDwXXaRPczN3pg
-iegwo9BLqYV5+0Ncs24+G0hO6iTToX4166GvjWa0e0YHuJ/zztXPy9CAJ6FMJy4Q
-2ZpyfmIPua653srMDty1igFdR3TVNd7xIvyhw+laJY9GxWM0G86JOCpZhrTWDDZi
-BhgL+sF1iNPcC8kAEQEAAYkBHwQYAQIACQUCTAxXzgIbDAAKCRAr5dmPdR9BNoGn
-CADj7y3qDzkFxiHbfX6RlWJfaJ7wvz2r5D7WOiiyWL2y++zMVPVEhpPSw26b8Car
-4CjRxoG9TqR8GTO8yLlgQ1mPWovaxcmfNzJ1GBQGKD564fKCJLwVMaMgMz8jEANd
-FQNA5Ka25MdixHIYafKgY4TDATQYAHSs4MXW3Y1B+54LCJcL218vdWPxQ7k8AYLQ
-Suei1+1yA4p+tpjxhr+HUuFv8tA2HUk8RcoyRfUH9fqAEuR/u+xWm4kmE4qMIgio
-665T8WuTGYLkUDJEh7F8+L+r+f0nmCxfPhIWenVOrjpyzyjPlNfaweqk2dvHG4wZ
-ulntJIX+jkiE3IPFPSOU3gs7
-=s65m
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3D12CA2AC19F3181
-uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
-
-sub    575D6C921D84AC76
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-FdEbaZ88HZxTa30iXtOXOLvWIYRp8hv3pSb8id8=
-=hALf
------END PGP PUBLIC KEY BLOCK-----
-
-pub    280D66A55F5316C5
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFOOGVgBCACiDwUZOc6943aBGUrxikkfUnsyZfHtF9jihYmA1pSgfsye+JxR
-oG9QWW9+3qx4L/d4ZEqBftTWpsjyrY7NyMaeXtJEjE0vhiWNehgXB1z4XTJ66zCX
-nhlMvixGLQtfZANqCxOmtUGoSXw+oRFY/SExAioSS19HlSxApSaUzc0prdujqp9k
-vOKKIBWTBIUELdDTA4+enfzkAnIINUX9LcMTmO+Fh0AvfjDbq4fr8rBglyVUSCqt
-TOT4oGZlbpsq9TOKrTXh5go0rm5KJcbgKvX78ZErK6pcpTgNA+XFXCz1rQ9nkIQt
-HxWaEMJtpSkIvHIBz9qoAroGtNFzz2oF4ElRABEBAAE=
-=1QGy
------END PGP PUBLIC KEY BLOCK-----
-
-pub    164BD2247B936711
-uid    Marc Philipp (JUnit Development, 2014) <mail@marcphilipp.de>
-
-sub    EFE8086F9E93774E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFPU8TIBCADGNvExYTJpVuNGCF9NuWw+IkitjAD7WzF7QkvFCSw9VftzgTUZ
-3PYrThRiaDdmHQAke4Sp+nYyAJ7iUcQqg/5/ONiMdzXEv5Kwy5WJN8+o2aXSunIT
-PALIw29DemZdVerw8Xc9jcdNYGxbPgtfSjr/DBCBs5Guq+RuuwsBvyTGLiHpc6hb
-91D/wX6Y0NQB4UlY9f3k6AgqiR5OGq602hXYvL10pH6eT3gSmCvxp1WvNJDBmaRi
-ZdgW76Y+bGQkmygWdAb3Q2DUEQHVH30YTBx5VFoiCfx1Jud4mD90Tv1hhPn0fS50
-oLGqI6f+VB14iJ4XLaSfyk/UMl343iF9PAg9ABEBAAG0PE1hcmMgUGhpbGlwcCAo
-SlVuaXQgRGV2ZWxvcG1lbnQsIDIwMTQpIDxtYWlsQG1hcmNwaGlsaXBwLmRlPokB
-OQQTAQIAIwUCU9TxMgIbLwcLCQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEBZL
-0iR7k2cRglYH/iq1jxu/Wsv4HTLS+aGZYrgxJUv7bWGaFP12VG1xmhVDCPIxNV1/
-MKR9nI9BXyqTlI7ccipwJyZE6VmbbK+wCuALGJNaE04Iw6adGu0bHvk9H/xjY7HA
-8lWkXd/fnYe8bnCaGWr8NpbTxFNVo8u0QXzn1U5sindJSzyE1+Wi5Y45BE9gYh3o
-uLEJeguj0PodKsjxfRnRnijEqN78pKj8gkxLY44pt/arG9iGRQ8wD+KiXBgAEpnc
-4pZVe7hXA/PIHBsWufBDr3HFbfhI3j+AxhnLWbDick2GsOTsSTX37C/VIAaGzUnD
-NZLW8NcRAhL4RhvQY5F9TDrD+guwg3HoPFyJAjMEEAEIAB0WIQRFvr7slQq9Bc8O
-9cNQoE0MO2UX8gUCWz80BgAKCRBQoE0MO2UX8q5eD/9Egux1zMbRm6ZWune4Ov2c
-ag4X6Qx7eA0so20w299jpNyr4zZVJAcAyeYjE3BCAPaIwZzGeW9f6LuYcZrv7qIT
-Ij9cxquD5oPzgd38UhqFF8N9p467Wh6PAU3wwMrTJXIFpKZ6r843mthdmDKPXG23
-OEyCEK47Ga/PltW+K0sHauUTei3iLxePrlsjGBc7enKjBHgkj87RgMJ5bzSMJ3ai
-7/V28AjUIu+Y6z9BaNpKDRJ8Rp3HIIvVt+uhloP1aYD53OKnohCXeIMuUC0WnqWl
-yN4RhguCUuGf0ygzcSwKZBldh1friOdkZdS+9Vxm3Y0l97BPB70QdgFJPa8CZSR3
-DXpdb2j5N0bryI5txP2bO6C8Yq5/Xx7JddnxatOm1dsATxv5EcZN/U5d+wdd0dCz
-36RrqQ+beYs6WST26jFMgNyifU8xoY/9PqemHMURkP1n/zgsnYMqRAn5XtytGtv4
-rUOugncGVH8rP+YpUhVl6vTeHSI5irsgjjhV5EOPiY5fXoxfY3SpqKunWajgAzTx
-FCEQ6B4v/HyvySTX2YR7x3mJ9xHfBm0EP++mSnMMQrxR/cgIBpeOXyboYQZZ3T4G
-V5cZjHKabs0uQSy8uVm5NBXKAUT199M0aoeDeT0O/+ook60NBQzpvvJCObLc0eRv
-n7q8wS/j7XFSgIdCN7NB7rkBDQRT1PEyAQgA0A5RG31MshHFziVkue970s1KNN7e
-Dzww5KgIj8SzI5Hi20yZzs2o2ALBhfK42VqT6NIa6ktuJQJoWr6KhhY+kMaZlkt+
-I0U+Llmby4l2jlG6lFPNZYIavLOFvU8eWvU934fgLutK4HimBNo8HTqn+jsfoNTf
-8cpvcASQnjQVOElf5xTYQ6RWz331ZDpfJpuPyPWK9/GMHQrurhK4QYSla9sYdYIZ
-M27OmNxdi9haPLSkaAmeYF9png0CoPqanI3HfIN9W9Uu7kPczW3Zr1DgXq4pto7r
-lK69M01GewKMVuTS2MJqzWzaP9BCMj0jI+icpSRV0696A/1eZCR7Vab9NwARAQAB
-iQI+BBgBAgAJBQJT1PEyAhsuASkJEBZL0iR7k2cRwF0gBBkBAgAGBQJT1PEyAAoJ
-EO/oCG+ek3dOenoH/1vTfHTzf4Z1odIE7lC98k0zF7jtvPHndsUysKp3zMOtruEb
-8CE0cuw9Z0rYzIBzVTzNm305So7G1xv3HVOd6rVcMtpsZpo2dAyFEbBTyOqbDKfW
-rGx4T9e61m7syNCCjadGlTAEr7XLkJwLgjhHGwTN9/VEWz207JfL6u1XdfaGGSxP
-gZRqDw7c+kKax1fU10wV9wv5bs6t/fnPqJppZSR607BiHNUAt8Cpn7kEC3Rm8mS2
-ufqg5LX+quLlgl4K7L+EYecq5Ox/UG4lRCNGa6e1TM/LyoM8GpMC0OOK079GceNj
-R+r1Jx5fxD8Qi04rKo8U4LZd8Kig//NPGjBx2ytpcQf+J0linycedx3OyhGifM1j
-7SfrWpeQT/TJZG08qVw7mr7eLzYgtPfz7YzsxCAcGo+IvxSaxVF8c3BMe0liwwcS
-DL3SF5XWYt+3X04e9YTODKimD4bqhZto/DsJHR2Md8m8Q8Za+V1bS8clogD1f6Wb
-o3adzy2w+braL+KDyjm2NQsBSuLNBqcK/ztXGqxK3bhWH2wT541djd98y/jB52X+
-eVoeCEEPZi21wW6UDCgHqfC1Xxhsq70BbH5RCwIMx2iyVVoKEyxNhaOgApSfq9mk
-o0NAlpAuT9HbTm6GPVgoEzTAHBhD37R+PsUfSEPep+pmyBlX2nrKxxoRNsl5KWNi
-Qw==
-=iceo
------END PGP PUBLIC KEY BLOCK-----
-
-pub    98FE03A974CE0A0B
-uid    Kotlin Release Key <support@jetbrains.com>
-
-sub    CC3328A2F49A80C8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFhlXQUBCACoN2nTeSRVZnGoktKHyiCgeYQ/hEKKKDDAbWubnnQwonCTILaN
-Qw3GmIT6plmi9iy4rl+rJprSzDeQDZngQCx1KPYcXCrrc0pnjERDaogw9fC3c3z2
-B6+90qT6UJSTNmxMs5zbhgzKDWb3eaDmVDqVqzsM5xz9GxX6zo83o37fTFSbVbtA
-9+c100+KaAldVL/6uLeGoQsAIxtMH8GiOPiSjrw+XCQ5mbP6e+oYYBKxEyAgu1XW
-8jP4bF0rz2+1lkIGfWfYHZmMbmSutDxXqOXA9cZomhOayOSe+iczoxXkVXkQzMxq
-bG4ru5CHxPh+RSfpwA+9StLvzLeoFrBUlqW3ABEBAAG0KktvdGxpbiBSZWxlYXNl
-IEtleSA8c3VwcG9ydEBqZXRicmFpbnMuY29tPokBOQQTAQgAIwUCWGVdBQIbAwcL
-CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEJj+A6l0zgoLPTgH/AkH+uBwgQhS
-xIfYNA/pEt+ni0eGtjClsFtFF89jjQQAAOMsflebvBmGB/ptpfAEp2QYqRiGX8Mz
-3cRYwa8JcwEVWbN8BrXSgtS3P5zlzBJNPSJJFqpXENxs0VOLZUd63ZbDgQ3h1DDt
-lP7VwsIlF/ogq/wql6gC4qdP9c/kA57eqvZeMrflSUCIUlN2XkeMZhGugWd/Juee
-kz8qMRXY/kEKGbojJkmrehLKOsFz/L8vOW9TLskFuYBIb9PHf2hqLFOOQ3z4o/NN
-fgrOGQVZxM4LWIsUMkO1hRiIdk6R0jLEdFJIOS0z7mGqKzODWNOVegPNhjUX1E7E
-viyo727zBJu5AQ0EWGVdBQEIAKNt/VhkI5bXMxoM2XYMh9MPz67sAaqc9Eixan/O
-ONftycStOVHB0YhfQ9lsNeLIb6qQvvesktI1exv18wxSpN+AEwroMGDSDfixhpga
-eOGzj8omXOTBZ7Bv73A+4dCVeoQ1F/ss4OkRK7Jx5jLM7TuY7IG64XSYy6D6QvMO
-oIxKdqB81f6JYDzVwszFvUUbDqVQIfhXcuCLAbYxtJVVzAldGBWR/72Uq8nE3ere
-eeZjHniADawU+XR2Egv1aMDvP8zUpWl2mRzOKA+1SJyXhA569435s604PfxPdESl
-KnMYlinWZNvL5rrRV15vYYU2u59ol/g27DOFy33UCrCgZ4EAEQEAAYkBHwQYAQgA
-CQUCWGVdBQIbDAAKCRCY/gOpdM4KC2NwCACTClhcW6GbsRaRHzSdnXDPUNlWf0UD
-Pz0amNp8mQwsygL+jW0awtrfxxSqbv+1myMQB7g6tLFGcTH+jqfkDsN2rpQ2/cnr
-UVmunMjkCnoSyhrqolSv9ow0L7K+FERmxq5QGorE/Gya87oK38ovXZmGUs79OGSt
-AeEnXXkta+dDlX3nyTGM52HEaabPJRv/eMoryZPgv86ahajMUxbc9LdjkdVnwj+x
-a5Ux6ZVuPGHeodq+MWTZuKM//qT9uXbOsgiKWJ1E3YPy4Ip7kc4ne950WGndzu/O
-3aBldqsxUstQ0abZXtAVj1j2Io/Jgvt9btE9i0ssfGT8HCatMFwsfi98
-=2z1p
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A1B4460D8BA7B9AF
-uid    Mockito (http://mockito.org) <mockito.pl@gmail.com>
-
-sub    BA6D22590B3F9BEA
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE4waOEBCADHDHNTq1NRR5TSooIrKY0BTQnaLfjKZfcJOwp+btBJrOUO7+e/
-V3M4DZQclj/e8SBiVmRPK8Oyrv6i5B5+Ee/qNlLjWiO10AJ/PLRjYdoW1V6PlTm7
-2aUxQ/wNXxDcOoH8M7Y4fEqZJ3rFuta8ogeIYnkUwUk3gc5YKk7KJDbiOXQfRxlY
-9MeVKyoYfj+2Szaaz98W097Pqf9+7i3WjB3TKR1pnWlzF6rLWIGBJqcJuTGLWUAB
-hwOMoNiIBAqyGu8E4rT8pP9OueprOeIjyKgOBWV5yctIxd7uu51sGR47TM2wmMmm
-r/Kz8FkMr1efof7Bx4mJuup6wQXonRMVBqpLABEBAAG0M01vY2tpdG8gKGh0dHA6
-Ly9tb2NraXRvLm9yZykgPG1vY2tpdG8ucGxAZ21haWwuY29tPokBOAQTAQIAIgUC
-TjBo4QIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQobRGDYunua/0Ewf/
-QRv2EXl6rlgV9LgXifdgD4ctYsMvhmJV0uaAaTvTcNpbYL0lG8FpCs0KHvBLWkoq
-esOdJYT4q/9msnBAMXS/9ckteDism8BwZR0qi9qzASzzMJEH7cdpr1te17JR0fl7
-8cgbGyw6UGfRSay9c3HyV0rCuQSFPMwQkG5YVpRiN6NSnYqDczS+aSjd6JCKu/4I
-LVgu4jH8oaUcGJEaWLmExSUzrUv9HFZXQJxLzrFT4k6AVVzBQCuEYW9XtgosKwfo
-0GweBXkC7iuO+bfNi84vyRLTkK50h4+rVNkyvNlgqknbeGrpvOvGErYJy24API/5
-TNP+ZLCTl7Y+qQejTFVJ4bkBDQROMGjhAQgAxDjlr6Oakgs+5d5NcIYpJ/8S5BIU
-aVlmjKoaFJoAy46WzvvpaTC022js1ZSvrM8wlSxSk+kD6/FAJw2pJwRgVrolOYJQ
-mqLqgTA2QSN+leWo0x8gC1+QXzrquCOd7m/+h8FHUDaxc29XQ+7+HtNvsSxY9dtD
-zgQGXjPXSppVCSiDNy1IuIAxmEAFSxok12Glxq/n2DFx6OnVB+5vvt0C8nQ6w0hQ
-AQKPUmO7fNav5lZMfKgR95NrvF1Hu5V6DZvpbXg6+NWfA8LsCampARrou5qzy67h
-b/+KKGHTDMOvZZlGw6oSnPngqmh06QqY7P4PKVkOo3Vb6+02ltyZ95RgmQARAQAB
-iQEfBBgBAgAJBQJOMGjhAhsMAAoJEKG0Rg2Lp7mv2b0IAI5pDzLtBGxYhmO1rSDg
-Y+JY7ZAr4srW/7K6Zc0RmWv48JsZOf7T78kIrif6jrF+ZwBLrdP93umMr9aJ/mJg
-lr+0oag0ZVhEW6Jb7dgiRn8F9+qcCs6lyozAG805oW2lULkwqSJ1xNs79v9RtOWl
-I5ruLVbS7XhGv0qH+ly1xpIuYOzNvpOgj1pC3Pv+NuL2hrLUZVg1vM9eCM3TDVbD
-yJZrxKdMemMSGHHsXWHtn8t4BT88kice4weDq8GBl1Dx+ApO1+iHj779nMX1Drfa
-xtJLTRqH9fhHesISmte8fPiydGT/HCA9quKUuxyN4W6Uwu+Uov12cGV2sAI+H5qP
-hF4=
-=FXjQ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    BCF4173966770193
-uid    IntelliJ IDEA Sign Key <intellij-idea-sign-key-noreply@jetbrains.com>
-
-sub    C9F04E6E2DC4F7F8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFKneXIBCACtnX3ZQmPujf6ocvdnhsBheze71DSl34TfebyW2Qt+g9NhMxo4
-DaJy+iFNnsaMwLZRr6k/qf+ISE3A4opWAQlbk+Wb5s6DPPA2cHH6W4GdkxtuJzqt
-tFn6YtkFhA15Aahr/vz31NBjUJlBmO4PwvkyxiF/MYP6TQ/AHar4xP1RxSYEPcCi
-dIQczQ8nXzya4OqOyTfibeGz/eiHHuwTLHi3Rd2kihQnlRQdhE1rmm8uTyzFe1H+
-P7WW7kQgygW6yxQ3J+DXrG8kG+nbe57ZY1oyv3F/fOBxzn/kuoKHZ3JJEMJmTIrT
-Lr1ngCZApgteAynRHk4t/SYZiyoyqZCuBcwHABEBAAG0RUludGVsbGlKIElERUEg
-U2lnbiBLZXkgPGludGVsbGlqLWlkZWEtc2lnbi1rZXktbm9yZXBseUBqZXRicmFp
-bnMuY29tPokBPwQTAQIAKQUCUqd5cgIbAwUJEswDAAcLCQgHAwIBBhUIAgkKCwQW
-AgMBAh4BAheAAAoJELz0FzlmdwGTIqEH/AsyCUbhP0m7BJRULiYIWyB1WHK0L8cm
-yLid5X1P6VrktgcRbTMEzn4t08eeqb978P+GHp79xgBU6EQ+2IYiyeeAedZ/m6Lt
-Kv6imJsFPXZO3BLeNfwIzPC8QXdrkyVqU0vG/pSdULyBpc1aGNEK7Hr2dY5vQTX/
-sUrlwxDEH3LCmOnIgilf/M927Gelond9VmUh14HqCqtybv49XQiMUdkVkXmzKNld
-QQk+O24XbnSGOknPW2sADDglwoMu8EZTkZGdetgM/8X9PTBWWd9pEV32AnoYNMtd
-d2ujH+4i7AhH+Kbmn+zWYBQv3J3yQWj/dmFlOa/SFilLmmAtBEgl7wm5AQ0EUqd5
-cgEIAL3PEOztIFUibB6FYEkObVhsDbCnHw9yO5MAvAWB60Ohf1J4T9QK63jZ5/Ci
-qcDrw+uab9I+Ruz/SgGyFS0UXAkwfTICUdhT5kUzZmGyoj2ul+iFDP9uUdEgSgyX
-XakrxBbBPzNaMx8+GyIXRVFyRTH7+1gWgPQsdN1sGYOgZ+f8TMzAv6sxu0JVzjKX
-AAbXdiZTyJh9d6h1jS5Icilu8vRwn3Qc/ZzstBRk+eLbb69wS9YGoUlzYvDBz+5t
-iNwvHUriKc6zVT4Edngcr0mKWTdvD+AsvZffU0XK+vxbgMuRWi/51qb+VgK2gFeA
-seV6a+D1059u2+5Pn3h/Fv/vRAEAEQEAAYkBJQQYAQIADwUCUqd5cgIbDAUJEswD
-AAAKCRC89Bc5ZncBk0qgCACdP8kyUZVqfncA2RsQH38NFYhBz5MAEOIhCm7qwPC6
-XG08CUZfpPXdUbxZGUliE6vhfj7rZbvUKKHlcHDPobdTJqGof2jt2MfsjJ18JY0e
-xSWuVTmNmqAC3gsiMfEGIqjQFWonfm0Od4AvduLuc0TPkyfr0gobakgYvhDjk7eQ
-vgC1QfKlk6hHA/OAFW774qaQsyrANrFevRa7CBQEob6V6N8aV1vNxgl8a6fJzPTN
-BOOmP0mq7xk6nykQuqYTVFyqfXN0p1bbTxHBoW/fvdizi7zMSsuBkWUtfG1wyN70
-uoEQzSQwqgWCIaddzrPZPmaZ8CtzzyB7+JdSNItBB2Sp
-=3tsV
------END PGP PUBLIC KEY BLOCK-----
-
-pub    E16AB52D79FD224F
-uid    Google Api Client Libraries (Releases) <google-api-client-libraries@google.com>
-
-sub    5A34A5E06B936F93
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFF/4bYBCADTeOLZiVGNbjlPrwG7UcMl+yXmEqpf9dB1A9cuicH3PWXj0WOb
-LSzHjzoRvRekEqSUmgoveey1lPuA2qjOUkXY6Kiyx+oLiG0/ObJHUQW2O+tjSQ0R
-ZXKd4ftaw65SLbwYO2JHzj5fLC9j2mZQiRjGs1bWM58c/dOKp1XaOc1/ffcl3L3q
-Up64jWH9r3yhPemh5SHo47UxNvItdaJJYnt20azpZj9oq1ebUuQFMaQDc/RTALhf
-Xb4BWO+z2PCmChz60i/Ko2ZKPJV2TqPqWO+aklgxTTwZZ0IvgFm/5n3Dtn5p5iGf
-qwKkHPJIDWc8cWYtxC608LFdqiAlYmp/oPi5ABEBAAG0T0dvb2dsZSBBcGkgQ2xp
-ZW50IExpYnJhcmllcyAoUmVsZWFzZXMpIDxnb29nbGUtYXBpLWNsaWVudC1saWJy
-YXJpZXNAZ29vZ2xlLmNvbT6JATgEEwECACIFAlF/4bYCGwMGCwkIBwMCBhUIAgkK
-CwQWAgMBAh4BAheAAAoJEOFqtS15/SJP6NYIAMbwdE5S9M/5tIhLPg2arbvnxfh2
-i1e2aKE6PcRlBGeNq8YzWQStIewRhoDbY4MY3dG0nX9wgXU6XFJNxjyjE5Gqpyrc
-xEhs6r+HfxlGwB/OCaDMGR89lcWn1xF7uju3Qsdkb6o2JuCSAqOh4M1zIqADSMMq
-OjuSJ13GddcUFQ/MEvouE7Leesls9AM724BNZfnyJjIfJqfk38rXCxKpMbxCJ2v2
-louDMu0LClA1efdvDBPOrc8+A74dsVh7cQqMoe5lCqrcoC5apMqlJ71UV7SIBNBr
-7+AD6p0ZdGY8C/pTCl+NGe/Skjdqk7uEbmyePpm4BaJTmbwIgiZdGxthUgO5AQ0E
-UX/htgEIALToF36j45OitNd4k17BSZJKnuS3uIL3tTw0fRqLv0/3EBaj4zD5Qc5Y
-TKFgM66Bb5ybI63cwYhfSBHP2ZRS7oNdDbPd/30jDKNvmcDjIhGLT7bZJwC9SJVi
-fHuvtzr6wBR8xoItyYva5D3ax8ZvnzqIbMPeHou+0ZnRYSPjy2c2TxAJTjDOG461
-h9mVXDdK74wL8kQsIxqqYRIeEdmrXMrd/B8IPwuIv8w7LwzadNgRnXaJ5Q5bnMvv
-hVLnWKRt5aiQVBxc67FTujjqFF4Y/1UJb311K+1LSqNrTT7As8nhf2Gu/Gb47kw1
-bb7wBdKv2Swx5mYqiW5+ARQU7jCiUVkAEQEAAYkBHwQYAQIACQUCUX/htgIbDAAK
-CRDharUtef0iT2SyCADAznSkG/8EdIU5UQhp/lY9h3WLzYI7aARw0IA6O4ijGLwc
-ytO7TaWjEzUCMZdw01vAjVH1xNn9QvTgQV+2GyqyBNsjmgGt5/tK/+JtMgXUwr8+
-KsBf3908rOqAAZ3YGyM9N8sRsyfPB/PHfv289sL2IKPxiFTGI0NGS3qOAKQ5TZvV
-7OPsP5+yHfeJG/XhCW8p+nkMGpH4rE8Z6NKgLe/WC6J36aQ4kBfYneueH90Dc400
-rfGyL+0Gn1Rzuj2KFuUFK6q/GBlFaNo0azCqtdpcO6C3GpJYtISxpQ1Rp9kSEzSC
-L3tOli8Xs6gsruc+vCSIy8lzRw19ZO9G7qhjcHLc
-=JOMJ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    CFAE163B64AC9189
-uid    JetBrains Compose Team <compose@jetbrains.com>
-
-sub    57CE36BB68F1BC57
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mDMEYYx3eRYJKwYBBAHaRw8BAQdAV7zh1T+xL7mD2O63rTIvRfQ9kwL2Gvq/Q6PD
-9apCe2K0LkpldEJyYWlucyBDb21wb3NlIFRlYW0gPGNvbXBvc2VAamV0YnJhaW5z
-LmNvbT6ImgQTFgoAQhYhBCByOmOZvAYBVCg7N8+uFjtkrJGJBQJhjHd5AhsDBQkD
-wmcABQsJCAcCAyICAQYVCgkICwIEFgIDAQIeBwIXgAAKCRDPrhY7ZKyRiRslAQCE
-XiOkwreTSEDg7UXsRd1IruaQEUkrAFsk+1/FkqqvcwEAiAx2FgUTgDV8RoflRcaB
-kqPfkSvkvUBuJBQwqjGuhwa4OARhjHd5EgorBgEEAZdVAQUBAQdA/AOwflH/rum1
-g1gvFPBcqhvFOcN80VUb7OqoENSzUD4DAQgHiH4EGBYKACYWIQQgcjpjmbwGAVQo
-OzfPrhY7ZKyRiQUCYYx3eQIbDAUJA8JnAAAKCRDPrhY7ZKyRiSq0AQCEwGRGd5MO
-TT2kKJf9CphX0LOsqVBBSNvzoloV04wzywD+P4TmIz/CsigszDQy8yl1/rGvszo7
-gaUwnfnqN61JHgA=
-=DQGj
------END PGP PUBLIC KEY BLOCK-----
-
-pub    7C30F7B1329DBA87
-uid    Ktor Release <ktor@jetbrains.com>
-
-sub    72FF58594F983302
-sub    3967D4EDA591B991
-sub    0588BC69A286FF16
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBF+TCd4BDACbIA94MfIWL0SpvZwBddXgx36Lp9GYOWNgGoQCWSvk9vaMrLaI
-rEll0xnoP98CfBQYrVSAmHDMhSLBCjNB3V1Sdz8GRdOG7HUffF7Cqwbm3Fxo3H/h
-+Tsrodv23NuvKsDpgglUL6nJy5e/FO8y9dcxLXRRVdPFDhJubi08SiUJy9FQbnfA
-yb2LuTzXtjDmjEsMZpdpQUlQkk0xNDkrrq+2miwxemVd35cnVQCFP0K7c4T0ksGg
-Rf9A2r45DBbPfvwTL+ZbrGtCssUpCneWhPl79UsMxeY+vJjEggqqqRqbHRn6nOQd
-3gKSaEqdALZURPzvkKxLUeUUtMk/tkFdsNe/ea7edk6G3MI4dbUY7p0XLS54S9cB
-1JUAHNEFtuJQKGWNuwWO58Yun1EBtOdUEvnIIoQ+CIN/XeKrnEIXE3LSblB8BR3H
-bqX54BMe9AzsmDQtc5pUOm2pfvCoiv8xFXQznBg24dGqo2A/jMoUnGj6oRj7k8mt
-i9AdPLigldr0S0sAEQEAAbQhS3RvciBSZWxlYXNlIDxrdG9yQGpldGJyYWlucy5j
-b20+iQHUBBMBCgA+FiEEOUy0NsVpFvwB7qSnfDD3sTKduocFAl+TCd4CGwEFCQPC
-ZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQfDD3sTKduofP5gv/WRDpats/
-AbkXtXF90tNmdLomqzrLaz2dmsmekVjHnppEDZAJDWgHKuqi2LL+FU+8RPZj91yE
-rln0/LmOb1gGAkYhL5HIdSKPhd1BYrlObYIvxoarEi/U3+92B+13621qu4GEV96e
-luRXXe85vncuZiwjwPQqmST8gsAD17AiRt71jUHCqQUhsEE3C/5btOrqvM0Bhh+3
-QDUEoJcl1KoQjkPYhSDP630jhgsq0E22Yb1CWSXbwlJZTpmidAKICurll6YFhHQN
-wL5CLj+DjBJfkyC6nRDK1fX1IyU5jN201iDYMh+ibUclJFF4Lwl/ISlb/8NdhbPS
-SnNehscKyAK+xZ0w9CVfTVOIl0qx4SgwfoWu9fi02vQe60fK82usbrNJl+jWHAJY
-FcZjQ70cU0JpFVwhWr0ffOLD9A+HhiqzL7SBASapY4w5yLSlqZ5BOKcZx7NVqtXI
-qPgmbrSIYoXEzz4HQb+oCeXH6AigT+pxZJXpyEQudIaBtC67Nern3mYbuQGNBF+T
-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
-=/gGC
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A730529CA355A63E
-sub    D5A25EF82542C54A
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBEUQYOcRBADsCu4zTVaB4TOhV7NyTvHhG1bqN+3Va5t4vpGQJg4M4U0Yu0ut
-4bCZP8I6rlXGj+TqDKVUx9kfGpIKX6Kw2TvZUYbHIDWh3UhQO1hD4xy4b8rOak1w
-3vDAMYA5L/jsZshNHp++aTgmvSoXGS5S1xsjrbrOics6iTtHXMV9TCRelwCgkwGj
-WHzPJnlSj0z4jAlRG4ZubAkD/3LOfrXtti1oirfDTnBZcxhvldyCT2yiE3LRe8N2
-ijmtNO6fl2fqXSWuP0L125ytlOvww1r6Gd8sVXiVwt2oKZVQ+A5028BbHa0u4e3y
-54nA21OBKLCC/hJvyOkPf9/kZk6S7fV+Tour/auixX4WqUg+siMRe/EwHw6bQDD/
-1OK8A/4rVPPCDTLvcQbT+B3z0IEfryMkivJMu7dEoENDXDK7N5KginugnCpJd+g9
-GbYgTYI2YPNB6A2eaR4lH8yQCMyDXC5+bGL+1NL3SP1qR4JE//nUcbx+iMTYR5uX
-kwmaGMXRl7z47OgtaWM/dVipNuNaqkD9WkuMGb4rdSNHrI+amrkCDQRFEGEDEAgA
-pH7D8VkxWJgH5zCO7I1m2ITBf8pu/McMCvpCHR7qgQp4yvLBiQ+AXkbQPRPnxO8v
-QNlSL7wODfYI9hKDkoi5pFNlzhBI9ivehUrfdx3uMIjowZk+UMBhaiH4Ppazkw3F
-V7JhKm0rA9VX5HnujGmZjWymE+yVRJhR9dy0XQo+b4691Ve8Ce9L7j0j8BzCcCwA
-hTOtEKxBnion46KLgr0caDa89C1HG8QJCqQrN+HRbfj07Zs4HjJl2CuJY6ql/f1G
-lGxJYZT0FxfIst01dAdNFppD8JJ1I+PYErWdgkm1rQDkAZXEN7rwtihHj6A0EEqr
-s1ogkXzyXs05fJurUtI5/wAFEwf9Hqv0J5kyzSA3mVhSzSY1pOheiVP6pWWKCsZ6
-xLM90PWekAHsENvvF0mtoAAOS6HYKog5qDHJme7jr10wdalynSfgCDCzt1qm2dvX
-vEk69j7vqLmqAkKEir//1XaPlGKxA3EYjl4U8HxdqOhw/FApWRmJncezqeE+R+uD
-4pMugi7DLnVa90hlPvRNYfButXXS8p7dhuiCa5ebPxclvcW6F/mf6ZDwDSuhkddP
-Du7OD36ebmiD6RHJwsfn/uOz4sRG5ogYNqiB5OOkKO5zBVztgcmWc3ACzNCbykin
-DmNHnAaeiPWR3xTp8ZwNa0BDLGBX5RUsUhP57nhQr0ifllubsohJBBgRAgAJBQJF
-EGEDAhsMAAoJEKcwUpyjVaY+pVgAnjLQPFKg6QdrUiYYCQactc2Gx9OlAJ9r5x4Z
-Pk/ZgTDkz44EfZS63bJ2IA==
-=6Dub
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5D67BFFCBA1F9A39
-sub    DBE749136BF76809
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFUHdtcBCAC5xFdAcSc5qQsPkujcRdzeldrESZBo1/SfGwFV0T+lgp99QJuI
-LDwZ1OEG/lQck59J0JRdAgxlUj1um5LzNYexIJSdxRz2DffQ/z9R+hw4DF2h0fyP
-0lXPOb/sIYJyQIMaY7Rw6NJ9iiP2Q+yAd/rL34NbaelOjNy00rQkVNBixp88iZB8
-WjzHAZnCy9nz5nL7fDz6c518PaHMwVnQtt6Aza+fZ/4Na5NmKMvLC01SLFSKqV8+
-j1T0bh50vss+7rLBIYjuq024WpNdZjIUdbzsLFRZTgmv6nUKtamlDVu++qDV2tWE
-POV3OyXAPCxim2+kwVoBCsJbhFC2NMo0P28pABEBAAG5AQ0EVQd21wEIAK88nihe
-mV8Hm1g95BXaqc1UCRxXOnYT2wOmeS7nkOQlFzQNSsn6FIRCbSYUae6Q2Wv7NqvJ
-OGmiBCaKXgMSq8iEEPrbY3Ed9BTqiFtoA2smBswA2Do6SjWg9kiuXv+sRLiOMTKf
-jitErkL9Wi5CNnERoD09jICcEcMHeZbzvjslADzJz1iW4cSRmbJC+tY9Tf9LMwUe
-etTmeXYJSv2w34vxuT0zzosN9ucEElmdE1oQXQ1Ryrts4Gyv354R7+raIzEPIcGd
-4fbub+x69G5Xxy3AKI9DbVapwskME7oENwotlxzLm0or/1vVC9tOnjVh1HSd1u5T
-M4DeCQ/7wgxl8Z0AEQEAAYkBHwQYAQIACQUCVQd21wIbDAAKCRBdZ7/8uh+aOduc
-B/9wmTVaPsUtaC7+tsFBf+EM6zVsVgMe6aY8/AG1llwX1IujYRyhs8YvqD+cc9/7
-CvK3GlT2wJyBrRaiHZXE9u0COJUgBHyuIvnV0W7fE8aD5AoPCVMacKxZWoRTY4xe
-r+gde8NpAp5f2AKu8kEquXOiIymG8kXJlUqgvZmQWSFYOWF+j7Xx7iRp2+0j2f6k
-nayvHLvyvMGygvNzzhLYKl5zZMks6XMTk6daVt6WbgaSuT0le5LfpxB/k7p7xMOe
-yW0bFgNhSQMDmPJ2iTnW+iliBXOntGQda/W/uWE3LZ03Z2xTq+2SlXtDllVh6Ma2
-QaYKBnGzozJvTcMbyP/aZ3lj
-=kPmv
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D7C92B70FA1C814D
-uid    Matt Sicker (Apache Software Foundation) <mattsicker@apache.org>
-uid    Matthew Sicker (Signing Key) <mattsicker@apache.org>
-
-sub    B4C70893B62BABE8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=K7VW
------END PGP PUBLIC KEY BLOCK-----
-
-pub    10AE8966A146E8BE
-uid    Thai Duong <thaidn@google.com>
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBFrY3D4BDADSiDX16IC+236IeUiqi7Nbt2wlsBS0zqqaXi43QwXwcf7aYn4+
-qrn+4JvsyMrDgkRgOElz134B1i5OSzP/32w2JCnj90XUjO5N1KD0QqoSops7NLhZ
-/jW+5cFLDDeYPTYNLxJVsDRSqhIztRC0/m3eP0590MbnPxd+ahlj8uz4NRv/bwj1
-vqfIRDyoQOtV0+QX4M8ytX8cyLW9YynWLWMeHUFY344UztDunZrfomPC16roKXrq
-niP71cILlVFvhGhLfE4iF+Q/QZZnn6hvuQGagHR261N4LKw5II737g/5f1DsKZpu
-Mjam5juYCWobRie4fN4k0xwi2+I0KTpYMjBRTNNcOtyAb1AvY08E0HVwAYz8Cm+T
-VQQKriNpa40RI3KtDXCboCkz+LLL1w6vBXnvCes6F8CjSn3IlInpv2AE4nhcPC03
-zI56gPFHhUN+h4vm+b5H0aw8DyyedBDv/GX5sPxYYml3H12L/idpgAwp022rL8dP
-lxtvZrtO9PlOqHMAEQEAAbQeVGhhaSBEdW9uZyA8dGhhaWRuQGdvb2dsZS5jb20+
-iQHUBBMBCgA+FiEEyHQQgv8bDulryr7sEK6JZqFG6L4FAlrY3D4CGwMFCQlmAYAF
-CwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQEK6JZqFG6L5LEAv8CDTDJbAl/Rh3
-ALICi3dsXasWNQjMnG2kqDXQg/ysTPCoUphnYBTvwkEGxg+m6Bjb3ULeCJo+DIfw
-JxgLl5BNZOROeBmlX5uYZ37XYPntl/WwyGBnCF1IW6cHmdtTMwfYd6RkAFYVyFyZ
-FObeCrzdVj2knwqsZQb2Ty6BNodKV+xLCYBggT6VjNpjp1wOedn5ByQEReG9HDim
-qmVWz4pqAe5ipo9mTEwkQzZny6Mw5QHp+SRk+Yyo/NT8Q0BkGPwFpYn9YYUvda1k
-mYN41DwJBzG3m/kfwn3tmIbxCOnrmTt9x6cGuejPPsOI1VjhaJn8HMK7WOOA8DRh
-Zyi/IkZ04pdNlz6PeC7CbzvgGMgrY5Z9mIHP67GlXomOtoE2ZsUyNUBEA2QCBroC
-ktzkT6Y6IIYUe+EdQ8LdMJ+uisbPl72jmkPmnj0ssZfKkTZRTMF5mpR8a/AlRQwL
-VG5qGWHCQvsYUT/C4fNqaZKjwn53SUp6QDhrpMrv1UWhdLSWS+FI
-=YPkN
------END PGP PUBLIC KEY BLOCK-----
-
-pub    47DCFC2A59F59B5B
-uid    Kevin Wooten <kevin@wooten.com>
-
-sub    FCB1A11865F6A17A
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFVB0KABCAC8YRgcTIomAMw865DHxS/tbFgqN9i7M+tgpih1ETJbb4enhIBj
-Upeq+MoFCtxN86zGu2gsA4DOMEXVCReJ4O5n0F8E03+NUraCnJjbXLW9eEyRQRaU
-sYXDn/3SpXQyZGP0XemHUfG2Gok77mqiqbYGO5PwQoTX09X1a1wvM/GUYS8I5dUh
-UY6MwB3IEXaoNIccuNs3exm9ojmnvLO4VZuXcLOizlqxq6+8VbEP9qr06UNLsPDH
-vdqLxIUpZWSyYnUQZIrkctsUvlxQMnB/PpzAN9hKvyps6quQv8tD+dyPreT1TJGM
-ej4OcJXkQNmDxXu0/GP7X5yPsunKy3MLabutABEBAAG0H0tldmluIFdvb3RlbiA8
-a2V2aW5Ad29vdGVuLmNvbT6JATcEEwEKACEFAlVB0KACGwMFCwkIBwMFFQoJCAsF
-FgIDAQACHgECF4AACgkQR9z8Kln1m1tCNwf+MaNFqR4lezA6ebkpZ4vIKGPoCOAx
-b0zEXgKPUIsqiH3R0oYzkTqrhm85w9cwJDnPKISg/uoP6gKqJIFIwjSVWO9ESg7w
-SSXKpHZTd34XaqrBWS102btT3wi0PwRs7Bl098jgKmtFT2AhctwZfh1gULHGjHYp
-tOK4KuDch6gYoJ4h01rxMZ6vkO6IWT5rjkgl8SYbjHMsffl1/eLMpS7UvA9S6xIF
-JLxI1+/+5gg2M6VRAgMFZXujstoKOym6t/8ayZbz3HNA9Sw01vJiMYXmWoNn6Gj4
-nxxCtsorIcTW9qzGubnoDGR/DkUlux7QZrEl84A3/f4Z9SWfZ7u8aTuqsLkBDQRV
-QdCgAQgA7kQawwfOhqatOWR4JvWROpgk3TQE9QJGKOPkIlkaxTws0cyap4idMcZo
-RETVqXCpFiWcwVqwDbThQUhJx36EGn3P4mByNN2wLYw05fN4nofiuM708v7hG6SV
-2DcsYHyKXT6dc7pZDWSyCtEMv03ST93rTPaGjM+X0lj7gBgODyYLAtHcAgOuAFkD
-ZU2k1CfGWnm06QZ8Uj+EBf6fGp0sc9aySGQx9asyV6pVa+tksLuJVCsHesT7Up01
-cwtbBQsfSDh4eAuYemqNiHS0H8EI8PEozwsDdmJYtXwGyoP0rvXojv3v0pgrJgfs
-cJsyPrc7ajsWWMMP/HsPQr6DV4OcUwARAQABiQEfBBgBCgAJBQJVQdCgAhsMAAoJ
-EEfc/CpZ9ZtbLAsH/14uJWhG6mxG28lIaWqsNbv6fcRFVBK182n2ZziTZR9zvgqv
-dFZCX4mJA14JtbPV7SMl4Jt5wCcj+lrL2Zg9ywCspGXDp9gDRczYeG4uZHOUOuP1
-sF0QHtjUPCl4vrzcgo9BHx40tg83Yqkl4684Jk1GsXGmjX9krndXpYpZxjqvZEy+
-UcrlzfBwAxMiFWPbHxRaUyAlJADF87AC83CythCne8+MwnR51gNwX6VB9e5G8CJh
-KI79Ml4Nxu9bshJivTH4X1hHy1WZ4RTpYh9+QiX/mUWpESL/3MHE258/4t4kSmmZ
-uibIH78M76e5PfyVjZBdAdgcuQBYGJ0p9c7qSM4=
-=/5Qn
------END PGP PUBLIC KEY BLOCK-----
-
-pub    80C08B1C29100955
-uid    Jake Wharton <jakewharton@gmail.com>
-
-sub    CF771F914C2A4A73
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBE2fCWARBAC3v9wYo5kmynmVP+43ccamidflSLQjjpsXpSDLPFokGxeuw0OC
-QJy46m8b5ACoCqRlfwnRRcEHxiSlaBATJA6hi7NRO41R39C62JXsIxNJR16JNQ5k
-oG/NOAraw0E1RQIFslznQexfxPg4yFIVrsFp1wkpCRrCklatPMNap2DuNwCg7PWJ
-1vV93YIsaH0O2fnXz3E+6zsD/3cTzUWuySEDiCLNO3JYJm97v4NDQ93encP1Ooxh
-n+PSIP4GvjrAObh3FfWUucv8UGqcw5bAL7dA1z8SgKeyFk/afs2XofXdvC+PhZqC
-DwU0NiE0D/tDWqX0qIG4ezTU2uk+5dE/WVl3R10nOBgquQdWIdYKGfV4FNTiEduD
-Uw7fA/0XcwFom7eyR9eBonQmgIadljztm4gkv11lY33V1ZfJNndPKNzwevDwX+om
-/VEHvpEfPx5toD4H523BPx55ZtfowuMtFHZI718alpCo3h6xaDhGwXvsg3s9k03k
-rfxzCjf9qcJX1gb2JVZ2+2jCwUDQZeEwV2vivjGNiN9rShWW+7QkSmFrZSBXaGFy
-dG9uIDxqYWtld2hhcnRvbkBnbWFpbC5jb20+iGAEExECACAFAk2fCWACGwMGCwkI
-BwMCBBUCCAMEFgIDAQIeAQIXgAAKCRCAwIscKRAJVQoeAKDLeCOKKnt5aqlHD/7+
-QPOgX4iYPACgvGRCubBztEBkU2xXbr9J2cQY5em5Ag0ETZ8JYBAIALeU4dgFKEn8
-b3E1LUT25svvUUX2kuVLQ5TzokC6zjWQrPehOlsYx+ey8RSN/6A5rBLtn1z75ror
-F3+vN5kLPAz8x2Th6Cxd6lvn3DQHfvDL0YHlp0AZzhHx5ogyJxdaqwzNy0JWxava
-FGN6b8bbrR1Nf08kq/d5dNe+NGVdBXcuqUo6jt1W+tkbntklS5e+B9/Q/4L8dYkl
-8xXRIMAuKw6h8j4LFXse6xndWeWtTIkfZImz0f7cLQV5X7QSv90i1KfzT9hLiUjp
-wqPydtTNuB6+gda64jFNhVcvgW+h7MH6FT/zSss2Jh2eDR4HFrv7EJSS8dKCvPox
-y8El8pQMG/8AAwUIAIXq+ryw44voH/IdbvTQtK4t5/lp/Oj9b7QrMR3u/iQxM4K3
-dq7rUbA8hjdMM3gfMu13B4pzGtpcf25b4NIIQkhES9+CUDQDYHF+gwkrwEascbdf
-YZiLAHtcMjW1Og+IhTY8wDuJT4I1pqumSzWV8UxVJctqNUTY2eU7158oD5+prdCc
-eQLbzxoKFtu056kZ2+46v6bAl8g/w8WoVORUuHruuvKohMVPHwNQws7KHCFy9YCr
-4yIQfqC8g8oITqlgUZcZaXx6K+NndwA6LAoXJL0edaZOZBuFq5H7Fkrw07+OIQFq
-LTGcFpR12AzDh9lmtyJQ8nVfb6IjAOSwBPlEZWSISQQYEQIACQUCTZ8JYAIbDAAK
-CRCAwIscKRAJVd58AJ0YA8xv0U5Odm8u21BvyxjGS3tBZACggF6P6KjhUPpIAYTS
-6v3TtzhkJdo=
-=Zirr
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6A65176A0FB1CD0B
-uid    Paul King <paulk@apache.org>
-uid    keybase.io/paulk_asert <paulk_asert@keybase.io>
-uid    Paul King <kingp@ociweb.com>
-uid    Paul King <paulk@asert.com.au>
-uid    Paul King <paul.king.asert@gmail.com>
-
-sub    EA8543C570FAF804
-sub    CA890A5FA09CFD80
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBFgMcBMBEAC/xcIVVOOh+F7S0OTzBlFH34s5fDbi6Zto469tZyW1peyWtXAZ
-m+2jzFfeTCHaUQO3YjoTy2fPygS4tVD+ew4EAzMG5Uti4kwWZw0PYKz2JO/gl1JY
-fKpWWkpKfHsGIFkfsOX6J83J4GVpaNJBUHsmcdep8YNf1nYDGpIZCxufihQXhuuK
-x9BPm2SUdeyFwUFdxhGN4JdalxZo+x0pvQ6sKO1hQKK14YZXQxLUV043p3me9lVy
-Ubld8kcda0edx3cyhilehib3sZPVhOm8s18GmjV5/ApPnehJN7SueivB2dzzFPN7
-mUwrslti0j2DmTdOImzcz0IT7zErmiV7xtgsgP8jgKEp2LF23VFXuWsKO2yNubQP
-shNDKpYMMgJn0PfD5gwYl8FN9Yzj3OKA5wiJpgPjPl2PveZ/+rOS91bQMG1hFc3W
-v9ZWSisJAZlNQlfyv36rD12WhwQLlupLo0zPlqp7e/i5ZJBPg4unbAYECtJI5Wqj
-Ljhyd0j68QWon1Ripi8ruqXA9MUe7JMy39ZmF3/fLT4rBiHyRVpWkVKjzLlm0Ks4
-f3cNAPxn4FWeTwM+oUzEbpkNpE/swIbR05u1J2y0f+GS6X5t0CSTcHk1VIOnOiTl
-wLzSEJe9hNkBuNJjwM9Cod7dbdorq6Qwd0ffPJoTw1SVkHMPwIjikzxU7QARAQAB
-tBxQYXVsIEtpbmcgPHBhdWxrQGFwYWNoZS5vcmc+iQI0BBMBCgAeBQJYDHATAhsD
-AwsJBwMVCggCHgECF4ADFgIBAhkBAAoJEGplF2oPsc0LrzcP/3w1z7KeiwXUc7fa
-yYeoWIAXJhtYSN32BCHpfOLruDAXA5FaQmqILVzT/Uk3SYYeaapRwJ72oon4L1oB
-+HaZu8WPwKbKJZ2zJiWDWtwC1aIMoRJpykt3GHlkorXLM4bY943eBnLbFhUi7RpZ
-wfPvrlnblVfUZf+Shxq7CNSwsgaj0CLv68B41HgUgNJeDqCI3DjHQYZ+aL6Gb3kJ
-q6dj4iLFM9WfMM3j+orGuc1+nxWa4GuS26rLlT4Tm95uEA508s+hOOZmMwgFr6AZ
-eF/al46f5jSY35asIIy37IXTX3X+Igky10pEMrMo1XlKOFllyXWBvpZ5aGKgp18Z
-YCeBHXxC85I9JYNUHaAiYVdA8eiLN172dzWvOfCbkYYTvQVXApD2oA85BDjLWnsJ
-3bGERMFnJap+WokGbP/5sEcngozRq0USKlchsN9ij9EGD/AWiUiJaKzPKCKGblmM
-mg9wMR9gUakgxUYFK8HsBNG3dX5zaHRiVxSQwupH4alVSdEqhpYQ3wFFzECcGs7y
-fxT0gxS9zr5e6BauA66BYkwGcNd7ieNwvWvIMpxBQ+eub5fZ3Ndi7Ys18wiNi4kc
-754yDFES8CvapSk4wPAP7j8ua+UyhjO9g8NQlulPES8DYiE5PiW8/0fc4wP4NmAm
-dHPm5OXE31G657HGQ3tqvmdnthBOiQEcBBABAgAGBQJYcO+0AAoJEMjoVWEpccxC
-x2cH/iUYciKTNOjMas94SnLNCFZQTzxFg+cfd37i3FzKzMXJrKTobDLUVtMq92KO
-+GvLjH9eYV99p098rJ609d90QpawKofigi5UNLhYsjLH6o9Fx84MokfXRbnkEnrm
-Fa0eg8B/E1pAli/1F+BSW6anLEAI72nrSnTTTok3o8RNsoJOJdFp11vNaNTv+L0c
-4IeCALiD8c8ChO8lXCK7rHfptsya+r+VrKqi4Bpv4xuhBgJCFvHj6tUDEPa/kVhU
-wbWgXfLtZogzO3ZZKYikAiOu/Tk91lIIocOHQpYYcoIXuUhVBuqAOeHIZHOSIc1U
-izv0hAvQ+FXQX9cH2r5zUyuAFAqJAhwEEAEKAAYFAlhzTG4ACgkQelgJCIR6+eAO
-8Q/8CoOCSsWa/MeTcnQsFTGwPhPgOttjyqV9o0cdmRqS20ygW2ds3uKUe+iP78yX
-NQnt9JOtqUVtL3bIAY4qH6VZSdpBCr904/4MemrHK1UOAYkhaQuWEv6LP/kHndDX
-L4wALn+7lideZjdV1N7jLRyvSH35Hf13yz2o1K4f2Rjrr6e0QRJKTm2RcJnH+zxC
-C4K+vYY1OBn8IyMDr+sD9iMVcy53zkIHHbu0saROaLBJ+vlntvsfaOhWEqOHUx7C
-/KiJQ9VshFyndSAc32LLVIu4/P0HQpLfezZTuNoZtHEaYXRCti3KK1zsGvXbW9aP
-DRAu+FrypUiRGWCyY4hnz3ex9QSoYpa0js6o8+VFPWDuwx428as8iGcbcZ8fPtxQ
-+91YDnWACNDCZq0mYTb+cFohnBhL+/PI3waZDKMypQnT+Fcp4uMV1oN7088mzMUq
-C1yBpEbrPexccDAiTKwYt4Ie4zaAgZmyUH3sSCctyoVhmv57DA6/PXPxJn4Y6IQg
-rBcpmx/MHBmhxfhq2hwTaW2MWESMADvoG5/2ze0bl3rp8FxcYyKhEtyn0bo2JJho
-ZC9YvxXlW1uzWci+CPw6nV6TtdsStRYryweNhoi9ob5PNQxGUfvivEfsBwAmyz9D
-eJI66tzxqyJptBuuaXmIzV2QS/Vpoh2GDgh0zusc5baU6Ky0L2tleWJhc2UuaW8v
-cGF1bGtfYXNlcnQgPHBhdWxrX2FzZXJ0QGtleWJhc2UuaW8+iQI5BBMBCAAjBQJY
-DHf6AhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQamUXag+xzQswow/9
-GpjuyZMxZlpheqRv8YgpHo7cepgBC7YO7ZIphEAvelYGuIwXcMquTVN0OkNNE9iY
-c8vphvFPCHzcqweBKw25EOLzvx+DZbs5u5T6HX6MTb1Z+RNKHsP+HGlcEghcg1sS
-vT65mel3UsOjBv/cgt+8xEfRlLooJprjvlUGoT3z/mV5TLBHu2+zK0pfHgZcXC3t
-uACx2/ozO0WVD0b65UAkVf3wRP4yzha3biy1nH/sUKYOA31WooimDRlRvW+Q0TZJ
-LAv9ckdHsRG9lq2cXDn6h+jjkgbv0/jGpqziix649gjd3xB4Zbh7fEkd0+AMJOtO
-5eUkJUfEOB8PX9mz4Tvjg5995B6Y3G29Ct+pDsHv3zUT9Cvfsw4v4xz2BQa7pCv5
-+cpWvPt6hlhly1Q6wHMziSVWR+4Q0FGfGQMXXMvqa8bxEchGBFL0atCHrCopGj2N
-BcD1kzalLKS/tIw5gpgvDHGDJx9bj/D5lxvM6rPtNhAfoOMNdd7gdQcX3asxFTuk
-nSxzZKW3o1y92fejYdv/e/ScuhAwbAzoSseOodeKAe9SBn7ePz3ogSxR4Z3K0gX1
-cDBjjmETFBCigWofxXBydc/GXljaXDLtIEmo7ociU92xFaIETCmZMlT2bFGvz7TR
-DHFv7Ks3Zxn9Y9aNYBxJCHAMYa+8HO54fSYhlRMJeouJARwEEAECAAYFAlhw77QA
-CgkQyOhVYSlxzEKFDwf/St98fhr4Ngsz+mbjxjYMhmkeHuRU8+d0dMFpiJ++2cTi
-xzgce5oPFOM+mblDJuJRlS8YD+Ca+CNH60YGOUCIzEW281ZANjS2PiHFaeFKC/Sd
-olfOzUfjNdqffcGFMEZJkEgn6m0oc+MGljWwUdgglopbza7LM2A04R/VuNwUm8Ie
-irmHjBuPdJLM2VZlJdPQL+/wumXVLyT8oPPJMcaRFQyglNZw9ne5ftj6zKWRPoti
-o+RCAhjDhe6nE+G1WSHYL5GNdBH7UqHPiaL0hkzabPy960ycpGxSaOSBtRlqsqhc
-41frkjSFIf+kACgN29E8V7jw8ceg3lD05J+UBpDkSIkCHAQQAQoABgUCWHNMdQAK
-CRB6WAkIhHr54MJ1D/4/H5GkufHGm3GTtj5UfXW1Rr/SdvC5AqBpz+r66f8TUUJq
-rXBcn3V+gTITHZdheSUiL/9Gv2DsGeJ65RVBgEiya/4GgV8sjx3/tWRCa4Z7difx
-FBpjY8ZWSMD1r4rtCMANRaMZ5CF7iu+nQ7sLNoMJJYuO7C0MsF2jqUC67TFHoL5F
-N0vwMbk7yuhos/hlfhr+iklYppz3TwbKCEMSP4KfrusrSkq3LqGQJalzNT6RR47O
-LNMqG21XgWopxtyvBCsR2fJV8YUr9fUztskK3l/FCW8Qi92o8FMJpDwln5YNjy1W
-jlSJT/kFk2wG1leucpPR5M/Xf3OeSyelr4lW8hg4u72npOTQ9vfb/sZaS0IPOPuX
-A88NQVMZLbSU+OrtNrdY9AM7jKHxuwszj20wzGcx0XTAkleTHqhKL0tbfOJiq7Cu
-HLxgFOWO7+k4TB6ajMNrtr1rhkTCzjiiUT585+CC0pTtNVuonveq0ySId3bRmF64
-dl6ADFvibDUGsc7GZW/r6WU7xBI/7biykQdOs+GRtm2HrfGAVlrur+cITI4sLRx0
-D3eugxY98fz8DQ31Zw/LPNsKe23DdkHjoj07wRP7nAiRTZ2r/26Xw/rwK060Y2++
-lGVlsV2bJSNfk70jdmGddi307HyJLyFzdaq/DWc23gJlpBUeVtTiGDMjQEz+ALQc
-UGF1bCBLaW5nIDxraW5ncEBvY2l3ZWIuY29tPokCOQQTAQgAIwUCWAx33AIbAwcL
-CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheAAAoJEGplF2oPsc0LTUgP/RGmHtWXolS2
-/kzTRwovyM1w0zUd55UbmdPZY2tsd97BhUslfUGnXGLBBEaMYejeKTqDlg+EUGv9
-thQIXuB4Pt1WSvDDHWGFRS6si+VEprkU2aCJKiMK3n7Lof4Q7RAve8hK6hGlwQGk
-ApEsig4uHNY4XwvoQ/+AdjlHggJynN1JaR+ylHJWbAEcAvZMuLqxYtNX10uy7tZc
-DveAbf01VIhQSI2rMWWy1nk9nX9TdlP6cYOBdx1s6+KXoXFb66Q1t7JUP36xRXPC
-5dKl62aENoYbSiZpHJVekX2fBDT2UILT8q81UJ2SJbr8SaQVfUVNQIDrOlZCYbhP
-CvOS7cOrYET33nzsGS3rbhssp6bS+tnVz9f1fJoNigBv46I9yTpSZe4PS6nFTFSL
-l17VgeEqbjaGUs8G02wFH5V+VXcpSLSLd28v/+BDmYWh/3/RXnI2XO0qTNK9tNHH
-ADJMQ8LaVUhAKk0DCR5W4SUg9192WMQwilpI5mNfCbYIFNrnzcsNarJMsvtUzFp5
-3RbQrwt0eB3QwCDonjgMdoHO9gXenkL3WeqC9MptzrkA3m9vTAwtnFQrN00DnaIL
-J80jSJg8cWFxwfR2lHldv7kM5muC67ZMBIBiVg5dKq9+yKEbUhaTsESaHvxOO8Vx
-ko8ohMsEXyw3Pm8brQofGV+8Ck6gvoQMiQEcBBABAgAGBQJYcO+0AAoJEMjoVWEp
-ccxC3zsH/0Nm5f6zzvLRVevJAn6qIozkKCO3kfHQpyspizDvhOO6oRBnlC9/7Ejg
-+Hl2mxtPnLly3V8fE2f6DHw0hTCWHxpzdgmR/sfoqwz7OsY1/miAFDs7BCNS+HmT
-oZ3PuvkkIXjPkHjLdAq7Qlp3epSfywXaq0MfZYhexLK3s5pqAc6r5bxmGgsDvUmw
-6vUR4I2EPL7Hkq1k2deCTxaEvTv16ESlGYvNSdmWEYHwGDz1n6ZE3sBnwpqVlIrp
-rIOt/+wmOm5BFwq5w5hZ3SGZttKcJlcfwzwfV9c4+EYbnnpl/WhQZFDRn+XuI2pn
-uOqLWMAy8S59HiV6bGqUvqxQobJaenmJAhwEEAEKAAYFAlhzTHUACgkQelgJCIR6
-+eD84Q/+Kate3f4jqwRUEr6cqeqnXOL87V2sbdcKeYtwx3MX8IZ1QhSY+BquDdVG
-XIwYzEF8oKm6pNhpWH/GZ6IcHHpKyhnCP27LDJQiH0cVfZkyzyg/Ae47uPNxPZl+
-ElC63jESvM9rbkEQPxlbhEWEZYL4+HbUGeIztjhccOzo6r92J0BkbBdnV2k7vZkW
-ZDy5zUkMhIyvn09/McaeZfL7MU1V1l+oSG6xQrmU0GheL8F7EMDo8g9m1sP9nqZ/
-4iMSJJdyLlnCz751ZH8yjfK0D7ouMo0QAIRZICgaboPSW4mG5kzQuaqiUHoQwm0i
-1aB7ZX3W5SStkH+GlChpFxaUutEKRsAWn6CUa/upXjZ6M9cpqiuDBLETNgcZhx8C
-Gf7Fake9yg1hq02kV7mSNfpjW8mfj6jvyJ/H7QO0U36ztNqg8VS2WfI0K3EXggCS
-UGKOp4SA6wST+aBe9Zlk+WCEZRFlRBuBE7xFcvpRUSn0Myvmi9iyyxncGjgz9f/z
-rgLWFwNXIjudHEFE0OxlzxQFay3qclLc7uJgRfmr5rURSPBLLdPVRU847CSWZYzc
-9ehIbsBFCesTiiTFdKFTCPah47JBuXTwDiHMMzW3NoGceihYB8MnaFD1e7mz2Ovl
-DpbUs2c4lF0gCSsALBsAsMHY0dqQJhLWN1hslgALz2KzzSP+fBG0HlBhdWwgS2lu
-ZyA8cGF1bGtAYXNlcnQuY29tLmF1PokCMQQTAQoAGwUCWAxwEwIbAwMLCQcDFQoI
-Ah4BAheAAxYCAQAKCRBqZRdqD7HNC0rxD/9AMTbcAybUWuoHznDgjKOl4OmW5LAe
-PiKW/nz4AsZHM/+/s4gqoO9ugydRCK9ZVMYNR4ukU1HcgyPaJuUW1jAc40p/eACR
-+f51X5rT4Mv976FvCCzP0IdmTilQUubh0RGEFfPK9FtrTplmqQoDf7ehDo2Tmt71
-V0P12LUBj5yx35DZBjjvV42wQzfi68oNaJDqKE7xGax8zOPI1/djyEtuTe/NX+/j
-XG8DP5hGLo305JZKytQKXeVW3fW0/3VEJ+YvVKEuvpoupy8cVYov8NVfs8YRRNwi
-ctRZEB6/q/RB7yin03rvbhN5zVHWMlseJAPooTNK27zxO28rlv55wZoK0NRDDJiB
-GEtF8bCCmdiBQaQdJuHZDfsCbvxL5HPmkUuGW8xbn7+FmW/X3T3VIzR5UNdJRh5A
-m1nvkdo9tM34c5wOk29VTzdgbN/1g9FvRdZMBGvKrQ45FM5pPi9Oux6HArEbRhaW
-UFqNXEatTZtGo+cTj6J8K5Qh1r+GtbeAQvCgq8WF8SY9S4j0vO/TnHYP+Ll+CT7D
-FKQlvHahTetfI8td2xH5Co6RkWLeUF4Z51H0lANZwi0KFI5FDM+rhdD8HKr40b8I
-/+tublwOXUHm71ltI5eDTxEgkK8a3Ii2zieXwsGGY4TK8XrhXbM3TV46hRwlv4lY
-YMIlOK2KZblXSIkBHAQQAQIABgUCWHDvtAAKCRDI6FVhKXHMQhPDB/9/9Ir91uzh
-us7NH1PH/QPx5K9TvaxE7hMfrz23CmxMN8W5yYFu5ra8roxTYRmyc1FdFRA9gM6u
-9tL4GjHpp+fd0Xgep0NcQ1Almcy6I8HgpDNQp5F712gbEYKMSup8dHT8+IBnFXHr
-YW5eIAGuaOYt0477cGQSDXbPhATd3PtLada5T+VNQNEsbMNjtXzr/XqVqOzsSD1Y
-jKmE9+eec2uFxCvMA8STBLkY8ScGD1b3Kjy3yEPwIkBKHyEFcIObPq4GRiRe+M3E
-Yg6xwNEe3tDFxlL8HKWW61YHm5b6ulIeUEfkKYIWuTMJUQVL9vgfZVZSIeaArlL+
-fRTZEfHGGooEiQIcBBABCgAGBQJYc0x1AAoJEHpYCQiEevngRdIP/1T3/aBsFgC4
-Bi6haOIbYsgdubjMHRZjvVwrer9odsQDs+84ntAad3ToN4QmwOnhjnh2vzDHALqR
-ICr9C23gKSRiW9k6WxAhdNOuO/ktFI5OOE17HPU32x2Jv+AMd+jgolYNIo3P5usB
-KACFTB8rsYLFXXwMuOuwbZ34+xmOnNoRCVcBxOhTiFUoNwoI7Q6ZHDmkiTa9vPI4
-UkshJA+bDLPK1b5aZXv55EZ/tHl/at1npT1lJCVAA6RXqIeapwtNxxOemNRihtvz
-gzO0SEpZfUfjOTnCEfMHEVlbAjSuT8i/uM7j0PK9OTS4sqGrBDEJ71GfIn//diNZ
-5WxVQpj6jqIMabfDC7sscVbmVJTrvqVHcs9VtrPnpnCvUZ2kBBAHvbU/SN2wjLsf
-fSOX3TSsROzw78geVDdTLIHH2mb3qlKsOupGvdkNvKGPs/WNwUjZqqZmNZzgSSf7
-4QH9eXoJZTOAuFmJ9Ja69x+19XR0uEjCl7stxAPFa0yag2c3a5x0AhQ1TkgjdjqF
-d34dW7GpQgwDqAL/CDGA08ma0WyP/sxq/ppgUfThakOu8JQHqHsK4SymwqAaLa8c
-/NwQu2a0lxZPLbvhK+A2hqX+Z3j/7HuYFektxCmFSF/sPOEBx/yJIbTEqhwOempc
-mTQfg8PvUHIBUKgltzQjn9WqzH804IqvtCVQYXVsIEtpbmcgPHBhdWwua2luZy5h
-c2VydEBnbWFpbC5jb20+iQIxBBMBCgAbBQJYDHATAhsDAwsJBwMVCggCHgECF4AD
-FgIBAAoJEGplF2oPsc0LHJkP/1dBsfR9T/mp901Z5BvhLfY7lQpA1sALRtWaUgx0
-Sw1ewrjHlzipFXB6OWTwVemZzifDFk/sechnRiC6QYk9vG+hc/CLhq8OllMM6l5V
-tyjKUjqMMu9ie4e72/YyosH3p1GrWpg6oxL09VzCjtKT8lYn9fQBHKXzTtVPnwkI
-DdD3K856UaSQy8NTJPkzfZOkkCsY/Yx7cgxStOU2WDspdqq7rs7P+xz5t9Vgj3GE
-8ynZthNrF8Qb6F4o7Vv80i1dktK5a27OBIjIrXTHryZdQuNJYC2yKRRuD+Us99wZ
-SJZhQCVIJSdIv85Pt9420+bgHwX5nSQkn9MzEh5nh8rgFiBKFYku7VpcrwR6Hr1M
-qik1aaEP1f0vufBcfhsEubqiIoA2Ik204dBGwzrmFPV5lHZ8j2bg6QHoSVQIe38T
-cIRMjJm4TS/FqnVLnf5B2pcpl8uYFPLFynNlqEgSxTfvGRw8Grs4cuA4RfRBX8vP
-idkWG4g1SDAhcs8UDI/QfPvqqNDxsDePSnrAr3BQN5cH4CsMQv0TVWr0aE5dBxKS
-dbND1HV2k1jikGVK/SZFTjdzWgMxzSU2j/gStTbKPVXrBykpLmYXSCVh03WNooUr
-hlq00v79enF1GpDxEV4fbHGUhLdPh3y24CkRt7gkm5LbaYBDuxqSHR8oAZpofthB
-QQDIiQEcBBABAgAGBQJYcO+0AAoJEMjoVWEpccxCyhkIAI8wL37reQe7T9M38XG7
-RxQCzn3TCpx9MGprEhSaC8Iwt5Wl1BKFyLrypQE8fYRhktkaraubEz+GjfVmHpWQ
-62AQ+HwPSh1MsvR/ZUgluIOPPs1aXJF30mBMlfP4gZ4H0CjGHT+inUsEU9axETTu
-THXCaN+BjYHv21zyewSdkU+8r9gsiLvqQnOT8xJrRXJoQl9DFRVOS/hH+VJLv306
-dfowzONAf0ToRaNaoaZ8vq7boov96U5lBIhuX4WJi6PuS9U8wvsRYg3XYhTSY0nC
-JrjJcWJMBZtAnJJAjf27wNGbT1CuLNMOpXzu1xYstujFyqzRo/iN+dOlqB39EleJ
-NSuJAhwEEAEKAAYFAlhzTHUACgkQelgJCIR6+eDZmg/9EL3qCgBf5wQc65uky7Ut
-IXaBeMmM8Wj7ZwN097ioF6AU2369smmU0kjmBDQtlFIxP0026HYTa38WtHQ5ossC
-Z0F7NdncjZXPH3DyyP/2mSotdBhORtZXjKWp547fpT1hX1/VnXxRU7uZpBgMDi82
-aPSEK66qYLUmCv1yWGvRl7y5mezj0UH5ZthOCKsFFJBVJ5AbOyRglHyGck1BxoIv
-wXUGK5IIfBMgrPSdKIeb/2bkpIdcOxZphP770pBbcF1sCnNPcXNxRsLxHlWhgS4e
-zq4OSzX87u49rKcS9Vd26vTVOHdc94My1n3pe6TuG0tkGnOwNLabSioLVX2V0Iuk
-LUThal1kpaW28nleNSwu5MeU7TT58OIvjzZuj6rDzwmBna7bV6eipe/FHIXYGo/q
-u5ls5tIUdzdeMx6PQqaXfSbr4Vm8OgcWgNxQpMMA3CtjIlK3ExpyHenoaBT0Cqvs
-LJEum1Ee/6jEvZ9Go2+kOabYwdOa50hqdf0C4urxox0AiHiYE1lrHEiH/yo9jhMJ
-0E1YFboRyVgSU+ZvuNZF8ZXmZUVFuKN3n4A2tgFUFDkT2erBPxdUi0/pg/A+cpzE
-+IQjCsURlX+zeko+7v735mil/tnmP9/h4dDDa2nPh/zKCRrJEYm526GsX/ejZseP
-lWDb7QYtk0aPkBUnAds6U+C5AQ0EWAxwEwEIAJILxPHY3dmmmonTcC4MmsE5w0lT
-3TddOnmXfuUGXQmI0IM/j7KCQJNTLPT8rlgpBgl/K5WYzmrTJ2qFDryeauaXGq8X
-FEi6DlWpoTtVaGSzI0A5E63EaL0ujoC6Qofa8rnZWHW6pE+Yrjiq0HX5uTwMTVge
-6G3TRcHUDC7iiMi3dYq5Gkz+hJh9uyiXzZ0+3VekO83V63ZvF432pFuUKnu7zc1G
-Z28AaIExERLrJXqfxdalAVORFh/vDJWuiY7PP2bzV1YBbkmzlAi+HcYxsUxL7Zud
-P45UiucK0kLDRO9NffFnHIwS5oK9gicJkD3Z+uakfAkxdq7v/W7XbO4ct+UAEQEA
-AYkDRAQYAQoADwUCWAxwEwUJDwmcAAIbIgEpCRBqZRdqD7HNC8BdIAQZAQoABgUC
-WAxwEwAKCRDqhUPFcPr4BCZEB/9T4GiPb/btnfXSPXjm4+GHzDXX1dzBWoKmBIBT
-DJzBA1ZSPBs3Zxs+0dylG6nvHhc09cpXXJgiE1UWIvusOLVmT9mYi88Yh200MkHJ
-yu1Kyq36kNHLIXey0G9b7cK+hBMkEfds1kJlk0UO/Sy480VqWrPDUJIj/RB0/x8v
-uTMYnUYBcP9dUMo83LVWgLOl74kBtQpoNX0OVYCecZ2WIs2x/UoVExeDWsLod8Er
-BbbdcRj97ILwStHmnEb0f+xK/7O+ySz96nHrepfNSc231PBHJCR+RkYJOb8Oh3+5
-WMzkGlO2axLzzELobhqlARdvNXydo3KTeY8kxhxWtYOT3pIfPncP/i4X9v+DgSkh
-HuHc71kKUKiBetGuCVAFjZS3DDNKNvRyjJmAXmKAFnkTri4yu3+QYEwuZUeTBSXx
-h1CZCtLqO7yWtOt3/teH0sf8w7FcExlpfD79k9ysfdpAVKi1wvYJeYE2+/g6yit2
-ImhN6gggWj5j/xXI6CtTg90b0wL+M3L7rU1wHdXN7IDqvpwu7z7sNeMGLLgzUnAR
-xGjdWl6G4nJM+xW9DwdOCAYS+vGqa/8L7h8B10Hl7xKk8uzuvnCsGyD6IqkKUGMM
-FUWnZIiDYaP1OihCGGVNLWzvsfGWdPdf2bu27DDSi4+NtVv3yeQSa54EC0QRqjrp
-irE1d1YfXRQqiHF5m94JCDMdp8iIOe/Ygt3FzpzGvnDqMSe1t3Q6kgL5X7eX315n
-gnLmvWkZlgSwDcDMDcZ51gtRYY2kNAIhVM+OHN5sAp3dUEiXI98y0dh+uGED6spz
-io+XhI2rKl9TTGvUy4e9vYJTrBhgBKh5B9yp3FvRA3GqmV9L4M5QLGi16OjhhZtG
-wLQSg2/xiSktqGGUhBmNrCuZpm1FOhvTsgqDtKw7Y73R40ncwuF/8BR8bVETQZ8f
-KjnBafyjDB2oReaf1x128DiCqzxsUFX5meBYq4XnzHAe/p3f2eg6iPzkN0QGi33A
-560aWMAoMEwYJdYzmVemU54z6gWzQUL8uQENBFgMcBMBCADbdP0cslUGpTkw26Wg
-Dwoq/1IuhLHRZhnri4OkyKsuscgmdNomOpeHh0zzcYZwzz+Hpvt/4x4fOEGp9NTv
-LCQf6OAEm4owJbz8BYpGifBof6CnPhTuZFMAHIo+H/HbYHZJxipcqARahHX88wBI
-kpV9Bu24qq6g/pkemDN3hWwU0Sn2VcJ8ETIzSDfJ9hVFKbzCnBnt79+Bi/e3vaoP
-hDCAWekicXSmjLbwHymAelxt1CJpQUHWEKEvDoyiY6B+TOzUWPKm/r9PDOc/eM/n
-Wdphees6VnCJaHGCE+HlYv9ifIbcpIMSAQVojT38mC6yt69oexrUvtHtjG8IYVIp
-ozhpABEBAAGJA0QEGAEKAA8FAlgMcBMFCQ8JnAACGwwBKQkQamUXag+xzQvAXSAE
-GQEKAAYFAlgMcBMACgkQyokKX6Cc/YA5TAgAl5h5XUOfyQ1VAr3Dsrom0MUEO0JN
-/Cj8uH58yhkcUAigDhdnkAu2GtpMgz3/XkeXQh8vRZrFdoePy5/YYflksc2Pc5hR
-f0CGYKtr8RQkKmjBpdppJcVVTIK4Azkgx9KkdGmyWeFmUENn2CD3/xRsETOff0PE
-0QQHq4ArUEsiqgf3YgJHibuZUIPl0bmTvfDHtmLqZKTxnv97OLgOIXOegkE6wDFJ
-3RC9KUQoLLVObTI+H8xwA1KXYFyaitU8TMQM+Hl05bxoD+h33Hud0dUqOTTWG8rN
-nid9Ne594nGal+kqkNVcEXlu85iUxeU9AqnAlIXh31Ksl1rsUmdPJDtoR92hD/40
-ZpM9N+E0s9AZ+tJKOZyxf+ZTx+jpvL3U7JoLmCGQg4XzlKX0A0n7ExvricAD8gfh
-76qpwTVg5e8UZS9sPhgRl/d7BTigZS3L+IbyUlRL5kG0wIMzoM6woMhfdQ3qhoDI
-Y5QJig9odPE7UuVn/WTSYK077kZz6Ct7RsNM/CR8D66lDKUB38nKhcXbyy/WfPmw
-NuHRShr3qw0QqwIcoEA8sWmOlbgHBnI2ulCV4qpWwSBOvsFZASCAqlslqcfXLHz0
-t8wCyiqNCY73SC/aTXsnbbNWgR6bFM6Yn2/8m+ihGl187yCBgf88o5EzJXiFMQyG
-0x2/rJJvbvBZpNqNBcKG116cFnFP8KOCj6FfuClaqZjj7KHnX4QlUW+Y0Iw8E5ph
-1Y7s1hbRoCzcLeyqRgzUKOX13rj8aNdGkiX84TM5xrc6H/QjfmkO3BcKG1Khto/p
-YMzMrKAREAxIQ2x8AhaXZVEmgmjys1IBb/mWTajhZhPDDlWaxdE8YsgryrdXIDVg
-sgiW1KorJoMy62HNL1bhc3S0ifOPqIxNuWXkFH2GK+fWtr/A7DsnWyWEGk+d5CkG
-oxjJp6kyI6lyfkUmZRfMgmSDxBx1nq25Or9reT4VOK7Kd1ckrLDP3fcmXBpPDlGO
-sOpznL6YLU4JiwHgbHheWdSmNH2JWMfWgwvQfmLUfg==
-=Wk+k
------END PGP PUBLIC KEY BLOCK-----
-
-pub    4B1E11D5A4B91E89
-uid    Adam Cozzette <acozzette@google.com>
-
-sub    726F4E5C34CFD750
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-psR8R04jHL/ZAxrodA4Awc3BTpNxQDPfdRPc8w==
-=8STR
------END PGP PUBLIC KEY BLOCK-----
-
 pub    CC6346F2CE3872D9
 uid    Jisi Liu <liujisi@google.com>
 
@@ -4045,1335 +2597,20 @@
 hOBjAbTGc2RjcuhueFse68NNCUUEzS+7pGWSpkwo5CsLyfbaCJUiSNIC06ygkY6R
 XCDZUFXI7jxfcReVMK+Wpoyk/RqY++xGmCf6MWJqkcKbn9G31fy0arHWnmaMNUUi
 rwGGzEVggMH+sbXKsLvRWr44fA/cKf+EbZ29ABEBAAG0HUppc2kgTGl1IDxsaXVq
-aXNpQGdvb2dsZS5jb20+iQE4BBMBAgAiBQJUSEMhAhsDBgsJCAcDAgYVCAIJCgsE
-FgIDAQIeAQIXgAAKCRDMY0byzjhy2UUPCADOIICATGIaZb2wnFpgXIq+3zOHutZW
-M+zmXXw5YUK6s5mRZycr90neciis8g31wTFa3832VHbJHEoLni8C1hERg4rvVrqU
-Q4y7iBEoGhKn/lgBCjImRfpYlhKtd5mmEXye2iz5EQ+VRHQWxOy3cG6TesBBpD9A
-Tya9BCSaUbc7UkGTRwhqNyX5+oeGwhoUrn4bOL+JQVATEMDskgAx0h3pIWMbhmZh
-XuKRVMxVgcPRbTFUiqDMl0uNUJwuFvvEorAGGVvEDh2Bws8CaY308b2EzF1tt9I1
-oOuqQh49JScg18aJU/h8n9x2lkzJhbobdmmvICQ+FClS4CpK5X89M8dduQENBFRI
-QyEBCADsdI8kpJKcdOgZjPwpp7xnWhaxWJ4JYVCB8Omr6ToEAaw3dWqkYfmTQwlO
-i2oBRKUnxgc+VBo/+mKOz18BIQUduM6kPjp/Hbas+uF0vKjbYKY/aLASRKR7drwp
-mphuZqibQr894HsVqXHJXwBN7/PUoAfsjVhcuZDtz+A1YJi+6D4I5kB4gBdk+fjh
-mqoapUhgDQ1RZPYzjko7UH7cMkQkHBCj1HmlPKU6MlZbvQn/p5lbIL7WuTuNI3jy
-jiWp0lLkblWgTyEY7MJvFH9s2bpPWjkxcx2+lBG2HAmXiOgRWmZSrrcX9+a2/Nb1
-5+2pMg/8ZI1bSw3lju5V/ozQ9pCRABEBAAGJAR8EGAECAAkFAlRIQyECGwwACgkQ
-zGNG8s44ctkKkQf9GAw6vtfuksg9BhVP1oyAqVwEDrQ7L5Bt1SB3iZbMcs455nY3
-YFD+0N4yPIIsYg+K0JaHr3PzHBaZjGFh3pD+tV7cuMXq/HkW+82Ogvn3onHWCfiG
-Yvl+ZBLlN9C52EGbIjx07vnjJoDXPHpeUeLEaKn3R7ijMP67/mfKYKUlZ/9uMRcJ
-Jt+HJXwaSaQgyGRDT37wmUCBUE9X0XaNKXYlZA7kn7jfpDBy/IaqcNOxe32yum/c
-4MpmcKGOFdm5Tr48TgdbDu75FT2tNsb/VtD6OFFaX7GjQB1CX64SCeuT9sDmqXsf
-uup3aw/ff+A7vCNFbhwiMUCJgH0aXV+A/bgZ3w==
-=ll74
------END PGP PUBLIC KEY BLOCK-----
-
-pub    41321490758AAD6F
-uid    Groovy Operator (Groovy Language Continuous Integration Server) <ci@groovy-lang.org>
-
-sub    01F3A913FB698736
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-ZIY=
-=83HN
------END PGP PUBLIC KEY BLOCK-----
-
-pub    205C8673DC742C7C
-uid    Brian E Fox (CODE SIGNING KEY) <brianf@apache.org>
-
-sub    AD9CEBA0521B1945
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-hfxMZo//jMG5FUu/pIWz5aHxQUjBv7phbwxwKvQAB7q4eYIPG6ZabYTQJDIweq3S
-q0XJaY1DxbHet+O4PKHUu+p0fjLabGTwENN8fnzI1adO6mKDrn3LcdZmPj9m1KkK
-2hslY7P8q5jz1AjAsVlSMWQoLwqfwj4ZqPnvUDeR1YivXnFf5jYkmX5rrzOHuSpk
-i5K7fKT30hwLE8Ew1Fn7LftldGWIi7U/T+IUlCDUgF6CxBKMjXCDtAic2dYo62aY
-WimcJC2KNWsj41+Iq+auUBdbIB4uHkROm0/V08OhQNSrHx7piQQcBBABCAAGBQJK
-/hroAAoJEIqviNbYTkGuiecf/0ZxYsoCsaUtkmLHhIeaB+VSgsGQRzQJExLyUi58
-i8c91+FXYykabOCzsQlIN3hhqDI0s7rQUJQTGoFWgwdVWRWpAhklidEFGx4wS9wN
-9twIiY+xgdwQkQ4/hf//////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////+JAn4EEAECAGgFAksM
-3mcgHFNhbmRlciBUZW1tZSA8c2FuZGVyQHRlbW1lLm5ldD4iHFNhbmRlciBUZW1t
-ZSA8c2N0ZW1tZUBhcGFjaGUub3JnPh0cU2FuZGVyIFRlbW1lIDxzYW5kZXJAbWUu
-Y29tPgAKCRCbuGOw9Ru4ikI8D/9vWt/TfpmUErEq+Md9F0MZqJ2H+y/nJJMviUDH
-Hx+po2etYJauhw5Ota6brkLjef1cNRWQ4tDxctQRPc8SsU05/Epzrdov5SWVutcw
-vmAjWSUs2wKp7/+lPuFUvEd7g4xt8gXY+mmvo8qi8tTNE+nfzaU7I0MHIMbN25P2
-b6//+Po1ifLVFE+S9fq6NbXI0QvuVBKCCmzVvA4VTVNaCd2CQCrZA+6c5VuFJBZK
-VoCW2FThDvXyQYlQAZmE3zYAZDjNFU+jAYF6aqY0dtU6wh+U1c1qbpLhrdn073pT
-HsfNsQW1vyzYLLr7QxkU9pVpFJ5Ajq41NwyU6xxSZhnJN+7TOYcJ17EnDKmdO7Mb
-52nn0zvxG2bactz+ycWwZrIxfQo9RAxyor9shORfPmEoVbsLOdfuoJxvb3OL8mI7
-wcTTfsSoPeqac2p7NS5ZWaDenliNrVR5ZWJFQeeoll/paBampGjK5En/QpIEoct4
-p3KnVTusFSsZdRnNkOFCKPUusbiQPl7dga17oiIqhpsLewq7BnQ9oW8h5jO0TuJ7
-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
-y+5xrNg+uv6po4Jjtidfww==
-=uA5H
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1DA784CCB5C46DD5
-uid    Rafael Winterhalter <rafael.wth@gmail.com>
-
-sub    7999BEFBA1039E8B
-sub    A7E989B0634097AC
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBF3Ep5QBEADZfs6o1IpZbZ1qlBkoJ7oWL0vFCcdPUgF/PRFXWKlsuFHVVV/N
-oZF9SDiCJxfvsVXmI+IHTVMR2SszU2xDF2SlScRfZQwrLhBsDP9nv9N1eGIoA5Ny
-e3WOxOwAvMuPowP+jdGMP7sC5PhdLRYfqalHQWjdqE/pvAEozIgLe3Bc/CoEee1/
-TGCaclFrYTPJz09tdD2knvuY95F6WAKpJ8M7Msf0sdQkAf4yStZ3IWPeL9WVgp9w
-0T5cQvi6FQ7mQ8adtYBe6enHbYG7yXqzO/Qf1ok9tgzS+71T017JauiWTSbxXwnP
-rBWvrOWv9LnJC4hHyne8MvcyLC6qDe4NVaGyL1uHdTXe6inReykus+uNYkWqIPHO
-Xk+hg/ESwbVCRCZbV88txLrj9Zzg2BSkVoUJ77HCbKuxWeV+v6ITbtJg1sJJBf0Y
-wZRdGMvEt7nRCtEMb75RiMmrwWtCqz2DWLRByNvaEmw6J1W94HLoh3C9Pw0pqoKN
-ZafLc4+NONHm8bQIzn6BhoN0ZjMmEBvLM6apA8AkV06noo5ET26VxoJze5MerO2Z
-lrSLUBHIdgUmwztCep8AdqE38v9G3ie8qMgRLq8gePIdQdegva/urmb6Y5A16gFE
-3/vTI3M9UbAaRy7oXwO6Qw7O+AD4etiuODW4NP9vDnRHV4ihlvDdwadY8wARAQAB
-tCpSYWZhZWwgV2ludGVyaGFsdGVyIDxyYWZhZWwud3RoQGdtYWlsLmNvbT6JAk4E
-EwEKADgWIQS0rIzcFBrwrkaNFpIdp4TMtcRt1QUCXcSnlAIbAwULCQgHAgYVCgkI
-CwIEFgIDAQIeAQIXgAAKCRAdp4TMtcRt1Vc6D/9JpwQateJdJJ6PeOgPKNh5O5F9
-Kg6QbmOVIBfAS4PNVFKO+M7POrRJXi+GN9AqARB/4juxGxd/DnF5KRss8kNScUg/
-A8Lkbkly1C4GBKrHd2m2+tJxqStXfy/rDitC6KOCXM/5AJ8qVridgFjpgcLLQ9x/
-gG+X20f50gPadhmYiLus4pgdRCPFUa+GdjcjgICb/q4fJUiyaCLRcA/0HsR6wHqp
-F/lY/gO9LfPHYyGuXKjhZVIr29QWn6dvhe3pxmiA1XQNxLBUzw3Z4rgg2h9r3ZdF
-JnZreTuciyeWMOie+DentPHjn5UchBkVi4nN8hltPUGeXso5scrwtDxr5z5Tv4QD
-h6JKjADZ28+1ZMvR9xA4Yv9emlXSSmg+Z0VM/mg9TszWqEvBUmfBp3iE2TSeID7w
-MyZ6DoLtjJeeJ4TG5vtgd8TOwZMPXOdVH6UqCBpKBl7+/KvMvZxqyQSqjPpi7z1+
-FBvMTCFhpSBZs5CtDLXUKxVXKVnzNOsXOZgEB/Mclhy4tWjOlnGAuWCm258s8hro
-a48rZemyLunkwpzJRbaGNxNfRLMbBHj7Eti3cDuWgcuFCr8JDcetoXhZdFZk2em+
-YN7FpPZ/nuZVRu+TXAfYHfFD1DpNXzo2x2LMakNNXkpw7UT6lmYeiixDs+JHJqgB
-yFG5drBimAyqP0QWXrkCDQRdxVMvARAA1fVQF8Npv0OtT2G2KS5a369FYmbnQIsj
-oe+Wy3GcvkZDtenPRIryk9OJ0gNrJSiKA2wHIHzVCRIEU28vtN+0jSIdAn8KimUu
-z9IB1V3+w3jRoT9MfnhAMyRygrAb6LpwaGbhceGNSWjR5JjxXR/EJWY2sAQTMHhA
-TfAPZ1Tati6c2RjTDSF0p/7DxHPslLp2ocUwIrhA1ADz18c8Nl1YjGQvMnDNjCbw
-g8V1XRGt2HQoIMmtUZ+jvQ95e55aFpIQD3JkK1+mD9E8p/BJHr1zkbVQJ3dKhSlX
-5uUxr4XS489Bqnx3mLjlV4OyFF5DZb1k2GboPSwFvZoJ1ReFvz/go4IxWpf6yS9o
-DrklFQKbKEuVzh9H43Q8HwmV+1bwkvn44ztV3Vvn7ABRMZZcAEai1HuAqX6uHgJf
-KQtj3T4f2VRcmItqoViEopvat5O1TsZdJCR+vCeo+O1g4dxRIMaSdofYKEdWQZMX
-JEjfEjFwmOa4UnIYbXaqPwn7u/XvB356TkvJ/MvuO8dOTIns1nrVH3h8HOb4SE3N
-0HI7q11K7P4LmmqPknbtCbZ9u/7PcHRmo4yk0NQOop71VKXwn6HWixQnVQxszggb
-cAMpJjwZNLE80QF/Ot6A0Ka6uxoUUHg0AOpCMtCo22mHNGJks3bD3YW84VBs20/y
-qfB2SCCizekAEQEAAYkEPgQYAQIACQUCXcVTLwIbAgIpCRAdp4TMtcRt1cFdIAQZ
-AQIABgUCXcVTLwAKCRB5mb77oQOei/rkEAC2NCm0bUbEgTri3W7sFXnM2onXK0hX
-+Ng9HOdYY/AZ93NhPOSONLCkTyJbJ2+WmS2lrTs6SNRZjwMwI3nVpgi68vOaa1GV
-r4SkGP+ZjmYx+FZkTuZHTQm5c6qJGHB8/7UwPdGtemT54ku5gyviB8icmSVx0jGF
-WogyxExswHPBS/O47lnWMr7btHFeQeqLrvsxOKpv0qSFsysEsmFdfZlCE4aCh/Or
-WbZlQPqPDOOTQxaHiodgQBrRYetU0nw2P5oOUQEg6Zopx8tMAyUQGAz023TIQafb
-AsnrYY1hcd05YVowialM48g1i34XBmUR9MOALhWzbcCR2oY/52jSOyrovpUOj4X9
-kJdItqKtFXAtsyeuX6EZB5NsqOWUm1sFv/+AZlh1yH7GrXSsy3265oIcLjAmcTTp
-9w8hiefmESmo7IeZ1iTccwz/cyEX+KDJjfx2OPbcnhquDcgTlmNJpaCsxOpp1ye/
-KQykw/FC5KQXDGs6JUd0ij0oj3KfvmqNmG2vhGuDJQMrBDeYe1i8d/Tj8iZtWtnp
-r5dpoBLA0dEwYlHuzz6kzJ9xml1lESI5F8t7m9mabMwEKsN8vmbv8MXoOgsUG8za
-XKCelw00v72hjUf5ITYP0GuLN3S8I+pBo6cJSc364xIMm3kux13n9Qb4Vz0iWsfh
-1C8pqYAaNGqzAp8vEADY95jo1reyExY1NnVTPxZjwOgbAkAfRSrV1UXG1jFFgPXg
-ttoegj47E9iauPdvHQBdFx3/KwHBf+miDeMqIGc4TGyUx6HBtfTFtdUOfVYTbdg4
-3jMJ7IMtEq/d9eTyihxRIEVYzOMDENTfPorr/EvZ52XBAOGLP7gYTc++m7cbHILK
-eGbhpU39NRoTzCrimtn4rAljjFFtY4bRPPKAspsAy1KOhFA6BoQSz6ri7cd/y/wL
-MAmBEkmquwqRpzvrdnJGw0Nc6GNVDdfMQT412W/cUR45VmUpx638J+UczeNQVrAX
-8qeq4bUKSqts+F25F/yF1LK33fjvfyBAQwsu8KLSpRYXBX/M35Nd+lWX03hKWRk9
-M4TlnevSvbsOX8K49aNkpxCLeB3X6j3ouzVmuYq3rJFcgiktxLn/YzodQnzys36U
-hCTk//3t9IPHaGVDvOgXV70Jh6ovtoKmnuwUnsx0O7dZxUnOYMBlVV7whunI/UeR
-hwkk8ySY7ejAoVa5/b1vwDfEnTFYI3et3TPX6jxaEcEiswMXVb4xpnvIq3CqDkrB
-JLxZ4tPGPpdoz9M5L+s53EQ1QfQZpNXk/ykM9Li1MIjfiK3wur3TX6XiscOjvQhR
-Tl+2fsh0TmOrGV1OMBWYEBmx2GX8J8CxcxZIhgBM0v+Z7E3aOJl4MjI84KzZx7kC
-DQRdxKeUARAAx7iVYVeV/+nxLuOnqizUP13p8rxTKXRGIhA06uEZZiXILc8xtJov
-G38xnQE+qBR/qa3E1OLAvWPkfFKyzNfySI9q8ZLe6yRFwHdWig0gREGVqI1pVcNn
-l51hQ2j4fCeXOqzr06XmoLjHIZ4cJxAZHzmpNkMypFHGf9e/f6WGVCTdf5iRzTe6
-evb/Lo1cAuC5w92EH8E2ztFCoS/dsfVsPn/N+tfoOmOTXH73BJrvGtid8zrCqSNk
-xWRpD7zTkye3tF1ICJ9lAFvVjvFHeIyLheP7VBhQilPm9jZZ1h4iAZJK1pUFd0CK
-5fftXYsY/ptOf+Lb9fUNCxQj4tHbVIDBkctDPCCfPlNM2nP0X2DaYO9S0wFXVrd7
-icmr1H7eHZySZzdXjVZynh1FoqVrrBb1A6k1DcTaB7KNgKknJvXWwrkya4KgG8YY
-z3enBDwCMhmKED+EuhLduU+ukQoIqEwsDHkCV0Louy3i/OUJ0A7M61WH1BWbH8E+
-YZqb+e68tBVpgtipSfrqEndKybEPW6abvrNtel0ihLEYgk/6csv7Liz29bA6H5NO
-a8LWbNIKzgf4c8CPuSWQ0vUQiOL9EVDhsHVG8jUcfaebT52svK767wJmYx5wOAfH
-y5itrRhpuPpWk63Kn8FN+SZ+yErZhT31kFbtHF2FNFJMSwav+X20b/8AEQEAAYkC
-NgQYAQoAIBYhBLSsjNwUGvCuRo0Wkh2nhMy1xG3VBQJdxKeUAhsMAAoJEB2nhMy1
-xG3Vf60QAKzmfy1aK/eBpU4HIwKxyEbAk6D+Pa6iSMKLXqzXzRs1V6s5lo+FNppQ
-LZL7zDS6C/WCHhGaoI8ivEORiUNGBjOoXjUHnaYG/VJJ8GXOXqOIBrrdt/6lVXk3
-RACJOj8wRfedqIUEhJ/03kiNfKMqnL8acckdnnmteZA8xK0q5oZQdMq/0gGRksoB
-HCESeD39YgLgb7JIdSUgIaV0vhqStu7tT4dDKwIb0nH2jswDAPazflPMqtAnK/kZ
-kbWQcXPSM/yLwJfP3/dtl8DeYUAHZw0okrPSWAdjcAIiFXJ0kgamImjIeGTVoIKa
-mm/d7unqcK3tYChglpAZjkBhoDhXSSVjtTREIRYN25sh0yw4ithVpoBCRk+w9kRA
-mU1/+GBUwWO/eYdpka9ABh5x3DWICijkN5jo2awoAA1hMOaszsWv9Tya8kBrRP4f
-/sxR1XWZYlvoo2zPUDqWVIIW298jXmteGRevP9IzV9VcSohaROsSfG5SPWYVDSKt
-7UZTj7oxX2EXLjgMFaq2BbPJPLen9WxiEgBvIhsHTu0buLb55OMwLARu3UyyBC5+
-te6KgMqdDzmfg/RRfg6GxriPfZfGG3fDzc1h2tILYoQrX8ZPOtUTsTPEjzfpsce+
-oq4V1cVDl4k3NnWm3dxFnP6kheM+VDSLqRXSHwpqkTVSjTTkliB6
-=gRaX
------END PGP PUBLIC KEY BLOCK-----
-
-pub    995EFBF4A3D20BEB
-uid    Ktlint (ktlint signing key) <ktlint-admin@pinterest.com>
-
-sub    B89991D171A02F5C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBF9amNkBEADKyJj5snYd8bZpONpu1QHf7c/TK9HxcMzGZaIv9QzViX6CtEHb
-2Q2x6ejXQ2frECMrvns5JAJd21B6215EhlOqrHSMkTrQ6fvOIfWd0huZ0QHr4FME
-58xSA5quKBUfl1iO2qx23qv6Haw5G50twq4A9WJdEelJJDKzzweVw0BJdv8z01In
-/+sfiitcTzRT0NPbsuOnKCvfIa3gn87BvHCtqai2njq0b8ZQroLaMONtvzrn/gln
-R4oPBdeIpdjf1CrAdWs8zdiHAZWuL2mZBieEgr3+je074ARM3yCpo3DRw2bMwJe3
-JiqIKb0ebCs8ddmOaT00UngmQqCOx1qGjQeXwTD3x5Tzcihdyi5auP/zsBUZHf6d
-kmugzOWrgQ+rdfUCRI29gLWcwMp5dvMJxanREY+p854Hib5n4HZflmkaZCnEls28
-Xh1h3T6e5pWKvfZhsu7qefFjgY3G8O1vKmHjOQNoc/sEUwimAXJxK8E+S3iH/cSV
-9mdtr0TnlzI2r7+kXdyUy2rGgieonSRVRtd0Gdmu4MkiUkbrX3MBvqP14OvT4xkC
-6lcbQK1lrXflWSSRmtfNKpysVOfaIgT5p9F5zJJFEFGm5J25z8beCD8Pics+OHF4
-xfYB2SlM4xmbow2kr2htAE2RyT5EuUNuokkdtrZONmBGHBqzBPvj1vzncwARAQAB
-tDhLdGxpbnQgKGt0bGludCBzaWduaW5nIGtleSkgPGt0bGludC1hZG1pbkBwaW50
-ZXJlc3QuY29tPokCTgQTAQgAOBYhBK28mH0ae5HbawqqgZle+/Sj0gvrBQJfWpjZ
-AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEJle+/Sj0gvrSf0P/1UHPPd1
-1/gohW7EDBz1S0R7Nvu73PIx6ajhRfPmS5rwQes4EoHSVx5DjLMJb97FbRRuXJCM
-TJd3lbyBXbU/k6cfD1KbyhrqZ5NgWL54O+9c2WtaKcatnbn+YdHVMhF89FwDURCo
-gF8CpH03sVgZzS9X+WHPtdQ90u2SV/5AWgsAFR5kxRRF8OjLd38LORQQ7nDfxB0/
-pmppQym1NzeNfWa4JBhbKbQoucMuum7tL1l8tFfqpzfLi6TBXDPM7lt8zvZYwRs/
-Yup80iPd/3W3vNjmPmWfqkv4p8VuC6dP/Rv/YRer5lz943JmEutPFx0aLopdwhOF
-5ARwHFkoJAgwgQn/S+TrKlwAZcFv0NWiXSUDbBhZRE24/MlpogrxTOCPzbw9oeEP
-0BZK9fSsYaxZo4mQJl+jUzHBOzR+F/36OEip4V9bJqyEKXI36peO3s5SAFriD3iA
-1yx21o5J5MopSzTNu6YFXQoy7qXM9ePhuaBCyYcLWpwB8Knhc+XvqEfv4a7RWXhR
-eNXeVRGlTO2Ktc5jyrvbEwLoBa8NXt2TSGhWZvyyjEhKgG6FlS7m9j4io2PooCiJ
-fFfMM9yUKeCFWW/OAKi5O+IRIHwn2qtjFRlIo/OG1aKHwBnsOpnH3n7GYJRtRIma
-nY2bTfu4DB9ziayHEOXlyabVxqu1AZ0oMvTIuQINBF9amNkBEAC46u0OHX2x5/hO
-swLlZqgGdscFpjGEtAcfAhTj1zo8v2vTNYX4E9aF5hQSQneH59a9SWOFDzHCvVWR
-gfxtupVm3AFPPyWHcb0xsQyfssG0VE6T4B3PBNP52pAt36tr9gh69oxfzkC/CJ/D
-mlKi8Dy6wqt9CzWG4vciI3v7YRj6JOdM52PSr+3r8Ih8EYYDaEPAYVJPqNYqt+cj
-O5goVqCSQfHy1DuM0ggvZ2vZQAZwAgLmKrEDA6xQUicHVOfN22MIEsGy/qyC7TRJ
-gyhJzU2KYavS3ySp+hPSuffNh3evpArWpFN52e6vq3l+5f8iuBFuNRasnkIAf78q
-su0nR25pO8EYzzdcL5Awkjq28661P2veuD9oeR39B8G4CsMvYQ8h9oKLh+Z8il0W
-ACycujJGaFxJr/hm3WugCSltzhCN60ocCOaNBMq+5rLEx1PQ2DBaf09xmW0SW+pM
-l5dUDqE62/cGdXF1DaBCr8HjujZ5GXm2ZCruLikPaYU2zEk9pfZheRGOW4uvp+Sf
-euLFo9jt65TbYQvT/hX8FydwpG0dwQtuM2+9FUDSpu7k00NDtLMUwF+xlt6vo49V
-t0E9nDMYH9OEQOozFJTtxENapOFvHEDI1ZCYxCcKOATKqraWzD++MpKIIfVYrRZ+
-CTjrh0m3Q2NA5aZDLTEmzB5SY0xliQARAQABiQI2BBgBCAAgFiEErbyYfRp7kdtr
-CqqBmV779KPSC+sFAl9amNkCGwwACgkQmV779KPSC+uymg//c3AKYXo/FdD1un0c
-4fkKiKliAtpsKUf8KZZsw4Vka22S1nqKlucxwWipFyqXyv2otUn8K4bjDd7YdXBn
-ZY/98V8HMl8peROScqIwVDRF6AavLDejYVp+W67rO/Ur/RaFFr788iqo0WTXhbaf
-AIWlGRwPPam3iqELuWToy/Qx+5vxXAdKnrrmyFIyLiiTJe0us07j6rgUXzH0jdLU
-u1qWfBuBEU7xKmgO1tncBtE50nhLcQCIVhiHARRZ1lPpYo5JRGl4nhJ0HO3aHKwZ
-ifJBhYxvvv6axI/cyBZBEu3YQn1LU/OKWqMDxTt8akFIHEUHDppFD16w5knEyELZ
-5BrUYfMoelCwYa0LrfB4r4xdBZ4kFYiKx5RLo84IDuiBcaXaEL9yW3JxaXs+ZUz+
-y5nD0oUz3Ko28X0XpcT1IzL1tiPX1QDLzA8HpOSKIhwVO5SwUUNfk4PD4qbaLopq
-l96UMUq+hXzD7tB0FsnTu8ifLPRE8zNw9gT3ZNMkILRVS5vO2lUefAKUG1OsY5jx
-tV5Gc6MBNfzultNOvDhqhwve8VRIvcZDMjY5hHb1WQTpBJ1A+hJVh1nMGk8p3kKC
-C9+V9OFld6+2rK6oBloxnUh7aEqAUUT4Xni3bD6Qc/aECwy4BBgcKw3t/PVHKOE7
-RUjO/QWG6CIej/nl7O0g91NtlEY=
-=Ixqm
------END PGP PUBLIC KEY BLOCK-----
-
-pub    CF9F3090CE4CB752
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE7E4m4BCADCkqre+MJRRn+yBa8PqDHFIpfxOk8lQeueZTrU0Hw14wMkkOW6
-XFBb4hDeezStNNP6s2TS7bf5YRXZwqOwwgg33WYVVH4jPldaP1m+Z3GtYSLKEjTl
-G7/YqLcCtLxDdhLF3WpR7LUyZFQpIPEwRj12UyK8gU/Wy67GP3JBz/YhGTGfEaXE
-13VWM6FLvS6GJVouT4lFVqPTVv54+RKz0GdlgCB7Ht7kPtpMkz8ceKGU8+JcbAsL
-zkcicA97ZBzYEnlHFfoNI4M6EZumw8TXM+hvJBQ3SEWenhmUj5dwkympTahH+Dw/
-iam4sbZPiQH01GLiffeNNfTVlf0bvaczvvG5ABEBAAE=
-=YoaU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    21A24B3F8B0F594A
-uid    Karl Heinz Marbaise (Apache Software Foundation) <khmarbaise@apache.org>
-
-sub    D658968EFD5E9F85
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=klCb
------END PGP PUBLIC KEY BLOCK-----
-
-pub    79752DB6C966F0B8
-uid    Rob Manning <robert.m.manning@gmail.com>
-
-sub    AC9F6F1991913E30
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-1v9wlHhhdbE=
-=R3mQ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    8614D6AB265B4C63
-uid    Antoine Levy-Lambert (Apache Ant Committer) <antoine@apache.org>
-uid    Antoine Levy-Lambert (Apache Ant Committer) <antoine@antbuild.com>
-
-sub    8832A83FA3060393
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-NACdFJ4KIATJDK/5ajFq5+irOpodoHc=
-=VIEf
------END PGP PUBLIC KEY BLOCK-----
-
-pub    7C25280EAE63EBE5
-uid    Oleg Kalnichevski <olegk@apache.org>
-uid    Oleg Kalnichevski <oleg@ural.ru>
-
-sub    926DFB2EDB329089
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-ZNfGiQCfdH3+RPBbKSQofz2bGx7/niTd9qg=
-=CP3a
------END PGP PUBLIC KEY BLOCK-----
-
-pub    0E91C2DE43B72BB1
-sub    83552A552A0D431C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFBIm/wBCACgqvegptBhfKbyBXZiW+7XchIJCOpwq0/9QgSehKMwELbUKqNM
-sIVrywANqYn32S9hNRvBiKGm/KY7VwN9p1Cr6Ey3XuGSbRo/xN6tqfV/rV5YClL5
-6sMc67BlnEaCZRNuB9ATeUE/4wCO7fWg79jJuNl8tKQ8EYIrVGizzjmZHt76OwAi
-hQtD6A19+qjQ02SyPUJS6a2lKx+gwaHNxv4L2FqImCFGOOEToyRb12GD18Mgbf5o
-OtQVVtr3qbT07odFQt8Iyy1DiNUJbOfC+YO2wO7eMTr5xaFr1HejsTvKZiTDC0Nr
-EjtctqGxrjxPmoUPNwtxwEDTEh1lyKMhnqgJABEBAAG5AQ0EUEib/AEIAMDUgjnP
-KBeHIN0KNmXTS/uXXC4LTGltnQJ57OG2kmPz/JjAjYLoLvINY+xtghehMhRY3DmQ
-Dy/ufZsgO9oH8PztcC8QL5/dV6VTYf4U3FndbiSKgikaBX7yu5Qcrtkv8XgkJ+aw
-IEUgTGDXn2VT1hH6yEG1tA97iT/d7ZUxLEBsVgbxz9VtPellTNK5x/8NGY4NW+fM
-6+yGFpjr5juZVYRLa8u565vGBQO5FU7bg/69DftmL7vO4KRLs154VpsfAsTeo1rm
-U/8kIjgCVeKFClJG+Sg+m9rsJNYgiKy9dGfD/qDmVlEeWBuhtlAfqM7pHTv1Mu8m
-v5/DheBwvlwheg8AEQEAAYkBHwQYAQIACQUCUEib/AIbDAAKCRAOkcLeQ7crsaE0
-B/4/+ZcjdUfLPlKk/8BH0tMafEWOGvqY8bG4YpxGoJZHT/Lb/cnWDLvZzs98FVaQ
-3DKHZwQhhtnQIhnupvxSHX5wLeBZMtAANGQLauGp+A3S1WBVRHs0mzOdlVDbzJu7
-RW72mnkRMSoVd018fh4eQ0+VpZh0Pf9KfKJDwpEuESP1+6JcLLBvQXlEJYHOk7Up
-5eRkhljdIwz3TlSuJ9sCscTgM0PI7/L1eFP/iCgZIBHhpllVV6v5IGXx3P5Q7YQU
-y32zCrht4t9fdtdLct1j6eNaAQdPAU91auSbYhuVCpjgKNpwOv1ULoSWLUUPMNW5
-Qc4ZDKq+ywOElvONMnX4oaQ1
-=f1ra
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9B1FDA9F3C062231
-uid    Brian E Fox <brianf@apache.org>
-
-sub    458AF764D812A037
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=o0/H
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9A259C7EE636C5ED
-uid    Liam Miller-Cushon <cushon@google.com>
-
-sub    D66472CF54179CC4
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-mYUp5X93bS4y8yo=
-=eURh
------END PGP PUBLIC KEY BLOCK-----
-
-pub    461A804F2609FD89
-sub    8067ECAA8D58321C
-sub    750F9A735EECF640
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=QNgn
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3AD93C3C677A106E
-uid    Carl Mastrangelo <carl@carlmastrangelo.com>
-
-sub    9B2A1B698A113AAD
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-U/UZPX6m9g==
-=XXe6
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A797295E9D87BDD0
-uid    Aurimas Liutikas <aurimas@google.com>
-
-sub    FB4C179C9305F3B1
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBGJZox0BDAC/pjQlGW0w4nlUz/pJo69HlaFXNcTw8B6oGwIAhzer/iJIYaPM
-OYM44uifatxD16n4eFk3ZLHkIYbU+2wfprLlfsMhBuh+esY5qIHqFlhos0yQATGE
-8tEKYrCSh5umHPQ7lY7B8D2ReSxbvXkjHKaEKaiF5T5Bwp8cX7mS/N0J4Z0t4fLb
-WBsYfypnVD5w15YJlIugr+bKreoK1WPheHrnKTDZ0oJ8Gov61KR3ryTq0JdbUdBl
-1XqARj19J1ia11uglyAPwsbb5cw9wx9TXcRrzvGBSrACrYGaKs4F6jIbPWorP4SZ
-CN4z8Nzi16cOOwztSrDR2+9u1evHlyvgXgUGohp6npIHxI23FFXCHLNkifZSMA4S
-4xQeYQo3zWUJ2G5mda/JdPtk3jzNGuSltNsoh7pBfernrBqGdtZcahc3rP5YFODF
-B/vQLZHLPvs/8W3P5pXG6avtkQRGIIBHe0s7k06JThKWVhW/EdEtZ26Sg6w/YbzA
-VxpsNyu4kgWddwkAEQEAAbQlQXVyaW1hcyBMaXV0aWthcyA8YXVyaW1hc0Bnb29n
-bGUuY29tPokB1AQTAQoAPhYhBP9GCs8yZv3Ojrj+O6eXKV6dh73QBQJiWaMdAhsD
-BQkDwmcABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEKeXKV6dh73QldYL/Apv
-yu5wopI4rUZbFxRtcpQXGxxM9HHrYZi26+Y14Az6O5VE9ITdr9DO+INfmFi+4nSW
-DAYNFw2lQWXpOJQKXimUL4Oelt3PIRw8y2Ly0j6UF0yqazDmpA6xuXovG1/hjtIO
-vgchaiL/989HXPO//WlZDNa19Q6xQ6Ap7iaqk4tg0hIbIxPsufNQ6vjs5TA/gsQi
-T8DGDbY0h2/MrAiPo09O6yNCuPoUsZTYPlnUdoZetAqGNlJMoPgsaB/Ds+uio6er
-kgAYE8kmGf0bDj+xZFTs0aoPSFMN184RwjiFzMsJySph4HHGpUvnF1hH5BN/xxKr
-wDFTztbFnepa+CdffbNR8NDhNqnx1bxewVf3QgFPgHeTf6FYR/xEizHUU71AoPZO
-ZSUdRAFkTpQNrTCSTRc1oa4gQODk7Usll8A6tE7FvwmRDdWq0UOfQzUIlpF6rkGZ
-6oBlMO9KNa740zxPQErejh3fWrWb5p7bzSj39avqkRXJlkNtnpxK27eOUzANfbkB
-jQRiWaMdAQwA2KxuO548cX/8k+MWzl/K1VZBixgcxJFcGreHMW3jM+8DRJItB+Wo
-1DL+EUoJ8LZ5gxvM2qvjE3Y8X3rV/zbSz8iPIWHMfHliWZ8VXjQQlGuKaGfnCQmX
-bR0jtJdWKFpMck08k6RDo5NPmHm/hldEzT714s6GjM3M8uZgjoRreqkekdyIvFl0
-yJh3RHs76PEWV4m4knkiqocHFqH9ZUb3vJqnl6gnBVXQCm7/uTv00il83y06zEHe
-PZIKPJC+JnILXHINP9RhVoRB/qkqhxPt7KNKnXioZfwejoMjOXcUY7vIo3LYDz3E
-M+G8z4EBkdr8bGBlDKzMDmqeK9EG9OJg6RzxfTZukJ/eRAWmV8zgaFXaeYnhR5zg
-FuqURRy9ftSwOa+736HDA3+ler7ZfD3+cuzuBZo8WhKISoOrG43sO8F3LG2QWLwz
-LFnGmPdPYKijVNyXsNR+A3G14JaafSk7ZSkL29SpNatkIc4KN6jEH8d1zAogHszd
-cc3jBHUAyKuxABEBAAGJAbwEGAEKACYWIQT/RgrPMmb9zo64/junlylenYe90AUC
-YlmjHQIbDAUJA8JnAAAKCRCnlylenYe90HLLDAC0bPZ2rQfb3FOYCUcfEqqKofhu
-JyQa/geqgg0fBJjSpFNQOzC7LswV/U7nr8nnVXOTbISmC+GADLBa0Bmu88oeCySY
-dlEfVZGI6p4CQMpcx4Vo4cOhR9hhL915Wv/G6++nhUKoexrvHquAt29NbZ7epqEt
-QdmpgWqZ+1wN2uxnpzCV3g6X94HUy2Mc9T1H3RyA3iat+B9QVU9T8xslhUTr7B1o
-4b91Dc8Rpi95MRy7Ht7g6De6QczEJ4wJe0jCIWcl9aPWlpFWXK23iF3YzchB4IK8
-aSs3IgNewHwl01LSLc5rQxrky4DQKPFqTPdLX8K4ujxMg3ehSE8gCVSIHZRjyQtF
-jc82r8oGFBZQi71TwPvIS2BgbJprjAqG7RaIN3eRGCuPfBdcKzge/M5TKuKuf2yu
-pMhRQiaGN79lt26XU+tbwWftHrUq4LlT0Ir9eo+G6yLs3x7Tl0lbjhmgimdBlF7G
-q757UsGg74eHTP6IdA89lHXL6F5cuTBcMM+tIu4=
-=k/aW
------END PGP PUBLIC KEY BLOCK-----
-
-pub    F406F31BC1468EBA
-sub    4BB1ED965FF68B71
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFmnALcBCAD1KazT9eswNXzML5+M72qhdIX4VlJrrOzeiQtTW9vbXj7DZUnw
-U8m2bNmKHtpnyXQ3Vl7FE/e8CKGUVKmB854VJGDSyjToeAnt8A0Lg4smaSfgbEim
-rVi6jkgSCjzvNFUsKx4uOCkI59lbAWcww1aoQZcjW3D0ZTrrjo5ilx/zNXbKMfX5
-KosRIO3OzIfHYOjsmbLKj9U6pj85AXJ3/aKuRMLbFvOE3KZTxKLhl8LsgSgJFg2g
-XFKOJeXyRHCLTlsRB2qD+jAXeE0f7nTQ3xMnMUi9U2SN4WuYxxFTtrZ7QyIze0/4
-568f0ylZda+3j/FkbcZK4KJEi11kqS/ph9UNABEBAAG5AQ0EWacAtwEIAKH79EfC
-C5z/pkDx9MVSnoA5WAYX20KL+ErpMnaRbwzpizQeQVhqDjiKGCk6qyC4PUUk+H3I
-aYuTQN+rABVur4S2sO6AyNUETpAMNmrZNvClG/p6gnlYml0vzvEKtsa3U88rTTWx
-fzoecQs0UugkUrRuJI4XJyTMgRuDDLClH7IUjkrUmw2g6EzlDVdLczcpLxvP93j6
-I8R+DwDwlCX6Nqw5Nnr7Q16n9sPgDthJAF+7VS7xXs/jeGROFckdrolrQGirwbfa
-Kh4k0gfSJykV1ivuKx7QOWN6bYejph9DXD8oxE+Nne1y8tfNZFw16i75y46zAVqr
-rKY79Pkcr4RgP9sAEQEAAYkBHwQYAQIACQUCWacAtwIbDAAKCRD0BvMbwUaOunu/
-CADJcTU+K/cg8ItaIfMWM+miuYpoITqDiMpMw+2RkUnlXwn1ouZP0QP7Cpt3mq+K
-Ihei1JIRKR5+XvMV5h8ffvDy6gKpWdsUFadyLMNY07/HVtE2ydUjDhPo5vb2AWe0
-9qMZWef1/hQumkqqhz9Dbs/L8QATpnYVAtv4QMKFwDAXYCgnBijZClYwwhnJwJ3U
-rPejhP0MQomdy/li9kFMlkp795s0Ng5I/BjkFYg/S3IFQEHsgizPclibJdUR8P2C
-GXOcxXB5dE7ykv51FxMpcpgd6jnK0XRzWwQExelrRb5ys/D7pDiJBuGG/u4Hykbm
-LuHslpPWYJ7ZOeVf01xL+I5T
-=dLR3
------END PGP PUBLIC KEY BLOCK-----
-
-pub    95C15058A5EDA4F1
-uid    Eric Anderson (Maven Central) <ejona@google.com>
-
-sub    F57552EA2A2B5F3F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFUITeIBCADHIijQBuGmC+Oo/XE5qIXxzZ2cK26uD0tlDqaPhRLWt5RP3EbU
-b6X8ZLE2AlmawFzU0IqndrCDxSyuo9+ZFQRYT+stf+qHFjtvVQJh2+4L2LpcPrnf
-RK9QmmlDpKsTeS6ED32kYLDj7vwqrU+sdJcMxPViQ4TBq2AH+/pXoPJ9VBW0hg5Q
-WNehQ5yKireszStwEceRvNAnPffVJ3QVbOqFWQuxMboxZZnEmbpCot6hSCDTM+Kq
-3cyJkZTLm5ew9jHQGRmQB4sM8krQomokooSqUCb6YjPf5CmN5a4sB2z/YJMGbINr
-GOv48A9k+GDXliESyGyFUdrbZH+SCjU/LklfABEBAAG0MEVyaWMgQW5kZXJzb24g
-KE1hdmVuIENlbnRyYWwpIDxlam9uYUBnb29nbGUuY29tPokBOQQTAQIAIwIbAwcL
-CQgHAwIBBhUIAgkKCwQWAgMBAh4BAheABQJVCFAvAAoJEJXBUFil7aTxpLUH/2tF
-HofV14ZdDcrx0JRqVy6RUv6juLCzwdmaymOW/ZPYgVBs0tByQ5O1bZ5JprEuQCAk
-HKQj0SgI+1INuFsGDxJLXMwk9wbZGMUY3dcdXE9xAVTtxkFOExtEjTkjxP8TwCYt
-3AerZ3Qa/bdLfxIc1Ikeo5TC2rLcm0VJUh+5l7JKPxADpopQx5ATUdLgZEuEBRlg
-nWNm3Hrae6ovjKrXBomrdbAFcsWJNKPkhfszfh/8ajzXWLvYLAdGHaOLGtN5qHuY
-OMt/KNSWF3h6kC0a189292tTSHQy2lwKFVlbR/QW0VJF5K5cIv59dauGkGssiDj5
-Gq1o3bAfUdrVPBrtwba5AQ0EVQhN4gEIAMVQVNg6Kqg1pZNcafvm8CEwJonaIkmH
-82UmxslxuOP23O7so34CPYPOMgHW6werXSnjmGyk4X1LWOeexjbI1Ve7oG/zixy4
-GTtYST14BeGelAGYELc4CtoWlJ6SodIj/4pyuZdyrVjgWlWKvDS0wL0Mv0tRfP3h
-6bPkE1T4dsCVr3O3//qDWBFrPKClWIj8gPiQZBOZLWMwja6ML1r1KB/zW89mGs/Z
-NQqLjnXdSnS7Db4Mzn5C0JFrhbIhi1PICLYx2a4eW+ZQWArbKQYRg+aSRGZEUFyY
-lowM/FC1t8cPix7JnND7fWY+0+vDyB+dpPQ75VH5rHCpYEUIZzPUIqsAEQEAAYkB
-HwQYAQIACQUCVQhN4gIbDAAKCRCVwVBYpe2k8aYwB/9shrf3hLJEnLY9x7Py5wHD
-bKRw53ep/TXe5qHcH1iSClMEInREVE4ju8IHjOM0UsPKxTT/XDZ/rDXjp8eJYx6+
-ftJfk3Us8LnxQVcZGOwC4tO/sBpy+Z0pIpK4kyPzZjy7XjEDPauC73A1BrtIKM87
-NvazV6bbzMc57RAiwzigVGwSkqrur8O4H+seJ6YtM+rVXl0D7q5ZahXPQcZdCsAT
-6UYQxR4vx28L8k40ZTAx/gaT4SRV2vuNm14iujAgM7RfXM7l4LXt0HCaZYqitg3j
-qFEgtbX3f75Uz7wHmq1mY8CNjlnd2TV/NtdSzBeGxfsCXMEAOwWJ9rIWBuuAY22l
-=YwAJ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    01D734EE5EE9C3F8
-uid    Stuart McCulloch (ECLIPSE SIGNING KEY) <mcculls@gmail.com>
-
-sub    C753427AB202DB9B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-Bx1HfIQGzU2e0dHlGBhNVD+d31gs8Aq9
-=I4v2
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3C27D97B0C83A85C
-sub    4BC7B9A81C39EBA0
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBGEdX1MBDACuRDzoPMh3CyUHQydFo363R6OdXqMZ8mJQMdysIJCXOXZGRwUC
-uyPOUfH6uSG24RU2zvD72D2SGAehQKLXLQeN6XCt9PRAszP18dJADm10xgkXJm+G
-GJm69bRYP0GIskQI0D2hXoUlSyXFKZa154pkVzmeM40UXo90FrMC/YjH5dLp7uDn
-QtZbsASlHiy7lXFX0IoJHSHZFppmHcW2KOmFfKwgE9dpku7CdTdySY9BXiLC/Erb
-l2WjwzSDEkQbnq6Jm3/wb/AXxDEu9H2SE6kOxrERqXBfc1ycaEsJMxpLxYpk/kGz
-U6YXqXiOla1SYC78/SnSV8Dkj4/hN1/XtFmkmLUn/WgctmPnsE+fMN/ALXrH2OE7
-pUYLTy7jxJ46dChpjIPJ6Tp5z7EbxdsXR9JwLFQP+Fyp/anqLO/uLkZhZGhI3r6t
-lvFyZW8zoAuf6UpKL6bIvxld9SDuEqahbU1RcLsK/7Lwh8gFYXvq6k9siV2Fs4K+
-UWyVrn5cdSMErMMAEQEAAbkBjQRhHV9TAQwA0zBHsAralWNrZBdCkXHvNI0VqeJf
-Ix1c6AMqFW6FN73153uan6AYkpeBSWz9iHgchZY5UXgaKwx75eW+89X4X0SBU2Lb
-B39584+VDdjieynrW4HH2Fv8VJicioyMYyB/16ERidkIPRAREN3K6SuDXRkkzIZF
-LbHhRZZ6XByKDXeAZ/U56TPgsvYEsdFoj7vn+44ZP1GaAeje5v7nqXiHB1lNrpFw
-T7NV7YQXSpkqQJ4ADaL4jzGHS7umGjY5/T4dy+43qTPIrDSakHFGElfNfW5y46ta
-JiA+Hv4BowILjDMHska9hXM123CCuUS8ZQYmouYleKTCcfp34xxXuKRNDJgY8oiB
-sjXokdCoaRhdcS/PrlQvWfCA/D49XLGCeXdC5veOeGJF9W5fk5qv8Bq1vD/jnapH
-Uf92VkCJ+aVqynf0pPTKrctf0fNsttstGrPSGg+RW6NnQ20B4zgqwZAYME+z9w2z
-jmmLjm78BRJ+nzVvgll8aHy5bel56OdSldK7ABEBAAGJAbwEGAEKACYWIQRvZWt/
-a/sjjTis+B88J9l7DIOoXAUCYR1fUwIbDAUJA8JnAAAKCRA8J9l7DIOoXBx7DACt
-p4W4buVzQKYLZM0Fxucb8AgzJyrMU/01n4ys/hHBLNlCHj/Ar49PPxJ97M/QnI8q
-7yqNWOXPGecU+slBmK9biTHtHnaRhkcC/NhZsIwPNhw0H6QGGYi55VSuUPqpus3F
-fPBQ5uhGpSCy9dfux+9swNl1ZhMj2qO+m0flVf8t1JWLqTPs9giRTWAZfHuGGFdQ
-g/I+3LMyqmcphe/ysTlashiLyusQS3x8OpNhReXjZiyU44bVO5F8K+CZ28404OZi
-rg/TV/mtrH5t5A5rniev4r1FBzLTaqEXslSrvGzZhnZyKefHNL7HMiSWe6AkJBOu
-MNzPX3/PKRjhnZlLM9wpDSpG9Z66cNDDFzUwtDYx5O7gbLFib0OrjIz7q0rhm1h9
-nWky+RZ+dRuNR6HV9OlPcS5OizxbdZ9dgjy4fUuMK7G1gXyifGEXKJCXFW1whs0n
-DOOaC87hGOpfZWMBVF1mbtI+Mhb6xY5pv4UXfmVBNUZLdT8RShMJOwemBJjUkyc=
-=f4Sq
------END PGP PUBLIC KEY BLOCK-----
-
-pub    971B04F56669B805
-sub    D3664677F6280E44
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBEzZjwMBCAC0ecfE/qkdgq8uJv1c1ZlzegeWH/lxW0W3SWK2RwaHx7LrfpiN
-WhxLkXbK6fkf86FN4579W1+9Qef2yjZCwTfLe6bqj3zZGQWSu7HPw1mmhf9lbhJ9
-+TlxlczRt7m20fpSakGLIs1Jp7L4WJq3N5Ti6IsDFNOZdzGCpuiezzvp08PAD/f+
-eYABnWskOOarCOUrRJ5hV4FFj+9w+OPL25iaaEvHaAuqxvmahHzIPaT5v5Kr9Qiu
-zx0jdNaoq4/wJOGQ8rfMnXSjmuoMNgzTEs/H9ElNdBRfH50xYG6MACnVrZ1kGiCy
-z8BYBZzNUen+I0ek9SlMQDvGr0vRe4AeqlutABEBAAG5AQ0ETNmPAwEIALb8q/SE
-92Bg1UamGopUJ7lbqyebdVx0Fjf8T9MkEnteY0kvpEvluDaUWty393w4QRFPFCen
-Qtn5iyIiE0x+/xF5WlfP9kBMS03n6eXTs1pxgQ0YZ73qvzyZdOzg71isigrduA4r
-yXpoiTlWCfeStapimSUUgXxtsxFLeRVm14j0Xht1cvFCKpdxVZ9+vXIQZlyP2QqU
-zN46bwWwK2lNkKehkdSUPgUdEli/jw3L8rdASs6d8RqO/aiQN0R2kc9EA9kaRaQc
-mBboLsuZwoOCbyxPTpIZ7836b/KRuCM0sBy+RVNem1kv+905yWWJF32lZij/M01c
-OUnlnw6TVDJW5hMAEQEAAYkBHwQYAQIACQUCTNmPAwIbDAAKCRCXGwT1Zmm4Bac3
-B/4umKNZuUFKwTD+FTu6kRUOO2Rnsmk6WBuPm8h3ov2g6lW+2NjeeBib3fl+ehQ3
-IeRebLaxa0ZNAiajxbiMW5LNVC0hvqlsVAxP2Rv+DVoznI6L4I8vNEfa8ysbMY4T
-musAds4kbni7oHTUGA5bzvFgQ0ifDaFxFRvbn9ycDYFfatwDEbs3xgjewy1611zQ
-ef74Si6NR86Xit6v+056srmhZyV53e+pxGAVMw/qR6ROiMNrgLl7CPhtTwSYmSZE
-zQseNBFZpHUb7IGzk4B3ulwlhTcLnb7SUo5DhrBz5Et7XcQ/2mQOH1SrSEmoeyoq
-UfbLkuGneZv5H0KIMZ/5pV4H
-=3VLr
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9EB80E92EB2135B1
-uid    Slawomir Jaranowski <sjaranowski@apache.org>
-uid    Slawomir Jaranowski <s.jaranowski@gmail.com>
-
-sub    E3F6790A5A167F5A
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBGHDIagBEADpzdCwVjVlHuo8qpu9HtmqNpEW4TB7y6+NX7Q39mj8w+iVskE1
-sL0+BOCdP6ZMiQziWbOQ2FxCd3mD0ixZ7v1i7+0jowySPacJbVNaPPECP38gDte4
-RQwUTTCHgW8ADhYJBxSkA6RX0c5sZvi0fxgunZARs0pE68V4kUnAKiLvHerI3BBE
-kL1Pq6+CvT8K8/kU7kSk4SlgU9C09S3/CiHfb9k0ekYMJggvJV5MjqrYyLd0boBQ
-GWo8hWM4Reg/ye3+6301FDkmtza9bLwVW+euhPgzKYNoWMzOBj2pqjfWk0jF0TRR
-4iOW9aATlIZ2z3/NH3SuufW0HylmMEIbtxZ4bA0wverDje32YGYebEb73xui66Cf
-Ezj/mZPhyRDA3tV+LulyEy3CgMmDhpTSoN2eRTeXe3rq39fgoVFBE6lzJkQeNlbw
-lrFhdYEQhSddMReRlRHFeQYpbMWiS3lW2e0Zp7zjGKLqs5/0BcX+xuwBq2WaVKyx
-fqVNuO0xP8+J210B9I97Mv6CnJHg2US0q9cFOPyMIIaOtQAuzMLvmG6c1UlBaQm4
-N1PvV1ycKUpBFJv/qmNvhznjJHH5M+Yjm7Zp29g40XD1m9e4RdFq+3/4btJ6eyRn
-9eBRPp5xYNqjt4AApHUmSnWquihKXXw3sT7zsv5H8ZA1Ol4N1pFc51IM/wARAQAB
-tCxTbGF3b21pciBKYXJhbm93c2tpIDxzamFyYW5vd3NraUBhcGFjaGUub3JnPokC
-VQQTAQgAPwIbAwULCQgHAgMiAgEGFQoJCAsCBBYCAwECHgcCF4AWIQSEeJ0k33ej
-JDPOHweeuA6S6yE1sQUCYcMk6AIZAQAKCRCeuA6S6yE1sUy2D/0Z6TncCud4O+J6
-edm6RWrdU/rNx96XaDjai1Tu7IGSxHnwyYDdEL6E4AYTCMnkxFlG7AkTlTDCBGSk
-4V9i3GadHpu9BIPQvDawkE9qRpenSBizP/zxjBhnLBWX8Nis1ebI24668W7xZfSS
-YIvJ9l4qaj/2XF0+PNWUs7hF67sBijvHqsSy+ihfCem6bndJLKiO5mbgFIXP7Y2Q
-gyebjl/yQgnedfIv+R8ES6SBNXfVlrxtMwJmJIIYoNQaQaZR6wVOTfMmYAcUjZn8
-DVrT+a14lnLah1SHF/SDCLKTksuwD14vrUbBfV1wptdy10O+5rImsh14knlLNt7x
-3+iK9PCBQfJzuVQT33/4cWKK2YuRffghNzRMicm0oB3Efo8zOzqFdDj4e7tU2xSE
-0kJCruiDdU9i+iU/bO+vh8eHmXfv2S3XdMSmE77GTweGflihwFgM33J/ZDX78YC1
-GqM96Cbj7WLuOpleljjwZrxuRhSHe7wtnScM7WLhvfo2n2Fq8fASne2hcHN0lVdl
-EbeHUcHnQLTsIFL4O/lbABBfM666DFdXY2rXQqOUmSpC0CMa63AN2oa2Fkur56dP
-0CyYaE5OpFxbEbQIzC4W7YjX7whBTBhxs3M9G+gBtpXhHG3Zy2qkags6sszz2Sf2
-LmrN33T766464JRi2AY/V36yFe8ycbQsU2xhd29taXIgSmFyYW5vd3NraSA8cy5q
-YXJhbm93c2tpQGdtYWlsLmNvbT6JAlIEEwEIADwWIQSEeJ0k33ejJDPOHweeuA6S
-6yE1sQUCYcMisgIbAwULCQgHAgMiAgEGFQoJCAsCBBYCAwECHgcCF4AACgkQnrgO
-kushNbEibhAAtPwam2kB9+8Idf51p673s4prOmWRRV63HaXlvIMuT2JzPr+FO9w8
-HPWKXUjWVps6HAVMJo6c8drPtRtUqCS9CLEUwmdwOddsYGlu8C9x7SmV6qptZIRN
-Ga3P91Us0wYhMMI9Olp6UouHlG/VFvSKZTbLMGc9ClXDW9FtVXWlAi/Mei7zUzyA
-LujaE+ePagIqT6KPr/vUGpi2qcjVdobjkdtSImActsZAlYoER43TDj1libNJZtH4
-RTg9j9XUsa03Lco8Jm6LiPDvdZoayIJmYTsLa05ccRSYVpOy8oLgOx0aSaYIkydm
-w8TUOv6NkirmY/+jsOFFstc8cExTe0ogW7arIrRlBZbbCafuri/mVLvITseDWMty
-0vuVQZpeLecSEt3yf4xpf+rwaIZol81MigegscQs6u4ELaCRNmj8E993o0bB3SjI
-lkLjIUI8ZaCjJOkm1JY8RdjwYGhgQ8crWO7/E5zjtDEXNZcO1+IKSjxGpuIcxG0t
-orwcJHJ8x0DpxZ4LxLOyhVHI3cy2eXc/YCEmEnv1k1dRnzVBcosVP/junb0a4Aej
-PWnkQnW7uhp+w1oQ/uO/VcwhE/s+A2+hUmn6qMD7KDROut365kBtME21knRTdvWB
-28yhOZZEVYJLOiEe3jwNXqZrn+M8wN/qWD0yJzaeaSFYx0RtIQjkWtC5Ag0EYcMh
-qAEQANAPQUSHg5zmQMTMFZzapUgFg4UkD7w7OmL9F1+zCVmuvSD+eSrQtXK3ILSa
-+EB4ZPAn3nwJBQNgr5CBWo5/sTWz0nxQK82a7WnCNHvfgOyFYGaZC/aXHM5V/LcC
-LGW1IVKsyhWQ9UGn94cwvdfOiVrR++PpT1PJw7ey3HTnvz3PEu7KenNQcfZtXc+H
-zQDF+0s4XjIGfnsTbHoEfE3myLdJ8OG0akyPy5gR6tn4d7QEl3BOKXma3SWOIehE
-VBxbJcDRucHUFZP98r745sqZI4CbVsuAiwvjncyDYDvadaphso5mmvYPTlXgkLcc
-ltPbcqgfWY1qrcI8HIAMvyJyZIUwHVwY8tDMz+rwSIzQXNm3Rmm6dEMfNfZl7eJx
-J2wG1H2aOFQdQBbEw60OTRuHxn813IqiCnMnwIf4rsYT1MTC0WyJRvL8hbxkwXsM
-LIXvPVJe7GcizfUbYzjdYlbx8ij2Ua+0z/pStzj1cXv1gBuFRH4Vr5V/HE70k/5y
-J35Sv2sJgaVPf7troE8V+LTUiJaZmxPWSORvmMzi27m2PtwHZLQZ9fKhl773p2C8
-NryJjn/WrE1pzaw/S9aKX7EXUIp/6gnIdi8rCOCJqdZGvMpl43hUO2tLhaD+UuBU
-Oz7SWqmsPnBRAt8+ENBQ65mrt8sVKp196HjRoywnVpAKH61nABEBAAGJAjYEGAEI
-ACAWIQSEeJ0k33ejJDPOHweeuA6S6yE1sQUCYcMhqAIbDAAKCRCeuA6S6yE1sSSu
-D/9EbHq+swI0tOsrD5E7kRJMCnzex9MknJVHH4hbso7alqdr0Cqom2Ea4KLVKb+2
-Tmkyc5vgqzw7ec2Up9kw7nWqN3ANThP2RPK2BqGNgYqYtilkAsDjDUMAZuIEdCq5
-TPgDqSVTTp0EYODqCezHPLd6QjRK1CbcNoX61ahUyu78I2OcNPQEvr3rn99sWeTU
-DoUEIUUJYSqyNOb/wNi8v2o6CGsW/l++huPhO2gSF/QgUQPc3OvIDg1EMidI2s6i
-SRRXUPfJfdL2rP5KCbrJxDVeI6qIK3MtachBaDLZabcBsArsxNKpx88o6yGuzM6A
-4bkcdnXpxHE3s7DkAk6EA05zaToB/3KoFnU0FuYRkl0MBKWcGT/p37iu+LiJFs19
-0negsnLVAlbwhT78Umd8WWd5LAZ91DAOxeUGH92T0xz1Rhuu66L32cY/gh/dZItL
-17xApmK5Q+N1E0B84DLOJ3NjuBOn9f4oazPMig+72q9ikLaEbILh03dxF5b9jcJw
-E9AKrphN+8L/OMaHaA270ZQZgUfdlsnAydGz7syt+J07IcWiE6ciZv8x1B+PtGWt
-kSkTFiY0ACKu0OiXgajQ75g2LVI2uXkezd8cyzD89a/c5QhvLV3fbwh/hpjHNaI2
-fUB7vVlzPnBDQ+imN5uNOymMNiLYjHGN2OXzU0XRDL7u0g==
-=cPzY
------END PGP PUBLIC KEY BLOCK-----
-
-pub    AB2DA4527F6FFC0B
-uid    Egor Andreevici <egor@squareup.com>
-
-sub    1A94B14C6A03458D
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-aEmE
-=lnZo
+aXNpQGdvb2dsZS5jb20+uQENBFRIQyEBCADsdI8kpJKcdOgZjPwpp7xnWhaxWJ4J
+YVCB8Omr6ToEAaw3dWqkYfmTQwlOi2oBRKUnxgc+VBo/+mKOz18BIQUduM6kPjp/
+Hbas+uF0vKjbYKY/aLASRKR7drwpmphuZqibQr894HsVqXHJXwBN7/PUoAfsjVhc
+uZDtz+A1YJi+6D4I5kB4gBdk+fjhmqoapUhgDQ1RZPYzjko7UH7cMkQkHBCj1Hml
+PKU6MlZbvQn/p5lbIL7WuTuNI3jyjiWp0lLkblWgTyEY7MJvFH9s2bpPWjkxcx2+
+lBG2HAmXiOgRWmZSrrcX9+a2/Nb15+2pMg/8ZI1bSw3lju5V/ozQ9pCRABEBAAGJ
+AR8EGAECAAkFAlRIQyECGwwACgkQzGNG8s44ctkKkQf9GAw6vtfuksg9BhVP1oyA
+qVwEDrQ7L5Bt1SB3iZbMcs455nY3YFD+0N4yPIIsYg+K0JaHr3PzHBaZjGFh3pD+
+tV7cuMXq/HkW+82Ogvn3onHWCfiGYvl+ZBLlN9C52EGbIjx07vnjJoDXPHpeUeLE
+aKn3R7ijMP67/mfKYKUlZ/9uMRcJJt+HJXwaSaQgyGRDT37wmUCBUE9X0XaNKXYl
+ZA7kn7jfpDBy/IaqcNOxe32yum/c4MpmcKGOFdm5Tr48TgdbDu75FT2tNsb/VtD6
+OFFaX7GjQB1CX64SCeuT9sDmqXsfuup3aw/ff+A7vCNFbhwiMUCJgH0aXV+A/bgZ
+3w==
+=vLa6
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    CE8B1D1D2530EDC5
@@ -5429,92 +2666,374 @@
 =R7zg
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    0DA8A5EC02D11EAD
-sub    71499A87DC1FF84B
+pub    CF9F3090CE4CB752
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBE3LMfMRBAD90h69D8yyPWaSoAyh2mOOOZ/XH0isuBpDZCWptemlMHgImqdQ
-2sXLXYT1bJKmSaMw+yKjp8J/NYk69EbmSK1C2nypLQtWhUmXXd3XVYw6hrG/dGvi
-gjkS5eq8L04f5CSuXO7r1eLTOch9iDl/ESaI5Nhq9A3mRQIhQalum+FjzwCgx0PK
-hoC4MVPVGXzOQPc5sG4jzAUD/0OX9c/yKQqjHUs38HTCgrjseM40iPhp8NfbWenP
-IwUMSWXE3lz0MMeKrGcEOcZOGWsjyepkLHXwj8DDOeGxhfh9bhFRJssdfzOCKBpf
-6S70A3fanzqOAvddxCqF/zOwDaieDmWvVntVpmZO9d+pgR/sZN0JgSIm7qGDdNqG
-Aq6eBACyywfwuVoY6lfNz70ZZqYjYuUkbKnKqpG0XmI+m5LYrUW7QuKJqaNdg+ZL
-vVgX/TdkWVSIoSRS5+eYm3fRD++cg3ZgoR6ZY4WEa7SRSp2zoidtQijWOzp8WeHs
-30rIaXBrb5wHR4GQ4FYsBGRuWkmIaferusllUmHCHFJI4ldvgbkCDQRNyzHzEAgA
-1rD70DvCcy91ShQKP2snZ4cLJnFwKArulDUcxoBZ0AG0qMbaE8jiiJTHIwgVrqsK
-aS1JENv6tVdUS8xHswu30zvd0obaj+4IGXlMVdc6052Y4SLAGNbGVw99Ah1OkQ7o
-v92gmYAYfqppOtRt1tylz7Jf+F6er0umdVBZm8fJ+QjzTw36AwERj2bjVbc6ogM7
-OsTyru5oZGOJ+oJU+M9/mh/Gq3AyrcfU8c6bL2pacXwylME4lxy4fBB7BsMogPXX
-iplZ2XRH7RmlZiAfLHv3StxVB1RrLXVcjdnqIO2guVYrK6mxH9WMG4LnOGvcnYTf
-GtWexEmNA5l8IOSgsK+InwADBQgA037clDFi3XWaZBVXst7IfkU6bKq9vhmphS4f
-uBx4wp7MBA62k0kGDmZWcbinZWnybypili9ihYSHlp3EYzCNTbUMWlbhc/ffYHuv
-rZsIT2DxMPb2iCnjPu5HMGegTM8iTTotW4xYmJUsEDIvgQUz0/UNsPHTX5XU09So
-cL3YOP5MxcEbgO0Fpjny3X76rc+ETAd9TmDJi7HOm24grKdOQXHQJr65j7nTc9M3
-zWnTxOP3fL9jcVnGTnLGRVoR7kedDpa5FsoFqtY8YMaFvNPVvI4+m+jozjNwTg2d
-GG6nU2dEC0qgDEeKMSJwF1wgO3Fe6mXHvxratgNrqfdY/rtEGYhJBBgRAgAJBQJN
-yzHzAhsMAAoJEA2opewC0R6tNKgAnigkHDCNu7Owm8x01E9+aL73JmDXAKCj7ROh
-7Wu1iZQbjeJfypM6CQ+fdw==
-=GCHG
+mQENBE7E4m4BCADCkqre+MJRRn+yBa8PqDHFIpfxOk8lQeueZTrU0Hw14wMkkOW6
+XFBb4hDeezStNNP6s2TS7bf5YRXZwqOwwgg33WYVVH4jPldaP1m+Z3GtYSLKEjTl
+G7/YqLcCtLxDdhLF3WpR7LUyZFQpIPEwRj12UyK8gU/Wy67GP3JBz/YhGTGfEaXE
+13VWM6FLvS6GJVouT4lFVqPTVv54+RKz0GdlgCB7Ht7kPtpMkz8ceKGU8+JcbAsL
+zkcicA97ZBzYEnlHFfoNI4M6EZumw8TXM+hvJBQ3SEWenhmUj5dwkympTahH+Dw/
+iam4sbZPiQH01GLiffeNNfTVlf0bvaczvvG5ABEBAAE=
+=YoaU
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    AC7A514BC9F9BB70
-uid    Punyashloka Biswal <punya@google.com>
+pub    CFAE163B64AC9189
+uid    JetBrains Compose Team <compose@jetbrains.com>
 
-sub    7B92B768F9D37337
+sub    57CE36BB68F1BC57
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-sg==
-=w5lW
+mDMEYYx3eRYJKwYBBAHaRw8BAQdAV7zh1T+xL7mD2O63rTIvRfQ9kwL2Gvq/Q6PD
+9apCe2K0LkpldEJyYWlucyBDb21wb3NlIFRlYW0gPGNvbXBvc2VAamV0YnJhaW5z
+LmNvbT64OARhjHd5EgorBgEEAZdVAQUBAQdA/AOwflH/rum1g1gvFPBcqhvFOcN8
+0VUb7OqoENSzUD4DAQgHiH4EGBYKACYWIQQgcjpjmbwGAVQoOzfPrhY7ZKyRiQUC
+YYx3eQIbDAUJA8JnAAAKCRDPrhY7ZKyRiSq0AQCEwGRGd5MOTT2kKJf9CphX0LOs
+qVBBSNvzoloV04wzywD+P4TmIz/CsigszDQy8yl1/rGvszo7gaUwnfnqN61JHgA=
+=Y19b
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D041CAD2E452550F
+uid    Deanna <deannagarcia@google.com>
+
+sub    5199F3DAE89C332D
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGCtdhoBDADdopjDt4eUNEqLJSw1ZICSR0oq09SOVtJSaSYdF8UiXjBfL1Ds
+fhTDqSv5pT2a2gLj0OU3tFhWHvINLaKKCjQnHVcFXi2LTxt+XBOjRYkFjHVisbaZ
+PZ6HnTMStPrvs+hQ168vU3VfYOsOLN22j53I/Ba+FA7E0G0bqkratuT5L7BTR1mC
+fqDaeisWSCllfe6EEysaFF+/1RcRy+Yt+8ZWV0FZEF7UwQvqKHcYmlkqPIn3v/8y
+J/yvmzIEtCQ1F+bvJbzaROmeJf254G2Uh7IfMYEm9WlqnGwNdbIhil7bdxq8Y/0H
+XbQPaESxkki7yL5JTfH/+UzdklMe+Dga273L/cgzfjV3zJJ9vR94W5ABAbGYh4ZW
+aKvNnT1m4vTbEMfo4r3NF2zc+K9Ly/JNaHqkR5M4SVElvN2lsC5KNUiRvExhg+h0
+mKyx61mu3gUIrC1UOmqhtx7RzQQf7ESMdzmNHY0P93lR0Ic10fyli0wfl7A6q7+q
+zV2a1V2k9Yg6B9sAEQEAAbQgRGVhbm5hIDxkZWFubmFnYXJjaWFAZ29vZ2xlLmNv
+bT65AY0EYK12GgEMAMgP3//QeBsTS3IrfSp3m44el96X6BWona2yo4DvVyuwqfUL
+ZE+Nhj7I+kEZLrA29AOySOD/6quJ4MIJZfq/Do920Di8/10WQ00OdCM1wH7bMz2U
+vcSqsr0iOgQtycuUf7JOHSTME9vqk+C3Lhn0r59AVaRdXEe6zBgNZyzZJeCr5F8w
+RhglPlwvhOGs2aLEqlCxFnY4pLayQFoQyw1lDjHIXHg5JtfOHvqiNXVDcGpyKLG8
+SzImp62iL4sfuA0weVIQeS9kZiQabSYKvSf3TvNXYTgmFz/vjPbYhv9LTkBroTlV
+g3l+UmAxLrHVuXMx0zX3jfNNHAqUjVhPYZhnifMkmGJgLeMIVqr5Q/tx8pzyYiiO
+cqQ1zDg8ubJDGRue1JjlUGdw19OvhFDs+lydukt8Mmhb0gPkBLi2syZHgYHtEooX
+PLwEsJ+SynZCFhZiWj8BsWNFJpaDd8ynNeWhMAcwi3B5ZeQiZaAlV0sItxsrzvbu
+4ZYZtkjAkQdsaaTWSwARAQABiQG8BBgBCgAmFiEEaWthmaKp2MKc54zA0EHK0uRS
+VQ8FAmCtdhoCGwwFCQPCZwAACgkQ0EHK0uRSVQ+G7wwAvaVPDgnM+i2pGQPwq6Mk
+SzhKEG4H1pvBWyYR8H9D3p/dE33IjVu3EEy1h37Nzdyp46KtASGNe3KBodSsh6gv
+PlV5pNGxMNbX6fo8ZGtS83C+6uTF1cYmuO1nmi8P4+7qtcNZg4xv/ujAZIC20kem
+YKDth3FvPxEXsoxY+Ns7sxgd3SqoyLhjcyoczI8uyhim5nfvvbnEd6WrdiBPBtb/
+F1h/nfqdFj2TcZkAlnzGnlVlgU8J60u6zE+9VvBm0lJR73Ar55mQEwarGFPL1a3/
+A7ZEeNa0Dc3Oa5sKMYtxMlGKZ0WGUoGcDWiaDEsv5YyRnaSOaXKM1NkJCR013QAr
+RcHrRBPo+0/RIZVE+b8oEcmGzdL8HNwnm7e06ruZryF9LQA5YBmCKE0urigmgEvC
+zZsj/fMJ+OIZcAhE7UVae48GpW2kLATxmK01oSzvizIlmN3rVz2EnjOun2iuuEpF
+/lmDbjK5n1r3f8npB1l1fT5cozzQJkPVYzhBWH1KXP5X
+=nh9O
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D364ABAA39A47320
+sub    3F606403DCA455C8
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=5tlI
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D4DA5EAB3CD7E958
+uid    Jiaxiang Chen <jiaxiang@google.com>
+
+sub    D826E3935EE9DC71
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGETEF0BEADoVhSwI5d3PZTca1W/1HvIf5UiTJrSlZby9xRdSbfJ0dj7V0QG
+aY1tsOcLLuIkj+/wDJuATokYx6IiGnntorQcLg3b0XMoPqzTVDl4lnKcNIsh/kxD
+FqsWgEy43sRf/72nlQ9XoDxQITpGpZRMALTNGmuNznEBu1lPMo71/n4CmvYUtyKF
+st6LqsA9ft7nVmsJrwU009ejD2Ik0nRra3euFQ+uPJ9QM5kdgyv63GsRpLMT2nMk
+Iv64IoeM6hsBgggA/BvBcrDv776rR6Sjcw6QldLKmf6JgKekRgmIBFayxpuC2KWI
+OcJK/UzKCab0sUlxBBy4UjoIiB4vLinqvMbQ0z8imELvGUW/R+AbaZ5ra7gTk6mh
+6dUjnFOaQizbDG8BST/Zv/haGAfpGBYd8G/nOZuF2NucKuL90FTdqxPepo0fFIfW
+XiEZNHW4fJcuyM8qyXdDBs1Iy6fWP9mdHyiflDgKCbZPyNGpVMSOUSdf1t1F0U1c
+ZPBvy6cA/Wf9+ykELBjPw07fLmUGsVBVWAcxXixsN3fbaN9QcC7dhmpcF9OxdzkB
+3VHHe2KhbUfMxSP3I6Sd1hgoFDpz85rmeSFtzokRPr9LOlKclvrAuQh33vaLeBYG
+IaVt/wdWvS9U7p4e8GzyL3t8trabpfoJ4RASD99+UiFyAWkPjozTcx78dQARAQAB
+tCNKaWF4aWFuZyBDaGVuIDxqaWF4aWFuZ0Bnb29nbGUuY29tPrkCDQRhExBdARAA
+zy3TBWsGPZWpaBrmm3qzkzTOOaDQ1SfN+8jjwa+uVvEczf+Yc3Hzkpk6JiAxTdC3
+8ZLpZVOfbwfRQccMZQOyvpqW+UAFPsXMXji/D2QCn8FKq9kgBOADEInpTn/TtQeo
+G9nPttYPaV/hlU7c300K5qKjyivwh6/kHvshqNRuq5qXOku1mwSdjvsRs2bfaaF9
+q6hYGv+Avt+gBnkK29fW34Kn5uLhMircZcK9+qQ+Ag/49n1IfkiN+Fts/yv3LgrR
+AlCfIY7llHUiOLfTmfghLu+Jg7BYd61KpWm1Kv5n3+QEoDr32M4HDhFtRA5lQRr+
+bx+3uR0/ODu6ezNKKPLSMzcocbX5yNXnEKxk/BHWVzLBB4L3Cwbj1nDjmnZqSb7w
+J7ololszhKBVrb5pRYjmEsEZ3iW8Iovn3whvFF8oU7KJtwZsORJsWS2NTwhq1rVM
+SNPIiLDOW1uLmGN94VT+1AE+J3k199gYYiYNet0CnTKqB/7bv0dSZqVynWozTZNq
+HDgqHp8Jhxx70K07NvjPIiXn+qwKA2Q8qpohMma3ElJl4ZpZyUimd8Ujif7o7WYh
+Fbju9UzeqGWtbg0hzGbpekADvKk4f4FkbYd1U8XyzO4p/4RkJnc05KrVtDDu0v6O
+HuRzSV5A7n/xC0BKHPG+yS1ss3E1fyPwovppfMQHVAcAEQEAAYkCNgQYAQoAIBYh
+BA1dY0dVc3oZq74pMNTaXqs81+lYBQJhExBdAhsMAAoJENTaXqs81+lYUUAP/R7N
+TPZkdo2BUYF5vnTjyA6JMznnxRSC70z2JjPj0DIenzjOJ5p3E3rd5Gxa/tJIh2rL
+0Zwj0p2gam1BHZZFoBtRyNP7Gnkq+L2yHih7JfgCDOaxVppx/xNMqBUaD6X3E1uy
+mzNYm85OI7H0aVpQj81rqWq9r8Nbtykt6FKqB3YjaIX6GtUqMWZDJ9BXiFvEhhZs
+BdhEFbFwXwBCoIcrsH4oBKj1FC990pH98SQ7AfHn5PJTzJkP3ditDYJOLYwJ7ft3
+blQ5PrWp3HUag2xdXwVrQxcg2ZYhWpOOURmes2C0s2KIMVMS1K4nWAgjrrZ5W/a/
+q8qAI5HKTG4WmMxeoLJpRB8MAUAZ1yHhw0ypNmYG9ZzwfAkBDQWYzANPKKQS4f3m
+vJl8HTv3FJh+uX/QBf8DwzdtfI1vzPF8QKCXL5PcTcuCjYT7uuqz1ffyj9veBgAw
+sZzwjhFkc7tus2w52ydx85xtGq5BO4/+qKB+lr2fZ1YZWIjbCw51RwKrLyOYQdmT
+1NqlUja3lWI0/h/IpbVIIsQfDM3pjUcOCsBMTixn3w9vzNwxAixJow2XfQxTyl5z
+j7oRrVDTIHOxZqRVVz4Zvy6RkPKTkDoSb0wgBKpLHXhCJv8WM+MbFHeI3Jje+EHo
+WhVfu3jhpYE20kLZPWMTu6amKPK3dSJ4aIDjkosy
+=Jp6+
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D57506CD188FD842
+sub    63F72A7A8658D653
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFj2NXwBCADPJcGfWz4Zsfa/UEUF6a4aAIjqCy+rNmLf9Vs3HD6B5p1r7VkC
+e0HhxrfbkDkQu6aEmAwV6GwYiwWBf/LQYNdKm1FYZFhKLhyuTPiirFqIouEFqiK2
+HPFdil0d6Bi6HB27qe3NScpqMK21ectpQfTGlmd0HrSN55pSnb9k+Dnx5MdR+XNl
+pfA4f5jNBIrnsCvaY5jccyFfvGpzykVF0yaSikbcs9hJ3pbfddLuBJ4Tk+yePDjR
+FWJ2Rtau0Pbaz4CebAIQprLfdOuxKQ8l7jhMZpRE7+sz1mU6fvDnPyj5kvnoU4SB
+tVvsnSuILeewp99/MG/wE+B5uqxG6KNpxRgvABEBAAG5AQ0EWPY1fAEIANhZYkCh
+aM7zRmJZhzbwoHNfuKfSVYfNjCpRdu5PkutVxBsjqGWs47SjXEjhiTjAD/s3cgj8
+x/uHKmXXJoHUhnU+9RPlRiEwt6xdaEgRqMJyqrqIJ/PqmerMZsZsnAC4dFFDbR19
+lfDBNa5RjF7f2s+rHtaAPSMbn7lfeBpP7V/r4qUg9E2pRqoCCMqCtFRFlNgLwv7A
+jgMhaTaO1Am2sxfsTOVyoxCxC6kpJE8r4iRVstdfKifZrfStE7ZmtKmRjqLmblla
+GkQXWAlcayc6SLJa6bj61Ln043+qum9l5H5xUBHwfv1p/UPzNpZVGgZ/SVfV9rxL
+/DktPZ5S+HPSyBUAEQEAAYkBJQQYAQIADwUCWPY1fAIbDAUJAJ40AAAKCRDVdQbN
+GI/YQsl1CADJMZdQGxuAOmK16/0k8q7sNSbGtrdyD9n3yLsWg9cCTI9ecJdM1cXT
+RglhAfsm5sr+xJnyA6ShTn8KCxgRHPqLTIwSfmFNjePKmWUK1iBRdbNdbfHiKUKb
+Xc2CMwkwHj6hWo7rwh7WWS3gtKzldUirfIJoA13AXrtJQRq0qgV9qN5sEpVGr+fe
+5whzG9BallTirYztskrI82p3e4thRPr5XDK9r8SWJKPuhL9zEfStSMVnR0gO4n6w
+pFryXcDaWuA6/+hIzS+RwTQKpQYNbb/OKrkAUH6jDLzKtixWNwxuDJpVz5YHDJVI
+LCwzEShVwuejAYnuG+xpgw1jIxtoj/bGiQElBBgBAgAPAhsMBQJZnMEmBQkBRL+o
+AAoJENV1Bs0Yj9hCzpQIAMMZ7J4QXPur6jDgjpbWESvLbSSYGEt6uIMB8SEHBEJ1
+DdMNdRKu6AvUn7doVOhVDbzof6jGpycRFG4goL1fJM7pLljcOwJ+75FrYZCdC0sy
+JPd+QkpueUHyE+/lZpvWuu0vlgfDkfIFFhC96/h659oTt5j82l5YIXanpgQg/AiK
+l9joXXxvVt073y+ngFHpYhCkrdna6rxN4WRbVN2OlUJx8BP4tfFagYKaMSlPkA40
+03nUlwsPKQ8Bj4tASVSpCihlR5ijmxR3YxNlMET2f1ljvj8Uu3N0LrR9wVr2g7t7
+nqTzRs0OjV+r+qy7eoZ4NBugYFXpP/RMAXZJezpKfKU=
+=FXUZ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D5F4C07A434AB3DA
+uid    Egor Andreevici (My key) <egor@squareup.com>
+
+sub    9D49CFE20A7A3EE7
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=eL1Z
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D73C68EE4152C255
+uid    Eric Chang <erichang@google.com>
+
+sub    A23FC45C6F9E2F57
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF0uFrIBDADbJkwrWs0qPrv4bNmPZMWHcryANAwodvFF4f51Z6S3pBkuBxx0
+vW8ZKC9/scJiAzSqJRf4im70GPNE3MZjNyfuRdaedXw2rFc4Ip7lBsCtklYmTWmC
+vA9DXI6gIhvQ58s13fHcLGepIfKZcIXntyXp3DcPz8XJpfZTwgpS6RlbJjr296p4
+ya1LiyH5GBaWal7DcKwgIBSSAbtEyZH0tNp9wfkiILiTI1RE1D+DrQ9MJa1b7Gag
+qBMn2A74TFEzx/bSPMMllwdKTRurvjz33TTdNuyd45bkteMKiw5O+6c26Q29o6hw
+oQG8efNDrzWOCjW2Sj91DPdA52UfJ9T7C5dcf+EcCLmpV7hWrfkDdzDX3NXnMU7A
+r7kEPKeF608jEcqS46YB8lIBqC6gPMwluLqmukRpxrlyMwsygc7bbieMZRhczCLo
+tj9CUAUW2dvXwY32N7zUqFgVnJ26t4/bHRAW5QVVqrfDC0WmoUVyOsPh9/KKGmIf
+3ocDh93eN6x0UH0AEQEAAbQgRXJpYyBDaGFuZyA8ZXJpY2hhbmdAZ29vZ2xlLmNv
+bT65AY0EXS4WsgEMAKfohKMRHHVJ9aAse/rwsoF9D5Qxg/g/DeuWRtnFwrSv+6rB
+JW00S1jIXkzeM99MsjK4aJaSLfId8SQmMWMvzwBp6m3J0Gqy2CdRo3v6zW0juPHZ
+2vDs3wt9sJPJedufqxlXwWo6XhmNJXcclBzeP2f17Phx6Wrp78ONo6tDg77IHLds
+XER/KwYAv4cK6O+MahvnelpAFyi1fdiLJkkrwIheUKF9jKgCvYGQeQSoe0sopFD7
+zXYgE0DurlpI9Shj++i5jN7atvaHRSFp6Vo8PkmtGeD0jq1N2nCdVWkIIZL226AB
+cSBSQSVdTiLPFrMmqlppoxvwl8Q/R8nKo1lsNKp/HV/qshF50GfpJfLKA3GmWZWt
+/dkCb1nurCmKjAO3AHCL5p++idGIsSTgIDg5mcpnltG/TH1atoQj1ixRZ/ykSu6V
+O+RygcV60IdGCt8CFTLSLUacfPieSR6mGqLdta5ISNHqbJ3Xi2mQwADQmLbYnwKc
+U0uunRUjYDzyIINn0wARAQABiQG8BBgBCgAmFiEEDrnXxGj5fkQFHWUK1zxo7kFS
+wlUFAl0uFrICGwwFCQPCZwAACgkQ1zxo7kFSwlWfEAwAqz6AHYxuxfbEOkCd/d7Z
+hd8OvmLHyH70A3wfw1LXHowUQBhQi2BwZ9jwXzu7s3ciohMaHvN2w4VFLwCY86Vn
+KQ+mn36Op6/O05UlGFauaCxyT9PMHJOHpKdUopCPnajquSdpHZ/y2oCl+KUcMEY+
+s74dEkDvj+QbL4VMawOunmKlomYyFurRJ5k28RhmzgGaUr5r/2xUMIvPaKQ+Yamx
+jW8THKMyNZquD/cRNHusxtXXoULhO9XOhSWyOV1EDwrK+uIV8Vg7kP0AD3jNW+S4
+2NmrQnAUk4NiUj/2vtXqqZrr57qxOAz7GGCh5xNGuPXeb8mjwCLqYECLIms6clQT
+5gWHD5AU36tes5nZyahgbVU34Jx2XQkbyw1245MWBeOfjZA/cAQfweDmKNf4sevL
+fDoLu7fnsOywIwrtprcYdzyhAaM+pO76brTX40781a2yUH2zpZPWobdMyDNDeo+b
+ql+Wvzb+qRGSzJV7rbKv80zNxWNJMOr+yshtM+Hclm3s
+=7sNz
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    D7C92B70FA1C814D
+uid    Matthew Sicker (Signing Key) <mattsicker@apache.org>
+
+sub    B4C70893B62BABE8
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+YFgIf2xqp6U91eVdz2QEZkjmhrna4bgPMQ==
+=FgFQ
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    D9C565AA72BA2FDD
@@ -5533,820 +3052,275 @@
 tPPngDB7k9w7n2NatF3aHpHvkgekaLlflmZ5rQnMadhBUWgJoiwsx2q4TnSh70/t
 TI3dPBbdVG+8YQ/LpNzOVshY2uMHHxJq6lUGVl6BIIy83Yslu0gFYHzL7H2tXKpg
 Q0qAQBktmX6H/P0AEQEAAbQ8Z3JwYy1qYXZhLXRlYW0tc29uYXR5cGUgPGdycGMt
-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
-=t7l/
+amF2YS10ZWFtLXNvbmF0eXBlQGdvb2dsZS5jb20+uQGNBFrjUQUBDACq5JHcBH/y
+8KUIR8blOOov354cQgX4x+eF4znw42/5lb3pLpYF9gAtPMs0zQFhwgKFHCr8SxZY
++nYi9h1pULqaLJXeNLZipaoUufyXALyXJojvBf557UljlvZM4J6n0xHMVM5NuHxG
+kkNoZyMrqDqsarbsLY35ssizc+fwXq4dPmyGn5hCSwwc1Z/DXqFadK8jSdo7klVx
+wtnBlOFlSqQ3iT0o9ppB5h135ygkGY3vfSsqrxXE2Cg1Y7vQBdrhC3t12dICZAzq
+I/sfYL5Ejw1DYY2H4c5vbWPIj5mRQNCsUkotF4Bt/IAOHN50lPpoDLMDrTAnBpvT
+mU/vsLNWfZ06nMJj+Fm4zZ9rPfdgRnTdFqlh5iFEhRildPSdHTd1zw1tFW1SpgVI
+o49pvQIjlSacwvza/oajw3p5FOJJccbAYRuvekIvBMVQlNh2S7TEYD1MKddONSw1
+bv4JyjptNSa0Rk4aiZEYGEjSob1SPveNZc1kuAu98ViPbtKNv+ylUBEAEQEAAYkB
+tgQYAQoAIBYhBLAjNapUzPIeUrv5q9nFZapyui/dBQJa41EFAhsMAAoJENnFZapy
+ui/d+yUMAJKh1e3YX2mFpMz1oCuVw2zPEwtJvSLE7q592b09LyTOXOKi3eVmvFVw
+QMSSoz0JQfINoB/hkHeB5vzU0atgN2sUTA1hVrErX1rLdpjErJ+6n6vVXfZcrFMX
+fjwmxuhnvbAqKDQ5Cm1meykOrXgGRIglHVJBs4KQnCcdS/b0uyujs3E3hBR11jAu
+g4eUXA7nWOVI7WeCxjLlA5+gCzOfiRX3Njl4kBQX+ekIcxO88AJmf/NlSjTJzEC3
+t/o0Tc6dN+ZYxpOT0eICC5xrEj2WaToE3cU455Sq3ZWyUgxviTWlfsVFGy/M25ZM
+k71LwM+WmDhaPNa279wdgJKrqHebCiOW36HtIDoK2XW4D66aJ28+nujO5tvGwZ0I
+J3EZJWDjNf8vTaL7l8TNTuSQ9SkoHHqEeD/MmfBNUBj+Dj4jDoIfAGHD7b8qgymN
+DrdWqPBBnr5UjB2xIKHjDMAmR/4OG8OYf8b2whrC7clxWPU/NrQjDeAt//3Fmtue
+X4dQRyz4Xg==
+=9DRM
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    B57BD58EF6D0A713
-sub    781D1F35916E0113
+pub    DA70BCBA6D76AD03
+uid    kaml GitHub Actions <githubactions@charleskorn.com>
+
+sub    66A2CBDE49E8A25D
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGNBFsZf3oBDADUgeJsq9asQLaUajkGON9KmxKBtJS+IbGa0jgvx37T4LDigKS/
-wh4axvdJ0mE31uXKitBVDkr5TptyxA0jojYwlt5YLXsotnskdHrIg35Q8xpMp72K
-BfBsqtnfdmBUd/oBZEKgxMM2Pl/VZ+1wmF+KnyToSWuy4Q+9d88ame+8Jdq5ELJn
-zWZWYhwE3c2Y8t62VGzXeZg9Zz747Qt0ITl02//ufoR8aLdb+8uLuidNktyoqpt2
-UG8oLr8mgOAaOn6npN81FbteIWCEcuGewCjiiYTHGpA13JmToDDUfopWYGJirkSI
-dYjP4fZBu4aryHKwXt/zsiD7rzbHrn821CAAZKGptVVu9IfqD3jCBhJilGmkWw+j
-IozAd33hLvlCnH8miXRnGPyNT5T481qbi09wOnQEUYrXBe1zOvBAEVxwSLcNcxe5
-/2gRDbSNU9NJst994hzofSyxA/3X/CDiOSHDKdAcOglgqfpistQIS68FqDGo4eIS
-WeR3S583Two98+UAEQEAAbkBjQRbGX96AQwA5IIECRfqpRDQKsgEYdDMzEYED5i4
-w8GrkqK9Bl2KErI6WQmuBnZaHr71bMrYFS8duUOYetasTKCxjU/Ps0THuOmTnuLv
-Am6PCkpzJ+qBNM4jf5sxHflcb1jRUQ/R+qoWOsWcwJhOw2OgNONHhW8/2mAs+5Zz
-ThWe4cL62YRK3CeWdWphwcUSGx+zQo5vYBZzIbdQ+E+c7aRyc4qEPfyGNccAJRdQ
-eW1tAWydmf+QIYGMbANWNPXm+g80wE5xCA9wwU7N26Rk0zn6e9+lSy8e+l6+hsNh
-uNxWxDDBubF8YMuzD4q+VM4dOOsAJARtp6HW/0mBTcTD5BEOqnDd/aRsNOrR9Cbk
-K4nU1aSrYOeOby8jc7Zu0SnYC6g+JXalt0jtDEGVaxY9IMIe6AcIJhSXlgllK87b
-YX+t4uVXYFb10QfxRj1oduBQEHJkCovsi3EIIl5a4XyoGdNUGn2IgWg+C0RXrcb/
-KDrg7iakp9SwXP0xBSbcNiwE/3C3Xom0l3ijABEBAAGJAbwEGAEKACYWIQQit59F
-awb051uLV521e9WO9tCnEwUCWxl/egIbDAUJA8JnAAAKCRC1e9WO9tCnE/ydC/9g
-6xJK/aIvvKLSraYfS90XamIyUqNgAyXgivWn0jqaTwoz27HG/hRgWR85q72vZ4qV
-vYwx06S8WHMijKMcI5fBtEL318c9V6Y8Pl7jwSOy5yN0k8IFA+TzqHGXVvPcuCwH
-TQAvvP/9v2d7ZrOiH7urM0eoRDXj7Tq+K4rLjeVIHALLEhqBT8w8LGBOEZUAwS7t
-aaGrURVuhO80QW2gJAoG5AU1qMUkzFsTXBsRTcwPP25FIPYClXPNsMR+2iVZAZ1e
-3yBqQkwRlymU3gPGY3M+TOyplfoYIJy6oT2ri0wYa2jeNdo6eEmLUjNAbpdiIEop
-ruzQLLaT7PUk+RU1UFVHjV0rgrXrTYvdgKyI4dX2yGlTTmnq94eaxMOsMxkHAGBh
-GrOJpBDWzJKXX48WAdi/4WpnhOD6N1BOrvWq9QWIU2374WutAX09dt1kBG3m4kGR
-STHuixCePH/e8n89lWDXSsqkV/+imzi75cTN9RWBT1mRltc4jNQ0B2WwUgrTSPo=
-=yiE5
+mQENBGAwdRsBCADCXfWdHhywp8Rcgt834W/Z3MFEAxYdxjAJOTQhc/In1SJfIqi/
+xD7OKHA2fbwzRnS/UmXkmElTK7JI3/1gWRm8kEaaHTnlI63Z9MZV0DHMpJMgvpFM
+JXKMw9GWbOZt211YMFTkY3oi+kCIibzs4S+2zAiKX0/B5xU1gE0hnPYbXQtZ2sUb
+8t4axAkPdlDVrnBbgPD/+31c8G2Nsd3w6Rughi3SXdqp/6lKZpJNZV7ZPllA8wa3
+6hdOqWkh2Xh7uyKCXPtPyw57vwK1CeTmrAvI7Xhfh1Cxj2bnS8POnF0YsthtbG0Z
+6TupcFBrscugbl4F0aWsxCT0WjKQ75J2zgMnABEBAAG0M2thbWwgR2l0SHViIEFj
+dGlvbnMgPGdpdGh1YmFjdGlvbnNAY2hhcmxlc2tvcm4uY29tPrkBDQRgMHUbAQgA
+xCK/qAeVJ3lTUnNzy8UxL8+3tEyDY4XxZ52JupzT8S/MgdKoCRmdWzyJWZ/pVilv
+HWKEUbjJJoKZWSi8nti/rIc3LKqnVKxE8knXMZRXHlRI47yxPoWxLVaKzY2ZZd/B
+wmSE7pF8FQXbW8+NeQaVuSHJDGqycJa0IOFlP384Zpw5N37FR/0Wra7koAJ2fuGq
+VUyFpGCs8SZ2H73lGNIe76WTOhOEbhLStF3u7petSzjDmurAGpZAHyPNLkjwvocy
+kueYtByTGcgIbBFTIrLB3bf/MXcc3rcNuPwwKiGthGff1xe62VFssfh0byE+mggl
+4/s5hkhQkYlh2yLmr4QkCwARAQABiQE2BBgBCAAgFiEE4B7Sk5ga5IRAO2XX2nC8
+um12rQMFAmAwdRsCGwwACgkQ2nC8um12rQO1EwgAmJY25uA69cNq/eXtZ9/6o83M
+woWH72U0zItojk7x4QaNcC33R6w3Ux5VsrAWI07k1Izaot/tAnppcXpIhQaxa63U
+FQ63bVDm6eXefhhn4V/rMD9USCeIYkEkEGcGrZ0k7+UkqP20uRxu/NXQBr4wtD6U
+QHeW58YNTjGwCmnrDXxhArZlrrh2vFgv3IKGh9IfTH4a/HtphpeL4rUv8dRKHuSo
+FzCDGaqWdYCudDyxh3hYXUs6mXObjKnRehwe1xnSFAbRlbeQAQhM9h+ZWTbqQ7RG
+yJrvVkAea4RiwsfPq44ip/pcdsVQhMW12M85KImZCEiCIULO8VKCvHqMplJHTg==
+=IZXo
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    1F7A8F87B9D8F501
-sub    7D1BE4480B61E2A7
-sub    C2148900BCD3C2AF
-sub    CFF46EE3C17E53E9
+pub    DDDAFA7674E54418
+uid    Cedric Beust <cedric@beust.com>
+
+sub    50C6CC55C6F24FB1
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-Lx/KSjFhpjYYPWtx15xNpdqJ8g==
-=Le9W
+mQENBF8tnmMBCADROe7j1ZvgiMgfsQKqCSuSqgMkfMT2DEXwZKdHqkj0gfx8MPQg
+OP1pmMgpIwIXKr5kZ9KMGiGULNnS+WU2SNqjyKeq3MlnSYW5Di52MoAD7W4cHmry
+8ekaasF/x0AS5Q3M/6X/EBOD8YLWaFkk+h5x8D4IOSqiOiWH8olGjY4ZmGblaldX
+PLr7BWSrPKQ1QDsoICn583Mnjz3YLlc4p5IKnY2wss1zm7/gQk6KkdL5bRuASxLh
+to2adZ1LEE8MQfHweauHCK915RmMg7W3KW66/EsuCyEwZKBwq6rIpAciym2FngJt
+CPnY0o4IMFSasV7d1xSH5N4jeHL3Hh2Yd9tHABEBAAG0H0NlZHJpYyBCZXVzdCA8
+Y2VkcmljQGJldXN0LmNvbT65AQ0EXy2eYwEIANZAQd63jnuXS/btvoRXGM1kwaU0
+j3f2jeTg12sIGCUiiM4NcD2OnxWSKwvv6SWuk4/W+ahV3zQuTR8ZI51kNwgxvNZY
+KFExUyRjS+B4Oo6ArDSPp76Kyo3+82KmPaeHxxibir4sHoZUTSl8UKyszxEUV7BE
+756wS7DRHWpeE1gsjClFXc6/hnEOnXIzsoAdIFzzockfLW3guouh+MD5EE/x//rY
+yZJEotsPCu4vP/TanR9H6WnYOIn8g3jSUarV9LFGNcxNCcj5sh2x3tOVjQBtPpE2
+SUEveLj3aHFTXzx29rU9kzSzEAxlFdK3pwUK/P+MO+V/qMHoOY3XwTZp3nkAEQEA
+AYkBNgQYAQgAIBYhBHzVK1qClRN8iPtXSN3a+nZ05UQYBQJfLZ5jAhsMAAoJEN3a
++nZ05UQYDBsH+wW9ifWjlDSv6eB0wksKNBhPxrq7LxIfw3eTxGxMn5p3RN186gbC
+/GX9IUHUwSMRWleBuiOO/TWBUOiVrY5shhJf4ZZy+Ul19crPyhnl/z8p1GsBzeHP
+uB/yG5RV6uLAegQQDvGLXiQlmnAI+Hw+IwyXkpAVa4bgPV5CfA6bnhwjD/2FgHdH
+uhUj7ZMeWbcICUVqWxfNnU3+X8lAbot8+Qqau5uv74W95fHqLONmyx0WJouDh2QB
+B0DCCmYWYJAdvrcEIrOo/APGlrOmTXA/pjmiucu78hJo6j1UL3KVf69Qr3d6rgoA
+W5SOf8mTnm2l1QQfyZbXZbpSSO30XFVvxlc=
+=hvNT
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    5E975CB00C643DBF
-uid    Xiaoming Jia <xiaoming.m.jia@gmail.com>
+pub    DE453E55DC86FC9B
+uid    Touchlab <build@touchlab.co>
 
-sub    91A4BA316974A467
+sub    A947A3FCB1697B4F
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGNBGHvIbQBDACpPdbz5UIVIWR4cfXyyZEMOG0ayCzJQPsT4eq8XR0o5Y9egfAq
-dRXC8paInsaF/iVL8BJY6CNq4B3dUfJwKDcJiCiPbiQgknqF1HDBqQtCb4akW8f4
-Am1Q6qWxTcJBUtVjjlTMoWcCRwFNP1229ICL6XdfM5djqxOuIcCMIHC55YTldrDK
-5WWgcXC2NZgUbRn7/8dpaCn8iFAyhYjYKAk1lS8kSxCDvQNU9DtdAWtaCosoWBZ7
-mWWIeWp21erk4jgC145GujHYeqynf7VmdIB80u5OeIV6CwJx2ap8AgrKcOCON3Kp
-kYa7fsDGxq6Lbzbc0rzaIfK1wyGo56dMySDK1eZuOY9Es/wzaYfpzx88gn3rrcaw
-HwTKBoug+9z09m/rWy1DThW1gruYMUrxjeyhcdXlEeVrv9EdNCbbfKcg6MbrZ1mu
-Wc9DIAfSQ40Lv2sKxTyubZXxvoyEhD5LTqSKC0tRt9xKjHWWWSG+cyhXu/2hYmp1
-Dq7XvS1p8NKjD6cAEQEAAbQnWGlhb21pbmcgSmlhIDx4aWFvbWluZy5tLmppYUBn
-bWFpbC5jb20+iQHUBBMBCgA+FiEE1fRrwLhq9dxW31jwXpdcsAxkPb8FAmHvIbQC
-GwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQXpdcsAxkPb/HBAv9
-FHX6iGu5bNqqNJWeaX3QontSlzC20Ef1Ub9MGro9nyk0yRSpp07e40YvLtSWBZ/w
-AXQBSr3xSiKTmhspGpMfKjtgYGIaby/EIJnds+08EoNS8g0k8eNMKR/kJ4qbIbGT
-6Q6ZLtIx0wcqamwLPlUpcjFrQ3jnW6Uu3Q7d34LBItjU7H0ZdmApXb3aEBUah6hT
-ERhW+nzKSfjqaqQl3BlWausoCHjmFFgb9AD6u6skMWEH294Qtiht7K0VhZuLQF9L
-5ZtX/WQ75QVbiBDBkzMyKQ77B00lAV/pT8d5I3+FpcUs7V3rSR5nlq6LNkk5Mir1
-dGcwD00OpSwOko1TWLTPHW/AvORz/mRa5fraqEytujeRdOl5nQ/f5IeQqcg4ga9Q
-JAMxCA2WZYe37hc3SfAobBYFe6BPk7JPTLlRLA/aohNhMVopQ1HwLAB32+mq78p8
-gPc9LTnJOAUPTfOY8TRz9D0w0DaokrJ4VYbd3n0Ds6NPXxA+w3gsHsvIlNYHOsn2
-uQGNBGHvIbQBDADNSRxyLYyzfkdxF55RktDmgSKq9tskfR1QcrQgWvi96fJekLYL
-/a2hmJnbfUbqaILnkyUmIf7zONlCFv10U81prG9wxfXUTMuabpp+eXUFdbCZMc7R
-9JGXw5iaRWje+jh/GaeB8xY3cPbtfHkXZ7nWkQaq7b8DutJrAqo39NuprRaaujfU
-9PXj93tunJExqi2w++fjT1aQ36PaplXRZ2qWiRxAkaIUGxjVgLuOY1FWZJjWX2XM
-ypMesUSfUCV9IwlKCc8+55m4jfbtblPQHkbe5zvstxxfHdYQkGngp1rNWLHHSCT+
-Tf4Y4aR2J/E3mp6wSBVxgfguS3u9h1mY9fEfe2vSHWkWmYNm4iDAmsPn8KTuccbZ
-lB/cKIFS3AET8ZHwHqHuCb4TvUy8febp4yo5ZRniTVQSf2aA/izuwmKSmq0bX0hj
-GRBVdGR2jlD2ND73lkJXU7+3sIwY1ebNVzvl75Y7slmJNHsij24fkeZtcSmRQ7BL
-7ZpZ3fYiyi1/MxsAEQEAAYkBvAQYAQoAJhYhBNX0a8C4avXcVt9Y8F6XXLAMZD2/
-BQJh7yG0AhsMBQkDwmcAAAoJEF6XXLAMZD2/kY4MAKDX+NsPosjHt95895Z2H8A6
-JXOEt2F/LqUZ6XOqW1AAeLj+cGMWBDDQYNp/IkizV4iMynmlHlzgYivT+52xrUvE
-zOqMRUrDNTPrbkLUjc/Wm+TA2J2ZGUSjZZUmP1sBTqSIa1NCqWl1VRWZcmbckCHz
-5oyoeXKM0EKGnPwOZP0lf8M7f6QDUJY5DS/5RTIp+6BxHhtRi5uZBN5QLcamhIAD
-wR9fIlfoFfXEwEAQl5Z2YTnyMf/6/5FWVgAS1PPFqvI9H0HiWPx+XSfgJV6K10Gw
-RTtdhT12M4teNFsFUNhngsvO8WCZKsxz4CV+Ai8bSMmWpNsYk72CbRMoEHMrHuVX
-KKaKv70eFd+BaGTuLPd8hZgsDuKxU83OpS+LGOYV7Lb3sZNEeqWasWMqjeQC/CzE
-AE+Qfj0RuucswEZGZ2NWvwouGJcTvLAKaUelMr5IuWTkTZYmXww7ffu+Fps7qSMn
-U+mxOl6TkfoQw/cNRpZdMqwI/7119TnFeK5/AORupA==
-=QK1G
+mQENBF7H/6gBCACbEuIbxWAfHEYViPqdpwxDYauxsYwk6FgA9sSO1nS95KRwx+Cs
+X6F8nRGnfLtbo6Ffcp6r58fNi9RvY7ueRGiL0kQd6c5GYx6dH1b91Q1qrdVOeEdj
+vjHNVVXAlk1TN2oxFB81cz737cv2CTX1ibEO+qn8oxwOssgNO8ic6szJGorFur/K
+pCin+E1orZiL52+aSNtOsmzLW7qmL2VuDmoQ5guPfX7l6fioCwnUB9VA2LhD2Bm3
+oV4IhhH246CZ1iXWRG+vzCFDQjjPG5oPJfPvXtTmSuD7/65vNlrRk9sAh2p0BG3I
+i0k8304elsm+HnVIUDyroBjud464qc+iY2bLABEBAAG0HFRvdWNobGFiIDxidWls
+ZEB0b3VjaGxhYi5jbz65AQ0EXsf/qAEIANsauQOn0mT4U9pX/8bpLLmhagrX7ceH
+DRpriwoJK2uaL6DjI9DuXoziEuPxxITi7pSVHAHyz8UYHoI02qgIk+Gp1MetigoO
+dkpQ4sv7x5gKdVwGgV2sk6ZvHqDJoF9GgqP4TM8iBinCeED5690ghesVyzTfpguk
+BkQwquFMA9OIXcxo6GNP0lxPUtKzIAGL17+v3MFCDOvvXxiC8yZx7vacq3va+nW2
+KM4e7SrdrGL0jkti3s7MGxI6YKBSd0hv4k8iR39rETvt/+3Od7FMoRQB53/G1ioA
+6D5998a72BGmRkVsU01MfeIC8s8+DhJAAXd1Dl9LBPQ0RtperoVP5pMAEQEAAYkB
+PAQYAQgAJhYhBLL5Z7Z9rcHwcXLb2t5FPlXchvybBQJex/+oAhsMBQkDwmcAAAoJ
+EN5FPlXchvybYkMH/iFv+1oyf7XvvoN3gNHMlXCJdjrOnBSaGAyVECYfmqK+PW9g
+rYK8AIJ/jhUfTeEqi5QiP1kAC4ccmOoqoEcxb4AwifcIv6SX/aOyPz74IzOIS0EO
+ySs0Upg4eRCLSj5oE6/Yy863zzXz3QmlwIgdoKYsie3b2T2vs8qAdKIUEXnf8JAH
+bILPCKK60DWoT70cVTI0JW8qwgALM6ksLANTX37wtXFus0P+ez5NqHvdYdCvG0p5
+O3pphg66GOojGM89MmeAHNKM0NSY7Gj0X3mZt99DaHUW6CYojXEFmS4KVh3sLABy
+WOkXEcjpGiX2xGVNsMm8BfhpC+sWqGUP6LVfXY4=
+=OGBe
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    40A3C4432BD7308C
-uid    Michael Schierl (Maven Project Release Key) <schierlm@users.sourceforge.net>
+pub    DEA3D207428EF16D
+uid    Dexmaker Team <oss@linkedin.com>
 
-sub    C0B9C2CC3DD97C16
+sub    E8D0C72FC5A02B28
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-ZmnjA2cUdtHLvchd4fiFbu191pbeIk/BSf10
-=kJKi
+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
+cC3sdpmQC3cCkiZvIESNRVUN5oUSjxbjMJ3/
+=bFoA
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    C1B12A5D99C0729D
-uid    Valentin Fondaratov <fondarat@gmail.com>
-
-sub    606CC6C4533E81A2
+pub    DEE12B9896F97E34
+sub    9A716F957BC42546
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=Pyox
+mQENBFAxQKwBCADJGPv6pmFEq0SDwAKESEgCdnXycbR0bNXpNa/3VGboNto1xKgd
+AQ/sI5x+CmN0hpUjklEwff6QIt3MlofEMkAzSfRmTobhJTK9W7r4+p5DuhJpi5Wz
+ITdbNCMT3Cvp13rRE+dx9qY+WFQmTYPf3gq+C6T8Q1i35ePNlCTN2RayaFxxR77D
+W93zKZDdd7I1qH0Vx7GGcSwBgBlEB8jmhNAkz/zAhv53S6px3ZttqYYmuwRtg6Fi
+i/u9VoDR/c9tyUq8L6oAUtg0mo4CP/tfUF/uZnibshEsLzbRP961VQXduhn8HcRp
+k6QPTj37B1vsNWJ9U7XXJ6pYnkizQo7sl5XxABEBAAG5AQ0EUDFArAEIALyNR+z1
+eBBF4S+dOEWKXz2ANmsp6RRhvR09QeQwNycVdbdEXpOiSZUCAkw/EhuJWmHBngat
+0KBO+7CIHyQqwHnqyatizzKXi1OuaEhMzPsQMwPRfYyWHgN0aklc5oOzB2RbSJN4
+et/oVvfAplVSjgR0v+56+qXw9TFlp4kxqFeJLycZ+5ImKQ+XclsBokKuE7cjeF+g
+O5oY/CFHdkxD8d+cLF8FSNUFMypuDQ4IH9zPYGkUJqsb2t67iMyxi14RqyN2YNqK
+JcwxTL42VBlUFlTBoF2Y3w0LNll6pR2WSNvpcj+5/uBjtY1qAj5e7yVts+d1YZsX
+7D76AV742RQ31kkAEQEAAYkCRAQYAQIADwUCUDFArAIbLgUJB4YfgAEpCRDe4SuY
+lvl+NMBdIAQZAQIABgUCUDFArAAKCRCacW+Ve8QlRhFDB/9xE/cXf5fVaLa598xL
+muXiD9U1B04dPdz445/chdDS9iGWBB+5QVvAqv2Jt0hyPN0+n9Mk/4lLStEEL8TP
+NLdTBP1JRvVWC1c+G3kTJq05Abj8CGFFm1UZhFRwCTJ+vrv8fSb15s+YYxBLIUdl
+tKld6OupTHm8A4XJQOhYxd5PHs72bJ3bXs4GmPLKD/RpYmXYJ9EZHQHKnrhZKJ8R
+JKTM6sxBrgdVeI1K0ekA0o5HAVpNEXgY1gG8Pa14jqK0iwlcI02ntqeJkobvv1wN
+vh+nJT2wM5QyLH737kdPrUdi63PfCYLOEHYhI6sFkzI/DAtI/C3wmHtTuRam3aLs
+Rnb7GNQH/i07ndoI4trmUor3X1JBbcjw2BVS+idCtML3jhKtziwK2/kz0rJqBQKa
+Z/zxgEfwkRPqhXLaBW8a1G/d1mGphazHqSaDqylz07XqR31ZtGCc6256anaVbWaW
+9HXUsU5ADNrAK9PdD0EibGB8YumuSTtApICUqN5SVz+h3Mi1MXVsmbiVSAZPzLTD
+0YRwzPJ3jiXIrKDUmZMM7oWwGx6nzW++tW8aKyLKm7x1/y8g+XHvySQiVOKAvvxj
+yPStkEW38Rls5nucpyLzLjoA5vlyIcOkeKCy2jlUmM56YrAIWNn/eCRFPHMOY1DO
+B1nUXMr+2W21xZO+/sWrEEysY0mdGU0=
+=uzFx
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    5F69AD087600B22C
-uid    Eric Bruneton <ebruneton@free.fr>
-
-sub    0440006D577EAE4B
+pub    E0130A3ED5A2079E
+sub    0AE7BBD7FEE66E0C
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBE7JURcBCADO+9Dc4/JnB+wX+fq+Fr2zUGSPOT6/qjE5kXL4FEbJKsqDSAKG
-VnbtRrsIUdmNIFQmz71bBDFhRBbrSrkz927k8eUPhYtxE2NmmWSuKgrjF4qviPQv
-m/7SqGx378m/qw4EvpgGUB8EYif98LYdWp5vsU/zx0Ps9auqvetAzJaL9489oE0F
-q8FVhve6BMfUUV7zOTCmJnf438YO68upjU0PVBdfFE6Qx4cgCeWbQGy2cooW5azN
-iIenhuYU1qikmxMHq2xZzN4uSTWLGDpimPyz+Y1aTSYJ/bgn9gPStbI9sojWo9SS
-5gvNK3XqJzMwxwFow86UcIE0vPD2T6ZlBAXRABEBAAG0IUVyaWMgQnJ1bmV0b24g
-PGVicnVuZXRvbkBmcmVlLmZyPokBOAQTAQIAIgUCTslRFwIbAwYLCQgHAwIGFQgC
-CQoLBBYCAwECHgECF4AACgkQX2mtCHYAsiwWdQf/ZDnKejrNUOREfAZQYoAmf29G
-zPnQ2XVb6ZxoD2kg+b7SyzVL1lnpXw961Ayme9trxztb9KJcxJ6a+oSVIHWoiINS
-zx1g+lXCsBRH3Lb5iJTAr2u8+Gyva9+PB60CBmmcsuOjuLBx21N0/E4KpBiwEoWw
-5z8HGNVsa4jtRxB+RoQGiilBUIelsI17e3hQWgScIGJdLW5xErlC3WfgtUOL6q4J
-mSk/A1R2jmWKOO+WBvGbnOr7mKZd+/h4ohzVVwyC1WrFeFJgEZK7bXPA77Iv/4u+
-al7RuVztBKjrXD0yPwknuxMgyN+Y5f/pqqKncNl0lOtiWayKSxdatBLmGifAgbkB
-DQROyVEXAQgA2uNV77VI+ARj1d97b5cY3/er0Mcc8/Q9ctMY+5YpSYDOQF100QBd
-OQ8q3IJsfhZeF/iMFlHIUikuSgatb/Ih4lk1+irnERPuV2MNoAw3Fvn3/vwl/Jy0
-ZsQCBSXO54U42TcOXSwNLkYOJaomDiiuo61Rxj7jqijpnydwoFvEi84v6q/Uota3
-MijGMbzU9QyTX8J9OKMeCSUq0uVuk4ezebjv/bwA/ax/qQRIrEHDOOB1LJ5JyLac
-K4+h5J8tMkEmWxEQv7MNokRLgbaePqv+tdf1gee4f2fSE3EXKFxjTO2wjLPXCrHS
-SI5gecsilQn7ZNxH9g2YUJipn9yj3ywMxQARAQABiQEfBBgBAgAJBQJOyVEXAhsM
-AAoJEF9prQh2ALIsrWwH/3s8uN8/gDnbcbTX+7N/ZfQBXJZ+H9GGikmYRJE1xoOe
-Et9MOqZyGDTZfGM/qNKeDGfar7pcRQlMK/A4Nts5E6d1OX8fBkUBtYanyyjNLlT3
-yDjO6VaV0SCsgAzNjUZqc4lxS9atN6md5m6lWLAdHghrXuV6LsiKOS+96htchoCv
-Tvm7mcPI7w146yJRSyCC5+PybG3ult5Y6QASkwI3ZWB0u0PKUoqglwWngplu+0Fi
-b2rxQvL32is4YrYaZ+XwoR6u/Bgv0ZvZiypk17Uk17rDb/JfeLqDn7oW6Hlgi9KO
-LbRRIg7vwZVo2Ixco7aGxZp5c4zSfaPvn241v813ZcA=
-=A2GR
+mQENBFlMSXMBCADcgN0/57D/gU5cDobPiRuDT6qAxb/NWhQiqwAocKd274r4gPJm
+RbffUEZEgKhjH6l0CQfilC4R4x2QtU9sNC9kB/D6zumoS1uI0Hmx1pC4UseUy55r
+20WDxujUQ7OcJbpe2cDcQVKmMok2top7ZJqt4KVosQEeT9jjsgBBbEtg4cWb5ddR
+5rf+aJw0v/6dMLef1r9YAo0ZtLc+g2dyacqw73tcWEd3oCH++SgE26NntN+GibZu
+VXSE5u6xI4KwfT2vUT3jt5Fb29myX4sxsfB7n/xageuJYy5ms1ABS+WDO5ssEZC4
+eQEVL7eyIb9YhNAW/WtjeAuOfOKNonoqKFGXABEBAAG5AQ0EWUxJcwEIAMgrP3U+
+7YCibxSQKOZrp63RaSUkv7mCvQ3Lx4P4ZD/sDEsLOiKkAc+ZU7ETTIQkEpHaibvC
+ZNrA+R0pfAj0LYBLstEIkUxtAaVM4DBQGN13Zdup46fI8rPZEyZVb2XpZ/qS4RYi
+StFyJzUdazBJs/IB7CT0xp4DUFUOrsykVy0aWzWt4z0QBe1x3AmpAO/DdrDN5gvt
+mWzWbV3f783PuK3g41ju7F9XX5nuuatNSNHOHt65XL4vmhmSfXuP6UFjK6MKzq9z
+pbZD4ipUPoKEId5ONDSucX4C8OydpC8+rFWJCDDDvocox3/l6TzihQXf8MDDcB0u
+1TgDPz4M/S2vBh8AEQEAAYkBHwQYAQgACQUCWUxJcwIbDAAKCRDgEwo+1aIHntk2
+B/42pBknUQB2YjkPryJ1B1ArcxaLO7gVo/lgT/rLGL7BuTYsFIl9kJUD156EfkmS
+AkfsxPzwUNh/GyfVQt09F6wheprx1fLNJCFIYA9ZA0WVZGSwbE3NdiuwEaJ3/HZ7
+7IteQh5LKllqFuSlZ3u0xdtGJjnAUU9wHxWH+0W3RPm62piSJcWUw7CSqEyuX+8Z
++eq4HY0v74znfy6GyCiil7S1T9fdan22hP3xiJHgVKtyFmhhrz6YxcZLa0fYl+R3
+mCQvt2FuiaLL3d/uH0z6EzWs+XZNbjRBTGI9VmO7siIy6rjatdult3Sx1quBCixC
+4Ms2AWEA7bMqvUmCoB2M/0x8
+=6Sqy
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    B341DDB020FCB6AB
-sub    315693699F8D102F
+pub    E0CB7823CFD00FBF
+uid    Jake Wharton <jakew@google.com>
+
+sub    F3DBCE882C3A01AA
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEowbDsRBAD2jx/Q2jNuCkgiS3fzIj6EzDP+2kipIKH2LEnpnTiBlds2PFYM
-xYibVab/grgQODxTdDnAKifbJA/4h1/T7ba+OV+xIUoSI5MbgaF3USidiDHPX0pY
-qvG+k3hKECLysQ2zoZpcC8c2ePiZQSVC2i5BRqgs0xZPz3kiT5U9WPozTwCgtasB
-TgHhkOGhZ0SOUuQ4dL54R9cEAIaDjdPcI7LxyOMvvGTuW/SaS9JyP21Kch+Vf6I4
-vKWWqXEaF0So8S088zHnBrcBKhu9D1sKIHS64EoYCrznfMUtoENPe4sf5QuJmZ9D
-+fBuFcudQIpkx8L73q+E3fmCK0uX+anqipJtS8mgpMeabKda4KkjDsZkiaNl7OBI
-0H09BACofK1HTNHNke2N0wXN1GyG7IAqprKl4lBbu5aRXvfKQ2tDj8s5webNQ+Se
-Om/Yg0Bi+CiONLgUjiwYe1wNls8zkk3LwYFeKIJ1AjAY3auBRWOI0/IFFzwTkV8J
-YPHa3Dl/kmYp8NMMwA5bgrblggM0Qhnp+k//xpb0FYbmwHMwUrkCDQRKMGw7EAgA
-5MMlt89bomqE0TSq63JnPaSeEKsAx6A1KaXaSg0LEI7fMebSQcAdVdAFBo4HaR+j
-NNGv5JGTvAObLrqxnn5mU/+qhdTw4WCf17R4ETEKc3iFN3xrpxz2Vew8ZWpw3PcE
-gCe27ZN02J6BgtEqhT9v9f0EkAgRHIkcaFCnxme1yPOFN+O0/n1A+59Ar8rmwcHG
-opSoZlGDEdEdqElx/shQjqq6Lx3bWYXS+fGzSAip+EAX/dh8S9mZuS6VCWjLx0St
-a1tuouq9PdOz5/4W/z4dF36XbZd1UZHkw7DSAUXYXfwfHPmrBOrLx8L+3nLjNnF4
-SSBd14AfOhnBcTQtvLuVMwADBQf8DC9ZhtJqHB/aXsQSrJtmoHbUHuOB3Hd8486U
-bZR+BPnnXQndt3Lm2zaSY3plWM2njxL42kuPVrhddLu4fWmWGhn/djFhUehZ7hsr
-Qw735eMPhWZQpFnXQBRX98ElZ4VVspszSBhybwlH39iCQBOv/IuR/tykWIxjPY7R
-H41EWcSOjJ1LJM2yrk/R+FidUyetedcwUApuDZHnH330Tl/1e+MYpmMzgdUGpU9v
-xZJHD9uzEbIxyTd2ky2y3R+n/6EkRt3AU9eI0IY1BqUh0wAuGv/Mq2aSDXXNYJ/p
-znXSQBjmy2tvJlqXn+wI1/ujRMHTTFUBySuMyZkC0PwUAAnWMYhJBBgRAgAJBQJK
-MGw7AhsMAAoJELNB3bAg/Larfc0AnAmQbEg9XnLr/t0iUS7+V7FcL5KpAJ9k3LS5
-JI97g3GZQ2CHkQwJ3+WcPw==
-=OasT
+mQENBFsNoY0BCADIvRrJEX3k7UeuT6zt+F4++xH+5Qo7QzdicjFhhyb22PLPyIsI
+Ema+T4QqiPDegUv8yKKTTBmHNw/vSUHTPX9ZUpglckopuOgdfnuQjTKEOEzrN7V/
+ZGLB8yR+BoKEJBLdp6W4fGHIxza/o8Iwg8nV0/C9X1gvQI0I63aexqqA5Y0eYt4y
+12mQur5sKabJRRWxkn1U8oQmcFs+P/KPVtS4lUb1nsGzFJbsiKY8AOI1RbnYgtIu
+c6mzpiUk0NPO27xKScyDq7lKBwwOZMwRzX/6yX7jcAtyTWZnWS675MCbT2K07ubU
+Ykrs9NObwDXlKZWLk6JuADgzQaueYIrjLRYxABEBAAG0H0pha2UgV2hhcnRvbiA8
+amFrZXdAZ29vZ2xlLmNvbT65AQ0EWw2hjQEIAMvs0IpYeLX3fWxo7uRF2s4T3juq
+cyocto97QnyZUsixgTQ+e0ETlwFHPdUBSLtwkbqhdYpoN8RyUo9vkGjLZJkD0znS
+BS6xea/WNJj18uBP2QgPXNtM1Upi8pEReZ5RBq0boYz+jbd3cbG5TDAEYQolSmCg
+Z2TuugIucMYP9NumoKDdidEwunGjyi7Spk7FsgdrF9BapdaiYrSQqAsXwpH+m1b/
+m41ItWF42fW/mpOk8XaEdzGA8xLSATpQ89AWnYi93fSr7ETodUffn51n36fz16M5
+W9CM1tHMdHa5gmdLvRh+Bx1MU985wxTiDUfwDN+6k1fbX+t84ULH6asLNtEAEQEA
+AYkBPAQYAQgAJhYhBEe/WSJhzRqKabcDtODLeCPP0A+/BQJbDaGNAhsMBQkDwmcA
+AAoJEODLeCPP0A+/SUwH/0Osdy2hl3iII7OJyO//y3eL1kzmj7PyWj4sMJdK375U
+bs5xsUct/e49qU/Q/oz0zig+lHaYSnfLFMx4qpftW6VMZ/iGl/mekXoCdOrUxZ/0
++srpfJMpIDJyozdZ7n3bFtlq2no1Tbm/kyUrwu3M8Q/a2Lkh8jwygLBGqluz0PfN
+sAECAGlxpqGwS1vWjrhHtPIfRb3UD3Ho++OFmz5zKKObjs0x7AlcYIr7Oe+Da2Mv
+TMgZUgKMGqsJhvdHsMqZRKV6aVbSdPs3PJgt8UtD2waA4lLRA5xlLdgTdN5dp+Tm
+u4awI7kDfdqz1V5s5prLGlkoPhACUxRZeznT3Js7NVE=
+=ZRYf
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    1DA784CCB5C46DD5
-uid    Rafael Winterhalter <rafael.wth@gmail.com>
+pub    E16AB52D79FD224F
+uid    Google Api Client Libraries (Releases) <google-api-client-libraries@google.com>
 
-sub    7999BEFBA1039E8B
-sub    A7E989B0634097AC
+sub    5A34A5E06B936F93
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=gRaX
------END PGP PUBLIC KEY BLOCK-----
-
-pub    604F437C1682DDE5
-sub    F664BA5FCF7560B9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFv2vg0BCADQzzfU42MkbydOEese82s5wyfs/qkUZOQatjwPMyEMlK/H7LZc
-Bk2ZOgBMaDDdEZv2Vq+6oUa/rD/Xmr71gCEk5U1rqeZZ4HuvyEZjjIisjnVrMCT8
-py93im2MJb1zifvY+rgiveiVBNCjSkfqX1/g7HmGiYL30romA/io3jvtWOo6PkQf
-GYzifOKz/5j9oWm1yqdXuhVmPD1aUkpXZeoxfWDpaPS+iUm4Db38umVj7GY55okB
-rrfQAdAUuOG9dyseIgI4HPZMB562Qy2tww5q+PvSxs9ydgSbFHFu1ejCmlViSeXL
-leGPJEoiRdyu9zMW5sU68lxhErtFRpa3IORjABEBAAG5AQ0EW/a+DQEIAMiknjyN
-qHzzG07PNE68DSlUuMvraoyJSkcA6Sjsg1nTgcp9jubqekXW+ZHnNYWZJSxZx4RZ
-wloo3+A4skthmDVh2UN/FO9Vwx1EGkJuyaKELmIVBRSC4IBrVrQ/4/nUXMtG9NhL
-Qmgug3glnlXYg5gqlQc2YjNiWI1zdYmR7pHTxBhDYLB1hweA8X7SH690HDevqhiy
-/qT8YAHZzMZaauj/xQHpvn4uN5xpGm1eQw47tormy7I/1QaDW3pbS4YIC+Q7gdYd
-IA217tTgN5OA8+kXuPJJQKDMG0WtEGegYjMMuNh266HMtfekJVSlJTRdIFQT1j1U
-0OLjrk9WRK/ZcrcAEQEAAYkBJQQYAQIADwUCW/a+DQIbDAUJAeEzgAAKCRBgT0N8
-FoLd5RodB/4pZu8Segyb2VhGYbl0jgmZFqMZDI9iPINx7oZ+09Ck32R6UJgaiaTw
-KT0qeEssum3oj7zz3r5D0s1k5pwvd0w5TLL8CeQ7NxTy+hE+8cHZbFfoMBlnr73c
-UhedkZk+Cf7dm/GVkv1ERr/XnL46wLO3OAMamh2wwo9Od2GP58ZFgFd3jhroIuTt
-YtBVeB21JO5eaktP1ZLi7zsGWcP2mPkQAnd7BtQGwjh6x6M+Xhs/mZEmLP2/nLEf
-oX3eaWU6uE54giiHDC33rBGerBuHGeW0WT7wzatKPz9S51w7mqPXLYNmw7/Qwfvi
-Ca2w4l1R/HAaNTH5suZ1HGKy1nNcY6aA
-=fcxU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2383163BC40844FD
-uid    Roland Kuhn <roland@rkuhn.info>
-uid    Roland Kuhn <rk@rkuhn.info>
-uid    Roland Kuhn <rkuhn@ph.tum.de>
-uid    Roland Kuhn <roland.kuhn@gmx.net>
-uid    Roland Kuhn <rkuhn@e18.physik.tu-muenchen.de>
-uid    Roland Kuhn <roland.kuhn@physik.tu-muenchen.de>
-
-sub    EDB3D937B0C94C3E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBDwczzwRBADyR8BVt1SUMHxjSG1AAekABO0YQHJG/XwEHYk7zPH3aU14/ocf
-g6M8gxZXumM2f3oCCkmOpnW6uKxqTclQX44GyaMDETcAU5/bjWenWNj4INDlTjFS
-aWghWshotoGrfYsJFOctk4mBZKKW0+P9drC3pNGpfNYogwL7qYUdowyyRwCgwBTN
-+ivnfWziygGHvdghntgOBHED/2lr7y3fJ7xGMGfg0UbHbVYgWKegKTUo2/Wxerzd
-H1laNxjZVl74NuHamkYTGuhoX8S3TBKwFskZbJcLSEfEqwulULUKnEkGxZYTkEZ5
-/3tXT6aHj0OSSz0C00qjInL1ETdU4MNXmDKs/wRUfvL73dTPrsbnOWQDCYlk+jZ/
-uDr8BACgHVEhJV0O0TAOYDsthK6NJP4otlms1I3Ya6KyDp5z/DGaOXFy3yLPbyw3
-QCzzCdwwIPDcALQk6FkQ+E2jEpJk6QkCWNcpPzZAmIwX5Kvttb36XCjKHkLjImlH
-TpdIMl33dYNstoQpN/fLB3COnRKC+c+nI+BwgdhMOxANJfJV3rQfUm9sYW5kIEt1
-aG4gPHJvbGFuZEBya3Vobi5pbmZvPohgBBMRAgAgBQJFXDsAAhsjBgsJCAcDAgQV
-AggDBBYCAwECHgECF4AACgkQI4MWO8QIRP1eLgCfT+Ovm52g5u5+h3WX8zDF/lFo
-ur0AoJe6gBMpHfe/0OkjY6+zM5wUfjt9iEYEEBECAAYFAkVfSOwACgkQiDzo8bG8
-unfDvgCeNjVQP0pFlc5a2T1XnYLZoTwJtz0AnAqxisgS6OBrHYe2GVBMWz5GRntp
-iEYEEBECAAYFAkYKNmIACgkQAej4Rm/xLDC73wCgp+uB+dxcZfJxfcXm5Ikcl36/
-ylAAoNe4NtX2ZO29Hp2CW8ytdExSQfMDiJwEEAECAAYFAkYKUDUACgkQo7JDfsbG
-CyiKZAP/fudAPRtwaUXvdaZlAF2SKmCQpw8KLkiwvC7mttM07fceOHECusZWJtOT
-SNmngkNXtDJ6KOi0I6ZHr2vLOBPCIH0jMA1e3bdVn5JP4bG3T+NZz8Z3vi6xTgB7
-3wj7ZrCqReA01Lppzy60OBOP/OgcA/RFzV3Si6N/6NlyicETTBOIRgQQEQIABgUC
-RisTwwAKCRAIeBZRg0fR2h0MAJ4wFEZ1FVSuSIw9cW4bd22mwvl3rgCgolZDn+8z
-54YAAIWltfmI/fBMLIeIRgQQEQIABgUCR7Fs4gAKCRDhW01sacYWxxJ6AJ94gyuD
-dSn5qBINVpW/dGrupov3VwCfc4g2ivb3jiY+WHxqd74b9heXSMu0G1JvbGFuZCBL
-dWhuIDxya0Bya3Vobi5pbmZvPohgBBMRAgAgBQJFXDrhAhsjBgsJCAcDAgQVAggD
-BBYCAwECHgECF4AACgkQI4MWO8QIRP0W+wCfedFdYYmLszCN/uCPbNBCRX2TSpYA
-ni08UFDBgGD/RV9ROjAD1lMF3MtEiEYEEBECAAYFAkVfSPEACgkQiDzo8bG8undZ
-3gCeM8TVV8cQ2sUVBstfKBPz7bP3ZV0AnAgqRCxNcl4N2463Twq37YbSKtMMiEYE
-EBECAAYFAkYKNmQACgkQAej4Rm/xLDDnGACeOKCL5ldfQzK8lV+AcrorBm/+YMEA
-oKD3ek7avLPgfVO14H0zsySnZz+jiJwEEAECAAYFAkYKUEAACgkQo7JDfsbGCyj0
-iAP+ME15RUR0laBRlwjNxGCAoGL4NKRxB0VHyvpxdvtvvMvKOiB3GMdr+HRi0WPd
-dzsyZCQSLJWJeOBb0QM+7RiJ26XC45mTd37B7YXdPw9AInBAts8R4G9CVGOeiOD5
-7/UNmTmZylYhoGjn1oG+dBNxQKazSzbV24m6sbg+nh2fUAWIRgQQEQIABgUCRisT
-wwAKCRAIeBZRg0fR2uJXAJsExAor4w+/2hqJ7bFcuWuFZSIwqQCeI+ARW3/fehdQ
-N4TFOmF1GyMzC82IRgQQEQIABgUCR7Fs4gAKCRDhW01sacYWx3aaAJ9U+282/csh
-O38qshgmqGGdghe4EQCfXGDeq4aZ5T/xbr51W7v0+C+6lIO0HVJvbGFuZCBLdWhu
-IDxya3VobkBwaC50dW0uZGU+iGQEExECABwCF4AFAkCAAWQHCwkIBwoDBAMVAwID
-FgIBAh4BABIHZUdQRwABAQkQI4MWO8QIRP3/ygCguzKzkNEInS9NJ5iL3l0dXSdi
-ZRgAnAgxhYIf4GuTlygzkp43G6IdqXUmiF8EExECABcFAj34pyYFCwcKAwQDFQMC
-AxYCAQIXgAASCRAjgxY7xAhE/QdlR1BHAAEBacUAn2YmoLBvbAfnRMZxyHRVB6eL
-XUHJAJ4ksnQnpwBLZt6fBdUL10pTn6OMxYhXBBMRAgAXBQI9+KcmBQsHCgMEAxUD
-AgMWAgECF4AACgkQI4MWO8QIRP1pxQCfZiagsG9sB+dExnHIdFUHp4tdQckAniSy
-dCenAEtm3p8F1QvXSlOfo4zFiEYEEBECAAYFAj3+8eIACgkQbxelr8HyTqRJ9QCf
-d5To6Jf+D4aWp9L+8PmZjs7MLzoAnRIopXzVt9H4pcgR3+ocqsTHwAwNiEYEEBEC
-AAYFAj3+94kACgkQgh8b4WEoxraPZQCgmuSblXHMp4hEmdv7yxC03kWQm9EAnRJo
-Ff4ox3zvsFjLrFhRvA0hlPoniEYEExECAAYFAj3/F7kACgkQa/m6DIbeOrctewCg
-uqkEjaufmB05gzdt4C2aREAA33MAnRkiEFNwtWEQChWETO2VUBdNW/tsiEYEEBEC
-AAYFAj3/T6cACgkQJhnUgw/SWV9K3ACdEVgs1Pi0JnCEdVt11H5lCYdbu5QAoMij
-Rugw6KhzCVHFlmtupgVEmPNHiEYEEBECAAYFAj4Az9AACgkQOYk/iYyUuL42jQCc
-Dewb/MBsG4zsqvnyn4rIjUnOzHIAnAxsbL51YvY37+ZEZhwaQYFOj++1iEYEEBEC
-AAYFAj4Az/gACgkQUlz1cr7NWzs7xQCgxlFAq7T03ZXmBoeDmhmcMWxGDDAAmwfc
-R7E4sNgzaTEeEXtSiRDnHFtMiEYEEBECAAYFAj4CGPwACgkQJpmyu0pQGyC3AwCg
-kw9Qmv8izc3cjrE/pEA4uN+VzOcAn3oKsTF0Sq+nTWZqoIJrCbs11MQfiEYEEBEC
-AAYFAj4CKSYACgkQTAqriu2jaAnjKACePwN9qSMuFvljnQXmCaPTzsH33iEAmgOi
-FnLyg5CK/91cNrAzVjVWQrZjiEYEEBECAAYFAj4DQVgACgkQ4VtNbGnGFsfIuQCg
-u1RvEKGZGPX+02TWFFj21C7lkpgAn2yI6JZ9PpKDbkCYy9XpMMder5GHiEYEExEC
-AAYFAkIMiZgACgkQb35XOFRiJB5k1ACffZzS9jOlvZq5JF8oXsPNFw1ZtqgAn0C5
-rEDcl1WLykhK6Jd/nvxUyijIiEYEEBECAAYFAkVXgpMACgkQE3GHdZhAp1/kSwCg
-/SbqwsZl/d2ivhixpbkw9R+vHiEAn3seWkrOSyMpwixYM59WlAnjqlLciEYEEBEC
-AAYFAkVfSPEACgkQiDzo8bG8uncKegCePGIb+c5cbTHbzev20ppJy+owjN8An0sL
-0G0NOcmcOS8le4fZJTqEqfH/iEYEEBECAAYFAkYKNmQACgkQAej4Rm/xLDAYZACg
-oO0sLhOtIUpy8EitufoAVhzs/40AoM4gzpyHcejx3Rp36pmzP6jKB1JuiJwEEAEC
-AAYFAkYKUEUACgkQo7JDfsbGCygSZAQAmA3uagEpciDboJ/05MiyR9lBxgJ8eIzG
-U/b+tdPRDphsqJBl/CXNDnjl1BF/DKUkeyw91EiefR4jjIAL5yxe2HjbXdd9N9xi
-eNd2Au2JHZTCRgIHg3ZwFGFxDHzhG8WAhOw+NBUZ4ZCg0VZQz/U1x4ceYt5o2ZYH
-tzwsE/NOlkGIRgQQEQIABgUCRisTwwAKCRAIeBZRg0fR2tQsAJ96mgLfUYv+6pEq
-p7k8yqm2D/ooNgCgwroahKwRNbHQKbvlJ6iNjI+SP360IVJvbGFuZCBLdWhuIDxy
-b2xhbmQua3VobkBnbXgubmV0PohkBBMRAgAcAheABQJAgAFkBwsJCAcKAwQDFQMC
-AxYCAQIeAQASB2VHUEcAAQEJECODFjvECET9/nsAnRoRp5GZJ57GBqmQxI/Y7kdk
-HgtkAKCMTYmCt9D1ADzSFiI0V7SPxLomLYhfBBMRAgAXBQI9+Kb1BQsHCgMEAxUD
-AgMWAgECF4AAEgkQI4MWO8QIRP0HZUdQRwABAWigAJ9DYiO1XGNPcfGbnHjlt2Wk
-m1EWrgCgpGemTUJbW3ulexv4LP2cNTEdnwaIVwQTEQIAFwUCPfim9QULBwoDBAMV
-AwIDFgIBAheAAAoJECODFjvECET9aKAAn0NiI7VcY09x8ZuceOW3ZaSbURauAKCk
-Z6ZNQltbe6V7G/gs/Zw1MR2fBohGBBARAgAGBQI9/vHiAAoJEG8Xpa/B8k6kOogA
-n1+SdDs3i/gDTyAPu/uRNbhcCtdjAKDT/X7Xx3v+RYSXcJhsAJV85+aXK4hGBBAR
-AgAGBQI9/veEAAoJEIIfG+FhKMa2js8AoKX5mEMU6cP9T66vT0fLOL8n2AtFAKCV
-eYhLsREx3hwogrsxuhS6MKHzxohGBBMRAgAGBQI9/xe5AAoJEGv5ugyG3jq32C4A
-njQCqLF84g2bHCejS99uYg4A5upbAKC03B0RS2tBJws20dwevanO0TixQohGBBAR
-AgAGBQI9/0+nAAoJECYZ1IMP0llfNR0An1gtNYtsYmweTKOWBhbyU892aflTAJ9l
-/pZSPM7aSiUPRqOic1/J95ssMYhGBBARAgAGBQI+AM/QAAoJEDmJP4mMlLi+/3YA
-n1JwKzMg71c4AZcOyKBv60OI3wnZAKDv8WDW6IioZJ4ii++asFkEiEkAuYhGBBAR
-AgAGBQI+AM/4AAoJEFJc9XK+zVs76YUAnjJ6wxIitLokoUyjPySs7GUeNZevAJ0e
-5L/SPhwav9vpQiVgdZ000XohEohGBBARAgAGBQI+Ahj8AAoJECaZsrtKUBsgQPAA
-oLHI3vy33CFagnaFd5PfzL+NOoY3AKDdVLvVN9G6lFbqPbr0yWboELtFHohGBBAR
-AgAGBQI+AikmAAoJEEwKq4rto2gJomoAn16U2TOQiDlpc6YRkBw1C0WPP82SAJ9j
-LZrAlNMtD0GKy906fbNuxMPdC4hGBBARAgAGBQI+A0FYAAoJEOFbTWxpxhbH+HIA
-n3f/9Y8NyyEu09B8MVGA1HYxOhlXAJ9AKkF4hTWY8vmAFe9gOeduSEdDIIhGBBMR
-AgAGBQJCDImYAAoJEG9+VzhUYiQeKe8AmgIguCD3blnr0pQQHmkXlHN5gboiAKCW
-XsLs8EbnxkoLSKfw3iNZcLo7N4hGBBARAgAGBQJFV4KTAAoJEBNxh3WYQKdf1XEA
-n2rFfq28ZwBlpz8V6UdF+Te7qMhIAKCVDBmEoMmhUvxpDaUvV/7Ouc0I/4hGBBAR
-AgAGBQJFX0jxAAoJEIg86PGxvLp3rFsAniEn7U1lgZSsnDh/hjpP41tBe77RAJ9n
-ZenIqCwSorEfVtrd7lv8nq81vohGBBARAgAGBQJGCjZkAAoJEAHo+EZv8SwwzkkA
-oJv1CRPkb8gRAoD3dZotTIhm0uDJAJ94EHg9LFp8gjk0tROped1NXOYM1oicBBAB
-AgAGBQJGClBJAAoJEKOyQ37GxgsoqoYD/AyAy83K6aubFEJo6shvsQ0rcYR026/J
-kcuM86sO6d8wI7bVF9V1t3v3eAD+gebaJb838qIHbhTa24UfxfyC4oLhDTiJpwXo
-Rh0aNuC/NGV/M2B8yH3iESQ8OBMbxnOmSIjGezQgei5FepYIv1MzBypLsOUVI359
-07EfHj1aqL04iEYEEBECAAYFAkYrE8MACgkQCHgWUYNH0dp07ACgwvBZWljLWE40
-sXaEO+MtcMiHI5MAn2cvJWTTqB0gj+3k2NmSFU2uMxM4tC1Sb2xhbmQgS3VobiA8
-cmt1aG5AZTE4LnBoeXNpay50dS1tdWVuY2hlbi5kZT6IZAQTEQIAHAIXgAUCQIAB
-ZAcLCQgHCgMEAxUDAgMWAgECHgEAEgdlR1BHAAEBCRAjgxY7xAhE/QVFAJ9e4+/D
-sLo2GPNtjdyjaOjyqHOzjQCfWmD4dQrdM4urJMI+T0vzvhSy8/aIXwQTEQIAFwUC
-PBzPPAULBwoDBAMVAwIDFgIBAheAABIJECODFjvECET9B2VHUEcAAQE6LQCfWJTk
-cmsCWMkg8oCpXmM6K4+u8KcAniHeV05whXPGLHUfgP5wul4R+pE4iFcEExECABcF
-AjwczzwFCwcKAwQDFQMCAxYCAQIXgAAKCRAjgxY7xAhE/TotAJ9YlORyawJYySDy
-gKleYzorj67wpwCeId5XTnCFc8YsdR+A/nC6XhH6kTiIRgQQEQIABgUCPf7x2QAK
-CRBvF6WvwfJOpHsTAJ9UxhqTrNlbqRz/WIkJFySAk1+wzACbBkv9N+lu5ME3w5/v
-Jx7hXi1YsKeIRgQQEQIABgUCPf72BwAKCRCCHxvhYSjGtp6pAJ95PiZ545M4I6Dr
-+7DoMDjVnR0LewCfU3TN3RHLWUfMpClKQ3kIGG4PvJGIRgQTEQIABgUCPf8XrAAK
-CRBr+boMht46twW4AJsE9ZafAKOoZWZUxq3SLGgE92BtggCg3mUCPB7ghD0osPUE
-6kWYX2xiKhGIRgQQEQIABgUCPf9PpwAKCRAmGdSDD9JZXxrqAJ9Uns6G/DFQ4QfS
-vprXpqhGtVaFBACfSxGCBzP4F95pSIrVg037V73m52iIRgQQEQIABgUCPgDPzwAK
-CRA5iT+JjJS4vrqUAJwKVg24DpvVF6NoCTRroo/TXMHLnACgs7zhd+DUpIW/o4hr
-0PwM+qfWlNeIRgQQEQIABgUCPgDP9wAKCRBSXPVyvs1bOzeTAJ4hVJFiu//Z6NWF
-W0+2WjcmKaoFDgCg0HihTivB4oLQSX1Nk7Y4thsWWXOIRgQQEQIABgUCPgF0QwAK
-CRBMCquK7aNoCbCSAKDRNSaY0chDaljdNtKo19RZrVQ1ngCg8Ul3kMtZkF7C4GtY
-cQsTe7IwximIRgQQEQIABgUCPgIY+AAKCRAmmbK7SlAbIJCHAJ41w/YgHFpU/ZDW
-JsAdWrlv8uem1ACfap21W3qqdckX0K90nQc/2MH5Jv2IRgQQEQIABgUCPgNBQAAK
-CRDhW01sacYWx5vRAJ0cl7G65BmvjHkzXVXEEkYYtfS+kQCfV39Q5dcabanykN4c
-HfmmyWj/aESIRgQTEQIABgUCQgyJmAAKCRBvflc4VGIkHrSIAJ4ysFHSOjc9Gjzf
-BtlibOBXgWN22QCbBet71kIBdytPPDNf+ZuO6Mj9EfeIRgQQEQIABgUCRVeCjgAK
-CRATcYd1mECnX5AsAJ9iSAfoiBMKzB1Pdo2nS1cYTywIQQCcCyWyfibtQ/tamCAG
-KdAiG+auEQCIRgQQEQIABgUCRV9I8QAKCRCIPOjxsby6d5LgAJ91AA0PfJSkJVd+
-moQCeJVc8zGcrgCePBUZ9ey+vPxrBlsB31I0Hgvv0KqIRgQQEQIABgUCRgo2ZAAK
-CRAB6PhGb/EsMLJ/AJ9/DKOtXATttE+HFFm84UJf4f+fAgCgt6Ux+oPozdF02LAr
-4qMnP4mRM0GInAQQAQIABgUCRgpQTgAKCRCjskN+xsYLKG7wA/4/lExiL2PGmuzP
-urr+LDnRWjsJy24gqgNm3DZHu+KycpNUzzyQRdFrVO1NIQn4QJuVyh/jLxOkKi7X
-bpexev5WRpJVTIdLKn+YnVxHZMVbYMNDEEwqi93MbGFXn2HziVprZNaKOCu7prEP
-9SbNAKgTWaGIHRmjhTzqw+z9G4sCBIhGBBARAgAGBQJGKxPDAAoJEAh4FlGDR9Ha
-O9QAn2knWm6PTEHav9HRo0NpfWnkFcoWAJkBVoqMglIrU5GLElW+CwJTxqma6bQv
-Um9sYW5kIEt1aG4gPHJvbGFuZC5rdWhuQHBoeXNpay50dS1tdWVuY2hlbi5kZT6I
-ZAQTEQIAHAIXgAUCQIABXwcLCQgHCgMEAxUDAgMWAgECHgEAEgdlR1BHAAEBCRAj
-gxY7xAhE/dOeAJwNEUIIpIETuHqcR+yJwNGI0MM1sQCePu0S8du/ib4RbuJEeO/x
-B2KPFxOIXwQTEQIAFwUCPfinSwULBwoDBAMVAwIDFgIBAheAABIJECODFjvECET9
-B2VHUEcAAQGMcQCgjE+RYMRW55m55oPWlxr2GcUrAfQAnRBaA3/7pkjP9W8IVfHt
-uKRrYTOriFcEExECABcFAj34p0sFCwcKAwQDFQMCAxYCAQIXgAAKCRAjgxY7xAhE
-/YxxAKCMT5FgxFbnmbnmg9aXGvYZxSsB9ACdEFoDf/umSM/1bwhV8e24pGthM6uI
-RgQQEQIABgUCPf7x4gAKCRBvF6WvwfJOpGKnAKCOKCG9qC9SbLXWAH5dg2d4R2E4
-9wCfUBE6uHxqfY98gRHocN2Aff/3x2SIRgQQEQIABgUCPf73iQAKCRCCHxvhYSjG
-tvgxAJwLXg4L0SqMpxLqYbM25k0FKVZuUgCaAwMuB77qzb6xRIj/vZ22oBGuiWyI
-RgQTEQIABgUCPf8XuQAKCRBr+boMht46t2aIAJ9kw5BJWhafdRGMU+l25zXu8wHH
-WACgyKU6Z1VjVKdgmn0lqUh+oO75GoeIRgQQEQIABgUCPf9PpwAKCRAmGdSDD9JZ
-X3AoAKC3n5KCjh9DNrEEs4eZk3G2Ii97eQCgjM1NINTTOlB9c9K8NXbMVPqMweWI
-RgQQEQIABgUCPgDP0AAKCRA5iT+JjJS4vmFEAJ9O0d7waJi0DdmGoMuk45MG3iQw
-CgCgvCANcgScpVu52V4CB1OW1kjb31+IRgQQEQIABgUCPgDP+AAKCRBSXPVyvs1b
-O6A8AKD3/iyspWDTjWau9wV/9KwaGJ+yxgCghPbM8pElloBc8444PO8cY0amSGGI
-RgQQEQIABgUCPgIY/AAKCRAmmbK7SlAbIMinAKC3FTOL3agqCoukN7xB3xcHutY/
-dgCffuXv/Wup2WA0zqoboDZH3qHmwrWIRgQQEQIABgUCPgIpJQAKCRBMCquK7aNo
-CcSvAJ4m07cmT8unySrBlqBnUkQ5GGrMPACgnu6iDgowPJfvyDbuZpIkQf3zoN2I
-RgQQEQIABgUCPgNBWAAKCRDhW01sacYWxwgeAJ4iBRUJirkPJum3uQgFHd8Koobd
-qgCeKHP3LlS1rmjjDfJ83Bj29yG5tYCIRgQTEQIABgUCQgyJjwAKCRBvflc4VGIk
-Hg0gAJ4nVZKYJ+aNM223qcOPilRMEns4AwCfUEIJbO350f2fyK/joc12rGsKLpSI
-RgQQEQIABgUCRVeCkwAKCRATcYd1mECnXz7vAJ9btXDf1tzrkIMvZjyU3FEpMMXC
-swCeKZ6QK5DVv+dOMOnRVOYldWXiadCIRgQQEQIABgUCRV9I8QAKCRCIPOjxsby6
-d7adAKCLAufdS898TpC20lovfmCm2JsGZgCfdTySfepIvW2cnEn9NR4FJa1kPCuI
-RgQQEQIABgUCRgo2ZAAKCRAB6PhGb/EsMP6SAJ94EFSym1QzB7o9eAlhKRNM5A7/
-sACdHbMOqymIpzDPtidrCOl6Gg4+FMCInAQQAQIABgUCRgpQUQAKCRCjskN+xsYL
-KHkgBACHPUAiAuN1AdgroXaSf7zvplXomj1IWcIyC4H0/vKyK4K2jjbS2z1+zUn0
-PZFLkPJCioS5GQqKq/CjQYuOO6Z3JTuTLUabkvRv1vlCib6lAPSgK2276zWq/HD0
-xr9r6kjQWBtkigfec5y2GCIVS5Od2Koiymp5gFL1qwW/6FZPBIhGBBARAgAGBQJG
-KxPDAAoJEAh4FlGDR9HaS1oAnjhYdkQF/Bqk25rKWz/sOT4NUqijAJ457YjcmFIF
-XjRlT04n/5EqOh9ijLkBnQQ8HM9OEAZA1QjzjxeXwBmMVUQHiJgQvH9DKIR3f/lS
-TwvGnpFGrYZ/Qx0OgnrWmq0KKg9CpKKlGCfq+vCV3MHtHg3ZewHD6ESH/WpOwvEW
-Mp/Ql58lcz85Xw343P24BgPwSah9K5EW19vLo0C8evQSOw1HbheidqLWiCg0xsSc
-mMN96d7SOeJG67qRohGQ+FNx0unbw9OfKnnRUFyKkvx66kC7XuZvYQCmDhLr8mU3
-VTZH/W+nXkcQWUZ9IaEkCzJ0aBxZbKvBEU7CSj01FpMAAwYGPil6yMuJ9uFPEcKx
-qR/+op/83Ic35gBMzEIDX2snqnz58ETqsO8JmQucXilLzpRBoWD0bOBz4YjJOdNq
-MGiNJUE9xnq2/3qWuCCeHE3THIXhTNXK3IQ68PfeOu3Mn+pjnJIIfLeyRsaH1KQR
-z1y4bzRtlYV8xbNhgeYfkbRRPdvhcoMBrglHNkeWGl75mkfd0vCl/RhDWW1VlWIV
-QiWcK9o1o62hMuUi03H5s/OD4DonN8FujbJs1XK+tZ9hlJ2rIT0ekkYShsHFiEYE
-GBECAAYFAjwcz04ACgkQI4MWO8QIRP3xswCfYu37U+tEsEEg4sCfaFN+wKfy2/4A
-nioz3lCi3MT/S/OkR9SjrdSOuUYuiE4EGBECAAYFAjwcz04AEgkQI4MWO8QIRP0H
-ZUdQRwABAfGzAJ9i7ftT60SwQSDiwJ9oU37Ap/Lb/gCeKjPeUKLcxP9L86RH1KOt
-1I65Ri4=
-=5Xso
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2F566D4221D3EC52
-uid    Ryan Harter <ryanjharter@gmail.com>
-
-sub    C4725C965E0455E9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFPSiQsBCADcgBiaKkIG5jVFbQ0NyG//y18S84/OT1X1I82OwtTryxNqxT9A
-q6HuTJqRPi5Qd0BwmQB6dG0mug9AEp58L8W5udiDysHeUvBKY6zTOprSSFvFg/Y8
-S7i9D3pM6k7L7lGahUQqVAAU4RSky90nJfcT3qTNpmsO24EelMf61XvdFHdyPAjS
-aAO9W+QWquxNqXd0FVQqpHKRB43oR64oeAAE/N/H4lvemuxK6aWEq0/KJo0KYHkt
-H60Jo+djdNhHD/EQwCp9m8pKd3FuAAI9/ypvE/a8LeH/8AcLqnrPq63vxVe678nZ
-yePb1Xl7zQUsMw/ZD4urlkcTrOLl9yfIg7wBABEBAAG0I1J5YW4gSGFydGVyIDxy
-eWFuamhhcnRlckBnbWFpbC5jb20+iQE4BBMBAgAiBQJT0okLAhsDBgsJCAcDAgYV
-CAIJCgsEFgIDAQIeAQIXgAAKCRAvVm1CIdPsUvShB/48Ai4yB2nlxy05CwbuX1ka
-E39VL2sb2Bd6ZVtmkWerIaA16MFj+/o12JlJ9R1S7BsrvZor/oa9ejCyJLUOHW5s
-vRD5BkAJC8IRpk88szJNeVwh9gRgd/lWv8IEKMaMFIx1I96NDKo2bjw+rdF6Qo1Y
-C9yC1qsj8vg9+szMvfAoDCN4KDa9rk5/k7a6q390QpaXm7KY0TbqTkUr8Y+NMY+R
-yEap/qk8EzaauKQyHvxOBj9m8bkv2QlxID9Cyjd1ZyJ9hWuyQy8UWLPy6pVXKPaC
-CVlf+Uoj/qbzoVrElZDqGok5GQfKjNFzOkHuKEgXdYEuX7JWJgDO2i4pAr5isfST
-uQENBFPSiQsBCADt3ycVnpTw4NeU+q1rt6+aBrOQfcdRrTAxAwhilKEo+jD1kufJ
-LfcDooqEYZ6l4B9Sw91/zECNmIyqRiMlMTDtZOniuv/fFgxKSzHIstVDjO6tlY1R
-DqjzQUSb5uHMTfToTDrLki9KJfHIHfHSgOvfa1l3FmX4vt9ro8X8f+wfZg8jHY2p
-aWW5RfhVprR2/A91nzgs5a3wdPQi9Bl6YRZKSJKNvgktsm18LMhwLqvuBpQ1ongT
-QdUVY9VLIkDc7Tn/V5x+2mWCAf7HrJg9UnZK0JoKjop4ZwR7MQ0DoBh2K1Hd6RFH
-rmKjpCmKA3TZVAe5C1Ntloby7un2FOL7zZfvABEBAAGJAR8EGAECAAkFAlPSiQsC
-GwwACgkQL1ZtQiHT7FL7Xwf+PM0DHB+7ENW+1HbkEXZRVF3hNHSWFWj1AySvSrUe
-Xm4z5I2Edq0zDdTQPmi/aEhYgXVzsOWXi+MinkNHXerzt6YHIfbeJJ6dX5IL7Xwq
-rsDRxpg/J7MoWL826FUXZ6CePBfGoEA1IjhkeSkyKvLm4aLv9vfC4MVuLHRbsx3n
-np4ZkMVvLBSnBSeBTLaINvhlp15NLyHweE1KhtAqVuiisWm86n9kqIXjfoj+DFuB
-kK9cE/YCU0sNFELYgmLVVoTjxxtY9mPsROt+KJxIDS9BQ8mjeifXbYwkHERnOTKx
-NzgwWngWLQBG5cIsQ4b80Hzl5AF5ApOcC5iu6Z5e2OWW+Q==
-=qdIG
------END PGP PUBLIC KEY BLOCK-----
-
-pub    07D3516820BCF6B1
-uid    Ben Manes <ben.manes@gmail.com>
-
-sub    11F4CE313A637CC1
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF3HgdMBCAC3ET5ipFXdZ9GGMbtsCQ3HGT40saajsNDOdov2nMJxzKkVe3wk
-sN3bpgbsqBU9ykVkIhX8zV5+v8DOBzkV0pJ2eLjFa9jBPvNjV+KoK2BAI5pzNzYg
-sHPwo1aRXdI0MvCy+7iaIiiGF4/O16AhU4LmALHnaRQZCyuN6VOQ8rlqNvcczwUf
-J2DQeLHqR/tsch7S01hGpPAptBeu19PyAlQsntYN0yLCLKoe9dFXWCDkvd1So5LF
-6So+ryPqupumBbh4WxCmTp9qwDJYJItjAE0zyPe890FurOtxrFTwtRtX6d6qGKkY
-/B4T3r0tTE1EiOUpmSnxmGNItMh7/l5UtnHjABEBAAG0H0JlbiBNYW5lcyA8YmVu
-Lm1hbmVzQGdtYWlsLmNvbT6JAU4EEwEIADgWIQRjXuYnNF88HdQisuIH01FoILz2
-sQUCXceB0wIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRAH01FoILz2sdoo
-B/0YUh73jUMl14MjWvp9zrFHN8h+LqB4NMQcP93RdPTtDKi0a+0h8gQtm0D+K49Q
-BQbFztOObfZS3kdJ3VOqmodScWrGtMU3HsYT2ioQalqbYvl9FIPDrlOjHaZgwgyJ
-We0DVKHRApbtIh+NxTpQUJtanxgF60ZtOoToZe8XMGc9LaCZcrFxK/AlMdDMgUCx
-qzBbXhAcvut2bJVL5B4kLNMABrbUuFMjTNI4JxvgTXKL/jNk6XPtCjdmgIh7mT/G
-Mpu9t3i1zegAPdM5N/MAgiGHqm+blANLniSAbZja8Ny7211fwOYoJ546VPwDjL7B
-rBlymB3COoYZhql2DcBBg39cuQENBF3HgdMBCACu3VQKKmagcPbcMZOqbDXE5iK3
-0G742rCpf/j3ywnwTZJQ/58HtAi8+/fXxUhTHswoON2TwiiHrHAkObe+K9A+jv0E
-xjKVMmQ/sOCYWZDEGMth4yJnzDbT1Tlm/l2i5Lv0ZaD7fTEhtprQNuU06dveTeJs
-zDyqtK9T80mvI4+GH59wM80l1y6uj8KA4pY0PdSFgbyS9iAFADGsUsc6t1KiZ5W1
-9odMjDPlQtJ20pm5CvJlDZbYNRJ54CSldZikRvmNRg5mWdRLNfbRMFDLFfcdYLdO
-WJXnAt9cKFJC9P//ItZFrlhu3akTH//HF2kxQNW61Sd92/xtFUD/2tN1GlXfABEB
-AAGJATYEGAEIACAWIQRjXuYnNF88HdQisuIH01FoILz2sQUCXceB0wIbDAAKCRAH
-01FoILz2saySCACibIpnls5wJkfX1B/7tDjWk2hEGZYcASr0xp/DDwSgJ5edByuQ
-NQF7RHuCk0ke6IQGfytMLJlXeEIu79DvgPakxBP5iG+c095FbhRu+9nCEkRqQvop
-4fA7ZdhuerOyuObWz8+o3Z2RywWPXlK+F/9iJiO/qtvmdORuikJtN9VxgvAUvANZ
-RtlzjL296p0TJzGqXhyer46CHl/Yj7TtX6EpnZDgiaQbOWRFOZ5x81xI79bQD7Ew
-DzfrwQHbjQDkqhkwOoV6Wq239ZaHh6p7GXHnQkDMQ0H/7Y2tw6PH5VM8fDJkJKF2
-PIukJrUXa06KqrdZ9YxqvSmu5UY6tMSRwGWp
-=/wFN
------END PGP PUBLIC KEY BLOCK-----
-
-pub    30E6F80434A72A7F
-sub    C30F4CB428DDFC28
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBEaNL+QRBACYhfwZdDNXVeU9G5/XsxrUgQGKkhfOaB1CyPHAd02Jyc5oHR0a
-nu7dHb6QBlY8b47pX8ii+uTCOX2yyFlJt2cuKYqN1TwHrMspDTC9K1x8WJMmKdM5
-KUtWchFQ/zmFgIcXM8Vm1851k0aOOP3Pkexv51u4kZ6tbAK2iqYAawB93wCgkv/X
-YpZR9qL0FWip23gsjjxf01ED/3cHs+5L6hm0vP4x8xbsei31/4yHPIRytLhkS3CP
-tPZGANloRi05FlPxNXMQdeI4tUk//V3Yew5LkJC7Ue0zkAKAxjyWYBBsbl20grmq
-89ZKcj0/pZBw9Gzm4indpORfPRT7BBc+F8+2TUD9jpha+W6paCLp9pFJR++OyiZ+
-hNwfBACIyapWUmoEmV4XG869hsnico6vF4WzuhHe/PfityhlHX2M/DDX0KrMqNeM
-muxYNsKoSw3EU8BS+g6bHYvxDFePPhpFIMwbtEEOul533V1sGbPYhBIiSBpnb7FX
-AnbVIYk06T5mKfaK8n9XB4BIrt/pz9gxDjb9KBuIHE0H8OkfzbkCDQRGjS/kEAgA
-madPbo/cLInRyG4EezfSMDw3wNw3Je3+Ozy12FgQE7aaUQ6a4YRLkWeldmTtOBlV
-XqRUV1MrGQ0+C1bWEAXPsrdzzInM8NiXz4d5kCVNa8WzfnA5Fe46hxUqUawSEt6P
-9QpT02mzYQZhazDMJqgGWFHoMHKQVtAqTlKH8W0D0YPRdV6Qn/VYZ2ZRW2mk0tU4
-/xBMLprmcQCrDYXYPC/apl3tXuzXqs/FA60lKZzzE+KqW53G7qSbSSN59IRCpk0N
-X5hFMZJ+/oBItH37Z5V/pVhRGytEfA9yv3IELpJ1CLtFZVS7lJTY7hsr74qRhbCC
-JAkjR1Ywz1/Ya29NUjF18wADBgf/SXXHiYR4XasV+LOngRzA/yw8yG+1gBhF/5LF
-NidGG1NnkUVk9t0APwgd5pubPagIrVqJVbr3UfFjU8lZQOLUigadk+JJ3NnhRQkQ
-NZtkvN9a53vZeORGWNDoxqnIm4RDLJjjf4pfI8tORRwNyqxWxNB4bAc+k9ysXEO+
-4qbQQmCFKzXjCaxWCsl6dXuRvQ4SKzoi63pN05o9/YG+wh/c8QCM7rZVDqIVDoqz
-hHrsWszUyHvr8Vg2uYOaIbxnWXhaNPb9R4h+DV2dITCeIrOj+Ey3MRl+vXNDqx4B
-nEq2SxFS6PXWTjqp7xE0ITKv5rppyrR231RLmY5lQxSbm0PEE4hJBBgRAgAJBQJG
-jS/kAhsMAAoJEDDm+AQ0pyp/2Z0AnRYlvIQAMoO33jBp6ZEd8GQ8iARZAJ4323AS
-sjiqTZMbrvYrk4fWvFzxXg==
-=z07+
------END PGP PUBLIC KEY BLOCK-----
-
-pub    C4C8CB73B1435348
-sub    EA2A558279B36E6B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-4q5nL0cFWrpYBtEUxDwWSI3K
-=qAlt
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5E2F2B3D474EFE6B
-uid    Sebastiano Vigna <vigna@di.unimi.it>
-
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFijpzMBCACxAT3jijwXbI6b7LIF/k8oSGyM8ZNJpb6AQvPqKIqCzxNFXzow
-EBCasKMhIWgGy+293Tpt/DY4btJie4u+igMBS86iXrF8CUnOLPgTlAIyil/oREGJ
-1GFkHsf0Yj88zCo9H9GNiUZRNSHdf55gsgjzzFVdZ6x0MoN7Yopbvl71bcTSbe25
-AZM6K4gIf5TTo66smG9FgwDkMxc61ixRty44gkfWapzdob5d0cli0Ze0mu+2PHJ0
-Fdt2sUX/4M0Bpxk7eaGVecyb9sm6KkRaGziJ+XVByZ0UMdrEEJscLaX/UpfK+Wek
-aPQjDdyYLW90PJofKFPt4h2DBQyf9DSZ8NfJABEBAAG0JFNlYmFzdGlhbm8gVmln
-bmEgPHZpZ25hQGRpLnVuaW1pLml0PokBOAQTAQIAIgUCWKOnMwIbAwYLCQgHAwIG
-FQgCCQoLBBYCAwECHgECF4AACgkQXi8rPUdO/msQeAf/Z7IJc8pXwUzm2w1G877N
-KHGNivS5WLfuQk+bCZalLVA25aigwP/YVcF7xdQoS7aBSNG+CJzrLCyyUZaixwrQ
-sV+B5E+LsJWgb7xSvnRoCETYGeFQJdAshlu350GTVmCfy3xil4FFyAENl5r3nB98
-tJ4HgYh+NwUH9GUTBZV7SpnV7I2MYOv7mvixqioN8o51SX8AqbT3LgDko3XegtDD
-Sb3JMtTACZ/7SltVNoGvLzCOSgnj0HkU77MZQ5q3rQCPauz8Arp2vJCwOvkYXPde
-O4t8s5dGRTH88sYI81CWQT+X4w1q20CvWxUd3j3ZJthyunX5MH11nbYdXbAnGPIi
-gg==
-=UN0W
+mQENBFF/4bYBCADTeOLZiVGNbjlPrwG7UcMl+yXmEqpf9dB1A9cuicH3PWXj0WOb
+LSzHjzoRvRekEqSUmgoveey1lPuA2qjOUkXY6Kiyx+oLiG0/ObJHUQW2O+tjSQ0R
+ZXKd4ftaw65SLbwYO2JHzj5fLC9j2mZQiRjGs1bWM58c/dOKp1XaOc1/ffcl3L3q
+Up64jWH9r3yhPemh5SHo47UxNvItdaJJYnt20azpZj9oq1ebUuQFMaQDc/RTALhf
+Xb4BWO+z2PCmChz60i/Ko2ZKPJV2TqPqWO+aklgxTTwZZ0IvgFm/5n3Dtn5p5iGf
+qwKkHPJIDWc8cWYtxC608LFdqiAlYmp/oPi5ABEBAAG0T0dvb2dsZSBBcGkgQ2xp
+ZW50IExpYnJhcmllcyAoUmVsZWFzZXMpIDxnb29nbGUtYXBpLWNsaWVudC1saWJy
+YXJpZXNAZ29vZ2xlLmNvbT65AQ0EUX/htgEIALToF36j45OitNd4k17BSZJKnuS3
+uIL3tTw0fRqLv0/3EBaj4zD5Qc5YTKFgM66Bb5ybI63cwYhfSBHP2ZRS7oNdDbPd
+/30jDKNvmcDjIhGLT7bZJwC9SJVifHuvtzr6wBR8xoItyYva5D3ax8ZvnzqIbMPe
+Hou+0ZnRYSPjy2c2TxAJTjDOG461h9mVXDdK74wL8kQsIxqqYRIeEdmrXMrd/B8I
+PwuIv8w7LwzadNgRnXaJ5Q5bnMvvhVLnWKRt5aiQVBxc67FTujjqFF4Y/1UJb311
+K+1LSqNrTT7As8nhf2Gu/Gb47kw1bb7wBdKv2Swx5mYqiW5+ARQU7jCiUVkAEQEA
+AYkBHwQYAQIACQUCUX/htgIbDAAKCRDharUtef0iT2SyCADAznSkG/8EdIU5UQhp
+/lY9h3WLzYI7aARw0IA6O4ijGLwcytO7TaWjEzUCMZdw01vAjVH1xNn9QvTgQV+2
+GyqyBNsjmgGt5/tK/+JtMgXUwr8+KsBf3908rOqAAZ3YGyM9N8sRsyfPB/PHfv28
+9sL2IKPxiFTGI0NGS3qOAKQ5TZvV7OPsP5+yHfeJG/XhCW8p+nkMGpH4rE8Z6NKg
+Le/WC6J36aQ4kBfYneueH90Dc400rfGyL+0Gn1Rzuj2KFuUFK6q/GBlFaNo0azCq
+tdpcO6C3GpJYtISxpQ1Rp9kSEzSCL3tOli8Xs6gsruc+vCSIy8lzRw19ZO9G7qhj
+cHLc
+=BZt3
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    E3822B59020A349D
@@ -6430,2209 +3404,6 @@
 =2g4Z
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    DA70BCBA6D76AD03
-uid    kaml GitHub Actions <githubactions@charleskorn.com>
-
-sub    66A2CBDE49E8A25D
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBGAwdRsBCADCXfWdHhywp8Rcgt834W/Z3MFEAxYdxjAJOTQhc/In1SJfIqi/
-xD7OKHA2fbwzRnS/UmXkmElTK7JI3/1gWRm8kEaaHTnlI63Z9MZV0DHMpJMgvpFM
-JXKMw9GWbOZt211YMFTkY3oi+kCIibzs4S+2zAiKX0/B5xU1gE0hnPYbXQtZ2sUb
-8t4axAkPdlDVrnBbgPD/+31c8G2Nsd3w6Rughi3SXdqp/6lKZpJNZV7ZPllA8wa3
-6hdOqWkh2Xh7uyKCXPtPyw57vwK1CeTmrAvI7Xhfh1Cxj2bnS8POnF0YsthtbG0Z
-6TupcFBrscugbl4F0aWsxCT0WjKQ75J2zgMnABEBAAG0M2thbWwgR2l0SHViIEFj
-dGlvbnMgPGdpdGh1YmFjdGlvbnNAY2hhcmxlc2tvcm4uY29tPokBTgQTAQgAOBYh
-BOAe0pOYGuSEQDtl19pwvLptdq0DBQJgMHUbAhsDBQsJCAcCBhUKCQgLAgQWAgMB
-Ah4BAheAAAoJENpwvLptdq0Dv1YIAKtEikvgdsiHjOAl30uN71sjfa2IQpczLqnX
-I+UWyFLbjkvXoYyhOwkbK+J9NqOVEn3r6mG+lQemP7CIyFixRTLw7B9kl5RAGe2g
-tfqPOufiWTAwkvgCfnR8OxOcz2tjspZpw/9I9razrJbvCzHxCc4QbMtlGQwrrDm0
-EVCH2Ks7sbiWWujl6EIKsVobuZHaRsqrpxPtC1I7xm+ed8rEKkrBThLB9Tf2itun
-+w1ct7y1rgOGKh5XH9IYuSwEbWZH0dhMIsdItYZW1Uk+t6DXXTRq5OXHmr2s6JWt
-9HECR8b+xUUZIue3d8PWewiCElgz6c+Jq6ywEwGiSyZXvFBpLaC5AQ0EYDB1GwEI
-AMQiv6gHlSd5U1Jzc8vFMS/Pt7RMg2OF8Wedibqc0/EvzIHSqAkZnVs8iVmf6VYp
-bx1ihFG4ySaCmVkovJ7Yv6yHNyyqp1SsRPJJ1zGUVx5USOO8sT6FsS1Wis2NmWXf
-wcJkhO6RfBUF21vPjXkGlbkhyQxqsnCWtCDhZT9/OGacOTd+xUf9Fq2u5KACdn7h
-qlVMhaRgrPEmdh+95RjSHu+lkzoThG4S0rRd7u6XrUs4w5rqwBqWQB8jzS5I8L6H
-MpLnmLQckxnICGwRUyKywd23/zF3HN63Dbj8MCohrYRn39cXutlRbLH4dG8hPpoI
-JeP7OYZIUJGJYdsi5q+EJAsAEQEAAYkBNgQYAQgAIBYhBOAe0pOYGuSEQDtl19pw
-vLptdq0DBQJgMHUbAhsMAAoJENpwvLptdq0DtRMIAJiWNubgOvXDav3l7Wff+qPN
-zMKFh+9lNMyLaI5O8eEGjXAt90esN1MeVbKwFiNO5NSM2qLf7QJ6aXF6SIUGsWut
-1BUOt21Q5unl3n4YZ+Ff6zA/VEgniGJBJBBnBq2dJO/lJKj9tLkcbvzV0Aa+MLQ+
-lEB3lufGDU4xsApp6w18YQK2Za64drxYL9yChofSH0x+Gvx7aYaXi+K1L/HUSh7k
-qBcwgxmqlnWArnQ8sYd4WF1LOplzm4yp0XocHtcZ0hQG0ZW3kAEITPYfmVk26kO0
-Rsia71ZAHmuEYsLHz6uOIqf6XHbFUITFtdjPOSiJmQhIgiFCzvFSgrx6jKZSR04=
-=Jrn2
------END PGP PUBLIC KEY BLOCK-----
-
-pub    15C71C0A4E0B8EDD
-sub    891E4C2D471515FE
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-tiwy+wOBjaK9g3Kk8jsN3I8t
-=8Tiq
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9AE296FD02E9F65B
-uid    Luc Maisonobe (CODE SIGNING KEY) <luc@apache.org>
-uid    Luc Maisonobe <Luc.Maisonobe@c-s.fr>
-uid    Luc Maisonobe <luc@orekit.org>
-uid    Luc Maisonobe <Luc.Maisonobe@free.fr>
-
-sub    2F3C9EEB05D1D1E3
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-IChSZWxlYXNlIFNpZ25pbmcgS2V5KSA8amltQGFwYWNoZS5vcmc+IBxKaW0gSmFn
-aWVsc2tpIDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFnaWVsc2tpIDxqaW1Aamlt
-amFnLmNvbT4ACgkQNOp25nkUhagzfA//fDOf2r4R4NmRxMBYksilQGdgtrenELGh
-0WXsPv9ogvau+7nuJ+nIVG9b7S4+rac7Lim9L+15SqWnwASdw+yVOUI7r6VHHaQY
-6mYh3PtjdkuXkT04jCBKnEBXLLUariGTPIYEJEWH4FUzORg6nt/9vQBzXbG0DG4J
-7DzDmFGKS9nQDAqxKRbrRVth9IumhIh4kuwDJbN1PHdJAYHHRyD98f5uTxzMvU7r
-5VmG009oAG4JCVBMW9enj0/qu9mLmNm4IxyvmbuC3ZiJXwQUn2qDJobv9BtDnvJw
-YCNtFJYHtu8lpJZyk2wxP+tpcvny5D39iQRDG0WpymtDZcZt8I5S86PrhxVXEem3
-7INHiXVsMDLGdfNpfdezAqvIkYVmVfK4gYhDLj1oka4ruiergwW3H8BakStpeGqd
-tp2tNMNGQXuoKbyjqK1WFNVUKN3s7efjrgoh2XR+yFjBop4pNLktbjo+LXGc0e4u
-T7exRrpSlHLUuEa2rZeeKtntnT4DKv3y4ebJ5f34VegBAb4e4Xsd6XgtDPYX/HUG
-seSjj72OPN7pAUtbBTO2q1NFG6vUPZBSLiV9ZzOu1lPYWEV0g+cIKPmLmIsRnETP
-346vWx2wq5EIWh7T3fTfYkYnsD3vyApPkG9MqMgotR+FIKlWFglPNEv0V2cZgcgV
-exvw5RD8TMuIygQQEQIAigUCTNK0Qx8cSmltIEphZ2llbHNraSA8amltQGFwYWNo
-ZS5vcmc+IBxKaW0gSmFnaWVsc2tpIDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFn
-aWVsc2tpIDxqaW1AamltamFnLmNvbT4iHEppbSBKYWdpZWxza2kgPGppbWpAY292
-YWxlbnQubmV0PgAKCRCLOmAfCMl15cvtAKCStVtCjnhZQeccqgGtwJqnGXba+ACd
-E1osWknKnvFCvurObyp6OPRoyuiJAhwEEAEKAAYFAkzStckACgkQgngd5G1ZVPqI
-ehAAihtxeHdh36A6no5dt9LwrV3WDApxM4M9G8zfN9f3sr5RKq/9cebZjiVWOKYu
-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
-wT3/uLspPh8CTR7DkLU0twAr+POjct6QdzOlwv4bCh3EII4e9u5lqLlmlvvp/X7z
-8GzeDwxK2oDyUSIoN+FMPuS8ESVhMV+ST409io7p9On/MpgQ4F471UsYuzpLXfHB
-l4l32Ra3haNIfW477XgRHz3tfLUvFQWQ9PH7OFJV4rXDFyiLPQsJgW7TTgz0zJt4
-N2x/2awenMOp3T3IXnIpO80ENO4VcPmVSjL9aXkMiS6YicZG1YkCXQQQAQIARwUC
-TNLXrEAcSm9zZXBoIEVkd2FyZCBCZXJnbWFyayAoQ09ERSBTSUdOSU5HIEtFWSkg
-PGJlcmdtYXJrQGFwYWNoZS5vcmc+AAoJELDZkbR8QIc3jXIP/1R4765cKL59YnFp
-QuJNwrJmchg6oh4E+C60cWes955cYCitUPzRkHeHCSmC55TcFWwhGtzQH8Ql4Xle
-UJk7AXh8yMv3KSxG7Ic5/w4MTXAaY53r1q/ImTHnlSmF0+iMq4LF2BfLGW1lWXz+
-5D1Fm2fqlyYJ7BfDRwhbQZiQAxeddf+Ydx8d8Zk1CVqQOkhTFWpN9O+oxiEyxfo5
-SNOZzcCKi+cR0E7AB9qet/OTjecnKy4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6k
-nrX3b11ilu41ri1Y2PqHyjBJnm4zSVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5
-CwuMeyDCz/8Ob5K3fTF7/0UAsG7c/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLH
-eS00rky8g8mNV901vsGxoJhu/w2diFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV
-35ChixhsMdr+Sl4eBWF3HxRJUsyIT/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO6
-7VLPfb+q2JW+BdHMlbVsQdfWhLJoMTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZu
-E63mvtjgI9GRdbDOHdkhJ5yTd1uQe3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPF
-xok1uajMV/fXeqdDYutbZrQgj56piQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVt
-bWUgPHNhbmRlckB0ZW1tZS5uZXQ+IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBh
-Y2hlLm9yZz4dHFNhbmRlciBUZW1tZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBU
-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
-zuF5mZ85CvswdQE31umGLWlHhgJq5DB2rMY+bIvoeIMPAan3ZgPPAB1rDKNUzNQU
-peO678gaJqS81TIHQbcXKxzfCem5auHz7hVfENZKkKPh11XPzIA1HJTpkYQleOQK
-sc8B5qUwQd2ecATfrfIY1KTAmT7qcTnBpdO/TTwnw7M9wwpZBP1IfJwB4nmlWkI8
-Bnllv289lQWAdw12F/4gjJ46MxQwtHrWOpcxWAUTcF/QJZf7UUT8EkzW6aveTP3P
-7IkAkAvvadEWzZcMwVEy70ceayrufDlMYZ7ia24WKFyzm8zCQKWV5X94uQhPQ1e6
-osaXf1wTpshbnmqhRSqZC1FvAVsWNS4330T78p1bQAMYesmYQQkSa53ecW3/////
-////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////
-////////iQEcBBABAgAGBQJQmioNAAoJEO0JbZPu7UfaclUH/RezKHySASl/1t/o
-9TixCcyysDuSeRbhuNlQNZDeOtvnaajMnPpRZEs067uK/YVqNj/BEtDn+vM/sNzs
-Nu69EaaSZZvM7wn2Ig9MywCFaCCpdeuzD8cVG6uuYwO4vIvMrc5dKcFoQQA5bOEQ
-rYofqsOPePChce5dE4kxBN8MjcgHFIBh3WzPs8ohXzNWzNKU/lew0StEKbbR3CPz
-dYwQ5/Xe5IvYlkZtaCWgX+r1vVjxuKK5NUWez+5crHICtuhVy06E3PRHKM4elh/G
-wPVzcP8cspMgofAM9cSHKjFfopynq0RqXEPldG8xJm55uFacOUag4P4PE26t/7Cj
-sY1d+e+JAhwEEAECAAYFAlCaQ9wACgkQNiWQp/XP2RUr5hAAhpLsiBfJJN0wWDh0
-dH3MbXiZ69vWibHd/CNG3WZhxxoxnfT5M1P7Xdu+k1vUjBGCTT8mYuHzMUyZRa2q
-vGIZK1cn/eZzjS1AuV9yR45WIcYtl8eqekvpI9wN200B0oGWkV//9mWO232s79eB
-9j/t9XkozQ7HkFaKevPQ70s6oLfKBT41VTgFSlqylSkoFIeekynwk33Ne3SHwZEj
-kJeJv770unXeTxeGjuIXdYAnk7EkI1E8ysskyGTYzrjDn5Z3m1gqd//msjEXSXXU
-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
-RnQfDzV75TMLdPbRNKk6/9AQtZUDSSf2rmAJDso1/Hw1uXRzhWUSQjP2NKgqDg1h
-kSsrxVcf/HT+/qEDV3c50RxRCkRXWnie+7DE7gV9VxYVGFp/RDcI/CCo7zk8opuy
-we779RU9Tds6ngXMmcbi4HdJBIVavr8ZlCyZ5mj7HSenujIUhnDqKZf/JE2CIxmJ
-UUQbD3LVlOZByPKowa+nR2WzfezkRCNhw20aSxOWch7qb6dFGQBRHdi2E9Ovy3JR
-xAyh+mLc5OMx3yBqe54v0cn+Ov/WYCb5LqtPKc2qd/Oy27pfo0Ly2eE4AU5EVcV2
-PpetTpC5W2xZqVxFd6irpyp8/lFiXb09FpNe4ykad22GA87SIzoGAEUK3Eyx+K06
-CVunXKc3PR/WyK+tM8KPVc3L9g+OzVL9Jnj5HasNO+NJyfNVvCY6f0vmBrZEsRbn
-lG7lGJ7HSbB5kHgTZGQFfxu+ftrXWkg/xg+bUQcPGIGlKh9lMVeZk4kdkt6fRewc
-0GI6h51FD3S5T6kKDBhEt6wXshYaTVxRHNWw0dd5sMzNar6CHkyaFVaJAhwEEAEC
-AAYFAlCiZnMACgkQRmNAdwvZNvFYVw//cKPW7WtU0HIVvkDD4EsXe9ejDOH3Wg4d
-4XT4bYFl8p78/msZipDTX9lTZzYHEW2Hhvl40frtA4mOUfZdwyB8qQSVjgvwnJD2
-Skp6MMuCOOEv1m29PACXjNzt/UJcVKEr8e8A8DdWmZx/ifeNrKx4qB6mKm0f2AU4
-qjMCApncUBPvpTxPTsO2pw+HOObXbApxwva4kC43QEHbqiBVqI4n0YIRQo6bWClN
-/FbxfzF959iaL/JY9hUY0KTkPfPrNlq12CY5M/PoAlOpP0o3l5ZfI6zf2VHhXB46
-XdTGvwxZsJ21fGADLh2RlXRONM5mtkVuY8cgfRmr1u1VzJWCiWsTig/kkGm/OjjV
-qCc9+7rFrCqI7Bs90Kf7+VDrHLEEjLM2Qgr95jqaD7c2QJWmns9DQ2l4ilKSOfkE
-eQWFu+nbXVRhu5qB5X2ZzcvZmTc5kx43bGJTemEettzmdGyLUk8RZvotuCBeWiUs
-X4/Ko56pIEjODjXfCeT6J4ysvCnRscxkcSY02KWJbR77vZP3scrx6rSch/H7V/hX
-xmslCUErHpYsmzSaCoh153fSQaiyfKUT+loPTas3x/1fbJRsDBwhgCJXuVVkE7Kh
-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
-7efjrgoh2XR+yFjBop4pNLktbjo+LXGc0e4uT7exRrpSlHLUuEa2rZeeKtntnT4D
-Kv3y4ebJ5f34VegBAb4e4Xsd6XgtDPYX/HUGseSjj72OPN7pAUtbBTO2q1NFG6vU
-PZBSLiV9ZzOu1lPYWEV0g+cIKPmLmIsRnETP346vWx2wq5EIWh7T3fTfYkYnsD3v
-yApPkG9MqMgotR+FIKlWFglPNEv0V2cZgcgVexvw5RD8TMuIygQQEQIAigUCTNK0
-Qx8cSmltIEphZ2llbHNraSA8amltQGFwYWNoZS5vcmc+IBxKaW0gSmFnaWVsc2tp
-IDxqaW1AamFndU5FVC5jb20+HxxKaW0gSmFnaWVsc2tpIDxqaW1AamltamFnLmNv
-bT4iHEppbSBKYWdpZWxza2kgPGppbWpAY292YWxlbnQubmV0PgAKCRCLOmAfCMl1
-5cvtAKCStVtCjnhZQeccqgGtwJqnGXba+ACdE1osWknKnvFCvurObyp6OPRoyuiJ
-AhwEEAEKAAYFAkzStckACgkQgngd5G1ZVPrnSg/+L4892O4wSVGmIZ7AGHtq08NP
-TLNfzfkcKtMUOBP3hnH9tyiKkxmQKuUAAUAatx3AkxYfsN8e3Rd/w7SfyeqCeQBY
-B/fmBWVegpUkIUmUDnAT89EXParMOBk+NAmTfBo5H+zS/lo8y2MC8WXJYHWI9TE8
-uft0nHn8hLCVqA2YcLD8oxQ9YP4lKCQsbZc0zz1GEZzcxgXFKm3HPHPSymr5sBbh
-TlKAXZ0kjzUgAz8asHbyAuvNmIMstRjZuqhvig/E9JkWgBdGOk9UfLFbQ9p9Hzah
-LnWkutfhSVcs1IJ2kf7P71NpfZl1/sifqojWUkrLcVwYUqfu9A8tICu7zE1xluRs
-cdv/3mx4yyWvMk4Eu0WTOrIWeQyoy6Sg9zt7ymjw/iMvFs0Lq1KgvI4TEL2KR4ln
-FU9BJQYwTVaWIWwWnTP5361nU7ixCYBQu+Vgv0sIQMauu6RZrfb1mQPpBigwFTh4
-GYBhQwgfF32g/4oiELkHQJ+Sf/6Z6oyE/sSdz3vsNFSxF6av4Yr5iSXojBXD/jt7
-ivOUOE/K00mNVNSW/T9oJGy/S/7XkOTV90MvtWSC3CWbLv7YNMYUN/3TgYV8esz7
-wG1Df0ogD4PbLUXwyXHXoFbiwIe2a3+XTHb5zUbl7LUgN+LAGzT7GItaPTjNgj+K
-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
-Ky4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6knrX3b11ilu41ri1Y2PqHyjBJnm4z
-SVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5CwuMeyDCz/8Ob5K3fTF7/0UAsG7c
-/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLHeS00rky8g8mNV901vsGxoJhu/w2d
-iFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV35ChixhsMdr+Sl4eBWF3HxRJUsyI
-T/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO67VLPfb+q2JW+BdHMlbVsQdfWhLJo
-MTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZuE63mvtjgI9GRdbDOHdkhJ5yTd1uQ
-e3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPFxok1uajMV/fXeqdDYutbZrQgj56p
-iQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVtbWUgPHNhbmRlckB0ZW1tZS5uZXQ+
-IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBhY2hlLm9yZz4dHFNhbmRlciBUZW1t
-ZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBUZW1tZSA8c2N0ZW1tZUBrZXlzaW50
-aGVjbG91ZC5jb20+AAoJEJu4Y7D1G7iKmpUQAK9EKFrhM2xi5GeTFv/nhzwArK2M
-pncvQTBGousnyJYeqW3dptSl/u0gB2CpOZdtMwvdOciB39B/s0+uvXOV/ZCh8Joz
-Sqsr7u2dJ2tjFw1v18ZwKDk7meZ/M/VJqUkEOC49FjU36Kx3EhPdN58u/V6kR4b6
-G08FSTjozwpCNK70GFNZz5pY4D3Pe70BFZhShVmHmdk3qA0ECbFs0bSk5cF5utQr
-iqvWiAWsO/6dU9NiaB9aZoQsEc+nKwl0gCgzvNhmYGKz6S7bjfdF/pXIgI1UAI2o
-dtHuMCU/E6OCFZIX9zROMJSNADmNSQhzfSlC72NJm2XBgvIKWigDIbHfIxm7To9y
-xB5WiBo9qG8mFH2kfe3Mo896wy0p2Ag369GuAg62c89B5uuV6nO1GVXEyOIEaklr
-ZC5NYb0r0Fh9w+Vndq1Hnd5GEMDDe/s4yJ+5JCTBgNpEv2L8ngabzKFvG7LRag8Q
-HmXm8yR6+CmKM7Ebhgweqdb3zk1wqIwloOEOy7dlJCcs/g9EzDSBZ8nNXQWkZXQP
-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
-YXJrQGFwYWNoZS5vcmc+AAoJELDZkbR8QIc3jXIP/1R4765cKL59YnFpQuJNwrJm
-chg6oh4E+C60cWes955cYCitUPzRkHeHCSmC55TcFWwhGtzQH8Ql4XleUJk7AXh8
-yMv3KSxG7Ic5/w4MTXAaY53r1q/ImTHnlSmF0+iMq4LF2BfLGW1lWXz+5D1Fm2fq
-lyYJ7BfDRwhbQZiQAxeddf+Ydx8d8Zk1CVqQOkhTFWpN9O+oxiEyxfo5SNOZzcCK
-i+cR0E7AB9qet/OTjecnKy4vFqG4adc6RNPU7d+20GOiJAZMOChdgl6knrX3b11i
-lu41ri1Y2PqHyjBJnm4zSVw8x8HxbpHt5TB/TIy7YwVnZs13mitxRoa5CwuMeyDC
-z/8Ob5K3fTF7/0UAsG7c/dhZBA6ENzjHYSxhlYDDL0mTUG+b8C6ZypLHeS00rky8
-g8mNV901vsGxoJhu/w2diFRf/o4QAbj+9nttxxtYvBKTvuHSEGFErOLV35Chixhs
-Mdr+Sl4eBWF3HxRJUsyIT/kRZzL41usXP2KH8CbkerQVaMzOb3M9RfO67VLPfb+q
-2JW+BdHMlbVsQdfWhLJoMTLHGgxhXCA7Fpd6slI3HrUvlFxd/f9DHmZuE63mvtjg
-I9GRdbDOHdkhJ5yTd1uQe3p+QWXsgq/YOIQj+oIVI5R8ZMXHzsec4vPFxok1uajM
-V/fXeqdDYutbZrQgj56piQKpBBABAgCTBQJM0uOxIBxTYW5kZXIgVGVtbWUgPHNh
-bmRlckB0ZW1tZS5uZXQ+IhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAYXBhY2hlLm9y
-Zz4dHFNhbmRlciBUZW1tZSA8c2FuZGVyQG1lLmNvbT4qHFNhbmRlciBUZW1tZSA8
-c2N0ZW1tZUBrZXlzaW50aGVjbG91ZC5jb20+AAoJEJu4Y7D1G7iKmpUQAK9EKFrh
-M2xi5GeTFv/nhzwArK2MpncvQTBGousnyJYeqW3dptSl/u0gB2CpOZdtMwvdOciB
-39B/s0+uvXOV/ZCh8JozSqsr7u2dJ2tjFw1v18ZwKDk7meZ/M/VJqUkEOC49FjU3
-6Kx3EhPdN58u/V6kR4b6G08FSTjozwpCNK70GFNZz5pY4D3Pe70BFZhShVmHmdk3
-qA0ECbFs0bSk5cF5utQriqvWiAWsO/6dU9NiaB9aZoQsEc+nKwl0gCgzvNhmYGKz
-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
-aGUub3JnPiAcSmltIEphZ2llbHNraSA8amltQGphZ3VORVQuY29tPh8cSmltIEph
-Z2llbHNraSA8amltQGppbWphZy5jb20+AAoJEDTqduZ5FIWoM3wP/3wzn9q+EeDZ
-kcTAWJLIpUBnYLa3pxCxodFl7D7/aIL2rvu57ifpyFRvW+0uPq2nOy4pvS/teUql
-p8AEncPslTlCO6+lRx2kGOpmIdz7Y3ZLl5E9OIwgSpxAVyy1Gq4hkzyGBCRFh+BV
-MzkYOp7f/b0Ac12xtAxuCew8w5hRikvZ0AwKsSkW60VbYfSLpoSIeJLsAyWzdTx3
-SQGBx0cg/fH+bk8czL1O6+VZhtNPaABuCQlQTFvXp49P6rvZi5jZuCMcr5m7gt2Y
-iV8EFJ9qgyaG7/QbQ57ycGAjbRSWB7bvJaSWcpNsMT/raXL58uQ9/YkEQxtFqcpr
-Q2XGbfCOUvOj64cVVxHpt+yDR4l1bDAyxnXzaX3XswKryJGFZlXyuIGIQy49aJGu
-K7onq4MFtx/AWpEraXhqnbadrTTDRkF7qCm8o6itVhTVVCjd7O3n464KIdl0fshY
-waKeKTS5LW46Pi1xnNHuLk+3sUa6UpRy1LhGtq2XnirZ7Z0+Ayr98uHmyeX9+FXo
-AQG+HuF7Hel4LQz2F/x1BrHko4+9jjze6QFLWwUztqtTRRur1D2QUi4lfWczrtZT
-2FhFdIPnCCj5i5iLEZxEz9+Or1sdsKuRCFoe093032JGJ7A978gKT5BvTKjIKLUf
-hSCpVhYJTzRL9FdnGYHIFXsb8OUQ/EzLiMoEEBECAIoFAkzStEMfHEppbSBKYWdp
-ZWxza2kgPGppbUBhcGFjaGUub3JnPiAcSmltIEphZ2llbHNraSA8amltQGphZ3VO
-RVQuY29tPh8cSmltIEphZ2llbHNraSA8amltQGppbWphZy5jb20+IhxKaW0gSmFn
-aWVsc2tpIDxqaW1qQGNvdmFsZW50Lm5ldD4ACgkQizpgHwjJdeXL7QCgkrVbQo54
-WUHnHKoBrcCapxl22vgAnRNaLFpJyp7xQr7qzm8qejj0aMroiQIcBBABCgAGBQJM
-0rXJAAoJEIJ4HeRtWVT6q4kP/2bGNVdu/6oI+aERmV/m8oaQK6BCwJXsAN4dKXRx
-bevuFEyic/HZqztb+7Eq7DRAusx99uJVwWYEUP9lgP9G2ZctNXP1Y1YloIZY+Aoy
-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
-xCCOHvbuZai5Zpb76f1+8/Bs3g8MStqA8lEiKDfhTD7kvBElYTFfkk+NPYqO6fTp
-/zKYEOBeO9VLGLs6S13xwZeJd9kWt4WjSH1uO+14ER897Xy1LxUFkPTx+zhSVeK1
-wxcoiz0LCYFu004M9MybeDdsf9msHpzDqd09yF5yKTvNBDTuFXD5lUoy/Wl5DIku
-mInGRtWJAl0EEAECAEcFAkzS16xAHEpvc2VwaCBFZHdhcmQgQmVyZ21hcmsgKENP
-REUgU0lHTklORyBLRVkpIDxiZXJnbWFya0BhcGFjaGUub3JnPgAKCRCw2ZG0fECH
-N41yD/9UeO+uXCi+fWJxaULiTcKyZnIYOqIeBPgutHFnrPeeXGAorVD80ZB3hwkp
-gueU3BVsIRrc0B/EJeF5XlCZOwF4fMjL9yksRuyHOf8ODE1wGmOd69avyJkx55Up
-hdPojKuCxdgXyxltZVl8/uQ9RZtn6pcmCewXw0cIW0GYkAMXnXX/mHcfHfGZNQla
-kDpIUxVqTfTvqMYhMsX6OUjTmc3AiovnEdBOwAfanrfzk43nJysuLxahuGnXOkTT
-1O3fttBjoiQGTDgoXYJepJ61929dYpbuNa4tWNj6h8owSZ5uM0lcPMfB8W6R7eUw
-f0yMu2MFZ2bNd5orcUaGuQsLjHsgws//Dm+St30xe/9FALBu3P3YWQQOhDc4x2Es
-YZWAwy9Jk1Bvm/AumcqSx3ktNK5MvIPJjVfdNb7BsaCYbv8NnYhUX/6OEAG4/vZ7
-bccbWLwSk77h0hBhRKzi1d+QoYsYbDHa/kpeHgVhdx8USVLMiE/5EWcy+NbrFz9i
-h/Am5Hq0FWjMzm9zPUXzuu1Sz32/qtiVvgXRzJW1bEHX1oSyaDEyxxoMYVwgOxaX
-erJSNx61L5RcXf3/Qx5mbhOt5r7Y4CPRkXWwzh3ZISeck3dbkHt6fkFl7IKv2DiE
-I/qCFSOUfGTFx87HnOLzxcaJNbmozFf313qnQ2LrW2a0II+eqYkCqQQQAQIAkwUC
-TNLjsSAcU2FuZGVyIFRlbW1lIDxzYW5kZXJAdGVtbWUubmV0PiIcU2FuZGVyIFRl
-bW1lIDxzY3RlbW1lQGFwYWNoZS5vcmc+HRxTYW5kZXIgVGVtbWUgPHNhbmRlckBt
-ZS5jb20+KhxTYW5kZXIgVGVtbWUgPHNjdGVtbWVAa2V5c2ludGhlY2xvdWQuY29t
-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
-1Rd/N9uAngaAuoqGAThmyfc=
-=G1yK
------END PGP PUBLIC KEY BLOCK-----
-
-pub    FD5DEA07FCB690A8
-uid    Baptiste Mathus (Baptiste <batmat> Mathus @ CloudBees) <bmathus@cloudbees.com>
-uid    Baptiste Mathus (CloudBees alias for Baptiste <batmat> Mathus' account for infra access) <bmathus@cloudbees.com>
-uid    Baptiste Mathus <baptiste@codehaus.org>
-
-sub    5F68B9B2F1725F16
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFFCLwoBCADxtcGi0nfolr1kGWe3jQ7n18roJFwBs4Q52nx0h4+a8ZGr7/1E
-1brakrz3t/cTSZIrhfru8kirP8cJtXBxpd/nCeRrB/4ZtXPUJiGwKx6sVGr0ix6U
-eZKQb3anH3jdGTzZ2csqt6Ro85SvIHfqAREcPOoQk7Kz3DFOGbSfECN2Wf1pTnRT
-jdF1Z5DkoTd8sGBmGOdhNMzgqMTHz6np6M2B/JVP5DpcKPbbMhQ75RPcxNEb4QSa
-HtCL+gMZiF7fndWx2Tjbpanbb5+TomfWOMizpkyziyYeUmGoyggrnXQ4BMlzsIuK
-ATz6wA5j4qfRLfoDDgNv5UacVAtWL+rlTP8NABEBAAG0TkJhcHRpc3RlIE1hdGh1
-cyAoQmFwdGlzdGUgPGJhdG1hdD4gTWF0aHVzIEAgQ2xvdWRCZWVzKSA8Ym1hdGh1
-c0BjbG91ZGJlZXMuY29tPokBOAQTAQIAIgUCV81wjAIbAwYLCQgHAwIGFQgCCQoL
-BBYCAwECHgECF4AACgkQ/V3qB/y2kKhonAf+Lcl9bj90OOyUANRNkZnuq2sLI+KD
-kerGmbwG7FJCM/Hvq6MgtNaXt98RfU7a1aBmmM6uTOBFko+7o8QXocnU/2TrlsnU
-yMHsFfO7OQSQJebSSyAyE1vy5VYzblsqgfs7Zreb3BO/awzr0GZXjR+g/q6ivxhK
-+2pIkdfuBBkConNzoPqSC1f/F4qZuCi1e/VM5LmincIUEnWUR/PXpgXOwu/KoyzX
-X8VC/Vwk73vGaeBN3avCMVzNUmyYXELzcimcaa70ISKReUJvoYqHEDyVcMk9Yzjn
-VosDTfun0kUcfs2nd0ZySyygn80JHsZURIzEAnliz56lE8Fq5i2MO9o0ErRwQmFw
-dGlzdGUgTWF0aHVzIChDbG91ZEJlZXMgYWxpYXMgZm9yIEJhcHRpc3RlIDxiYXRt
-YXQ+IE1hdGh1cycgYWNjb3VudCBmb3IgaW5mcmEgYWNjZXNzKSA8Ym1hdGh1c0Bj
-bG91ZGJlZXMuY29tPokBOAQTAQIAIgUCV81mXwIbAwYLCQgHAwIGFQgCCQoLBBYC
-AwECHgECF4AACgkQ/V3qB/y2kKjQQQf+K6NNaERzm+5dkPOdmrVQQPAXrUxGW6b5
-Bsx12mU4qJKxQsq9tKsw9kdkvlP7rVhJATBk4J3ZYGWSqQajnVcAxznlWZVksWqo
-rCtYAH2+rhlUBo7/mvDnCW+z0vfEwBS4vQM3Oo83CyOecSnn98wp+W1O+TdCZVAf
-k8UOrODdc55VpXoQTw4PZ2uGr/56EFNYNXia6O7H0FuyDM6g5ilFd5Wxpp7qS7D7
-zJkWciSGmOwcw4NeeAMAu0bv8X9vmom30EEoFa6o3GHUJz0/DsbaoAOxcVMIymY+
-SzQQ+XyaHpTeRdpWB2qQo6BHSktm+vxp54811qSwyqPp0uKjHmVFLbQnQmFwdGlz
-dGUgTWF0aHVzIDxiYXB0aXN0ZUBjb2RlaGF1cy5vcmc+iQE4BBMBAgAiBQJRQi8K
-AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD9XeoH/LaQqLyjB/9diBWw
-NMYG6UB3ijZYyUo0P3F49JcboW8U8vtGkDjZU8bSHkDQX/1mstMSTPoO63TrszRh
-UCn7lMxHfDaYVhbr6N622Jc10WhGiJICPGSz4azHdQA4e2tC2l2BCMnq7mvJ0bVx
-uqVb3VE5P2R884g3K8Jq3O3tjWTten5Z63UvqPcPmpN2C8WoI4EDWqxTAxyJs0GQ
-hNnfPDKycIpv7ESjprJ7c4oo/K0YUtlK5rF3eNorZSOrj6adsrdcf7IMvQxnI2Ro
-tFr49wqdvn3fTW7db+1qoXAvsHV7bHZPxc4OmOeCuqNOoh4J5ftROO8o0Gi/wC4B
-bniNzu7SndfMOTjXuQENBFFCLwoBCACaK5wadodZGLdBAAcRg9rwBzPy+F7ZXdwQ
-A1kHo0Z6xhQJP2/X3C/rEgKW59QhBLyEMBPELRtO5vTC5UYLu0pHK0XsOEacFVTW
-GQ+gLGp2UkScAJEgAQPYNNWrAz0MoAPQ//RW2Byph+WBVtgnP09nmq/WcXjv0tz7
-FrSFW/A0uADkcEdWGx6ItNiHRAZBgO4uzSY8GUw2YSEBjAilDwVs/Jftj5dlJlwI
-JzA0VzNIFunKwBTicMHSSHRNic+zlxMOs02a3XK3NBPv9a5DIffZuU9657rHmZM9
-zaS1PyHsMbpZsy+hFtxMFfVuViojg63ZC5eh9C/ghKCIbP0F+L9tABEBAAGJAR8E
-GAECAAkFAlFCLwoCGwwACgkQ/V3qB/y2kKgcqgf9EGoznHgOwfohcWsi6uIuLgsT
-ypd2f+zPAYpgySP8LK2+UZBnTzo6zxtWB0ZZAj8ICdciVOdcSYim/X29pRzygKYD
-JpHh7ZvvxeB9bxg7Gfd8Ml5Ycdf1x8L/Psi8kajbkMczrhClxhAR76Zqjpm6gvyi
-e+21f6qAnx9B+J5jQpN6p5uLg1Ac3dU+kY9MJLL8qy53yXxJHfcF+hMoAVZPajU2
-fzySiLttENnxXHIqJiYj/N53RJmcQdYLNjQNwfpq01DJy0k5nvXDGCZmgUB2T7w1
-sVIIF1w0sMxaEy8blxB+j25b3KhYYe9NiQvK+/gthDgWyhkHs2UALPQwIfd9ig==
-=YlII
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5B05CCDE140C2876
-sub    9D29AE4A6B50E01F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQMuBEwVZOURCADNnKQzSjFuI9/IGj3WTJcPU2B/H8NbZaTsz5WE91WumgZulK2q
-YeD4u6zdOyFK7DEScgxk7dicox9cNEgYKQnQXctDhfqER9bnvA2iJ+AFxjRAWyvs
-en3ClYLXT5UVx0H1ZfDVKCvmaZVirZInfkqbi3OiPQoWrUfu02c3DiHQJ+Y34kdB
-egH2sIShNH8WLfEZ3YDQ4XaWHVuN1C7VwCBM8R3OeTTfyDrTsuyqJ0SeZXRR/6df
-2pEckjF9DNSXyjzFg24MrZhuhgbnj0oR1zmRh1EF+KlBfF4DF4acfxWqqcJVJx/3
-FTtOkLe3Xjj+inyJgxOW52gD4DsJpyf1tIbjAQDZvOdlRRCqZB4FnzzIb/1GmkGD
-JpDLC4MQmqgxkm0n8wgAmmHLpqDTdmuyJXvdX9RdGycpW64sljd1mpzTWJ8UKDhj
-uFQVHSSEdLoHoVj8ItnBV2kXd2uoQ/tWzbxFBST7wE/tX0e9G5XWaPKogvOKeDus
-u9XTIds2krYp80UTYWFZ88oNwGikdIrEYURSYDsYt15miROtKHWbSOHeLVbZqgVx
-dtWPqQVfH4gJGEH97/OSmozqDVog1aZDKBLGZQosng5h4j2RAQpjkaIdxKl8m7CQ
-x0Yi9tA8yD1QhRGggANQIb4n00G/vm7RMU/7NBvvjAQ/nAFjbsyO5oX1rBY1M6Xo
-NFqIBrHSBzV9MmhS3nXU+ZjAktCRhyJ7TsoHM0OYEAf8CduM5Zzp5w02iVYkFQBB
-wAoKHMpycW5LhMMMS4w7gmOfP7y04rtg6+zVe41y6bOqn/SxHCcCgnE/nhdexlzH
-ElYE1H7+HpphoI5vEwS6uElF67CoO5r74Zrb6nshGEj2AoOqjbrsdQm0noBBNYAu
-f9RsjU0sQQFzLW8+2xahqK3oZkLWOkSxzLtVwJbm7EGaGIYxEBjg87OnGQkAi9vv
-tVPwdO3VWyvgKLuPHudLDhTpeH3AMbzKgnru1Pnh/ZpiRhPzsbuFtFPEX8PMuCyE
-n4OLzUALl98kXuPjG5ww+24UsNgKMbKbu8qq/zRu7IHlpZvd730RoCWU2/i18tnY
-zLkCDQRMFWTlEAgA+MQFGIhyA4Ww9g7J8ZiEltwSzRblrjM1q9anexsBIGsWH37A
-92rlVK1RzMVfhj5yl+BzIBGO+zHbgycX7iB5/Fwsm+6R/2Uich6NDm1Qai9rc/jg
-3MS0phOAQzgxlGKOTS2GzdbDJCBQMijDObNe+Cs5DNB/E29/nzzCTQvtRzSeplZN
-r+8Q8lWz6efXmm5EeeZxN4x1YXjjzMJCHbc3yGxOjTgYQOs962yUYsg9UDRJm1OH
-9NKZe1m3dTRIMUcZvL12dq/kyiHHR9V/6CkdiNw1AFMi3tvEdvX4D1k1/Qr/2ORZ
-E4lRzgug4sKkpgaclLnkJZ9EMczmUFTGbbkx3wADBQf/Y+2nZCJSuHiDv/+SdhQh
-OBapZ2hYPDvg29mpPqin/LwH7eFTNv/oos1wzuzGtTHHGEP5mUQLOxjwdAXsWMMj
-scSbCs66ytTN7X4O8qh+1yN7vrM6ZBL12Ix7Ku40cgkWyvTVLBXKaEGm4ElhAmSL
-Fpu+/fJw0riR6rIuwHcGB4R1IJtMWcj+b1odgw9QmJ8AGpHh2WVdXspoCGnTUN4m
-DEswZjplkKXCgLypU13SrHVOqhjd4caK5GNZUfWtCKtwNcJMnvgp2truMvh9BBn6
-widfK48hEknQtXzGjui+bZz2/AD7/OT/T1CqDspB8IQlBCMBn8J4U1grSrZ1wTJf
-HIhnBBgRCAAPBQJMFWTlAhsMBQkLRzUAAAoJEFsFzN4UDCh23wsBANDSDn2KWz7H
-b5geDwUTX4T8Uqn21eFbp54tFTfopCd/AP4nTdX1iahsClr9q6G+CWQBuQWHVmq3
-FlPU/jTn6vXQwA==
-=dKtU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    7457CA33C3CE9E15
-sub    ABE9F3126BB741C1
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFIXyRQBCADe285y3Pu7KzoKyP6wqeNXtvvuwMatAmPm5x/i+S8MlryqzsYa
-x6twUmXV1yKjjtGrO+9fHvTOWBfSSP+fP9KTaTQYSasoJq2Mw4cQDy1i0zrxNZUw
-N4/BiyjQA25sdfaOolhO0sFlZuTZpYy5wG72KkA1ygNq0L+8aBKhEF6zDU61YzCC
-AxjcgTftgTeeoqkJtYa06lNz3jmJDN+zUQignfRa3ymoGtFHTzoXR9maE8RWDty4
-y+DY+8ibdGgSgKPZ0byTCDyNojgU1YTlADa/1/NY1ShYg617O1xicLNo0JEJlf2U
-Tu4Ymql36+xSkYSISU97Q6Utgq27XMuZvDUDABEBAAG5AQ0EUhfJFAEIAN9NHRd2
-bYP/3CDi+n1ilSChld0NR3DUBgS/AdqQ7IoAUfj7skyI/WyaMdV4uy6vRh5YgNg2
-g01nd0LLZR8Gf2Ck+D6F88CdZaTxlkcxHV/dXMZ8yBO+0D6yFRZEL7Imsv8Ig4QX
-OVwfuiXEPk/Ef5Dy9SdAVhcoErTGGR6BOGVVvexGtBwefsjMaOG0khkRbWIQ32Wx
-fUFuAv5XBQ0ckLrlKvYWUYhOlXg27GtFKH2EBBF0Z5ZWu7gaBFwSV0oLp9EWcD+C
-+WEwUSfBdqfRJtyXvgf4kZdwdQ5caM8P2/Sdncl2l/LU1At2Smc+plr6zhIhDlLh
-lrzKGa16oARSBdUAEQEAAYkCPgQYAQoACQUCUhfJFAIbLgEpCRB0V8ozw86eFcBd
-IAQZAQoABgUCUhfJFAAKCRCr6fMSa7dBwURMCADHrqwRNHkbG1QsXJr9oUK6KVkL
-sPhcngIhxRLlqe89omg9G7eGNauzs2PKsB3txotCFc7ROVNv/TAuSDYzkPos8G46
-p3bGesjfJb24zc6GMT4RGIJoh1oNG1IciafIIHjp2ZJHRmEDwmvZG24OHJ+mlHLj
-aedtqlWu+zwwhH2VZrI/U3gW/x4imbk9UyyzciEIxrAc+fc19xl5PkUVcSDVC0cA
-qGpeZz8+SxFaf3Rr0aGnSbeuHRjNupmoxkQOAey1ztmdWiCPf5RFfmFD+fENh+/x
-qYiGorYpcIN7UAsMkvD5UHc5ZG2tTD41jM99w9Lm/xHJ9ks8gNwZESwIzr6ABKIH
-/1ulsflI216qPz5o7uUxlTm8NfTyATfCUuZEDMYGOjDQPqQa8hFebqjWWYBUq2Sl
-aKD2xMeEuEXV+M5k88Cx6T2nvaZWMsrD7uGj+tTsFaKBGxP5p2OSEWOTETKKv6Cx
-7vcMTQmrqSFo47bFKlNSs+aVM48UnQeFtTDyOhwa5jvtqtst4eQHwHWQ99BK0TEy
-mNx0vF0nPjWA76CRrfopOwXKdxJgoKq4MrxE92ot5I82AZBPeiWVJ+6wECeK/GoB
-IXZ5jEUqrQmmzIboWA5G5PMJ8egzLJNRJjTWHjCWrUTnwNcqaD4/qZxIlW4Lt0uv
-Glx6pKOJQ05u+9X/BzoVWrw=
-=ajY9
------END PGP PUBLIC KEY BLOCK-----
-
-pub    164BD2247B936711
-uid    Marc Philipp (JUnit Development, 2014) <mail@marcphilipp.de>
-
-sub    EFE8086F9E93774E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-Qw==
-=iceo
------END PGP PUBLIC KEY BLOCK-----
-
-pub    912D2C0ECCDA55C0
-uid    Emily Johnston <epmjohnston@google.com>
-
-sub    37AE8263DA3084E5
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=X7Ws
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2A742740E08E7F8D
-uid    Terence Parr <parrt@antlr.org>
-
-sub    74C249541619FF0B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-jJNKSYyrKuT+DCAd1uFvcTw=
-=SigC
------END PGP PUBLIC KEY BLOCK-----
-
-pub    11509ED50EC155E6
-uid    Konrad 'ktoso' Malawski <konrad@malaw.ski>
-uid    Konrad 'ktoso' Malawski <ktoso@lightbend.com>
-uid    Konrad 'ktoso' Malawski <konrad.malawski@project13.pl>
-uid    Konrad 'ktoso' Malawski <ktoso@project13.pl>
-
-sub    DEDF3A7EB400D53A
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-1+61dcLTcdUOi2uBhwZG67Mpp3cSRw==
-=lHW6
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9C538D5A79281639
-uid    Alec Strong <anstrong22@gmail.com>
-
-sub    81176177BB514041
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF3xPHMBCAC7OXU5uXXKttUU/BwWm6q08NBC3ybk0fNIfoITWiFA1RtxO7S3
-K4ijImBnLLb7ivjpTtIWzUwFAfSZHc3LgS/TBQJQ2PGsO4/AdaMAcs69irgfoPYY
-1sJkR/Iw/C1gi7KV8PR/vwIE5N6wVll42FMGjBvKl7wTmvuHDou12tANXWJp3X3M
-5qj4eMK5fIv11u0vPIsmBHQTPzZN6prxAEp8Dm3XDT7OCZxfCYsy1Rl6zUIY01ai
-/lOk6YAg6IjHqGyChlJnhQbmvu4kNrRiKRSElikiDDra1Ltj66AGD86O2yQ/21ha
-muWwm0GWkl1gd3k3BOy7EhvDTAE3RFi4f6TVABEBAAG0IkFsZWMgU3Ryb25nIDxh
-bnN0cm9uZzIyQGdtYWlsLmNvbT6JAVQEEwEIAD4WIQSbvBw+QIygnPdtGgKcU41a
-eSgWOQUCXfE8cwIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCc
-U41aeSgWOWEcB/9tOXz5kHKjfZOFKjP8v6lmDZfpJmt1oFngOLVm/fjqMrP1M47w
-cTCershV8DW2LWIoAh7p5w4/9c6Uaa48YptT5JqAQ4G21Fy0P2bAZ90uDYRxoY0m
-ybXiH9lwTWgrj7X38HBZfZthRT2THLWXYlYhbsxQ3s5Kfj0gdAN1R3IMm+C5bjxe
-n3X7fCcShwbb+rX0yCH8uUT/kjVJU0KQHXwih6QcknkK5pIpBfLRgukAf/qYY73b
-K+lUBXBxxiYUGc+ydQi0huEpNOTNokOh9PB30wBwccrLPLeWrpakGpUlNv3gZ/sI
-cHXWDtBB2g8KxKESfWzoroMq6y+XXe3ubjE/uQENBF3xPHMBCADGJu/jqEe5/eot
-oS3YqaBATQPZyKgYisyA94Ivo5ZrRGwVACW3aWbzeGdGGr3AazWmvhfMovSp5Iuc
-yFTvjIQwlNetAXHuZUi5sN4I8o0sDPER7Y2RqBfZcvU98CgTziJe85iEy1Vx0NVJ
-OSd55ZeLtEjeQbF0MNljrU4j4jqt/NR20C0DrJ+tgH4tGuo7n3AWmCSwzoXRrzEJ
-dkqf9IWXww21MjmOYGEOSClUA9L6HxeVrZX8IauV1eVeDNyTUbC5eVAhV4/8TiMM
-6KbBRUsPzW6TXbo2HTAtRPsvzM2ssC3QWV4aafLBN7MadK51ZKD1ZeNnbPvxGWrL
-XDVaXDZvABEBAAGJATwEGAEIACYWIQSbvBw+QIygnPdtGgKcU41aeSgWOQUCXfE8
-cwIbDAUJA8JnAAAKCRCcU41aeSgWOZNrB/0UbtDXcjpzehkR73Xc8dj8DLgwMANh
-5Jr/dHf/ZENXOIORuN2uWg0Dai0mZ+gPC0jb2qNK0MdTbHRNHPEcS0UX6wDBX0Bc
-BcbW3nesQXv4LYJY2DN8Q0vtxj2Ra/4FfxT+lZn3A3BmHRu+Aps9nmJoGOh06ThO
-e+6KezHnYmmo8IDzS3JuyGz8ma29Qem71VDAMlLNg0QUN3RJc7nSLdwoLUDJWmpm
-WXmOR1JD0iewyjuSmKHuizRPPNVMbg9R+eMPF9OECheR+Pseu3XTqCyqedEDItwb
-htywBZaReIkxE3VIhM7CEI9gsVAaNgoe6Q7BXIk3WMDpo3t6JWORF/PE
-=EwZF
------END PGP PUBLIC KEY BLOCK-----
-
-pub    479D601F3A7B5C1A
-uid    AJ Alt <ajalt@users.noreply.github.com>
-
-sub    868FF6CCEF26A83C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF5CDMYBCADC1/aWU6ZbGZEphRbmjUPNfqh3N5goSnDCou97mmQ9Uq8iBuKS
-UXJnGSOHudXK56f+Drx5lGZdLAzveZdqaqb1o3yLFO3PJxwj3Ulhab3O3uTG2eR0
-2Xo7GKjRW13kEfphJrfVIaQq/TiyIG8IQ1dbm9Vuzc5NLDIeC4jxYD2S3hUqCLGQ
-BiZAEH9un2cPax+hiT+9MGzdfQwdVrSQ9aEA9mtMhEGsk80XtxXJnd+hw2va6l5s
-lSErmH5nMtyKh/n9uo/ap1CfPl98n5VUI8dDtUfWVrqRrkyHgdX+MII0t0nABV5X
-rJLneg4dVy5Yw/+FVbLWB1Ta21reyytcIYQXABEBAAG0J0FKIEFsdCA8YWphbHRA
-dXNlcnMubm9yZXBseS5naXRodWIuY29tPokBTgQTAQgAOBYhBAPBIwOMIKrp4obI
-V0edYB86e1waBQJeQgzGAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEEed
-YB86e1wafLcH/0X1r2LOU0cdgeDJ51mOmzPeheibjJkwNnPqjuA+xMe5Hf2ujv1B
-nc+HXaJeR3bcKanxxlxw3whY7v/Y9vpzhhyr742LjQ83XYX8Weqi0x6t+e8WH+pY
-OVtP3SRvEAzwDpQoQysHsjD4ZUrsyCv7S/D5Gu9JaCImdWu1aa99Tg8HL0FxxSyd
-qmurKmZ0BowKojyy0EWcsqXqXk5xJg0J0+JN0pb5nmmTuRMwMH+tVroXIkW4ZQgv
-HeDo8l67DAouKJbLC3AvSrc7pstqF7dN+eclRDIRR6yEBmFM7JXkGh52DcsDT+ow
-1pd0J24jowri8o8SFRDC56RWC/TdUYEWdpG5AQ0EXkIMxgEIANaEBxDOsD+NMT36
-WmAQUQFlaBI/wmwFegaKAKUqkJFdHKHDPcCvdOWs9hZpSp+Fk2cjcIgNnh4x5Xr7
-CIyrhyVoUg1YbpXCg4tHA+sE3I3LXA1puzN7b2iAm4nmUFzx+5Y7uQrfNJAaOaI3
-SaFxg+9pFYUrohfLzqwDoizlz/Pm6QqWOPi2eKrd140p65Gavof73MvXK8Ls7hZU
-i8DEZbTr34q6yvwkkGWbahtj2099AlhUOtQy6OA5F3jRtXyqZzmgwDGgnnbfqTQg
-ENVXc8tb0/W/OS7Th/wpobpozN0usf1VsFmVQV4tsVSxQpJty5VoqEr1bOjWtFb2
-qtFg7G8AEQEAAYkBNgQYAQgAIBYhBAPBIwOMIKrp4obIV0edYB86e1waBQJeQgzG
-AhsMAAoJEEedYB86e1waaGEIAI52Lscl2hUmwnNhBVg6wQPPjp5W0oCd3rWiDqC0
-B/gs7+vsC2HPbJ2QwZviL28xIt7V34tUynESOYovcA5LYtCnFRa0drablwy1mCBf
-dnEgu1cgYsk/2maZtM1/Kj/LY0Wb8u5nsG56IrdUenmuVIn0i7ztGx6jaLMH4L/d
-LK57lGDGPLb9bEqOI9H9M63v5OEE/LAk3jA7C7L4jCL8tVpbNSD0aNUltXrhhhrw
-qG8YJHvA8OUILprncD6noTmVTpCG7nXYHLq+eWRRXorTDqnUaF5KxqHfb+oWGNSc
-/Fv2Nrc2ZlrHnRSHOGobgHmRunB+gHPKax60BM+pUm2dH5Y=
-=GErA
------END PGP PUBLIC KEY BLOCK-----
-
-pub    296CD27F60EED12C
-uid    Charles Lee <ckl@google.com>
-
-sub    D95ECEC170500D9F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-pbySzrh5PAD5/2W6CzkFMpH6a6E=
-=sgH/
------END PGP PUBLIC KEY BLOCK-----
-
 pub    E6EC76B4C6D3AE8E
 uid    Sandy Zhang <sandyzhang@google.com>
 
@@ -8649,2307 +3420,142 @@
 lRop4uUznu5JDawoYhbEkn0bMIx3gM396J2jyp7tTcNeVCr7+VnjoinWzawDYxCH
 qSxdSmVH4q8qgTPDtoIcKUdLJFUjJV+2Ea92Y/wcKHMvUYUfcjaqP3avl3AZrktP
 DhMeqoyMMMKE0VsAEQEAAbQjU2FuZHkgWmhhbmcgPHNhbmR5emhhbmdAZ29vZ2xl
-LmNvbT6JAdQEEwEKAD4WIQQuW3PG79LrRTEEwurm7Ha0xtOujgUCYpE2LAIbAwUJ
-A8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDm7Ha0xtOujgIlC/sGV3si
-mhEKFa3f5Cg+SPeR6FTxXZoqUunvCDnsNjzcXwvusdInKD5YZiSu3GRyvybb8RB9
-Oe0TfWyBXg2UDwIx5IXfpq3ubRh2jFSYWC0uM04rR58D1w1A5AH7EZ4N49b4/Nfm
-N9lEMch7x0C1uD9aupGmW+n4IVuaw2RAYjp3W5Sf/Yga3UZLivjrh5y9FXzhAJi3
-fSznHzbZs0gALRJ/SzYLrm/JmQDMLwW6nq7UO+swDimSGwLihaJn+NOcvr/jCEiV
-p7nQ9cxm1OU6oIqROR2GJFtDcfKeJEA5IhCc48TyorON96yUoO23U7BJzPOVmS9+
-sFerquQq7HMSMw/9TjznYkegYRcClXiVa/xEqMn+MdzFVwOBkbgvo5xbo0u1FvuT
-uAYtIhGq9pWd2DR9VifqGJDsVM7X6u5qBoTZRu0tV9til0OogFUaVytEnZZ2a+aB
-aMXrb+yrX4VRaP3AIdqTkfQkTBo22kIi941unbUhKFck95DrS7D/GZFm0FW5AY0E
-YpE2LAEMAKyGd+sGmSrCMk5AuYVZBvymKDD7mAXvXTAmiFjFZmfj55XTUk0EWFqh
-PP2Ck0WswlCefBout85Z3BONx2eN7OyVEljVK4zcr4P9A73mCCau4iGpgYKWbhyL
-I9LOEkdd82zzuOO4Ts2qX7LddwZ8hZlZUUY9F0qED24hD+KptQOeTppviu/ybgR7
-5tyzDQBymJ5N5fGssEREFLTsnVtoF39zfVsLODP7s2YtG+jcMf1fKbN4Q5a9DhVr
-UIYuIQcsQKp8qPHK59Bp+42eEIZJcoW1sPMUnxejPjBUdAu0A3dQ7sLLcdAMIy8t
-ebmNXYeTIbz1Ws2Djh25KOdj04v2TAV3XfA8S0EQcFyv0C+zp14LMLMZz0IGUibL
-T5R1tGlZMrn73TpOg/fqBCXDG6OfzN5j25a/j5HXgWQIS/m0Dfaz62So08qSe+aS
-3co3m8UloU+lvKYqn5HYcSeY4rDVzEeQD2AM6lTsaWeaMnVSU2Pij//Glgz0WdQC
-Y9wzlTnvtQARAQABiQG8BBgBCgAmFiEELltzxu/S60UxBMLq5ux2tMbTro4FAmKR
-NiwCGwwFCQPCZwAACgkQ5ux2tMbTro62dQwAp9grRDjnX+jWnC0al2IJJ63sIRCQ
-vRoclc8OS0p0FipMkYm/vzFas1MRUJa4ekE+83eqP0BbfIjjNovLgozJPAWHSuV3
-eBOK5+vSPZMcmO2vpaAIJ9pKctMbfVvF8KONukaF9dpzDmBdolFAaSBQ/dywVjrG
-qb4AQJgEs0WkobX8bkRCWL+3seLJ2ABUDgQNJU4IGwe0TF1Ik7ceIHFXuSNzZZNx
-j/0yB7kvbgq7y+Th5wNNxPWdvTWscSHm7L0ZPjTqsE/QgF4beTm47ZhS+QUNEtGB
-Q5cKh8f6cw8vNFklB4SXFYf0YjbpiNuf7Po0W/rCveGsbLNpF9ZMTbv9T/7JwN/i
-YVVhGP4KTgOEb2MFLfTun9XD993vWwjdVvnKZmihCzZVagM8qfYpS/nHJkyXBymY
-ejD2ColWB1CGlpxCuwlkvOcsqXogp2AcNOTjOX5fiLQtNUnZnLad1ZmTwxE1Ui0x
-MmIzscVR5uuvPq1m2aUkkKLFWLBqkpuelMmW
-=W+so
+LmNvbT65AY0EYpE2LAEMAKyGd+sGmSrCMk5AuYVZBvymKDD7mAXvXTAmiFjFZmfj
+55XTUk0EWFqhPP2Ck0WswlCefBout85Z3BONx2eN7OyVEljVK4zcr4P9A73mCCau
+4iGpgYKWbhyLI9LOEkdd82zzuOO4Ts2qX7LddwZ8hZlZUUY9F0qED24hD+KptQOe
+Tppviu/ybgR75tyzDQBymJ5N5fGssEREFLTsnVtoF39zfVsLODP7s2YtG+jcMf1f
+KbN4Q5a9DhVrUIYuIQcsQKp8qPHK59Bp+42eEIZJcoW1sPMUnxejPjBUdAu0A3dQ
+7sLLcdAMIy8tebmNXYeTIbz1Ws2Djh25KOdj04v2TAV3XfA8S0EQcFyv0C+zp14L
+MLMZz0IGUibLT5R1tGlZMrn73TpOg/fqBCXDG6OfzN5j25a/j5HXgWQIS/m0Dfaz
+62So08qSe+aS3co3m8UloU+lvKYqn5HYcSeY4rDVzEeQD2AM6lTsaWeaMnVSU2Pi
+j//Glgz0WdQCY9wzlTnvtQARAQABiQG8BBgBCgAmFiEELltzxu/S60UxBMLq5ux2
+tMbTro4FAmKRNiwCGwwFCQPCZwAACgkQ5ux2tMbTro62dQwAp9grRDjnX+jWnC0a
+l2IJJ63sIRCQvRoclc8OS0p0FipMkYm/vzFas1MRUJa4ekE+83eqP0BbfIjjNovL
+gozJPAWHSuV3eBOK5+vSPZMcmO2vpaAIJ9pKctMbfVvF8KONukaF9dpzDmBdolFA
+aSBQ/dywVjrGqb4AQJgEs0WkobX8bkRCWL+3seLJ2ABUDgQNJU4IGwe0TF1Ik7ce
+IHFXuSNzZZNxj/0yB7kvbgq7y+Th5wNNxPWdvTWscSHm7L0ZPjTqsE/QgF4beTm4
+7ZhS+QUNEtGBQ5cKh8f6cw8vNFklB4SXFYf0YjbpiNuf7Po0W/rCveGsbLNpF9ZM
+Tbv9T/7JwN/iYVVhGP4KTgOEb2MFLfTun9XD993vWwjdVvnKZmihCzZVagM8qfYp
+S/nHJkyXBymYejD2ColWB1CGlpxCuwlkvOcsqXogp2AcNOTjOX5fiLQtNUnZnLad
+1ZmTwxE1Ui0xMmIzscVR5uuvPq1m2aUkkKLFWLBqkpuelMmW
+=Xlum
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    A4B1A03FB9C2CE23
-uid    Pierre Yves Ricau <py.ricau@gmail.com>
-
-sub    21200D723F53CE38
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFy+swoBCADGyV4k02OjVCrziziYIvIO+qDm8Yqxt4KVd+ISw2DvmKVcP7lx
-z5WVGvxVdAl+Xy7FdcrIJYFCsYfFFxPz+BM6+np2c477HkdIcDwBWiHEoOqMehax
-wlEBhJdJUVCjTKvpMgqs4/a0PddNcp/odYx20HzDAK+X6/EgL1McZk03okfMSn0R
-TUvZeh76SbU0aQRXdGlSs5IUtywn2f+5jUNLht/TMd/bbAXWA2EQo1UallY3+dj8
-I/Y722X5Yu15rLu8u+pcVE/pMO9CHeX78mgPU2xU/xwDSGtU5lxwNXnYpHMUdFB8
-YtG/ofDtZR9+9Dcjhb3xSIv6Vlui9HgOgvctABEBAAG0JlBpZXJyZSBZdmVzIFJp
-Y2F1IDxweS5yaWNhdUBnbWFpbC5jb20+iQFUBBMBCAA+FiEEucyhPFnyHGzoQajR
-pLGgP7nCziMFAly+swoCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AA
-CgkQpLGgP7nCziPuugf/fDa86INrKZ08fCywB6oMcLEi/sNBbaKaysbp/zmmANwk
-nTWrIH6fqfQfkFdBpA4roPrjCNqQ3gdpjDhB9U7IeqpUzzeM+WEWVOlkA098MFrj
-ToJuxf7oCMXCPAtW3S+tGM1FdIFtqzoE3mdbhde/F0ppJDIbuAZfjKJclIeGj7eC
-6QbLua+IQeDKuQ6TRuFCc6vWl38L+LqqmNPxfw7Uta9W7CrP5oUYQqrdIszeVWGV
-ivK8cyLltXgIKcWJmj6GLsJtIUuXAj3kg1d05HQ5dpIkgaRN7+Q9BnsTcdnc+R6r
-nprvl+/QNk6XeNIRrPKiv7SWf1gYWbi4CpthjNsGy7kBDQRcvrMKAQgAvap3U+0R
-j3ZFSth8u9AnCrJrClbNtysMEYmpK0JgiNpaCDbw5lPv7yJyTPjnGTLSS2qx/+C2
-2Bml6b7lV2JgCXA54p9sa9Jpw5Mili2rx/62M0VmqMCNZi0vCxBOlj49fSpyxfKr
-IJ8eNwXd/XbHl0uKm+AYCJgtmBE4+ErSb2tJ3iEPqRBq9vYXnm1LKIZVKHzZr1Gw
-LS039UfGBFtlChF7ED7wQ4XuODmz5dx92tkI6svqvOuXZaTP1PDTqu8l5+E8yd3q
-JvonloHroLKbTDEuCtpn4jDSN/LZ1C7ekRu9OjL4gChvs/TJsPwkVka/rw4OWEOR
-KQfo2iv64g4NjQARAQABiQE8BBgBCAAmFiEEucyhPFnyHGzoQajRpLGgP7nCziMF
-Aly+swoCGwwFCQPCZwAACgkQpLGgP7nCziMSkAf+L6oedz16wE0F2ZYc4UM+J1bf
-qS2HEesB7YGTwnafi14xRQorvFOJ+CxfyDnl9HGCbfwqie1wO7VNQukhWl95wJSc
-Or1Nv3XPnHq6RKpBQrIR09eggfegf1N67HmorYRkfA25fwe9KmbNAUfPiKa6Vyrx
-6htiUIK1V7ArKVXwBL0saatdOnwrxOiHKBbxyy2jyZgt+rHKNUFmQLiiIvqg+krh
-sSksRMYzjG3Y96Wm0K/IH0XcuiQkVaHPOYSEqODz+miiS/PSqbw+WhfSNtdKfKDx
-OS6mrMnFluqthJ06aXBz+RmXGPtzJvKnI2LN7lwoGXk5zynZK8AXpTOpWED5ow==
-=Ig1p
------END PGP PUBLIC KEY BLOCK-----
-
-pub    DEA3D207428EF16D
-uid    Dexmaker Team <oss@linkedin.com>
-
-sub    E8D0C72FC5A02B28
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=Uwhf
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3F36885C24DF4B75
-sub    97859F2FE8EAEB26
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFmfSwYBCADdZEuR8cs2ejLLW3+Glxiq15rVbHbxaWmmZApGNijFro/LzFrR
-z+99N1mnA5+Ar/yKmn8lsCiTWukGQzWbdH/QSRUdyHtzxbCSeONdMhdKl3sJY1h2
-jW28oYL6iOMtNYe8qKoCrHRtyTl7oqYtYuhMwdNedGrkVWPrInmg0ILUSz9RufCh
-6KW3V3eAwz0LbckpSi9ZNyCNssjINvr6bRf10HMucViAB0O1DjrwO6aiFnatTCyO
-ig5MMZjgRPKjMASsPG8Ri1xivBYS/tpgamQzq+htWkbEydNv9+g31S5sN0pPw2km
-e8SjKp3C8RkSgz+dJz+P6tQrmGvZNs+pm2M9ABEBAAG5AQ0EWZ9LBgEIAL3j10Fr
-ODkE7yVreTlYs7UrZGaJwdx8stENYdHHA7MmDIMkVnjAOkzAwW4zRXdtFHqICLUO
-L4ZRnAiGuyxiwvxXM7NuGgCfC94M2w58xf2JREaCmU5kII/O3KOv60y8+QixFZl/
-c7p3YOGwOQEEit5445chxYwM88Bq+LgkXAn9zNnZbOyUv+E4gx17khkyZOXP+Z2P
-d606+KRvENLlFbrlVaJ7vzGiLhvIr62I4g3hJj/ob5nXT2tZSyMN19bJOtOd48R6
-NXFDmVC3uLWBgqLK1UgV5SylyKg6N32CUdds6E43DHLVUipawknN4QDc3s+ok6j3
-nN688afjFCLQVE8AEQEAAYkBHwQYAQIACQUCWZ9LBgIbDAAKCRA/NohcJN9LdaVO
-CAC7wk7tKsSNDxLhcq+Oa6TrE3JDQUYx6xlVsw0ZOq+TIbk2D7S/4phY+YSUUqWZ
-rp2vpFlszbcJXx41+s/ljfNnkMVjoU6D/A3R0az9weFfmq0J8CoJeP86CNxCiRIX
-d1rZ6wHlc67QJZe/aaYzxOO8vkzkeEiDaXjvmaSoADucbF1c6KjQms/yJ9nFz/Mk
-FPRxWntD1UkxNLh8UQZhIZFrAmhpgdDa0xq0VCJwL1ZLEo+cm6wKTZb6iRnSqPbu
-fwS6/GYF9IKUp/WVQvhZ952mwzfrz9r1PbTg/fOo+MOGywdBZpEEPTL5pvfrrOYg
-5q0kixiYviNzHBn/YKmH2ibE
-=xwpz
------END PGP PUBLIC KEY BLOCK-----
-
-pub    9C4F7E9D98B1CC53
-uid    Benson Margulies <bimargulies@apache.org>
-
-sub    32E3DF6FC5E91334
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-4Q==
-=gGyT
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6425559C47CC79C4
-uid    java_re <GF_RELEASE_WW@oracle.com>
-
-sub    D547B4A01F74AC1E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE3XFIUBCADcj1zw8m1evCgEMqxgOfl6L8y1tsYWsX7tVPvHEkYlXHrdcpkB
-fGuWPrauvhBmB9sBkFfxzU98Ilz3Xk9pfISYiaMUk9Mk1ZxsCoYPVhxvOSvk5LgS
-sviDzjYdZfZtskUM0sRmjmoQL//fVQbfLxJ2zses21za2VHuS3puUbdcm8+UIl/q
-oyneDbzM7j2nYXXJPNXJOfvyVxi1+rsc7xcjMvAj5ievYlWwYlAIgYbAiz969NdL
-RkoA1Wg+cQg+59k7Wvi6xwTfzMsO4jfkV2p24xn4fpcch9J49UhADh6O7XEls1Xr
-80WjysMJWTOX1O2oTtV/BMjpI4gj08SgZRhzABEBAAG0ImphdmFfcmUgPEdGX1JF
-TEVBU0VfV1dAb3JhY2xlLmNvbT6JATgEEwECACIFAk3XFIUCGwMGCwkIBwMCBhUI
-AgkKCwQWAgMBAh4BAheAAAoJEGQlVZxHzHnEMlgIAJrrq+q6k8jwxT0DJO5peszc
-0X4Z4tge6FBwb/O1K/1ViYv4wmzwidouB7lAidDF/wPh0XQxBOqXpcE9V8vAqMnQ
-DzWS4a2H6/m5jUdgc6S43CvOszSfUg70X/N53+WG2XiuYMvrxD4j/bZbLH5vDD29
-Hh8dJVOsMPNtLaTKnkQvabBnWFXovy4vDebKj2/Ln3CVtqm6lwAw4KvwFZgeuOWr
-5g55O9R03czI9AaflTYVsceB/MaKRw7ut3VuoFr/HJQnfEonZLCyHZwjXqmqJuSO
-QHR0ABrHHn/Um2/eHiPAERctmJnVYv06S/mXMr4VCYSmYTU/LH96jFCW0rHKFsiJ
-AjMEEAEIAB0WIQRFvr7slQq9Bc8O9cNQoE0MO2UX8gUCWzeh6wAKCRBQoE0MO2UX
-8jkHD/9DGURSVUovLwFcBRLl9uh11cn1ULdUffNC8UkzBgP97cC3y3XUH2nf07as
-+QJRKYF8mbIP8gHBul0/Kybd8LRajMDRVtgcRSRu1Bgj4qALP0vAztrlhFDuztOg
-adxUfZhdaCX3Y9tqEhqygonQqYiJ1AKGcrZXgA5e8JuotYm93h/wuXf0atho9Gx9
-U3ZIJfe3IkWySKg2OKErT4oDi3PQd50iZwBH83YnWLtYPsNBAGvfIXLGbvPxqjqu
-17yY6kx5vE8+kNRAzl8dldajT2fke9ixPM0tp4qgQvajQRUXa7wnE1Gtz8lylJLq
-Ys8w18lm2/mvD/RZh4B8c9Zd1bedp6fTCo4i9tRGkBALbyMQknNvCdpjs71B+w9f
-OeYOL1nI/+olvtad5dtCK7/CQnDxnEB4WbfCZXll3QArGxko8FLBiLs9fJ84aWxx
-+i94vS+Ul5BMilaLEAcwDgHjB9XgSlJ8YuXSUQ9g/XWk7DgVVXHZFiC76FdQayEc
-adJPJkmz3qAchnLhN1e0xlHMKS4PlNGPy7L2rfMWv9/FXEs40knpfCHqYwZPn9Cu
-749FMUVkXFqdxOkTtaioI+sQ+fsoITguKk5rZapm3lfKwndv7uRXRFWfWdMtvBgo
-BWdRgsO59UMeaxk/Li10+JqCuB4XSiCuFY3OFwcC3r6qBDx+obkBDQRN1xSFAQgA
-urn65eNLggdkGY5Y4FJ/pHUSdTilSoTNrS7CAhfleva5JpoIw8KbnGtu1/8i/jlU
-S5HzMYpvz/R1XviZ7qdec56oPbumSSWJUTmcw9CeooBRCasDloNHtPOZ7LjoGZz4
-gWu9taqLIDfJnBSmLUUplHlUsRiEwYjSo7KhprU1aMPcsMvv8CZARJ71AsK1PpCE
-2GaP9BYHJGma4iFrI3I8aWHmiwXKIaBVyKeVkTvHXa4bvoLVXuOj15iuSOX+4ckd
-Gp8Hrbygu5sMWKYqXWtpgKVFnreORtkF8LV9FjPGTrfnqYDGUHY5UMfdpgH3sopm
-RTxxfbYgxrCThoGELKFfywARAQABiQEfBBgBAgAJBQJN1xSFAhsMAAoJEGQlVZxH
-zHnEhsAH/0dT5G5oXEAhXDJKsC8HDJyurmpvznRFT34qCsqjwJIIpMt2amGAFITe
-kIyvoD9DVC05Sd1ubtJKr5eo4OGKPgV9THQrPrr2I8RURmBkJq6xjssf1pOZMkJE
-z4TLZ4zfZKTP66vRPzXZ03eI13we0L+JokCgYUCdZEd61wfTdAwS6iBmnzQ0GDQI
-dXkizzHS6HwlEeLyFYPV/q9Wr38bBuBGwM6mlVrxnYGDIc6wEOh5z99gLeLiIXys
-e65IapqOzDMb1KcU3XMtwaEsRQQ4nN4MIA1vVvawk7av3ES981yzCPqSxjmWAi0T
-WugIjrW6eRqMfhWIeF6otn/vBGbp44U=
-=+bu2
------END PGP PUBLIC KEY BLOCK-----
-
-pub    689CBE64F4BC997F
-uid    Szczepan Faber <szczepiq@gmail.com>
-
-sub    C0058C509A81C102
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-B1jblPtxo2UqRO/qhPfqSkoVcpWmxgiPUFOr
-=w8k7
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D4DA5EAB3CD7E958
-uid    Jiaxiang Chen <jiaxiang@google.com>
-
-sub    D826E3935EE9DC71
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=E4ez
------END PGP PUBLIC KEY BLOCK-----
-
-pub    88BB19A33A18445F
-sub    FF59C22B07640A16
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE//SjoBCADao3lh/I96fWIY2ZU49ljtHR4Vnzmifm3URFNuv/c8McWGxxCy
-Y1+oolgVuJcy4hCqcgbkwTiAfBhjZSmsC1QK/2Vs1awFzGccPcgTBakFw/TUav12
-6Zb8y72dH0VxxcN/HUGBUOSgZg9IMe7AmmVnxbJ2ED1I3/opkC6ElPXFOl8EJdgE
-Wvinp4ok3mwBGMIexQDyEN4DviuqvmB4K+gYCjS33HtHh4OrkXkCO5pDNUDgkAZK
-1uG3GfmxGBjdG6nPWgIuDMEL3j1cW9r5D6I5obXsFlg6bX8mBs91jAtmfTNv+IAB
-bwUOAJC+9C3ZEIsZOcBSSdUIXmuRPa51oP9nABEBAAG5AQ0ET/9KOgEIAOokxMbt
-TY2zLvdAWD9xPHj1kZPThN7o52A9Atw0zKjiNFl9jy+IFarPNdbMzwooQWgx5Y3S
-bKdSCSDlP74psEMOttEdw/23wt3oG70I84RveLuTs+dTDRAd5w8jxLXhjm+QxhiE
-+z+peVhfe//u1+kn2vzesXMIRBdQTikjIZ3W5TMgu+RV7Fgf5zUWTEUTns1kmM99
-XPhOVh5BIr1kkty/Fyg/1Wg87leM3WZUoe/7bnWju+YSgjWvxwv8HEBYPKciNG5n
-0oOPoU3jkyEugJafmlhAt3CAgmFbfrJgkncXPvow2xK312iy0xIslAqm0dy2+E9j
-hYLlS3p3J8TLPGkAEQEAAYkBHwQYAQIACQUCT/9KOgIbDAAKCRCIuxmjOhhEX5s3
-B/sFcywEwoA4ylzSSsVctp7pjDczczlD1MnvCNP9ldzzU2oOGAduvF+zzJNL162J
-qMd1TMYnYROoZhIS78He+LriBSjCsweKDqEix12mtuWrAICpF3UcY8WLMB6SXgXP
-qnZS1cw+Prr+NVnuR+0G/cUJieVdKO5rcYuwrs4OGh2rEMRCksAY5FAMe1lSB4mj
-9jIGKW0B31D3/AxNlQuN1aRzGLj72k6d7Q91OrbQ1+yG12CLwSd6mS4kVBFjppUD
-JCKN+HD8NGQ9EtyiVpx2/gmqshFVdwUgAqQ4tKtFI713bi8xz/oNiHkOfclHdgMM
-E1GU2n+gEnCLRpmC3Qqmeb0n
-=2JQQ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    94B291AEF984A085
-uid    ReactiveX Admin <reactivex-admin@googlegroup.com>
-
-sub    9D149DAC4AC24632
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFPzzfABCADK/wEIRhUCUTj00TcBOxGTPs5ad8jn5D01P7P5ILpLOgmnUp1I
-E3EYy54PQYjDIeOFvEmEywvwMRV8yCVhhYGpOPqbegKwcebXoiMGhJjuRf2nPbdZ
-PSB+S3/WAsdydiPiz/2Xl6hhlaKIQSnSOgYPOQjbDjgfU7B0vYGPohYR50fbOd9D
-QLvwsYxQv7CCdMM1M+tx4HevvYOKrceAwTe6yRx9PEhmuXYRCes/AKOs7yODvNm5
-SFFlZzBrYMxh6LSmCAGfYrSGWJliJUuFMQ9U0R304nmVUo3rrCj3tD25Kdr7wj+z
-WjtJVBdWVFTq2/Zh0QnF7mbIOs4bYxLlKe+HABEBAAG0MVJlYWN0aXZlWCBBZG1p
-biA8cmVhY3RpdmV4LWFkbWluQGdvb2dsZWdyb3VwLmNvbT6JAT0EEwEKACcFAlPz
-zfACGwMFCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQlLKRrvmEoIWN
-gQf9ElK2o7JBUbQ/QgpPbaKlP7+Lgc78g2I20Insd51G7C6SFmnMj+Ae/EariCV5
-R8JObne8kfY2EpmME8ISUqPrFSw0hhR0q7E7jhZgHrY4s0w7R1mujjWYJQ5cSi0q
-2sQP1GDMIk6paJBFORedqQ25B0paWGGATyMLRu2ljz5tog3DVaE/yvaQWAgiH77i
-It24fY9waInC7F+ruYSiL9YwGaDi5VwV8mlVeNZ+yobjXllzsh29UW24UXjWJoEz
-1MH2IXC+v247wnr5s0x4GiBaYFIS7sg2WdPMImAY9tGwfKQRNs2kBAT4G2Y9cDx7
-Oe6eZTFP+VYBhioN+5GzDPMwwbkBDQRT883wAQgAqj9m/clM4PMTIRwRkDbrfFSA
-TZznMxgUe+jOGRbZgemEd0Lpa2Dgrhq1hd8jOQgm+suCKjhJi15oKHMYHRx435cE
-8gvdW/C8R+T8Iwd+Ce5IuaRKBisgcIpCcSBbaDgYqGsjhOT8W5N/Tgqobera2Wvm
-wDGnadIN82RQkvH9Sypj2eFyLuFUk1xIKCS25a62EYr1Pb2/mNwHvgEjkswWeoWR
-a8A6xQevvrcercj/a4dYB8m/RQQhdapo4J3gh/BQxJIHAvjVxxWyLfyOIdnV2tkG
-Cysl154R0ymVHIT/fXILnkUPJNeAQzITMIjbV6GAUklVr1sjtcDqXPHAl49DBQAR
-AQABiQElBBgBCgAPBQJT883wAhsMBQkHhh+AAAoJEJSyka75hKCFz30H/A4I9FC5
-kU5ipCv4iqc77egCekoG8hhm0DtVdWrKOgJwbayIRsyCB+hISnZpt69QyZi5iA2k
-rIPZx0Sq1Nrlw2lPlv87CbreDy57vdtMdFEFQHW0zRbFN+XKZ0noFQGYxG/1LyPR
-4AOg+ykBEX09gnWYHwUO6x7Q73OQs88y5JOurF6A4iQmH7na9Qz2A0YPWNKQ+tmF
-MEciypk7/YABFZrg+9Edz/TWyN81EERhJPDkxzHkYLm8fLpOhnQPOyDxuzt7fh7y
-hy/+b3B9QT4Cv1yH73DYIfJW3jtuQDdmvtTk6G7BdEzAWufGVt6EiY10pr4zyfpd
-eaSSyYoO8iMWJxQ=
-=e7Sd
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5A68A2249128E2C6
-uid    Tink Developers (Signing key for Maven artifacts) <tink-dev@google.com>
-
-sub    4E5C59DBFF7DACF9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=TnZo
------END PGP PUBLIC KEY BLOCK-----
-
-pub    8671A8DF71296252
-uid    Jesse Wilson <jesse@swank.ca>
-
-sub    51F5B36C761AA122
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=nFNX
------END PGP PUBLIC KEY BLOCK-----
-
-pub    840B2BF6DA8ED8C8
-uid    Phil Weaver (Software Engineer, Accessibility) <pweaver@google.com>
-
-sub    43115D7B115DB0C0
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFSR0DQBCADw8XL+xgFg9WVPknAIqqb0sUIZ3yNNr8LkuNtwQXnwAcSJkHSt
-C1k2CIKwRPPfcLsb51l3SpxFTs/s5yhyiknDfjqP8IFtLocBSsn3kD4VRjcxFQhc
-0jjgsTr9ZP/ZAWMBRIuxaZtpe7bpqbLbV9lvqjbOnJzASLKJoUngZAXvljGrWGfM
-3+A9z7SdrilRlA4DOZNqPoxN2RNY0QOwHh8Wv7+R97K/VQoAbvN3tQxlfn5B2scf
-WL2nWoGRS6OuO9Zp5/W1twoVdf4d85FlpNFFM1xzT8f5FpjF5QRgQD/Az2XHnObn
-ukG3ZPEhgwBIwx1Uw/Y9aOceXke9vaGEsDT1ABEBAAG0Q1BoaWwgV2VhdmVyIChT
-b2Z0d2FyZSBFbmdpbmVlciwgQWNjZXNzaWJpbGl0eSkgPHB3ZWF2ZXJAZ29vZ2xl
-LmNvbT6JATgEEwECACIFAlSR0DQCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheA
-AAoJEIQLK/bajtjI12QIANhe1ZrLQQvYFyDXGHS99LrT7WUzvxQdJ4xYYBRhmfqE
-6povjXvBAvYQabMQD3iBHie8xZ4PDngc/osp6SJF2wCT7LCFLr1ebCbulnL+rPDc
-y9Y6vQ1zD0NrBxsRYjTGq/1JqBd+Q7L0xMk8BK1xuZOCAUyq4CVRzSSxgTxJSQ+n
-Y4ZOL7PzBTYbdacMnqJc+2TwZKgi+CKIpOJusHa98mZSafzotNbmasKGRLPeJ+66
-Y/+Wfh6P/N2VL4nrnOrERW/XV9QNcI5VYlBUW6eYOhvpaiMeTMHNiN1VfDs1nnfH
-ICTdeZNhw0J7S544RXII59MBjOO3UklyZ6A20fiuvwG5AQ0EVJHQNAEIALIuFrzu
-8kQ/fFJ2FA51e+ULp+dy1ZYrZqJdTF5pMdZId711/zN9NExsTIxck6Vx9PYYaTre
-aquTkRIKnFD4XH/Q5MItEiiKHRtwdyhdFqCKSHaaNSGqldFwWZK2zh/x7OPk0ybn
-9L46E4+Eg9Ie+4WdyTxDKoeYQYl9asjtZPtfbNLad3UBvGAeyqc2hbePSxiNifNe
-cTJqzBpW0voJ85vTkuRa/Y3wBdkfyxRPRofAIjzwjyIXCLQQFSel0ok6aV8nToOp
-/j+HST4L+TVnY2vYDW1UWQP3y/suCp0jtz7/ygEyTie+6P/LEgLfp8LKri0jJqxi
-RUXA86tgDiy8x88AEQEAAYkBHwQYAQIACQUCVJHQNAIbDAAKCRCECyv22o7YyDOi
-B/9mnGjQdqXQ3NWMiqAliYnPEHYuNaP1UnRWrXpAHpRnQ2L0mWTHrAW/f7P6W4is
-l+oUKbURBEItgYY5f4/nIfp6TMrpD2ej91Q63gQw8KLL1x5CpKKLrv27w2SzE3ZG
-c9PYRuvW5rPqIXAdBYpznGKoowszWlRsgpw2XShuTEeiM2xLghmb2gSnU9l5wXFz
-VSa0PHvXoUIV6YeO1wym9bvRdvmAhf1AimvyOlpyk826vmI65l0OSbx30N67RaTi
-k2eHYk1uQ1WlnmgeRB1NfTANUMvaDbrFsbOliPJm3ncc9eGhJ74hzl8WGUy3SseS
-YYRhm4MK4YpKCJtCTWxKdYj9
-=zW35
------END PGP PUBLIC KEY BLOCK-----
-
-pub    429C8816DEA04CDB
-uid    Taro L. Saito <leo@xerial.org>
-
-sub    8A57131A07E0911E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=ihmL
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D364ABAA39A47320
-sub    3F606403DCA455C8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=5tlI
------END PGP PUBLIC KEY BLOCK-----
-
-pub    685C46769DBB5E5D
-uid    Egor Andreevici <egor@squareup.com>
-
-sub    CA7AE93399B1ED99
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFqHCi8BCACgRpCaVCiJ2MccCN01SbHYowmM255nSYKOnfItBmXYAMtc4rL9
-n1y1qFtc4LBbkIrPH8CO2zpEImUTZel4W93BQkluPOO3EX/hLCTCFfXrO89L1u4V
-XL4siS8vZl3DVDdY7m9G4vcpiIsggGF683KNctN2KXZ0D3tu9C1X7eJk3GyDo6W7
-MJwiiCm10968VqFqIFn1rTkvtGtXGP61Vqy7kLTdiBrKbo1HkZDbryl6nvCmT++E
-auJXEDYH9R+vsODy10a5in0n0EzQD4DYadL6cQTbwP2SvMbRRRQ7AnNtys6cNCCb
-CIJ8iySLaHYi65w6FEbiBM2XQ2hzf8Dek9yDABEBAAG0I0Vnb3IgQW5kcmVldmlj
-aSA8ZWdvckBzcXVhcmV1cC5jb20+iQFUBBMBCAA+FiEEaC92XupxjSULvbLxaFxG
-dp27Xl0FAlqHCi8CGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQ
-aFxGdp27Xl03AAgAgtnhNsz++UIqtiETzp0Y5v40STwdI+8KYhvbhzL2MARmnYr8
-US+NqeALovuWPNoP8CuzGN6dQP4tFMVr/4GtDJRqzi9EGUHIk6KzliK69Eir04TP
-3CgJb4OqrfgqU/tbXTPFVVKbpyWnrrzg50THhIigMxkezvTWa8iLWswBHb/E/NRn
-1NOfVkPqHY0D0Z+KeAR1/20n+aEh5JrLsxzIp3vNF+qXSN4gKtmdj2fYH9eovM85
-0NzlZnaqwetTtBxeu9mYvCHLCbTLrQTY2MvqBpZbUdVJytJrvOTAddmRrNiBz1w9
-yxzGOKXDSB0t6LVWldwAuTM0eGXqaDgInbe7r7kBDQRahwovAQgAzYHtmnHEZVad
-1Th2c8oFr3/QaH7UP7Xz+lhKyYgq/FsKmkQy88qxcxTX4kMfSB8ssKFdaCtBQI6y
-pFVvaUm8jn1LC0dVPZJHKHOdDEiLdg7B20bPzdY0x5+Yav7SJjYIq53V3pkJGZyH
-P9CvZ/L5uJ5+2sFx1nj1qyK1FWVx2VZk2TsFmL4fpiAi6SOXRoGVLlO0sCqUvlH2
-eR873/1u5Ya387En4krWnu0T+dHyg5/xu9S2Q7XKmO7GyEUXRnXsJPur6CwXpUao
-eoXIcydpdjl+TR70OgxyAGsrfQYVNjPvRVK4yUv839Xz8mCIp21CRscsx1IIeshM
-BqRGXIo8BQARAQABiQE8BBgBCAAmFiEEaC92XupxjSULvbLxaFxGdp27Xl0FAlqH
-Ci8CGwwFCQPCZwAACgkQaFxGdp27Xl2rCAf9EwynJ3Pb70PcSVboGozFCnSayE+c
-/SboSK2Cujfw1Fy2Qr0YizXL4RAE4jXzI+Y3EYZpcJ7XMxUheBTZrxO8ACvMrAwm
-MC2vf1EoM3DQVpyoVCv5d1OIY6rYCjyHeBT4rwsl8GLZZ9vsjGWpI9m8Jcpi3jhM
-ih+zfrdaYJpFzu5MA2y/dV3aYn0kpODuN+WVWRyF/3jhLCZtrNFnZb3pfrS/jcDM
-+kdiyqH9wE6iyvIxX8Rk7a+1H0zFmKQNetxdMQPYODUSXQEuygXaZFzm+bfWU+E9
-x+HCpeZqmOpBQgdhFZFEX+ru97s07kBMVUlWM4s4uETNKLIwzkAk2FlbGw==
-=S5Ep
------END PGP PUBLIC KEY BLOCK-----
-
-pub    AE5A7FB608A0221C
-uid    Robert Scholte <rfscholte@apache.org>
-
-sub    38185785755267BD
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-GRaLJzret1R51ugVfZjKo498Hp7vRZU=
-=l0nB
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3C0A8F4744F37328
-sub    D17266C6E05F9993
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFSQ6LEBCADnoAfQsg2uDYMnEPqt7tlnZxzyLVKiHXdJzT6OHA0FUdsB9H/9
-vWI863v20dsk4+tf1pXLa1AWBusInf7FM1JBCQBc/By3fR3JRhJU0QSoEcwtOQSa
-MmktLQx6s5V3hee6pJDJicY3fESWqrVygiUeyuRJupbBOOh3V4GkKnk1s48ZBesl
-viHzOjz8ysZKbn3h7mDuR4NaMx54U9x008NKs4Ry4ztAXbf2FqkmhkU1aE+1v1vz
-/mShXXuwGjYuv4OnQyP6ONHJPOclc4mDFU3yuUg328AUCbWHPg1kAMbpZLiEnBgN
-anC0K9BxYfVdQV55XSMMrdPfC4dNAwMEuzkRABEBAAG5AQ0EVJDosQEIAN9tyXFa
-CMYODFVn/vTf/9+Am9AoNvTtvoulLoC3VsamyIel3QI7ek9rppLi6G/lww9q1EYy
-3F0dR4ciqN8meMnGCbl0KhXCn2IJLp3MabaG4BmMbdskAGoqd2P3lynhbOnjQMBV
-RMcXFWqHPMfpAB4/5RM3wsgOn3vn/eDNBWPbGiHk297EUxGhooVmyb+1mbVXuNDE
-8S9KsiLus3Yq0vytlUI6DoPZoTMaO4GGJG4aOUw0abK6zPfPylzDaFXoryTaRhhJ
-lb4HONVT3GNFOT2Ob+ntgFx0I0cPfKKHDqJhcZl/CAWUMNyQb5/+u7uybyBGHzJw
-fydRH28FC9+m/xEAEQEAAYkBHwQYAQIACQUCVJDosQIbDAAKCRA8Co9HRPNzKJQj
-CACofWbBHPEPNj5mqVtJf/HuViQYib4PlIZKvcKsl2TVXkDdARzW38MV18ZDKUm7
-XECp1BPST0pwKvf1auq1/25X1BOtNC9FIFs8649K4U6RouDbXPo4hyzB0Og+608b
-KC8MN311Cqth+MuWy7rHjBZytNR8CW6e1XQBxJjW/G+1SYRM57g56S9IoPiTMDsW
-8jMQaYyNY7/Getddzfl4EZmjiiOysN3FQrrwF1tUGczLaDiaTO+db/FEGJpzBVmW
-WkxFGLuAjlkSPvBW+ijlTMnWwTnd3Ps/iBHWXLb2StrDV2vmhVln2gw3uR1qML90
-iwdK19eTAhhc+QJ28/SKBcyA
-=F4/Q
------END PGP PUBLIC KEY BLOCK-----
-
-pub    C51E6CBC7FF46F0B
-sub    4006CBA6D352F1FC
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFbgSbABCADGGENSy3oWLjW7zfYMSsR0pm3l3eMA7ptyU5C0U/MoIYjbXwyX
-XtlGwKnNgngATh1SMpX4WDbD8tn6vdeP4uHQsDb40t0XN7/HISFcLhV5pCgz2wNR
-t1dZbreV/EaZn3f84Vnm9s6TU7RHuPP9qBne1YLbB+LKKZUfQGavqGR+n322DhrR
-NqLdC3zFNtSmCVXS6GZ17IV/B+6CiNdbmPVk0o7zZexqZCNMXxv1IFzHV1/Y8Htu
-WQBfZ0zWwrX85ZKysU7UDdoyUw2aa8/+YpZmKwo32N8GpqA6azBeUjjVXGuqktMy
-l6IcHbLlgymkkjK7TyAKltuhvp6AlBTzp9i/ABEBAAG5AQ0EVuBJsAEIALE90/PK
-unEOu2B+QGGV9e0jJMlW+rs3BV6NI9ZaRw0Uvy0xN+jqhMsyCzB8P1joTZKUsmK9
-ptaPlMuKrTaQ/0GYPi6cP5EamphyvjK8ljLhhQuiAxt7zwv78vX7CGqRUEcAszsK
-8FPBAXERsSit661rjp4Ai71cyQg8YOXDjhissHWmneF8TJ3yItocj4KxDKLxoY+h
-F64epbkjIkpfrZ34iX8zdZMRCNJlh+oTHe/xulYLQDbgkgQa+Y6gnKmUZi0QGU01
-k6eWw/U3yOC69++ehiYcZYS0dWpPE/H51Rizn7QipFeFfTsia9jkGjzMyKHGju66
-URQ8okd4E6ev3N8AEQEAAYkBHwQYAQIACQUCVuBJsAIbDAAKCRDFHmy8f/RvC1c0
-CACy49b4H6ZzY71Ao9JHRRpQZ2VSVk+6xPblr1DOoytDC/zhVKekerE7OBEul0UO
-qzUyLNwkDiHy+5PRi6ZquZr85PlaVV5j6DkuZ/0lcL3ofsvtQi1Dwd1q/9RzedSU
-jjY3OimPWDkDBIGyBXohxx1BxRIAvlRnk9agapfbAdwtv6cjYxW0TDcPx4XW839n
-MN3CMEWtlI1GhKGYi5nsUw73ctpSq9dm3ov85ykFOqB/juvTcPoiOwPE+6o0OCTZ
-o60VwPUfv7uoXtkrLVJ0B06mfKiUgZvaqppYDi9IrhcHarOz8MD2OrUS3z4riTsL
-VEPwY+Xd06QyemMynHqpcDpm
-=1WLL
------END PGP PUBLIC KEY BLOCK-----
-
-pub    56028DF552BA32E2
-sub    7EC19439E4D4C2A0
-sub    D89D05374952262B
-sub    B5681E477AD61C38
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-5KzrCgVUcXxeOohqkl0SRuYxdQ==
-=UvWw
------END PGP PUBLIC KEY BLOCK-----
-
-pub    7A01B0F236E5430F
-uid    Inderjeet Singh <inder@alumni.stanford.edu>
-
-sub    C3E640F38D845FA2
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFZUsiQBCADGmoidvh3VvXWGdwbAtHPtDPKEebE/MfFVO+QTRbjJxphzKwAt
-mxHruikafaSTnC9FWizj99e/Yc45YZHcnt5Htmy0a7DSOQXL37rrnieZxg86tYmC
-4PxvvzC/s7xF8wmxDo4A+mRyoSF0NF/fQTZAr3ri5l0G/vntH7w8AbiiyerpLobW
-/TqQn1tpMh7XfZZ+XqQKANVRECUiCYT4iJKWMqcBpLZW8aa+iYW8yCQ1xfmNXjrx
-jpTqFCiQjvwCw4dDffNe/A1Dbq0wE6mw3YHW3OC1fnLiP+TEM9P9v02bZyem6uW2
-+krrToLTTHSqIGF9wUUF6S3Ikrw2EtJiRQtnABEBAAG0K0luZGVyamVldCBTaW5n
-aCA8aW5kZXJAYWx1bW5pLnN0YW5mb3JkLmVkdT6JATgEEwECACIFAlZUsiQCGwMG
-CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEHoBsPI25UMP6r8H/Rq70+JN+EyS
-6iK6ilytB1vY5GdwBzAxpsRUhTL1lXSqgjCXy/6sgrTQv/9/EgQznm7hEFVkwr5Z
-CacXeajvFJ3FVtjgn0aLRADp88Ry75DsttjwV5nIBNvFBJbydvJhfruHY8gzdUv9
-yOHAX4qtoNDFRn1HDbNsYMlRSXgjHX0JvBexdtZArtsd3aLOM4m8r+t1GFM6ePgj
-CD1q8yBH2RAIETAId/jiu07AqsJXp+UPBgJQi8o7cEtEE1HgkI+IoEsZXFJldRqF
-GJS6eKS8bpjX16nHI0SnR/gtsWpblAdZsY0YieK7o2pU8lvlCFffaUxXDOP7+BCq
-8W29nfaD6YS5AQ0EVlSyJAEIAL0+8UoJuUsC3jDE60tmrApu/hK+dCbe5UJnR8z9
-3aQ/1AfEX6So6JZzBlxID/HCOvRjJbauL6Lrvw2xgSnrnOzRLf1StvBPASfJk1Zd
-o9LZon6Xofzg34qCLUQLkDyntgXQaYF3Yw/xfiqqTC/yav29VTzKnf0Nri8aXGsH
-OycJ8nTO7I0p4xuRirFu7Bkvd7bK99/tDxttYkvUnG3BUGlr85UX4uODh3EcVcgV
-QteawYbmsf4F00IBoTAycutCOdbP2RAgP6kgFxLcGz4zVqu93QjSjEdTegF1SUXc
-GpzvDR8T8zRsQbBCZ32A/UJqmx+EIPPFHNkLijDp+f5mkJcAEQEAAYkBHwQYAQIA
-CQUCVlSyJAIbDAAKCRB6AbDyNuVDD2xjCACqL670xI/26dWsz66ZyHQ2yJI7DNQx
-oiU3OZs2bfrRZxLpGP9Q6YWCehb+iucvmFFvLZBoGGWzffmVBisD2Yz3mHtF3wLx
-+2zJXHt1Xz7H6W89M54T3qUhQTTV6pl5f5/JCXK1DP9iC0y453ORY5B60byrGIUv
-BAv+qWXBPn3ECZ/3oEkErb5ZGof+gJjffqvWRAN3Li0WBRj0ldXpJoP/YE8naDJ7
-UdPfzcnh3tnOTfUDvFer1Nh00ilMmf6EYznRwaN9whc9W/1HwvDeXrijrc6/1U7H
-p1r5b1DddTtx6aHxpWrcwYw1yXGcm82fjXnRdomz6nBt2DF400YubAZR
-=2qwf
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6B1B008864323B92
-uid    Terence Parr (ANTLR Project Lead) <parrt@antlr.org>
-
-sub    FA6831EE37606774
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFTDM4oBCAC9cUMAjkP1dD7tt0JUI5kVORKagn4/zG6+Y2MUwGgJs481xsFC
-jXPuNZMucAVtXmw5Sl7FbsfSxR/9jJ2pnbXL918eRFbUqY4LnuOTZjcgNWo8PWPc
-0NLmqoLj3HXaLrpB5cRIXaQvzmfoWxt8o/ZWq1zSfDJDePuQb6qlWmnoDz/S2YJb
-f2AILPsljTE8kYIBHORGilKtUXtQRjs0SCqnbx+DSDAVKSnqYHWDMmxgBMMQsSE/
-RQ/EZ7I4eGRLLfONCxox0fuIt4kOLuMNqGWQlqiG2Kp6Uulx5SepToSrPZLyDGVA
-MgefKrKe/lzKiLeppmx7ELXOKBXlIvTFZBuzABEBAAG0M1RlcmVuY2UgUGFyciAo
-QU5UTFIgUHJvamVjdCBMZWFkKSA8cGFycnRAYW50bHIub3JnPokBOAQTAQIAIgUC
-VMMzigIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQaxsAiGQyO5IHQwf/
-VuVSUFdUJToUScygLSxS1zp6dTEUXc/BfNXD0+7TVRXtzNKNUUwLYRlPRX5aHkUV
-d3+g3QiD6DQIVlSH0INCOto7/EP0ENLbC0Tm6QGhhDg2zO+A1OLRLwXFAVun/4Wm
-1eV3lakXRBCE/Fji0QxDWTYXakShmzIyTZCfJB8jtxG6EYyKNSrOMM2HBjJY63y+
-sQWOYJRz7Y2pv3kpwzPPQ8yxRSsDkJSKU9FyzBZfl1F1UnNkzK3BwL+CyKOAh0Zu
-2u11SJ3gUF0O65Y6FeBW7FVyPYr2IlMsYokr6Ry1pmndehQzQB3paEGUiMO4KWN9
-1OZUfcG0LBZB/FFBmVTVYLkBDQRUwzOKAQgAy86UOqIrhAeN34v5QKv2ZGWWNc6r
-Wi7ieC+dnx2D4kmvn+BLaCX7hJCyNL1ex2TvZlhXt8cgA8jAVgN5+aHTaJwpcTHU
-pzx2p5UIe9oBAEq20NyjF3P9o7lt1C5V1b71EKMTwTOSfWUcK0Skz4G/+gkhNjSV
-fxYwZO1v+Ce4mRCCRi6x8pFGHdyukVR0wJ/o8yKvQijUciGMEbnpDC76N1eAQgd0
-wo79WWGZty+w/qQSknXwTTJ028LlumuVV8UlYxZ/eYYSrtK2t2w+6UG16TqHATDF
-lEyShzYJCer2H1fmSGWncZZ4ODQCkNzNWirPn+q/Rr8CBo7PlMUV06OKZQARAQAB
-iQEfBBgBAgAJBQJUwzOKAhsMAAoJEGsbAIhkMjuSZOMH/2V3TM9qXvwiGsmO2msb
-Ita9b2MbvdlIj7EfI9rt2azPjYTLiQcYWWntKN6tYmB61kK3qzARwcW8pJQ0FiOo
-XEG8jqwHUz3bIxF8ftbq3peLUJi03PDQoNlTpKRuj5EvV7M1f1uZGaKU5W8+BVVx
-Oq8exMeyDU+8PifHmW9S1iFPqq0gPqjljlzzcIZH/JM7pq59uoj3YuNz2X3PreQP
-XVaz607JXUhxJ4MIEqEy/qjD5OGZRKQr44eSxk7938j80OcBa/1IbbjvGs5oi2IY
-gEzpV3KGDU+kSDHVuKcwloU5qMC1Vvhrkildb23wtFBRYIpgke6HBcaQOIivCatS
-bBI=
-=yW86
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3FAAD2CD5ECBB314
-sub    3260CB2DEF74135B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-xZG1NzW9unRL1j8/o6QtwZ1S
-=cP6l
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5F7786DF73E61F56
-uid    Ting-Yuan Huang <laszio@google.com>
-
-sub    73F7734B17EC71F4
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=v4+t
------END PGP PUBLIC KEY BLOCK-----
-
-pub    476634A4694E716A
-uid    Simon Mittermueller (none) <simon.mittermueller@gmail.com>
-
-sub    4CE6E05D128BCFAD
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFE0soEBCADAy/iIRT/lpb+vfDjWs/k1XQNU3mzXoMm1mmS/Z8VOc0jF7sVB
-A5z2pC6u2OmEr1oJkhWefX+mU//7kXs6VvUCReE4uheGBlisg/ELEXkTm342TcwS
-K+tR/NMk5h1DwxeGR2qc0+zhFcrITiYqCpdaggRVx92syhuYWrG2DtRI3eEz+fys
-2WLhAd/AqBTR0ENDZssp5S6tEBcLvU/jAvKv33/+ydg+1Bsw37CqCOO0bR388+ow
-uSXSARDJaesnBpUcXT9pbog3Wm9pSzJ2fX1FyFaf3rqIIYEqGk1rEND+AkT2CB08
-BykABpDx0mgR6/pAgQVywCatPuc7wneiZY+LABEBAAG0OlNpbW9uIE1pdHRlcm11
-ZWxsZXIgKG5vbmUpIDxzaW1vbi5taXR0ZXJtdWVsbGVyQGdtYWlsLmNvbT6JATgE
-EwECACIFAlE0soECGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEEdmNKRp
-TnFqfr8H/1DXbZ4VzAqqIBhMUWOIvF220gZ6NAxgIP4IAzfuLYKso1pfogbuPzS4
-IzbTZIZv0TXsK7zEzxZY4Oxx5cQaOfRiPOBvkeEC1T8Pf8l9GDQ8ppy0aHPNLgV+
-nloylBUHWuKpTMUHKu3MpwHfwMFZ9ZFsUmgcQ9oYkWcvprH2uOachsuA4BSxXJNe
-OGU3aBIG1CR7lGENmkjwZowXhxM7QuYZ7qIR6oFxQCOj9jcV61AQhj5LuKNOJLfx
-fAICIeUD8mJP3NcblVNp/Nj656naiLWBsK1sfjGzvLkeTKnFYFMpJqEuLTv7VTx1
-fGJnaq2+2UznsLGgWcMVPg68ZOW5V6i5AQ0EUTSygQEIANTGYOD4HupAmugS69tx
-MTAW4GvRQ0s8Li/r/QQQUWPpjo3IkJDA0+kPCe2JRamNJJ2plzndeGUpQIZn+HJS
-N8fGRjZG56HG6l0BJmQRFHD/6CzNOOKK6z+8e306DAwQPqDdDpUgpBmbPHZDhCs7
-tvrOhrUesfLQla15MM7n1DEtII9y+AsMGfwrZCd2PeigiRC+/NH/lYObLUPc+NL6
-GrC1ZHrpGoOR+9GQ6voVNY5EIxVlNgoVBxn3ufcFvvghmZe0WyudBHK9ByWeioBI
-tHQW5n7eGpljcCUbTpsJmErhjH6KBKSuxPQsyV4TkQMqcsymGW0jhdHXc1/tStF3
-L0kAEQEAAYkBHwQYAQIACQUCUTSygQIbDAAKCRBHZjSkaU5xamOiB/9r943gZZy9
-FJv/NGPnNxCvI3ZusQfntgRfVyIFZLIUeaYDab6RqKTD8ZRgyfO2rmO73DiQ2bnt
-zmSPHeAlpKAIhTXfty0g5UICLjr27KocLNt234BKii6go+CDo2+lLUPUAe3cJPFq
-ZrtJ3pYLFwS7O43wwhRaO9A7L1uyruoCqql65B6CJcymMEsDnCizRVEAsE2lxenu
-fxcM8JIaQlczXTsHYf23vnmLjlXm5HvEAfXE0s7iHo9BMlSLxHWWEqeyrbwMdnn/
-gT8lHGw+SHO173THvhtGuKGkrglD2CA9G5d1ZWgAz3il0fLdBenLH6t1m0x3+P6h
-4sUJ04LlldPb
-=GdCO
------END PGP PUBLIC KEY BLOCK-----
-
-pub    DDDAFA7674E54418
-uid    Cedric Beust <cedric@beust.com>
-
-sub    50C6CC55C6F24FB1
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF8tnmMBCADROe7j1ZvgiMgfsQKqCSuSqgMkfMT2DEXwZKdHqkj0gfx8MPQg
-OP1pmMgpIwIXKr5kZ9KMGiGULNnS+WU2SNqjyKeq3MlnSYW5Di52MoAD7W4cHmry
-8ekaasF/x0AS5Q3M/6X/EBOD8YLWaFkk+h5x8D4IOSqiOiWH8olGjY4ZmGblaldX
-PLr7BWSrPKQ1QDsoICn583Mnjz3YLlc4p5IKnY2wss1zm7/gQk6KkdL5bRuASxLh
-to2adZ1LEE8MQfHweauHCK915RmMg7W3KW66/EsuCyEwZKBwq6rIpAciym2FngJt
-CPnY0o4IMFSasV7d1xSH5N4jeHL3Hh2Yd9tHABEBAAG0H0NlZHJpYyBCZXVzdCA8
-Y2VkcmljQGJldXN0LmNvbT6JAU4EEwEIADgWIQR81StagpUTfIj7V0jd2vp2dOVE
-GAUCXy2eYwIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDd2vp2dOVEGLQr
-CACZTTneMoaUR4pQHa/rQfGnYcYznSL32JUP98bgstwN+g5BoivHkrN/5IinELly
-n2nxrjrPucN2arjOvObiGk7UhvUY8h1kqWKWqc5Gsc/iXwnrIx9bwzwdbYaiKqMT
-E6RJ+naIN80rNRQnOMtBRTNmRWYZ9UMk2W1DEKZeCaKUJpO2lLpMW6R+Sta/pkq9
-L36F5G9qWBrVhUS4U/rEE27G7xiDZ7fCnjYt6lfvc6mKQ72BIUGtjVDRwBAiG98X
-Zn5+TqLaMkC8NotYInuV1/CwvfE9SuYH8dn3YJqAkkn57L74y8I0V54AyMXaLNp5
-G62uRD43Xw6rLakCxGNUafcouQENBF8tnmMBCADWQEHet457l0v27b6EVxjNZMGl
-NI939o3k4NdrCBglIojODXA9jp8VkisL7+klrpOP1vmoVd80Lk0fGSOdZDcIMbzW
-WChRMVMkY0vgeDqOgKw0j6e+isqN/vNipj2nh8cYm4q+LB6GVE0pfFCsrM8RFFew
-RO+esEuw0R1qXhNYLIwpRV3Ov4ZxDp1yM7KAHSBc86HJHy1t4LqLofjA+RBP8f/6
-2MmSRKLbDwruLz/02p0fR+lp2DiJ/IN40lGq1fSxRjXMTQnI+bIdsd7TlY0AbT6R
-NklBL3i492hxU188dva1PZM0sxAMZRXSt6cFCvz/jDvlf6jB6DmN18E2ad55ABEB
-AAGJATYEGAEIACAWIQR81StagpUTfIj7V0jd2vp2dOVEGAUCXy2eYwIbDAAKCRDd
-2vp2dOVEGAwbB/sFvYn1o5Q0r+ngdMJLCjQYT8a6uy8SH8N3k8RsTJ+ad0TdfOoG
-wvxl/SFB1MEjEVpXgbojjv01gVDola2ObIYSX+GWcvlJdfXKz8oZ5f8/KdRrAc3h
-z7gf8huUVeriwHoEEA7xi14kJZpwCPh8PiMMl5KQFWuG4D1eQnwOm54cIw/9hYB3
-R7oVI+2THlm3CAlFalsXzZ1N/l/JQG6LfPkKmrubr++FveXx6izjZssdFiaLg4dk
-AQdAwgpmFmCQHb63BCKzqPwDxpazpk1wP6Y5ornLu/ISaOo9VC9ylX+vUK93eq4K
-AFuUjn/Jk55tpdUEH8mW12W6Ukjt9FxVb8ZX
-=Vb7/
------END PGP PUBLIC KEY BLOCK-----
-
-pub    64A16FAAEC16A4BE
-uid    Evan Ward <evanward@apache.org>
-
-sub    1E8F1D57A4450BCB
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFbqsT0BCADwERe1Rc9qNWwXOvwZHsjauVDy0TpqNVY8I3S+OYm4rX1dkjyh
-+6bTEH1ys6bKevvR+PLhYzTGKboHnMT0RIINY/DQQSzHr/GRyCiiRlRvULbt9Fnz
-kJJDgH2BcbNSmWJlrCqYk+E3GAyQial+szkEZED+02wXHsbs0z3vozjQGHy0RVOj
-Gc5Shwk7Hr/F3vw9EQKa1nNffWmcGEx9B+WcC9ALPVd/fpQVXvlqfbi+kaIbqv2x
-NHQr7BL8j3SpN6vhfZM/3zeghlxQ5HYWER983XwkmvbNdMxt5HWsMKWZ0utt4ocK
-TnQP8NFGlPWEQhPvRRFNb9BI0wvGD0NUb1gjABEBAAG0H0V2YW4gV2FyZCA8ZXZh
-bndhcmRAYXBhY2hlLm9yZz6JATkEEwECACMFAlbqsT0CGwMHCwkIBwMCAQYVCAIJ
-CgsEFgIDAQIeAQIXgAAKCRBkoW+q7BakvnygB/41oiYgfDqkG5srQ4nC7jE0Pe5V
-MnuLVHqsfJBGPvt2tz5+Z1ciIFFwUi/xsafX5DhC+FVOOGdeEnkKnskPBOI7uMFh
-v/s90lbhNV62LfwcS9hptE4qn0JTg7mYiiL0Zue99mlkeP105+GlMmvH5q54X2Le
-hIDBVR8DehL8ZqZCvNEVK1ftpx45mvF/4yh0YK0oVuCAAzwF9+6OxeWTCUTRHTZC
-4CWjtXKUHMq4nTRSp0wGdqd5UV0VbMn0bKTkhgRNCJAKyFw6lJ0FZWwmuG28T0s+
-bKuRAJHTAZmSM7UmBnKo22t9whNcozcqxWhK1lcS4OWEArXpCKxAx4kXmbwnuQEN
-BFbqsT0BCADj5dHK9K27rmkFscDY6x53w4L/X6AYKmVu7Qol7VhR+1WtZXgxZaLM
-xDxj5RK4sNOIqh6R3vEMlAVS+iYbzahI/A0fcSciCoLCgjJKCR3STnTu2k0D/MO0
-la+wF/bGPa0UADGIJLRCjalkl5uv4c7zZbyLnRl8a9XSc81cp2WJTxafZJlJkFOU
-4cyewwFuH0pwMvc9Wmwhkh5IeBF6w8Asj77M5bzJINXYxtKMGYA506609HrvN0+r
-obfgx4Aqy4hGKsqXMsSZiuPDvbdtH3gIRV8NPdYRq+dQg/gv222Y3G1xprDVbl1A
-1CCHlaUqT2lIFPovjoB2O2SBeX9xKRJzABEBAAGJAR8EGAECAAkFAlbqsT0CGwwA
-CgkQZKFvquwWpL4yawf/WDI4VqLkR9RqaX3am/kS8481pZPWZUlCCL7jONB7X7eG
-Bit/FjmQWzfL5nWAEB5qhm2qqCgvgtPmVxCrQLECVmaGmDFmhGIFh8TQsYvQJPK6
-HZDxZj97lUKsG/ojOY4ZArvZnsXBU6C963QUZF+P5UL52n1pE/ByMV1R3enEfrYI
-X+wZslOx5uRFOR8dgUpG/ohh2vkFCaKD6KJQHm6C5lGBgUNqGMFxp1nknKJaNqYq
-jvippm6KcocWARfTHx6Xm3mBqxigmpsalUKAGpjcsxsIEY6jnnN/5i5y1XeokTY8
-6fqEt2OSFSkWiApqq6lxMRluTiq33bSquTxSomKfQQ==
-=PImz
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A7F5ED0FA05D64B7
-uid    Kengo TODA <skypencil+github@gmail.com>
-
-sub    4044EDF1BB73EFEA
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-3ug=
-=QgEH
------END PGP PUBLIC KEY BLOCK-----
-
-pub    47586A1B75EF0DE5
-uid    Benoit Quenaudon <oldering@gmail.com>
-
-sub    D74B959DFA1D84F2
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFkW7RoBCAC7NMtr/e27nrUuIcEZEJBZS3TbZYId80UNQXgYmqPhy/sfCyMc
-87eKzOalauwLbr5+VGuKqhvKrihV1WCt2+FUjOtnCf1GutpAUH9plfSs8IpRog0h
-i9IpApPeR0Q37fHhc/fSLDxoHIylML0058K2X9js/VNg9xospjvRBi0vXmNaMWuo
-qMQXXVJrDDtDlxljx78Fk7b/qiFuqBgIPM3U5OPyaQ9Qks8wactSYo9pcqIZx9BF
-/XR//WvPwQ5MEAPCkwXnNIlrePDGMule7QRRmDvNkcD8V2xSOM+fhVd3UpuCpMEG
-h3MpiaFq9TF9O1Fv22Cs4eM3mnYOEHjAGyNzABEBAAG0JUJlbm9pdCBRdWVuYXVk
-b24gPG9sZGVyaW5nQGdtYWlsLmNvbT6JATcEEwEKACEFAlkW7RoCGwMFCwkIBwMF
-FQoJCAsFFgIDAQACHgECF4AACgkQR1hqG3XvDeU8FAf+KJqG/lNX1xzASjIYxXPj
-W++DVsvysQaSAr5OebRsD/KLeEM68ps65AfpMgxIAs094NEhA99wIXclf4vjZJ3W
-5z2VS2+IwhnDNYD9Pe0xt3H8zfbL3no0LyPS+pAsavtgJ0gqRG/kNDDoM/RmI2S4
-yZgaku6kQ4hCKKubdrPBV+LqCSBvEn6kTvHMvIYQrtDgvm/X9hTR/42zaAK9UaD1
-RiLF2k2nbQeJlDu8ZSvuA3IOGTb6ALUA66KkmiDqMG43vZs+ZTAKnreWKsPKlQr0
-eAAN/dcFVg35+bjf02561Zi73NcgMS7M6VgBExBoGYDW4299vnu8K3FqOHDQs3f4
-8rkBDQRZFu0aAQgA1+Ve/M0qe9PJ3RECh7T23GIGQSQ2qz877YKt0ZszRRqO3zyn
-+odZTlDV7dNfWuC4vZfzY7tMs+4VpYiiFBGnEmZkgCc0upK5IuHrS9HwuD3VcOw6
-e9SpmOgYkJYKmjtNCNz7BIoYCIu+PYzaueP12DXCIod7bij8+smRaon0IkDj4SqH
-ALxnb75+L9MQKaxTfkOybDWLfhz9oxfUtO2StLHlGVk8Q6GVAhKJIp6bZGDA/S3m
-Hx/AZHnVsL8o98oYRIuwLFPxeAYauY6cgwoD/9FYpkQSlxbsLsje8HRT1nvzWKhP
-4NwZFDkmEWsKOiIYgV9lQWompcLpqLFfmp0pPwARAQABiQEfBBgBCgAJBQJZFu0a
-AhsMAAoJEEdYaht17w3l3ZoH/RYBt2aiAhrbjQteyA5CpNZ6V8jRrudzEHB/boJH
-FnBUGNhzDDeu9FoJGrR8r4AvLyJgqiiATN3/erKEiZI/cP8wBfzjoMBM9MiYLgRg
-NawvoLd03oEUq856SbCwW096GE6m/eLcT3735+aIchMAHSagHP9cIuWr+t3+W0z5
-MURVOe71bf2TSySXhbdp4E05XjRgAwdQciW0n8SCKgRppO/CuIWiUyvt5JCCrfxY
-gEOMg5/wEGRSuNS7YtYB92CBgLPQ7SmpNSMUY3Hvvg+AblS7sxPDDvvY7whHK2U4
-6LJQx7BqPFqTmGPfFbSt2843qryNpjbAIzMpm0WC40LvvLU=
-=5a7q
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1188B69F6D6259CA
-uid    Chris Banes <chris@banes.me>
-
-sub    0888B86856F9D71A
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF2hcBkBCAC2H5WcFoeByKBUAjRDjmP+5P6FRsZjLe6c1wy7G1ha6/EQUVK4
-gZUZYE9W7l/4QKHvAu4PvFWdD+5FXGZuB/2kw348CtabAlJTehm1QlPt5//ODkxB
-fWPPz3uHBo5PQJZuLpStQn+aEkTTHK6Sk5033e6fa7mV5X/c8pTmTzkunG58NFbj
-5VSVbks4pbafKoMY7rSN0/I2hEApCjB9tx/7DJuQ9gbaGhmabnhBTnwHXEV1/hIF
-369lfiqeoeqDMOKj99C6KFD/NPRrRLfoPRpqL3LPsPp7P+TzyZN2q89Xqn2ysyI9
-jDtrlssEXLskU5kA8fVa179V/QR6QtrJ29m/ABEBAAG0HENocmlzIEJhbmVzIDxj
-aHJpc0BiYW5lcy5tZT6JAVQEEwEIAD4WIQRkubCfFkqgv4h0LrYRiLafbWJZygUC
-XaFwGQIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRARiLafbWJZ
-ygNIB/wPXRnQJ5Pj+G/S0sbcDjTFegfN5TzXRRu0wXyogHPCt5ItE+8DURp7coq1
-eaocMZQ1186QLow/gInpji5l2pyv8BjC+H0GrXrT00S4wWcmd4ink+cNIwCtO8Dk
-Bi25t9RxA12zKqXn62W8sATRl4DlL17ASw8k1bYDGWWJAM8GJG2yucaFN7RohO7q
-5QmcjsXmuzfZtcKrlVBVNkYoGQKfjgr5fPjG1p5aOKELYt33u16stDGOuvXyJL2h
-4FhqMJL9UvFj7uOdMQLK10QPb3tFXELchvBWCkD/GVHtH1hwFumLkLbIKaj43Sq8
-Kap/NfRkl5GXw5e8UQDQevfTXdJduQENBF2hcBkBCAC2kr/FJuCwW8jzPDyH3EsJ
-ebKgUGpdZ8O+OtbvIBgIt7opJ+tkOyBjt0kUbiXEeoZGOQ8qtaj8BD5nAYytDZcd
-TU7ZOE8A02bMXsTVeNKkPgbmYQm9DZokAUQWO6NxohWvJqnDXkzZyMb6jGCJyGHL
-x6bN6++0DWPD2c53wzaSZLg/776BZw453HWkHfiomtoKgBR0DMOg51daAsj8d/Aq
-itdK8Nwz7cmKP7FaOu5lSyWb6F8dueQ2yjQEykq4YrgiLCva/pSL2Pc16CNnCRbD
-QNUEog5Ldco1tbrPPfizLeXVQmp6tG34aa1OCd2WKs1EtbFQHpFWNo0cP7LInV/r
-ABEBAAGJATwEGAEIACYWIQRkubCfFkqgv4h0LrYRiLafbWJZygUCXaFwGQIbDAUJ
-A8JnAAAKCRARiLafbWJZyoPeB/9hrGRr1ivPnQOMtAJgrT+Aev1gFKJxgTJlB9QM
-fBmjyiELgnjwW0COb9nRgalDk404f6nKcH0x0jElhUU79h2Qz/NoGP7QByaymdeP
-j69SQeDb3TyI+tHShX8r3gt7fEyeJFYyr7w8xmO6B7GdTpltTcrbG3uk2o+e1GPL
-+u86S0QhG2RyBKOIWLXoRCJQlouzNqiZl7Viv8FN28NAvCi+Crp/evPtNNOYjnUP
-yIoOKCOCv1Fth5H0DNQMLsCZbHPLl1Lx+AN5JFR0xp774uGkzLQ1jyqXTbv3rn1s
-LjK0uhsXbr+8I7TfsExnrL9DmAn8R0nE4uPV2wW1NzwavqcU
-=yIZi
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A7764F502A938C99
-sub    F20DB7FEF61CE1E8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFc7oMQBCADaIPEUzMrwF9gnEC+PRn2cSPG8OV4RxXxa88TZm0L7NF7D+F5N
-MNUAZ58oVqFUW+ytgb5iey3X7KjlJXZnuqES4m2Id4N7FlnvrmpeOg7MUc9VmNkt
-E7RH0O5GAo3V3o/Xp5nATUoaQ7v1WaPloB78ucyWLnH/iANw8YuxYuYUTJ0f2b15
-1oY1feqkpibbbO39kdMY36FH5h8Gsv0vvGdeS2O1p9vbzDHXEMLkNyKfcILLjbNU
-O/n2FzDL1y7hHXcFKDl6z2G7rKJCAsASH+r51YX3dOKUepE3pFcUbMAXGeG//n4B
-T8cv9YOhsYGaXBdbOMjy1WsZMvizbp0p6yIhABEBAAG5AQ0EVzugxAEIAMxtJLP4
-EGHrf/bnRuJHkyMqd/LEIMR4KszUl1AU5oeCxah7ZsK2MjwAUDD2UeLAIyANmKq+
-vXtma2wvQeOzo0QDMnxLqADSQ4xqUUcgbn71rjMq2O/T06BI9Lr2BaXeuYYjifA+
-loWzCbOHcgz78p8RRmxlChO5mWWlnrznDbUjV4Pih8M1LR/a2bUiU/Ftg14GPSrh
-ct9D3b5CjMIa4tqWMpvI+6jOjJm/ZD3Ux7WbzlHB+B9/yTw7n3pLSMXj/07PJKrp
-tUeJONprdN7V3wg1fnVS8CuQmLKoJhU1kLnucgnCFQMaHThhjxdaBMr6Mlq3urT2
-BSw970AB1qV4Wg8AEQEAAYkBHwQYAQIACQUCVzugxAIbDAAKCRCndk9QKpOMmUjO
-B/9ByOS3hX9yJysA/IDbFWonYmlo7p2hQbR1tiQ03QpbXZXCPxkSknW2uHqFLxd5
-eFkR46ExXINqFzMO6V7+o+soj7jUOK2rxQUIvdf423rhjdOU+TGXSDVKfNhBc/P+
-z0xQX7TkOuNwrcztgsmoSI/5K0rbF6+Yx3Thz29ZNFPTTkdFGiq6GfDOwBOp0VOv
-NyHw7mO4x4/5gdPKJ7zsMTT1OgBY+UQ9msb/ae47HvAEIgFg65OAamU+cWe471PQ
-uo8MEmeRKCsJuZlYjHcwqvqcVOcHJ9XzjuiCPn4N7aNkSTvoOcGvBWaAmBTxWVRM
-hvtJrydlnWJlCJiPfZvTePUR
-=IsAk
------END PGP PUBLIC KEY BLOCK-----
-
-pub    BE096E29EDB8D141
-uid    Eric Lafortune (Key for signing ProGuard artefacts) <eric@graphics.cornell.edu>
-
-sub    E05A9780475FAB55
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFFGZXQBCADeZK9xuCrDwJ7v37y8RITlchzBfJEWv7cSbrSIBlFNAsUUoshW
-Y8U6xYKe0GdiLVta2F8bzs0Si4LcDeglQNi9Fxvh3/jfs0MEJUfSeZ4z1Mn5WY35
-utbdlHe6i+7qvhpHveREwWoWuvFGKeSCV8SioolG1mzxrDVLkQefPZ+Kr+xd2cYZ
-SIkbjdhCvJHcUkD9gs8Wz9q9eDyc7dGJmfBYaQ7Xa6lbd852qj8LjQ7Gd41yHU6T
-U3oo0kKfAPFkW7rX4zeJEBgpncK0i4ertd5to/y2hauqPU3VMExqNS0/L2GqKNmb
-Q2Me02pBSBCrLLCUJkm8jZorPNxlQxHpFLHDABEBAAG0T0VyaWMgTGFmb3J0dW5l
-IChLZXkgZm9yIHNpZ25pbmcgUHJvR3VhcmQgYXJ0ZWZhY3RzKSA8ZXJpY0BncmFw
-aGljcy5jb3JuZWxsLmVkdT6JATgEEwECACIFAlFGZXQCGwMGCwkIBwMCBhUIAgkK
-CwQWAgMBAh4BAheAAAoJEL4JbintuNFBUQ0H/1ahtWOeS+EEZqUxxgLE3aiuw6XR
-mcFY/9kRlnBsKpWGGyV0DRkLThXSV5fWwiP0+moef04Miv81txVXR3U5f4MY3U5J
-SDgeB1GK+BvcYz1CXxGcErgaMIDXu/K03OyQNp1lD2kjmDDz8SHdVqpv/aFfxWpL
-uMaogbStXfbDiMjeMg2zRcAzXqu7JlMt3z33uiTUZk9jubAPOBnP5/Yhuc2wcnfu
-cLUUL9xNE6gpl0Noy8qJ2TaVoHLfDEdSgVbLDNpippNQCIEXn8VtlBCG9FBtTUR7
-z8fGU8f+ijNYHMa6jNsDlSo45/RV+alQSSZhx3hPCIgO2klEkawBs0ikEjS5AQ0E
-UUZldAEIAL0CmXXJLZWMbKXEROAYFnUqQ4eNLUcLY1NfL9xrF2KP6apMXLJdftwz
-JtcenfD5vra8w5JJBn6cvY4Dr4zmueDSsN3Cpgr7c0trDNspAQMyUGmg4Cw7lAMr
-uIX2om1TTa5ALsQ1PfupnLFLFKbYd2MmfwEVHgEBAzqmr89RoG/NnlV4uxvWumb/
-OrLzzizGLHdLFjnq3Szl6wQPJwmxCtWHvzW/Y+HYclm+wp0sufvrXJ/G1RrHKxwh
-xaDVyLKsb5wkUC6SZmE477SP6ZCokoAGHqEK+5JnM9MYXreQ7N6NggRUseCokFaq
-ckze5wVBXmPuVAg76ScPFQd4JzLkGzUAEQEAAYkBHwQYAQIACQUCUUZldAIbDAAK
-CRC+CW4p7bjRQSkUCACPWdIvMXPtSQFnFR8oUIGxvcp9MYdealHNYkf3qgJTuWbH
-TeD8WpE53immju4hitOq/qDevKOWhcfSaLqCtdRyYQFFDWQt4SsiGdWfCvKiBMSM
-nrDQI9f+XCv7J3ute5alyMgv9Uo1XLyyiwhz9kJ9mzg+ENvy152PucI4TN63qMRQ
-MQbkAenrTzIer+5Q9ZY4TILC8pVVAIPQjTHuhdh8VMclTdkHab2PCFC57/3djJyY
-44PLhN3hLI4CElAGLUwBZLRa6OFOvwW5naivwgk0zeeTqq/jTOWPYiy2dyyX1pRX
-8bJh5et4mXyM7HLHRp+FblgWxpFWNvMCEpxujLsG
-=B/UT
------END PGP PUBLIC KEY BLOCK-----
-
-pub    E0130A3ED5A2079E
-sub    0AE7BBD7FEE66E0C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFlMSXMBCADcgN0/57D/gU5cDobPiRuDT6qAxb/NWhQiqwAocKd274r4gPJm
-RbffUEZEgKhjH6l0CQfilC4R4x2QtU9sNC9kB/D6zumoS1uI0Hmx1pC4UseUy55r
-20WDxujUQ7OcJbpe2cDcQVKmMok2top7ZJqt4KVosQEeT9jjsgBBbEtg4cWb5ddR
-5rf+aJw0v/6dMLef1r9YAo0ZtLc+g2dyacqw73tcWEd3oCH++SgE26NntN+GibZu
-VXSE5u6xI4KwfT2vUT3jt5Fb29myX4sxsfB7n/xageuJYy5ms1ABS+WDO5ssEZC4
-eQEVL7eyIb9YhNAW/WtjeAuOfOKNonoqKFGXABEBAAG5AQ0EWUxJcwEIAMgrP3U+
-7YCibxSQKOZrp63RaSUkv7mCvQ3Lx4P4ZD/sDEsLOiKkAc+ZU7ETTIQkEpHaibvC
-ZNrA+R0pfAj0LYBLstEIkUxtAaVM4DBQGN13Zdup46fI8rPZEyZVb2XpZ/qS4RYi
-StFyJzUdazBJs/IB7CT0xp4DUFUOrsykVy0aWzWt4z0QBe1x3AmpAO/DdrDN5gvt
-mWzWbV3f783PuK3g41ju7F9XX5nuuatNSNHOHt65XL4vmhmSfXuP6UFjK6MKzq9z
-pbZD4ipUPoKEId5ONDSucX4C8OydpC8+rFWJCDDDvocox3/l6TzihQXf8MDDcB0u
-1TgDPz4M/S2vBh8AEQEAAYkBHwQYAQgACQUCWUxJcwIbDAAKCRDgEwo+1aIHntk2
-B/42pBknUQB2YjkPryJ1B1ArcxaLO7gVo/lgT/rLGL7BuTYsFIl9kJUD156EfkmS
-AkfsxPzwUNh/GyfVQt09F6wheprx1fLNJCFIYA9ZA0WVZGSwbE3NdiuwEaJ3/HZ7
-7IteQh5LKllqFuSlZ3u0xdtGJjnAUU9wHxWH+0W3RPm62piSJcWUw7CSqEyuX+8Z
-+eq4HY0v74znfy6GyCiil7S1T9fdan22hP3xiJHgVKtyFmhhrz6YxcZLa0fYl+R3
-mCQvt2FuiaLL3d/uH0z6EzWs+XZNbjRBTGI9VmO7siIy6rjatdult3Sx1quBCixC
-4Ms2AWEA7bMqvUmCoB2M/0x8
-=6Sqy
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A6EA2E2BF22E0543
-uid    Tobias Warneke (for development purposes) <t.warneke@gmx.net>
+pub    E93671C7272B7B3F
+uid    Rolf Lear (JDOM) (Used to sign JDOM Packages) <jdom@tuis.net>
 
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=thlj
+mQENBFCPD00BCAC4tY8wMQTsCKyII/mMkUDAkXA2cLM47fY1Wn+iohtgtalUdA0v
+AhGvTdFU6/St35rOKNoyLC7Sy30FBYpAEfMB/x9j/CaQtdtGhaQU0hCvtWGhhS3J
+BJb3BIzhKuP2mx+6tgSPtP/meiF/K1GV8x4s+4JyrVxSFtqz+yp5szFNbIXA46cg
+UWOkzPhwA567Jf/8dUWysXb3lp59DG9anp2BQENwh/EmUhuhlPoM3PeUIPcZAiyD
+SMJCR/KooLzE78lAOK14oD8eV0qg3tT0R5RlsNKfFRRoo2bwwPhz0SUVqJlt7ehd
+By6ztFKej4M4ZKonnWUiVJhKEGm3dVoEAJTZABEBAAG0PVJvbGYgTGVhciAoSkRP
+TSkgKFVzZWQgdG8gc2lnbiBKRE9NIFBhY2thZ2VzKSA8amRvbUB0dWlzLm5ldD4=
+=Q+9k
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    D5F4C07A434AB3DA
-uid    Egor Andreevici (My key) <egor@squareup.com>
+pub    EB380DC13C39F675
+uid    Mark Vedder <mark.vedder.key@my-accounts.info>
 
-sub    9D49CFE20A7A3EE7
+sub    BB09D73166EEF1AD
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-Umx6zyOUi5AfW8LWHwPYuk2dkLY=
-=KXp1
+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
+=V/CK
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    A40E24B5B408DBD5
-uid    Robolectric Developers <robolectric@googlegroups.com>
+pub    EB9D04A9A679FE18
+uid    Uber Technologies Inc. (Uber Technologies Inc.) <developer@uber.com>
 
-sub    6A2038967E03726F
+sub    34CF779A8B04720E
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFRdA40BCAC0zSALsOjfjr+gO8q+HV4qPWuIRB8S4z//jCEpKypyCRR9sA0W
-IDHG6OqG5fO1bP6VsHvSx32E8YUf0bi8eGgpKj5gJ9jmausRvRHtUHJ0pvZRBw51
-z4amYVr+NdVoyqLXBgBYeFlEYI04rQH9W8r1bCk8RKGJFNvO6ikTN9opLRkvZ7A6
-7VKlQGMd0sSJ3MAhzKUkM+ZWeCb/TG0xSrhJHcrFUORdV5zaX61anOTSst4HOTuL
-ByIZq1RMxKP4UJIWH2NYVUC1Bdn5CbY5mJysqQXjobPwG/cNAyBjsDBCh2VMnFY6
-geCHL3BowNd8gHUr0wjGKOipRmyfOJoTspMfABEBAAG0NVJvYm9sZWN0cmljIERl
-dmVsb3BlcnMgPHJvYm9sZWN0cmljQGdvb2dsZWdyb3Vwcy5jb20+iQE4BBMBAgAi
-BQJUXQONAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCkDiS1tAjb1Z24
-B/4iAEYvEFhBGjOuXhAPmZSyYyiHWrehY2yZGKmjPKoDKxD05PC6lCNOsdYn5WQ4
-sO32Yi2MbCRpOdphJDJORuGapMeEdrbNqAZ3kzCyMEI7AojH70B7/g99bY9bLq4c
-MYS1udCVPBzfNNSZok22S54fJmFg1evzJbOynZnIFKAhSWL1Ns0zQ9RXQ3gddhAF
-zE1ciZTwmRwdkObd/oxjs/g5ps3VuB25b88+WxGRaZf1vlZN8fNvK4AEDhbH/j5+
-VjcI7R5zLVsYNHEZSspckuoxn+1PNOKDZvhrSrDlqf1EUSmPb4j/nrW07c1p/91/
-T/R02aGSzbwqbbI17ZuxYMU3uQENBFRdA40BCADhMeWEVcUNBLRWDatdlvc7q3jZ
-EyejhSl3zw0I15yhoBbuW+ZnOTG4fkIr9SRo4whm2NZ7eemEnQ6tuGhVXUqPIxWA
-wBteY0ZBhwNGhMql+IIdOE9WIo82yV4gj1Lo2rjxaxG4Rd7FQnys5f+XyFZ8vaXp
-mpH9VeFjc1Ls550DUP8iVvIoKI65Ve5RMZc9e3AeP8FZqJpc3q+Al2f/FAO8+tiD
-/J849aP4aqUKiwvHk/nxle8FwepQyvXRrSpFNz2uK5bgIXQrxgcKLPjl6s9l8SKn
-Twg6ok0EcJjGuHjzCeFNp/WFpAeJAxmAZ/qUbr0TBp6jxXoMc/RqdO79MPX5ABEB
-AAGJAR8EGAECAAkFAlRdA40CGwwACgkQpA4ktbQI29WOzgf8D487fhQSsH87OJfp
-oSPf9p2wGzgNFAc+sb0gUy8rMmc/xySKGfZ2BZFT/CAQsOzGZ/KSM3og+FFgDcm8
-GWpSfZNymXnmM8aCaEyNj4arENxwhU4BEnKYFf8PIDoCjAqBbSWuTa2RzaWlawEE
-g4hItheFmw/My/tbo62N4zn98IYU//50PNDuDb1lvOi4SVFglXRoM+jS2X6E9R3Z
-7sYceClr2EDN2k+RbvB6ngOiu52FvC9ZZPJnfK9/XHFtKcQ64yu3pbeXwiuqyr4T
-SpzGJNm7czyVylHZfvkZYVhmZCEG9xQ0lzHshaXmkfqi5ZJMEtXwNP1dWIMhIGgY
-4aLehw==
-=LRPz
------END PGP PUBLIC KEY BLOCK-----
-
-pub    102E05D8DA6C286D
-sub    7680B2343D1CF013
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFOZyw0BCADj6eDnIjaug0RJQCi/HLw5jJ2kORPaegxFuE5IhpN9pZCPASax
-aTROfUSnys7cbxZxh3Sri3spQ0j+ejod0MhVX9ajTg508YAJUaCBbM7CGZJZtVFL
-atf99umsxzDrXIk24z04W5KBiLS3M7QKPyMujjiVy9naFxyW8GXJxYcGKUEltWwP
-zgO97xwHs+T5nXcO6jOrJ7NxI9fbnWb6QY6btSkrlpLnwH5yxGpajcR6R8+kj+0W
-dqWWrs9vo0DQGohkoqjTzeVt8UWHqUBva6hULkz6H9CRLfVxuK3lLFtnRBjnjRbu
-bNyOdVdtaXArmMKwsonsaZ0E973yqcmbhKQ3ABEBAAG5AQ0EU5nLDQEIAK6UjEUy
-lBC987DwdhJ8sQKGcOq8JM7sfLgpBfuRL+kWM+jpXi+DmfThnO2tI5UaaF/jMd8w
-Kd4JeAGE0Ynj5V1n5qUsTUXwEonDLLBOBYEj2NYJ40kmVrPdp00auDf11Y8NC4vS
-m+4QV+FDcWvV62ogOC5rYKOaKMPf20F9rCxUBwvrXNHPQJZeX3FqU/HBhvaqtHjA
-flZoQF01baDMQTZf5JgATzXJRsKKum7z0DWiYNoOJ8wpbuXM6CG50N+4OrlSZfxx
-kN8I9sSyREzHj5zVWoKqeyii9HUeqBLWh++TiYrRyP9NHM1SXhrtp3wZ36CBXqp6
-ME2K1DQTMlqZTwEAEQEAAYkBJQQYAQIADwUCU5nLDQIbDAUJAeEzgAAKCRAQLgXY
-2mwobdDhCACjfIYnUCHd6KzmgOoYXsW8NeVE3QFpMxMVq9rNEJxAiOg3b+Bdz48L
-2lQy6yJJ7owKAH2M6FvVXpfrdkiMQICEzKr1IT48H1Sa0jj0cSR0jRYszmd8k3G0
-hBqmGnfPBfolrOVDaRGf2CXCZFHVZA/Qvof76FaZ1cFAKYmUraXJBocxupXz6QMq
-P4qsPgkscwEVv4b9u+Q+YLpqHBiWmsHk9mp1Jtqz1SBTqI4zVj7w6qmc0aZh9I2T
-ROvKAtF7WjBg9LEFstqZeP42rKenm9vOGs0aQbe4kkgFMIwkLI1TeXrYeQWSdjlN
-nCYHwzPH+lq2dsCro1T8dMZTRFWKeaPn
-=w1VQ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A9321EDAA5CB3202
-uid    Werner Randelshofer <werner.randelshofer@bluewin.ch>
-
-sub    D36DB5C489BAAC5B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=rtCH
------END PGP PUBLIC KEY BLOCK-----
-
-pub    42575E0CCD6BA16A
-uid    Taro L. Saito <leo@xerial.org>
-
-sub    47624A56526BF2F2
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=6Iv0
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1FD507154FB9BA39
-uid    Tam?s Cserven?k <tamas@cservenak.net>
-
-sub    8DC6F3D0ABDBD017
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBFAJOeEBEACn8aGYTnhyLS9SNi+SAdRU+pMPiqxdpxDMZczVee50y3LiRnCX
-biWqZyhzuHZTccgV9IMYFwxD490BioH8M80escHrMh2C50FCFglVYsZQG93jYJJR
-Bs7Zclx3DzqUPR46iES+Tb7wirWIZ2voP0/jSPCZ9sipba30ujO0FnP53QprH5jk
-poDzQ5M4EQqp1HPqepveikhZE19KSc9t5Lq0pMs2rDeEXElfBwHrg4V+dbZv9Db4
-57kWz6AQWfmqWr0262pQkCc4cy3LPMLkvKcH61T2aE1hm+L9IBI9UBkbL8xNXYVO
-CSG5XhVOSKpAjMHQn1kbxbLlFj04z70TYmT2ZvhFWZhsYIGs0DMgujZujGMWSVOr
-ajS/XGrfK5sgv9vhI1TLiKJpyzkEO+/ssNAJGnk3dlkJvr22EJjrUyKCwUTNxCAv
-vH70l5r/peJ+H7OHejr2UBNyFPi8uTFvBKi/Hj6xjVg01KsWREczkdKG3LlFK92Y
-9C4N2QCJBZJURpX/ITcHENo3sch0RhRR63gMKB+TcqCHCCBArjcSwAscBsehlVdi
-El8OmWickCxUv7Grsdgxkx4+9/SdimsSWARK08gVqmMx4h6jzTPFCqW62schBiFg
-gm2H7RALlZauiv8BGlvWLrzIc7ONbT2a4MEN8anUqrhrQ6FKhjO+nKaGlQARAQAB
-tCdUYW3DoXMgQ3NlcnZlbsOhayA8dGFtYXNAY3NlcnZlbmFrLm5ldD6JAjkEEwEC
-ACMFAlAJOeECGy8HCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAf1QcVT7m6
-OfB1D/9StrqXL9xqDrZ+kRbF65U3fvGN83ucfGeJpfYWi3hSVc5mWZC8gnQPp+zI
-e3Bhso9Bvyh5oekACeJcPOnbxIs8mESGu8h2+piQkuSjjTUkqaXoVd/3sFsertFf
-SkuTNSYoRzL85GzEuk49iHX/C0cGUOj4Zc1ftXwgD8arvgbkE6UGwr/zmpqrjQGP
-h4VJI3bmu+EJVpzZNzf85o9peKIP2qZs6uMGlOXe+HSCqsvrCn4T0cllffAD2Bn4
-giTWILgx57W2o40tdU5bg2eGFb5RaBRWGL9Pqc8U/trSgOeqTJHLm/iNZQBtIkvN
-wYVLnOu99/yz2iw0O+Urjkwa5qqdCD+MABOmqgvAIBTFLJetIGGJ8MRno5/vvNE0
-jsJQ67oV+jmnKKgJh2wkGmHulnvrfbI6Uvz1cY/URyw7Fn/6I9yPrjO0wsfWQQQM
-4ABMjPNY5GPgPvc5/xyvI9vlMm4JIFkwWrnqpVarkukElembSY0ynoq69XJKKMk7
-k3WBO73/aHEbudVTO8lcBdXle69wbzSsnycSzhzuVdiaK+mO9zWr/H+WNbwNfK9k
-Q94vSW/Cs6yT03cQ7WgRdfZTDXLqmJ9tKxLHsKVsRnJVk/xUThzhetEARuzrUApI
-NzYBCqM5O3+5qK5T3OouhG0qcWq7LVnccUDFCb8VAkIbY8DLzdHJjsmMARAAAQEA
-AAAAAAAAAAAAAAD/2P/gABBKRklGAAEBAQBIAEgAAP/hABZFeGlmAABNTQAqAAAA
-CAAAAAAAAP/bAEMABQMEBAQDBQQEBAUFBQYHDAgHBwcHDwsLCQwRDxISEQ8RERMW
-HBcTFBoVEREYIRgaHR0fHx8TFyIkIh4kHB4fHv/bAEMBBQUFBwYHDggIDh4UERQe
-Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e
-Hv/AABEIAGQAZAMBIgACEQEDEQH/xAAbAAACAwEBAQAAAAAAAAAAAAAEBQADBgIH
-Af/EADMQAAIBAwMBBgMIAwEBAAAAAAECAwAEEQUSITEGE0FRYXEiMoEUFSMzQlKh
-sQeR8CRi/8QAGQEAAgMBAAAAAAAAAAAAAAAAAgMBBAUA/8QAIxEBAAICAwACAgMB
-AAAAAAAAAQACAxESITEEURMyM0FCkf/aAAwDAQACEQMRAD8A8ds7bCqufwwME46k
-1w8TBiVGN3K8VeLiMW4XI6edCT6jGhJLdOK2HQTBOSy+1tXEe0jKluc9a6kjUPH3
-Y+UYPr6Unudf2H4WoB+0O05BPA4oXJUhmK73NPZsIZpVlckMvQHxzXyS9jaUtK+S
-G59vAVirjXnJJU8nrQY1WaRsFjS3OHRGnxl7ZvZdQgE5kU84xQkt+zvkGs1b3LyA
-ZJphbZYg5qfyNpDiKzT6TcneN3Sgv8nabHdabBqSj4ofhY+h6VNPypBrQXVuup9m
-7yyK5YxEj38KcHOjWV2348hYniuxgTnJ+lUzs8Z4GeOB5UYFdZtjfDg4wfOhNTjK
-OC3XoMeFZb5NkdsDZmJ5AB9qlfG69c1KCMnqk6SAlfTIpNqCyZPWthDbpeabFdRY
-J2g0svbEHNad6KTHpkBmJuI5M+NCPE5PjWsnsB4ihX039oFVnGy3XKTNiBvHNXRW
-x3DrTwaec4IAq2OyAxkVBjhOaC2MBGOKc28e0DpVUUO0YAoqNelOrXUr3tuG2wyQ
-M49a1GhlFiO84U8e9Z6wiLuqgdTR2qXJSRNOtjmUrkkHAX1NWqPHuU8hyeM857T2
-hh1m7RQCRISMc5BpPIu9CjDnnFbftJolwNUE0Lhi8QJU8B/bypBNZwqSk8cls5GM
-SLj+aoZMaWZp4so1Jk2BUkHqKlW3oC3cqqwZVYgEVKqsuE9M7DassDjS7hwyMN0Z
-z1FaW6t1D9PhNedw2umSaEL7T7qcX9sAWhkxkDPOD41vNEvDd6RDOW7xZFGSP0nx
-FamG2zizG+RQHkQea1TOQp9zxQr26Fuqj2p4IY2BLHNT7PCxAVhmmtIoyameeDHQ
-ZqpomB5AFadtO/VuAFUS6eo5JU+uetC42SZSZ7uyTxRNtbliCeaNazIJIx9KsULC
-hYjOB4UJSE3+p1cXdvpOnG6l5YfKPM0Fpum3t1YR6zLdCMXJLFNmePDJNWWr289y
-X1KGKRAfw0YFtvv4UzvdQe87qFdqwqAAijAA9qPQ9sBWvRPutqrx2chIOF2nih41
-jkwrxrIniGXI/mjYxFdn7NIedp2H9rUHErRyiOVSrLRp3uBV61PGdcUJrN4qrtUT
-vgYxgZPhUph25t5Ie1V8Cp+OTeOPAjNSsa5qyTexu6DJqNzJJdS3lpYtawMdmzJK
-5xyMmtV/iu+P2+40uQ5SdO8jXyYdcfT+q9JuF0fVtGOhzWcQtwvwBeO6x+oHz/uv
-Lrjs3qPZ/tHYXGnypNFJdYgcHGQOWDD2zV9w2w2LjsmbXPTPRommbDVEmFx3EUvd
-565FA3r/AGO3/H1ExgdAibmb2rRzRW9+Q4wHx16UpvNISOXvGBkZTkbuQKsWq+kq
-0ueMzF/dayLlLeOC+Jl/LDnBb6D+utaG/wBD1jSre3Ms7NJIATHkkqcc01ttXmtr
-fu4wqlejY5B9DQ15f3l8RF3jbPLz9zQlKg7dsJyWU0AQGN75GAkZHXGTgYIpgsUR
-gZgc5HIrmaPZGEZgWxVUU2yTYR8OMUR17BXfk4t44SSr54PUUSkUKcIMGgnDLKR1
-Bo+2jlfB2ZrqzrStHK3XA9M+tNYRDdQM0nEicqw8/KlfdkT8/u4+lXwziCVwSPmw
-AfGiq69gWN+Tx/tVd3MnaO/NwfjExXAHAA4AH0qV6H2r7G/fuq/eMTQxb41DjdjL
-DPP9VKz7/GycnU1cfy8XE26hti8m1grAKwxhT/3NFS28epaQ2l3TGN+GilHWNx0Y
-UKE7gmQKdn6gP0+tMFJaBmyveRjfG37x4ir1fpmZb3ZFemXVyGkt7kCO/tsLOinh
-x4SL5g07ivldQkmCcf7oK+t11CCK9tpBFdxDMchHBHijeh/ilsF/FJI0ZBinT54W
-OGQ+JHmvrXFuPUlqX71HEoSRvgXGfSokYixj64oaC6YDBAYURHMJFyAB9aIRgokr
-vDtUvjJHhVAV2VS6bS3KnzplbrBF+JcYbcDgUovNZSykWH7J38Qb4SrYIHlUW0ds
-mu3oIXHAznDLyKo124lsFWIZAePcDn1phpWtaHesqmZreQdUlGP58aV9oLqHU9W7
-23ybO2j278Y3t6Z8K62uOxnU3z1YgmkXM0s6o8gwTgAnkHxzTZLWOW5LyOWPQA9P
-esbFIyIp70ozz/N5CtxHpyhFktbtvPJ+IGl4nkRmYKs5a1bcdt2VHkBUr6Y7gEgT
-RnB/bUpuiK2/c5hlidYpwcxTLg+ma4MBhmksCxAYb7Zj5+K0PcYsdUutPY/hPmSH
-2PUfQ11O73uikxn/ANNs2UOeTjwodydf8nelSFY1D5UElGH7WFV6zpttcgLcQJKA
-cqx+Yex6igo7xJZUnH5VyMOP2uPH/vKmsUxdNr8lRgjzqBLGoSNXZM3PDe6YDLZS
-yXVsPnt35dR/8nx9q6tNZgeMSW/AYHKmm067HB/S3ynypPqGlbp2ubEpFOfnjYfh
-y+/kfUUpGvkdW1bftKRqF7dyskR5B8TgCpcWt25/NRsjDc0Bb6a88rm2uJbe5T82
-FznHt5j1r5BDrcTMDEZNviTS9v8AcbxP6YZZm3smZ2Z7q4xgAjCj0rifVJpo3GQc
-jaEC/wAVRBp+pXsYIg7oF872PT19ab2mjR2akPJ30rfqK4xUhZ88kWaD32zO6u3c
-2+4AhgwG0eZra9i47VtMjiLyLKF+PDcg1ju1lvIlqqpw7yqBT/sXdaYzGz1Kcwyx
-JiFwcMT712J1k0zsxyxbJrfu0yfEl7kHzXmpVtpbXCQ4ju4pFJyGNSr3E+pm8n7m
-e7bko1vOvEiuMH3OK40R2FxMmeGXmpUpD/JLVf4iKidk15EvCqRIB5GmkMjMiEnn
-pUqUFId4U43W7KegGRQgJaIOeoqVKNi6yT2sNwQzriRR8MinDD61Ro9xLOZo5SG2
-HAbHJ96lShf2If8AlhennEG3AwrsB/urJGO5fepUojyA+zPdreJ7QYGDJS3WoIwS
-wGCMdKlSq2T1lvF5Wc6Zf3kNqI0uJNoY4yxqVKlDVdRlqm/J/9mJAjkEEwECACMF
-AlAJOiECGy8HCwkIBwMCAQYVCAIJCgsEFgIDAQIeAQIXgAAKCRAf1QcVT7m6OXhP
-D/9sUBLIhjHbEv6gXHfQoWBmASz+aPeUxWX3BYoriZI19/HGCsGv5r2pdTBo3wia
-VBMRBvyeaxiTRin68ykvmKIwv4nlxUsxKMcUQ/3uQwrWoGv2OeZvVSB9USYstK8b
-Z3PPvPXvTcGqOqz2YFfVuHFbepVHAd+EjNeC3Ubf8+XAMdJNm9l0WIBY93nsppme
-80X9K32du7eUmn3evzLR2dgxcWWX4TIvua4qJa7STpjm9fGUqieexRkAtU44/0cA
-coImQL1WHEkq5tdYyMVPujIftuo6ByqOKLVPrbll3Z2jETFalmKqroieFzCCRTDc
-ujxVid9Z4UjSLjmkmpKY7IdRPr0ODaWmytceXfAIkR18qLi2kmrPpBhEpJm/3aNk
-aRIJjIj+7BvHfY5ZyNQD02Vno9DQ4A10eFm+YjHLNZDmHtmrvNxgsPk90n2I7D2D
-6mX/CPbJNpXErnYAOtkQJIXtMQUYRASbUY3ycf/YKmWrae25/EOE4kD3/lGeHDNm
-Hi1FxaLTrkYsM/+F31S0xQBWrRg9u3CiM+KBBbcZ9wyj56xJmzmrWKR8wlnI359k
-81S5kEAYnAzj2Q8sciBbycRNZYNvbWVEl7JiRx63XYpyiZ3u+k7zDo4B1Jvea/2n
-aCrGa1/KuLhWczOuZK+1Ps1Y88acU0fwMQb1MbnTHSJJprkCDQRQCTnhARAAu0/u
-U2Qn67vlAnerKeUVclj1oAlr2FqG9uauNEIL3KFa3n4YDKVrLl156+tOKZLV6FGv
-w+fGX2SjZw4Uq0SmGYe5BOM94hlYkb1ZzLicClfYEDPp335cvsaOxbgHgXSAKIz8
-1PaZZ3ZGNilqirLpjvwDOtNsqsRJ+L3nQjPF4J2WK7iI6BngebSPm8XPYX7gtAsy
-hp19mXqi3cMGGqTZnWaKvXI9ndwQlB8t/orPlWe7uc75uL2WORxpEZXJphIuI9yQ
-16ED30bKWmBeanZFkEGEvEtIQCfSq9JsotBS/3t8XMRyj8OsSSDfk0XYxqNhahoH
-0RVTcBFUcKCH/+g67So59vITzhGonf43tL0eS0BrlGdBiZiVn+i5IAvnpDC5OM+0
-PXLOZiC2s/i+KAUNgOTZdPgkCJraXg72IQ40Y1rfzcg48Rz19s+w00TG9R+jdDRC
-WUerW5TeUhNYVTevP7Vff3L72tjE8cZUJlxUAuak3vL0pB+ketIHH37L12mdbGWG
-ZqfebwhQkVMG+pL+AipXevwC7sCIOv/HrRgJNOfk7RhW2TJI2XS6rdRMKv+AJdWO
-Hw/eD873nir/T4C9jANk3XpUCOfEGGTwiD+vrcFGvqjcoSIZ1JVoS5ICsk770wxO
-GIhSZhzbvQ11N24Vvb9jSQIjVBqjcHRUk+koGu0AEQEAAYkEPgQYAQIACQUCUAk5
-4QIbLgIpCRAf1QcVT7m6OcFdIAQZAQIABgUCUAk54QAKCRCNxvPQq9vQFw4jEACL
-oK1pkiWsGAbLPi0OX62oNyrRP46wiAyfghlQMuZqO4HOvrX5Pdmbtswev8QO5qTm
-bi3wb1ocWMdf7O8t/eRyVf2gdVgsbuZoM4R/A60isQDLTnUDjJuswUfoNgI2LUR/
-eFhDOPQSnGMduNHuAEmAMyPodHqCdvOW+j9pIQtksFNTXqGNRNrH3SgBiRBR1fEw
-kTie2idDD6wBJ+f9h3j/r9y/lVBCqGzlDRoBG4XsZEytvJrhoXXzp6YdpJK4sPRY
-BBlsMtTwLxU2RdlqEXS858BxGqrXRj9SglioDCPi14a6ZJt9u+x17zY958dfXeqB
-9yaEQrL000Ai125kFIpUk7Rk07tk2xShHVoiDgnJGqWO4hxrVhZnq2IYqk+w9BK+
-ThepR7uPGyvlYnfXwAhA+eoJdPiLxavEpJl1YhS8lTxcCmE2iHRSiIl7cCnmRi48
-RiniWVMzEiXTlq1x6mzjyYwUe4jHmTlnM9g9CEmWNq20kR7HoLP9q3prn2YujCSW
-uQZ4PX0LAqRGzSWSLnaSd76lgTGaDBHoh8yiu/MTU7vLXVVRl7yUZ4HV566WsZ/V
-puyIqEIkvA6KTmSZUkqQZmGBddhB3Mo9xweScT99Xvr8h2SCtSwgSY7IcX8AxG7r
-DW7d9EtDX2WgEHfAd4GpO1K90M6KMCGAIYaj9gVMccihD/sEHl2IfFU34732vHQn
-DVb9dqve2Eg8VFWy/gA3W+iljxQaQowijKO2PeSGQE0AvHdHw9PNcRH9y4Cq6pyk
-nQWuQUZFuPswUdqMf1CttkYJBtX/B74drFxPuPANK4KSaZxImhQtT3Xq1hmoMKA/
-+o5AQeDQP2oPIFY4mVvCcuODch5QUY97EXwkdIQVHRr5Np05j8HIKZQAs9QUS1oC
-cvwx1cDPpG+9jJuagTUZFgPSHEYYkqOs1Z34rAd5cir1d8VxLxDfbY0VvWAAHdun
-1gLvPRGUXFKqfMHqqXEANhkjfd9XRS6o6D0RxtHNjT/FFQZ0uwd91yd8EOXgrkay
-Ye+C8yTQDL2GkeLPBAjhZCTC6pXpj/AJI+q2IqiHvbQQLaVD/Nu5LfhIPClgHeQQ
-W5TJA4yRyOj0Ra7Trjdjm6kTZ7ieP2Szfc2DgD4xjJBjoxHXzCjpp8DjzfN/argg
-RdIpOunrNBiaqOOR8Ecwat8FuKUeu+FWlxYoMHO9Q043pd7xm1hbP0VJkZ7X/X9I
-imvyoH1rj5xn85PNau/Rk2M/iCYy6jDW186bK6lv9PYPd5T24p+K3cEz7TMqCgdY
-WSxilutzw+P/v+OF+nOhju7fE3jRIAAH/1GnsnXoNxZQbjleqr3bilEQDYOAbbGa
-jQlQ45HLK1Gc2XY14/tAyoBzsg==
-=Hz2w
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D73C68EE4152C255
-uid    Eric Chang <erichang@google.com>
-
-sub    A23FC45C6F9E2F57
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBF0uFrIBDADbJkwrWs0qPrv4bNmPZMWHcryANAwodvFF4f51Z6S3pBkuBxx0
-vW8ZKC9/scJiAzSqJRf4im70GPNE3MZjNyfuRdaedXw2rFc4Ip7lBsCtklYmTWmC
-vA9DXI6gIhvQ58s13fHcLGepIfKZcIXntyXp3DcPz8XJpfZTwgpS6RlbJjr296p4
-ya1LiyH5GBaWal7DcKwgIBSSAbtEyZH0tNp9wfkiILiTI1RE1D+DrQ9MJa1b7Gag
-qBMn2A74TFEzx/bSPMMllwdKTRurvjz33TTdNuyd45bkteMKiw5O+6c26Q29o6hw
-oQG8efNDrzWOCjW2Sj91DPdA52UfJ9T7C5dcf+EcCLmpV7hWrfkDdzDX3NXnMU7A
-r7kEPKeF608jEcqS46YB8lIBqC6gPMwluLqmukRpxrlyMwsygc7bbieMZRhczCLo
-tj9CUAUW2dvXwY32N7zUqFgVnJ26t4/bHRAW5QVVqrfDC0WmoUVyOsPh9/KKGmIf
-3ocDh93eN6x0UH0AEQEAAbQgRXJpYyBDaGFuZyA8ZXJpY2hhbmdAZ29vZ2xlLmNv
-bT6JAdQEEwEKAD4WIQQOudfEaPl+RAUdZQrXPGjuQVLCVQUCXS4WsgIbAwUJA8Jn
-AAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDXPGjuQVLCVSyzC/9UHsOGJ3px
-qNcSYm6UJGnaco1XNw/znMBUFbhxO6R0dhgfc5YEDm6cQlMlKskX5VgdbwXKD85X
-YJx9O6Xew9GQJJy+xVBm8di0AqCes/0mfRsANeMWsxZ9c77zSZdWHjyYxZSvVFAl
-0UL66S1lYuMxeBrBdWn1Aq85g6O5vQI8a3OiBWu6Fx90GwX9DY96BSwTqxKFkn9s
-Pt3VL7moJAxSBUEeWKezD3C9RlkOqmjuEtsQ2mnF0NPWgIO0tABMUXJiOR65YXNq
-V9sgu7OVhXylBvG8fVp/rFyA61T1CJwDoZwkoyXBacnK8AA3vVwP4Ll4vw/MIxww
-B8p1oO+4dbHzmGDU63ic0JFSuj9eIGdQWXf0acaYmjIpSs/0jR8NOY8S67SNsWzX
-9xrekvUriWjo4l7L/k4i4lPcZOjpRX6Zov0G00rAPq5Y+ZV7J3mRkKrHqw+GZZ5C
-41YP9Td+RBapg0OSu8wHeAeh5rnrFNDHL15iYl0/H8dgeiVrr3YCaa25AY0EXS4W
-sgEMAKfohKMRHHVJ9aAse/rwsoF9D5Qxg/g/DeuWRtnFwrSv+6rBJW00S1jIXkze
-M99MsjK4aJaSLfId8SQmMWMvzwBp6m3J0Gqy2CdRo3v6zW0juPHZ2vDs3wt9sJPJ
-edufqxlXwWo6XhmNJXcclBzeP2f17Phx6Wrp78ONo6tDg77IHLdsXER/KwYAv4cK
-6O+MahvnelpAFyi1fdiLJkkrwIheUKF9jKgCvYGQeQSoe0sopFD7zXYgE0DurlpI
-9Shj++i5jN7atvaHRSFp6Vo8PkmtGeD0jq1N2nCdVWkIIZL226ABcSBSQSVdTiLP
-FrMmqlppoxvwl8Q/R8nKo1lsNKp/HV/qshF50GfpJfLKA3GmWZWt/dkCb1nurCmK
-jAO3AHCL5p++idGIsSTgIDg5mcpnltG/TH1atoQj1ixRZ/ykSu6VO+RygcV60IdG
-Ct8CFTLSLUacfPieSR6mGqLdta5ISNHqbJ3Xi2mQwADQmLbYnwKcU0uunRUjYDzy
-IINn0wARAQABiQG8BBgBCgAmFiEEDrnXxGj5fkQFHWUK1zxo7kFSwlUFAl0uFrIC
-GwwFCQPCZwAACgkQ1zxo7kFSwlWfEAwAqz6AHYxuxfbEOkCd/d7Zhd8OvmLHyH70
-A3wfw1LXHowUQBhQi2BwZ9jwXzu7s3ciohMaHvN2w4VFLwCY86VnKQ+mn36Op6/O
-05UlGFauaCxyT9PMHJOHpKdUopCPnajquSdpHZ/y2oCl+KUcMEY+s74dEkDvj+Qb
-L4VMawOunmKlomYyFurRJ5k28RhmzgGaUr5r/2xUMIvPaKQ+YamxjW8THKMyNZqu
-D/cRNHusxtXXoULhO9XOhSWyOV1EDwrK+uIV8Vg7kP0AD3jNW+S42NmrQnAUk4Ni
-Uj/2vtXqqZrr57qxOAz7GGCh5xNGuPXeb8mjwCLqYECLIms6clQT5gWHD5AU36te
-s5nZyahgbVU34Jx2XQkbyw1245MWBeOfjZA/cAQfweDmKNf4sevLfDoLu7fnsOyw
-IwrtprcYdzyhAaM+pO76brTX40781a2yUH2zpZPWobdMyDNDeo+bql+Wvzb+qRGS
-zJV7rbKv80zNxWNJMOr+yshtM+Hclm3s
-=mRRB
------END PGP PUBLIC KEY BLOCK-----
-
-pub    62C82E50836EB3EE
-sub    2AC7BF2F3349DE80
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-egz57oSj4I+NT33hA64x6jicEKyBNxNI
-=T3Bh
------END PGP PUBLIC KEY BLOCK-----
-
-pub    AC5EC74981F9CDA6
-uid    Cedric Beust <cedric@beust.com>
-
-sub    501B5ADEF57CE6A3
-sub    5D9FFE7B8E3DEA8B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-FF1NsuDIia3lMYUCPApVQbA4f0Paaw==
-=qDUR
------END PGP PUBLIC KEY BLOCK-----
-
-pub    78178478013521D0
-uid    Ktfmt Team <ktfmt@fb.com>
-
-sub    FA84183FDD6A6B98
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF6RvwcBCADIVU7oxOiljoWxNTkZ00PKVwyqhahYpN/4lamULtECCS+HAF+J
-DsNy/6QCl7lKAGrSyn9dvsI56KEkGvUJfpQrpRlg+uIQDMxS8JF7p9n49DNc8Q88
-XuCaiv7pv9hhCN3Mn5qcuzTR2gGP7ToZ4fQW9W/PSJBSOeO6JK6xXNyiKcyEoXp/
-jGSRqqbDkAT4OYEUy9RfG9BeJEGUbDK4RIaH5Bo0bdahq3mfdlKYXMwRWGV9D3KN
-4iLE/26h3y6tQZS5zHQGjIIJedaKGWEiMsF+b7Jjf5OEC//FoH1IS7nDz2GK9BjW
-iELtSnmyDIDiFAvMY0pGsn8AQFn4JxEP3TMTABEBAAG0GUt0Zm10IFRlYW0gPGt0
-Zm10QGZiLmNvbT6JAVQEEwEIAD4WIQRkgZCZbsCTCm19Sal4F4R4ATUh0AUCXpG/
-BwIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRB4F4R4ATUh0IbP
-B/4jCLSh01uY5TizFr3PHMWwc/JG0KUOS7KGA/ePkj61Ouo+NkprDZ9TAcrtsSZj
-98JccSwOIZT51ueacpcvonS5iifsdCOsQ7L1CLL9CtHstT/9KELDuzD5eqIEuCJS
-x1ntycHN86cHU8zQFNxObEr97s0T3XKkxn5mnq5SqPouLuuJLFUoJOrE0Pm3IOpy
-QmVTW6GZnS93acbIasHCPN+ij3JMVF3lijmhoGSp8oPkiBSEuxS+E7P5MYCVCcPd
-o8GTPZZqowk1q1Y4u7GVtedPcA/w9HojD2R/bZz/WidKs79pqGgyUwiP3aut3vmz
-dmdewtAMmtpVjRVqYJMJIhx/uQENBF6RvwcBCAD7kTkyBDjDradO3GdG2MLjxLF+
-NEyTRTzsYGpPTMfUUn84UjZ0NB2sWhnOzvh3pbBOsXlrYr27h1o73llL6Mb5I2qG
-EPVlbQzf7AYdpMMUtugZL5cW2wNuWQ4I5PjNMQqsJAdFl9juT6Fde/iiVIa8VPck
-inuETgk508yyIH075Wi9Z87CXfzVgzeUYcwSnvVL/aXMWQJmckg15p+s+tgeeU18
-nsr80GVmh2nB2+A2HQhO7T5H1WPu5Ffi72izrFrAX+b/hKOMkG9RBXOGHf44DE6v
-BlAJzfIrEh3kNeEm9a95h0jwPv/EP0hmebPjSXNd/0UtkPDoYjhNNOyTtpwxABEB
-AAGJATwEGAEIACYWIQRkgZCZbsCTCm19Sal4F4R4ATUh0AUCXpG/BwIbDAUJA8Jn
-AAAKCRB4F4R4ATUh0F0rB/45oOdaDy7PELtFEseGh1YJg9Bd///cbLMcd/0luZeo
-kfFDyqMVMtrlDgGfMUqw2vGqzcX60n9YeVkaydBqoijCZvHnlQ7i2hZxmF9S7jIA
-tqgq3zZUNPQ3RRB2B58chKMowT1oKnGaWv22DE4jo2x8/hxELO4FARhBLlods3s6
-eTF+mudMwQ+8IRDfasM1c9X8XQMG+V5fol6kGfpmL0KPkwamzPyjXA292uob/dOB
-XHc8tEnm92l1m97s2kA0iRBCccRIFo1BvbhLkvnjA+Eyaq7H4Ok6jespF73W10xz
-tnA9AxRWTczuarlqasUyzEoDbMBQeJo73dJkt21CuA4T
-=DHo5
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3595395EB3D8E1BA
-uid    Ralph Goers (CODE SIGNING KEY) <rgoers@apache.org>
-
-sub    FE694B892910DD22
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-eHQMYs8Q+LJK0tUXjXfXSbqs
-=F199
------END PGP PUBLIC KEY BLOCK-----
-
-pub    79E193516BE7998F
-uid    Filip Jirs?k <filip@jirsak.org>
-
-sub    9F7335D63326E7F9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFWdcSoBCADK8j+0eVZKUGctZo/VaJ/K2Wppx4jEFgih8xiIWREQ9B3QEugJ
-mJMWZHhrnHB+sjVx5No482ch6sVhYmC+VMyTdzepItZ8beYa0pnNGJnrFT+HcTOS
-g21Ef5e6BRORNho2j9YTvxvjof29XxU4SJFVgffs48jGeJzN1EDmOz4OlZupKGU+
-98o+kMKCiFjcf6Vu03asuml97b2fMOJ09n+UQVlZbBR/Yo407ZLkL2Elx47Fz+82
-iO+M8w2qNnxT4PA/TLgaVzkVHaR/JIDlQQ4DfuyloQI1hBpMB8f60oukVr5dBGuS
-1dPZ1H7td975sLegWoj7CCOFZXrDzYUXwwXPABEBAAG0IEZpbGlwIEppcnPDoWsg
-PGZpbGlwQGppcnNhay5vcmc+iQE5BBMBCAAjBQJVnXEqAhsDBwsJCAcDAgEGFQgC
-CQoLBBYCAwECHgECF4AACgkQeeGTUWvnmY/Z6wgArX9fzySIVWcqFuhaIlRlib9j
-1qE3sSiFVENV4NrCYv+4ZUQUEUvqwX0F4ij+Au9fzvaWb0gT02ErHYJ9UowUgUYb
-IdHsifoGh05jZdiClXJutcQHddM+P+ReIAS4/JDlXza1kqa1RRvDh+OtsrDkL1MU
-a5T6/KbCWzAj9+96vqa2dLO0mhyrPpVX/hF4tPY6ltGYEXA9N3c83rFmaCZTNM0t
-sEQniQMICOMZul2dKJ4Tev12/G9sd4owtlHtAtv0+tFPDMPQAXjToUo36q9MIzKE
-Cyz5sX64QRablAJc7QD4MFI/7J6eQdpSKM77QaL48kcUAK1j9nlXv+oj/1d437kB
-DQRVnXEqAQgAonYI6XgMnKL5jj1n/3kVxKA+4m0znSoMutK3B2D3geqTzFWlDIWU
-EOEE00U2mBMPUibQ9orbu5IYrbXLR6t0QORJiHudP3LxdtjIqXCagdzCewJ0Kfvd
-pR/a65dsULLu4+v8R7KBH+lBVs0aN0z8e539ZaoGPCVaWliybbHwcry4tOMu9wyB
-dPlt0pkqQ7y+YerXgHO+hc9urQVY9zHVBRe1J2vqzFONitFlD5BoT386pz8tBi0W
-32J46nTgReukzJWLbtV53fxYAFUroA7Ydy2xYKQ2yVqBq9NraUNqbdtlEhJRDS3W
-eQs4ittg+oyMumIdNjSbUlbDX0O7EP16KQARAQABiQEfBBgBCAAJBQJVnXEqAhsM
-AAoJEHnhk1Fr55mPAAUH/itFMvGq/ri1alRXhLbhx8/HmwBBkgS8wCu/oIIPEZ4W
-jRB8EfEYAMbmqtmbGFc/lL2QSxvqAcsUGFlVqRe+Ux9LilQx/84zvD6aG90eTzfF
-pNUHkgBOS7poRbDggVaCSuDYKiyTc07hHNl4iZON3VSiOaXf/4rzbIzv0n0swc0s
-00N1IcwI/pP+74t+tmfH4PUjZwUC6cXHMHSfvImAO2hPMAbd3rJ/ZO/ZVwjNocjR
-5fQj/MSOgl5hiXEkuBdoqoD0lTJMYCwPgwPGNcBr2xeXOKxeIlbYGwh/j3AsK0Op
-uqUJfZ5wvADbdmco+6Piann1q0WvhfmRaie7IPG2tB0=
-=ZbfA
------END PGP PUBLIC KEY BLOCK-----
-
-pub    B16698A4ADF4D638
-sub    32784D4F004B405B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFM1v9ABCADD0KoXq2ZKlUHeIVovQy3gFmW9oFAaraV48ouv8cYvqdf+s91H
-NyqeyNPT/ihFeNqZJUAMyPdwN5xrWD6gxMrOCR7BFhA5kLmAKz4HfFCQ05ViyQdI
-/HVNFvTdF8LNnuF+a5aNgg+jjLvFwzkyMFkuiPGuUDFnqEGxC+z9J8t40tpOTOIw
-tPjSzkDN41AJDpUK/simKC5F0Im78nUbwMalE5z2IsZRWpYZyIhN1HhEdDvaDIh7
-3vENjH7enAjWh0iGRu+GTP/fayZnX0uhmausCCwMMhsr489e63ZOaJrqeC//wWrX
-dtEJjcmvRmJ2hwLmgwMP4zSNKsnLGzP0sh69ABEBAAG5AQ0EUzW/0AEIAO62SMbq
-gIzEFQEHlxNN5pZHd7msqDESILFYFkI1mxlkD0twFWMbk4nMH2VXhiuT3ulqKBOU
-UUNQrO7egtfbGsgVv4bWbUHfeZkfvoWDlmbrvi1YLlR/ZxzGpCNc8e3aOcN3XKHl
-BwfUaco6pcTBvLpKPA/TAjkTOtK4A5Azv1CSwpzSJf2bVVbrn7mi/rw78SmZAV2/
-rtiOU5a9S+3fzswLk1PO/z//d4VoCcL2s2WueVO1Q99kejkE55l3lYwEiBzVuAA9
-8Q0a5wg84vRGFZQWLIw8c20On2+dZcTLZc61ZjnsI1LSnLUUyQ/fzHQ+BynQF9l4
-3ZCPKFIl125MGikAEQEAAYkBHwQYAQIACQUCUzW/0AIbDAAKCRCxZpikrfTWOJel
-B/9vDc3G/mrIHB1P/zl0Fdl5wQzaSVc9JB/ce0018ptplL711af0ZDvWqmZkJNkY
-u0lHgnniaXB0l3GGUPIa/TZzVgFSRPj65FWTMkBbNnhGIwV5IVOPcSKSyDYn9/nQ
-PpmWl5fDj8xiv6kKYxA4hjjRbRGuUXiI2dnyFHuFpacf/Af/Mc0U/CDDuz5a1jS4
-SYuYM/HFVL93POZzwLUR/+GDuVJFnm12rmjGnJVgR0rWcJKJt6vCsBPVfIamfl6v
-G+N4TWQ9euj8Rd4hjsYPOwDfgVIUGIhpTUJ+fz046fkz9MWnX7RJh6hqLAXT7Hbc
-0FTFsKYAbLJbm3Q+rU9jTdM8
-=mDDW
------END PGP PUBLIC KEY BLOCK-----
-
-pub    62BA9C275D14234E
-uid    Pierre Yves Ricau <py.ricau@gmail.com>
-
-sub    FD2D3AEF63B97A64
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=ukU8
+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
+=IUIB
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    ECDFEA3CB4493B94
@@ -10982,75 +3588,369 @@
 =rjff
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    C9FBAA83A8753994
-uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
-
-sub    AFF3E378166B1F0F
+pub    EE9E7DC9D92FC896
+sub    3B7272A25F20140F
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFeWvEwBCAC7oSQ7XqcGDc6YL4KAGvDVZYigcJmv0y5hWT4wv9ABP4Jhzr1H
-NDmmGyWzhzTeMxwuZnc9vhxCQRwyxj3gGI5lYPEARswbi2fWk//78/3Wk+YMHJw3
-/1EO3VqvvDUt39gbaSqMCQNHctnFdb2QYZ7nRFTQeCqG/wyMdB05beqEnWEXzjeP
-FDF9y6gXkELn0lxUm2TKO8tU3h96TCuutDKJ0aE00lOeh/MbEaGHEbIU8kdfui6U
-znZ1X80EWbkCY8cKxEZHKD0aONSVHXwE6nETvFW9/9+K+sj/I7ytlyxwHsaQpi1H
-6aRGnq013VsIECrwkhmXBsLLXNjmhER+LkcDABEBAAG0NVRhdHUgU2Fsb3JhbnRh
-IChjb3d0b3duY29kZXIpIDx0YXR1LnNhbG9yYW50YUBpa2kuZmk+iQE+BBMBAgAo
-BQJXlrxMAhsDBQkHhM4ABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDJ+6qD
-qHU5lFtxB/0QBiKaHHdFu3GOs21+S4LZYmO0bvHASg7ueeWtoE/1cEsKqvES03Tw
-iSfMabaPt+UL4qP9w6/SUtTITAmxuc1ksyU+HwC/R1QuF+vdsguFZ0/8VdVRVY5I
-5/6Dcp7kI49RO0LxGPXCMn8s3Nj0KXiCoodMDLHwwMv5OXWrQQ4yXiQTsJudBxy5
-o2yfp0AlLm4uZdDLj7Z4u4DfyKOuKIUMsMQ2Hk12gSkDaZViIURH6MaSEdC+XbDU
-cPTq27+JSdjfYEX0908P/bH36H2kPCGVh+sXpICZ/Ce7m0OHBfE/pTTCuOlAJvcL
-Y4QbyMTlyPpZ0zFgO+jX+fj8UFi2sRhquQENBFeWvEwBCADfbjqRN1GvSf9VkjDD
-WBqX3hILiPx3DKPiSFmSsAoiLSEkP8gRDBDy6po/Oez9q+bgb9Sk+iGifJvbVNZr
-7+88LSxQECsrVL+ZgTAZ2LkqABQJ8XYh/dTO6BMJ5rSLH/YN6bO9V4NjYod67W5u
-Yox+aCp6keE7ia7eBHck2wyqxikCqvVzmAduPCkkNSRuOwLkOguduXfwb7Cg1Rna
-cMMEfDd9t+a6ytY/8JFu01G++VVxFHO3vs//RINrm0O4xKPkT1+Ocd4+h3DlhhRv
-RXvI+MKeM0ud0OpUVCBKCZqbFKTVgoRpsKC925ZRUSqbmyBcIkqyYjzD1adaZdkq
-4PLFABEBAAGJASUEGAECAA8FAleWvEwCGwwFCQeEzgAACgkQyfuqg6h1OZQ6swf/
-Vm0ndBcvdK0qCoubR/WOsynS1wdQ2rGKJC5oVsUN4YVCZhg9OMhwMSO3EOBPdxtq
-4A8bSZp/8ZWmHLohE8QHD8AgaQBtRZyNkvMRiN157XGkPEBRWdHw6XAvx/lE31W+
-19qFRnAE8BbERE3gieJcG4CKWy5CyzXnjSM+znZvDQ8J7MfG+LxKbr7zUHQH9ZWs
-k8V9D+GXDgpuyZc4ct1tNDLcn6784FubcdrD3RLMiOAYSSgKSgoELRzB8zZds+WK
-FuiAYXZSdzCbjJJ2VqnJnQtYHN7Z5r3ySqbG7w3rRen+Ett6PX9Hrvc1MTy/UUdb
-3s08C0wD0x+ZzFzqUXKTZg==
-=nsI4
+mQENBE/oyDcBCACgYsHtmWmtUzqyr/JN+orfJaTl2363qiS+NJ1lt2CNxUWOqldc
+VcIGyjmzokxTRpGdCFmT1Lh/hzZhcDPLjrtxf+f6njIibt80OiEbX39gjwZRIikd
+Uv44Z7zAGE/upTM87/s+1+M1h9NFHPUg4SOOHwk3hYvCbvde3bZaUDhhn2asrYb2
+wlUbPBZROtFWlxZXHGXsMnER6ZScxK3ckrJkikM5L8tGFrJlBb/lG2vS00lcZDoR
+7v7XtmHqOBxPFf4RIMP/HimGl4lEuBhc25eAt4QxoVmoqb2C4vCUWxwfAURkJzI2
+JU3l5YP0rSgO9rwrXGlTvASCuEoQyPDjwKGLABEBAAG5AQ0ET+jINwEIANpeqMgb
+VzzRnT60rHPxCM40VfwVTYFEspNZV4g9Byb/Cu4UqHtdOApqIS0XQDgT+042x4Jt
+I6OZ7fUzOpN6Xb673LnB746J9cOlDL9JkqUwD/sjFg9YYFMROvhOOB023moPDsPk
+9jSDDxWmMfpr0NWGba4xWG/R6FHAbK023oRZO1BACBcNF59M9y6iJ3Edb6qfiGXF
+fnJrvwOYfGEqzOA+5YJZHPI59RoxAMm7NT1EwhgnD3qw5qCBHBDzaI7qinAy5Zs2
+jtZIEZHlV37CAKjeXjmjCnAnYD/Tlh9vOY9ku3UK5uH5CGxYDKdd5bX5bNmWK2mb
+pRk7C6MSTGX9tTUAEQEAAYkBHwQYAQIACQUCT+jINwIbDAAKCRDunn3J2S/IluSv
+B/4o0x3rrIK3T9WK2Ylvh6eRLbB18fEiYj5B/aWRTYTHJRfGa+Tziwm55stRnQjZ
+ZMC36K7LjPQjqjAW0011azO8oFKFbJnVmmOTUrosVdkxYBdW6fcOXmFcFi2c/M4U
+At6Mb9qg7vVW1DUk5+W5OU3TC33WCBKClb3usf8Uv0hZ5TRs+gt35EWBYpHuQIhq
+W4+1ntttT9gF6+MruoAKy8ViEsPQ/tpLG0eOTc2XjWg9z2wVl0KVKJN32IQKwje8
+RtLK0bY1KEeKXo1FCUVTg9IWDaNsi2tWPL8CLpP/Hq4Qx9SX32Io/3rJxy3h+sg+
+hN0x6m3QjnijzvokolnfxsAb
+=RmVV
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    3E3D777C909A447C
-uid    Dino Oliva <dpo@google.com>
+pub    EEF9ECC7D5D90518
+uid    Daniel Santiago Rivera <danysantiago@google.com>
 
-sub    7ECD484BE871E4BC
+sub    AE7B5A78012824FE
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFhV2aoBCACyHcEuTUn5nVo1ODvWvgBgV8b6Aju4cVAhMNIvAdcOYf+N9Rgo
-Y/669/P371uN2hc4SxJeORBjHyzkAX2sJZQj+FwdvGl60YX9Zv/NQaTzC1WFMRp2
-rb0QGj8yia+WA+If6hatbZmCg87CtDVpzpPIZUzX4UO+DRQEhezflt9uZ4YrFoYq
-PmbL7znqm7/3kpenKrNoinGnzFG7wnOrDfMrBrZgL0Vt95zvs/PBTyE2r4GWCNms
-PH6n50oTck5Lif0EtnIp26o9+vgkVVAFcHLUDy2y90g67j137SNnYu/47FD/rS8R
-A2Y8wRd6lXXxI/n5Wyj+P0Vai5zq6BIFPMbpABEBAAG0G0Rpbm8gT2xpdmEgPGRw
-b0Bnb29nbGUuY29tPokBOAQTAQIAIgUCWFXZqgIbAwYLCQgHAwIGFQgCCQoLBBYC
-AwECHgECF4AACgkQPj13fJCaRHwthAf/SihiHP9sr4LRSw3TW9t1CuKW2e+DwsJH
-6BY7m64jENIKF2zXWuMkHzGmM9pVO6qy/hY610wI6GqppuPESaFOVBc4sp5i6A5+
-Z70ZzXVEM+rfjS65qAbz0VdaF6cIEcZrJ25DD2DYLMq9wMAWo+EqKyiN3OJ/m/3t
-xz4WECkgpAgIPdfriJ1mmkn0fbpG1Hc7uhwtg0EfcAc2nN84AyPlBbh6RMkKDFgk
-K2/zwsdR6t93JzexVEXRN7hiNqBu9rFPbyvXy2jtoO9P60vlF3OuvM3SCqAr4yYL
-l9Vlkh5ytoZW/XPMJMOYsullzk7q2zSKIOPkx/Si7fqKz4MqZzc7zLkBDQRYVdmq
-AQgAuTKXw+m5HveJjH7uTGdkmX37rkOX7Kl6cyPutq21tbG9cGhrOplTJN9lDoK9
-7km2YOs16SGVlKTEQtJ7CLAQGRLW1qPATMlW6gJ5+KAAY1GFej+DZOLYy+RjxxdT
-+gDSIXt8kQwAlETwSNgymp53TrU1dDGPMjod0AfFbawJtxp/gaI/Sb+MkzLRS+NA
-7g1fDNAsy6twjxwmL5lvCUO+JMtlG8vXlIoiP7N6hXk4PYzYFCI4JR1H4aNhIBk0
-4MoUngJj2WNXfPJYQef3DqAJrzaQpuiCdQAq6F9GgldMHyv0ujHpA2JBikcxlR1r
-dUdo2Yqnc90pd5KB6IO4TfN8twARAQABiQEfBBgBAgAJBQJYVdmqAhsMAAoJED49
-d3yQmkR8SNoH+wRfWyXUFPVDNN4UrAi5HEY/Ca10AGuREkzacZSVz4dYtofNOAxx
-RVfOAoZr1NUECNvWgyxIZ8ZkeQi8fGN8uS3becIVAWmkji8l9jDRpC3DPs/g/7wL
-4A5VGzvp4GdD6jHk7KCVPiEk1DzRajI3sAntmpTKL9LNB9LpP4NdWiFA8TPMEHIg
-SqMuv1Jzycngjd0Zr9joSJvhIU+j38FvL/F+l/ooa7TKpRv6f2eAlyls0K1V9bUh
-a9KhGsyjXqolyxHZ25Gc3VnxEKIZS6R5QrxVbnXPmd/SV6MI4fBSrcrNgR91iH9X
-r1elbwcAFltomc9/3/7xXmHMaEfaxJnY5mk=
-=geV3
+mQGNBGFUnmoBDADItKvcmnwP6xsF7EnS+gKxUBU+M+x1sdzLJGyOL4laakwgUx3m
+RhKwDfT6tIQjTAVpHpORa2LNYikoYYodIHshTuwN9Gba/pybeRdazWguOv4pizTx
+1Nv/w72mmBVfnMePDlOV6GWbQpOgDaufLLFKumg3k4HynWlENlitEKLXjHRcEF5L
+xeapD1ZzIUTUkyeYJSMO5XSDIsCkl1dTF2PtqCRYuziMQU0OpSV1+f/SLRze4ftD
+9Qy8ZRs6O0u4UgrBhVIbc6Plppj749qlMPQf8v48v45VFxfAlGD+YpYTnas4Yy/s
+p5AKaTQdAZciiS6icv1PtLKhpbqxTrpgnClSN1TRecPsuwAcF80rJdFoIS8vMHNf
+Gv49mbBxmetZPvtvHL7zCpnUIdi9M3h1lrlzalCHxTgNAr9uqWGgvdS6WGUzy/bE
+5K8QOR1JO6VSkUiH3HX6GfAl+mrwpur+lwstqqgf4mwbUd0R4XhhtjjcjmoMKz+I
+5kv9BjtyqgjUAfUAEQEAAbQwRGFuaWVsIFNhbnRpYWdvIFJpdmVyYSA8ZGFueXNh
+bnRpYWdvQGdvb2dsZS5jb20+uQGNBGFUnmoBDAC6WvUmMjF1YdDksL07dTQQYHfJ
+Od3bGSVSPxW3jojk0PPu0Hw1jDpctZWufnO5fsSa8Yn1esrQUoJakjcvWy0KFeoR
+UocRz0U8BS5/RrvxRziQA0mYMSV7T+/oNVN36FsjDPuhNG4lJwyLuYjt3hTjQsrE
+lxTVpZsouX6K79bAE8hZ4PE1D3BkqjAMuBfc0zgdxy7EFINIzzxRFJITjmoqQAOt
+7wnn85kvVrlEbIxfIVri/OYSQQBqyzwTMCNzMUJYDwQXi99uVV9M6JbICta8QlMv
+AgC52pXG3XLiqP96nOH0VBFYt+aaOSBzqL59eAtVm9pwb/4MgtMdFuJys40SB+df
+scZO/xLy8qq28WIQrKqRXTg0fVLTi3U7//R+NTrUHejEBReHBHWiXDSPqsoo55kS
+FOHXFFbnWjlF1ZXPCt+lAB1ANpmKkzvMTmKcGmgcdKqON6rgPT/3zMhK8jQrRGEU
+kjDyIRcg8ytT4NJOi6WEzEyjoq3or7mvRJV0zc8AEQEAAYkBvAQYAQoAJhYhBD6z
+hGs9wATBOIN1PO757MfV2QUYBQJhVJ5qAhsMBQkDwmcAAAoJEO757MfV2QUY2CkL
+/375uJL5U3zNV16wQaCWEZGRcQletVrV7+lwHijg6dIxritQ4Sj23CP3LW5BXa7J
+rIXz2Z0+uAuBBE/7pwjMjfQLjYncatdcwjoTU2uGezHnsOYT/PXr977QDX8TME+9
+Q5Gq7HNhZVtDQzLDgV0IMBWJ8UZMHZNrFZTgu9LmPDxqVNPPgEvPvPlxm5C+/a8j
++z4oMtWKAnRpmTFttZ2paI8mRygZgJw7YJMJTVxDQ19pTENyNnmVAmivueb4yG21
+LisKpEVPlv+6x0427RIb5/DoJSoYef4Tz1G3BdD+WKXKIiNwN6N9kLR2PcbgkHzA
+i8q3R/gXUcwpXwhjitN/ZCRAwJGyu24zwjyBjrMQkWvnfjJ/RG3YxFIo3TOGx0Ky
+EEMBm7mghtfL61CNNJt3K5wPjclrO2X2BXVgq3APYmK600sy3APe0pMHpKfMsTxA
+VHKtnnYTwSusCep3e6HwsCyEOTMW2yMWu3OuUo9X2RPbjzM41LU8iKML6ecd1fe3
+uA==
+=o3wx
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F1F111AF65925306
+uid    Luke Hutchison <luke.hutch@gmail.com>
+
+sub    EF375EEBBDEFD775
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFS2J+0BCADZI8RYk32YeO9gnEkY9RN+4dKb+H1AR4v+IGxmy0UYy+O8bo4m
+YzkQHTlPpEPGe10/quKk1embDifEfNa9mwcSJl+XUPFlTrSA97SR31mdyK/Ua146
+GKMW0F6v8aCgLUlm9BCJo/OmOat2jsc94SuKnPiRRywhmapte/8o9t7/0GghqLyj
+X+Ifz4WSKyKZ8oe9mRFg1ZIA+z52a8QnfyI8WS8bpGHM/dXkBXZpzIDlrfKvoZYb
+I2DcbOotJK/ZzStAZ81e4E/q2BEw96NUKJC5X+G8qahEFNJDcJz33UAxLiTFqWmw
+iKLqy8oL8p9qPYlx0IAXoW/GxV7E0rBoA95pABEBAAG0JUx1a2UgSHV0Y2hpc29u
+IDxsdWtlLmh1dGNoQGdtYWlsLmNvbT65AQ0EVLYn7QEIAMde+nVUcozJy9dzLCUp
+n91SCoWld/wTaSckxTnVMcr4uNLlJI/2PFjMb9ya91grr1yuwqSG3jE8P0Qdk9Bi
+6t6NkMIGUSJuzyIipsDDWaiCfjWxs7seFd9c+rgcH6r9CaUbNRfUrPqEZSeL+RDw
+IIz1gQkXmosF94DjZHP9abZYObH1/Or64CSRD8Ocf6kTRndwJOZkRdDtUX5NPFSi
+U17E/DoEkyryuXMR+Ci0b/hjQ4JnriGeyy6c0StWQUW18SEYPV0j3VyRRUcOLhJa
+jEu8KU4Xaaxgb/2X7o/BosjjQ8BPPUdTz2wRluU/1tKUQ8D+O8QH7dCR3lJt76kK
+WbsAEQEAAYkBHwQYAQIACQUCVLYn7QIbDAAKCRDx8RGvZZJTBvJ/B/9vrvZR1pFq
+Dfux/ezze7ovgYF3jkxfQj3Hqgx1GvLYdvNacZiJG1bfGRuoEvLPv8lPIfEBTSqJ
+GxzRiEl33eUUXlatI20Dh4oeRYUE70hCfqRn7cqITJ7nXwctMZGtwSLduNa4+cjK
+dSaWq6kffpQVSLrjvJYyxk8td+NvCLYiTDnyybAmSGge44RppDjwGsQ+9X8wyd5b
+9hwcBQOY4UTm/6RPDJF66KPlPaU2qy8NeQB5AcO6goAdGI9WwOJuxg9IzULwpCvR
+YB0chLKkGOBh0vuyQbHoRmI6gs2K/I3i0q8Df30ObL7oBALsr2QfkkKatq4qx+xU
+7QMdeMs8STRj
+=9jjG
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F3D1600878E85A3D
+uid    Netty Project Bot <netty-project-bot@users.noreply.github.com>
+
+sub    1C9F436B883DCCF6
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+WASB7yEJYwsl
+=qHo0
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F406F31BC1468EBA
+sub    4BB1ED965FF68B71
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFmnALcBCAD1KazT9eswNXzML5+M72qhdIX4VlJrrOzeiQtTW9vbXj7DZUnw
+U8m2bNmKHtpnyXQ3Vl7FE/e8CKGUVKmB854VJGDSyjToeAnt8A0Lg4smaSfgbEim
+rVi6jkgSCjzvNFUsKx4uOCkI59lbAWcww1aoQZcjW3D0ZTrrjo5ilx/zNXbKMfX5
+KosRIO3OzIfHYOjsmbLKj9U6pj85AXJ3/aKuRMLbFvOE3KZTxKLhl8LsgSgJFg2g
+XFKOJeXyRHCLTlsRB2qD+jAXeE0f7nTQ3xMnMUi9U2SN4WuYxxFTtrZ7QyIze0/4
+568f0ylZda+3j/FkbcZK4KJEi11kqS/ph9UNABEBAAG5AQ0EWacAtwEIAKH79EfC
+C5z/pkDx9MVSnoA5WAYX20KL+ErpMnaRbwzpizQeQVhqDjiKGCk6qyC4PUUk+H3I
+aYuTQN+rABVur4S2sO6AyNUETpAMNmrZNvClG/p6gnlYml0vzvEKtsa3U88rTTWx
+fzoecQs0UugkUrRuJI4XJyTMgRuDDLClH7IUjkrUmw2g6EzlDVdLczcpLxvP93j6
+I8R+DwDwlCX6Nqw5Nnr7Q16n9sPgDthJAF+7VS7xXs/jeGROFckdrolrQGirwbfa
+Kh4k0gfSJykV1ivuKx7QOWN6bYejph9DXD8oxE+Nne1y8tfNZFw16i75y46zAVqr
+rKY79Pkcr4RgP9sAEQEAAYkBHwQYAQIACQUCWacAtwIbDAAKCRD0BvMbwUaOunu/
+CADJcTU+K/cg8ItaIfMWM+miuYpoITqDiMpMw+2RkUnlXwn1ouZP0QP7Cpt3mq+K
+Ihei1JIRKR5+XvMV5h8ffvDy6gKpWdsUFadyLMNY07/HVtE2ydUjDhPo5vb2AWe0
+9qMZWef1/hQumkqqhz9Dbs/L8QATpnYVAtv4QMKFwDAXYCgnBijZClYwwhnJwJ3U
+rPejhP0MQomdy/li9kFMlkp795s0Ng5I/BjkFYg/S3IFQEHsgizPclibJdUR8P2C
+GXOcxXB5dE7ykv51FxMpcpgd6jnK0XRzWwQExelrRb5ys/D7pDiJBuGG/u4Hykbm
+LuHslpPWYJ7ZOeVf01xL+I5T
+=dLR3
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F42E87F9665015C9
+uid    Jonathan Hedley <jonathan@hedley.net>
+
+sub    6064B04A9DC688E0
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEtsF2oRBACcai1CJgjBfgteTh61OuTg4dxFwvLSxXy8uM1ouJw5sMx+OKR9
+Uq6pAZ1+NAUckUrha9J6qhQ+WQtaO5PI1Cz2f9rY+FBRx3O+jeTaCgGxM8mGUM5e
+9lFqWQOAuCIWB1XPzoy5iTRDquD2q9NrgldpcwLX3EVtloIPKF7QLq72cwCgrb5X
+R25dB8PUdZKUt2TtJbjB+SMD/1UzAPirgX0/RpL9wUR1i14yIrTfpFP/yM9PE4ij
+qcZ1yafVdw64E1k5W4k+Pyl4D8DvSJvbJHvYjg8/G9V66WzaKcv+987fetUuePvY
+/rwxBPztqq8y6+hjBc8QVhZGWmAoGGEFO6MIGsSyN5ohqPMpNXkczIo+NMvDxGzz
+ld5ZA/9awGTsigBdpBK2F6GOmbvBv+Xebu9rbaJvBvP+npNx01s/f5sHPCxmBTFk
+m1vtaMdZ29RovrWPSZRj8WWes0bcisw80250r1CBlYzGzqEVZ7b0Hh2RfkfaxbYh
+wikyfTfA2iX8TUGBgirsZbyegjUadElhwFNDASnvLTEuQKeVLLQlSm9uYXRoYW4g
+SGVkbGV5IDxqb25hdGhhbkBoZWRsZXkubmV0PrkCDQRLbBdqEAgA0sZ0JZvWoKIG
+b+o6MOwI6p3uMb+iWBwdYfoh2RPnUZdBwGhJjp32CiTt2Y3qYEcqC5NvF5FWdx1m
+5KOQe1O+QFoqPKnC1bPj9uZOjLVql7x5tSwCePIaMNB+fMxEh5hYwLWtBz8nrdCP
+gwm+nAwecoE8YfrpmrXZk/YLak54FOeEwLYaP8E4u2FHiEqN+WmKMjIRwLzVpYAr
+WRCbTLhSSKyRBy7UxEovUH9mIa4YuU4Pb2R64LwopMHCBm5ow0U8kCw8vpW40GrB
+c/2eaIeXCX2XJ77E9s9ZPgW6MoJ6Ic1xV6voLJKIEV8t44deKNSwDfVNZHxyemaK
+a8/GgpjU5wADBQf/UzL5lXRmyTdJqRvHIfUV3g4A3X77d3vOroab8KKw4MFy2LiT
+ioN7btKKxE97Jjp21YZFd7Kpmfu2i/kr9QVJo+DSxe2p2xcQozyS+layPK8h/61L
+hyh8vjzV5AUWA5Zup+P7Jh/WRlh9Gxs0k0vimYMFKImw3mZr4EA8UCj2e85XIHNH
+Bd0B1VIukq4OjU4QhRrutNebIy3GZ35ylcaXT5v18Rq/iRJAuJFoCzXUaE90/V9/
+2ob8A1CYEKGLocvOQgBsj7+2gP5WOP+WxI4TWPENRKMVchVBE8zV+7YZiahPCwOQ
+r9TQWMaUIJxZ85yr7O8DhJOBX3B7EHIfpoADXYhgBBgRAgAJBQJLbBdqAhsMACEJ
+EPQuh/lmUBXJFiEE8xhLzVX00BbjDUyb9C6H+WZQFcl+zwCcDKIILbGBUNHRGY57
+mmZ5xKMWbCsAnRbmM18GlK1TKRcOcqqEPWSusurHiGAEGBECAAkFAktsF2oCGwwA
+IQkQ9C6H+WZQFckWIQTzGEvNVfTQFuMNTJv0Lof5ZlAVyX7PAJ9ztvyEP04cy6zP
+9lHt0qXdrucDfgCgh1OIUk0pFzNYBt3PXvOeyD5FQbk=
+=dtK1
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F6D4A1D411E9D1AE
+sub    B5CB27F94F97173B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE89LqsBCAC/C7QToaRF8eZgGOxcvp9aG+mFFCMjaRAb4Mh59OYdmUb6ZjfO
+9388HPebGbPNR8SHYs0dBIuWY4ZJ7oUTYPswasL8vB0iPFdyHhvkCca+yk0b8ZBM
+DmFlISm9HkYpoVjcFUp1oivyeJ5LRTJTd5JGEd/SWFRbB4TimdKXBzej9fIm2zVl
+KInEMMd8HnSYE6nm3aNkbyiqhx81bFvl8x6X3ZMWcKs+TAVXdP9uLVvWowUwcApk
+xpee442Ld1QfzMqdDnA6bGrp8LN8PZF9AXQ9Z6LTQL3p9PIq/6LPueQjpJWM+2j8
+BfhbW/F2kyHRwVNkjaa68A544shgxJcrxWzJABEBAAG5AQ0ETz0uqwEIALmEZ0xN
+tuX1cLsNUzzq0HVzwDiw5IquPWy33McESXvkaMyqyQtYisW++dY06MxBCS3uV4+1
+nKI6oA7Lk482ixwzbwws0Rb8H5CeLHDEwGXfthmLAvDdxoNCUYAtpVOMGcbGpy51
+TG3V9i9JWe1px+kvhieX9BLfDzP4Pldho9lK2gYRhmpPDgUOjYZgiQXMmIPAYfdH
+IA/VdYTETC0lu4Adb56SzOwvGMpnd3rXWUiJbZg7lW97hvbOFMKudbNjBCrF7LhW
+Ah089MU9rvunuz7mquVdNtfEBkdVrqZJdvYiFBee4RUe3+qGCpHnLzynOGHr+iIt
+DG73NR9fZCzl1K8AEQEAAYkBHwQYAQIACQUCTz0uqwIbDAAKCRD21KHUEenRrp0k
+B/wPuP2W69oweOqtSRDf1FeFNzAUIjbwjkg/bTjzJwb1cyedx7rbxhpJmn27W8A2
+WjfmDLOn4orQTKoxf3kP6SeeGhYLkzxjBa5Rco89p/6X35By6VR4LPFeTOACyE7b
+cAjqPFb+7t1YzvnmuZIgpvTKickq1D9g7+JT1Qd9nqBFKlg8aMngAooVvlLXaPEw
+Q1XfkfMN+ltwlEr7o1ts/YzDUxflaFVg0FnN7qezam/s7VvcK46rO95yQr/Wyz2o
+VDzc34e+Nr/b2pN05MDHA0dXmb/irwPBl0mTOgAgC805qkR14xhd1GeL6MEA34k8
+2Sq/O3gWhBaB3KOy55/lvvKp
+=CmMl
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    F800DD0933ECF7F7
+sub    592C39141EB02A78
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQMuBEvQhhQRCADQ2MH2FpQD7pbCTDJ4uvPSeaOz0IUhkX9bK4sKvIISx8MbHhR4
+k4sXi+vVkLngWCMUV4nB4WcCibk2S184SzL0TstTDrudxe4eJFVbmZw0GrgASugQ
+aD+8daVhMgQZEjvEB7kjaYzMyljzVRE/o30AaizHPMVytZQpIL7GTsaBcGtxLkyq
+JG+SF+fN3WAKiMyKCUTaji1owY5SyZIbPBBHqcIQVdtCFRPXhLDNnGHUz/ubI4Fn
+U5sN9gEe7raXQfvZzwS6fW2SaxhxMXDNVDEipY7okuRKQ0wPWqcanh9dri8qoTfI
+7MOqfWWKL3NF1hnjuutyGTTKCllyTWEW4MfjAQCJBTUh43abqyHej9Dzcc2lSgLn
+xeN5iM48tYZRv+aYxQf/b9rWigbReKL7iYmCTqd+hLfh0YDmaJbZ8ZZM4p/YZ5tL
+NdkNJR5TiWwH9ub0BvXYOtYUwclOaaD85CKNN8IU+A/YcrWP2O8fBQw5lqARuGx+
+TjG7c+WRVn+fLrTzrzbUYh+/Jg5UYCbDYh6H2kLKnPVQPzSjDScJNtevFnX+IRjT
+7woB/WHlrfvowZGO1kclypZZS6nDiPYhEk1isEU+nD7OvvM1fQN1rdl0QhkLUh2w
+qKiM3xvY42LGicnJcxyMSODkYlG6J6OE2sFDBJ1axa90+S8Jze1fBlbQVb7OF6ma
+31mhOedb6xiqJ17/5Kx9gPEUpVMpkrDUVToIv18c6wf+J2TJ1sdMPqUsiuKHDQq1
+elTxtfq5ELQoNlnuK+mRrsSMfa1I6jE7QbZkCcoTNnD5ikOVmkHJFQlEZsmaKCrD
+oUpEyELdzFy1ghfGDPbvv1a5AoGVsR+sj39XNckBgZS+25vZupBxWvTd8Fj/KY5l
+a1aQlPUyMgqmo7rdE3WEzv7v11xBy6wQMAoGu6lp9tnaAE7sPEy/UHuYSexCO3Ar
+83sZ9o9ZQa+z33QU5Z0guNz+efCkFfG4nqjHjZ8ZY5VvWlw0W2gxNqzNCeQR7m14
+C4J2TNNn/F2nGAKEpKEgp8IjpEXYZ6kF9xoSkJ07bjujvf5vtvAm10h+ZEumKSiS
+mbkCDQRL0IYUEAgA7Ci1jY5JdrLs7pKjhbqP1lkZKDRn+0fDgix9y2JP2O0lJ6Am
+SAVUE6Mi+izqV97q3vMmOkIuDFLoBP79/YOaDlMWAj9QelNWwz30yT6LB5Wgw0c/
+Tpi5lQD5K75L84u2vAFjoOwvnLx3cKjC7TG2h7zxt9EHEtLFAFP2JBtsMvcmpFPP
+Ucpv0+/RFLhRV6JPxEUKiVbz52pgBLSa83vtZI4d6CDu/W3QXvCw7uYoTWx7e0+K
+rrZj3LE7KUzEa/Vazsn6Nwhi7VL0irNOZJGALdhrxLA8iGnPYDys78vPBWB3k4VQ
+G7rgvdVXiAldMNtoy7sNuhtI8Cicgl0JG/6flwADBQf+O8kWSrda5ezDK7vWAhBh
+r3tEMIE08eL/HPErE3DOzud8oyV8B7Z89ZOjSqzn/6EQdnEGnVRr/isOJcmgAXQQ
+RpJfFQ4dnpEeestJ5y5hzrtbMvfZ/Wms3WFgjgfYl5+TAbSF3Gz9VNn5AmaeA18i
+d8qzNVQ/e8J9zXfLV62qRLzbAS74K6rzGpYaZEWFAid1KLTu0S+I/ZuvQfZ83jyq
+oenwS0iYawM824w5oCDN/+8cDzLcHipN+B6g6S+X9m8s5E3RZGVKqUjd+fTRg0LY
+JkkasJwQa+20AadpCE0RZtR82jrbyLfNY2FFJT3TKYnaVhYcjpPBqffevhwSRIEs
+KYhnBBgRCAAPBQJL0IYUAhsMBQkDwmcAAAoJEPgA3Qkz7Pf3m+4A/RghXcZwWrZB
+/vvvAfhkYQeQJjPmYluGNebJ4wPi5ZI8AQCBjv2b6yDTWPenmPNeSB88HWjSL8/A
+mimEzF5VTg7GrQ==
+=Q4rB
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    FD5DEA07FCB690A8
+uid    Baptiste Mathus <baptiste@codehaus.org>
+
+sub    5F68B9B2F1725F16
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFFCLwoBCADxtcGi0nfolr1kGWe3jQ7n18roJFwBs4Q52nx0h4+a8ZGr7/1E
+1brakrz3t/cTSZIrhfru8kirP8cJtXBxpd/nCeRrB/4ZtXPUJiGwKx6sVGr0ix6U
+eZKQb3anH3jdGTzZ2csqt6Ro85SvIHfqAREcPOoQk7Kz3DFOGbSfECN2Wf1pTnRT
+jdF1Z5DkoTd8sGBmGOdhNMzgqMTHz6np6M2B/JVP5DpcKPbbMhQ75RPcxNEb4QSa
+HtCL+gMZiF7fndWx2Tjbpanbb5+TomfWOMizpkyziyYeUmGoyggrnXQ4BMlzsIuK
+ATz6wA5j4qfRLfoDDgNv5UacVAtWL+rlTP8NABEBAAG0J0JhcHRpc3RlIE1hdGh1
+cyA8YmFwdGlzdGVAY29kZWhhdXMub3JnPrkBDQRRQi8KAQgAmiucGnaHWRi3QQAH
+EYPa8Acz8vhe2V3cEANZB6NGesYUCT9v19wv6xIClufUIQS8hDATxC0bTub0wuVG
+C7tKRytF7DhGnBVU1hkPoCxqdlJEnACRIAED2DTVqwM9DKAD0P/0VtgcqYflgVbY
+Jz9PZ5qv1nF479Lc+xa0hVvwNLgA5HBHVhseiLTYh0QGQYDuLs0mPBlMNmEhAYwI
+pQ8FbPyX7Y+XZSZcCCcwNFczSBbpysAU4nDB0kh0TYnPs5cTDrNNmt1ytzQT7/Wu
+QyH32blPeue6x5mTPc2ktT8h7DG6WbMvoRbcTBX1blYqI4Ot2QuXofQv4ISgiGz9
+Bfi/bQARAQABiQEfBBgBAgAJBQJRQi8KAhsMAAoJEP1d6gf8tpCoHKoH/RBqM5x4
+DsH6IXFrIuriLi4LE8qXdn/szwGKYMkj/CytvlGQZ086Os8bVgdGWQI/CAnXIlTn
+XEmIpv19vaUc8oCmAyaR4e2b78XgfW8YOxn3fDJeWHHX9cfC/z7IvJGo25DHM64Q
+pcYQEe+mao6ZuoL8onvttX+qgJ8fQfieY0KTeqebi4NQHN3VPpGPTCSy/Ksud8l8
+SR33BfoTKAFWT2o1Nn88koi7bRDZ8VxyKiYmI/zed0SZnEHWCzY0DcH6atNQyctJ
+OZ71wxgmZoFAdk+8NbFSCBdcNLDMWhMvG5cQfo9uW9yoWGHvTYkLyvv4LYQ4FsoZ
+B7NlACz0MCH3fYo=
+=PlCZ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    012579464D01C06A
+sub    CB6D56B72FDDF8AA
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFgnlA8BCACVtx3oLXcanfvwtMRwal6pLQ8IVMG9+fr4xGdbSHXCRNbosDa5
+agU7WeQMPhusSxJGaA3w7NOdjAwD/LeHADhDPeI6llJg1Fb3EyqH0NZaODKU/Or/
+dID/i1onAX1dE914J4lf3XvIAxGiAjmr3UvWO9RiFxRUkecMAMlCBp2FuHuvxkcn
+Mk8q9dP9Ef360wu8X5rj0kgP6vPhgl9/RhuPsUxlazb2Kn9Zxi/RmDKDiH/vDuwy
+WdRGFOR1OPV7l3Ws01nrs4vKd2v5rsUmsjvQ8ldxdrA1xzX4IszHRDgSC9PI8ItZ
+1VlbaKjE0L03acPfFTg/wRFSF5zsrGNbTmq1ABEBAAG5AQ0EWCeUDwEIAMGWqQT5
+ccT/Q1OypoOQGEZn+oRkgEdnzt8mjo7aOXd6pkNTkt3+LCkmb8Pp3/a3iYEfvSvB
+Zbb2JbY9xnmM8jBucWnow1iwEPxGhUuu3jlIpRsCwLk+utLkMALRkooXqanDoVRW
+xuVeFYN0as8nndgWiJT30innN4vfaR3x3E6/nS57zp5IggxZYsXTRHb25kaof9lg
+lHyXeypW7quKOP4SeES70PVVUnYZBlLpnX8a2msRtJiouWxCv/kHnYsjW62vc7nq
+vWAsSsfBT61TVx7yI9CckVFBnkpG1I8C9WpfcR+j9yauptgUMfrfDTFg3Aip7czM
+SoL4Jpu7jBcXy9UAEQEAAYkBHwQYAQoACQUCWCeUDwIbDAAKCRABJXlGTQHAapGT
+B/oCoCsuJ7617gpcuEAXxWTBfcXKo4z8ObBek2RUh0AY9aXjRYSzwwbtVFRC01Es
+r7R9b5ScY7W1TDQBKL0OSRZ3jwy7/hA7k8P7xAp3mC4+FdHaHMH8nGz2IbUjGWl3
+Yp01NRn4jc8gcnHnqcUff7PXsRMUtJ3dnbsIYOrBAbWKld07RVEQUyafgUfdF9cx
+e6P/slSZxATJrlIPveB5bgcVDMMw1UQNqJL9LWP2IM7xcljOBHY7jqwqnQ4pRER9
+2VzhLdtsdwF0H1SuERpDxBAuibchMoCfQ3HER+K2mTUoJ04xog7MQs2aaMwSbem1
+LMvNBZ/mfF7QMYfMV2n7rbIk
+=PoPV
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    01D734EE5EE9C3F8
+uid    Stuart McCulloch (ECLIPSE SIGNING KEY) <mcculls@gmail.com>
+
+sub    C753427AB202DB9B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=Jcla
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    02216ED811210DAA
@@ -11087,1203 +3987,109 @@
 =Lmqo
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    7A8860944FAD5F62
-uid    Sebastian Bazley (ASF CODE SIGNING KEY) <sebb@apache.org>
+pub    0315BFB7970A144F
+uid    EE4J Automated Build <tomas.kraus@oracle.com>
 
-sub    C189C86B813330C4
+sub    7CD1B9BD808646B7
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=Q+g9
+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
+H08luQlLBaPcEJQr3waLDn+10bchvXI=
+=yLvt
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    66B50994442D2D40
+pub    0374CF2E8DD1BDFD
+uid    Sonatype, Inc. (Sonatype release key) <dev@sonatype.com>
+
+sub    F2E4DE8FA750E060
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQINBGDoYisBEACqUDZnT4h6ma6XIzdC6KR++uDbR2VKdhCuv0Og/sHEKkm6ZbG0
-OFB8tAaQx/WlsoQyf3DlLfUEOGDai875Aqor3fbM+E1hrZbQNfsOySKEE52k7PYe
-0qGWlnAzINuQaEuZwNw+pjZqPraMlwc/hwzJB8yFNHCv25pCFohK7KXvFGr5Fc6y
-NHBp6pM3pnDQ1kbkloDr32YZY2LdrfdkRqwa9STNMcZtM724aaInValFpVGEHolF
-dklo9MIsMI6mVHlxi6UwFSSLltUfTXGYY+rt2Q2sLNnEKzK1GvVhK996vrNWCvpr
-cdtbTzGE3WK4f2knhqzlaX99OLmkM1ah+p2EkK7HgWM9oEO7SYpNxKe/F/QfRNRS
-4W0aokPsEtfKCD7vQ3cRWQXdqFwvksilv+b6pcSrwfAsaCzVuhB3lcIra4MevJcH
-ZEbPrfGMi5/MIVtLayglLHSPoZtjQBhlqo8w3nuADR/aFlIUZ6NGOwaz5yXIGVEs
-6E1wiuILRAd7ecJ3Zyr/URHjawfHfKMM2tNCJKl48cScBMY61FJ1EmYzwhDw+at5
-D4pCk75eM5/t6VdYQ1cDWm7J3LGXEANMU5aSZMqgVnb4SQEmRxkW7oq3Z+GIkQQf
-Sj4OK6Oi4cUpM7b0m7Cbcsoqb6nD27VKD3J5KTYEq3e+78h0VRjhoi0Z+QARAQAB
-=UUB8
+mQGiBEmoKU8RBADEN0Q6AuEWEeddjARAzNXcjEx1WfTbLxW5abiiy7zLEht63mhF
+kBlbyxEIRnHCSrPLUqY5ROWdyey8MJw+bsQn005RZmSvq2rniXz3MpcyAcYPVPWx
+zgoqKUiu+pn3R7eldoDpMcQRsdNbK4TOFWNUomII70Lkj4u/DP9eko6xowCgvK/R
+oRhshwRoxJl1LauUFuTeVHUD/i5DryK5j/P9tv9BWSb/2Jji6gbg6Q3MThZ+jCTi
+leOHR6PSqajYphOFaA8xVWQAkvbqfSps9HnmdFJ37zxOn2ps9d1L8NLoX1GMu7dv
+UZkCY5hR4gwaAk5YpyKa93NpaS5nX6beKiCes7lDy7DezjQLZVbKI3Vsd5t70eTW
+tD7JA/4lGUSkole28jxo4ZKKkGMFnAXkV5mWeOTz14BibW7JqhkiIpckDfyq4NjK
+ts1EzMmnXmPkB/u5QHHe6fJP+Laoe//gP3Y5+xlnAsyI4iEfEjydJWiSNx48c/2l
+qCQ/wdOb28xoFavdCCBavqSKXKJREHXul1UGMICpu3rq9EOk47Q4U29uYXR5cGUs
+IEluYy4gKFNvbmF0eXBlIHJlbGVhc2Uga2V5KSA8ZGV2QHNvbmF0eXBlLmNvbT65
+Ag0ESagpTxAIANEHh8lujiAJyotn/aMY57BpYtWH3ia5xAA9CsYcMwHzvXgeK5OY
+Ao9gydiENr0IZxa43AnZ4WoJ96AHLX3OtXJhr8jdvfEHrrHpH7sHgEgrlv3VYw2H
+ZSU9cmfv+yviC7BSrQqa6LfOwSaWizg5ZOrCG7J2FAKhCnRdwa8ZOs2P0/Pu6asB
+4G03mnVaR62ZShntFx4iSWlO78caKUQbB5OgK8oYA1k9YA4EReSwZMlKWpfGOqgw
+HGw+xuRkXUObzlhaTWvfXgPr5RsxZzIviKH4EXSfdiIp2QzqZjM/drmfIx9r6Ai2
++c5WKOIyt0WaX0HWOGsh1t9bBPs2FrrO1H8AAwUH/RxVVWYuO20H8oR1bp5zkjof
+wgWk7t6NSXZu7mZMZwqaRgx7gXB89Dq4jALw4xXsAWebgYadReWef1ZSUlx8Lz1M
+KOikCAld18lvqf/lfvrHi+ZHInNzqYcAdamT2BKoXHhIIR5jf6/8Flf/FsZGe0sN
+QJw8Kl0yYiGYWhI0VV1CIzeVqSDSLLM/g4xZ07u+kt7/VUjo05lFO6jyCNxIO3SR
+IBNML9xNXfZSDz21GtKW2ve9+bjC6qEDa0/O5FykoyoUFA9LuW7t05i3T26B81AV
+mB/9NMxKHcJI1itU8We7L+IAvKC106chw4SxhXYxa/G6fxTNlkPSKdcPGsdFALaI
+SQQYEQIACQUCSagpTwIbDAAKCRADdM8ujdG9/auQAKCCtFUmslioIPSjZkWVLJpo
+77IquQCfcgYbAHsCuMFkHkZ1oZQA/f/ku6Q=
+=YmFm
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    8E3F0DE7AE354651
-sub    D3047B0BA4452AE1
+pub    056ACA74D46000BF
+uid    Norman Maurer <norman@apache.org>
+
+sub    DECB4AA7ECD68C0E
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFMnpeABCAC+vckg+AqDG5Sg+GKbA5t2knu72aD000Qle1X//SjTvPHz0L1v
-rUNzwrqlmah17usczZHOoOCaGjSUFl3nPmBEOlLBh6L4+e2Av8PSbP0qUneaQVgi
-TQfbNgRB4v4H5dtKIglK1hZwCeqFazuRuFDWLHl/IG4ymcMwy/86y96BJKWrW+Oh
-4vK21DF/BRhyFGaIGwN1aPYRofy3ERsUfwe9WiPXXuYb3gvG++QuiS4V7UJwcAkx
-5TGukoatI4T1PVmZPk2zmeM2pHQRisHAScRt5YJ9bswgBphk1xHoENVQ3BYhzrsu
-a3hFDY5hO+UQiT+eIE38noOuKuSbRalSPelvABEBAAG5AQ0EUyel4AEIAO6MSdr4
-Sp59Gb+J8t5o5g+f4jMJPm2v7BkJzldN1JISoEWeo8iyCOVcM4D83coihMfN5Nwi
-7Tuc4tnZH00+XxYFkHMOLMPtCE7l0Ai8mVhFqE3HraCVnk7gRzNCyXeJRu+Q1TSN
-4QbiIEeonBSoGsAYafkAx1evBJtGmrDv0Y42NdocnACyRPZD0usxMARk2ZwQaqN4
-Ih5pL2MGXqMeo6uEW8iIIumnkMywXyZ0jbAcZSs9Smi3AdU8P/eY/Afpu4nyYVAU
-Sdm79eMjcBHRluvuk7db3mMzQPAepWQSYOgsbWq2BS/0rMq65M+uWo9MNpP1ZH2w
-G87qh+7nFIk38h8AEQEAAYkBJQQYAQIADwUCUyel4AIbDAUJEswDAAAKCRCOPw3n
-rjVGUXwWB/0Yq3UknzRomC9wi8sCh9Nv4erqjSP/JSoNx+rYNpwJX74jVmUA4u7p
-pzywCwSFKyE2L6pkgKw0y+KfE4cWsotlfO7E6VQQi/+cCb5OCxqf+gOelupuW4Co
-MSHKkPWXI/dhM1NMIW77+bLiiHfaOW3Wa9kBSKujiuFSp9tIq2gjTf/2rKQMbywK
-szhlBICdvYzji8t79C7tAJ0xNgZJJv0QHP+5MZJfMAARKrvtRP0I5OB1HYVJrH0v
-RbO9Y8PoYrPxeR5zQYxAyt36/DE+PM4CpEcCZ2D7Xrtk/GKe3Y/jU8FBifEebuhE
-HdZk2xusuOEx27cIovRPHwvLcgY+4u3j
-=oNWb
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A2115AE15F6B8B72
-uid    Stefan Bodewig <bodewig@apache.org>
-uid    Stefan Bodewig <stefan@samaflost.de>
-uid    Stefan Bodewig <stefan.bodewig@freenet.de>
-
-sub    6366592024774157
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBDsSIk4RBADSCj6rUjV64tYCGT1DYKYR7GthyWpNdGHSYLbETBcDatAe1dzQ
-5NsCgfrlybfyeY+y1lxr3T9bqf6zJWDw/718wff96qmmv1qzexSYtmIrj+h53V82
-EXwWOFuYMJisuxdT940iQzosm3GOv4MJdEg3oI2SgfEyRQQ6vO4Ob5rHDwCg5taZ
-nrHOrXx2dIGHxpxRZ0SUl30D/jmtttFjYOQ3LBMriikz5mh2sK3ZnoSRF4o5O0zW
-Ve6e2SFXOEjVjImKsH6KCbdQNelrAdgiyOoXClyQKsQ27pncbdWo6bO0E3POJZVm
-XaeW7iudHVr63rU5PViXObIQrdQl0D59j5brKj4vdlTyUw8kaHPvbKPDEOwvZq4Y
-LJQ5BACA1YilTeXRJqwFsNlpcxCHwlULD4QUVP496prQWf1B7Z6g0KvLGrQsO0Vn
-Jcn+fEqukysTJixSXCPebosltd4RalJIupVYkp4w6MJ7biaDAlLuNhDcI/AiXTmV
-dXUedVXIaM8I3Ne23gucwbAyc0Hvb+3cSAKRhl/azFQhuHBvlrQjU3RlZmFuIEJv
-ZGV3aWcgPGJvZGV3aWdAYXBhY2hlLm9yZz6IaAQTEQIAIAIXgAIZAQUCSgkegwUL
-CQgHAwQVCgkIBRYCAwEAAh4BABIHZUdQRwABAQkQohFa4V9ri3IWMwCghs0wCe4g
-GMPBq6jtBXK46e4aHKIAoNn+9NX6NlhF04qaHyDBhXK2HMmuiGIEExECABoFCwcK
-AwQDFQMCAxYCAQIXgAIZAQUCOxIiTwASCRCiEVrhX2uLcgdlR1BHAAEBjzgAn3a+
-nFeNb3mAZQR4lRcXy3F+8eThAJ4iuLt4No6TUB9xNETrm3Y/0TvkU4haBBMRAgAa
-BQsHCgMEAxUDAgMWAgECF4ACGQEFAjsSIk8ACgkQohFa4V9ri3KPOACfdr6cV41v
-eYBlBHiVFxfLcX7x5OEAniK4u3g2jpNQH3E0ROubdj/RO+RTiGIEExECABoFCwcK
-AwQDFQMCAxYCAQIXgAIZAQUCOxIiTwASB2VHUEcAAQEJEKIRWuFfa4tyjzgAn3a+
-nFeNb3mAZQR4lRcXy3F+8eThAJ4iuLt4No6TUB9xNETrm3Y/0TvkU4hXBBMRAgAX
-BQI7EiJOBQsHCgMEAxUDAgMWAgECF4AACgkQohFa4V9ri3IsngCfbIpJDWj6UgXY
-7rBH8To12BgB+RIAn3jw72WJzplAtShVTmuMlRFS+FUNiF8EExECABcFAjsSIk4F
-CwcKAwQDFQMCAxYCAQIXgAASCRCiEVrhX2uLcgdlR1BHAAEBLJ4An2yKSQ1o+lIF
-2O6wR/E6NdgYAfkSAJ948O9lic6ZQLUoVU5rjJURUvhVDYhGBBARAgAGBQI8PtWP
-AAoJEIEEZE9RiYUEnZIAnjOkQx1BfxN9+E7Yiz4MOxqZjSUpAKDQi0Alv/VR61fm
-R7KHZ11J2g+HSIg/AwUQPnWqGv1viMYh0KcbEQJEBQCg5pVlbkJ1n2hivc/Aj+Lx
-Ek34l8kAoKZ39ciVg4Klr1BzgLznmkzw0XDpiEYEExECAAYFAj512sEACgkQ7tHq
-OSJh0HNFuACfb7quMJZHOk5ppmTxf4GVS5bh3E4AniLa5788ktdcZCBE5Or+G+yu
-IGooiJkEEwECAAYFAj513wwACgkQPo+38viDQdknZAPlHNiMnR+LUavo2yOYiJT+
-W9+8+qNs2grYDZ+WSYujaWT2NJrUCYXQRM6gKDyFlkcJvHI9lF2yYMkVetllZVN1
-TJkeEdtbHncNHcdq+ZUQR0NkFKTF9d1K7UI2rfWxt1y6a13TcUjpJXzbtw/OXX9E
-ZSI6QQt4rSFlvci9J3mIRgQQEQIABgUCPnekEAAKCRAVP6DNdaZ2ki/rAJ9Q0x5m
-4SE3hMNGUoMgS0MNmYXDOQCdGa0QW2fZW4B1wSjiUIi6VgY+F7GIRgQTEQIABgUC
-Po3OLAAKCRDKaTl0gQOjfpFKAJ9TY+mKmq0INLC9iqxbEETjNwOn0gCgspeNEqX1
-SUjt932Lj3IvXR6fkAiIRgQQEQIABgUCPqxrPAAKCRCrLDHp1imPAWR5AJ46Qmuc
-7mvaFYOFfgAI88s5tm9csgCdHRUcCCQQfVb+3sHjN0Nh0EFmt3mIRgQQEQIABgUC
-PsoulgAKCRDb0kX8s7KhLBfwAKDV6uwqf9AMBJlr4aE45rWOnlWAeQCgjBYQVHWF
-jV1cmpT06vE4bMDVJ6+IRgQQEQIABgUCQZLyYwAKCRDkE2EzDKpotCz0AKCKjnMl
-yJ5gummKC9JgsF+5tRWtdQCdEpknowAKkfp+mjPa+RzZ2Hr21tKIRgQQEQIABgUC
-QsUygQAKCRCb8iNFL+KLzxoJAJ93VwhrAOqmRhTzp/ckSNw3zme0VwCeLSbxZHqz
-5uSHd934QitJGyu7e5CInAQTAQIABgUCQt6sbwAKCRAxpj2W7BQLgRr2A/9Y437T
-EhY69Y/uYqSD/5fS6Rb6ZuMTjbqoq0b8HS82tMqkSWbPy21H6hqOpuDbQtrOgRS4
-D1leMs9+x1YD68WTGBXqoh23Fg8xqY+bvK0QE6aAyjBhdR+0a16ozl/EuVx4eLB1
-SXKcbZ+a0yq8+d3Y4J7NIVHHdbqe8CIiOgtmkIhGBBIRAgAGBQJC3q1jAAoJEIuW
-KUP8JD88Q+wAoKip8nm/341UvL6L+BXj8Xi47uJrAJ9UghmohfYBH/qiGmVJ43E+
-yQyfeohGBBMRAgAGBQJC3rrlAAoJEDLJ5M42QstL5kkAnRxguozhFaPessqLKU6u
-2y/hBHoqAKDTCiGcuahS112W0jb7I+5g0YNnPIicBBMBAgAGBQJC3sfTAAoJEDfj
-9F/uZeMhwBQD/icOVBudOhJIM5mQWPUKgYvxOOxWDOs7evdLfHfy5BBMUAT8AYFj
-ia0eA1xiaIloLaE3Vj6aUQa7/zRGO/Xzll8mwUR6tTpj/21EknVKj0AB7kCa8akP
-3Kxdp7mB4H6T56kgxK5/1Yx5NFQJtCz258ZktXlryOqy2/5u1yvM1pj2iEYEEBEC
-AAYFAkLfRQIACgkQQeoJoFeTSY8XxQCdFd+XEWqyDkCx37gaIQAG4dHpwiUAoOZ/
-K5OHyTJCNFaBUDtpCh7hL8TPiJwEEwECAAYFAkLfbHgACgkQms08wKmfdd1EGQP+
-I2LRjoDdp8Mb1kv8rgms4+AdQVYL8OAAQGZ7gBjrZqBSxPS5eXP4y7U+zYTS3bp6
-NJy5Uwy+qleDuInb7fIrOydfTJIRdbr/r3pcSl7dMWfWJU6YwSU8rFqSfe3+OvpI
-N6mj2OoPk/kIlHgawOwbeIoiKxZ0N/zVlel/zrLsDl6IRgQTEQIABgUCQt9segAK
-CRBQjq7FMC2laFiFAJoC+pUGxNfmzhz6xM6jToE0x3MchQCgjClOEAqr3fpLPL/c
-Z+/wreCzk06IRgQTEQIABgUCQt9sfAAKCRDdumS6LDEtL3PwAJ9h6hw4rgnbTjHB
-teAR1QlDK8crZQCgrPYAXUjZvwRu7u9NRks0VXVAy3CIRgQQEQIABgUCQt+SdwAK
-CRABBWa85BNjkvdKAKCISLn/W9i8msqgB2XSFFZTnuJ5QgCfafTwFB8xklDjf1o1
-b8KcgryM8E+IRgQQEQIABgUCQuA10AAKCRBzzi77hAj3Vd01AKCgEHV5uiEh+WKc
-A+W8jfukUe67QwCgnjIy1spkxqrTEgGfFX1zm67320aIRgQTEQIABgUCQuDJOAAK
-CRBc/Tf6zHjIk1sSAJ9FyPpAodUdC1hVd0JgpRuuP3vACgCeKapXXly/PWyIONQr
-0r9pOyQbBqOIRgQTEQIABgUCQuDsywAKCRDJtabs4td03xShAJ0V+p5/wzLXGGfq
-Yt31ZMstoh7BNACdFcaH8B/iFUbQrC1lwkQDjricKgmIRgQTEQIABgUCQuDtPAAK
-CRBbloAQ4E+aiX4nAJ4vFmMo2KyOA/gDFXkEIpH7lJT02gCgjA8X/sHY2YY1HS3c
-RnN7zCk2FDSIRgQTEQIABgUCQuDtXwAKCRA39o/1AVr8ip6sAJ9p8omLizwthXYn
-E19AoeCZFfN4ggCg0Ec7O6QMJ3Ei+Zgl9qYi2cI/jmCIRgQTEQIABgUCQuJibwAK
-CRBtmI0XhzFcMfwfAKCrw/b0LAxfs8qFGZjdPfYA+w5owQCeN139a/NUEW1NwkVa
-QfqIXgvwRCmIRgQTEQIABgUCQuNVvgAKCRATLknU5B7cfnoMAJwM99Ys7lwOR4oU
-K8g/yZzingqR+QCgkhNE6V0hHFepSIwvWhMnGJ64cl+IRgQTEQIABgUCQuNk2gAK
-CRB1yqKj85s3UIi0AKCwmGoHF5lNpKtFU2TdqPpyIAmuAQCgjE9dhO8imdYGvj9Y
-xs3SOlXRMYSIRgQTEQIABgUCQuPtZwAKCRAyhk5BnIUiK0KUAJ9akfT5X83q+65x
-ZntuwybYFyYzegCfd8Xmqqi+WiDj89yC8oJOg0QXy5aIRgQQEQIABgUCQuRvEgAK
-CRCM43a4HNSGH+BlAJsGkiqQIS4ht3q2oKHPc/NwgaJluACeOW4EUeXiXX80e0/1
-8RgKCXydsK+IRgQQEQIABgUCQuSSvgAKCRAEkTRC6hujjZ/5AKCO07oQ50NGKu4K
-LqAq/AzVrZ5HBwCfRdQQubkBl7MvkTSsR8gzYUGIyLmIRgQTEQIABgUCQuUQtwAK
-CRBSeS+vmXivhhRnAKCDu8mkOlRee42+BzlEeAbtRiFFBgCggQoeyuzCHpfNWfnJ
-BGR+N0H8DQ6IRgQTEQIABgUCQuURpAAKCRBrc6EGKmI/ckDhAJ99vw2BCyw5BdpV
-HR1LA8J5TadA9QCfXkQCPKRVmxSLa1laoQzTxI04oj2IRgQQEQIABgUCQuXCHQAK
-CRBhGWouMz5OhL2nAJ9QSA7zfhdj9yVbOTD9UsF97swtlACbB3PSeV44dhYUGudi
-ATPnd3gzFQ+IRgQTEQIABgUCQuaZYgAKCRBo64x2+OopZ3sBAJsGnDKK1DvuR30o
-hPrL3kibW+Za3wCcCeQ1MFy1W0x/B11hMb7EuRo6WU6IRgQTEQIABgUCQudhUAAK
-CRBulHWUwVJDGohEAJ99CpRdOA5riHIdhAFTCuUYSqZa3gCdExdUaF3juWhLbsya
-ISJbAOWQ2MmIRgQQEQIABgUCQupj9AAKCRCyvrxAFSkkr+gxAJ9zsz0qkCkJZbt4
-TbY+Uug3Ww8r7gCgl3ATxOwMzY+Z6GT0r64cjHoWhG+IRgQQEQIABgUCQ4efngAK
-CRBmNbbA3ohd06v2AKCHZ+fbpbQNIvlZkBO+9CTBl4k2IwCdHr7QCVQry4VIUhWG
-X5Fkydj5cXCIRgQQEQIABgUCRZ2eTQAKCRAhgklWzkGcj/RKAJ4oLDf0g3L0hIW6
-eUCiNiBIicd+iQCfa9Tyrgk2ODXeo15yVk32SY32ZtaIRgQQEQIABgUCRjjiwwAK
-CRAVRbP+4iLeT6q8AJ9+mkGmhjzYwS8NXtzj/pyPDnjgJACgkA8J1kD8tGogImbS
-IVsOvCGxJvqIRgQQEQIABgUCRjjnnwAKCRBj0K2ukRID5CsAAKCVEH9V0Sai9vJZ
-0wOaxN3LDiSFrgCfS4rBl4od8FHdwLazsy+qqYyjP2OISgQQEQIACgUCRjj3hAMF
-AzwACgkQc92MFgFTAjVJogCeL+3FTTVR5snJx9qbGQsgv23ZaT0An2Hy1CcXVklc
-YBF7LbnbAgbe1HpfiEYEExECAAYFAkY5GrEACgkQ4eHysJkO1KoWSgCfYq2gwbLc
-3lzzLbLd8fmV3S0Ju3IAn1gw4GkDmvAqDOf/u1grZMmrD+gYiEYEExECAAYFAkY8
-UEcACgkQTAQoGDEaPeXj+ACgrhEFOn4z8v3DxIqoRh9tydmBK+4An0vLwUxFOLEW
-zqJkxLiDT8W/ejmZiEUEEBECAAYFAkY8kyoACgkQmHDv8/EvYHIkCgCYgXQZTJ8V
-mHwSX3pXOxnMhp7mbACeIPXwcPvmfP709nfgQ8/GpT2z9ISIRgQTEQIABgUCRj2g
-kgAKCRAuuUaCiIF0AgOBAJ0bJmFzA9WkG5FmfaP4ieG9+SCbXACgw+2wcOA/B94L
-KRtjhJT6j6zSiDmIRgQQEQIABgUCRj3WeAAKCRD1wmAWTO7XXwpbAJ4mr2IxFtx0
-ppkefxx0l0TJ6cFkrQCdEFbc+aMxRKhK9SCAWi3mq1UqEWiIRgQQEQIABgUCRj31
-AAAKCRCgctTQQ1jFhByKAJ9SIielTuD3StxPQpBkAkYP6Ld88ACgg1oPX9ryJA7Y
-uhMD7byXQsETzD+IRgQQEQIABgUCRj4FxQAKCRACpaYFC35s+k/GAJ9/VDyw2vNz
-k1xjcu/QZCa3gGI2zgCfeG8klJ78bAGknzxBlK3XtmoNqASIRgQQEQIABgUCRj4V
-vwAKCRA+Km/CXymIJIvcAJ9QSE4mCQldVnpbYwLTCk+xHDqhcQCggT9P3/rHIzIv
-v1tJ+A1ZJPvXOcqIRgQQEQIABgUCRkC2QwAKCRBtC8c6QFgYN496AJsF7qubP3+R
-gNXvDmm/Ce6BWy9uIQCeJN8tbs1bzPVJEFZ/qUwfdyUYCzyIRgQQEQIABgUCRkxE
-UwAKCRAfISPDa9hyoHbaAKDWenUlgVg+oIHd6Rm2zcr6mftGTACdFZ3oea2NGiVl
-2tl+SpAMkqZ3nO+IRgQQEQIABgUCRkx9AQAKCRAPRQomYhC/wMliAJ9bQL2sMBOg
-tT7QEotgKJbC0Un3wwCfYe9DcIOG/xZOb5q/fqURMuqGOd+IRgQQEQIABgUCRlJv
-WQAKCRAywdbvDxQ7wYZnAKDSXZPU786k4QJez+9gTbrj3A1NpgCgutSksph6/y4c
-B9zneVnosTSHVPSIRgQQEQIABgUCRlJvYAAKCRDLrr45pGxModlvAJ0VKWhYmHe6
-5MuTztpK3i5h5mspOgCgis3t6lnF672f17qGpU4vPznNzdOIRgQQEQIABgUCRl7V
-qgAKCRCahtfM0arqYP5zAKDeTgFGtGLqmOtj9SCAeOGIdZIPVgCeINCfUxUHrbQi
-TZxUvuFHVXRkvpuIRgQQEQIABgUCRqVMLAAKCRA5vlGhCEyRE6pDAJ0eEh2SVVHf
-jVrNUUE7poYCtI4/ZACfRa1IiKpotMRDnv6KvrYXFFgFB1aIRgQQEQIABgUCRq3M
-VAAKCRAzzWczr17EUh1GAJ9IZ+3oohn4JMQ8gavyWnyg6k1ocwCfU0JdlMk5b6vQ
-bmmXLiGW7xRcLgCJARwEEAECAAYFAkfAfZgACgkQGWWFUMMRBhFnhwf/dectbpQB
-0N3iTTGXaVQCP2AHshNRt6MLC+cWpTIoAT0/fxugEc19zpyWJBQ7PghNYM+GKKdu
-M2ckeCWn28rSjhH+0UXIYiYi9ua7ULyXI7YEk+AXbIw2sGBmHHT4iQAbdHiLL0kU
-gMaB12MtBI/hNfe5FQVRcQCEfMYD/9c/i2cLcKKy86y6hzpmPJkZK38dTNmgp/7C
-x0mV9puIrdCkPyVI7DwoRkXnglQLy5pga4EazuKHgVw74CpvnZQDHj/7Xd4R0CiC
-dUXYdtqIj4baMR6TIDAPRs/cNbKD718YG2fC0MyPQ6seSW8DyqgfEAy9ccgaHGOp
-kE4V6GHwM0QHpIhGBBARAgAGBQJJyofZAAoJEMnHkk5RBH1mPpYAnA61GWGrjkN5
-2tg0fnhAglIXDdclAJ9Aj19mXrOYpZKbWcmpdEL5rAqbDIhGBBARAgAGBQJJz9S1
-AAoJECTBo3hqAXsXvlcAnRPJN0IwYhkYKigz/GvfD6q/JkuAAKDRbw71Y5/SrBJW
-DKeaHa9CCBSLIohGBBARAgAGBQJJ0jaPAAoJEK6wGhU7fHWxkeIAoKWxeKecl8cx
-Bh7AU+rLXrOv/9/gAKC6We745sAMcyq64YLDgEvCu+owgohGBBARAgAGBQJKYKvx
-AAoJEIuttKwFuYn5qaoAoJNy4k0KA5AJmh9Hml/HnOB2fI3PAJ9NNr3q4Vxi9xum
-vEwHxiA1WvFdrIhGBBARAgAGBQJKZCSqAAoJEDzzkhzG1ETtLE4An1cH3260Cx+H
-DhNS4RytgLVCSPokAKCdOpeQibuNdXAY/s1LYBipelTB+4hGBBIRAgAGBQJOSOUa
-AAoJEEnH49G0aTGM2q8AoLUytGBOGavD18Fow0+S4t19zcQcAJ4tUWSfPiXaFUo6
-blWHmsRgMNE3MIkCHAQQAQIABgUCTwRWhAAKCRDdnNU4LfQLN3evD/0UNX4rkPv3
-7QGtgs4xl2vbN+ZmLDIL2twpK9Pj8k0JVkRuxkGmG6qPXnH/bMJ7RW00bw5UHqqL
-SGT1JDebpNA4PuaKqHW5n0U02+6Sm8Yr4pHoLzNrmJvdCI/22hTJoEiiRc1sJ4a1
-YDJ4jtIRxfQ10damUYaw6D9dnVFZYfUL5c57tDLQP3VLjkxJogc+x8HdrJKpY1at
-2eL2W1UMpySF9O+d0elAl0tRt10N1xYqcxtxVgT6bq/KZrwvYWjnzpX+QInyOURv
-jA4CzH2KfmXJHCKJoVoGczzA1BOarP1e5tcrQmdi2F9fI6NlPXH/66QoPzAKdMJs
-nMFgExsEocgwz6SNrUkwHZ+2Z7CLG79Jrkb/sCpW8JGiq+ZWPrgTVqqLecssu49t
-l2lOCBZpjmRkejQ5PIoQIeMK0ImLspaLr7XVMXSBm4bU1XPYHuDQrGDBCf5rA6At
-3Ioe7+fHKFyrLkS8d0RGJKp49B6LyWVjMqpMaPQVUajPcOffPe5X3S6lhIVuQc2W
-pg9+n56kqXE5bnzHg85Dp23/h+xyEXNlu8+GFMUIvGkQ5R4HgXE27K+vTieFtK87
-5dPWmbJY+2pVBjMcIFNfU282vbtZLbiOhg64pEHP+pCmJg803HlJbcsZPJF/28J6
-bIhPl/q33HhPrgLHdCs0o1xQcp7A72/PBYkCHAQTAQIABgUCT3RmNgAKCRDflC/g
-uqPk+aAXD/4gSmWpZ3xjO5HDW2v3NIBl4owKoOnuvgjK/rNqDpncd9HCFIm2ol3N
-Ne21eHG2syIpblFWvkU8YrxjKIxzeAxIdO6rdp0VWPpVCoTCwQHOGHCuk+OxHGFH
-KCP2H5raz47UZBI6C0OcUfQ5a2YGzgoxqpsoNeCoPe3s07LRvr1D3QEMmNvsd4j2
-Z4uJvFd2Gwii7baYA8gnzl6ypaaqZioyNs+DcdZikmiO2d1rR3muaKZKBQG5qClt
-p2RHccWki/JmrW2rlsh4rw9OwDrXyEe5TagNUAoRMTvHBvl+YNaP5NJFpWvYpXds
-PXWmGs0ONrNlKXrlMTHjMOQt1mZlFyA6Jp2O1rTTrcmGKcDme5B6bNFfaL6GfeLY
-r3JVnNoVkLbm3OgIjGcYQf/dRej0xOHMfvFKIPwxOTNcXXBgzbblzpQXukyRLuep
-lBwcd2mcLk+5KidOKlrULzlU7MeMDrxPsrmFqG7dE4DuLo9jxyjhm8gCMyQQqp8X
-3CC2CKyojUp9SpShkokDTkPnVK46hL3MUga2AI0oLEf7IImvwvqvnnP52a4c/H9a
-pMbt4vJHpNzJVPTGe20aXiPoh7CH6MU5i9Er7qVIev0EyUnIXhK2LWax90tmsiiy
-/6gahYIC7RaAIxMAPzy36G5g9Yu5nNEpvLRfRiGQtEgSEi8RHbvTfIkCHAQQAQoA
-BgUCWEe6IQAKCRBjf6WERgZUlh42D/9roNDWOjTIK/lEg9tNfqVNZIKL/Or3MwVS
-OaKiWZLyaffefZQj7mrvfkioX2z5Oem2VSvu3ueFOOwjq94Ls1tiqBl9ZfHqB7CJ
-E49EkjYwqPXUwQUnJd7hd8nGcfj5pcHiNWQda8aO7WgskEumPFrz8XKtpKsZ5Vyc
-r3Z4v1ROl0KhgDmxnJvuc5/nj71Q9yQdhANcmZ15RHQJJIBOqmeUghVuQuzsVMvZ
-LQm4IWtVSxea+2CdpOA+X4szICRsvhQXuDiuo0cIjuvkr1i8dnt77+CxcSHNwaX9
-/kMUxz3J+OY8t+YSZUoRvZRpHQ+gTUuyNeOVXfvpxrVqhdzH3EcXChd6RVEfOieP
-/V+GMmz5XYdHMqGM/YwXmfEgAMoRUMokh1Zp1lbV3emfGhu8tRIjw5gh4phkjfdB
-p4nCQSKI4F5OnkfZId9EBpWIyQxvQvhK2/GbNAu/pMYwZdiQt+3fur1bh+yOTRkC
-AHIUghE/pbYGHF4lti+aZIN46NiiYeu/8SxeKVqTlXd9xFspbTjuxr/oOxQmCgci
-EzvdNXz27aN0M5NCuzR9M/dRLpTKQog2aveBvkkeef1+eL5qYUOuBlN52FNTFHDK
-mCYNF8jaQRTUFh5EsY2E3vgkIORgfSizzybv+FMROa24oL3LU6ffVDN2w3+O/Yz0
-rGmVGin7g4kCHAQQAQgABgUCWGDxjwAKCRDLn9TBXzoLde6sD/4gqLevIbHZkK9J
-MvGYzBShBoMp3MFLmtQZ6jGK4rAT6AEoYsayqnjWspBZwK8B5CkaCPRVHdD1zzng
-EjOvmIEpKSBS9MeAe0c0M9aBJS0pIgbnLa4AkrhZ2pBf7Ut0jL0ZW1bUzotXzhdc
-ORBa0fa7B182LTKvIGMXfV3RXmN5M5w5xYo66zN/ABdOieO5gcHyLp82utuuucUK
-9qytJX+Iv42kvOrdm2yHzwvKxO0GQqHE/EVxtt+CnsilwDlKJXkw4dAzGbcjgdLb
-fRLKB5xeUuuafCrzHAoZZAEAUPAzg72/YtlOAHC23IVNPyegvHMs4N9dtBc4lQOF
-h0pv24ab1G7slLTaDYlYgqIuV7Uk7KAKiQEypYF44IUqaqSFmHdv2baGwDpU084F
-m0hQu5ugX0CtkSrfqtSTr9y51boUgneRb3cfVfrCvZbCZtFXMfFVx5d3y72J4NWW
-oJjG7k+iADhlkhkdKl48YDYo7HWcAYxayskDuLL1etLJ6fjmLnxpzj8HJIy+vL/s
-Wfqb1DnBhTwj+UJuuw4ycQmZqi4tlpw0+3+iqRh30sA4tDOgR3uP4S2wvzSmMqyx
-vepWBwdp1d+BWM5Qmf9Xu/Yf8X4ulgKzEp3rProlly78E1D6giG7EL+q0lM5LdIU
-we3oeveZ418AlzswwO25OR451UtPXYkBHAQRAQIABgUCWXH4+gAKCRAXdF71VJep
-B6U+CADe6UdA3isKr5LvGGK4oy2STlg95FwprYkdBr0gnMUFPcCVIHlgUK41UeTN
-fjfkoh0hurHxX8P3UrjUIv4lTrGZAKdH/tRUFWNr3udOqkKg+69NZge/WjqNyU0o
-GIfLBFUbcLamVR0pPGkqleL/jJY3UDUg93Rr7gWVencpGIx61w7R9CLd5m7KtGNs
-mEqKRXY4XW+PjFbKHgrAB/bI+G/AirBHP2Vg22nCO1w/WCf/Pe840GWAMsp0pRGm
-GkX8kd+c9XE8E7oyTBv2lzSSEVoMkU3Iz7FAEKbvLQx9EZH8ICV6QD51wBzM+Y83
-b0SRAUieUfoqqVdh20JTuq2pHjNWiQEcBBIBAgAGBQJZcgr9AAoJEBd0XvVUl6kH
-+7EH/3FNNjgEUar5zmCDrk9sSRfB7ayTsQgZIChY3aL+UUxQ3gua8xTF7TUrEx21
-p0/t8CuUjU1qUysCMq89veBrk2s7VHsnFsACvjgXclsbfkHIMiWOT53vFJLt0x1p
-d7999uNAnO+WgdOvPIuIdePMOW4gznMW3LfTkgoc/bn5fGBafivvCYNlCpOPg74T
-ceMNq3u8JIiFouubnabfUpAP8wdz8GDDbKbqMDkratbtIODRco64Rgf2ekFZ3EBg
-f54V39EoZ2g3tBW8f53ikSihRA8h2tlloFiUTTyaP0Zro0wLvDCaAmfuK1YjeIr2
-rsYwp0vFK1EqNLMe1qEiZreKRpqJAUoEEAEIADQWIQS10bBTFHtMTL5JaA+WEpPX
-9Ca6oQUCX8KG+RYUgAAAAAANAAByZW1AZ251cGcub3JnAAoJEJYSk9f0JrqhNlIH
-/0GbUhPKN1oKStWzH5YdDhU4QNxD5ii+U8MCh8vUyQvmI+o6ZsNG6FXvabTCqByY
-cUqiZkLuVIpW9sEJnOe5xbXDwN1zM5Fd0j/FQZJGc9miTKKjAz2czIRMLhwoZuEd
-kJIjzNRtvynBpV9ZZGDFGiS50Xvdj3Gb5yDbPAWpLmvG0OFogf9p7mZpuE4y5Y2W
-RHYPUyU8fSLxAWzQa2gt2U5lTBwDV7HVYR39O+1iugviektbq51NdVnExL1CT05G
-0bb8vDBuPzdMUYOoHxLig92dUw9d2Wp6ikBil0t4CfnSLyUhYcBxi+Wdo+giJ9gE
-lC4xLEGa2P9E7Tj7YJA1vKK0JFN0ZWZhbiBCb2Rld2lnIDxzdGVmYW5Ac2FtYWZs
-b3N0LmRlPohgBBMRAgAgAhsDAh4BAheABQJKCR6KBQsJCAcDBBUKCQgFFgIDAQAA
-CgkQohFa4V9ri3KGAgCguCjU3AcIzhCHzDoBbBd7k0E7y+UAn0NvetIxorPScnvS
-8v3yNQgTFUMYiF4EExECAB4FAkKcaeUCGwMGCwkIBwMCAxUCAwMWAgECHgECF4AA
-CgkQohFa4V9ri3LJLQCfV5FgLLtMydvd3RmvmG2p/ma9VfQAoN2/T3rXbOnm6kGa
-Ih0aKXJG2zi6iEYEEBECAAYFAjw+1Y8ACgkQgQRkT1GJhQSdkgCeM6RDHUF/E334
-TtiLPgw7GpmNJSkAoNCLQCW/9VHrV+ZHsodnXUnaD4dIiD8DBRA+daoa/W+IxiHQ
-pxsRAkQFAKDmlWVuQnWfaGK9z8CP4vESTfiXyQCgpnf1yJWDgqWvUHOAvOeaTPDR
-cOmIRgQTEQIABgUCPnXawQAKCRDu0eo5ImHQc0W4AJ9vuq4wlkc6TmmmZPF/gZVL
-luHcTgCeItrnvzyS11xkIETk6v4b7K4gaiiImQQTAQIABgUCPnXfDAAKCRA+j7fy
-+INB2SdkA+Uc2IydH4tRq+jbI5iIlP5b37z6o2zaCtgNn5ZJi6NpZPY0mtQJhdBE
-zqAoPIWWRwm8cj2UXbJgyRV62WVlU3VMmR4R21sedw0dx2r5lRBHQ2QUpMX13Urt
-Qjat9bG3XLprXdNxSOklfNu3D85df0RlIjpBC3itIWW9yL0neYhGBBARAgAGBQI+
-d6QQAAoJEBU/oM11pnaSL+sAn1DTHmbhITeEw0ZSgyBLQw2ZhcM5AJ0ZrRBbZ9lb
-gHXBKOJQiLpWBj4XsYhGBBMRAgAGBQI+jc4sAAoJEMppOXSBA6N+kUoAn1Nj6Yqa
-rQg0sL2KrFsQROM3A6fSAKCyl40SpfVJSO33fYuPci9dHp+QCIhGBBARAgAGBQI+
-rGs8AAoJEKssMenWKY8BZHkAnjpCa5zua9oVg4V+AAjzyzm2b1yyAJ0dFRwIJBB9
-Vv7eweM3Q2HQQWa3eYhGBBARAgAGBQI+yi6WAAoJENvSRfyzsqEsF/AAoNXq7Cp/
-0AwEmWvhoTjmtY6eVYB5AKCMFhBUdYWNXVyalPTq8ThswNUnr4hGBBARAgAGBQJC
-uAqrAAoJEIEEZE9RiYUE/RUAoI8fRvtL5PKVXW4G5hxidYhv9EnPAJ4m9FMw+dY2
-NXP4JU69XMlMfiiXmYhGBBARAgAGBQJCxTKGAAoJEJvyI0Uv4ovPeKoAoJdFlZ0a
-MFVuPcgEWXeS+HfEXaCyAJwPcfv2ZtUNE0zGkYCsVDWGpAXOV4icBBMBAgAGBQJC
-3qxxAAoJEDGmPZbsFAuB5s4EAIAUWkQoRM7dkduMyc+iAAI2voRkJDHMZMhetdLJ
-ZCzrxVwfnjBQ4DjKTdwal8famADFiNod6NMlG8Mq8as8aUoeAJkXLj7AfOjXulb0
-nVoqTaxRaVPruycNV0y6f+LxbEP3LPb31xdHqILE98/YcgwSpuzFYlpchOjt2tZK
-M7fliEYEExECAAYFAkLesLIACgkQ/W+IxiHQpxt9FACgwsbD2ZLCiHL4+7Wx0BMJ
-vj1efg8AoOz6K1AoCL0yFpyA/M0VgwRuAAl2iEYEExECAAYFAkLeuu0ACgkQMsnk
-zjZCy0v3dgCcDOwUCEIKiwNKgO+UdhIxxV0CmVgAoKO4mgDR8SEXPzcNfY/AsTW1
-iUSeiJwEEwECAAYFAkLex9kACgkQN+P0X+5l4yFFrAQAz3B+f2wEiwXNBFBsA76W
-Xzd/ySL74DgCePoNdDjFGYKVTGpqEvUGPHF5CET5CiarUh5sMmvRJ7fhcHSDcntv
-Ov+L1CYTASqcMl9ZWhu/VSCPL7WPMSuVkGGbyGcIj7M+etYouTSfvy/MnlGudVpN
-NX45bmvit1VnzrIpge2lVKiIRgQQEQIABgUCQt9FDAAKCRBB6gmgV5NJjzHQAJ9I
-fkjKkiEuFxUhznsghAQ8bsBWnACgoT0kWSB3iUepLIDoWhhGtDIS5FSInAQTAQIA
-BgUCQt9seQAKCRCazTzAqZ913QcNA/wMMP7UVBTw88974q5/Zsk47thyt6PgkXUj
-8ZuzYcffFeA5mxG/pYnjUz+i/EktiulWpADZgX8bHCC7Ct/iU+T7iykV1puC6Ikr
-R3b8pkC2cuyMjN1hyhjTUgoZPfGQ/AgMSs0VKbFfpsoJR49wU0dhnp0MEcUVxhVO
-x2j/BsB7pohGBBMRAgAGBQJC32x7AAoJEFCOrsUwLaVojHcAmwXQeOubg3bUTB2u
-aFL08cpAvYp2AKCOW6zYbK4LNp+Bv0kdWEEOuF6WSYhGBBMRAgAGBQJC32x9AAoJ
-EN26ZLosMS0vsxYAoLqtBTpmNJLqBWfCzC61qoHB/C2/AKC/aYwYl/aGdhVo02pX
-lYgUC7JyY4hGBBMRAgAGBQJC4Mk7AAoJEFz9N/rMeMiT1OUAn11szYejAjmgPqEZ
-KcAOEjZ0p8GtAKDg71a0WJHMuoLVOAICxuKCrL4kOIhGBBMRAgAGBQJC4OzMAAoJ
-EMm1puzi13TfXWkAn0vfJR7sZR4OozN3dYtZq1yV/uu5AJ456cD2eHIqAcBJ4Qr9
-ldBcMMFbS4hGBBMRAgAGBQJC4O1AAAoJEFuWgBDgT5qJs1UAnjCcB9wD+u1Szf4e
-72c2fxqv/ZDnAJ97pb6T3IeN3uFladgd2cKQBmQ4x4hGBBMRAgAGBQJC4mJvAAoJ
-EG2YjReHMVwx7NAAoKeT5KjQCebiQsPCX6yse8gHtvqMAKCpE4E3kx4QZdCb4Zqf
-ZVK36e9Nn4hGBBMRAgAGBQJC41XAAAoJEBMuSdTkHtx+VHQAoJMCV+E8XAc9ecGj
-7khE6inA1CexAKCHa8dL1VFlG3kj2Kw0No1/VuIJCYhGBBMRAgAGBQJC42TbAAoJ
-EHXKoqPzmzdQr1cAoIQuLvKbG0vF3Bh919Xd3F3reZXbAKCOBpSVCoVePHmZedGy
-DLhLpxL3K4hGBBMRAgAGBQJC4+1qAAoJEDKGTkGchSIrC7IAnA6WMvb759VDQFIp
-G8VK9L59K7coAJ4nGw6FvIJ3ejeurBpV5jkUWL4Wb4hGBBARAgAGBQJC5G8UAAoJ
-EIzjdrgc1IYfn+wAn0lUcxXAHAcPw83cNCryEcS6afy3AJ9VBJeig1jY/vjgr7yT
-qUs7yc4foYhGBBARAgAGBQJC5JLHAAoJEASRNELqG6ONv6oAnRn4CgYNh7XbbBEA
-5gAprKX1/17RAJ4p62iWXo1n5Gb80psUkY/p9jLAi4hGBBMRAgAGBQJC5RC3AAoJ
-EFJ5L6+ZeK+G/Q4AnRKD9QScH8gCiqMfMqgGK8IxgO2tAJ9VjcgMpEdtss19YFIM
-RFYJOkde2IhGBBMRAgAGBQJC5RGlAAoJEGtzoQYqYj9yoYEAoMSBN7DO3pOOYKQj
-1GtiMXjpr0fjAJ4k+HhuZPKZx/BEafrSHRr0zPWYpohGBBARAgAGBQJC5cIgAAoJ
-EGEZai4zPk6EN3sAnjSXftwtlxLF8+3czv9o4+BUalrnAJ9yJoTKfO4cN8hAP++1
-etlvabT414hGBBMRAgAGBQJC5pliAAoJEGjrjHb46ilneUQAn3DgRYCBFQzF/RR3
-XOjKBgNB50CBAJ4k8dJuTrYSPXU2WM0Y3XN3DNEe5IhGBBMRAgAGBQJC52FXAAoJ
-EG6UdZTBUkMaQ58AoKBAz7nR1OS0kNoN3yBU4YEpGJIiAKCRP2B20NpzSb2zYgcC
-qS2TSZzRT4hGBBARAgAGBQJC6mP4AAoJELK+vEAVKSSvBCwAnAzwiq1dCT9MGJCL
-oXKr8cebn/O8AKDlq1lXwX6vuNVGFPVIn4VpWxpAOIhGBBARAgAGBQJDh5+eAAoJ
-EGY1tsDeiF3Tm68AoKMyefgamdmGNYVLuI3QsheDGbk/AJ9ih2MoXnNJshE7Hv10
-njUaDT9XFYhGBBARAgAGBQJGOOLIAAoJEBVFs/7iIt5POc8AoJohQp2LJJquG7//
-MRWfrvL2r+zMAJwNShvUvZpzVHUUcH1cTh9N/89XUohGBBARAgAGBQJGOOeiAAoJ
-EGPQra6REgPkWVUAmgOFzR2KNS8+Y4oguRfp8bmDvcO6AJ4+w6uNb5ghzn5P2p5U
-zMfJ+baim4hKBBARAgAKBQJGOPeHAwUDPAAKCRBz3YwWAVMCNX3ZAJ4j7TbIuRKq
-Z0mUwFV9UT2OhP+kEACeMmXLCi3fw9LwW2h2WIJ82+qfpUiIRgQTEQIABgUCRjka
-uQAKCRDh4fKwmQ7UqvVYAJ9BjHLDyGmR56xKlKF3qVq1+jAmgwCfQR+0qbVWaSIa
-VS1DCg8yUr2txOeIRgQTEQIABgUCRjxQRwAKCRBMBCgYMRo95VO1AKCewEwAscfj
-9VfTxswF6BL6zNj8rACfW/3kG7zPI2dSjWJzGYPQYPAa0smIRgQQEQIABgUCRjyT
-KgAKCRCYcO/z8S9gctnJAKCc7DZ7JzXgaB4ImiwB2dyGMFUC8QCgitOFKEw1y4+V
-1dNN3kZYL4P/M/uIRgQTEQIABgUCRj2gkgAKCRAuuUaCiIF0AjxRAKCu9kiQfvVm
-SrVZb9HK8Mazhut+hwCfY5guSOz96KH5dJ2585cm5wPyT5mIRgQQEQIABgUCRj3W
-eAAKCRD1wmAWTO7XX04yAJ4/ZvOfsexCgIQRuoREg1/D9bniKgCfTcKh9dLFkPjl
-D3yIw/NCc1L0/ruIRgQQEQIABgUCRj31BQAKCRCgctTQQ1jFhJmBAJ0TPZlIksq1
-EnAYtTTSb/tHpXxNUACfd/m3jaTHdJljRXGI7UBsVHnL0nWIRgQQEQIABgUCRj4F
-xQAKCRACpaYFC35s+iQnAJ0eGzB7NIQtXLEgyuphyW0nBppVrQCcDj6tm1MCKXA7
-f4zV1R0u30jrUeCIRgQQEQIABgUCRkC2TAAKCRBtC8c6QFgYNx9XAJ9tLptLbRXU
-SWe5AECh+yaLTKNvOgCfd7O2sNAiuH78GRcgmjsgXQ3L6BWIRgQQEQIABgUCRkxE
-UwAKCRAfISPDa9hyoE+oAKDWPLql5498S69gkQp8kE0bsVXA/ACffLn94G1l1F5+
-P3QV4iJLd2vcPeyIRgQQEQIABgUCRkx9AQAKCRAPRQomYhC/wB8tAJ94fMkHq0l0
-DhuM8RwkqLSwwVx4LACcCi+SN1SEXZomukrZyvhtmGblFuGIRgQQEQIABgUCRlJv
-WQAKCRAywdbvDxQ7wV0UAJ9IXObPPeVmYH6pyVSrur5hWB3eFgCdHI2LeJgtRWuT
-vjpey/NZy/xSidGIRgQQEQIABgUCRlJvYAAKCRDLrr45pGxMoTQuAJ9hl9e0H0Sv
-uIpegN+E264Mh0qapACeIY0LemIsEKCAw+knm9CnYqym28mIRgQQEQIABgUCRl7V
-qgAKCRCahtfM0arqYLylAJ95XaJv5iaj8pD6NiyvUHFhUUI6awCg7fXa8uC/xDjq
-G5wYir1o3aKwScSIRgQQEQIABgUCRqVMLgAKCRA5vlGhCEyRE+XjAJ95t+iWktlh
-0aTjwm5TB3ayG2SJzACgwYB005KhfKcj/r9v2OzFCXyqbBmIRgQQEQIABgUCRq3M
-VwAKCRAzzWczr17EUgGWAKDQJRDWHrWUIsGMT378q+ySuHVACACfSBd6rU0oS56k
-MHqFCjt9VmtKkXyJARwEEAECAAYFAkfAfZgACgkQGWWFUMMRBhHxkQgAsBgXGKmT
-sV+kNsSdStMjbftC6AqOm+tf2fsJ0fEkufA4GvWDb979EyCgkcfzKo/yJA8Yx9lc
-JUszowT8ShRABVPQzQjVCwFXFMhfI+pAjMK/rOJstjIRcOVAM1UHiGp2GjPPHKMa
-u6pufvnN9vyaVMyiP2USU2FUh1xQ5UvbEeQHLqD9ima5lv+m3gdcE5TJaSYUrzME
-zGFfDls644/bNImT2tm3vB0o2PeIL7/73frJdnOpYW5Q6rRFfrVG1bx7dIl+jAYU
-F3vbyyeyIPQgUtNeivrZoF8EnnKIYoVQEzwtDbsVwlqx+jtrxKIFsk4786zJDWVG
-8tLzmQz5dkNdlohGBBARAgAGBQJJyofZAAoJEMnHkk5RBH1mW3wAoIAwBzzrnaqA
-pU90fRclvOirrKQ3AKCRNug9jt34YXITA0IeT7Q8CaQ+u4hGBBARAgAGBQJKYKvx
-AAoJEIuttKwFuYn5uLsAn3DnfTyT6GExTjkPjAD/j6K/4RMIAJ9PQOUfVSsetdLB
-UWMHmjZOLPrsBYhGBBARAgAGBQJKZCSqAAoJEDzzkhzG1ETtQBAAoM90QrElPOzt
-ep/2thle7Sk9sucXAJ9Rb2IKhuUBhD6cskJA549iqCSFXYhGBBIRAgAGBQJOSOUa
-AAoJEEnH49G0aTGM+ecAninRH5sNGY+ZcJ0GOHH/SouXbp1RAKCi/Wr14/pPLFqC
-Gzy4MOZSABI0hIkCHAQQAQIABgUCTwRWhAAKCRDdnNU4LfQLN/KyD/40WruEbQs8
-xxUnnGQWOXSt1Q98vQb8ryGCiRbMulID5Xs+NOQozcx4Nao8GSxgcSsuxw+6SxXm
-1v+0M+ntbBGPi4KKJdB43GAPwbT89t3XRUMKCP6pYBYKms3hB8FCDwwiAaTWRerk
-SL8N24HlsdRALDrkCuD88K/URQc2mYNEe7nS1X+iws02zKD1Zp+LkCQI2G95bwjq
-aerk9tGtKatGe7b9z4mpACLn3iwhOWhOaFM1jEobssrXbbJr+J/EQ95PszLZHMua
-s/kw7RE+2AJRIAU0Tzp1iHkGhNH4MudwOH2wPD0ZM3D0vrRzqvty5aPTscrncfKU
-wrXn0pj+KPwxOHWfgx+VDTLeun2BYYqkzpE3Aer8DCvH/cc3rVVM+aMhrjGx2b8l
-vGb781MeDMOnfijdAjhW18A+coZzvaQIpwzELUFugjwoGIixZbr9kNEzh3nEDkuX
-smIpxRMtSVcqS4l9GgCg3vA0toDQzCCY608D5O/5HZ0d+Vl2Uc3bLmnmS/lL1p8X
-4mUQPfsaHghQMsTWQLNqcrqnLUxTK9hRL0auRCN3zELHmBhvfVqutV7Rk4RmbfdE
-UO0LeTaXVKskaqC0a+zv5W0Iv99srV9BDCjLq2qotdvKodUi5bl4gSeqhalNt7gM
-UegCoeKbsf/oqlSddTCq8nlfn+Mc6n6ZfokCHAQTAQIABgUCT3RmNgAKCRDflC/g
-uqPk+VlID/9lYtwCb0rdp6QZU5UPEuR8J4nlr3pUTruxK60aWuOSifE1vKr5Scim
-mKsTUz6faD5A8g1n0Et8RqBmAii5N6IwwzHJqxiw5O/Gb71VvwlXuH+Vh6TOOGaT
-7bVzUrxmZu73XgXfH+2rbt3HeLMfTS/7PwTV/2sLKHQG1fg0/ejp91a3i9JV2FK3
-V56WYBJmUKumTs1wtQQQqwdY3L/O3LhfnRPAFY2Kn/85VN0Ngnawmi209DN+0Q1g
-QeDUF5MbKjvyShuU9Tg43m5gq8eCiqxpFZToNhUr7W4rJc+YoAkvG+NK1bPVMNLM
-WhXCkFVjPxLCU5kagjD1ePz843amEYHbH06IOsyr3Pwp/SXnFZclVZiIim1/KqBD
-Rr77RbhbQmN2HESKvyObDe3MHVSd4eCrbRvTSo16AO0+3w35suyG2uglMK4GTx5B
-kV35rfFtYCgVB4pDF+KmMpeyAdQ/3cULvumGNlFW4Z1Pqw6ssbKZhrz082VvTqoh
-OKDtAianxJcSdsRHXIJN4kjbM4UivDBpr6Y7G7idrnQsKQgp1JqquO1X/XN1eDsa
-LmJ6k74sbac/SCSY1yiHwZSb9taSovUxrVyR0g83hXuiCcbNdgORjyfezinLXCKM
-MnIyYtNlnQHwhhHreDTX5AsMA1ThvsB5x0bWqp6Pm5Bl1V7Y5ebvt4kCHAQQAQoA
-BgUCWEe6IQAKCRBjf6WERgZUlsTyD/wOtkH3+cS4EMPAlL3BzveBDviUpgUuCjca
-USP0P3OfF3+C56Rsz+D81ly65kXZAaS9+3++VAXdTedWycXsd33dc1q+Ai75Qnfe
-aiBExRkcL5Z8P+1pRR8C2WlfChqcjRGB+LPDv1yNt05VTfdfQ5DqnVYtDF+RPjIV
-395qFDAnhiDqAywr5DGg9MSHppeHPbDtmJSGH/dPflersfqevQFBkN01hHfS4X9r
-OoD+lYqmLMnbSEnpZHlJaeh7AsmftYM1U4wQvIbSoJ1Cv/K/QFmYqqgiNu0ebznI
-og+S8yjGFZ2lByRzKxOVPu4ujcIW0qNb7fJQwCikkZ3Mvij9J2i2TBYpd5Wy5hrB
-6P/vp+rd0e6rVuYndqzRhNB4NzwZlYGi2bRLwaQSXDTIpdrO2U9of379FOM7gUFI
-Qg/LLXD4HFHDJ3K9XEc+F1eYn9fG0S2rbUHNLmydfc99TT/p4+gxUGi+X7WF2ydl
-x1nY3w8s/ET+HDsywl8Wz9f5B1wKyzbD0q006rM6dgZwvlzNKFrTf7IaJfs7ofHB
-fETktSkUk1QXlSOpp8ocJVylcEDSIQsXXstghN9gFsuq0qdtZ6OFI6/fHGBRO48P
-EST3LQq51a/1tt1Z6ZwsoYsASM8krAfTCxknfwxCob0qopmqMtuZQqFgHd/VZAsd
-O+IDUvXFwYkBHAQRAQIABgUCWXH4+gAKCRAXdF71VJepB3rXB/9K/MINYV5hfyeI
-/ZF25F90lcO/ZvJwrrIdbhPlZdHyA+sfKhDb9RowM1xLAwU/FtMPrZg4pDehonkq
-g/7KUChq/HlHTN8a7BqI9MK1Bmqw4Lu+XzfnYlp7dh7SZDJG0v87sqBjY4BTHuIH
-0fJ2zj2AvlkDGWVbd1CqIM2CftkdGjLIPyXHPF1j4dEKirqKXFa8y+vFGpzKiSyq
-lgOZc9+Mc1+D+vNl8AVCDBqyWDzru17BH88nwZwsVZZrTbandE+OYllB2J2zM2uA
-KNVDbLjzKH9GVPs2Q4VT0EbHA/aAHq2I8wQzHQM0/knB4b8w6hdX9R+u4wOlJAYb
-qLO31GBOiQEcBBIBAgAGBQJZcgr9AAoJEBd0XvVUl6kHhfoIALyTNGb7maMmJoe7
-t8nAm3kX1/6d3rhVXv6pb/k2Hut0lLRN0M+oMDWExNE9Y8eaEiadaW2yT/sQSR8V
-sLIqnmIggB/ju5+ydXOjCuDdLh7nVM9Gj4DkJPb/KBna2kCBrqvCK7cPQlJ4O+CH
-hI5Lj1Tm5f7J90lOm3fcKOoPlU/uzvvZsPqh6h1+rrlJBb3wpQ6Qb14+qK+I5GCN
-PNbbJ+QY9eldQ1q8cdEzFS8i8+eyj2X+zxiEAQ/gkAV7JxLLKu+uKfoHq+BRkgqP
-QVweGVXeuNb6Ng8UXtIsbsH/2A7I3dOH+je32uuu5jxaY34TJJvSE/PxUFFr2otY
-xK53CMmJAUoEEAEIADQWIQS10bBTFHtMTL5JaA+WEpPX9Ca6oQUCX8KG+RYUgAAA
-AAANAAByZW1AZ251cGcub3JnAAoJEJYSk9f0JrqhdhwIAJAosn82PIZj/vkKaxuS
-yWPlwkouB0CHRCMrEerAw5OqNdfIMXt+BWBfPW4H+jzmYVRkJlW85+HnC3q5qFCJ
-EDkTufDwLOZi+CtJsyrf1L1M74PY6uVnaLeuRSDH4a0bmkHdF2pgoh6a/HR7EvsF
-uxlxGGg309D5vhLV1S4tzhO/Ry+avNtPnqL/bdLkxYkiHCg+TuUab9o8Pi/61tgv
-x5NCA0nbznAe2Y5M8AJWu+QZZT52NxtSfCYVRUtGSZtlAbYBqj0cg7xdJ6B/R9Ko
-+z0rIW/iuOLdZGoPWnJHCHuNZ10lsWbqXa6SZFgJqghTSTQMxDpxZQpB048qVvlO
-z1i0KlN0ZWZhbiBCb2Rld2lnIDxzdGVmYW4uYm9kZXdpZ0BmcmVlbmV0LmRlPohg
-BBMRAgAgAhsDAh4BAheABQJKCR6KBQsJCAcDBBUKCQgFFgIDAQAACgkQohFa4V9r
-i3LpKgCfZfhzR05NCnR2T6h+88My01YFshcAoN2tICdI/+Jpcii5OD2dwARGdcWC
-iGQEExECABwFAj5ogVwCGwMECwcDAgMVAgMDFgIBAh4BAheAABIJEKIRWuFfa4ty
-B2VHUEcAAQFPKACfXhFOr4gMMIQwEGvUb6J/X4asuzIAnje2H9T1r/jSVi1NbIEt
-QfbpmyQXiFwEExECABwFAj5ogVwCGwMECwcDAgMVAgMDFgIBAh4BAheAAAoJEKIR
-WuFfa4tyTygAn14RTq+IDDCEMBBr1G+if1+GrLsyAJ43th/U9a/40lYtTWyBLUH2
-6ZskF4hGBBARAgAGBQI8PtWPAAoJEIEEZE9RiYUEnZIAnjOkQx1BfxN9+E7Yiz4M
-OxqZjSUpAKDQi0Alv/VR61fmR7KHZ11J2g+HSIg/AwUQPnWqOP1viMYh0KcbEQJa
-ywCgqeRHrdtYYIUMHlgm19kn6dCrdMAAoPVvMb+QhNCkgexPa8JjXIGaVZsFiEYE
-ExECAAYFAj512scACgkQ7tHqOSJh0HOZXACfRTqAC+LhzLqh1668bBFTybxCdvwA
-oIGjkethM4lKnKqXZv9Wctz+E9toiJkEEwECAAYFAj513w8ACgkQPo+38viDQdmG
-kgPnUYJfHlDrQ2jYJWuPDve9n4pV9OvyIllKyLdfULjsLWXw4Jm+fMQJgWr2GEov
-1ZYIyS2+rGDZpbz/vxaBVbgqM8TPdiXzxwU8AFq4k+Em4fKXR58ByLSJjvLLza61
-spNHJennEUFp3tTpEsr4bNuuaoRYhtiKzTqNuoC+0x+ImQQTAQIABgUCPnXfDwAK
-CRA+j7fy+INB2Q/tA+Y9lc+LubrBGIuh+xOUcJsGtH56FahJKoKYdCM3UMZG1qYY
-TpfxBswi20P40un65PHyP8TSwZR0+daSTLp/C3V/cBh6gCAJc28+h7CwLqZmfcUx
-0Sjq8lzjcWaGxR+6Y626e8Y0Gdd0zwZIIn5EFL8BIyNGsQIXXb/XjHCDLIhGBBAR
-AgAGBQI+d6QaAAoJEBU/oM11pnaS+9IAn0kFlXAzOhhu4r5fglMVuw5bTAd0AKCt
-YRX2ESU/+tsE8vuXWtsMCGeI5YhGBBARAgAGBQI+d6QaAAoJEBU/oM11pnaS9XsA
-njknu5Trn4XN5n017O3kr6hArfPaAJ9FTPmIEB233Vad9mBOx7ejehj39IhGBBMR
-AgAGBQI+jc41AAoJEMppOXSBA6N+xYgAn1HbGamcXTDYSFjn3U5ik2vQa8nuAKC/
-uUM01gsdn+71EiAkmrjlH6H9MIhGBBMRAgAGBQI+jc41AAoJEMppOXSBA6N+jAIA
-oIcAeCIKt2QBPnAthnUk4DhlmM7FAKCA0Iz9ZutXGb2l+p8s7hhF3+Y9L4hGBBAR
-AgAGBQI+yi67AAoJENvSRfyzsqEsSccAoKqG39X2y6xoQa56nviF5iCj/oTFAJwL
-Kx9GyKEUbSM9f/IQ7AsZPhHT54hGBBARAgAGBQJBkvP5AAoJEOQTYTMMqmi0GIQA
-n1mpdHz/wV++rSU2Qn7R32slfNdpAKDJPqpnmcN4MUmk90yZEeHAdJmrhIhGBBAR
-AgAGBQJCuAqrAAoJEIEEZE9RiYUE0MUAn3cWFVW03CDuMuA7TSUqTf/eWARWAKC/
-GjQnPZ0+g7NbDw68ZSY3k8WuuohGBBARAgAGBQJCxTKGAAoJEJvyI0Uv4ovP3YUA
-n1z8L1EnLdIYttWrT1zs0E89Lz4BAJ4sFzcSq2NO3OZsEQfh9F6CrUe3UoibBBMB
-AgAGBQJC3qxxAAoJEDGmPZbsFAuBGDUD93nHzcDWR6AuDxDvaDp1xR8oJZHojeZ9
-sWSRQffiNJKF07vvdjGbygqiWbQmtTM9qBnAxEiBpSpJemBhvGTKivPkb9H88KQe
-2jqowDO3IJorIVMT+eUFB+4pn5c+kFLD/IhG7ohZ2rBIc47L62FFuD19esxvMcVe
-lrBFq67ZV4KIRgQTEQIABgUCQt667QAKCRAyyeTONkLLS8GuAKCV8K20jEUapVMt
-Or+eE+dEUwdf1gCgzhnTmhO48XEZZLhHPELMJve+mwCInAQTAQIABgUCQt7H2QAK
-CRA34/Rf7mXjIY9vBADqrguzlNOJFkWvEkgdVXCCH2TP3OUuPZ9JQtbJfbkg1nn1
-hCnMITapNJlEE3yyjB7kEpBkmUtyKv3VSwODspfis/ps6zJRIne/2R5xqtT38Hf/
-sYucoMZUceipFAoCLYOqkKJKwTpYM0401dUpuxp1y8Lq5N0SDtTW9fKMNs9jiohG
-BBARAgAGBQJC30UMAAoJEEHqCaBXk0mPIUgAoOF/OCzco+n/3sGJ57m0+aqGLOwj
-AJ9bC86B2hRvkaZlGm/ne3TzCgFGnoicBBMBAgAGBQJC32x5AAoJEJrNPMCpn3Xd
-ek0EANLj3wh2FCukydsfSzqgjFDpkVjiBxbTtCep86flaLMrF3H0idckGCjMUf/J
-ostBsjwCpL2VlCtvhwl5ZgIzm8luceHupq2iC5hvUN0IjKuIXMLbZP7DE+Lfcvw8
-2nKt8JNPpjosXiMhysQZms2XfuNP6f/Ey8J5jaB2Z2JCYWJBiEYEExECAAYFAkLf
-bHsACgkQUI6uxTAtpWgipACfTBzbyb7Vc0jr2FZDiXJFUSBCoEYAnR+ySWmedkcJ
-WESStqRstD8T72mOiEYEExECAAYFAkLfbH0ACgkQ3bpkuiwxLS/5RACgm88lpYDx
-y0bYF9/ubFbvqCw6i9YAnjrQoOLRBtQ4QmIPR+T/9HReOeSciEYEEBECAAYFAkLg
-NdMACgkQc84u+4QI91WwSgCfaGrzDQlS18mm7dKYxSQVksEWbf4AnjynGaMdeOgE
-kamiRfDiL0J9vnoGiEYEExECAAYFAkLgyTwACgkQXP03+sx4yJNXxQCffoccUBWO
-51YIEM0mbsqpnKHtawoAn2xTiDgo3TjtbRJskADuw+QnATQLiEYEExECAAYFAkLg
-7MwACgkQybWm7OLXdN8bPwCfeKtfQWKm8i+KuFJTIoMTvAN65QQAn2A9G1wtEN4V
-zg6HfnTvtgus32rRiEYEExECAAYFAkLg7UAACgkQW5aAEOBPmonAkwCfeF3l1lE2
-WijQF0BmPMfqvkyA2UcAnRQzuc7PWyP0nydGoJvfEUHByVs7iEYEExECAAYFAkLi
-Ym8ACgkQbZiNF4cxXDEC6gCgqICh/djzt1i6uadJAOztZc/zxl0AnjR1OaM2JxR+
-wqK3loSTEKX1uOpBiEYEExECAAYFAkLjVcAACgkQEy5J1OQe3H7rRwCeJWLmLyPz
-pg3nr65j7AxqGRJeDfUAnRT2Oa85dAM02wgdYlj3FejPuNFziEYEExECAAYFAkLj
-ZNsACgkQdcqio/ObN1DA+gCeOaeMarEJDPbZjaN3y/Pf5PB/Cv0AoMGPjPSTGt/i
-HJ2aArfyd0ME/R52iEYEExECAAYFAkLj7WoACgkQMoZOQZyFIiv6jQCeMior8Tg4
-msrRc+FfXfj5Uln03d4An3RTaHKU+Sv4SgEecXlW0RYlVa6eiEYEEBECAAYFAkLk
-bxQACgkQjON2uBzUhh+lnQCfVbPGF5UWlzFbxK+xKmY2DbKXb5wAnjpoAxffSRO1
-PZlQUHgWlS+NaeCziEYEEBECAAYFAkLkkscACgkQBJE0Quobo40fbACgo9YCJXu5
-Hpoc/SVp3rHCYmTuEMYAoIt2q6rPL/JbbkikbRqausEnFstziEYEExECAAYFAkLl
-ELcACgkQUnkvr5l4r4ZC9gCbB5X0rL/DtpGptiNO12DdTQqzsMMAoOWpJFg3W7zA
-r7alVjqlx0t1vS4KiEYEExECAAYFAkLlEaUACgkQa3OhBipiP3LYawCgiuQqhVay
-7FE8e05Za69seQwF4CYAnAxBVNyvXu/1aeAuSi3iC6tywvFoiEYEEBECAAYFAkLl
-wiAACgkQYRlqLjM+ToRP8wCeOVAIpaG+q9G7uJgVCyDZ0JbjjfIAoJgg+NrBfhNe
-OBuu5mS1PSGDztQ+iEYEExECAAYFAkLmmWIACgkQaOuMdvjqKWfdbQCdHfDneYM+
-nWXT/oYOqohamLvk8iQAn1LLJhkLiCMOa9/biF24zKt+MjaHiEYEExECAAYFAkLn
-YVcACgkQbpR1lMFSQxog0ACgp/m7d/NdNP0w605VyrJWCdogeG8An2E+FpFBQgyv
-JaD6klzDRNNYLc71iEYEEBECAAYFAkLqY/gACgkQsr68QBUpJK8HfwCfWgNlYNLB
-Wmn/nejlx0m6NstT2CsAnRdhsusv6RbcKNoVUudxGG4Xm3nGiEYEEBECAAYFAkOH
-n54ACgkQZjW2wN6IXdNgDgCfUVMGJZV/D1QEdnwrTkRmMb37KR4AnRLDWMsKtq4q
-KXQjYbmuLNdHa1EQiEYEEBECAAYFAkY44sgACgkQFUWz/uIi3k8H/ACgmKEdToiB
-aw1wAMXXKjj+8PTU880AnjTWDVjV2fZnj8iXaOK7MTx01gMRiEYEEBECAAYFAkY4
-56IACgkQY9CtrpESA+QXcACcCFtUvEcmTT5ezAsMsWPbRJAqtwoAnjFdqKAoBDkP
-r85/VI89GhfttMRdiEoEEBECAAoFAkY494cDBQM8AAoJEHPdjBYBUwI1PekAnR36
-SmoXYYegiEUSKxHCjHQnnYnbAJ9zmdCCloaaDIyqh2qr5x2jJscjHYhGBBMRAgAG
-BQJGORq5AAoJEOHh8rCZDtSqiDoAnR8FA/yGXEAd6gP0AoioyMHj6e0KAKCAdnxX
-UB/eSwN98EkeVwSPpiBLG4hGBBMRAgAGBQJGPFBHAAoJEEwEKBgxGj3l+XYAn2Ok
-z5W6SabKyirUGjF30lr9BP8VAKCBqsPWR50O8vcG0lDLkp1tuW+63YhGBBARAgAG
-BQJGPJMqAAoJEJhw7/PxL2By3XsAoKONmq8YyhYqvpafW9dX7k6r4pg5AJ9Sjki0
-Wqrm1AYXxAYGc8fZIesIf4hGBBMRAgAGBQJGPaCSAAoJEC65RoKIgXQCTFkAoIq8
-9nYh6AmxcqwQFeYiloD+FGv0AJ41la0vkis1JUIDM3FNO8xw5VbNZIhGBBARAgAG
-BQJGPdZ4AAoJEPXCYBZM7tdfcxkAnAsMAnhrvQNVPQJs/P5ysQTKHXZ7AKCGrxUF
-i5FQ93oEuWBGqw/xHcMfVIhGBBARAgAGBQJGPfUFAAoJEKBy1NBDWMWESn4AnjHz
-aapJEaIYFhc/39hIRm5n0dl9AJ9lAXqmz+YQSqJKQ/cchdKbLdhSGYhGBBARAgAG
-BQJGPgXFAAoJEAKlpgULfmz6xg8An1EFGiCeI1C+7BUDqI5xlPps6WB5AJ9cUoE8
-g1ipE/QtCVYcOUhD53yxY4hGBBMRAgAGBQJGPwYxAAoJEAP2jL3eiISgjbsAoLzd
-vLd5d8mADMZDFLi9ywPLk4pBAKCt23xxWAwNSj5W+uPGLL6R0IEb6IhGBBARAgAG
-BQJGQLZMAAoJEG0LxzpAWBg3YX4An2XrLaazjvwgpUwVEj9KCHAq9FYBAJ4khHqE
-JHjpBjQioqGQfL2Z/NqI9ohGBBARAgAGBQJGTERTAAoJEB8hI8Nr2HKg6F0Anjm/
-ExEyBoePXnjwORS20+/Rx1gdAJ0aVz/9sdWcnDCVQXP/U7ixfAO21ohGBBARAgAG
-BQJGTH0BAAoJEA9FCiZiEL/A7x8Anjgvd31Atoy8y9wjvxowEkfbLZ1KAJ973Fhg
-y5i9/2oSWKGKX/tr/2nrwIhGBBARAgAGBQJGUm9ZAAoJEDLB1u8PFDvBEgMAn3Gj
-h6BSBWjqH83sDmcwG5Pd1nqMAKDLY5za4VhiEa8ECBCkeoRJl/iy44hGBBARAgAG
-BQJGUm9gAAoJEMuuvjmkbEyhglQAoL+JREGW7kkrFkmpQnoPaTNi6ji1AKDFOm+k
-NYqqsYgzw54D89t1QmpOQIhGBBARAgAGBQJGXtWqAAoJEJqG18zRqupgx3wAoMcK
-QRL6tnmUztp7C5X7+i46ScZAAJ948yxdrkvg4qMDezOdydmRxzpaXohGBBARAgAG
-BQJGpUwuAAoJEDm+UaEITJETPdoAoIVf/V5humFKY/Yph+AeSGDod/VTAKC2Nmsl
-Q2e6Gw8ZEr4Wih52zcxq0YhGBBARAgAGBQJGrcxXAAoJEDPNZzOvXsRS8j0AoLVD
-N8WkRLiuBvr7qWrNhg7Ylb1LAKC1mSGqxofl69FmIiCXOMeZ+A8mN4kBHAQQAQIA
-BgUCR8B9mAAKCRAZZYVQwxEGESOgCADhwUA+q0JhWkR/Q1zt5yKrGlQsYtpQI64N
-8xmLPWRKReLgWIMAptJ+twYA+YuH7wCJBsgP7U8oi2x9azlmO4HMnDa2gXs4pJbE
-0pRImhP5JqkYauzepvLBlZGLzZ1zCpLE/JmaxB8tc40lF4/CBbLj5EE2+jfyPWEp
-lyV/zEwjjDXAkxSzfhdp70EYyguGm4n6M4KgbgkTdxR1/uG+HIkq0yHGsCJhViZW
-W6tKG00XcLOGrm2bzQlv2bXCVlEWC9QTqb/ZdbA+ONLSWdmegEVVnQeUx3jtvRg6
-7yJ5LXA2CSq2lHAGoEEfZc4ziRHmn+5Pusk33Jq/rPV8QSCZXlMbiEYEEBECAAYF
-AknKh9kACgkQyceSTlEEfWbGtwCePr57kk5WrDbIcRgYgvl37P2JRF8AoJHpjz2M
-wXPO/asQ9sCsLE54aa6uiEYEEBECAAYFAkpgq/EACgkQi620rAW5ifk48gCdHdnY
-/BsekZsnMZ6/koe2cFo0lCMAn3me/4UgZo0+bwc7hEIAOSJy3/gUiEYEEBECAAYF
-AkpkJKoACgkQPPOSHMbURO1KBACeMvU6BjYrBP+qPWLq4uypobqUAIIAni5YbvPO
-cL/YBcgZFNMGykoir0nPiEYEEhECAAYFAk5I5RoACgkQScfj0bRpMYwvigCfQ4pf
-WihxYQNGkPyQP3z3qLO/wqcAnA/tKBHggMa0Gbr2oR+BcEUQjvhbiQIcBBABAgAG
-BQJPBFaEAAoJEN2c1Tgt9As3HNoP/RkNKJsN+uUcpR+WAL8PknLypWYl41/VPuEp
-LoIv0a3Euy44x7iygwM205VVE7pNrqXphrztrCpeAA+kSvYFQb21zu6bxceN6AC0
-wlENtf3R+6ApS3CsZAyFiuBZhWPRWo41GMY0A6Qdpo69H9s3QwlYmm1y7bXTrHY7
-4gOI0yfNyAFdkwqTFve+tioPmzDWFO+z+een1iwTyeVpJZQhrcFcAcTd5RqGvPM3
-/lj+tQh+COt5hG+TBp94yVg+Mv0qioW6xECS+fvCYv1nxayqaa5wZqDm+17HMJgh
-vWVhtFCxoTqedSgoVegPWLXjXTj01oQ/WEYKexj2lfRYAIbzY66FpAMJoOxnv6ls
-WNJoI9ykj5hPdRwHZ464Pp3EzmQzJwzQ6o/D/dSKwQnXdcOyuzI21tzraEbn5XG3
-a4o8WyMbpnVsyV7UXPtbWDBEZE2SOizT1KLJAJ+Myy1UuLjGyZHTNz0u2wG5dJWB
-uKIIeex2itL6Zl4uw8cjzj8Bg3NeP7GDb/F8ZP5UWggNzyPHjUKaXXOB71CoSp+3
-2fXmnqR7T/OYjs4uwx84L6USgN28R2lEne4nup2tnEFUE3po2zsBUhpKuLTHkRh3
-OcSZ+y0MvdS5+1VNuH8Dfif8xrpyJLXpYcYogigRXUO9mXPAi61bfCip+M7E+GiY
-yvRoNQy7iQIcBBMBAgAGBQJPdGY2AAoJEN+UL+C6o+T5TigQAJz9aM5OVJ7u8SQ7
-+piydPvNqmsxkHmEzG0JqE5xMg0T/Cq3qTSnPxsVQv2nHTDY6re8mvFP6QenFu4/
-hcmaGZF77SEQvOoiUJ9regXfQX5I/FF752UEQIPJV0EkbP9mIYFCYF3Ns9GTHmX/
-HLe3Tj6AOM8jwFRyC9zIYRNRf4TpVAl4FLJgpCPgWuUPc28fCRUwURUT3CdDA2/l
-Cc3bjafEy0oMHEJaxx6iPFtmKKT7ZsPzSeD+cbYJIC/HwmnggTMymJ9WV9LGWI6Z
-0K29TZkjLyJazjvxowWBBVruRGtbTG7sUjj11THfn+UPHI+BB4r+kA4hPzCesim9
-/S84w2gb5sjZgg/KErQ0/pvF1ifzDtl5wiSKr4+IrDwAtvC2f/bxc7Em1zzJzHt1
-q7Kc1bWNNv3LsWKUxvXxax8PnOPBJ6EPCfGLHtBGdN3fHX0GD8MyDApfC7D4VSpB
-aCuyipGBsiPjO4epNHDSCySSpu0ePJhBslpEg3zrVmZ38yU77ySAA8CYS6gn28mA
-HIDNe6a0IeUeBcKEK8/68hSgdyjpBwbyQRXFzgVkJcaGZBIUESxUnV2Uo6LJdn4H
-U5kRIytHEo/8W6Ra+4Uk6OzL7MVvyxFNjrIr6y3XFgBnPuQ1+9CEuXymL9JMsQIV
-XjlDth9Il9np7tuY8rN8BD66cflWiQIcBBABCgAGBQJYR7ohAAoJEGN/pYRGBlSW
-+eMP/2dILgqllMW3Ra7krLI/B9/Y/5DmILETkpl4ONmHISQ6LnVtlOgRpubvEAhi
-PyOJJGmn695YgUzyxwIOGI4MWlqOpySZJLB38gXkfD2breUBUhMJ0plb2ngdbuLA
-edOMaAiYwDLkEEM+lqygyQ4bVKojfsOKkMnEUUYTAu+gPswRYTDfTAm+IFfnHZcL
-XUQbEvNsE76F4Bc/bzgunmGCKuQRY88dQ8Q5VWt+kuRyhsOfVZRobSbxR5C7UZOb
-Pf4UmbFESo3e9SVzCo7WJfjbtmNCzfPIexx1QDev8Pl9tULLwLUPugLA2BwdOcRa
-gMKBsmmaNlF5vVtURKJRga6NHymplFV9/UmFBac6aaJweQlLj8ZG0TTJ6GRHfHTF
-l/r6mqrQEhWZNmigoACBpWk6PZcOCMN3GnccnnSWtrITFODdgDPMS5lBm3pN83+7
-lf/KUS1BOJSC/jV1me7VIW+U4nBRL4sp3j9Ze1D1uVHqxUOdC+NcAM3s4r3ro8ha
-hjgEfriYXfJSlBJvEm7dVfiMYEynjCgCg7/X6QTa/IW7JV3UNL+srOn1SMnRwuN0
-A3mvkZ82QPfyLrfaOmkVyj7iAgCMZTQ2E5x6Oo+npG71331j0DOX5JIZhKwZ0BnB
-OwUYRnB8QJtmg2RqPE1AhAcXBY5RaBgVl+xn8aFCg0REw/bwiQEcBBEBAgAGBQJZ
-cfj6AAoJEBd0XvVUl6kHoPIIALQHKd71aAZ0u1uRb0iMNn52h9x4R0ue+upd6pcG
-K6jlifoimxp1hP7Xr0PHW79MI2V91MIYyc8uxbZPanZZ3tJB6JZ6CNJTFHFxUxZ2
-Kno8FzgrONGcKZnMhUoDl36OyNAHcHrqVIZfAImACD7cP8JO/KoFMWOubfhAOrHJ
-uSN/Ra7ge3lXalfn++8IldZvn11bKNoH1QxMw920KCbc8qYQmkQ4KPpcxIA/aNXx
-nT24SAlV0sytAWqxsgOZkaVdWKQPZY/tTos3AH/klkNPWESHEVOxGEhhN+hHT2g6
-GLB9lRja7Etr//bhEmfkLjWYfFtrDOazB8qmeIqzeDeqjxeJARwEEgECAAYFAlly
-Cv0ACgkQF3Re9VSXqQc17wgAxDpkqwr7KK972n4KnBc7zGFzi73mXcIj1mg/K80y
-tG5IJ1M0bBY2zHewVlg2o6A+N2z7fDWb2Yl0yZm6PcESutZa8Trt4B4RWIsWdFol
-fwWCc7LyOfNjsAU4SPYMc+UVdCS+Tkq3oEGSBGdoQmhpyRURiAbCXOq0rU+GbXKR
-n1QwCEg35QiZcFT8Ma8izS72fTaGrqJghhPeuDOl5yHLvsB8tV1EFdMiItIy0Wzk
-odcx/eIdM2QESgBjF5YcWt1971V60XQ/xT8bl0Ieu+FZWqjg1bQCDOWRjkBGZ0Pm
-yKpfZRM3alRljpuNtxPDIbwMbpg91PtLaEw2DlqzCy2MPokBSgQQAQgANBYhBLXR
-sFMUe0xMvkloD5YSk9f0JrqhBQJfwob5FhSAAAAAAA0AAHJlbUBnbnVwZy5vcmcA
-CgkQlhKT1/QmuqEcbwf/QJImfsuqdMFA2tSwinFEiUDb09OST2vg5cONLXlYWdMt
-ETPKFmZvbIB7eOMartP13cb/RJ3LdWyZIhS5hnCSOPEN1IVfSV6oSIGiOYPMjZBJ
-qYk/M9Xy0h8gKxSRt6OIjMYgC/eMhraM1op94BPeM7WL8HTQEaslgcTBNg9vGf6L
-35owAsBrWY6ZpGB4ht6hnSMBu2mrXSOTE1V5DiLh9KoGiTDY9w55UVtz1jzLjOlM
-7DIKggymmqGAwrxZLXuFUlg0BO8577oibagJ7LVG6eTCClDI4w7B9SXdCjj3OuoC
-IUWwUFrZfmVkgD/YkAeEezlxsVSKCVyCYnRZyYzq+rkBDQQ7EiJUEAQAzVKWS8Qr
-kysydbTJu2/14wIbz2Coi93aAGelwCwXSxf50JpYdY3Lkcvd0FqT8bcEnz43MCSx
-8vlKubQtUpx9WMGIb4ixtShLJ4lAa6FJldhychz/dnxSNyz5N8W6sby4dTVxac0r
-loxjAOurGanhG7TMtgfDi0cEEoXRyAVoKyMAAwUD/j1pJm4Npq2mlJoE7MK3vAhg
-KwYHFflmJusmqvSAtRuFdT15pbMJrA5bAK+lA3SVOOhhWTCItlphSR2qxJCAcBTe
-OMqUi5ohFcCkSRNvwmDtH+80B3BehlEsEKNk8Z3moa2ch7Oxnb6XEXH5tGJ5Qvx9
-Qid6ZfBaXx7bc8yKyCb4iEYEGBECAAYFAjsSIlQACgkQohFa4V9ri3INMgCgnc22
-kj8TfjktU6u4SUUqud25ZZcAn0B2b0zPjKjGuiwdKSnkFbNcFS3giE4EGBECAAYF
-AjsSIlQAEgkQohFa4V9ri3IHZUdQRwABAQ0yAKCdzbaSPxN+OS1Tq7hJRSq53bll
-lwCfQHZvTM+MqMa6LB0pKeQVs1wVLeA=
-=Td5q
------END PGP PUBLIC KEY BLOCK-----
-
-pub    21939FF0CA2A6567
-uid    Alex Herbert (CODE SIGNING KEY) <aherbert@apache.org>
-
-sub    A98BD25BE464EA45
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-II4Pqx0ip7s95q54JSpekQZ65g==
-=QoHd
------END PGP PUBLIC KEY BLOCK-----
-
-pub    DEE12B9896F97E34
-sub    9A716F957BC42546
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFAxQKwBCADJGPv6pmFEq0SDwAKESEgCdnXycbR0bNXpNa/3VGboNto1xKgd
-AQ/sI5x+CmN0hpUjklEwff6QIt3MlofEMkAzSfRmTobhJTK9W7r4+p5DuhJpi5Wz
-ITdbNCMT3Cvp13rRE+dx9qY+WFQmTYPf3gq+C6T8Q1i35ePNlCTN2RayaFxxR77D
-W93zKZDdd7I1qH0Vx7GGcSwBgBlEB8jmhNAkz/zAhv53S6px3ZttqYYmuwRtg6Fi
-i/u9VoDR/c9tyUq8L6oAUtg0mo4CP/tfUF/uZnibshEsLzbRP961VQXduhn8HcRp
-k6QPTj37B1vsNWJ9U7XXJ6pYnkizQo7sl5XxABEBAAG5AQ0EUDFArAEIALyNR+z1
-eBBF4S+dOEWKXz2ANmsp6RRhvR09QeQwNycVdbdEXpOiSZUCAkw/EhuJWmHBngat
-0KBO+7CIHyQqwHnqyatizzKXi1OuaEhMzPsQMwPRfYyWHgN0aklc5oOzB2RbSJN4
-et/oVvfAplVSjgR0v+56+qXw9TFlp4kxqFeJLycZ+5ImKQ+XclsBokKuE7cjeF+g
-O5oY/CFHdkxD8d+cLF8FSNUFMypuDQ4IH9zPYGkUJqsb2t67iMyxi14RqyN2YNqK
-JcwxTL42VBlUFlTBoF2Y3w0LNll6pR2WSNvpcj+5/uBjtY1qAj5e7yVts+d1YZsX
-7D76AV742RQ31kkAEQEAAYkCRAQYAQIADwUCUDFArAIbLgUJB4YfgAEpCRDe4SuY
-lvl+NMBdIAQZAQIABgUCUDFArAAKCRCacW+Ve8QlRhFDB/9xE/cXf5fVaLa598xL
-muXiD9U1B04dPdz445/chdDS9iGWBB+5QVvAqv2Jt0hyPN0+n9Mk/4lLStEEL8TP
-NLdTBP1JRvVWC1c+G3kTJq05Abj8CGFFm1UZhFRwCTJ+vrv8fSb15s+YYxBLIUdl
-tKld6OupTHm8A4XJQOhYxd5PHs72bJ3bXs4GmPLKD/RpYmXYJ9EZHQHKnrhZKJ8R
-JKTM6sxBrgdVeI1K0ekA0o5HAVpNEXgY1gG8Pa14jqK0iwlcI02ntqeJkobvv1wN
-vh+nJT2wM5QyLH737kdPrUdi63PfCYLOEHYhI6sFkzI/DAtI/C3wmHtTuRam3aLs
-Rnb7GNQH/i07ndoI4trmUor3X1JBbcjw2BVS+idCtML3jhKtziwK2/kz0rJqBQKa
-Z/zxgEfwkRPqhXLaBW8a1G/d1mGphazHqSaDqylz07XqR31ZtGCc6256anaVbWaW
-9HXUsU5ADNrAK9PdD0EibGB8YumuSTtApICUqN5SVz+h3Mi1MXVsmbiVSAZPzLTD
-0YRwzPJ3jiXIrKDUmZMM7oWwGx6nzW++tW8aKyLKm7x1/y8g+XHvySQiVOKAvvxj
-yPStkEW38Rls5nucpyLzLjoA5vlyIcOkeKCy2jlUmM56YrAIWNn/eCRFPHMOY1DO
-B1nUXMr+2W21xZO+/sWrEEysY0mdGU0=
-=uzFx
------END PGP PUBLIC KEY BLOCK-----
-
-pub    3F00DB67AE236E2E
-uid    Pete Bentley <prb@google.com>
-
-sub    6B7EF7B18190F4A9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=ZR2N
------END PGP PUBLIC KEY BLOCK-----
-
-pub    BAC30622339994C4
-sub    FC9BDC25FB378008
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFlMExYBCACmdTDSXPwSJeYbfYvHoDl5C7vx/0+LOTunDGJN38pNQHYQAZnv
-Gyoc9ZmChrhLoim7z4ILqmNo8eegknepQ3dGdUij4NVIhR+m+8irayTbsNHvo3UG
-9y7eM5tTSjyNYkyk5fAVuT7OhzIzMA+qtc3GRVxNYRKnaHajt+pOSqr+uoDtMG3n
-6eAMHCAnhgh5Nd+dCFcNT+syl3zCwolA1wrzGxxOaif+xi5wwXjmF/lAt4PDIuDT
-etA2/AqPM4zAC0BtC0iqVgVypjFV3EAexm/g0LNMiG/M/krzwjPq5gf1DY/57jU0
-02FpKd79HmR7bHdc4e2olEf9NlHxfbPXDDsHABEBAAG5AQ0EWUwTFgEIANmMpV3N
-K8aLrLgQTyh5++det8C3D3T5tkEdljHOuN31/qdKNge8H6uKH8zXRZsj5pd8adpW
-kD4TzIMvzIwzizsGw34O9hf1E2XPoDqvQr39p1sovX3PeDvRJY/7JFNt9DsphVc3
-xWQfNkC7JdMPa6JRiFHd3ynfbQ+wplf4tfaDVn1JXAWp0NSGgMtXfn5i19hHQWjm
-RNAKNQLdVn8UczI8XdVM7bS4giDpQMukSyjsjgAo466iRK2+8f8BwIRe1JRvF37B
-dnbvTg/dzoi1/E4ukwVJD6YE2LlDwzdGno9KxPlRsuY3nnheVgjbrGJ2XKRJkIk8
-7cMGh41VKw6L4usAEQEAAYkBHwQYAQIACQUCWUwTFgIbDAAKCRC6wwYiM5mUxEiH
-CACQViGOHi0BoZ78ZJz6L48YNMx8fSdSv3YJ83Ih1n5DWCJgrDV5S3/edYinkoVI
-0Lusy3MdftRg6OWaYOuOTf6MYcddO/mY363jiMByf9Uh3Dqq4sKqVLRnZbAqgD1o
-dRoj2NkEQfgEH/H4JRVrxquzAKoWwJh3MhY+kajYJRJyWfc1/Bm3Bj1tcMGlGeIQ
-fgWheeMg3kxrxJ9TXPqVi6VVPaPKIU5i8l46S+Wg3uvMs8vC3XzOIvhY6cwguJv9
-UkjZwGDSI952wLqnREMy0gFZ+OAB0qJpYM3nDEekWZP38G80kojnN61tZjRThu9I
-i8/b+PwSW+nW3EpQZdLqZtOU
-=2H2i
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6EFF5EF5523052D4
-uid    Thilo Schuchort <t.schuchort@googlemail.com>
-
-sub    E2F840B227D3C024
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF2ClL8BCADs2bbaF1ZMiMkTUUb59NTlyAbOOVWoIh7cnKeNjMWBUTP0kLFI
-XpoKiyccQLP4rFdbP2yI6h+LJR0Kj/lJmKpCaAooNlooxfIyPUX5TMvDTRutzwBO
-c38DafLBAJTUl5BMYsbWTGSvmpC3/qmZ9uJAQH6BVEQxmGNO6jpPsgi/YA2AhrN9
-w1F5Pm5Capc8QQ9fEj+AohXGtpOA6aMhnPLjJ45h0VEwYskRIva0AoqbM660YVi7
-HZPNEqspOtmCrR5yzvRmlDmQQ4uKp4InSQ2Sz0OMw3G9cuZy5AzfAL+/SG+iL626
-S1UeIGAjsCu2GGIFDVRuj4KvfmUZz1H/US5DABEBAAG0LFRoaWxvIFNjaHVjaG9y
-dCA8dC5zY2h1Y2hvcnRAZ29vZ2xlbWFpbC5jb20+iQFUBBMBCAA+FiEEKk9V2c2l
-h3cx++dGbv9e9VIwUtQFAl2ClL8CGwMFCQPDI+EFCwkIBwIGFQoJCAsCBBYCAwEC
-HgECF4AACgkQbv9e9VIwUtTFBQgAt+ZETCausF/UT43FRFa2Pkp+gXnuvY+pSiiS
-lqSP7BvVOvTFnYtljLLufK/O74/MJqGYbiyurNA6Zrhe3yMjQqCQlYGuGBeo8Ssg
-0RC+Z4NJPEyTwrx5XYYLaDyeRMcQwV2pH6sWXc86TZg+6gBWBHrvb1PDBFqd89hd
-UY0xI9Vyc4VWTpJCshX9qA+Bjh0xzmxie7leZo7ejF5L0ymPuROZz9VquxORHyE7
-DAqaKesgQVbmOb1Lc5Vpdy70IIVlscyLIfFycTra31cnxPZsb6Iak6sed5VFM5pc
-9qYiLsNk4FyzEs7w2nmlDjE06jmWWY0So76q2IddcNYeKSggV7kBDQRdgpS/AQgA
-0x3w8TNxkGuXMEXxDcRIXQ54KRF4upy8P1exrJPenVutDAvNJeHLxc/uwrAfPGcR
-/DIJCWLbQv0T36WwjQSpW+VBxX41I5/YRrp1BRqUtT1r9Fx5KodpG+c0Nsjs2qSu
-ju+/9RI5Tyu+fO+bgYfuOfPq1E9H7POHu33Gz5Fap7ZB7VmRPw5uAOU2ev67Qq+d
-cfcKsbh0TUwkErGdzp5HpcspEtHxoQCpc6ZX5Ttoj5FS96vN/VIOnvwgVjxNMEme
-CjwHkcXJkkcFGwkJC2lpZx7y/Uv5RPjeKLoJoKKHofRutL723mGORe/uj/0pYfLy
-gfwtaT9kmsWZbZwNCrCuQQARAQABiQE8BBgBCAAmFiEEKk9V2c2lh3cx++dGbv9e
-9VIwUtQFAl2ClL8CGwwFCQPDI+EACgkQbv9e9VIwUtRRxwgAjqQpC4OL0igysJgI
-xcSUAdltJ080Po9eUcrxszIakH3fYeuN+vtKi37NbTI8BxltbXDZC3JxF2Vqxkqi
-6ow6ZTk3NMS0R42DvkBjO4DGvpIF1F+4rkiF5+w3CJHHyEJYGvBt4MGQ2Ivrp1rs
-C/VKazgG7Bkl160msMq5TMUAvVOuTn3pMljVUcsQLDxK8vAvaI2iox3dOtWj0w0r
-dc3OWmufCl7W/RDicP1Xrodm2QrHZXftDEMr6qB+HvkesWCnc/yqCuCr1UXqsTsJ
-5291U3pZ0RCl8aTFwloSctwwQvGxWxT4uXD1beqJ1tGKyoB1kzhwXnzuCBrzCcmY
-h3cm1w==
-=WIxE
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5ED22F661BBF0ACC
-sub    31ADCD8BFCB760B4
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGiBExyNhsRBAC/W5cMapoP7NUn8S22iWG5bPw0bconApJHP4kQdT17gT2JgNJz
-BmuGWV59ZOGQkc6woeFKc1s6twlsgIL51jMeVOtgLJRGTS4So2hthNqDcgO4j8Lm
-yXpqbTkbD7/ZlRzL2hhedrMz4NQOZCvsZpQ1RaCDrr2hxDq/HhD2omGdlwCg/9Mt
-JNc7897LgfCMmtPOvAFt+rsD/0K87nvW37nlRqHdEtzvwUlyLJmYxdW9hDr8tm4Q
-Y/8rDvNFlhKV/yXmxQuhtgQ1qpBo75dwD86aJmzIMIWM0iei9Ecfu2DsWiWvArq1
-heDjMYSeQl6k37cmD59afo6e/jQmg2/ALC6mRf3912SfmqV5spw0k+NYdFxAnbot
-9jOfA/41shIdZloZ0aDcJDTNe22wFFh2sW8RwWtJJO8rmOCgh3MmkPn7LHPI9idJ
-bSdD1dRcR7UTyeigEeDTu0PAKfKZutc91lfcIGSZdk39SEEhUkL2JdPKVRBotiZZ
-Jsi+NxDdsprF/yQtr00XSGJYzh2TW/Srnb5nZQm2Iyokod3M1rkCDQRMcjYbEAgA
-k0wzZq25ZX73DIlxw30u8Qmy0HM2cVmRe45Pj857FlSQsO82YNPOMxSkACCmHAAT
-3pACuMCf5Z0HO5iLbHrxegFPGWLkNE3CJ5yga1zIiFgzNc9qNqWtPQISJIQjABit
-4SseMY8i+3t6A89NjWc/AOK1BloHdjAmtvT54oYtqFYCMlNMtCLaR6ioSUH38qLV
-jXtFvmTY4OqokNaz6JXxzTymyo8gJff9JRpcm2S2Xksr0dLNYm5QwJEN7KX4E8iH
-8Rz8TWxfAhrf0zn45D7bgHOk3JFPEXzKGV1l96Tb5h/yy9wuN4JePyXDGfigub+1
-grV5DBKQ3srkEwy6iwAYwwADBQf+LXoUj24Evhce+OJ9ZCaPEppmV6xJ+LaU/9D1
-hwMkQ6CXc0IH3oeNGAbbOHhXM2GymRfg8nmzbIHVueTP8ISeO7Dc+gMr7l7l5kB1
-W7IstMlS1xI3Vdg9D8HaPJa5gB3qEGrIPdDP1KRRwJflw+DmQXB5jOj4vW1xECqX
-0bGY9XNFFaSMhkr5XRVT3xgQ8d0wuCB9otuUZC9pxmwFiH2w/FvKzMTKMRwK4IRO
-n5FPhSO2VBHBnlvF/mSbED22jjB7DngUC4rF0fE1MrA6DDJIAKrsDlk0VI7x/tIO
-YbkEOyypDgBf4JLrxgrI6jn3iCRdmi51hS7dtXX3ZIkmDVJrOYhJBBgRAgAJBQJM
-cjYbAhsMAAoJEF7SL2YbvwrMplIAoP5GSTgknFm3ONZ/W59iK+l+XJWhAJ9Bru7L
-aSKZGs7jwqXqGNrZ0ZzxNw==
-=HDKU
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A6ADFC93EF34893E
-uid    Tom Denley (scarytom) <t.denley@cantab.net>
-
-sub    9C4C23E6FFE405BD
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE+xZxIBCACzKctn4ez8xOC0pGThhAwjYWGkzcwK4HNaC1usHThBFz3/t8JN
-OqUXRixLyi5wELN6GHlsGVUQS3IfB4JtuhScsieSB8PTree68/knMq6JI08mJqZr
-9nFrAB4eDW0UMbSL9kPmclUm/yN+qcCZBrsVn0q6CWb/Kcd8EEXEu6sGILzOGqGe
-d433t5O+tGXWL2TjAz+Scsk2Hf4zcuDeQcxELAMnVaVgKuGuEZvibrjsdIvJDGI+
-0BzWIu8ZP8ldBl4SVtzGpEVzLvDUo3mOqBeTkj3rP7xLtFDN/3AFtowbLfL7L2Pg
-SMcTnKK+jfFHRfbHP1Ih3rQ4ilLzhCnY/QIZABEBAAG0K1RvbSBEZW5sZXkgKHNj
-YXJ5dG9tKSA8dC5kZW5sZXlAY2FudGFiLm5ldD6JATgEEwECACIFAk+xZxICGwMG
-CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEKat/JPvNIk+ysEH/iY5dP/4ERAQ
-8YC1j1XoYmMxW219uzxZfwI0ltLtPjGQlZbwlFvwjZk0nDJ6O1iZSeZQm804uRup
-gUZe3wqOp7a7z5zHab93QD/nA7O9QmLf2RC7Y0mW0EvD0tfbCzt6JJkAaxKTDA+T
-jFoukUZx2KJr0XToE6kwAnKmCgyFkzb2SUqfsBRNRBJBa6XG/1mAtDJJSM1XLChV
-Sa9nLwYjZzIcebtmtQ1vVqovO74ixxEzonLlNZi7tkc3GS23yntf5tAH0bQ9bM68
-TB9RHpLvjGgHUJtghFQN/Ny+//q1EsjRGn6Pa20cUPxnMS+WguOYIQx5jTb9ZHA0
-WBcu/V4UL8W5AQ0ET7FnEgEIAM3i3e1sjwrx2PN8XYMPQWG+/YTtw1BYDl2+iYE+
-LaZvtq1hpbgeCLgEVwXrCJ4spLP1rFXogWqKrkJ0LRjlpdKhKBvyH1ex4grh3cWN
-/bIDJcJ7JA4I/Bhqhlh8hYycS9pGFeS+MR3aFIsii+vadrwYYvuVYGeWvdZhB7mJ
-KYevj5Ms0OpYTfZd95Pzo4o//lNpDnrG7Xd3tgTNU/fkpw6rFB/2Ib1Qlk+Kz1z6
-JNsp+tOPGGCBrzwfwglcikTuqS+xyRgC9cHh5eCol11uSoWPKcQR2Ar8Eo56nxv/
-UApdu15iJ7R8cA5guKeeS4jt0CGCPs2PhuggDxI73Xvl4zsAEQEAAYkBHwQYAQIA
-CQUCT7FnEgIbDAAKCRCmrfyT7zSJPuylB/9iwtIQeexMWBmQNdDe0md8HLulDfcu
-jPtklrvYHtXMJQFaGA0Vafq0oT9MhBfb1YCP79uF0qgswSxINYCOJx4nTPIP9BOd
-TwqfGo7ul27REgNq4lIUW0GkMgZAUA2ft/vc0u/I0PqnhKCi4Pq79hLIx7eiX2yS
-fXfYfLXRVzbMWKMoi7lWXseQqbM0RvCA54J1qAi6Ew+JyoYGQ7OvXdL5Eh5Tkm2c
-pIADyqCkp/aFDe5lqZiU1zS2fU6mpOf/o0co+GoYkieIxxibDCmt3BioLgmyzpGU
-sMNwh4pAIQUGkcxd4spC0KIWdDEvq/QJEEIhZlI/ojefaZkRseFrtl3X
-=rYGl
------END PGP PUBLIC KEY BLOCK-----
-
-pub    1F8CF885D537A431
-uid    Niek Haarman <haarman.niek@gmail.com>
-
-sub    B7D9C5C3EEC4A9A9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFkyw7oBCACtGFos6g11ycruiWMuXwrE4+XbU85+1jR99AN5PcKjgXo/J3T9
-XaZLjJ+oTWCVgEHu5PTxAftbkq9+lmDAUEWZ1Q8dKrnVgBLsFNn+G2pcvVschorz
-CYFu/WT+eORA2UkdPZ7LH00iMx8DFpGtL2dBZY+tS3OpLi1LdNw4Dh/dJO7x7gas
-GWVUnL7+Cv53rmvwj8bQEuvrQjaeXMGxJKUSm0qpJ7BvkSEmQZ7qnRS7vZ05Iz4m
-uJsTNnuxtf0+fmWNrIqpv/J4RvaZVdA5OW/zA1kKYaGlZoLtWhKOht9gPAKlBk4k
-/fBfHoKqm+vnaOnxSzuYpQkYWqeEu6qzfZOHABEBAAG0JU5pZWsgSGFhcm1hbiA8
-aGFhcm1hbi5uaWVrQGdtYWlsLmNvbT6JATcEEwEIACEFAlkyw7oCGwMFCwkIBwIG
-FQgJCgsCBBYCAwECHgECF4AACgkQH4z4hdU3pDF9hggAoh6EV67Ep7HGBScS+Ow9
-X/gxOWzFS9aMVJw+MzSRRBm5YDSsJ3QfSEZHSDc7gkD6cHUjpUCaB2bAnrfv2wKO
-4EawnXkj9vhnZ/M5lVl2TOi/95Yep3aa+qCgl3jNefzANgrRgXhW3m5ao3YazHVy
-eBezQGKbuBfLTuLd5sknl369zY7IOuP59KaB2BYZfPYqpRrquFzZhdQoReSyhu0Q
-DFewliiCF5QA2AkW7yqrQOh7mEpCPvjX2GfqCsvIF0HoIL6zQuBcif7ELoSnFWYX
-RRpD7b3zshMX4Yt6yOMkcoN/JOGe0F9L0eoK/Cl1oPW1j7tdnnEn0+56CxbNExQx
-mLkBDQRZMsO6AQgAwWzQyChoPMNa3OER/72w/G6EtbS15PxNNktkPYFz2ibrDhkf
-z3av4G/mxYpYgvPhGHlgHbnGGfmhetEXVebc2iaWYih5AXxzCBQfDQNB5gsVg4x7
-SAp5rVmTnmgjtPV0domsbwK/vNepUK4dw5jMwxIbVO8Hsy66B4yvEMj3lFKkOg3a
-8uY19DaAlxehYAWyiWfcbduD9GeDGaiIXnbTgaf0x8s8bC1zWUlShRISrPnMOvPx
-D+PCJ/Qna2ixES7IpkzHKJCX1NMwKk20rH4saiwIpQwL3A2ktF6VRMmv1xHwZUl6
-3xZYGN7u9cJ2pd64xSGkTZxVw3P5KVoMOPTY2wARAQABiQEfBBgBCAAJBQJZMsO6
-AhsMAAoJEB+M+IXVN6QxkUgH+wTO3xI0072PDGNFgkDcItRy7G6tKphQNAy2ylDH
-y1QZ2uHWqNBHy9LuR0lzWVqWgeDudQQL2MAENnxJIV3mKeiHGspOaj2RgQcuIF6g
-MvFUODfme/vahJMoe7JhmX7xCMVWDEMpOg8gIyr3qix0s4DnkXKXgE+v1qmVoYb5
-qoPguSQnOyrHYxWN6qc3I6mwBi4sJ3PsCrkKDUXgJBiRjgbSkemkDi7naK0sRRYE
-tujjOSICJy1rc7jjeEPRcsk1unydI8aLPO2fIooiLrWJJPr0feeZVrGHS2Hpr2Tj
-kB+5IR1A1FK4o7oFcZTLcXVlQFgkac8BPyRuUGhF1YX1JA0=
-=rXm+
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6CCC36CC6C69FC17
-sub    C694465FAACEE66F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBEtrDFABCADLXGAhjPxdh+naC6XU5kficZYEVAURNRa8MTnaMKr+31v2zcAk
-nyqyjihcXGQBCeaNsz2mQkc/MrKdnFNVSwp715JcmcqDJGfR9aIDMUs9PvoNkkqv
-IDtx9Tn73piqbplT2xQxd7HjFvaVuy7oXI68gwcyAGDvQZeiFUodcbAsKrVwFT+R
-94JU6UODFqE/Ihq15Za8Sc8WhWitm8XTQsCsLeh8abGhkvNEmRLi56fh8/Bz8LHv
-8T7r8zkROoQFlUEYaOR2wH5bbipww9+HEg64hrcak2w5smNt0NJUXZ2O1l00u3sF
-Qdu54hM9nZ51xxcqvo+tGft9kIr2AfTrJ28ZABEBAAG5AQ0ES2sMUAEIAOqnjBPR
-FjX47AxlF9NJhzOUECJ2QaoezMOcKQ7RTnDhOiDi/Tzl0MXJoo7ktkeSAMlPIXlb
-K/C2qrM2hT62O/5GSRy1dPErTZx53mNIWTsT0wjQCgxeiAs/+5bqceahRO4PES0L
-J7VR+wiCUP33CIK/Ea2c6ODB97OSly0/RY97jWbM1xwKuzeHH5H0QKTJky1CIdg+
-avdfeeHBDEpCi3BZA55JiAKMuFNYl+Q4yf/FoYI0ZqKFhIwK0OQLY+unIPlX+qPy
-B6TkPIj9tcK/cebpN3VcFvNzVkcqYXdxwUU9G0GyzC3Be437oyzm3SJWw1DRd2Fj
-wFeiL0fWOjwcfvkAEQEAAYkBHwQYAQIACQUCS2sMUAIbDAAKCRBszDbMbGn8F0LE
-B/9O8wwEDuRjidsflZTopMs2drKS/TN/EB/leBFsOqtw712+dYSNhM/LJVZchWS8
-y0RLHQMAd6aX89ooJpvmkijJvJhB9YtuHwmGfT40uco7ATqbo6tYW/aA1rfOs9HA
-jLb1UWQvEsL+96WsiQRLwIoX6AaKebG6mLYikiKKji4LJRp5HVdXpTxRaX/nSPSL
-aau62V7XKJXaVgFvSTy4xn2eph4eRVACKym/psNkXbRyj1maf4a1sdq3WMdiDRHS
-n3rRKsUGVv7HxE45vR7W7hqN0Bna4VzOgNEocRCKO9pDEiOmXsKXUvDJBOrvTddJ
-VHX3/m585HZda1drtSgEv3Rs
-=VojG
------END PGP PUBLIC KEY BLOCK-----
-
-pub    32AC66C4FBF15ECB
-uid    Charles Honton <chas@honton.org>
-
-sub    D79E291A1BF549DC
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=/JM3
------END PGP PUBLIC KEY BLOCK-----
-
-pub    5796E91EE6619C69
-sub    153E7A3C2B4E5118
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-=IF9r
------END PGP PUBLIC KEY BLOCK-----
-
-pub    125A9EC9FAA91AE1
-sub    F2EA967B5B8FD0FC
-sub    F860F86A8AA8521B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFolWewBCACurWoOCed1W8Ut0tmqkSTpaz1AvPrYvZxmNqSVbxGjd8S/Bpxm
-uypKQ/KIF88a8QbePYa6e/I9g8HiuA2Bg91T9khc1mztXvutkiFNaldecg2rFHZK
-tHMtLq0PEH2WMaATcQBgpf3ueihE+R4E3L2t8s7lBhCeGw+FcFs5zuzf92Out3XK
-SbWvnkQyvNfbdVx3jleEfrmjT0zHWQyPNn0//0gO4rgtHoQUnkGcUQJmYTUW59Jv
-RjWDKTpDNTVzTitP0g2+Ru2H+suRFGTMIQMlgUUv5bRYpejpzvTlubGsrRAiK34D
-b5koeGwW/tB8crJS4SqwGLMYRQjXRu2qO9KjABEBAAG5Ag0EWmil5AEQAN9XlvNC
-mUso25a5GN/hvKTlWQFHcOcpKUoJG4DYgtgMAX+3gNJfA5pvntsBgsBjt/8nS9gr
-rOLqaYknJTQ+tzsTjiLC2e36+aK2Jr5RsRSIWTgM94P+QuMNX8DiuuMq5JFFhCM1
-IJE17az4Iuay9ZMA9nCVolRSSepBWn2kCiacQg6YFQnxhvHyjpNuAvALoVyZ8AJm
-uuwOGMnB4qio2SROrHkV6ZLXPQak48yLFpswbhxQKzAsiG/sfoe/nO8yAUJQSAEd
-2yXDylaPHBXsnjI8HvQpGmPieCQMjlJenwMK9Ewqtxnuprklh6+/324MjBCanBo4
-OSiqC48GKWqtL2uYOqqdbuLc4SN7pLWBuSBDU0/4vwUS6mjyIwcuOK1f0SUBpUqP
-5U2iqFURn7x6E5cdDtfCagP3bFrAktkUcbyET+EgdFnYMmpoCqXGFPvPGmwLHFy9
-ELF7+bdqqNgEJviWE66V2feePveujqUFWqHCZ+X6DvwoQyZK9Z8ojoAWFi7AujJD
-BtaB99QeKYOBqJb1DymM1etMUEBRnP7Xxj0rIQmse579vwXrbRFlMV95cQne/LFH
-2jZJ3ORO9qpGetazXJv95e7RzRxLR/8qeXUU6oiyyrSaXABVTrVpyKISGlfhwlN+
-tq+oP9WVYMU4E6s1bE3n44PwwP7nH0KFc2NPABEBAAGJA2wEGAEIACAWIQRU9uWU
-kj69BPK4hgYSWp7J+qka4QUCWmil5AIbAgJACRASWp7J+qka4cF0IAQZAQgAHRYh
-BEeWssB9d/temlaYYfLqlntbj9D8BQJaaKXkAAoJEPLqlntbj9D8jwMP/jui0ujh
-1NEUJVvFNXvbeITVE22aPb/6f1ccEUK/tH2J7QPFbu885pKpw1HagYswlHpsTEsL
-yjia2Xc55N3rpA4C5in485/nCoxt2aWnkkNKmQcsU/+Nuj2WjaPsqtn/mCyhrUUg
-SK0+PG6nLK5ekUWbZaaHxITUpnOcmihRbvqBiC4vb8nN97BkJ4aXcNymDKlWjVKv
-V42Qk2nRwl+hvczhT3+FPRZDa3ToxQ6N2kyl6uudK5hYg+JcIgVKBpWIMp7vu1LN
-Mscuv+KbjbyTqNMbkTiT0L1tHuQ9ST8ouPx+pCxUfjlqc/9yS5CC/AvtG0XkO8ZH
-7fmQiGVVS6VKVZmm5AP0HVpatVVcKq3fIpa5f82dP6YM586ib7iXBfvsH3mEB6Sg
-m92d1c3uLrki+CIEZGdgEjOAhovGZUzdxt12Yh5T0Sk/mJ/V6fIRkORSU8Uek60H
-Eu15C6KbbwjaMBjurHpo/3aCnitxByNZubDRLFi+LG0rG8zbPBQgQKFhYb+8MExP
-hwuzd45VQdK323leHobPgkOY4hlYPr/RQEy8Jl2kfm3Q/mvvIK2aLwlrGwmTR7bx
-d8xQZvvbr9Fs5noMiU7dTD5isQMC63RkSvhAXe2mzYoT2umooO5HYJrgDm4lQuH8
-SkWIYoUxVHpG+I8lxD6R9Vod0Ijhyg/2EXvjxckIAKkJUXxygEmcHAXCzJ6YmpE8
-8nUctDM6puofYoZqCypEO/JUfatJITNj7Cf2vPWB33d0g3k4+dZKlY2rXNIene64
-a57XbEqx8G6/fAPsHKDjFmGU6CLPSPRwkERXhaGdtkFCXtT/WHctjpJCU3XDGW7Z
-1OqTdsFrxiR6JeRlawjQrXdERmdxIhK/I1uaAYZOfRfQt2OTFvC01IEWZhHH8+SO
-28zFI5wa5voDs/+Wv+hG/YgAmxquwXhlcuSEBW3hvLVIyXTDPXggSmRoeLFLy+xU
-YnryJHIYtus+IQDFY7YZUH+MsSiwrlcc/O8t/c6mxM6HbsDCIExc3IZlZQZlXVq5
-AQ0EWiVZ7AEIANeF3UT0VXZcDg0wshnO8r+nuqikhn3VeBR4T0PoctLnGgucjr9x
-h6E9FXIDmxAiYvhAeskt5bbN8a6gDQ2WKvGOwmpO24/crDBlrX5FOvy10j1lb7n1
-uCQFHtRbeDX/WUWYLlb9or33/QXP/h+5RVlHun3lzw53yBaPGBQUdxl6veJNuJMM
-mvTXGpVl5Dg19ijLoktedxfboChSWZ1k0sziTMOO/J07SzcLd+IdAhN1L/O2awoo
-UPz2Oo1RMvEQ14v08aW2USKpkOprrTMRJJ6MF5leBMDWQ48m6DzTnccLUQBpQSbU
-Kh3C1pw6MINm3vCD7+x5FO+B+9x1bhcHhbUAEQEAAYkBPAQYAQgAJhYhBFT25ZSS
-Pr0E8riGBhJansn6qRrhBQJaJVnsAhsMBQkDwmcAAAoJEBJansn6qRrhqRAH/iOP
-CnttWmCTNvZhiZMAPPZvJWNNU5q2dxip2x/Lz6/qUUAMEbVDNEP6ITU99OZHWJ3g
-xs640+NzjCASM4BzX7T2vGAyVtm4M7oYeeTdhDoaITANKkRzBJ2z9B/gZkXexlCk
-7zlLS7TrqLhGkyNaOAIz73ygtPp12TTOFzQF8CG1zGEH3veWbdehBqB5Qg3QJNNG
-njI+gJdRefMhHsRG4rQg0qs3jilQ6RMeXWZ6Ncz/xuTMYviyxhicO01w3PAA/3XI
-x0gGYEb/uYbga6qTBkphYK9nS5N+tkXp7fA397mVrPj1icjAXIIANqRFX0NLqinx
-4D0hnpwfN9FlrGaJAjU=
-=a9iN
------END PGP PUBLIC KEY BLOCK-----
-
-pub    F6D4A1D411E9D1AE
-sub    B5CB27F94F97173B
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBE89LqsBCAC/C7QToaRF8eZgGOxcvp9aG+mFFCMjaRAb4Mh59OYdmUb6ZjfO
-9388HPebGbPNR8SHYs0dBIuWY4ZJ7oUTYPswasL8vB0iPFdyHhvkCca+yk0b8ZBM
-DmFlISm9HkYpoVjcFUp1oivyeJ5LRTJTd5JGEd/SWFRbB4TimdKXBzej9fIm2zVl
-KInEMMd8HnSYE6nm3aNkbyiqhx81bFvl8x6X3ZMWcKs+TAVXdP9uLVvWowUwcApk
-xpee442Ld1QfzMqdDnA6bGrp8LN8PZF9AXQ9Z6LTQL3p9PIq/6LPueQjpJWM+2j8
-BfhbW/F2kyHRwVNkjaa68A544shgxJcrxWzJABEBAAG5AQ0ETz0uqwEIALmEZ0xN
-tuX1cLsNUzzq0HVzwDiw5IquPWy33McESXvkaMyqyQtYisW++dY06MxBCS3uV4+1
-nKI6oA7Lk482ixwzbwws0Rb8H5CeLHDEwGXfthmLAvDdxoNCUYAtpVOMGcbGpy51
-TG3V9i9JWe1px+kvhieX9BLfDzP4Pldho9lK2gYRhmpPDgUOjYZgiQXMmIPAYfdH
-IA/VdYTETC0lu4Adb56SzOwvGMpnd3rXWUiJbZg7lW97hvbOFMKudbNjBCrF7LhW
-Ah089MU9rvunuz7mquVdNtfEBkdVrqZJdvYiFBee4RUe3+qGCpHnLzynOGHr+iIt
-DG73NR9fZCzl1K8AEQEAAYkBHwQYAQIACQUCTz0uqwIbDAAKCRD21KHUEenRrp0k
-B/wPuP2W69oweOqtSRDf1FeFNzAUIjbwjkg/bTjzJwb1cyedx7rbxhpJmn27W8A2
-WjfmDLOn4orQTKoxf3kP6SeeGhYLkzxjBa5Rco89p/6X35By6VR4LPFeTOACyE7b
-cAjqPFb+7t1YzvnmuZIgpvTKickq1D9g7+JT1Qd9nqBFKlg8aMngAooVvlLXaPEw
-Q1XfkfMN+ltwlEr7o1ts/YzDUxflaFVg0FnN7qezam/s7VvcK46rO95yQr/Wyz2o
-VDzc34e+Nr/b2pN05MDHA0dXmb/irwPBl0mTOgAgC805qkR14xhd1GeL6MEA34k8
-2Sq/O3gWhBaB3KOy55/lvvKp
-=CmMl
------END PGP PUBLIC KEY BLOCK-----
-
-pub    DE453E55DC86FC9B
-uid    Touchlab <build@touchlab.co>
-
-sub    A947A3FCB1697B4F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBF7H/6gBCACbEuIbxWAfHEYViPqdpwxDYauxsYwk6FgA9sSO1nS95KRwx+Cs
-X6F8nRGnfLtbo6Ffcp6r58fNi9RvY7ueRGiL0kQd6c5GYx6dH1b91Q1qrdVOeEdj
-vjHNVVXAlk1TN2oxFB81cz737cv2CTX1ibEO+qn8oxwOssgNO8ic6szJGorFur/K
-pCin+E1orZiL52+aSNtOsmzLW7qmL2VuDmoQ5guPfX7l6fioCwnUB9VA2LhD2Bm3
-oV4IhhH246CZ1iXWRG+vzCFDQjjPG5oPJfPvXtTmSuD7/65vNlrRk9sAh2p0BG3I
-i0k8304elsm+HnVIUDyroBjud464qc+iY2bLABEBAAG0HFRvdWNobGFiIDxidWls
-ZEB0b3VjaGxhYi5jbz6JAVQEEwEIAD4WIQSy+We2fa3B8HFy29reRT5V3Ib8mwUC
-Xsf/qAIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDeRT5V3Ib8
-m8QCB/97mcLfMXI5MuP+dLVx0ZltfAKb/2BRfgfGHn+xt+o7jeRG5B8qkKrl8+fZ
-3kS/aoW7VZu3XpHPLCiEkL5MLB45J8+AuSYKhQBrugJSmaXifgeAR1To5qoynLMV
-ZY/UgnkRnL1fBZ/gjMfnJzZxn2BCtcKXwmTT5rGraaapc4Cska+ZjRvT1NIGdMmH
-yHDxqsFzVVhbWXWO1xJxajP//umDC3j+gyQUI3nTWql76u/BxMaU6Oba5y4zzRQd
-1xV+yCm4mcfXcvXi5rf6xYd05JAlbfbZ0xCNFGgBZhyMoTbc2SANZIvG1/v0+p8k
-eZUS+HVdfWc0/7eUfru3vzkUvIphuQENBF7H/6gBCADbGrkDp9Jk+FPaV//G6Sy5
-oWoK1+3Hhw0aa4sKCStrmi+g4yPQ7l6M4hLj8cSE4u6UlRwB8s/FGB6CNNqoCJPh
-qdTHrYoKDnZKUOLL+8eYCnVcBoFdrJOmbx6gyaBfRoKj+EzPIgYpwnhA+evdIIXr
-Fcs036YLpAZEMKrhTAPTiF3MaOhjT9JcT1LSsyABi9e/r9zBQgzr718YgvMmce72
-nKt72vp1tijOHu0q3axi9I5LYt7OzBsSOmCgUndIb+JPIkd/axE77f/tznexTKEU
-Aed/xtYqAOg+fffGu9gRpkZFbFNNTH3iAvLPPg4SQAF3dQ5fSwT0NEbaXq6FT+aT
-ABEBAAGJATwEGAEIACYWIQSy+We2fa3B8HFy29reRT5V3Ib8mwUCXsf/qAIbDAUJ
-A8JnAAAKCRDeRT5V3Ib8m2JDB/4hb/taMn+1776Dd4DRzJVwiXY6zpwUmhgMlRAm
-H5qivj1vYK2CvACCf44VH03hKouUIj9ZAAuHHJjqKqBHMW+AMIn3CL+kl/2jsj8+
-+CMziEtBDskrNFKYOHkQi0o+aBOv2MvOt881890JpcCIHaCmLInt29k9r7PKgHSi
-FBF53/CQB2yCzwiiutA1qE+9HFUyNCVvKsIACzOpLCwDU19+8LVxbrND/ns+Tah7
-3WHQrxtKeTt6aYYOuhjqIxjPPTJngBzSjNDUmOxo9F95mbffQ2h1FugmKI1xBZku
-ClYd7CwAcljpFxHI6Rol9sRlTbDJvAX4aQvrFqhlD+i1X12O
-=FrYN
+mQGiBEoo3BYRBACXE2oGRA58Ml6s+kvfk6n/AJ+5OFeRT/Xelco/cpdxOVF5LkRk
+yd+vR2+F9ldBlH7CSTCmrdZIN3M3zrcWndrk/OQkCxNWVnE/a1li7L3G9nYr011k
+MwMM8MLkdf1Wr+FBunf1qpxPYuydfjWGFL749hYr4uQ8RbFDRQcmWLYCRwCgl+ur
+E28AmiICPcje59DNKHZZxd8D/Rk1LcZojARyMPjEsPOVSOh6kOaJQ/FOKN0j97k7
+ZqA+4C+OnIONSy22uMia9xO5g8oMLyHaRiA4S7JSIypYfX7JMCmwQCSLM/oQ5zct
+tsY7tGzCRBA7UVmW8uCDDZGmmzYIGQ7h1vcabgOFQ8wsteMHW3F0tU1K6oQut71x
+5KowA/9LeDjhl3tKizJn5hKf+NR8kTMcFFVMk8tf9/ZdqCG2gVTuB0EFimH47j1+
+YFWftvKg2IwF0qRnYuhpXn3kAtkzSwDr2T4r5CpDjttq+oBwhJ+N6lcPRoU26ijr
+nQ61Ek0jFFE5vfU7UODSLYXYbjf8McM6BtksY1SWfFBU5cVzgrQhTm9ybWFuIE1h
+dXJlciA8bm9ybWFuQGFwYWNoZS5vcmc+uQENBEoo3BYQBACSBgW1YDdTu911T6Bp
+WXaj3fZ+UDoyMvXBeoeRgVxFA8t0/olYdWpOjqp9YN1ndL9l4EONIClnv/DtzBYV
+pCWyxDSoRsnPXSyKVw7fViCn1dzzW25SPxZhGBaniQzWVH2n/xdy9y8NGdmBNX9C
+q9yeuMbsSQAlIwM15LLBKlVEOwADBgP/U32vKyQ9OmqRd7ttqnewzWqOlJVHqESH
+ZbgqR32UNdJxA05xc+cDcxwZWQw6GpHrVGeSGO9oUSjHCzFkSOTGpLUG/V7xac4Y
+hqZbBRp8wgSPfQKk7Mct5uOQHVcW3Fcti33ofYM0vmZy+puPV3+5kLqkCWrSF5ls
+qZX7clnN1w2ISQQYEQIACQUCSijcFgIbDAAKCRAFasp01GAAv6p0AKCP/EDLrjxq
+74ryg0wpNrQOtMOdYACfW68zcmywrNR2KD7Y2Pe5zhMtLZs=
+=fr01
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    0729A0AFF8999A87
@@ -12367,396 +4173,164 @@
 =33eI
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    B7C3B43D18EAA8B7
-sub    02A4A6FB70018AD9
+pub    07D3516820BCF6B1
+uid    Ben Manes <ben.manes@gmail.com>
+
+sub    11F4CE313A637CC1
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-xMHQYSM2kcHogpDcFph6wXxGhRjYldaB
-=VHs2
+mQENBF3HgdMBCAC3ET5ipFXdZ9GGMbtsCQ3HGT40saajsNDOdov2nMJxzKkVe3wk
+sN3bpgbsqBU9ykVkIhX8zV5+v8DOBzkV0pJ2eLjFa9jBPvNjV+KoK2BAI5pzNzYg
+sHPwo1aRXdI0MvCy+7iaIiiGF4/O16AhU4LmALHnaRQZCyuN6VOQ8rlqNvcczwUf
+J2DQeLHqR/tsch7S01hGpPAptBeu19PyAlQsntYN0yLCLKoe9dFXWCDkvd1So5LF
+6So+ryPqupumBbh4WxCmTp9qwDJYJItjAE0zyPe890FurOtxrFTwtRtX6d6qGKkY
+/B4T3r0tTE1EiOUpmSnxmGNItMh7/l5UtnHjABEBAAG0H0JlbiBNYW5lcyA8YmVu
+Lm1hbmVzQGdtYWlsLmNvbT65AQ0EXceB0wEIAK7dVAoqZqBw9twxk6psNcTmIrfQ
+bvjasKl/+PfLCfBNklD/nwe0CLz799fFSFMezCg43ZPCKIescCQ5t74r0D6O/QTG
+MpUyZD+w4JhZkMQYy2HjImfMNtPVOWb+XaLku/RloPt9MSG2mtA25TTp295N4mzM
+PKq0r1PzSa8jj4Yfn3AzzSXXLq6PwoDiljQ91IWBvJL2IAUAMaxSxzq3UqJnlbX2
+h0yMM+VC0nbSmbkK8mUNltg1EnngJKV1mKRG+Y1GDmZZ1Es19tEwUMsV9x1gt05Y
+lecC31woUkL0//8i1kWuWG7dqRMf/8cXaTFA1brVJ33b/G0VQP/a03UaVd8AEQEA
+AYkBNgQYAQgAIBYhBGNe5ic0Xzwd1CKy4gfTUWggvPaxBQJdx4HTAhsMAAoJEAfT
+UWggvPaxrJIIAKJsimeWznAmR9fUH/u0ONaTaEQZlhwBKvTGn8MPBKAnl50HK5A1
+AXtEe4KTSR7ohAZ/K0wsmVd4Qi7v0O+A9qTEE/mIb5zT3kVuFG772cISRGpC+inh
+8Dtl2G56s7K45tbPz6jdnZHLBY9eUr4X/2ImI7+q2+Z05G6KQm031XGC8BS8A1lG
+2XOMvb3qnRMnMapeHJ6vjoIeX9iPtO1foSmdkOCJpBs5ZEU5nnHzXEjv1tAPsTAP
+N+vBAduNAOSqGTA6hXparbf1loeHqnsZcedCQMxDQf/tja3Do8flUzx8MmQkoXY8
+i6QmtRdrToqqt1n1jGq9Ka7lRjq0xJHAZak=
+=5JCQ
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    D041CAD2E452550F
-uid    Deanna <deannagarcia@google.com>
+pub    083891AD4774845A
+uid    Eclipse Project for JAXB <jaxb-dev@eclipse.org>
 
-sub    5199F3DAE89C332D
+sub    8118B3BCDB1A5000
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-f8npB1l1fT5cozzQJkPVYzhBWH1KXP5X
-=vnEw
+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
+=TLTQ
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    9DAADC1C9FCC82D0
-uid    Benedikt Ritter (CODE SIGNING KEY) <britter@apache.org>
+pub    09A79E1E15A04694
+uid    Torsten Curdt (Code Signing Key) <tcurdt@vafer.org>
 
-sub    923C08F9417B222D
+sub    5FB8CE6F93DDEB23
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-uGWBaZVODvhr9hDoUpp2+qte
-=rXX9
+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
+=YAXy
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    379CE192D401AB61
-sub    0CFE993CDBE1D0A2
+pub    0CC0B712FEE75827
+uid    AssertJ <assertj@assertj.github.io>
+
+sub    A9E4161147556D82
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-N9IFsU1/E/XhP4QkRJrZI1F/
-=N8tg
------END PGP PUBLIC KEY BLOCK-----
-
-pub    66D68DAA073BE985
-uid    Ceki Gulcu <ceki@qos.ch>
-
-sub    A1766BE5F812AC2E
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mJMEYvEGpBMFK4EEACMEIwQA6knc/2gtbqDhPh5EzrymR4Hwi1Xf2S0aqMopA1zg
-IeZzBgSfL+4fEfpXL4eAzvrk29jIXSizDEOgFpw3PW3Om1gASxub4Jo6EQrRgOdd
-OlJl1bajIRC4pAoZafDzhOb+FkjJ61lEJzJ6pQtG0Yi24QWDBfXHkSiQSbZFvcC/
-FTJpZua0GENla2kgR3VsY3UgPGNla2lAcW9zLmNoPojSBBMTCgA4FiEEYCAKxK52
-HxYU1sRnZtaNqgc76YUFAmLxBqQCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AA
-CgkQZtaNqgc76YU7ggIGKhGjOpGq1KupRlH1//DT/h5rfbwY9WCZfCaD3NKD+Ly3
-sOF/Mq/pow9vwEn99nbSVO8fk9s0MysiJwM7QjuOX60CBiMoQDTwZNPRRUVKM7nv
-xqOzXTYJNf+XDuAts2WQCRjwZF2uPLVxl3OXkgNC6tmnJxlXVwQ0PQYW+I3aKk59
-mhs4uJcEYvEGpBIFK4EEACMEIwQB2pA7Lzg7+PvGjWsBowHeMYcKfjbAEkXycxVn
-WiHpZE3x3fck/SiMKkIr2h7eXLGNlG8GxWQWE4XmWxvvaSpHfiEAteZm+HAWHM2h
-CXPg24MuDppCMBATKJLs2ojZJVOpsajIgTrKDZku6/ay/GTV02W+2q186eah4hkb
-enJtFGHK4hUDAQoJiLoEGBMKACAWIQRgIArErnYfFhTWxGdm1o2qBzvphQUCYvEG
-pAIbDAAKCRBm1o2qBzvphSQsAgdoBwIzWeI+z+SPc0SYWXc/2K8TGVZrpDjmXyo+
-CK0Is7a/3fZMSVf67Hw75+/QDHZcl7MCP54xX6VhJzK9embNvAIHfqe4+a2wInfW
-RgteE3ZYglY+89V6yt4j8ZBSrRa4CeB93oM60Ipi00o/vGoO7/ZsxTbdzEZpGPZO
-gfhF8IKWDUE=
-=fcC5
+mQENBF+EGtgBCAC/KXNQAl1rz3VBbqm6ssjzR+5Su1QWHI7oYDS+YHCLOaqfE3jO
+zQd+8iNgniVNtX2n7bt1hido5B94VmaqD+zjjSu2UV/eZoYhCOQ5NgvxIr7WZe9t
+DkhOppJoLqZJxK0EcTWMhOdJddIiXvK1KsC+pohW38+AXEamRKgKyFA/7F9G2c4U
+ZPB1+t5tujNn7RGq7H1N7ECV10Aou50DQBc0RaJmXVamWTUuQsWr/762yn3ZS/uf
+kFBZnXiQWJ5AL3pFGcmj4gQJhG6E5nmZsvUxVGSNftaK/fOX5Njv9EQUAsKYi8Iw
+1vf1Y/CgzM8FfWY7hHtk1QlCUq2CSg3ecNPFABEBAAG0I0Fzc2VydEogPGFzc2Vy
+dGpAYXNzZXJ0ai5naXRodWIuaW8+uQENBF+EGtgBCADFZidSQwOlpoDgkP7iPi+g
+mjy4ML6j69X3zMkjoh+iPsUYpSnEmiiyiQir+i0Qu0PjMDQTmFgNLFALtsoo+Wgp
+TDVwpmJLORDsPiRp0haNZzy7VYMq5FbnL8rSP+KyLKCofSCnmGRyS6Xqy9HXjkMN
+/ywoOU8rRPrz0eurrTgM+mgXLpl8VRmkM1BBAA0or/BIgly83wRTJS0Q/3aPr8ne
+jR14OrLgywuLKs3jDAc2n5L094pL2m0hgIPo7SHShuizoslAYBT2FbJbQTGRu69u
+40bndTRnfApd5qSQ0xxQxIiYXtn/g0S3DpVfKW2tDVcNz8Zm3eiRc0bsKDF0VG51
+ABEBAAGJATwEGAEIACYWIQS+aFEyr9J0DZCV+QQMwLcS/udYJwUCX4Qa2AIbDAUJ
+A8JnAAAKCRAMwLcS/udYJ7e9B/46vrP1NtK0B0PlY1q89P0GqWtveSvXcfNvnL9a
+DkdC68N+cOaczP4PlSXNt8R5RMRXSRL0k16BEj7wqENmx634241nSL07KrWcpF6e
+U9Lc1dHSxWxO4CE5Y0c0+cutImdnDuIh0F6GTqlO6dYES6/dlNWIrncr5oQ2hoL4
+4N9UBlagfhMiyHft/NDtkc+JsR3oCYLdDuJqI+ftwR5E8qEyfG0E8iNsQuRBn6Gh
+QIgLlfLO2fPT57JTdKu0NXQcNuaZgibcW5OZjd40Fz5hUqiVEpcDMU8L2G5YJk3U
+K96wS1RWSHtQn1zkoJ66ejQgCbbiK8fwQOMUOo54Mid7PbDG
+=sUxg
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    0D3B328562A119A7
@@ -12836,1443 +4410,94 @@
 =7aNS
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    208B0AB1D63011C7
-uid    Violeta Georgieva Georgieva (CODE SIGNING KEY) <violetagg@apache.org>
-
-sub    B4A1D8D630480593
+pub    0DA8A5EC02D11EAD
+sub    71499A87DC1FF84B
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQINBFI6WiwBEAD+kkswnsY8eaqvYkS+ZB5MJr7juWrv9Lw9OGsIXFlTvD1XK01c
-E8k4+uA2sOtaXQ5wTMdc5N3YzAXqFxplWuafQgEvhyTTq37M5YCxvtYEZy/EHQYT
-iok5H97lMRKbhLdZB+wkdsa0P/L1FveCUiEawKY/Rrfi+UeRAneSV+m7S+RrPphZ
-M9aNSczqYKfAqlpUAlUcrF/bt59vjhepoHcE4ev6SB+PCs0vbvX4iTvvZCTk1lZ9
-InS2wdK80Jz9pRB0Uf3LEnZxt9e3RkIFdQOCcEISmNlBKQQKFG+zCpIAbVoMLKEw
-rXWl8mLzGzBbhGmLpFroem3Ln1YiAxUqnPR/MoBquYnpTINwePgwKVWyQ1TXG2MF
-Z7DPayBMN+G51rfLS/8iy35pAnNeqbWQjavdUis6/0aRMv5EYMFMAerutQ5v99bA
-rGj6OL3R6repJLOGT4YWcD/Tw+eU1lMWxbq8BbbRU9Fd0iVFhFyKB/DQSxofvTCe
-PdWXRrptrE0/SmvuoTRVPmB21WyJenKdNmVOQ6U+W1Rs+5IKAdWWrGPcUt0qTrRC
-SL8vAQ7MejYLovFtRHslJRs7T3ratpRcQUNOx1jytJhmSUJktNWZWNHqBTe/eOAU
-Yr+QAkQVQXvRVWzHkDHQRTOFmNYIDZYRkzSP19sBWRnYdCs6CbIVPgMJVwARAQAB
-tEVWaW9sZXRhIEdlb3JnaWV2YSBHZW9yZ2lldmEgKENPREUgU0lHTklORyBLRVkp
-IDx2aW9sZXRhZ2dAYXBhY2hlLm9yZz6JAjcEEwEKACEFAlI6WiwCGwMFCwkIBwMF
-FQoJCAsFFgIDAQACHgECF4AACgkQIIsKsdYwEccMXA/+KMQKWfw2T2CXLhqvQLoh
-Irj1Vi9leAttKqKp2NCHLK1jf1qKzUx5U81VvizIGUsDXGlAvnnavrj+hmQqZdsO
-CoJAo7ViIR1ZhNca1tFK4Sy03wdpNyUkvxVuC+3peXmwhjPJoqU2ONCuDl/bCczl
-QAQpgZCMO93h45U9H6JkjqK01aDorQHxvXo+Ap2IViQvDkNtJ515vG2k5K+x2XHw
-Tv19wr5N2rz407TWKzS5hh7QHRgg+PZs/zPf1YHD7Tg5K6vvmZd+5EsDrse6tZXy
-mzz2+8Yg1SNa765Aq6p1uAQf5NKeej/25TbRYT7RyIlgDXPcPrKxy0cKzpqFqCFs
-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
-BCfJ3B8rg6v0
-=3GO4
+mQGiBE3LMfMRBAD90h69D8yyPWaSoAyh2mOOOZ/XH0isuBpDZCWptemlMHgImqdQ
+2sXLXYT1bJKmSaMw+yKjp8J/NYk69EbmSK1C2nypLQtWhUmXXd3XVYw6hrG/dGvi
+gjkS5eq8L04f5CSuXO7r1eLTOch9iDl/ESaI5Nhq9A3mRQIhQalum+FjzwCgx0PK
+hoC4MVPVGXzOQPc5sG4jzAUD/0OX9c/yKQqjHUs38HTCgrjseM40iPhp8NfbWenP
+IwUMSWXE3lz0MMeKrGcEOcZOGWsjyepkLHXwj8DDOeGxhfh9bhFRJssdfzOCKBpf
+6S70A3fanzqOAvddxCqF/zOwDaieDmWvVntVpmZO9d+pgR/sZN0JgSIm7qGDdNqG
+Aq6eBACyywfwuVoY6lfNz70ZZqYjYuUkbKnKqpG0XmI+m5LYrUW7QuKJqaNdg+ZL
+vVgX/TdkWVSIoSRS5+eYm3fRD++cg3ZgoR6ZY4WEa7SRSp2zoidtQijWOzp8WeHs
+30rIaXBrb5wHR4GQ4FYsBGRuWkmIaferusllUmHCHFJI4ldvgbkCDQRNyzHzEAgA
+1rD70DvCcy91ShQKP2snZ4cLJnFwKArulDUcxoBZ0AG0qMbaE8jiiJTHIwgVrqsK
+aS1JENv6tVdUS8xHswu30zvd0obaj+4IGXlMVdc6052Y4SLAGNbGVw99Ah1OkQ7o
+v92gmYAYfqppOtRt1tylz7Jf+F6er0umdVBZm8fJ+QjzTw36AwERj2bjVbc6ogM7
+OsTyru5oZGOJ+oJU+M9/mh/Gq3AyrcfU8c6bL2pacXwylME4lxy4fBB7BsMogPXX
+iplZ2XRH7RmlZiAfLHv3StxVB1RrLXVcjdnqIO2guVYrK6mxH9WMG4LnOGvcnYTf
+GtWexEmNA5l8IOSgsK+InwADBQgA037clDFi3XWaZBVXst7IfkU6bKq9vhmphS4f
+uBx4wp7MBA62k0kGDmZWcbinZWnybypili9ihYSHlp3EYzCNTbUMWlbhc/ffYHuv
+rZsIT2DxMPb2iCnjPu5HMGegTM8iTTotW4xYmJUsEDIvgQUz0/UNsPHTX5XU09So
+cL3YOP5MxcEbgO0Fpjny3X76rc+ETAd9TmDJi7HOm24grKdOQXHQJr65j7nTc9M3
+zWnTxOP3fL9jcVnGTnLGRVoR7kedDpa5FsoFqtY8YMaFvNPVvI4+m+jozjNwTg2d
+GG6nU2dEC0qgDEeKMSJwF1wgO3Fe6mXHvxratgNrqfdY/rtEGYhJBBgRAgAJBQJN
+yzHzAhsMAAoJEA2opewC0R6tNKgAnigkHDCNu7Owm8x01E9+aL73JmDXAKCj7ROh
+7Wu1iZQbjeJfypM6CQ+fdw==
+=GCHG
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    1939A2520BAB1D90
-uid    Daniel Dekany <ddekany@apache.org>
-uid    Daniel Dekany <ddekany@freemail.hu>
-
-sub    D068F0D7B6A63980
+pub    0E91C2DE43B72BB1
+sub    83552A552A0D431C
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-1ejrktxPt0rVTJs=
-=Rkt1
+mQENBFBIm/wBCACgqvegptBhfKbyBXZiW+7XchIJCOpwq0/9QgSehKMwELbUKqNM
+sIVrywANqYn32S9hNRvBiKGm/KY7VwN9p1Cr6Ey3XuGSbRo/xN6tqfV/rV5YClL5
+6sMc67BlnEaCZRNuB9ATeUE/4wCO7fWg79jJuNl8tKQ8EYIrVGizzjmZHt76OwAi
+hQtD6A19+qjQ02SyPUJS6a2lKx+gwaHNxv4L2FqImCFGOOEToyRb12GD18Mgbf5o
+OtQVVtr3qbT07odFQt8Iyy1DiNUJbOfC+YO2wO7eMTr5xaFr1HejsTvKZiTDC0Nr
+EjtctqGxrjxPmoUPNwtxwEDTEh1lyKMhnqgJABEBAAG5AQ0EUEib/AEIAMDUgjnP
+KBeHIN0KNmXTS/uXXC4LTGltnQJ57OG2kmPz/JjAjYLoLvINY+xtghehMhRY3DmQ
+Dy/ufZsgO9oH8PztcC8QL5/dV6VTYf4U3FndbiSKgikaBX7yu5Qcrtkv8XgkJ+aw
+IEUgTGDXn2VT1hH6yEG1tA97iT/d7ZUxLEBsVgbxz9VtPellTNK5x/8NGY4NW+fM
+6+yGFpjr5juZVYRLa8u565vGBQO5FU7bg/69DftmL7vO4KRLs154VpsfAsTeo1rm
+U/8kIjgCVeKFClJG+Sg+m9rsJNYgiKy9dGfD/qDmVlEeWBuhtlAfqM7pHTv1Mu8m
+v5/DheBwvlwheg8AEQEAAYkBHwQYAQIACQUCUEib/AIbDAAKCRAOkcLeQ7crsaE0
+B/4/+ZcjdUfLPlKk/8BH0tMafEWOGvqY8bG4YpxGoJZHT/Lb/cnWDLvZzs98FVaQ
+3DKHZwQhhtnQIhnupvxSHX5wLeBZMtAANGQLauGp+A3S1WBVRHs0mzOdlVDbzJu7
+RW72mnkRMSoVd018fh4eQ0+VpZh0Pf9KfKJDwpEuESP1+6JcLLBvQXlEJYHOk7Up
+5eRkhljdIwz3TlSuJ9sCscTgM0PI7/L1eFP/iCgZIBHhpllVV6v5IGXx3P5Q7YQU
+y32zCrht4t9fdtdLct1j6eNaAQdPAU91auSbYhuVCpjgKNpwOv1ULoSWLUUPMNW5
+Qc4ZDKq+ywOElvONMnX4oaQ1
+=f1ra
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    2E2010F8A7FF4A41
-sub    E4D15F24364C7906
+pub    0F9FE62F88E938D8
+sub    BF6D15D3F1BF7BCF
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEnOgPURBADYutfvXAtNgf67BQ2gWTI6+nKfILIwMPzCbQPMd7pykzF5nPMu
-Nswt3E7efo5IP1Zsv6DRrLafAW0OJSmL/oo8/ta0AfqcxCCbJ6CUyViifRZ5T4nU
-WfuWTZiaKRQ57jtt0WnNpFNFf00gDbYJWs5b4RU5Vac/0B0WDQ0wvOJfBwCgylAw
-LrDQmwyOZcws9VbpvZvz9pMEAMRkV6DN8kvmfktpbUnHNuZJOps5botqKyffQVj/
-b2zh9mQ9yFpaSWESdFgpJNeBGtQJEDOz2G/q9ydTrYyCD8ILMKmsUlj/DAjaE7mU
-/NmSpHBUO97NJN/fdMgkkbkSlk4j64lGaVovQph9ehw3DsuSTF8IPvr/DXV9nuIc
-duxTBACUE6vsxZlzB9dXe5HjKCoPGr90kUm8uCG/CVu6fBVpZZa9B6+OM6NhEkLG
-FA/EKgKc/tvNIlPsRwX1R2RoV9/tR9N772ZjhLcEBKV2UO9mb5iAWWZaMJtQ06SI
-Ws9fyd+Zx3GGY1+iwWPUxZ2lSGLlfg3Sunl7Cni86tb0fTHTrrkCDQRJzoD1EAgA
-lYw+EWr/t9pNqJhzVpAZ9u3LMKJfrGopbO+jOW0T58mIdVF4oMF5WZ4lHPTgHrRL
-KxXNcGlzaxjxBKtkUbnjRTSGk7ExzGIcWoqq65RI8JgONif1VpBaS4Y8WwX/akQB
-nCAL+eV7UwHttVUKEmt4xUW5CNa4BgCFKtVdiomvdxnBHBCgfWNHXpNnQLWhuOGJ
-ZVyqq1ZAh0/vIxUBDSJZPxmEh5235+2CDK8Zu4FCcsi409zrLTtga+ggsN4tp22x
-vRgNs6nwARsk4paFII3OMkdMVJlGqU0oQ+H5I5PADBFSUYwpcIYne/+k19+QMR1x
-Ik+7EavzdOribLC/nwaLFwADBQf+INE8jnD6qg3g1gRN3S9MNh+PAPEsrM/7Gw0N
-CAhaf3METVwSzZfwVNiXM8DVEGjaBAPTBpuJdveHpTG43E4eibjXWTe7j5A5QSUx
-O7p3W4AXNTKldFnlKkVs+6ZKCkKeasY2/7do6Cf2Ed6lL1CDXEYcZRZ6BbkXruI/
-HqT/IP2mTw1i53S5Gxj3gaG/jOroXN5cBZnRoaPJQpuri9hdUJVqPNIDhe8dz3Zx
-kHEgVPMoanp8xti86ErSjgvsxGs6xjjuxC9CNjMjyod7d6E1NSt7gvVdksX3vok3
-QvIqQKDO6l777R9LQcxEStPz91mrBRTAyO6b7AtCk4/5S2hTdYhJBBgRAgAJBQJJ
-zoD1AhsMAAoJEC4gEPin/0pBVNMAoLT0LzbZNVmium/JNdBhDhufgi7JAJ9s7DMy
-snT2e4S6/VitgWdoI9iCfA==
-=sgte
------END PGP PUBLIC KEY BLOCK-----
-
-pub    438E9634A2319637
-uid    Constantin Rack <constantin@rack.li>
-
-sub    2C8E4A350000730C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-qS9F
-=OTJj
------END PGP PUBLIC KEY BLOCK-----
-
-pub    6601E5C08DCCBB96
-uid    Popma Remko <remkop@yahoo.com>
-
-sub    0AC07D0BBD11498C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-Ds1RyzdSprcN2g==
-=S4Fa
------END PGP PUBLIC KEY BLOCK-----
-
-pub    2B172E3E156466E8
-uid    Tamas Cservenak (ASF) (Release key) <cstamas@apache.org>
-
-sub    673B436865B87E35
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBGKVyb8BEAC+qG+3tDrZkCJlJwiU72OrX/R+cKQ8Jvp2lzwgJg2Sw/S0xXAz
-KqoxvfkcM/egEWbxUsbuYVVXlAuGwTJeg8QtiuqIVXyoEEmUoWIqjOsCcNDbQ8Of
-PCtUpci02xrIjNEf0jxE5YNAIB8pUn2MN4IAWtfdr+zlZis+vtDkncfW/pTngyDn
-Nd2gFAcNcBpuP6r/jqWb03e0noxhANls5kNyJcN1a9SvmZzOgSN8x8v7CjsDwBGd
-BPqpZ4r6Fsb27uchFVAMaVBEsvc8kXPs8OVg/e10OQYPoNq24JqbaNUlwflRajn4
-57t0d5RC08GlA3nGvvTvFGzprjxaBTNhQ94RmpgMMblKIWxtUMWUmGtHu44MzAr3
-JXlhdgYrKaCKKZh73vNJfte0JyqCEoPJM4/wieTTn8K9/wyLfIiTMcQNajjRu8K/
-OUrU81WHtkq0pVEm1nx71J5nrJU+fxQklkqMFBdnnQ1EfOd7ust7LtSt5Jp/iBZx
-Rm5ekjPoZjMWGS6GhTbpu29YQWYtmYLI59nXLS4E37r5A8HAZK8MxpTs71sUMgiJ
-aYGDSzdj4BJ9JE9Se/K/0sHy9HzEGmMAnac2Sp1oqLwttfSkzwJWr443qx2NMbFm
-8aMXAzOE0aHGLN30i97jhLg8ItBWYi2BfLtWbcDX9jkESkpZvwW07XuM5wARAQAB
-tDhUYW1hcyBDc2VydmVuYWsgKEFTRikgKFJlbGVhc2Uga2V5KSA8Y3N0YW1hc0Bh
-cGFjaGUub3JnPokCUQQTAQgAOxYhBCm+oqZF8tbO1/sS4CsXLj4VZGboBQJilcm/
-AhsDBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJECsXLj4VZGbofeUP/2jp
-yfxu0NwLqcFm7NbkKPYUFahNJbjBpPxqnEkHhYZY/2nIPmOs3SJ858X9r3TRPV59
-/Usx9e4fxPYrd70YgYBMJ4YSNSaRH8PjNs4DCTTzBxFWQd8spTSxxkg4J+OQLFq5
-YL4cw+4dioh3J+CQgJ2SwS4qMCadmV/11mtzWyukhdudqrG+BIj8Se7TqFaMMPOT
-fbOpuG7fnE4ODweOUDKjFkucCsjmmRSgr7b1ElvrXjaTw2UOakvC2SvVSVkBxckh
-gJOh3oUTHhqGZTg5afAc/HOKpQYe2IqG/7iHNfcTdB28vEg6/cvtgl7WBdKc4bak
-93PYQ2+kMqu/icwDw/ATopu8M8vZRAyNWX3ZlK0zlQL4MkL9mhfcB1FDLBTXVdF8
-W5PrRcQS1AS5Zg1FbT4Qz50gsYLuRlVXT57lv0LacRUSqIL0Blk2pdRRX8df9bFm
-DVAJGedaoPh1EtJsbi7HRjGdfvWRn4aS6sPRYQs3vJzpmdWYSZu5bbeInem2CIix
-4+3fD7E3KI9d2quWhMB1ADLXCu9yCgNSJef2JhUHJk6gKnPxaO2MiWpB96QU8HHX
-1dZrR9E2g97C80vZT19zDCGAVPoKgrqtZJXdhssctIoiWkvFR3X8iZQEH69fKO2F
-hUjwFKWea3iOYmfYEnIqx+xUDf7u3zFSs5WQX7LgiF0EEBEKAB0WIQTqI9sTYNkC
-lIHn8u/s3+o8tEk7lAUCYpXfOAAKCRDs3+o8tEk7lM8HAKDxSThuCim++uviwDsX
-S+4B+JPL8ACfQdnQyeTl1hfbqyCTTudSOO9izPPRy+/L7QEQAAEBAAAAAAAAAAAA
-AAAA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL
-DBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBD
-AQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
-MjIyMjIyMjIyMjIyMjIyMjL/wAARCACHAIcDASIAAhEBAxEB/8QAHwAAAQUBAQEB
-AQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQR
-BRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
-ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWW
-l5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo
-6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QA
-tREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMz
-UvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVm
-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
-=XAs3
------END PGP PUBLIC KEY BLOCK-----
-
-pub    26E74B6874AEE127
-uid    Sam Judd <sam.a.judd@gmail.com>
-
-sub    B4E75C15C3C701AE
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFPsGJIBCADOxQoTLxpZVRIbLaRfsHa2y/TEIGvxLP7TgqTwspZYnwBd0cOW
-OHAvF8yGfdk5gvkGTlQ/xchwu2Ix05FO2c+fBoOgIG1Gn2Q+PwheZklS7S+V+GFk
-t5S3m6b54Pl2lKbcasaM99r5g2+MhxwVnG66ldLS9fdPWqWrviOC+EipHfGyuhj0
-R0E2Oh+dNHrsZR0vtoJawA8xDP5D1Ii3jEVdi71PF8OlavG7saAZXtOW1kU77oPa
-SmGFTmcFLjDP1alo95TTfBihaYiwFFnW7NQEi5Bw1u3G0+Vaoo5eJBQwYsNxLs3h
-I1d7wsqFW5LK6LSxEjfvEhJypi0XzrFkFzMvABEBAAG0H1NhbSBKdWRkIDxzYW0u
-YS5qdWRkQGdtYWlsLmNvbT6JATgEEwECACIFAlPsGJICGwMGCwkIBwMCBhUIAgkK
-CwQWAgMBAh4BAheAAAoJECbnS2h0ruEn9DUIAItn8TzZh44JQ0aRO3dgmh4kUnnJ
-cJyw+0m5m4gGyjZ3vFzbCXgzCHAz2jN3bh6crnUoheIUCn206NRz+aG0JGXAkgV7
-9R7QAKY3K8QzW0QWqHOKv1n4FbfPKhaGMnXYUcQjV9pkVgDmqV4QzjmegATVLkOE
-VVNUjWIP6wXwj0I/UW4jO608tTi9juH+XkDkpf+qqix8FUn81tw7/weWuZXFTpAe
-qAYzjtzzDse8uI1tZWxc8H6AvKCuigoTsD6xkfuPfL4a3JepER0R3WlGhW9hDLBc
-/VXGULLl612XfeG+xREy/pjILzp4ajTC9FdAmdWF2wQWhM9ZXt38FSBHg4+5AQ0E
-U+wYkgEIALu35o9Q309zBBZD6WLTMvFt/X+N6S/cUrNLMv3YvR/Bo1mtDxsYwmzo
-dWOHo6TNthWm1FIkDhHUMB58q9oHzL2/JIL2k/jCULOhj+YAT2N5fQwvZ2WBtWtf
-suFYFO5y7UKKUqo+2Dhnk8YuorPbKjVXELrHFIq0IRlKEKnDfNrkxwHBpfeU4QaC
-UcCW+OjRZFsgZVVc8ZjhvvKd9/vX4Jt/c4/O52Ym+YEYtZaiawcNYFAdMhaiwSF+
-dof+v2e6BIYOJrBifZuILqA87XsHQyBCABO1zhspt5X2QGGqkjVHiFJnYiTwqYX7
-2n1OpoMOklJZ+ShbbGpCst81i7lyz28AEQEAAYkBHwQYAQIACQUCU+wYkgIbDAAK
-CRAm50todK7hJ8OJCACtdgGnPNmYILYJ3jyXh+WPDvxr3y3yMKmC0pRhgs/WxGK6
-cmRV/ej8OB5aIWCaoWeJ03twgqiaSMbn+7ONkr1DbPLzqQGY+QJBJEvLE9m9YcAd
-BMHCT0fn9Op0AYQhoInOPcKLD6NFO+c91uLBOg0q316Wlpl0p3ULH526a2YVPeKw
-mjCVlhrQSoHgxagNrol4gC8bfpypsjTwCccjesiYMOPPU6eyHelFAAGEuVDmkh9g
-Gb9wOqgum0vJEummqOStTopEGr63PoWVMXSQbkrTrayCcxjSiKRfK10myhIGFU2n
-pCL9QbIT7Aw2vZ5VjIm6fWIOPJJz4dsRuYL9Ar8c
-=es9L
------END PGP PUBLIC KEY BLOCK-----
-
-pub    82B5574242C20D6F
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQGNBFC1VWUBDADZwqBEEmSjwy2JADG0qCpvVQzC5KszL0CjzqTLPMBmLKNuc/36
-26MU4yI8Y+pcCTnC3LN9hrI0hxiP4zFFFyLYKkUWCZRAwj4OQlnyTDKa9frKBMed
-PJtihlQAKeCtMh9AOXNa+hZoAAEG/dfIOJhLyZB7JEuuwkil65R4yLrdnbbhPYMi
-1k0GJsaxG3IhkR/XQMO6m1KnThxyk2GPQNLFHUVSN+Gqz9m6u7oUxhhFjwUj3DZb
-8oGcQ08JR7IGdB8qV+XC997MUGjbRRu05hfWJecR0Z8xkprsdKSbFjuw24lZtsfJ
-w8advblczq//NvaUj2g/U/McoTPKoWXDFSPtw0UydazGtBUEM7SFer29upgyxA24
-oHoT4qUj3+lelhBbsf79YuI2M+q6OfeWXfOEO6xkcw54SmcvfYYatGg9UBiZq9PK
-oUfyn4IOKhxPY82N35tDfoeBXDAwr8r00NkFJl2vHv8QkIKQFF4HWLJw/aElij5t
-T34qVUE12H0+oikAEQEAAQ==
-=Uua5
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D7C92B70FA1C814D
-uid    Matt Sicker (Apache Software Foundation) <mattsicker@apache.org>
-uid    Matthew Sicker (Signing Key) <mattsicker@apache.org>
-
-sub    B4C70893B62BABE8
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQINBFMvQKsBEAC3/wuVMv4ia132SA1Y/KnuZYkSNDaRH/Ie1WTAX9X0KrWA5fx2
-WmzKfaLNyBHU5aI0BjoE9DW3zkZcLEcL/cxRzoXoavUGRhRsaHbj4PhQkEqV35L1
-OdsOPRc5vesIyvYlQsThz6LS1LRA+nOz5qW3gwfrdwuD1AWjHHluNVlgL2y2ydQI
-m4nd24LD2VssfiNXkquuJmOHZKA1EWOwDq2SSQCyx0IcQZZSF+y/pnp2JUkGoI7L
-m39XPa72sKRMBSWoRh9i4+dGZSQV/BVtD5UMOFsfTNG5Tnv2MXoql4q+C3Id9evM
-3Qglih5Nmwld5OxjxhCvUf/FEz+55pibP948GRuhXL0FATabJEkEj3XwUaSvWQpr
-4qu1qUDqfDlCSKBfJLkx8hBF6ZthGBQOZOCNTzIie96ZNEWmZu8iu4JBl/Wm+wTn
-+Nkuu75wfTbHNIKPRBpuXysDtc4OvzDV51NW/6DOCJW+qLD+CI6BazdcaiWMoeFS
-irt5deDJdr9C0d8m8iD11XQAM84nTxAKaBi0ihiWYCMRpwUV8j3qxEiziFRa5h85
-3/6WiozTxLgIoJIGPoGFDisJ4WXweeT+PkTgqJ6ZlR1FPk2n7tAaPEn6/O8rdiYa
-HP0r9FhJYadPfjwAZP92JRIiv7buFz5VEq1Hqu8W85+/CeR/OLekTegkSwARAQAB
-tEBNYXR0IFNpY2tlciAoQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24pIDxtYXR0
-c2lja2VyQGFwYWNoZS5vcmc+iQJRBBMBCgA7AhsvBQsJCAcCBhUKCQgLAgQWAgMB
-Ah4BAheAFiEEdI8Vss+bqPAkFV5u18krcPocgU0FAl35lQ4CGQEACgkQ18krcPoc
-gU35ew//TbOSjL0rIy40vPDpdqLH9ulwNLnMx7xDtScYvSQOp43sBarvArtnZipo
-8IHH9fxybVEMaNlqhF/fI+E9vNTYVU9YLrz3A5z82nQlHoWzExahdAV4TnsmmQQx
-TAfp7sHqrfMckF2crZSWk+jiSlKo7BSAFDk3DHU8DPz00q7Q0TrxLQqhGjLbxvd5
-mBtgr/fD15HZdAo9uEnAnzGumuuoDc07fJzxM9tlymM7Y09Ykz+reF569synCA+u
-LIkpp3cVHoXwULZCMGg6Enu4P982BMYVBYtz9mJotyVubxs3g3bkpl+AtFakwJxE
-bXxHo29F+l+HJlte2RvGG8+5b+tLj6HWvmfpF0oRXXcvwnRZoNHPUsF74W0C4Xd0
-Uc4dCT6xdEMvnF0u4cmVaMkJ06vFKv4DGXlgZ10Xy/d1yf6EtWn8z6IrWnfctA6J
-ZC0OYhOL+fXLG9QFqxsUS/KS3JC7zDOqAWL8jQPPDu53Rm3FiUAnzgYjyLfi4pJl
-rnopzUu4VkCZOMuOwiKbvNRmZVKI8E/37UtpYtmn/wFs8e5j1SA0x6tpAX6UfMyO
-io/9k3bvourZ6sp5Mv1gskEE3NuMWZBGWlRQbNzUm8xRIdVLogjzp74nFzQ6R0gw
-/5voofA65kxYn6IKtrC/jsbkzcAKSK4axibD/n3DC34jFSXS0y2JAlQEEwEIAD4W
-IQR0jxWyz5uo8CQVXm7XyStw+hyBTQUCWrNfWwIbLwUJDSe0zgULCQgHAgYVCgkI
-CwIEFgIDAQIeAQIXgAAKCRDXyStw+hyBTfrTD/0WfE75XtR0UUAz10LZ4Eh+S7jp
-N+PxkZ4tXOaE/IqI21pLkz8Ti8oINbym9Boc03e5Y95uiluyIzPL+kRctFPx4Egm
-GBu5/tAPdKjRo7J/P396zvXlE19HXVwLG6W3ZG0q0uDjJ5BC6HjSrU/FGYpFZbRa
-EhvjHWQok8aFuTES0uyHgAmehq3DkMf02OHeqClIiiaOXorWTFhritiEjHqBGBGe
-IGM3EhxHceVW6e2rpRW22i4USxnVIcRNzmjDar9jYbU4aiHdjQKq0bb4/NNTbrkU
-X125HNj9a4hkJpelEr9mPNxB5nNs/APYX7BrrZ7BIVqUfyBjBBfjAIlsUiRLXDFY
-h6F/2duEixAFHbZkKZtv1XMNOdEiLmAo/VugYCoMxANJPc6H79WHd9+m8nwTvJuI
-p5edcj2t/bmmOns4OAJLF3puKUdX0cr7xH75ciSPHaxOR9oddM6p2mJ9368fxP1f
-qBmoHqCHC+Uqc/a4/PWdD/jOCI8XqLoIsucYeq5ZLVCq6Cv1H/CQVBu1CqK1WSwf
-c516UyCM2CXEoLUsyOVCywvHhEZgpcAKmKR8/d6zkDLd650nUng/kjm/ID/Y4S1P
-DWJLULJ5YpCTt0suLQdVPz1GHcUmF36V7QOr3P2xf7MLsB0khnEthx2uESLvzTxj
-Fm/KJJUhkJTqwAbTvIkCHAQQAQoABgUCXNxsVQAKCRCBq66oIN6eVEbDD/4hDrto
-6MsHdoX+W8y1OtTFtmr+6zwUcNCB3i+O9iYKcSX6sOMxlgtlDjdmN68PTLE+N/l0
-+EAAb3snqavNietamT0RxxggD6NFOS+bMUys5yGGO7pMhMuiz3Z9iLJxETe8d5Hp
-nwdkxifQDDAMUV4Mu0Ow20IbWY/TepL4V+IxWYPEAncG6sgPeD23k5Fai72VPG6R
-ndqx8f+qQngYQOMSiUwa1kJW/2LkaTpio4wpc97LmzJIYtd9oZYmUzaUPrYh4Ft6
-gKptCcdXlOEIH69U9etZj31rtyn8hFSkIT0utYiuB3YFRbkpMzYkBH5YVhm/0z1e
-hV3J2hMgwUC/cQlIivUGaHaGS42B6OEjlAleIdkPltb2JTjvuhtgnSXNuX7yftDw
-Z6vGAm3hLRwg/3Tx/ZHss9EqT+HWLwbFTILuPfghR2K2Ol2950iHovr5LM4uH5A+
-WDIzC9TiqUKkdw3jfLHp+ocgQgbj1Hp7Mv2VSlFMeF0tilwra5yNIyYw9lkYKCbI
-ySzXwDTLz8shVOBX59Kvify8tK//kwkAqCwkbEw4NwOaoE8XfIQPzie/5Pm75dyn
-BL/99lC72LNtJKss5BC+8+AenraoNkydPa+oSEfswbYZJxYNG0b5AebFf6Pp4TyR
-CDSo9uK+SAUbuUuxwuHk6ygfogG1PMM3ypCK9okCMwQQAQoAHRYhBCnk84ET33B9
-cipu+R/pr3MRjxp8BQJc4JwlAAoJEB/pr3MRjxp8vn0P/2boa5FL1E6KvsIYrNUK
-4eMfQuKWJ3hPPEYpfZNjhxt86bjd2Lt1ADQkJdijhpncWfh+sFiqiV90rCPfoMoV
-AHrYnyj//Yl58gaPC+B5oAghdlNW607OOq+NXENoJbiMfarUz68PxRiATeNKQHy3
-bsne5i3gMPlv2HHJi6ZGHxT407JadMb39e8Ox7D4evs+kw1UwzJ0a2PFnEmr+wfe
-ufC1ME6Vbd5d5G3YjhhrpY61EAZewrY4xspBKgxsGDJiTpZHKkV6ck+klRAtup8T
-fO8PD0XlXeHiwGXzq3NxTvbrdsrhFDfQl/cgwnbgJnR3A9h/GJAJoN7/ebtvmrBl
-dNzIU/tHtbUnjrMyPqTySsEv2bm9HdNdVqyMCidnLoUW5VwGD1tf0Ku1Vqd8vNXk
-XMxQjC3bvRDXa3sMrY4kbArmCaM3x76yPUkRwv1k4nRnsNKVefECmap8uFlX68Ru
-EmqpgwM1cbLvcw0TwtWAw7b5VCHzFmLogH6VVFOCiqpI8oOIcMeiCt8QJO92QZmr
-pO0VS0g4tjGrGb3Ad0UUG684iivexYQSus+0smHOx5BcNanerBIIEi66V7cRTRgA
-7bIrOT7HwvLD/DdlV4FwIvZKNLNOP7hfuhA8VFqKK3UMOOhmS3ODGfEfevs9hcAp
-J2y/JGqdomV0xhZhRd38F4YqiF0EEhEIAB0WIQTolmUg2iTpZC4Rml8Tlx2jlHW9
-XQUCXOy2DwAKCRATlx2jlHW9XTd7AKCLFG+FXUhq8af/NPQ1OnMetctLlACfbu+u
-56pK+3FaTj8EOcocUzTELvOJAjMEEAEIAB0WIQTEe8dt8BksspRlu89HsdatDmgs
-nAUCX2jDDwAKCRBHsdatDmgsnG1dD/98bY5FYqFP6h1ysbo+AWThcnOwIxCCnl42
-75Ruj953V8JHhm9tLX67lXuXNM2YzqL8O/OjnqeQ87/zYobEU1MJK3pHEyRFJv5q
-m+hD3adLKwoZiD3mG7haNFdiTeLXtX8Ky2jnPZCMaPibb9gXbzMqKg923WVjyjWE
-+JE9d4wZbgYvTPjRpKf+gAjt5xZaU7+Z7Vq1YRoWO2hIzBHI0D4IVP6EpeGEHi7N
-I1cP3wW/nIvOjLM0CqZRjsSHrzTXLc3DwVWV1VF0xiHmtpcs68U7GCcGgxJUCT97
-bNmXac+a1eZji9v5VLhjaMhF9a1nTU+1dFSwvxAjnYrmLibaeEEEnY1enq1g4Igz
-/ii94/4B9UIp4Lr5UTkngRchQLgKQQjqN3+txZeL4tAmDvYUL+1gvKmkvx3bRvc6
-WlF9ibH8Li4Gn4SU32ALKScg2krKcFn4H6VP00QgkTWhyXSrXFmpgZ9lpaBj6gKI
-HiZP8ykEiTAoJw6FFKchKd5DdcYn1HEuIDJkZlZ4gZMCSf5C1vYdZi2yi5TtewUb
-5liKKyanVBkL3q1ju5y0cRhjzF40kJ5GL2+5C4+hnZzO/I4cZXCyWKR42IWTXcRI
-PnjrJQJKJT/E3Oj5Lf23VDu/FoV+tOhMDSeKi0nXcT0yNopAQ3ee1SSth25zA3aU
-JobIazWQo4kCMwQQAQgAHRYhBFPJNYIapqdVvTN9tTWVOV6z2OG6BQJfaNL/AAoJ
-EDWVOV6z2OG68+cP/1IPhPMuV2fN26b9LX6Ndji3Er/2q/C9dLkPYXsGVHeEvTTZ
-htFLGLZuVzJN+DIeF1Omk7SpJjZpQYu7o7uyn0p3C0e40rgm8pUVRQhzKRZ5Srm4
-sI8eBzfWk/xDAU7CXMDjNmPsgmSOIITPg0rADywc+fYsVtCHKkSnTa6teknODMtO
-Ep3SYKqv0V7PnaNm/NKkOulosIUbqoEOe9066olzVyGNZ7GGT4nKcgnJr9PxgsZ2
-6B518N975KOri9bqLONtcxO3o227KgqEDakeWYsmGHAYd0X1DmYb4onhIoTUws8X
-KLtsOju+yXeF2LGosW8MKxPd41NxGVRCVpmAKtPST8D7UbuxjBiqiJQAARI1CZHZ
-ScYGN4+LhzjoBf/fPCLLblMCQx+I2HXENQRSR7lahVq7/9FlnNRAXKp7Ftvya1ON
-97rNQo+uC6m+0G5PkHezyL40LOTMHpq7DYu4OP2ZMGQcLsl165I6dim6XWm91G+q
-I0nJ8KZTc7GuHkg790P8TeocA54o6YU95y+nSTU6ztgOnLQ9y3jNQM3X7wOqdxeB
-6/wfmLgFFBcey9rRewshgqQEaAdGrW/lmk+nC6gXMiAOGrnMWJAaTChG+aICLftw
-gqXAUqH06vKv2p2NqqmMupR/zcbtMNumVe7RO5Dzvdl2ArmYnVeck0DwzW+/tDRN
-YXR0aGV3IFNpY2tlciAoU2lnbmluZyBLZXkpIDxtYXR0c2lja2VyQGFwYWNoZS5v
-cmc+iQJOBBMBCgA4AhsvBQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEEdI8Vss+b
-qPAkFV5u18krcPocgU0FAl35lHAACgkQ18krcPocgU2GYA//V2qBuqfIs8DXjKDV
-xsQEMu6Donci3vj5Xi4kn/f2MRoL9d/pA4k2AL+s835tS79o8oDFcmqLErqaFSNX
-XhhnNoWD/ShE8GqtN4FV7vXb6pK6miNYChCCV94IALqT5fU7kpG0nenD4QZyfnWN
-hCk20eqZy9AmfgtLfML6eEh3Tc23SFPnSx6qrEz/w5hf/1ECTBS2F+HXgROd0oKT
-G8uPw0YdCDrguRX+Wh8gZ7vyc5TeU0rLoEvJUzrgncQTEaaT17EhUfI7IexfJH96
-k3fsIZquAjTHz9KtjAiVBfpUC/egNC0G1/i+vlPmxt0rBPTM9npW69+maBXMKdei
-KvEVywIY69sXju/W1nO0LqJCWxNQ5V5L223tKCNqn2YCUA/hb0sLKNGvox5SRm7y
-S/6QvDHDwQmNY+LXyWqS0uTeXfinlgN5sc4mL4hqceRTGHRj/SoamlfxRfjcFXHJ
-diEcaJIwWA5FRu67FIIZXx37+d1QtispkDqfQg5yiRPbaDTjB9TSlz5p9LAM0PJu
-ZbaFSWIDN9dL5tLRzHVxH0jO0EwcoYRs7eMrS191dHxffINrQIBdwc/cILQwS3/c
-KGvYrL4wOyxvjfQvT1SRHs/kHRES1c5qI6s6cvyYu4/35gFHZNcvLyOMr74x7arV
-OTlQ+tXqYN9aym/ANP91Os+QnA2JAlQEEwEKAD4CGy8FCwkIBwMFFQoJCAsFFgID
-AQACHgECF4AWIQR0jxWyz5uo8CQVXm7XyStw+hyBTQUCWrNa+QUJDSe0zgAKCRDX
-yStw+hyBTa9mD/9YHi+CyW+9OMAoBGANE2xhV3NVMQF7Yg0RA7+tLQdzeYffI2dj
-DN2pcSYbbb7OOMVh9Bl5ikV8tft3BLwUnZm/5LiZcPIKQmv2e5VV2lg12khKL/6A
-xV02mL1dt7EcX89L8HRH/slYJzhcKN5OJRP5dmHmWN8B9eKuGOSuzYbCMV58tokE
-kZyfSUjB/dpIy7670cwJncV5eUV0CwZWYP+4uHkCOnbYplI8uOBaZ602mKLq+AX9
-UWpXcSUi854wyWgJSKicswcxysj2Ryw7QsafticKJa1yh4e3cg2tBKlRguj00EUi
-uSK3mC/AtHuhdjpbNxbO5AJ/XNhGNIwX+1MTNAb7qnV5cmzM9LOUgnF1yxO1dQ6w
-BBSoxbs7rrumIfN+wXyngEyviESCQEI2CIQD9YsnzLGp4Jb3P0TyWH9sYIfdWE7Z
-wBXrFr+VcP3AI5E23aW3CH5VcR1ldzKlU67TAgXpBv+ZM3mufhLBzLFGQsLh6PmZ
-C9X4Z+C92SNoA8mwF4Kn9mXXfjdr504D1mkrqtxwRypmDNiryhdtN9k4vInkTGpP
-k9YORJR+l0LBc0n/vKxRsqmcUDxNK1R5eYeP9jnY3C8NdC+icC+iSnG7KpgygiRv
-ppE8RFeksKUHaYFLc1TP3qgC2ARCO6uCsloUcLgWafUVqUd1yiKI7m+0EokCPQQT
-AQoAJwUCUy9AqwIbLwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRDX
-yStw+hyBTYsPD/0cQeknJvRxCnA2lQBLFgrppR3+Oksaq6DtVxv0pHFDXfXNr3TQ
-3T4PLe/sBXHQ+NX/wQxukiODkcwKwhB+69420g+c0GwqsBGqgRh7q25GMtq2K8QH
-DVuyPJRpOq6uZFRkMuoh9ctugSOAbDnhdjkybSsgly9wGCOvjKlt/pEs1d5IULUC
-0mJrPwtWoKJ0RidulUJD/D1Z0nzBCX3laq6qTMdE4I98BQJKf9ZQnANGNJCib5v2
-M5cRoT6kyK6P0mSdxA7yqHYJLRIQBFNCFriww2+jn+wgTorE6AZlhaThDmpOIK32
-gPAdxYK5VF16LyOhOcRUE/yw6hDf0NX/51Ny8CqfrwQZAJfl43khTNfMaWXKbCUO
-rWnaX6H0q0w3qG+pIIsKMq1NIQR6Zsadiz3malbo2UAp/S8FpGz3meawj6EU/f0Q
-QxrwR9ffUAJUJ9DWjPSvUloQbIfPqVrNf8xEMQZ//1BoY4pk3mSKYFi+bmunPKmR
-BvsMMKCLlKt2+83QLSd7vbfrZZFwABTt49/BZHzuh4U1PUtYIoul9mDTZBtw2T3N
-yclYwbve4XW+eKmFoIHbyKgfV+e48ID5O+y/gh3wSeYndiztTgd4WWUJv21JgdSi
-af8SEVBdU7pHmKb5hdSlO+RTnHZKiFcomVZxDtFTTVABbMaH2B5C78dR3okCHAQQ
-AQIABgUCU0YJAQAKCRBxhrBuHtE55w2vD/98b0padaLQINFlowq0qeLHoFbpXfOO
-+zWbdw9dWJYaPyJgqvZviLLW+TNrOoW1aMNny4lmtj2UZ2OqvGGISH8e1jX8tQUP
-GAgaLP5kWB1h5l2dXGZOh622vs3ePfTysg9oxDBJ9abDgJ5zB5N5e16CbkSvCu27
-WyPomaWNXWv0xdfKu0yOEB9H6H55VP26p8QB7zWmEgph1uVnTRFjcJyOBwGvX/nQ
-TQye8JDkmAsCpc0Nwpy48a0VL0gEXGRxzpVAqyuH91YUJflxw4kLkffWqmLSDKBx
-e2k3KQ05U7B48ap8jG2IL0CahNOfzGbbeuiLh4RWErvEaUhooVXGO9k36gkcOweH
-bKKAy6Fuf+Yo3YzJ/Vb2VPXhPzKoQqiq5hIMw6rGaxX3agtyq2jMoX5opS5roUcE
-YP+SSvv2eR8zyvDpDwDRCD/zzSgYEX9qt12uaOee184pex2ipxmC3fK2MpxaJ/Y4
-044uR2Aii0L1Zl0z7Bj/3ycwDv0o3Ja8TJnZ335AHxBI/Ux/TAOZ+//SvjkKVEMq
-EslmviGrz/T1FtN71D1u50Ncn5cUEBepurmHB3RvrOsbZtFkC3qhGYLjO8Ak35BI
-Th5ydpzPi+yKr2CLrPOyd2zAvvhlRY0azLqLl0Px1MKriuaoaD44YZFg2T5BkP9C
-e7z6LWUhhPL7AIkCHAQQAQoABgUCU0YqxwAKCRC517ARxnq+PyPBEACxeFjewW27
-6sJcPuvUNTKv3CpjJi9y4RTqZRPoE/ytfwK1izVT65MY6drDZXaEP9fDQlSjh/Yo
-nD5nftPNZq8hWk8KKd9IF4EgqvgfDvPaumItcanBwSTv9ogkLZfc6EkvGPqV1TPq
-FsAurloLOZnE4APnHcu5nskjgj2lqIY+E0qHECNFkkorO2xhLPsZGyFCACKt8OIA
-Dp00gFnHa4C7LHVatGHowelAQSNOXM1PMLujtFcf2PYnYkFBv6vPFC/3vKh4Qu0C
-V8edQ8LwXv4mEqUwHT41RhQbFx124S8MtJf6bPZ96oY9K5lkdGdSQ8WMpDf1KWzx
-TRsWUNV2adfXUI20IBobW+Ybiu0djluy77xzKQ2B5ANMKmM0xJV0CBDgkJEUg5Pi
-AqCScWrLj2Sh68aP03E1NJRwum6BVx22L8XB3hb136Eh+7P+eu5qv/uXeYLcPpB1
-5M+e4aeDoTJCicfRCrfwcd5KJMvr1CyUE0GPpZl8llQy2eOyBgkHS0A6rtiaQtL8
-Rv67sG9CtV+YRVqCK7xaiv3Y9CwJJGpibHP/snlv/B6eqpOYQGMD2imjRVie467u
-EvYyWNEVeAf//S4xuMsyt8pBsbrBRwq5wjAi0InAIQyMMPupakE/+g3kHoKPwMZL
-ZgqXT9Zfydx15kaNfhHc7r/iNbL2kI2aR4kCHAQQAQoABgUCU0cBZwAKCRBsRfJH
-owPVX9myD/wOlttGIEg9a0IkymlHJbf5PqaEheGxPHFFUPUfkXauKD21JEXhIWJJ
-8IyQODmX9yZAinSDAeeFSYYwHLkXgtWFSSKouTMkpNFcJYLngQ6X59SZEL89Sz/t
-zpf9S7EbGtX74whWZDJ28viupAiL+/WTiLu+j8w8f0r6rpbFJtmhD3I7ftHGg8Ka
-g2wCw3VR/ZAF1+p9dz8fDe8wak60sK5N4I9FspNDMllCsLZ6ckG1SNqQc79MKlqm
-kN7eGtRDZEZtZcZiTzKUrPv1yMVoq73WpL9f/QJl/9HhCHiwmFWLR9y+SUEfFTL5
-0N/udkxU/XjupI0K8KeuKQb8+9eOXJtrvxMdfJYECYOYx3mZ2encPnfSknH+CDnu
-Im1RllcdJGkYH3WQLowwHqvczEWDQdg6f2lr6lvRNB1i0AJXuMv5kqwPxkXBHPMp
-T7gSP4EtG7uv0Qr7aIOD9oKhvb9JxDhcba2Mt3muebLe5yvNypQOtV1+9ybp1GSd
-ldHgsjQB41Wt4+BaeL3TDpUihhz4ML19LuO9jiSltDqUJRcJUxU8TihKCWWxStuV
-jpLXjl+dJSXoXy+dW00/C7+rOiyscISbKZ357WRvfsi3PMOPqpI+LRauelnVHZHT
-c47fg23fo+EhtILt9qmBQfejX/FdlIB9U5qij/JxPCumbksoRR5wWIkCHAQQAQoA
-BgUCU0h+1gAKCRBi1I+tFqDeAZohD/41Ms1FUMBWWAfFhgb/UfAqsp5ItPZ5l4bb
-eGNcui/FQGX/UPhmNl5A0DupMg8ue0FfnuxRrOpyOSv+a4aPSP5osXAGYc2OmxSN
-NFidefbmR0rY/hZLA9rG9WeMboozfewEUW9+v7EZZ71P/V7ZL30UPMeze7pcYJHF
-tde3JxlshBjO2s9cAXhWU1M8TPpDJ5QEcYA3ItwvcaVkCgUC4DOku3y57zLAkx+C
-VqFKS81k5KMiEbrn2Mn7mR3bJB0HruZFX5WEDpLPVXEdY0dItm+cv6AvFj4Z+sDJ
-QFM6cg1lxod2i0eUfbhWToC/CJ5ri+VKl/zOCY1R3YLcJU2nt7/XACyV0QpGAWu6
-CZinNpUdyGXk66HaG09fDM2H3L/QkPPi0EmeeNBEz6uz0JHtiYsb9jjBmXscleCh
-smJU8TzGVDJ4109Wns8L33GHNqnBBi0Et1rv6cb0bVbv/7mNOGyAhtPKGikXw9Sk
-2oFIwb2lLbkWqykZpdEmzQ0ybr2pQwch4dYTUkbmwhpBy6u6OtR3jv3+VCFBU9xv
-4thfHqU9KksQyXrTrvdIntMuHMB5gNwLFY6pVgqXlPy4hQ6GFmhU9SKPnQh4QpXR
-YBsUNEAbBjJipnAet94a4XqvPdyoZL3SYdm0FcGLiRqRo5suMwfBPrS+XPxCR7gV
-dciUrWUHP4kBHAQQAQIABgUCU0ivpwAKCRDceM+3508zgsxnB/9OAr1+dgmxeLJO
-eI3dM8sSCmg/Fbtqz+GEE3EmxWiDHMYVSV0ADYi2koxhnS6ooN/RpUXviEPbBsRb
-8mvaNkLmS7PjXfmUGmAb6Dnh/Z0wUKOHUQ1THXcxTrg0XGhfhxkfkukwQckaY7LO
-5IAdM70poaAof06lgTD7fsahwpendPJAyYtU5tp9ruXSByLJiWq03mkZfh2p8+rt
-gvGOHP59vIRw93y1EaskiXo7mWBA0JnYHT0xPO5Lap8JJNMnwtJK1r3FwoZr+cTR
-0Iur/ZqzIwptQ86lsey/od4ngwNL0B9VoQFKtgKDvxHRcg/Af5DEvj9aykxyomgo
-kxJEf1NqiQIcBBABAgAGBQJTSrx6AAoJEGFAoYdHzLzHU/UQAJ1uJerezcUwUlLE
-GTuWSP24b55UFvQDpP0yCkW4RpGFzph7Xhs6COGI17WdXjJfaZgzUVhuSBb50Enc
-ia0trlCkdXReqzxYcehop4R7NnbYNMdEnK4FMJh7ViXiEBuEax9IEETp877IYJXv
-ln1owzsZeL/BF87U0yqSxa2XrXY+xLRKChUv6chXL6W5FFOJ0yScsyB/YrxjIFEd
-CX38zy+NkUbNYH2/rzQu02ky22sCPLG5CA5LRzVxRW4fMMG/9obaNGnKFbLSsMhY
-SEQjJh4ZOmi2dGRxfyFpCJfCm9+Gqo/1vuV0Z/fNbV826MghCSccwxedt/swqF8u
-Q4pRllpa6mSSAxfKSFQGToB7GiqDIM7+ZzWsjiIHjV+a5g/AUgQ/1Si0atMwqCys
-kbolQckvO6aqN/drWjAOYwxk/n0lpG2vScn81ymrVnyFBz/fP8KDWTUVIqMoOH14
-wFBkBwtxe+zPl86rJ0xVAgs94Z1/OJV7MiRMa81xLeUXRNi4XAmMCA+oxHPbiHzq
-xzDH7pkL0sAitvpI8U1WPLFGvsxQQ2+AFljzkoA7YuK8oONoZd8LWbpgzKv/PkYM
-R6vhuAGokiBLSRd6fE3a1hMIaZigv61Ii1FxY4lYnVs/OKv6nN2mV0QoBScm85dF
-Elzp1Ep09H74D3i4WbEfJbweXlKdiQQcBBABCAAGBQJTSyB2AAoJEIqviNbYTkGu
-oysgAIz0oF/YUPUhCF7/qPRqHngt9cJ1Ap8b0LQ9dcntrK2czYQwTBYmHdJmQTRQ
-2vG1Y0LmoaHdOAY8jM1zihmes2DHyVIN0PN5m1dQuFCaW5lZq5z7bUk55QyF8379
-8h8A2qhoqXlP5Z7GqBgFy/Dj7AErBJFmRYCNenVi2c1BJBK43Oy/c/9wSVjyqqyc
-40UGBX1jxmlOCbQW4iWhkBVeOVH1ghsaw483GYMMMNgC+xyvo1g58k+630sR5NqQ
-l3fR9KjCcuRrbOqltkEXMVZXPVX6FsEC3cvfRDX2d5uDfRrRd/BWV6xZjiZowR/J
-3f16OFU17NRpDNwTzhrLv2CqierQjTtsAu2o1xzwRbuV9hWhFeJBKTC2TV5yPy5Y
-BiCE7lwKvYC0p5sMu+0rdteejCMh2lzvpom39TrFfM/s3IRv1yNsqfBMCrBUIJjv
-q8kzTXKaY9ozoBRqlRpVsJPJn21YAPjAwTnVJMHTgj/thy3dYlJhDn6ZOhXoxNi/
-wO5xhF8SsGxkhPQnwtuzNe7COK9ktyUVOY7bWWpzLnMa0hPyM8uXF6ahWtyelgJa
-GZIsfY2oezkJ9VPkBWvE4qiYf32Dx8+AbsWIy8PpefZywO7VQwQZZKlwz8+SVqyC
-q3Z79fBWNBn++CEFwED3k2BzWZB7kGrFU5Em/v80V7d9WwwOGluRrqcXd5pbq/Cg
-bOZy0ujwmwaQv/RULnGlnQfWZFeMoJ34uy7YNmhceXB+Wj46xcotI5cZ9GbekMgK
-LUeil0TuDSAptNJLCg5A41FmvtfTnzG3gD2cfSZzLwKfaGlF3TUJ22Sf0uUhUQd5
-lQmK9t+T3MM88fU7l3iP8pQxa0urlybhBxapXa22rN3tfybrVsmijK0GibjSJiVj
-Y1l3MNTmLDdjSHZ+irWx222xRJzIeIJ2vpNzY514KFtjJbrD+WWZUtbStzoF+Z9j
-fBRUIMjfAbA73tQchpSN0xRM7Hi38AgeOp5eQ1jfB4QD9W8ifBj17G3xcZhrPzNU
-qKEppZToTq3dZMCbMpfddUmv8Jfr7v7x/6Hk4YsACSFuikyyPYbeRvsTduC4xl1d
-izKnCCE8Uj6Tm1e5/58Wax0o6HwVtRRXluscVOBo73p2hL1vYullypw2HWCVWw1H
-C1qlFzCzeM2tuFY1qw7XyOaTisbCx/R2uAeXdTaoKsHHA2bLWIvpPeGesjrUK6m4
-7O4iRBFOVfoGPgIhUST6Gw5+43zeEIv3Jnv9AVsG5msYTWxEtJ2GZNQq8zTlmkwx
-2fainP6V0j9/xkFTjLy801JsgrPsPnM9kjen2nZPoGX89vbWtin/q+PeEZRfhT9x
-nC4zoDaukkJC0wXYgStDZfkuQwaJAhwEEAEIAAYFAlNNSPsACgkQ861clKZ/cH7+
-vQ//ePOg5vJYko/eTb2bjnX1+wW5Fo2b6tmMwSCxUtbarOX749SMZ3e0oUC4SHrz
-5AcgVVePp6tp6RgnGjDsxQ/MbUsHhpFAHPX3MrhbhfbIsvxysdZu674KtsE73T6M
-svu8H/AtytonRowdg9O6ZEKVjmUBpzoFDDiPpULOe2muLyYYMH6qlPoAFWuEkeGO
-fZSlIwmPNCFs7ymLIJCZHDjORWjAJ5h/edhK8a+UbZTGfc40+MClEOLfhV5z7TOd
-XniT5cmhVZekhUGuMzGxW1X/JUmaxqrNdcTZkdVCpeBieASsLej/MI7U529Pknwz
-fNcX8LmbE0kKa89kxEA5/RQyhJKXrhVFoCfTIxGMVML4VqY7yKEE0D4D7HARjq2O
-Fn/+BLXXf7tH6jbNo7Snay0Cz5pgVIXnffG7o9ksMtio+inAkN5nzbXkgahEfBpJ
-lMuV0AoOY30J26OmUcmv9zGeRLcb/e96i2j5ifG0ln49u8lleFu4vRcfYJNf/4gi
-bzYe7hCsTFt/+8qvsWVzoyY/3qfDsD41vSurGDKfkU0ExMnvytWUhc9iZrpsixFo
-2ob6uWBIimyFioUWEHLwiX4h3Q062CiNj/Rwvd7H5nL3SuJNYe4787/oGzBtKIQG
-+rvHJClcXgmdLDLqGhaGaelY3Nq/ksMr74WS8zD9lIg3DA2IRgQQEQIABgUCU01b
-oAAKCRBc/Tf6zHjIk8w2AKDZFkSUtt/POaXKPRQIrsUC84up2gCgjr35WGd+zT8A
-t9icJsfyeD6HmYiJAhwEEAEKAAYFAlNNqJ0ACgkQzeGjdEknVVMv+BAAtYg4FyQR
-1UjkwsSQcu6q/7wwBD6BSPzfLXQo6/aiQEBclppFJqN8F4Gb3x6+Fx/TGso1bcIp
-7SjHNzRcQ40amfxlTcFMHTIGYHghlbm3k2LmdaWml17s0f0U3LDIOV4DQ7GI4/BH
-owwpgf/Lg3lapnmdMMvlSLJDCs7Zaa0zXLFQSEIbmIGsvFgtCGwjT66S8swU8aHW
-aG98A/yK/Yfd1p0WPtnaKkOoe60CzMBZwtAZ1dTDoRmmxhEJo2yZZGTRe7r5w0AV
-fPW/jdtNKTKeR0fFfT6ic9P3UiqbD0JG0jbrKVpLw95NVbpDbVMqD/d3zic+v7RJ
-/6uI0xJTsNNcDLFQoGqVl1fImU/O1NcAQiHDI/QRAIhaLpwWQwUdKhvaQFU5qIiz
-UosYvZ5bxijuaSli7ZRQ6Kz1OP9HvHjEaaP0IcaWjw//y9k8X8wjBGxcLBEauDH3
-mHoUebAsZhx6H9YmL5ACFRhwNsoOtkVgQG2A1DRmSJgIDKuXIaTSkM56CqBgjct7
-pEg0/ENrAumkK7n7JfrDeNHjRpxjKZBfIjhQ1GR+dYHQvLO9OEd8MChOqiVm4BXl
-8FANYAp8A/oAQZGGZTmq59h2Q733cfvPlguhCc78YdZYwPGFlEKvhGKtSrIhHHjC
-FviMHF9lujuK7U92PHQgdwTVk06fJqxRCS+JAhwEEAECAAYFAlNPfrMACgkQq+nF
-0h76/TkMEQ/9Ek+hE5mlfC0uLaN+1M2/EG3U58aU4Q3QBzsPLTGgC6Ap7HJb/sSn
-ZZoeYRZf5oJ4ZQ/FjCaeuMc6J11hVx+IUE0nDDlehbcWo6dfj5tNbvFqa0oR/Dbx
-WT67yh+cEvL6pGFMGWk61U2bw7s455LOZsTrETAjHAkkgVXt94D+n2pLdqTpR3yz
-iyEU92LVLo7gmBKJhve9Fc9cqqrrcte0K37yTYiWWgCb497h279K7QLa4Sg5Pgry
-sKmjXCAzZKN/QSzkyf9p7opKJ3SJgs07T88W2OR2xY6slzphQSgRzqVwgbXgliKh
-Nf1PBrpsUkzlQs9CsZdzIyq479T22aliVSSJkuVJrA/hn9VMd6rzftb0PYs3G536
-RdK+g9BGHe5sqm22Qmpmx24O5vIKaJXJyTwDDNsL+/6bVmhPEqHEKnigCP9lMVzk
-wUIXWDOqT5aHx2vpic7H1v85EW6Rr+zaIpz9vgackKoUGjZoqrsRSQSKDkAb4LbD
-zfsKFGdjK8mMXWqE7kfXworVV+poiIshea2wrzkuV35U52y/kOhEt5nft6oLcx22
-0B7psVjQPVmL1UA/wjuIKySVbnkNIGSmfk/G5TdyPYVq2u6+y1aJtRR5MdCrHw+A
-8EdE+vyq04ujgdWl1Y/mdud71sLzGVEaPdVyaWwE2Ts+mw0eqRYFC6qJAhwEEwEK
-AAYFAlReKnsACgkQKxGKX6FfMLkVgxAAqUz1DcrAcQ97fl7001X/AjkIje790OgA
-XrCgbo39QIPLPvmb6P2z4Np5BN6XRtKhiSVjPPNPCQw34K40WEb6hAyZofKDJjZc
-yYlxHkzku8I44Qmy1aVIMwGpQS7qav7T5DFRemvcDW96L+LG+JRVEI6lImsxUhRP
-wf8gdOF3YnLyhMhJKH0u6Wku4bMkwOmC87axfPkLEmAkMV1/8nW13K5W+ZdDnvmG
-ObGkB/Dacz08yAzwh8BiucGIpdm2EZJGHQeE/BE//SsnOBlV82fkxkMESj99Xha4
-sVVHqyaxOA3a1xn3juCqaTD65OIi3a61cgPMxjPfcDSxEgNq2id3xu1SsJzgRxz5
-PeEdgS0A9hVAekpOTFRFCFnJ4zk2IgP0Q52GlzmpRyPTSd6Bqg5ulJO8X+xI/ZoW
-83wMN8VymlNacyaoY4JNZI8Zmaupgj8JEykPfALbqAFUxZadMNHvJvY5xAlen3fi
-gqZdZ5H0bH+TtuelzYahzL6pFQQACAz0xLtn7DheWTWnS53W8UizA+m6HkaHxVMA
-RuVyRElwSpHFu1jsX7Lr2Mw9DcpyqJpwWPPBwhle/a0pgObXRiAKu6orXWhxRQi+
-GXL5dIxafr657Zr1vgy0lRXHBvjSWYX0wmPboHnGphs/uIH70OXp9fPpWEKEkUDt
-TlTtnRab/muJAhwEEAEIAAYFAlbPGK0ACgkQGiI6AvqTNvi6UxAAjaum4hieN547
-+8b9hv4BjHQUQhPWKBBsd3XHtdMDBuFcpEMZ/sm1c+5FYo9Wm+8OJ8wY3YOFenQY
-VnBPDVc2iVc/+W+S6rNfN9qNZBuuuxsPeFjzt/G3wzIvDX7BR7zOYNmXNhFSAEpD
-JM3rIAquE949Hn3WwS7/X7WWH1tpid5ISIY02+UKnFnjfKilyqq1yIldhoNpqun3
-wT+VuYegpchzU5K5dnErmbQ7a7BOvY5weMJ5ONtVUbNa9ktA2vxeDxw3GX3joNz/
-+DLzkHc2OrFsFafN4guBxJNeS4yyeLKwRQrU1x3UnHmg5upbeszGsv+DxBeN5B6i
-Om6/uWv31SBrxfNmvgBTRDlCrBC4JmVBt1kh3SX2cFFQyRj4YKbEsASRb6t1KVMq
-KUchOdfCNA2U6W6I1weNzDNWJUruJTTH/ifCfb0CnYmiq1+I1XTpy9SYwMJWviWE
-6DqV9JNukqTVLpU66/fuWKjHzBUXXl2Wb/kBdVlWGpHNJv/Bq1YhHIowksbpgZet
-eAf5TfrjJRrL9BWsgjtlwn/W5bDCEnXstf34nMJmRcLWQKG8wZjQRg/AbqRyOmyi
-j7ACUuHxOsQiYjf2Lg8SL65asJ9rWgDv5S28LwCKwmGjhWYUYoZ4FLNHbSOWfDYW
-W6LqmoOc8dRCDVz4sL2Q1zUI1rH0RWeJAhwEEAEIAAYFAlbWUvoACgkQP5AsJ27Z
-viGWwg//aUqfPOy1gbEZdlK5r9EpgeUFRkY3vsrfVta7tx7s43ATgfFaPgptMAb3
-k58g32Deajq31YTG8wVM/NHxXzf4A427jS3obvQ/s/23CZu1fKiRiL03tBNuNZdO
-Ali1MPFh8bfmEa8wvTeWWCmpZJG9SZX59irxW2UzMDZmzMc6l11Kq7EnkqDs4HRe
-zjG17XpYhVLL3Ttzzo5/DeG0a7WeGm+a5aBhEVeUUvt8EHcb+IDKXnyyWknLBPLJ
-+pJjmk3DHkPGiFJBzWMRyjZsDivWwNs8FOVS7+vqYEJc11irnfXVghrIWX9u62qf
-ZH5YlO/sxbSbekaapM88VC7BtzeTf/OGVqyilHp/1tqZdVIgwFuH1cFsYbCGaOoV
-uqb+a5vGl17pVxanJMNYZyTs9DIRgMSttyh834xN4r1SjO55m8ujW91reh4FU2Qz
-n+Evy67ZKnB9pJ6nl/BydFiSM3+OYjq+5XrQSazRkhxJRxhfGAvVUcAP7orL+V2z
-RQ/8f2/TkkBo41d0jgaBnyU6AtBDke2lA2+2biGrRZdQXHglOYQqoJolEmnQsfIJ
-Ts2tLO2fVAcOnI33K6YU9if4vffCDSqfVH8YoNuS+I5Ily9WF0yh9Battb4uSul9
-VPeeLQiO42YYQReqRzHwwdESTgpP9VxHbNJ2qC19vm8a+1/yvMqJAhwEEAEKAAYF
-AlzcbFkACgkQgauuqCDenlTzYA//Q/ayCDSyaGziOaTb+yhcWOAtwuX3JucIoc7M
-reSh4EXFtRYWmHJAfQnTzaeDKR7GFUEhZz7qMMsQ7YitpskbsLrNneECcP60ZTdb
-H5SHPIV7fSmncVMO/sDUD1Cb7Re2hibfoZ2tD0qI1DrIZbqE2SQqAF/eRkQq5PsE
-iT/vutiQH8hgbqw6bxRukmgeIJ6t714ZYk4VRdtrJFtxeDVgaUcmRzUqvPh95AqO
-UgJdhLoY6mCAJ/6UQkE2htrgOe/4Tr3cqNFjvFe4yvCvl8/yxKtESsG42X3+OWcz
-3AoqsI+sW0KjP7qAnzA1+uy2Z5Pqk+JWsM6+DE/PdqYm3C9tBRArnb3D1AD7Xeuh
-PaAEXBeWmt66RSlvExPJaPqq0x/cIJT777fuB4hSOJ/SzL8uuA431twt3pwsus2T
-107dyskulI1UMzq9nOFHR9q1QVrG4C6gUsW4KaLNUoprXM1RB9wTEL4WmrpwMKMU
-ovsOJbCeB6PNSUufj9kQlgztd1SNlEZ1/MuPGaYFB9ZMqHqiCaIHUduc6hdLEBLp
-L+uZAL8mE1BYwWnIxwEV/LVrWi3L0Co5pGka8RN5WQuZxNMYlMpT4DSwj3Dh+IVC
-Pw19wsFvBZdjwU1o9J8IS/oHlUix+3yvD0fpeMxmtu8o1Wg9FXcOmg2ywLNATHyq
-YFIHVkiJAjMEEAEKAB0WIQQp5POBE99wfXIqbvkf6a9zEY8afAUCXOCcJQAKCRAf
-6a9zEY8afHtLD/wKqREEswojEzHP5vJ2AdkjZbEdldtyJ4vvSk32n9iIN0WP1KA0
-kPmfE0E04Eg6VyiP3m3aMupnvz0/akzgNywuPQU0uoE39Z1u31QVErUMkOAJX+Iv
-LpUWv9LAxW8KEOihBc46LccTz2ayEcbe4wOE1njidLEc1iGvXNDGKpKBEHVZZkFY
-F0DjZvMAbZHmnfcncLZqQU/lmqly/Rjukg1dv7hKjNB0/1OATLvgMVh2vAuW+pkz
-iKrP+6pIgRTCl11xZ0I81IhVeygtG/xpUTYhwkyVq2ZdeDTPEI4BgxSH01+jbRN3
-vsCwioTtCp1LWy+6VJbcEkPrEjzJgY1twuacuC5kO/Hy7OSqniaATxwS+9CGS65Q
-1K0MDs5NNfoTccjSnCE/1ObcdBgIrTOipsD/l6y75Al1MAc26Hxa1yMnjc9BRnuX
-sfSvRxMfPNSiyhs2PnZPE7atlfScfdk8OgJSQtQrdylmlukdljWC+DX0JybcDwaI
-95m/Pa5iEZRzP3UpOeWdSTl715FNrYb6D2KJKBGGkFv4M+MvJeNcb+WWQKl83CJk
-fUwKO9hxTmFXaVApu0X7X9IObso4t/u+wGkv96xQvRep/cOe7Nu3qk8wLgiuqMgI
-sjTazzYJSqHuCK+4xyoaFwwnv4el1le8vecawH6l74kU57T8VT8V0Vyqq4hdBBIR
-CAAdFiEE6JZlINok6WQuEZpfE5cdo5R1vV0FAlzstg8ACgkQE5cdo5R1vV3T2ACf
-TF9eflu4U/IhQOI11yASbvA9TKwAnRCw2oK1N/0WX+Wfb2rqKdc7HnO4iQIzBBAB
-CAAdFiEExHvHbfAZLLKUZbvPR7HWrQ5oLJwFAl9owxAACgkQR7HWrQ5oLJzgTQ/9
-E4n/6bVkgOjGgr+BOQVVor0GE+1XplHYS2pYZ+yNRi7ywppgeO5c4vGDBXmbK5Lr
-f0opekUpMoT83oGrpsIplklGJWb87IOfmvwfIWAOgupbqMxGsFIF7HbuH6N+aqxR
-PN0Y621J2Q4NSPnLOVLfKTjl+tboDfENHrBFF4/RLoVBZG+azn2Iq7Vm8d4cc740
-Dxe+2rOcniMHHBNy08pKMHRjishKf2BiZaCg2BfVtNvvlkSMI3Eo197+n2B36xqo
-DHtnQQdVh7ZTxT6qHGHzdTYfZZOg7SfoQHCtbq/04cLe94UFaOgV5fXrv3PXJd6A
-Zk12S5uFDBaV9S97hyEuOARzZqzVbXAuO3nI6kFQg5K+KfyMRreilK0mHAmHcoyr
-YRoUtit4KDT0xaOXwdde21Iq7AO2yDsLnOJ8xMq5V5ndh020/7EboOAxm5Z+U3i/
-QMAH6XpYdwT/A1JeNHSmy1qvW3Q4zk5V4hK0rxU1A5GZhJ5aYEEjK2M31fwj9aso
-KbR7RP9cVi9YpgPxbVq3kj4A8qKk2D1MOBUPXIWZqMKbZtt3i3T9yyM3qD2AweXz
-sT5iSr7mqfEHciZY0k3/M/MRICfHB577M8P/2B4goLKspaQwC1yeO8SbJgvd2+O9
-xUtLMBio+W5bA34rtL1uJTNnpJ393D5aj7Us5xAu2w2JAjMEEAEIAB0WIQRTyTWC
-GqanVb0zfbU1lTles9jhugUCX2jTAAAKCRA1lTles9jhurXtD/9w4+JHh+ffHb/e
-dHISAjwtRdIe0zRL9iMfKqDKFvpGUgqTPbinfJHGGfzr09pu8eoZmrYMZnFkWCFW
-7pvB1UEQzGWmfWin+6iDg63SKJ10MT3SpCSNAwNCBjhzwJ6+jYedmFab+KkKSZGg
-QGjtp0QjB8/iCOLe1cFeJqBIinrLAdWXe7BVNCVdtLmIkAS9Hznd3RzJP1bNNqGS
-6zGjC0S87A03jixVM5JLiEHA+0/vaa8pOiClzjad2FINGiY+gx1/N4tWM46CcQ5+
-uz8Z7F4rt6wgV3gyxr4eH5I95Ny9X4c1zN41iLa2cbHB9nbU538GMZlHIHURfSrG
-7JbplqkTb897CR1NRKZg1zDDBlW6BX2UGjU7EwNT6Rult2jcypEhUIjh/kfNSijb
-96wzWArNqAPcEIi9e3cSrUCSHRsgNAt3LsVw+aFDwV0a77wiZb/wZVGttNMRsexz
-pZ5hV+ULSNEl+WeaVfg8Q3PukunwXu//b+ljzuWh9++k57AEw6tp/aB2+DpIKikp
-9eCjdTP/SDNVQfAW1lk8Atze8odTjvYNOWazsl9PzgGP2RNm042hanPo/L78JXaW
-mpBSjKnnKDMHyRF4n88KAlAd4TlRvGq+2E+wqakbc+eWkIwImZ1YufjR8nx2Lpmp
-1dHLC/FtZh7G6S8T1VoW3s+oWug1cLkCDQRTL0CrARAAyHiCGHKiZtJLoVjJcQlH
-kyj4QCdoy6omzPSTVgThl/l6z+U/pYvjmW/39ow9fYB5VM8ISYOCSo252FQXaQrr
-VwJouEr1v5C8VM+y6P/TO8kUodaiIJRLZRJt/FmkYAH2a8coJ2lwz4iDyMKNt5XI
-v29v+h/fLasKxUpZ1cQQvjFToivWsO9E9xoUv6f1eSvFGjsTqGEHnC91ICuXhNSh
-8cm2nHviEp00/jMIPcjhZkG6o8oVvBbjqrXQkfcH2HuNohX38C6GpION5JV8AQLV
-T/2+L0DzSr4EsgbxQYfmqytH+RVnRU3eBYiZpq2mCRvSDKhakCO8cN2cqRQ+J4V7
-3/4JPg9A9vCbFSEsF2MEa+x9Oxp1jGazV0+R02jIC5RP2581Nfm2gIpfx9Fa6TJ7
-ZcAd1c8wUqEwzVW2YNEyE9DCIKR2Xmpp0ucChWna+guhjocLF118N5MzDSUtdfRr
-qsUhmp9RpHfvrlnKJombYS1VcS1o/yuVADCJetylLmROq5sZ/11hUgGJsYU/pIUO
-s5ntxHJlXvViVzJkGD/lVCPhSXptm+PBtU9PdpMHAMnbE59tzr1gno9yDBn/TjeV
-2H6R42vfWJXA9qRcr3XkAHVBg/ZHGRXwxWbgObFI1laoS2X6RAeo04GxWcSVbzeI
-eRUMHHKJSj+H6PzOEOneoTMAEQEAAYkEWwQYAQoAJgIbLhYhBHSPFbLPm6jwJBVe
-btfJK3D6HIFNBQJgiaolBQkS/gP6AinBXSAEGQEKAAYFAlMvQKsACgkQtMcIk7Yr
-q+ifzA//Vm60DC7Iedh4cx+e0HWqusD5luXchrGVzCMO/UNkVHZAn9Yn9buReZW8
-HCqr8MJZRDuSbLhmyY1IYNZWtLH1Q6raD/9MJ233nIFDOQqUkq6M8sld+zsMwB5U
-y9iLQaWfgLXBVyoIeMCZ20HjTcRh1cdpMpTfi4S65xBr3Ji2W/zApianwSWK0ZCL
-+ItC4PVaRpwWsiZO9p3/In2x9+9DbX7DpCxwEdOVpOXiHmFoaLLSUmWkdos0Tj2A
-zq85s+8ah6Z4g5h07uLMPFWZrxL8jCdsdD2ZcG9zk1+I5VKxuYdzBHiofHcZBMbQ
-CtXUPD4wPuyyeKrN0MVgYvNLgZ4Y5YGuLjhX00b0SgQIDiQOyQrEqJWmYVh0KxYd
-7Zp6Cj0j1X7svGObcpisrPRxzpQHEN3rfZGzghnuHiU4WbZk4QOwxyJkTEo2PIKt
-oY0Uza93TJUhFvj+auEholhOM0qzWV3W8+BWMDpHhHN5OMMy7+4mDQed26OXN2/J
-Z343rqEADpkm2m8T+O+5+y3+5mmF7C9IEOZggs2/t+28jW3SZtQ70KVsKYuLJzLP
-lFYIWeB6reNSAvbpaINjxm0ZKw5X5N1CzmTuKHkTzdCkkeCgiSSFeE+o7yJNurTM
-ERlUCWba/HBabXaKtB8FZstelfccSeRu5DfzESPd25i34YDAS6gJENfJK3D6HIFN
-ERUP/iF3VFTudcRL8lzBZCRfSrJkXxfEHEXlZfXqjheLszP4HemF+/GsuG4Q/g8u
-YUqahWXRY4KfaRcZMfJ4iVGfHsLxUkzsAPm7IpdUB9X8sadNbjWIrph6fTedTySL
-sIZIfV5NICCpx3Nsa/99LKN3Qjvt4MuEaJ30wUJrEPKW0ai/a+bm6JmYd0TI80Ke
-+qhGu+Xyr5+Yff4EnR320zxqBFK2wS6+aH0URDYu3TeCCfKwTr3yaMbg4BtLWNeC
-iZGWEL22BtPL85AHX458BdEY2+oIKu+n4mSUED6ldJCChoLgkypa9JLhByhSWM/m
-fHxq55roXiuJ9RTp+pryJZ4Z5vflPX4umBBkkW1ObfReyeTzPfnOEeUAQAcpn9f1
-BX3ufd/GIQlSwZgNHo3zizF0c+/2HwNq3G31PkKdMKrBTvmnBCPRhml+SlMq6V99
-P/nXasOrwN4h3R8Fjd/5WPqyBakwRsCH58MYxST3J9abd0QGvx/wZZlJ01GhFBLS
-2KZYFE1sH5K6zKtQQ39n4KkiPUb/iDrrjRpBZnaFRPLZbJUdzMrJrcViASg1jDOR
-Yo/BgMsvSenLhAD4ewc50NNAghcHIdfORfZUdP4f8AhfZePz8IOhcKLrVsSwzULH
-QahfLc4bv2nznBrDmPC8JwWTgS/m//vJSBGtyFgIp1CfTFQliQRbBBgBCgAmAhsu
-FiEEdI8Vss+bqPAkFV5u18krcPocgU0FAlqzWxkFCQ0ntO4CKcFdIAQZAQoABgUC
-Uy9AqwAKCRC0xwiTtiur6J/MD/9WbrQMLsh52HhzH57Qdaq6wPmW5dyGsZXMIw79
-Q2RUdkCf1if1u5F5lbwcKqvwwllEO5JsuGbJjUhg1la0sfVDqtoP/0wnbfecgUM5
-CpSSrozyyV37OwzAHlTL2ItBpZ+AtcFXKgh4wJnbQeNNxGHVx2kylN+LhLrnEGvc
-mLZb/MCmJqfBJYrRkIv4i0Lg9VpGnBayJk72nf8ifbH370NtfsOkLHAR05Wk5eIe
-YWhostJSZaR2izROPYDOrzmz7xqHpniDmHTu4sw8VZmvEvyMJ2x0PZlwb3OTX4jl
-UrG5h3MEeKh8dxkExtAK1dQ8PjA+7LJ4qs3QxWBi80uBnhjlga4uOFfTRvRKBAgO
-JA7JCsSolaZhWHQrFh3tmnoKPSPVfuy8Y5tymKys9HHOlAcQ3et9kbOCGe4eJThZ
-tmThA7DHImRMSjY8gq2hjRTNr3dMlSEW+P5q4SGiWE4zSrNZXdbz4FYwOkeEc3k4
-wzLv7iYNB53bo5c3b8lnfjeuoQAOmSbabxP477n7Lf7maYXsL0gQ5mCCzb+37byN
-bdJm1DvQpWwpi4snMs+UVghZ4Hqt41IC9ulog2PGbRkrDlfk3ULOZO4oeRPN0KSR
-4KCJJIV4T6jvIk26tMwRGVQJZtr8cFptdoq0HwVmy16V9xxJ5G7kN/MRI93bmLfh
-gMBLqAkQ18krcPocgU1pxQ//ZyvA37f1vdnn5xkLmbvQigGdIK8fniLeV4PzfImA
-wQ+jnKeavODSThkeN7EZB79pOlQsygS3oH5gHCT5gkr327FMLcHkfU9z+E+EAcZU
-cklbSksOWbYjj4Vw4Am8YmYUT1FwibUm6Ry0yB3n6+vozEHMM9POIMcWFCcGMbHy
-5O0alIQPMbA7XF1ivX/kr6mNYUOe/eC+j+hQS/BIOpvnC2jwP3I5eh/dGJ6fnKf4
-DUW+Kf4+yAHLCXE1I4+PHJCV7rvR3XGG2QYi2V8V9Y2NO40TV3XyfJyR+Spdg6kS
-tGdT5xFdCgIJQSPYL607LMaZjqx6Mk92dgR6iJY7A6z+R1uBtKuzWZJkfQ0w7a/I
-ZQ5myAJiVjJYO3g1ILYSRbPD8p3kEqYhMUId5vzVtvXEzFkJWT4l6CBYWLX37icF
-jL4BKIm0MXzJrqueLZF6MuNf4skBegtd0Ge5vWpX3mCOtmRiXrUiGy3yH8kDabNI
-1pkoHMbkLJSK7/c+TM29344e9ngZI0PYwNCyfveS5nAh2bGWtqVkEnfG4MFlMWIl
-ObwRCTrHrv4M+HdZ2u/84HppVJp/1eDuC4IPSb72sUJfSl5qZ856wRDSMKrl+CZR
-D78NdHarmGgqZeHj17qHB3Uwd1X1iBX7vAelJ+U+IW9V4nMFf8+mURwQ59VczGmG
-zpGJBEQEGAEKAA8FAlMvQKsCGy4FCQeGH4ACKQkQ18krcPocgU3BXSAEGQEKAAYF
-AlMvQKsACgkQtMcIk7Yrq+ifzA//Vm60DC7Iedh4cx+e0HWqusD5luXchrGVzCMO
-/UNkVHZAn9Yn9buReZW8HCqr8MJZRDuSbLhmyY1IYNZWtLH1Q6raD/9MJ233nIFD
-OQqUkq6M8sld+zsMwB5Uy9iLQaWfgLXBVyoIeMCZ20HjTcRh1cdpMpTfi4S65xBr
-3Ji2W/zApianwSWK0ZCL+ItC4PVaRpwWsiZO9p3/In2x9+9DbX7DpCxwEdOVpOXi
-HmFoaLLSUmWkdos0Tj2Azq85s+8ah6Z4g5h07uLMPFWZrxL8jCdsdD2ZcG9zk1+I
-5VKxuYdzBHiofHcZBMbQCtXUPD4wPuyyeKrN0MVgYvNLgZ4Y5YGuLjhX00b0SgQI
-DiQOyQrEqJWmYVh0KxYd7Zp6Cj0j1X7svGObcpisrPRxzpQHEN3rfZGzghnuHiU4
-WbZk4QOwxyJkTEo2PIKtoY0Uza93TJUhFvj+auEholhOM0qzWV3W8+BWMDpHhHN5
-OMMy7+4mDQed26OXN2/JZ343rqEADpkm2m8T+O+5+y3+5mmF7C9IEOZggs2/t+28
-jW3SZtQ70KVsKYuLJzLPlFYIWeB6reNSAvbpaINjxm0ZKw5X5N1CzmTuKHkTzdCk
-keCgiSSFeE+o7yJNurTMERlUCWba/HBabXaKtB8FZstelfccSeRu5DfzESPd25i3
-4YDAS6i50hAAoh3GjqrSyYpCH7P2/bL57FYYkgEwgk/RxxzXyvr6M8uFa0glXIOM
-OU07CznF24g6PatBvJhb77IVTfODVwWKa8Jvb1vWeXHdrKdUzbHc5ch1IlTjTiiD
-DOB+zbX+hT6OHCVgVVpptV2WQxUrem/nRg+Y9lD1qt7Fus6zq26ie4WaK70cVuFe
-OJ6KzD9tOMLeKq9HcHhpiYeTqW8qxmhvpArI8DwoLdx9XxMyLWGNpXNueBpy6prV
-xXLp/RjF8ZDtPhMH7zT0ev+I/MzeJXQ0PT2mpYmiL4AWb1gjo9e3JXYtaLc2XoiF
-gS0iZKRrRA8uvVcDVTK8r/BsOca0XX8QwIXJnyhhDauNxMzS2oaIi9XnxLSXrNLW
-CWq4KGrKujNGAlYpk3KFSiclvzhVbqpi63Dc0kxNdXQo9EIrGRPG8RI/A0gc8jpm
-eGF3LfnqCQcz7Bi13IhUyHEYqxODQLj0kuY40OAgY9rOwaRE42vwZyVt9vEsyOZz
-l555gHHyLozgXr/FAZhtXGNjVpeOPmi8isDo0/V8ImiMJvLob9Y1vgegFlU9HGQJ
-oO7YrodAHYa6vMfKghphbU9hKbdiSRvWmhsPJRWDXIjVrsjGMI9PYje4h1KHzfSW
-XGfM5rCFVX83cckNyPjWgGBYCH9saqelPdXlXc9kBGZI5oa52uG4DzE=
-=K7VW
------END PGP PUBLIC KEY BLOCK-----
-
-pub    44CE7BF2825EA2CD
-sub    E01173141D06B1BF
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBEzQQMUBCACbwbw7tuTWgwPsDAdQTWGO355jP75oBLHwGgEwV+OCKtxkNXNw
-wrJqXst83vmD1dEJyHflQww+d+Olj90IefQGfR+K7O005C2nky7eNGIomxaP52Y/
-90+tmw8qtsI4nsPWPuVj4WdFvlFgUwIZ0SmX4CauVzg0Ris8f0taxg7PH9zEvICs
-G/WAXdB9em08WDD6ruhMAvDF4W8Yy7mpGmdWiFD+B9OC006tv+GzYAvUHRFeCnnT
-SoKRiBeLejW+t4kpdMnEfC9ILAYBEEjNYvBIyPdPKBwNfy0yjRebsUf0eNmjGTpk
-VPlfofjVaUaOZytUOQvntYpocMX+377DGQIdABEBAAG5AQ0ETNBAxQEIANp35mwg
-ILWWQI36F2SyWFTFF8zupjzqlcF4Vx1Mjs2rQYErv1qs09TJfO+uxPRAva0fKik9
-PFmZ0vLM7UAveZgaknzjTQveOaAJuT5OjudoyptG81ilHO66+e9RnuyV6gSINnt6
-wnq4n8KRPoEmI/nxMhvmBCPw+YmxG3ZcU5Zko4GtjLA4J01nag7jY+LH08qFfPcK
-sADmx7EtCRuBcXgQ202kF3o7BjULcLV3R8vni3jp5nljH0vJG5USSY2ZR1bFiLtT
-CMO8cm+jIuay25iWil5DaejASIXzbzTtSYg9Skxet29AWjlrt1+zKZsMSLPbKJ6q
-hdW5XNU4Qo9ycx0AEQEAAYkBHwQYAQIACQUCTNBAxQIbDAAKCRBEznvygl6izZwg
-B/4gOqGHc0Cc165PZggwbf1nyJZ+af0QiKWasgoUzo4a7OSIISmBYPGnW/VP4EMs
-aNEhnqWK3Tu+cuidW6z7MWHRsqLcvYUKeiZE2IhnMP85ad2S14UOHE8cbkLwfIGe
-+rIu+zYpzyc5bcRYqeLvd5Dk1H/eW0/hsadW9qpSWQRGxWPEsMqaAhiret0ntlGH
-2igswZ7SYNYLNtK78wppFqqFHfFvnVu1XNmiTDDuk2IokPIGRjeWO59eSR/kotg0
-zox4S+CJbRdQdPq2ofDNqKCIEtg6y4yM+dc7c7n1Txk53fMBMzXfGnLGfbTFLo1h
-pYdC5sepAZA1XWLRgZ3+5+vD
-=HSWu
------END PGP PUBLIC KEY BLOCK-----
-
-pub    14A84C976D265B25
-uid    Rafi Kamal <rafikamal93@gmail.com>
-
-sub    0190A8A50D88C2C9
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-sPa3uBnylgYyUnzuNZB3kLz3zAM04/jc8Vk=
-=/GAm
------END PGP PUBLIC KEY BLOCK-----
-
-pub    D57506CD188FD842
-sub    63F72A7A8658D653
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFj2NXwBCADPJcGfWz4Zsfa/UEUF6a4aAIjqCy+rNmLf9Vs3HD6B5p1r7VkC
-e0HhxrfbkDkQu6aEmAwV6GwYiwWBf/LQYNdKm1FYZFhKLhyuTPiirFqIouEFqiK2
-HPFdil0d6Bi6HB27qe3NScpqMK21ectpQfTGlmd0HrSN55pSnb9k+Dnx5MdR+XNl
-pfA4f5jNBIrnsCvaY5jccyFfvGpzykVF0yaSikbcs9hJ3pbfddLuBJ4Tk+yePDjR
-FWJ2Rtau0Pbaz4CebAIQprLfdOuxKQ8l7jhMZpRE7+sz1mU6fvDnPyj5kvnoU4SB
-tVvsnSuILeewp99/MG/wE+B5uqxG6KNpxRgvABEBAAG5AQ0EWPY1fAEIANhZYkCh
-aM7zRmJZhzbwoHNfuKfSVYfNjCpRdu5PkutVxBsjqGWs47SjXEjhiTjAD/s3cgj8
-x/uHKmXXJoHUhnU+9RPlRiEwt6xdaEgRqMJyqrqIJ/PqmerMZsZsnAC4dFFDbR19
-lfDBNa5RjF7f2s+rHtaAPSMbn7lfeBpP7V/r4qUg9E2pRqoCCMqCtFRFlNgLwv7A
-jgMhaTaO1Am2sxfsTOVyoxCxC6kpJE8r4iRVstdfKifZrfStE7ZmtKmRjqLmblla
-GkQXWAlcayc6SLJa6bj61Ln043+qum9l5H5xUBHwfv1p/UPzNpZVGgZ/SVfV9rxL
-/DktPZ5S+HPSyBUAEQEAAYkBJQQYAQIADwUCWPY1fAIbDAUJAJ40AAAKCRDVdQbN
-GI/YQsl1CADJMZdQGxuAOmK16/0k8q7sNSbGtrdyD9n3yLsWg9cCTI9ecJdM1cXT
-RglhAfsm5sr+xJnyA6ShTn8KCxgRHPqLTIwSfmFNjePKmWUK1iBRdbNdbfHiKUKb
-Xc2CMwkwHj6hWo7rwh7WWS3gtKzldUirfIJoA13AXrtJQRq0qgV9qN5sEpVGr+fe
-5whzG9BallTirYztskrI82p3e4thRPr5XDK9r8SWJKPuhL9zEfStSMVnR0gO4n6w
-pFryXcDaWuA6/+hIzS+RwTQKpQYNbb/OKrkAUH6jDLzKtixWNwxuDJpVz5YHDJVI
-LCwzEShVwuejAYnuG+xpgw1jIxtoj/bGiQElBBgBAgAPAhsMBQJZnMEmBQkBRL+o
-AAoJENV1Bs0Yj9hCzpQIAMMZ7J4QXPur6jDgjpbWESvLbSSYGEt6uIMB8SEHBEJ1
-DdMNdRKu6AvUn7doVOhVDbzof6jGpycRFG4goL1fJM7pLljcOwJ+75FrYZCdC0sy
-JPd+QkpueUHyE+/lZpvWuu0vlgfDkfIFFhC96/h659oTt5j82l5YIXanpgQg/AiK
-l9joXXxvVt073y+ngFHpYhCkrdna6rxN4WRbVN2OlUJx8BP4tfFagYKaMSlPkA40
-03nUlwsPKQ8Bj4tASVSpCihlR5ijmxR3YxNlMET2f1ljvj8Uu3N0LrR9wVr2g7t7
-nqTzRs0OjV+r+qy7eoZ4NBugYFXpP/RMAXZJezpKfKU=
-=FXUZ
------END PGP PUBLIC KEY BLOCK-----
-
-pub    85911F425EC61B51
-uid    Marc Philipp <mail@marcphilipp.de>
-uid    Marc Philipp <marc@junit.org>
-uid    Marc Philipp <mphilipp82@gmail.com>
-uid    Open Source Development <mail@marcphilipp.de>
-
-sub    8B2A34A7D4A9B8B3
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-bpJ8mdzS2PJko7mm
-=NMA1
------END PGP PUBLIC KEY BLOCK-----
-
-pub    991EFB94DB91127D
-uid    Antoine Mottier <antoine.mottier@ow2.org>
-
-sub    C327DD2B96A50E1C
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-zXFYXic=
-=osYp
------END PGP PUBLIC KEY BLOCK-----
-
-pub    A41F13C999945293
-uid    Thomas Neidhart <thomas.neidhart@gmail.com>
-uid    Thomas Neidhart (CODE SIGNING KEY) <tn@apache.org>
-
-sub    8183E80D264EE073
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-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
-25lhPkZ/FaSYF1lb13TNIRT1q1My
-=pAbP
------END PGP PUBLIC KEY BLOCK-----
-
-pub    22E44AC0622B91C3
-uid    Cedric Beust <cedric@beust.com>
-
-sub    BFE9E301CD277BAF
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mQENBFpqN94BCACaAb8Afmng1QPu5k5uzLoA1FJnF6Wf31ZU1FzDxHFHLNUYSWN2
-Bg6k95QH5ruZ+Z/QOJSoIB+b3htDklyxd8m+G2KsMIqnQs0BaTN18hb3PFyMIknM
-YWkkTPF3nVV9APk73AebTAcd2V1GB7xOP+L3T7tyUcB9/7bDeM3od6qPksdVGNMA
-0S32U8SNhe4jw8uXKdFL6PSxgyg9yeu0V7DyR92V9jF+ZicZWxaLeKpf/Vn3MBX8
-JdePR9SCJc8CNj0n/tsvg/aSmGZ3OMZTUYYvrtfgpXUw0WVkyma+T0ANcdDN91uZ
-P8lV3o+Ic8f15xwsTePDhMhmtOapIz/85ukFABEBAAG0H0NlZHJpYyBCZXVzdCA8
-Y2VkcmljQGJldXN0LmNvbT6JAU4EEwEIADgWIQTHC4RPAC8h9tK5yHUi5ErAYiuR
-wwUCWmo33gIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAAKCRAi5ErAYiuRw5Md
-B/9ajI8dvk0oUaenxcPCchWQ6pwA2B5w9yQVWQBoJbxMI+pvEqpS6ur7PI+bJ0or
-rCyNLiNj/okFuU6yeh9g8eeKIR3984HtBAkGo59TtH9kTg3HDZF2ys5j+tdtcb3r
-KrGafc41llryb4XTGiLjcCS4n6q1EmZIJjCwvt1sIO1fo3cBim/1kjhjMgXSpiYz
-yB+ve1NaG+f//nfallAnryxFHVfk2/N373cNZTD9bV2FRZs9SSO2mO9BoyG8deSF
-x89lwLxK7MeoSH6pAioMMRGoZhNz2Thb9voUjrqS3P3+auwPt//JbhmCR3Zg+upu
-n6Aw5q67aj4V959Qra3ZpD/TuQENBFpqN94BCADAfXydE1VYais6o/4JpVQwk9JL
-3r2hkgwfN68B2rRvw9ofXZoqaBCFgbw+Nvz15GLmONoiDvP4rb1TsaT2Ti/hTUb3
-ov2W1RJ6OFRmiSkOuOjZHlVslYF2fPlZEXWdJ9PWvoKM/3taaICXy/AVSm1NBera
-1l2MsJ1ePr6dpMMDBjUU15rzWm3WOqwBNE34whhOjvU9vDl8u4h1xV96E5B47ZbV
-B1pR6y3vSYQgwj6BYkp3Uz2Mg3GQ/nBFoNuwV/F7LiUb5W68wOe8Q98NuREh1ico
-/OM+iudjP2LO0vz2sGe6X5UZGwCfbJnlq/fqoPhiyW6HPb1+JHU08kKeY5BJABEB
-AAGJATYEGAEIACAWIQTHC4RPAC8h9tK5yHUi5ErAYiuRwwUCWmo33gIbDAAKCRAi
-5ErAYiuRw+XKB/0ToXO2daY6/ZlkfK69O8jRBzbhn90/2dePM/qLy5Fe3UaG2sge
-uFYbTMGbRPvCpn9E5bceczdhkJKqEj5dPHVhUU6+jeyH/DdDgrcP12SQR2vHg9hR
-e0pzVouiMDX4QnUbW09CwpmhymlIp3pXb5jNa4iNxjYIBmuHDEmMP+uW5Ue+e2lg
-IAFWRFovZ9C1DCg0YYyGktc47cakq3ENKNU2LFvRcbgoyfjM0EprSUColUUNN3yy
-UNc+I+bvGL5swhKqdnRHagbg7kelsn/05oDFGPQHi0/VOlWU7wBh+vUw6lb3Zi7C
-obUInUhW3rPu5LubTOtT+oIH7+RSUIEJO1hE
-=j2aw
------END PGP PUBLIC KEY BLOCK-----
-
-pub    55C7E5E701832382
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: BCPG v1.68
-
-mI0EVdDLQQEEAJMtYCaTA56YsP5RzQzPvqVTaR2nZ27qRk36blHB9WmXK+NHpGeH
-PHgq59mLPVueo2/M5k/fFrCe36jHePP31gYpFtueeYDfsofHwod0WhsHyC7JfG8d
-jEnSczTCmOHRZ3ed9ef6SeWUozYCQAX/tAbpoCthe0lTDYhFhkzVCe/FABEBAAE=
-=45ZY
+mQGNBGGNmd8BDADSpbdIfqzkUNAeYlP0nUw/HFU/v+/aydtjUioAi/KxYt2FOMi6
+gk1LOJzHBubv8bF79mlN6sXrnq2lV/MuqvN9DrTAQ4u4Dh0pgbLK6jbxDWPGrYIo
+ov24dU+1SXCInq/7X71M3RT3/1L1kTL5WNCqKkhxLNi0bwjyAHR+xOdhPqkeTrZK
+xZB4KvIzI3cIYoSw2tFn/iAlzzaUyQY+JkqBbcObbzyMt8ai7TdXKHM5mAiuMt8k
+MkfE/kZqTWHimPYrl1+c3kXqn5iTFfJIRklXqnXixz9qFYhvUqWS87fFRUJdPCz9
+Iw4/UrnJi4qzEN8vrEJpnDgfS5Ey+io9xcqd9P66dFbVHvMl4uTo4hLZVz8dkWSt
+CkCtAfntHAp4Zf+1vIZzbAgseO52D1mP7wO0QccgqdX0w5Jboc2kkM67VsWskRXL
+FO+c25gXdtZk26d0P3f1j3XuDm3pPWbgAk17HMyMpqla3xBQiLA7J2l41YwblV21
+uzJnqAoChPJhP6cAEQEAAbkBjQRhjZnfAQwA1bQfDtbglXMOgziqSdWAQ5jsNWuI
+cTAKcJ6Bg1d3a/B6sm2IvCJzae007hnGf66RgkiDBKpqsMjb5yXyGVL9lq+KHgPw
+3H8TMRiVKxXqr+Q2s9Y00PR5PgqccZLZuUrbBJwK73u3+vfhG4ugubQPnRd8sPwT
+X/OPXuuq25FuZb5T40Yh+ZjNstnBOEpWZ6bq8h2kMWm67zrYwKdBOoHRU6Nnu2fO
+8CuL42lQmkvpTIu4ttjbLyYZMYjHnO+OpK014H9B3DsRvgAQT7Qn5pgyxwF+AuiC
+qdRP+vFzO78gvDRpUEQp03ZsBK3LJVXqQY8Nk9zCPDz0T0/1zL5ZHFXdzpxVPxMI
+9cpugE0Qr45qh5hktz+cjE6/DYbGu8W/bqDRzXjxz9FUA5A/sv/hs+PZ0QVRFARR
+cooe/arzitxxEc1X59IBCQieH9xVzC6gEeI6jPgiWo+gEBItQt/1Uf4CXOgStTbp
+zM/GCJdB4VSQXehMNKI0zBCsEtBWgDPgAlwVABEBAAGJAbwEGAEKACYWIQSVEVGX
+xSJ8CIcpnQAPn+YviOk42AUCYY2Z3wIbDAUJA8JnAAAKCRAPn+YviOk42NADDACt
+BHrDFjhuffic4gBoMkgSHmG2xfWrSo/jo568hJdUvwUKlLix9o3iqmPGy0jLkaGZ
+4w/t3eFrTGdNPuJd6zQ1fDNm7alCnyUYzoxct4yOu7mmI107HPuxANGvmV9hfyH+
+UYJtNwM6XljTIhnKdYa6H5j9jlwMR7pw8Y9QACVozBMsaPQygjQhli4FhXA203g3
+lxidoGZUi/xrV4vO3Wlo+7VC8n9WJZrYq4jhlD6Ntdhbvf8bEb4L0cn0ybgREehE
+7THETI9Os8WQVGbU9sS1b4YdOXZEOS4WS8NQKRzLemo2YiUNIdI6QaRWCvJyZCfE
+eWWoEJoPMKZldSIhU5UMtTaM7f2n18sCn9rXBscSzeO6MlcyaUQnMI9Kai4C6+t+
+TrIhZrSJQQMrR9lF+zP/YJKvW2wJBw8jhJr04dgXt4G7VrmhS4/HbtmLjQsl6bb7
+y8VfvPmrEviA+o1KeRSeIsx+lPdI+IogX6iLvlBMPtILw/k1aqanI+aTZYFOORw=
+=NL3+
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    10066A9707090CF9
@@ -14307,600 +4532,1693 @@
 =HrWq
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    8D7F1BEC1E2ECAE7
-uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
-uid    Tatu Saloranta <tatu.saloranta@iki.fi>
-
-sub    E98008460EB9BB34
+pub    102E05D8DA6C286D
+sub    7680B2343D1CF013
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-Jqg9YirnHcrlYF0r
-=gukc
+mQENBFOZyw0BCADj6eDnIjaug0RJQCi/HLw5jJ2kORPaegxFuE5IhpN9pZCPASax
+aTROfUSnys7cbxZxh3Sri3spQ0j+ejod0MhVX9ajTg508YAJUaCBbM7CGZJZtVFL
+atf99umsxzDrXIk24z04W5KBiLS3M7QKPyMujjiVy9naFxyW8GXJxYcGKUEltWwP
+zgO97xwHs+T5nXcO6jOrJ7NxI9fbnWb6QY6btSkrlpLnwH5yxGpajcR6R8+kj+0W
+dqWWrs9vo0DQGohkoqjTzeVt8UWHqUBva6hULkz6H9CRLfVxuK3lLFtnRBjnjRbu
+bNyOdVdtaXArmMKwsonsaZ0E973yqcmbhKQ3ABEBAAG5AQ0EU5nLDQEIAK6UjEUy
+lBC987DwdhJ8sQKGcOq8JM7sfLgpBfuRL+kWM+jpXi+DmfThnO2tI5UaaF/jMd8w
+Kd4JeAGE0Ynj5V1n5qUsTUXwEonDLLBOBYEj2NYJ40kmVrPdp00auDf11Y8NC4vS
+m+4QV+FDcWvV62ogOC5rYKOaKMPf20F9rCxUBwvrXNHPQJZeX3FqU/HBhvaqtHjA
+flZoQF01baDMQTZf5JgATzXJRsKKum7z0DWiYNoOJ8wpbuXM6CG50N+4OrlSZfxx
+kN8I9sSyREzHj5zVWoKqeyii9HUeqBLWh++TiYrRyP9NHM1SXhrtp3wZ36CBXqp6
+ME2K1DQTMlqZTwEAEQEAAYkBJQQYAQIADwUCU5nLDQIbDAUJAeEzgAAKCRAQLgXY
+2mwobdDhCACjfIYnUCHd6KzmgOoYXsW8NeVE3QFpMxMVq9rNEJxAiOg3b+Bdz48L
+2lQy6yJJ7owKAH2M6FvVXpfrdkiMQICEzKr1IT48H1Sa0jj0cSR0jRYszmd8k3G0
+hBqmGnfPBfolrOVDaRGf2CXCZFHVZA/Qvof76FaZ1cFAKYmUraXJBocxupXz6QMq
+P4qsPgkscwEVv4b9u+Q+YLpqHBiWmsHk9mp1Jtqz1SBTqI4zVj7w6qmc0aZh9I2T
+ROvKAtF7WjBg9LEFstqZeP42rKenm9vOGs0aQbe4kkgFMIwkLI1TeXrYeQWSdjlN
+nCYHwzPH+lq2dsCro1T8dMZTRFWKeaPn
+=w1VQ
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    E0CB7823CFD00FBF
-uid    Jake Wharton <jakew@google.com>
+pub    10AE8966A146E8BE
+uid    Thai Duong <thaidn@google.com>
 
-sub    F3DBCE882C3A01AA
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFsNoY0BCADIvRrJEX3k7UeuT6zt+F4++xH+5Qo7QzdicjFhhyb22PLPyIsI
-Ema+T4QqiPDegUv8yKKTTBmHNw/vSUHTPX9ZUpglckopuOgdfnuQjTKEOEzrN7V/
-ZGLB8yR+BoKEJBLdp6W4fGHIxza/o8Iwg8nV0/C9X1gvQI0I63aexqqA5Y0eYt4y
-12mQur5sKabJRRWxkn1U8oQmcFs+P/KPVtS4lUb1nsGzFJbsiKY8AOI1RbnYgtIu
-c6mzpiUk0NPO27xKScyDq7lKBwwOZMwRzX/6yX7jcAtyTWZnWS675MCbT2K07ubU
-Ykrs9NObwDXlKZWLk6JuADgzQaueYIrjLRYxABEBAAG0H0pha2UgV2hhcnRvbiA8
-amFrZXdAZ29vZ2xlLmNvbT6JAVQEEwEIAD4WIQRHv1kiYc0aimm3A7Tgy3gjz9AP
-vwUCWw2hjQIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRDgy3gj
-z9APv/tcB/sFtJIfaqlhEMDI2o95mhd/IOpCkN+aECpiciquE2RkRPj+lUY9qYZG
-0mbcQkeXWQjkuD30DuiwHSsSqDzya+lFVHmuXfL8uxbDWJ5YYNnq/Xs/7NA5BwtF
-PVItqJVUGNSVzA/HmKtCF8ztc/o374v2UsNSxoPe0k2XirZ9XPaRchBKlYulLYAi
-mwsOI5O2+CvWojRXl/p9/NKtHYCDyVtaU4ujwJbrs2MEn0X5vPfkzphXA010T6If
-l1MwLjH+WGYiR3Sxs3dWuP6m4acACT3itSZ3sgoUYZ17aKaO99zzHKEPx8ov5/OX
-pAX71SdwRYph8/EVgsnk/E8zOW+DeXgJuQENBFsNoY0BCADL7NCKWHi1931saO7k
-RdrOE947qnMqHLaPe0J8mVLIsYE0PntBE5cBRz3VAUi7cJG6oXWKaDfEclKPb5Bo
-y2SZA9M50gUusXmv1jSY9fLgT9kID1zbTNVKYvKREXmeUQatG6GM/o23d3GxuUww
-BGEKJUpgoGdk7roCLnDGD/TbpqCg3YnRMLpxo8ou0qZOxbIHaxfQWqXWomK0kKgL
-F8KR/ptW/5uNSLVheNn1v5qTpPF2hHcxgPMS0gE6UPPQFp2Ivd30q+xE6HVH35+d
-Z9+n89ejOVvQjNbRzHR2uYJnS70YfgcdTFPfOcMU4g1H8AzfupNX21/rfOFCx+mr
-CzbRABEBAAGJATwEGAEIACYWIQRHv1kiYc0aimm3A7Tgy3gjz9APvwUCWw2hjQIb
-DAUJA8JnAAAKCRDgy3gjz9APv0lMB/9DrHctoZd4iCOzicjv/8t3i9ZM5o+z8lo+
-LDCXSt++VG7OcbFHLf3uPalP0P6M9M4oPpR2mEp3yxTMeKqX7VulTGf4hpf5npF6
-AnTq1MWf9PrK6XyTKSAycqM3We592xbZatp6NU25v5MlK8LtzPEP2ti5IfI8MoCw
-Rqpbs9D3zbABAgBpcaahsEtb1o64R7TyH0W91A9x6PvjhZs+cyijm47NMewJXGCK
-+znvg2tjL0zIGVICjBqrCYb3R7DKmUSlemlW0nT7NzyYLfFLQ9sGgOJS0QOcZS3Y
-E3TeXafk5ruGsCO5A33as9VebOaayxpZKD4QAlMUWXs509ybOzVR
-=bCXo
+mQGNBFrY3D4BDADSiDX16IC+236IeUiqi7Nbt2wlsBS0zqqaXi43QwXwcf7aYn4+
+qrn+4JvsyMrDgkRgOElz134B1i5OSzP/32w2JCnj90XUjO5N1KD0QqoSops7NLhZ
+/jW+5cFLDDeYPTYNLxJVsDRSqhIztRC0/m3eP0590MbnPxd+ahlj8uz4NRv/bwj1
+vqfIRDyoQOtV0+QX4M8ytX8cyLW9YynWLWMeHUFY344UztDunZrfomPC16roKXrq
+niP71cILlVFvhGhLfE4iF+Q/QZZnn6hvuQGagHR261N4LKw5II737g/5f1DsKZpu
+Mjam5juYCWobRie4fN4k0xwi2+I0KTpYMjBRTNNcOtyAb1AvY08E0HVwAYz8Cm+T
+VQQKriNpa40RI3KtDXCboCkz+LLL1w6vBXnvCes6F8CjSn3IlInpv2AE4nhcPC03
+zI56gPFHhUN+h4vm+b5H0aw8DyyedBDv/GX5sPxYYml3H12L/idpgAwp022rL8dP
+lxtvZrtO9PlOqHMAEQEAAbQeVGhhaSBEdW9uZyA8dGhhaWRuQGdvb2dsZS5jb20+
+=PSwe
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    EB380DC13C39F675
-uid    Mark Vedder <mark.vedder.key@my-accounts.info>
+pub    11509ED50EC155E6
+uid    Konrad 'ktoso' Malawski <konrad@malaw.ski>
 
-sub    BB09D73166EEF1AD
+sub    DEDF3A7EB400D53A
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQINBFEqVnEBEADZhnnAV62dwYvq5CxvEO9N7m7vrYMosc8PCEafxJqrDMbWWfv2
-tD3EaHAERt/UFVEo2U5FV1hELUvFISPhh/DpOWYuc7pwA75do7ul6dhwgi5FcyjR
-xmoU4ysr1YsHM1TdSdDdGFslLA0DDXmBP/B1wQIRdccVWr61xMb6HG6AHLvRD0mi
-POgJd+R72fv1vZeEBMnhbtqjuWd4o3bHrItZfccw49tQCgZQx7TMzIWNj02ozCId
-VCR+DBhaeUCm53i2V55+VxkC/vGzVQuidcam5oZJdZi5o5aCDxBaimK0/zRe/xWL
-qYN5YtSYMxaw+Kf3lg1Qu8FT9BwYlrxnsQiNvWF7kQ6wUrA3rRCOx8Nc+jnkoXfp
-YoqT8olxM4bM25i/MpkGI3h9BJAlfNLIwcU7LTmrO3n+5miNyYknDED1ax43gv6/
-8EhU/SFndT0BAUtQf7iCcEkW+K7w6NXaHGKPhlgO3ZIXf34EgZJ5ljABcH2S99p/
-HACzEmYlVLltof18+2UYAXYOc/R4je5rbqkHRWjvA4igebUOKZgsaHYPGCJJEKBs
-lZ9zV6hPxRg1K0a8mHa/KRcvqTVXB50hUx+QCp4IdEF4BuAq/WK69Nond3qT7300
-bIZo0s/FejBkUc5Oz0rgQB90YxRhB42l8uM0GXiPROrXjvXaqbbmjVhhoQARAQAB
-tC5NYXJrIFZlZGRlciA8bWFyay52ZWRkZXIua2V5QG15LWFjY291bnRzLmluZm8+
-iQI+BBMBAgAoAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAUCVkZHwAUJDoHy
-zwAKCRDrOA3BPDn2dXMVEADKmpXd80qTfL6jr1RmfeyUEB1VyUlcsQKXbbWgzsz7
-YCMa02qR9oqBQuONL3EIU1qCzT/qq0HCS3BHAbGDz0MN1m3h/LOqIQwNuN25Tt9G
-Fwpukm5zy3gok1rM6P01VwNLvNw7SP33ujU4xphSwJ4dGT781AbsEEgIL8KTplhN
-C+m+VUNzpaIFXSiguivRfkJG7XW94AE0JWJOJ3kjVni+HRkHy4FsDUnpeiPGoqJ4
-9JlxctNO/TUrG/e5K7I6VSC2PI5RjlZ7XgMM8bIFNYQIpWHb1PFUsmankX77nfo5
-65wfur233n+A7u8XYk/21VUR9xOSTtw6ZWFz/YpMVNq1iVLmr+hP0Fg6ktIF9rKn
-zG2fGkMCjMQ9+OJ44iJLudrhY3azseJZDD/D09WJ5tTqhRRm7j5VKXqgT1CbdGxy
-akEx/4LOcIsrvFuLxBQ/bcIgZyq2+acIE3xb86mcEuxp0RQObp0UAS3qZfQ9eub2
-QAPKS61HCHLZmj97vL0bRZgpKPxSfZ7L2hyPcO2PlkZ4APKGiZcoXgJ+woNRtFI3
-3K/CBXONKAAJ64rVvPfVzkKx1fPANS9IyQzD3/mTjZD8nC4PfhRl6LkgIxrDSxz9
-DrrTMxB+eDUTGsDVb+2U6n5MoOXH1hAvfxKrvESYLazQ8hq1RQJDFiMWpnqhmtzm
-1IkCPgQTAQIAKAUCUSpWcQIbAwUJAeEzgAYLCQgHAwIGFQgCCQoLBBYCAwECHgEC
-F4AACgkQ6zgNwTw59nVXKhAAzpVAY2PXoG/VfWCKBckHZ5UoBjAIuczGc7+Q1vVs
-lmCwAL+os1a/RYSG3ldd5hemP4LtVdDd+FINH9sC81lDPMpF1j4n452+/Csqzz+F
-9vOmWZNeJtZKgOS2JYpsis6cQhfF+/+aVq9ZlWspK2fck6lm74CGosMz+Al1nmBN
-5yAjeIpEK6CDBFkAJkB3Q9SBqXfcHVyVXSMP54lgsGxFkK/Ig6I70VMWkiI5+LcW
-GiKc5O8i5URLqVox7poCxvCwq2a+yXDwFiWEtTNqzB/4bnXewZ0KlckwpypmL9l/
-lUMWxYMeilTPvXBWcbQ1BCynINSczTOPTxdJoM+Afr7pR5B5eGtSGhCSLL/T7ryy
-gx6guOE6MowC6/egetNPOhtVh4e1b3HgAELbs8lZqnp94ddoa5v/Peuy18wkKWSK
-YOfwQUfoOQ7bKgFMqqLUEa/5WdmRyMU32pXHhgLIyCLXrC8rK6DgPKyfMfxEX/gG
-pykZNPM5tRR+rLujXjamw93mQZRSa5dlfFMP1K8YQguO+RhqM18V9zA0yn3UdjSY
-Me1J12F/GWdbgf4p6Gl3vr8UZUQNK8fUlVkvUpKoCxodDoxWmD5vgVr2FarzAWOI
-gF+TpnCLvQYpWWN3MgB9UhZOnGsoPyOl9s9az/+COpIn/Yk3Hkl9lIoIB7xICikH
-bwy5Ag0EUSpWcQEQAMNCov7w5hQcCI5IFWyy4Egwtuy+Pbl8DryTZk+0JrBzy/YN
-M0qf6LKMIRnqlOn+XbSD0z+H2Nls+adScb92PGA2glqgS95TQtpug1td2CEMnfVM
-Q2ialTh9+X+gRPvTDxTgJbfkvOJ+6F411EAoEanI+ZmuwFYYTVf29WhnsuSt5I19
-TIdMh0Y3mqL5tFIUbJ1Xm0/e5/Vz/fF35CHBuZoQI5Yn6zGo8fE7Cr3LhUcWXjQo
-raGmJ48Zu6uqcM0bDticqc0Daazae7/N30u1s+I4bkx8UeVMPZd++Gl9MlljWYxE
-O/NmYOLJ8ujyOrOS+RG3hms6WNtHjDj4HqAj8pbvpUql5thVL83R8xH3mKC10w0w
-XQT9Yim1nhiQRKb0cGPGiMrWNv66fvGv2s+cgJkwVz4LEAnCm3W44fOQAzm5E4Cq
-vDjaXVYAV5lKVMTNgGn6fjR8npSjupRflz/smNrJCVnYQJNqSvc0C4EhZ11vzNKC
-GrQuSjpZkcsPFXUS3plmZzDX/RfboEm1yR35L9Pw2XcymNhlzKXddJivfPeRNwRl
-6DExSPfoR0jUAHoq0DdR19AW6EMiulUrA3LDE8hPezTCklr9DXNhQ54DSV4vUNRq
-2me1EpMfIDuhc+DH+NuxcEFKc8PGEZM+Eo2Gz/IZ6eS5z0LMS3HLimxtP2ppABEB
-AAGJAiUEGAECAA8CGwwFAlZGSCEFCQ6B8zAACgkQ6zgNwTw59nXcHQ//RLZJgQMj
-fofrmMMCBXj71J6ODuIg3mPsZ0TxUDT195PNAjbQ3vhqNCHviiGFU3ZJkafuUJ8l
-1k4UlzW3eexvhgMUz2jYz/wcbqdVTsuYw5bPrFso2BRItxC7ZqsJMb89Ds1TCEJK
-yC2mrW6jISN6iN+UGbSHf56KlxZZj90jgG2QsbTSFFv3sPZjT2xgVS6gFYMoLG5T
-WATBMWasVmPr5BRseiVG/srTbcbZMR9vHHYyDqdUsfX0AU0l0sEpJIXvSECdPOGw
-3JFRhBvgL9Ohq0z55rSWOXVRhnSqc8qCLgXwZfC07I3ES21qP5AkNDjY/2t4F2Gh
-Xhf2cJfJgOUmnGTIjvKWpanK/zzTrQQaz+CWIF39oLGHB0EKPqn1T9FUH6N8Im65
-BHEiH/ukrwj399mohAMuvExOPURQRfeQ9qJrB8gfb8F+KkI/rL48CN3dxi8fsmGt
-qUHCUZyO32exHG8+YPW2cKGNwQDFi75enp2kniNV+qmQUEgBEsd/0lSKQY8UtPi4
-rtWrGA9gZ4lCBhtmCvu4nIGDSkzR3dqoLQj3YwPgbSrOWUBFfT35T3i77JKQ67QS
-DhuGBhaIU2GstADOjQUO5NKI2QfcYBffOmN3I4nxsvI+/D0ndGtQ9bV3hKSING+h
-gvZkGCYRZmWZ7ZLF7MaRIZ4ZBTuUDLQrApmJAiUEGAECAA8FAlEqVnECGwwFCQHh
-M4AACgkQ6zgNwTw59nUW1w//RqheT8OCDXyE6rLRQfRlJnkTgWwQriazmny/lqAJ
-/bx9c4QCGOc6+mnm+o/0DhlTGsDGjcJQxvGBCtOF2iWfGuzdX8Z8Sh1NbatvZb4j
-kYwmTytp5W70ul7W/wZEAJM38Bm6pxZeoQO2oUMsURkih7G6GrPSAzpzoOc7fQD7
-toyyEgLrvRpmxbab69XXE5naQDClGyjcRDIIr1YxOoUGoMbn4MCSoaa3fEjoufFa
-ui5JcmaAmzMdc4aVHSe1jKi1jr80g6gsmlnd60O9g4Z/AGZy7p8A8XJmAUKTXBdB
-vfZo2JeVPwqBlRPWFmBDXvS8kpvyKhY9HYnFlFomBtRVoGoE0RK/6SYo2Sw4GS1U
-pgNT94wbfc97YS3lgcauXoHRNjzzPQBTjocRRZkJYPb11uk9NOsw2YbNakWpDc/P
-OMy0wOl+FJUFSLFq076YLpGrJrZnnBUfpAFdw7EqPH1+sPdUV8w6OUDrlNIrV4wJ
-IxSDMs8O731kHXKkxWjum5WspzGrpX/1LksObgzhrby9zLW/JHvF+lv5cLgsTZiP
-0WO3cdBid8K4Jte3Vrv6TojywHalDjVHiroBep/sy7rkf1rhw/nEMQFZ2J4ZfQLG
-IJsbF8K9pewgQip+D7nm/IN/jUzy3/3/CUCn3GswmuA5s6q0z3UKe9VhXrNW6Nrn
-V3Y=
-=gTWy
+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
+=cvtZ
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    0374CF2E8DD1BDFD
-uid    Sonatype, Inc. (Sonatype release key) <dev@sonatype.com>
+pub    1188B69F6D6259CA
+uid    Chris Banes <chris@banes.me>
 
-sub    F2E4DE8FA750E060
+sub    0888B86856F9D71A
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-pA==
-=OkOT
+mQENBF2hcBkBCAC2H5WcFoeByKBUAjRDjmP+5P6FRsZjLe6c1wy7G1ha6/EQUVK4
+gZUZYE9W7l/4QKHvAu4PvFWdD+5FXGZuB/2kw348CtabAlJTehm1QlPt5//ODkxB
+fWPPz3uHBo5PQJZuLpStQn+aEkTTHK6Sk5033e6fa7mV5X/c8pTmTzkunG58NFbj
+5VSVbks4pbafKoMY7rSN0/I2hEApCjB9tx/7DJuQ9gbaGhmabnhBTnwHXEV1/hIF
+369lfiqeoeqDMOKj99C6KFD/NPRrRLfoPRpqL3LPsPp7P+TzyZN2q89Xqn2ysyI9
+jDtrlssEXLskU5kA8fVa179V/QR6QtrJ29m/ABEBAAG0HENocmlzIEJhbmVzIDxj
+aHJpc0BiYW5lcy5tZT65AQ0EXaFwGQEIALaSv8Um4LBbyPM8PIfcSwl5sqBQal1n
+w7461u8gGAi3uikn62Q7IGO3SRRuJcR6hkY5Dyq1qPwEPmcBjK0Nlx1NTtk4TwDT
+ZsxexNV40qQ+BuZhCb0NmiQBRBY7o3GiFa8mqcNeTNnIxvqMYInIYcvHps3r77QN
+Y8PZznfDNpJkuD/vvoFnDjncdaQd+Kia2gqAFHQMw6DnV1oCyPx38CqK10rw3DPt
+yYo/sVo67mVLJZvoXx255DbKNATKSrhiuCIsK9r+lIvY9zXoI2cJFsNA1QSiDkt1
+yjW1us89+LMt5dVCanq0bfhprU4J3ZYqzUS1sVAekVY2jRw/ssidX+sAEQEAAYkB
+PAQYAQgAJhYhBGS5sJ8WSqC/iHQuthGItp9tYlnKBQJdoXAZAhsMBQkDwmcAAAoJ
+EBGItp9tYlnKg94H/2GsZGvWK8+dA4y0AmCtP4B6/WAUonGBMmUH1Ax8GaPKIQuC
+ePBbQI5v2dGBqUOTjTh/qcpwfTHSMSWFRTv2HZDP82gY/tAHJrKZ14+Pr1JB4Nvd
+PIj60dKFfyveC3t8TJ4kVjKvvDzGY7oHsZ1OmW1Nytsbe6Taj57UY8v67zpLRCEb
+ZHIEo4hYtehEIlCWi7M2qJmXtWK/wU3bw0C8KL4Kun968+0005iOdQ/Iig4oI4K/
+UW2HkfQM1AwuwJlsc8uXUvH4A3kkVHTGnvvi4aTMtDWPKpdNu/eufWwuMrS6Gxdu
+v7wjtN+wTGesv0OYCfxHScTi49XbBbU3PBq+pxQ=
+=Lz+t
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    B5A9E81B565E89E0
-sub    28FA4026A9B24A91
+pub    125A9EC9FAA91AE1
+sub    F2EA967B5B8FD0FC
+sub    F860F86A8AA8521B
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-3JnT33a2taNG0TUPdkSq3adt
-=QSEW
+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
+4D0hnpwfN9FlrGaJAjU=
+=a9iN
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    083891AD4774845A
-uid    Eclipse Project for JAXB <jaxb-dev@eclipse.org>
+pub    13D979595E6D01E1
+uid    Maarten Mulders <mthmulders@apache.org>
 
-sub    8118B3BCDB1A5000
+sub    8B794AD8CE1926C6
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-XCfM
-=930f
+mQENBF8LXXYBCACuy3HnrpWl7boi98G4wG1ZrhBiYImyfQd1M+dvH3GF3Vqt2NYv
+Nv8vryhUkMi8uu233KrYx2/kVK0RomMYWtUrSbQIdykytd0/VsoEk82ysN21ld9P
+PfnNF7L0egnw1KEhcPzghqOsEY3ahqgTYqoiHLD/isLifMUJkJuoLlGx4XfQdpcy
+RrSyjzf4/7XUYaYZ5OkhRHCZKGy75PNwibalNMm8H3+paqbwextv3PswVXOZWR6o
+uyeiPgoemoM0T2ZcZdKIxrUZiVae8HJltyEca9hjqQF7zzofiTXW3qS3J3bPsylO
+lPLr/NZ3vyUtuGc3V7nuUIVvpjy8nAzZOtGrABEBAAG0J01hYXJ0ZW4gTXVsZGVy
+cyA8bXRobXVsZGVyc0BhcGFjaGUub3JnPrkBDQRfC112AQgApyhKFxKtBxc6x6m0
+m4G8LGB16PK0ZtuUvRUmQ9+VffXojLQI53p4+lN+m7ocQSogOQ21EysQ01wQ9mFo
+Zymyv4E4YmChvBTPnSFZ5jkmphKIAbT5G0O5faK7Mlvmlnr2To8fwxTjyCg0eAtJ
+4NfNF6HKyli8fx54T8tOm9qSxXYri+AkQ428F1KUapplob9JOsSfnEiMuaeL0C9Q
+joCXy6bS5lstSWX6ZeXCIYtwVNFldjy7e/ParPL1czG1d5PwCzDVXU76sqvvipdY
+0kcmf+9sHsT0bHxC+vpmzC0e1C2KDANaI5RrUtumeL2AA01azwKtjpi2+xfsGUiJ
+B8NPMQARAQABiQE8BBgBCAAmAhsMFiEEgsnsDlLEepNqhJ4BE9l5WV5tAeEFAmB7
+OnoFCQrV3oQACgkQE9l5WV5tAeFGjwgAo/QkkB8s+mEHCbNP16ScQvbnDcDCjqRm
+KRb/YVqJHVLWSa0sOEHCayssialUIJ4X+FNtdPzONwfzqD1MtAazl1+Vti/LpOKE
+UwWKEB/8h/DwOtFKeobomWlyW8Aq72EHmc0WMbhVcmvi2h70G8f6vEwSN4VwO8et
+mNu4HoX09pBo3eCgH6is/x9v9ixOHLddCWmybh6GPLcIDvGjJZ8xHNTFlI/dhu3g
+nrHqAaXQQ+9bzv95Z4SG5Ou5w0O1W+A7aUCUVFqKJKoHvVsSYp1NK5Wjr6DJi7Qq
+gDSidmx1abDsuiZkc5jmU8GOQTZaFQbcA3ejEFdqDmDrjH4tGHiSRQ==
+=9Dkl
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    AE7AF7AE095EB290
-uid    David Saff <david@saff.net>
+pub    14A84C976D265B25
+uid    Rafi Kamal <rafikamal93@gmail.com>
 
-sub    C707929E5065E0BC
+sub    0190A8A50D88C2C9
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=Exzw
+mQGNBF1wCjUBDADAQDQrGd1ul3QLVj5zbl72zNWVNsRVF98JLSXYMmxsY/A0YNzT
+B8LR58QCNF/xcjDyFt6+9jDEVjkKnJTHduzxddF/cQ9pw+0BOOwyfIkC2ryHzGUH
+FvV6yR2UX9t61gZsLrw33GaWDAJtlmKgWH9eClf2DennjLtAmAknptgHtq+gKHce
+K8PLewad6P++oVPTgz6K/aA5itSpBBiHIAxvnCy1yjgWyoqTENP4bhfOD7wzPov9
+nI7YZZpUUY0FsLQ2Aokw06zoEIPbwL12sLSM5j7++WGXkLuUeJ5hflRUlNvBZolJ
+AWG27AODVrq52LPkCz4UUws6p1aUlE9QyizLq1rLb9ofvwN7INuWaC+nckITgZFx
+NAMmIqsBa0sgUY1YTY0fE3vx0tGQOswT9SwZ7vbFoA70m5gZg9ypAiNzgCHOnKFA
+a2J62PsOXgLIuBsKraEMXg4AcZrz93F3HwqCrDKx1GeLrCJyN0mLlkmLHpRqDwrE
+WQmpLdjBfWv5tlUAEQEAAbQiUmFmaSBLYW1hbCA8cmFmaWthbWFsOTNAZ21haWwu
+Y29tPrkBjQRdcAo1AQwApH7wS9PpUyebhQNFcMSx+dcoxYry+FyTXhOS4N1PwYuH
+3XOv2WcktD2iM+gWUWh9wPf39RWN9dTpwxBRct1wZax6SUMjzyE2x8jq1dmr+7Oq
+3bQRrrHRdx3u1FlAwwttCRd5ccG2KywKkqfM4f2SluPcbRti8rEFcNmhTjd1OFXq
+4tQipKvpnr9aaV9CNsAdfiLgdviz7JqUl1o5onFjh16gTi83Y7czFqwgsx/+rNhc
+MtkmZmunaCa3zRa7E0KhXxBbczFkTZGkBT4OMUvXK+39hvhx6FBwYcBH80C0udMO
+v36D7d08qjdiMr5l9W5s9LmYH3ylrfZ2gE99pVrZK+ZSAyY5O6sunv1STwxBCD5P
+o1MmSM9HbEVJ0kdG0U28W/Kl2xypHt7i3Sh+k68/bO27AsJiQS6qHOOIF5td1hXO
+bK74KUivCJ6FQDDc6uA50SnaOoRQoA/X9dYVWlUXfSRp+s227ESm+MTU95JtFQai
+l4CZswZiU/Lo4FsE7/TNABEBAAGJAbwEGAEKACYWIQQ9ERJup35OB/urs4YUqEyX
+bSZbJQUCXXAKNQIbDAUJA8JnAAAKCRAUqEyXbSZbJcCXDAC8uykMl4y/vo6e6Bi8
+NTJ/ktdMTsTbqLjrhDR4bTtuHUS5HDxKxide7ogH9jGaJbFQcJeMGhK3xCHk8P3S
+Q7dvLZCaBo9kbExeAy6hukoSd3cDBjZHAKXwSdpC8+XFF8wtEas7QDdqKMsFZt85
+8UByyg/Y42r70y08KOC5nz2roQiLp6/nG/pViYXza9exz0tw8BGIFc9qdQEXM1pI
+YN+v8awxEgNu509tnQSqlFz/72bmclJ3Xmczyyx/8WUdVJUX1j0HVtuOl86IBkyx
+T3oMY5Hjk4Gn0VIwlwrabd7z44G5QQjRS6fWHV94uCj+y5kHm17tZQSa7cE+i1wg
+8LVBlLLM7Rpn81g7y84JINwUkf9KBdLPFN+AMcVcC4JfCM//FE5d+k3Fd+MkhzWZ
+LXoWNvQ5Jc5z9nNCjSWmpTL+cgqaWRtmRh9OXnhx9VZE3DU7zbKZs7p6tVIBo9t7
+TaOGLo2nZ/FesPa3uBnylgYyUnzuNZB3kLz3zAM04/jc8Vk=
+=rBHT
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    C29B11246382A4D7
-uid    charleskorn's Travis CI builds <travis@charleskorn.com>
-
-sub    97149CA7141687A7
+pub    15C71C0A4E0B8EDD
+sub    891E4C2D471515FE
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-WLi/z9M5/VqJKMD6Dc6RCIwKYA==
-=SsPP
+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
+tiwy+wOBjaK9g3Kk8jsN3I8t
+=8Tiq
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    C92C5FEC70161C62
-uid    Herve Boutemy <hboutemy@apache.org>
+pub    164BD2247B936711
+uid    Marc Philipp (JUnit Development, 2014) <mail@marcphilipp.de>
 
-sub    64863FF4D1BF1809
+sub    EFE8086F9E93774E
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEdUhrIRBADCU9cuKc92CWQlZxwtRuSIV/36Qmj264YD+Lix+r1Qe1PqRr1I
-/MObOo83ulorWigSkx1k81Mnr56NwmIeo2bMhjmgRgf7EG6XEbKdRKfJcJRR1lDV
-Ml4ru40W958M3PX5fsi0m0g2TuVrAKIS4vscUt4L/Cf4IT2/0OhaT6bWswCgsNws
-Qq6NtCkLkpWSBNYGT4zb6yUEALlhHMnfzPSDerKjDOaYHTz3PRc/GGUDSBTSVj6W
-hQIDrgTqrPxoB5JMnfUz8BLSayk0d6HiwspJ4Wnxe2/jdIT+6xhX9xBYXVHZVs4R
-cr8zbBNcW2kwFg5Mqy7TiAPzakzCslKAAX+cjAKSOWyRbmkEYnNgMlctdyENOR9+
-BpP+A/9anoVEfULqoETShmgWdi94gx713qymhNBpFZnPpm4j4JuxKopl/unQmw5i
-Jwtu93cg38UfaOMJjTi6tJ6F6SE8xXv43nKs3Xb+Ll1MpTgaGUXEhCOeTZl223Qe
-NBUp8kvfcys6aVX6GT93dmWxtMewlc6gc7HVQnUnyCFsVeoy/7QjSGVydmUgQm91
-dGVteSA8aGJvdXRlbXlAYXBhY2hlLm9yZz6IYAQTEQIAIAUCR1SGsgIbAwYLCQgH
-AwIEFQIIAwQWAgMBAh4BAheAAAoJEMksX+xwFhxid2sAoKppOorIM7ygdeFyhvcN
-VV0l9cRnAKCGxTdvoOnDAgZN+5lBP0q/o3PGPYkBMwQQAQoAHRYhBPp33P7y7m6y
-3r7dLAEleUZNAcBqBQJdyJjjAAoJEAEleUZNAcBqkiEIAJSzD+MACN+Dy/6l0htV
-6nP9sUTthw1Uwzxmj5vFCrBIjpq/l7ZSVfmNyyW+X/U3ZYIg8AmM1aoZ/x94pDO/
-XAvSlrw7XwAyiN+3lMg0PAIKCzjZPYszSvkdy+1yTd7ka5vp1F5AAVl1N+erIttJ
-yT/aKW708XGR5kRMBBvanXQJxTTNBrPVPBPTqM7F1cdR2sGzKcJmRudbuMJt6MXe
-SDOOjZD398ix8HIfk8CyTL38OvGaALOd2vxsyMLg6fjKmtbYNRE95fHJsmQcphco
-rLZcKg6SJlsGb8UIotMAmFWK0uP+h9oe4TGzhl0qNdsKr8EArWv+hUfRdmnw1moo
-jRe5Ag0ER1SGshAIAPzs1unq2BMWlk4yO8D5w9br9S3qtlkYRtSOWH7ilOyvdUzI
-pQZvC/qgphdUBIO8hepmLXcF4zogNGKBjlRHjSRC4SRSmTqHmaG/kdwwtOblLAZe
-8YtzYAfDLGoLOTeKvp6mUjGWhA5eSUeGQIWAmQcucQZp75kT1C+dAgzdiASsR1Tm
-lJZQSGQ7XbVR9+xsGlc17oT8bC4gDnidvVtbfEayD/U40JT4c8Luz/Rat/yXApoR
-fMTpnJ98Hwmf1TLXhVafGk6+GjuLqNDvx2IrG0rVMNmAxnv0Zl4jTg/AlxxToNP3
-OLXrbUYbZ5fDjt4UOLK2OXspgRuLZ1dNpd/2NgsAAwYIANouVBiqlgyeOi74ktaz
-cwSyxz7+xgEhYnEGOB8TE70RHQSHW/qdvO2s6dJdIsWi0Dquh4EjGW3sURvw3Q0m
-pMZTq/pIpeTSZx5mfbV8xppyz9VqMUBHNhVXRv4yk4OoM9sfQs9aUTMcQBzejrPn
-O4cWCmw+uPXwWxj4GTz9Dgo8Kx1X7t1mjGnpONUMZxX5ObPmDRDZcvl33l9j7mC8
-CsLlZGCX7aqIVPW0cdKYXQ4EFmyGTFc4oca+ck8X5Ar5h5ayx5/pQDs9zd8YdEIf
-w6H1hAwHnvLpPqW8wl0jjdr+IjvZbB4PsF2C0RAR8XRNBK3mbtlcwRWvYjdp4bSZ
-7kyISQQYEQIACQUCR1SGsgIbDAAKCRDJLF/scBYcYnKDAJ9NS1MPppAX0CRbDC3Q
-qcfjjkWDzgCfWEb3wKP15906jEy3qUAQdfV4cuo=
-=GWfv
+mQENBFPU8TIBCADGNvExYTJpVuNGCF9NuWw+IkitjAD7WzF7QkvFCSw9VftzgTUZ
+3PYrThRiaDdmHQAke4Sp+nYyAJ7iUcQqg/5/ONiMdzXEv5Kwy5WJN8+o2aXSunIT
+PALIw29DemZdVerw8Xc9jcdNYGxbPgtfSjr/DBCBs5Guq+RuuwsBvyTGLiHpc6hb
+91D/wX6Y0NQB4UlY9f3k6AgqiR5OGq602hXYvL10pH6eT3gSmCvxp1WvNJDBmaRi
+ZdgW76Y+bGQkmygWdAb3Q2DUEQHVH30YTBx5VFoiCfx1Jud4mD90Tv1hhPn0fS50
+oLGqI6f+VB14iJ4XLaSfyk/UMl343iF9PAg9ABEBAAG0PE1hcmMgUGhpbGlwcCAo
+SlVuaXQgRGV2ZWxvcG1lbnQsIDIwMTQpIDxtYWlsQG1hcmNwaGlsaXBwLmRlPrkB
+DQRT1PEyAQgA0A5RG31MshHFziVkue970s1KNN7eDzww5KgIj8SzI5Hi20yZzs2o
+2ALBhfK42VqT6NIa6ktuJQJoWr6KhhY+kMaZlkt+I0U+Llmby4l2jlG6lFPNZYIa
+vLOFvU8eWvU934fgLutK4HimBNo8HTqn+jsfoNTf8cpvcASQnjQVOElf5xTYQ6RW
+z331ZDpfJpuPyPWK9/GMHQrurhK4QYSla9sYdYIZM27OmNxdi9haPLSkaAmeYF9p
+ng0CoPqanI3HfIN9W9Uu7kPczW3Zr1DgXq4pto7rlK69M01GewKMVuTS2MJqzWza
+P9BCMj0jI+icpSRV0696A/1eZCR7Vab9NwARAQABiQI+BBgBAgAJBQJT1PEyAhsu
+ASkJEBZL0iR7k2cRwF0gBBkBAgAGBQJT1PEyAAoJEO/oCG+ek3dOenoH/1vTfHTz
+f4Z1odIE7lC98k0zF7jtvPHndsUysKp3zMOtruEb8CE0cuw9Z0rYzIBzVTzNm305
+So7G1xv3HVOd6rVcMtpsZpo2dAyFEbBTyOqbDKfWrGx4T9e61m7syNCCjadGlTAE
+r7XLkJwLgjhHGwTN9/VEWz207JfL6u1XdfaGGSxPgZRqDw7c+kKax1fU10wV9wv5
+bs6t/fnPqJppZSR607BiHNUAt8Cpn7kEC3Rm8mS2ufqg5LX+quLlgl4K7L+EYecq
+5Ox/UG4lRCNGa6e1TM/LyoM8GpMC0OOK079GceNjR+r1Jx5fxD8Qi04rKo8U4LZd
+8Kig//NPGjBx2ytpcQf+J0linycedx3OyhGifM1j7SfrWpeQT/TJZG08qVw7mr7e
+LzYgtPfz7YzsxCAcGo+IvxSaxVF8c3BMe0liwwcSDL3SF5XWYt+3X04e9YTODKim
+D4bqhZto/DsJHR2Md8m8Q8Za+V1bS8clogD1f6Wbo3adzy2w+braL+KDyjm2NQsB
+SuLNBqcK/ztXGqxK3bhWH2wT541djd98y/jB52X+eVoeCEEPZi21wW6UDCgHqfC1
+Xxhsq70BbH5RCwIMx2iyVVoKEyxNhaOgApSfq9mko0NAlpAuT9HbTm6GPVgoEzTA
+HBhD37R+PsUfSEPep+pmyBlX2nrKxxoRNsl5KWNiQw==
+=Phg6
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    C1ADD37CA0069309
-uid    Spdx Gradle Plugin Owners (key generated by Appu Goundan) <gradle-plugin-owners@spdx.org>
+pub    1669C4BB543E0445
+uid    Emily Johnston <epmjohnston@google.com>
 
-sub    3F078B16810B4EA4
+sub    5F6BA89D4B0869B9
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-LnWsAzM=
-=8kGO
+mQGNBF3TQCcBDAD177B+Btl8XBEkBQ5jFSezFrpEl4arwCEa7htCp6T3h55HvYwz
+P7Y9zWYXfhAC8XJlPQJYpqaQiiYtdlmOrOS4wbp5Lr+z/0XpFlJFzdKglxKYcdfP
+ntnGyoj7Dz03v+SitL9Ct1YZmOGz6onlifXsCTkWraSJTqR6/y2dL0Beu7dLZp94
+fgf+FAfr77bwGhUhOh0pPI6ZK2VwNMiQN92jS/RYb6i7QjzO654ALTBR6R2sqx26
+C0NNsTUZ1WawPreT/rmR4vux1pvgbC8DcXqdptVb+iQPymnysEr69J0f7YC579+7
+itFIh6efV75W9nDqp9QB/1G808oYx1rglUstOCI0axSgSNyazbInW9qOI58rLQ4v
+wnCSTWvesVNq+uO6aVrfpXIO3uUTI3t4mpBZgVYZ+g30BlCPRx52YofvQzYbbk9d
+wCMUDQAzKGJi+mazkgBhcz+neEuNUlR/0fBMObzb7cAT4gGo/sSzYVNN5oT3u/Mi
+J4hfzYUTFMsJBp0AEQEAAbQnRW1pbHkgSm9obnN0b24gPGVwbWpvaG5zdG9uQGdv
+b2dsZS5jb20+uQGNBF3TQCcBDADJ17PQ4z5UVGBVUefEkTXeVlGX4oc+vUOVn8Z9
+B34sQkFmgsORuwm+/1rGthrMatro1Jka4UXSxYFMCt6XBz4/OdJbquxs6D85iuda
+Id9aozCOJypkfprp+ez2PK7pWeOq6DQ/lqqNGyoHxA703wshI38sNcKRcypn/vf1
+VJlO3ZjfLCVDQw4+yNrdWiwklb4QS0xwjK9Bw9m8g6HiQGil8V/kL9Avpa76rGqa
+P9YnkTo7NQG0cwEbpcxNUrkO7fFKjTOMTmfPkh5pHAHVS+FsrCsxhRs6Eb6u/qes
+tHjpYj6qtMJ5V7oXeUI3OZ9nAPctSxoNVn6f0otsaatoBwcJNNhO/6ZIFH7NlgYQ
+NN3a5Pz6NrU13+zMGbsxYzlL4/nVwhdn/kHPQ2tl4e2R79da7ModAjeafimikA3n
+GZj1Zvo1iXKLfguM+U90kTrPKSxcJqwgV4QvrO9Z9llRTzhdBmrFePFhlxN3JdpS
+KYXFInq6JwncmOAeIDhNYYcVXhcAEQEAAYkBvAQYAQoAJhYhBHYVrVYUTfI3b0nZ
+ixZpxLtUPgRFBQJd00AnAhsMBQkDwmcAAAoJEBZpxLtUPgRF32gMAJoI+6dvnT7G
+OJB4S0HAB2qhizmQ5MWiO7QE1HKQ6ShylihJfAIMnAMlLPhorr1ITZXaNMFO+rWN
+O76BdsBxAkd0rKIIjMTU5r1HuS+XCGFzitffkJ2TgQ2K4vKnSgEpCsBilgCJzdJe
+vrYoCAudkZAaeBcT0fsTtQDnWHUJSkyWro0ovaaPF5tJzMkFZQBlaNyb+DmWPyNt
+5TP6iORnmeLNE0OajrUawFUcLUITdutn2t/PRE9LBDSlewE9Gabv79z8ZGAw7jPK
+x/p+ePpIj6J05TM0BR9KLrk3avMIK+eKwcvm+nCyYA1jKr7c9E4bg+6sRbc6igvV
+L4QeKzjeGll3vjifmghVXVKVBOW1fk10cMNKaTEkGng8OfLhJDQDXuNz4m8/pMA/
+wyGfH3HBGSx+F3GZUb00kU0HbxV2Vt0QlyjwT9vJfVGQ4Y+GhnMF6qErtdX8cBIW
+FJXLEW77wWHN+QpRD6BShYZDvUA2mtO0zlB8reU+VCxgnFfm66DkUg==
+=jYDe
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    EEF9ECC7D5D90518
-uid    Daniel Santiago Rivera <danysantiago@google.com>
-
-sub    AE7B5A78012824FE
+pub    1861C322C56014B2
+sub    9A347756830C4541
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-=3gTW
+mQGiBEGVK0ERBADwhGhmOMvSgvGaqHW3ial0NS80ZXyE1EeNL6ke/WrXHB4dT6if
+inoAuUgRz3v9Na4rjSQ8YVFjn3NaZq1i8RM2KJOUU8ZkJ2AsrH6fqStjofLTd5ng
+iQaq2wLM5rTQfdjLsGQb1iDNDyCXU56+/l4mFZ2JiEGCq3Re9EFHelRBKQCg/7k0
+BIfyoFVTHw39PKaDBmCYF2sD/3CMD0J/WldhBM7gLOndH9/YEQaEMy+PJNXcfTWN
+WLygGPSOQdNBulyLkvcFIZjUTxFVakh7FbjMq3dsAP1oqthwmK7L8A1zsvRgp/TI
+4YMHkZSkgcs0PBBby+h/lpgRrWmtwjTPzql/K5xX4VSRS+umHye/7R+4ZEH7mABa
+m/ZABADkPGG2ECvfjNosPQDHZVFuF9oVaske0OjzxI+rU6sR1fJKtbOPl9d+bgz+
+df7rZ3mwppkPX2r/muUbd0CM1Se10sK7ZAoPYmWqHX+vB/oj3Jq+iqb6M5mDZzEz
+6h4hdnaGERyxbktZvhRV7Psco9CGi8o7RFUQTR79Y5ElnBavqLkCDQRBlStBEAgA
+9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt
+90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcw
+Yc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZr
+M2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEs
+tSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8
+vYlLIhkmuquiXsNV6TILOwACAggAw6kL0PhPZ/EPI0mPfmIYeaKUgTB8q47nDKY4
+6wDs1l/msVJHAVwGEBHuxmbC7r/qfAgfSW+/Lj4XbSLCqaZIWSu6lfY43IOIYXD4
+pe5cCnWkQij+h3LxRR6uDmBr5cwheHEuB2sMFU5lJiiQR1+eXYkPNK4FgVQpHLWe
+boODAlTf0j8gRR+aTs5eWXqfSA+UEsXpn6453bfZKELXkRmEznb4xyGWJaLW2Mlm
+aRlauYvc61M7FK8z15SSZbq6oictpnEcfkgnBxcNza3jZQV7WOWZ3BlD1nKQ661s
+bmS81/nLnxbov9ASs25K2olXBsHkERhjMnERedvv7avlmBwi1ohMBBgRAgAMBQJB
+lStBBRsMAAAAAAoJEBhhwyLFYBSyGTQAn2u/CvPzKwRv1FUkPYR751j9PGwDAJ4k
+Pt2uco8an9pO9/oqU6vlZUr38w==
+=alQS
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1939A2520BAB1D90
+uid    Daniel Dekany <ddekany@apache.org>
+
+sub    D068F0D7B6A63980
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFHNxM8BCADYmt+HKkEwu89KQbwV7XIbgwZSfWc7y1HvA2YJpJRXJQsU/Pzv
+BhsHnm9ZIScBLIlgE5OUnMNz8ktPDdsFg3j/L0HREXOAqkOFxWx2kANsRo2HmkM3
+67RAu42fJqJcjD2Rs37wMxlSRRGQ+/bp+Bw2HNO1pw7GwrSgmZwzwT4+1pE/TvXQ
+Wl+Nhdf3swLyBaSuWHJZT3+JOR0kEGSQuurR+57r6fKDmouWSwAKn1z97JelHuXj
+HKZeueCkQvX7dayPP4a1zpoXPcoZhYekFarLWJl411EA3aHIIV8whknsZx/lGGC5
+yF9AVIzHHnhqFC/Fr+GJbwa9oMFXj0pY06ZNABEBAAG0IkRhbmllbCBEZWthbnkg
+PGRkZWthbnlAYXBhY2hlLm9yZz65AQ0EUc3EzwEIAK6rZ7kRp3uj0CrhvuTnLHU7
+nEs+KvoUZKLyhcIys76sJQ7cnhEygcG7tng/EtK8bI6skLwUaF4fnPliDj/yIigY
+08p7TvFL/6HL4cLrIXR9uZe5IdvBKYhy23Ie2JXdLk6zH6jq5+vBE0IA7ljJUQj0
+PgiIL92kB73Bn6dPayvtApzctajXvGajYNfOLTYc3n1L/Kqay+/UwjB5MJVlmFtZ
+1a/EAxyb5yHld/s3RKEaeEIpjaoPSJwXKOWNAcLdtgcPcsyfrV4bkgjx7ABzPvf8
+2gYucthyIx4zPZ29hZfktSV61h7cbJL5HGrk39UcSgfstHbfBQiTY/1kVN9tuHkA
+EQEAAYkBHwQYAQIACQUCUc3EzwIbDAAKCRAZOaJSC6sdkEFjCADEzcJtTbykHeSP
+GykEtUnApHYM8oZixHWFvDdjkGhePMTvBRJpByS/hdS4Mnb2AfBoV696eCFAtm+D
+6iuOA1OYgc1CnGhilxRVpzjgbD0S6bG0tyiKz1dk0HKkGh36wumST1bU2qdA/UN0
+CoRIA9Csb+mg+h8c+y3QixjbpTSS4shhXpzfj8QsZmPn38S1amaSTEv8zqF8pArP
+U93184TQfJBPrjAShTEitAmX3FQlSL5v5sZms7T5S/kOHkcHm4zNlwXRJ9avqb8k
+q2rcDJX4sCe7PjoMX3y2mTk2YezY4LrYbhEeOGcMNg7XOXlhtBBJ4OuqQtXo65Lc
+T7dK1Uyb
+=9sp3
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1A2A1C94BDE89688
+uid    Michael Osipov <michaelo@apache.org>
+
+sub    A3F393B5D034A0A3
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+IIPk4HpfOfTeH6tNcg==
+=D63H
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1B2718089CE964B8
+sub    A182F48D9C2C0825
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+yEpqZGNE2g==
+=OLRp
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1DA784CCB5C46DD5
+uid    Rafael Winterhalter <rafael.wth@gmail.com>
+
+sub    7999BEFBA1039E8B
+sub    A7E989B0634097AC
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+pIXjPlQ0i6kV0h8KapE1Uo005JYgeg==
+=ASmD
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1F7A8F87B9D8F501
+sub    7D1BE4480B61E2A7
+sub    C2148900BCD3C2AF
+sub    CFF46EE3C17E53E9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+Lx/KSjFhpjYYPWtx15xNpdqJ8g==
+=Le9W
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1F8CF885D537A431
+uid    Niek Haarman <haarman.niek@gmail.com>
+
+sub    B7D9C5C3EEC4A9A9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFkyw7oBCACtGFos6g11ycruiWMuXwrE4+XbU85+1jR99AN5PcKjgXo/J3T9
+XaZLjJ+oTWCVgEHu5PTxAftbkq9+lmDAUEWZ1Q8dKrnVgBLsFNn+G2pcvVschorz
+CYFu/WT+eORA2UkdPZ7LH00iMx8DFpGtL2dBZY+tS3OpLi1LdNw4Dh/dJO7x7gas
+GWVUnL7+Cv53rmvwj8bQEuvrQjaeXMGxJKUSm0qpJ7BvkSEmQZ7qnRS7vZ05Iz4m
+uJsTNnuxtf0+fmWNrIqpv/J4RvaZVdA5OW/zA1kKYaGlZoLtWhKOht9gPAKlBk4k
+/fBfHoKqm+vnaOnxSzuYpQkYWqeEu6qzfZOHABEBAAG0JU5pZWsgSGFhcm1hbiA8
+aGFhcm1hbi5uaWVrQGdtYWlsLmNvbT65AQ0EWTLDugEIAMFs0MgoaDzDWtzhEf+9
+sPxuhLW0teT8TTZLZD2Bc9om6w4ZH892r+Bv5sWKWILz4Rh5YB25xhn5oXrRF1Xm
+3NomlmIoeQF8cwgUHw0DQeYLFYOMe0gKea1Zk55oI7T1dHaJrG8Cv7zXqVCuHcOY
+zMMSG1TvB7MuugeMrxDI95RSpDoN2vLmNfQ2gJcXoWAFsoln3G3bg/RngxmoiF52
+04Gn9MfLPGwtc1lJUoUSEqz5zDrz8Q/jwif0J2tosREuyKZMxyiQl9TTMCpNtKx+
+LGosCKUMC9wNpLRelUTJr9cR8GVJet8WWBje7vXCdqXeuMUhpE2cVcNz+SlaDDj0
+2NsAEQEAAYkBHwQYAQgACQUCWTLDugIbDAAKCRAfjPiF1TekMZFIB/sEzt8SNNO9
+jwxjRYJA3CLUcuxurSqYUDQMtspQx8tUGdrh1qjQR8vS7kdJc1laloHg7nUEC9jA
+BDZ8SSFd5inohxrKTmo9kYEHLiBeoDLxVDg35nv72oSTKHuyYZl+8QjFVgxDKToP
+ICMq96osdLOA55Fyl4BPr9aplaGG+aqD4LkkJzsqx2MVjeqnNyOpsAYuLCdz7Aq5
+Cg1F4CQYkY4G0pHppA4u52itLEUWBLbo4zkiAicta3O443hD0XLJNbp8nSPGizzt
+nyKKIi61iST69H3nmVaxh0th6a9k45AfuSEdQNRSuKO6BXGUy3F1ZUBYJGnPAT8k
+blBoRdWF9SQN
+=E8uZ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    1FD507154FB9BA39
+uid    Tam?s Cserven?k <tamas@cservenak.net>
+
+sub    8DC6F3D0ABDBD017
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+EA2DgG2xmo0JUOORyytRnNl2NeP7QMqAc7I=
+=CY+c
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    205C8673DC742C7C
+uid    Brian E Fox (CODE SIGNING KEY) <brianf@apache.org>
+
+sub    AD9CEBA0521B1945
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+gMqQQpNoy+5xrNg+uv6po4Jjtidfww==
+=sfdU
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    208B0AB1D63011C7
+uid    Violeta Georgieva Georgieva (CODE SIGNING KEY) <violetagg@apache.org>
+
+sub    B4A1D8D630480593
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=Wz1Q
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    218FA0F6A941A037
+sub    9FF24F51B06DCC19
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFjDR2UBCADDfzBacBg664xalF55ghVkhxxwLaTNUdvTJ9o0IH+cGTRj7EYr
+7QvLVa68PKigj0q7SVVwhPT7fzBLDosGjHef0UWap10ynqACBoAYSFocT9m3Www1
+nW4AGT/5chvzYfNPpN7YZ2Hkk6DUpmSzS83+6nIYdCAgrcZ5XS0Vg40vUL34TJPy
+IxJinqWxt4A14ZryqSKWbWxRcocmpCAeRLMLNxbQq5rKjjxFksTYR0Sj+t47DQsB
+rqFmnPnZFExP+Q/KG1dKQ4UE/LyvzoCzCqynuMg7gIlMuRBzDv8QB2f6DgViAHdC
+vS6m2YCTGURCQufBdJOGuGplL1uxqoEW54G3ABEBAAG5AQ0EWMNHZQEIALwz8m2S
+GdANvkFLVqXdvmOZ1RjrbrzrIP/iOjs1Bo+sD94L2qUagd+/cKjvGR2cFP3g7Zci
+YBAZVCWZpgmXTL4tL3PSZg3NVvkuXut3MU+23ksjlkl5Lfzlq0Rmidu6I1TgBsXc
+CyD8Yilr3QKtQkD0l94uXX9+Ex2PuBO92qFpNqib567wSt8druTewYm270WlAVSc
+YQ3rJzdmzJD4WT+PyKm15NSLID/wzIHxbgloe1SVs8fNmNfXP4tq3fyOY6wUnsTO
+lj5hfBuEJRiRZj1H2Fch5iFtyc7kw2pH7jhXvOHoCbztjXgA1KgAaoVixQhOHMWp
+NZMy+qDbDlmblV0AEQEAAYkBHwQYAQIACQUCWMNHZQIbDAAKCRAhj6D2qUGgN3HV
+B/98pHsmnqNOu8pflm+0oRzh9zQypjCcKlFZM0WQ7jIRghOYpIKxy+zCj3HU9110
+U64JK/PO+AAOAqHnh1XXqXCooMIapPtoPV7Wn5rvK1agsDHUqeO5yJKlZMbj60Be
+f6qR8iuLK07nZ+GJcal2NCRq/t212otXD7f70rfD5ut07MDM3ifmZFdp27eEGxCO
+TaDf+KzZhP5KUFtAcNGpuXXAEW6t/JqJ+6h9EbpddQwgLsSwoWao4p3FRyu69ZqL
+CeGx/iz2BxYeUH+oNiFh1u6Bio4Z98zze4eGD5fT4RzcWwqMvyLxWjvEjVyucG7I
+hd8aQ+J7j0jtofr9xasevdRn
+=XE73
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    21939FF0CA2A6567
+uid    Alex Herbert (CODE SIGNING KEY) <aherbert@apache.org>
+
+sub    A98BD25BE464EA45
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+NblrOf6LII4Pqx0ip7s95q54JSpekQZ65g==
+=3q/e
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    21A24B3F8B0F594A
+uid    Karl Heinz Marbaise (Apache Software Foundation) <khmarbaise@apache.org>
+
+sub    D658968EFD5E9F85
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+jEA=
+=Pdn8
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    22E44AC0622B91C3
+uid    Cedric Beust <cedric@beust.com>
+
+sub    BFE9E301CD277BAF
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFpqN94BCACaAb8Afmng1QPu5k5uzLoA1FJnF6Wf31ZU1FzDxHFHLNUYSWN2
+Bg6k95QH5ruZ+Z/QOJSoIB+b3htDklyxd8m+G2KsMIqnQs0BaTN18hb3PFyMIknM
+YWkkTPF3nVV9APk73AebTAcd2V1GB7xOP+L3T7tyUcB9/7bDeM3od6qPksdVGNMA
+0S32U8SNhe4jw8uXKdFL6PSxgyg9yeu0V7DyR92V9jF+ZicZWxaLeKpf/Vn3MBX8
+JdePR9SCJc8CNj0n/tsvg/aSmGZ3OMZTUYYvrtfgpXUw0WVkyma+T0ANcdDN91uZ
+P8lV3o+Ic8f15xwsTePDhMhmtOapIz/85ukFABEBAAG0H0NlZHJpYyBCZXVzdCA8
+Y2VkcmljQGJldXN0LmNvbT65AQ0EWmo33gEIAMB9fJ0TVVhqKzqj/gmlVDCT0kve
+vaGSDB83rwHatG/D2h9dmipoEIWBvD42/PXkYuY42iIO8/itvVOxpPZOL+FNRvei
+/ZbVEno4VGaJKQ646NkeVWyVgXZ8+VkRdZ0n09a+goz/e1pogJfL8BVKbU0F6trW
+XYywnV4+vp2kwwMGNRTXmvNabdY6rAE0TfjCGE6O9T28OXy7iHXFX3oTkHjtltUH
+WlHrLe9JhCDCPoFiSndTPYyDcZD+cEWg27BX8XsuJRvlbrzA57xD3w25ESHWJyj8
+4z6K52M/Ys7S/PawZ7pflRkbAJ9smeWr9+qg+GLJboc9vX4kdTTyQp5jkEkAEQEA
+AYkBNgQYAQgAIBYhBMcLhE8ALyH20rnIdSLkSsBiK5HDBQJaajfeAhsMAAoJECLk
+SsBiK5HD5coH/ROhc7Z1pjr9mWR8rr07yNEHNuGf3T/Z148z+ovLkV7dRobayB64
+VhtMwZtE+8Kmf0Tltx5zN2GQkqoSPl08dWFRTr6N7If8N0OCtw/XZJBHa8eD2FF7
+SnNWi6IwNfhCdRtbT0LCmaHKaUineldvmM1riI3GNggGa4cMSYw/65blR757aWAg
+AVZEWi9n0LUMKDRhjIaS1zjtxqSrcQ0o1TYsW9FxuCjJ+MzQSmtJQKiVRQ03fLJQ
+1z4j5u8YvmzCEqp2dEdqBuDuR6Wyf/TmgMUY9AeLT9U6VZTvAGH69TDqVvdmLsKh
+tQidSFbes+7ku5tM61P6ggfv5FJQgQk7WEQ=
+=iA+h
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2383163BC40844FD
+uid    Roland Kuhn <rk@rkuhn.info>
+
+sub    EDB3D937B0C94C3E
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBDwczzwRBADyR8BVt1SUMHxjSG1AAekABO0YQHJG/XwEHYk7zPH3aU14/ocf
+g6M8gxZXumM2f3oCCkmOpnW6uKxqTclQX44GyaMDETcAU5/bjWenWNj4INDlTjFS
+aWghWshotoGrfYsJFOctk4mBZKKW0+P9drC3pNGpfNYogwL7qYUdowyyRwCgwBTN
++ivnfWziygGHvdghntgOBHED/2lr7y3fJ7xGMGfg0UbHbVYgWKegKTUo2/Wxerzd
+H1laNxjZVl74NuHamkYTGuhoX8S3TBKwFskZbJcLSEfEqwulULUKnEkGxZYTkEZ5
+/3tXT6aHj0OSSz0C00qjInL1ETdU4MNXmDKs/wRUfvL73dTPrsbnOWQDCYlk+jZ/
+uDr8BACgHVEhJV0O0TAOYDsthK6NJP4otlms1I3Ya6KyDp5z/DGaOXFy3yLPbyw3
+QCzzCdwwIPDcALQk6FkQ+E2jEpJk6QkCWNcpPzZAmIwX5Kvttb36XCjKHkLjImlH
+TpdIMl33dYNstoQpN/fLB3COnRKC+c+nI+BwgdhMOxANJfJV3rQbUm9sYW5kIEt1
+aG4gPHJrQHJrdWhuLmluZm8+uQGdBDwcz04QBkDVCPOPF5fAGYxVRAeImBC8f0Mo
+hHd/+VJPC8aekUathn9DHQ6CetaarQoqD0KkoqUYJ+r68JXcwe0eDdl7AcPoRIf9
+ak7C8RYyn9CXnyVzPzlfDfjc/bgGA/BJqH0rkRbX28ujQLx69BI7DUduF6J2otaI
+KDTGxJyYw33p3tI54kbrupGiEZD4U3HS6dvD058qedFQXIqS/HrqQLte5m9hAKYO
+EuvyZTdVNkf9b6deRxBZRn0hoSQLMnRoHFlsq8ERTsJKPTUWkwADBgY+KXrIy4n2
+4U8RwrGpH/6in/zchzfmAEzMQgNfayeqfPnwROqw7wmZC5xeKUvOlEGhYPRs4HPh
+iMk502owaI0lQT3Gerb/epa4IJ4cTdMcheFM1crchDrw99467cyf6mOckgh8t7JG
+xofUpBHPXLhvNG2VhXzFs2GB5h+RtFE92+FygwGuCUc2R5YaXvmaR93S8KX9GENZ
+bVWVYhVCJZwr2jWjraEy5SLTcfmz84PgOic3wW6NsmzVcr61n2GUnashPR6SRhKG
+wcWIRgQYEQIABgUCPBzPTgAKCRAjgxY7xAhE/fGzAJ9i7ftT60SwQSDiwJ9oU37A
+p/Lb/gCeKjPeUKLcxP9L86RH1KOt1I65Ri6ITgQYEQIABgUCPBzPTgASCRAjgxY7
+xAhE/QdlR1BHAAEB8bMAn2Lt+1PrRLBBIOLAn2hTfsCn8tv+AJ4qM95QotzE/0vz
+pEfUo63UjrlGLg==
+=3Zm4
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    26E74B6874AEE127
+uid    Sam Judd <sam.a.judd@gmail.com>
+
+sub    B4E75C15C3C701AE
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFPsGJIBCADOxQoTLxpZVRIbLaRfsHa2y/TEIGvxLP7TgqTwspZYnwBd0cOW
+OHAvF8yGfdk5gvkGTlQ/xchwu2Ix05FO2c+fBoOgIG1Gn2Q+PwheZklS7S+V+GFk
+t5S3m6b54Pl2lKbcasaM99r5g2+MhxwVnG66ldLS9fdPWqWrviOC+EipHfGyuhj0
+R0E2Oh+dNHrsZR0vtoJawA8xDP5D1Ii3jEVdi71PF8OlavG7saAZXtOW1kU77oPa
+SmGFTmcFLjDP1alo95TTfBihaYiwFFnW7NQEi5Bw1u3G0+Vaoo5eJBQwYsNxLs3h
+I1d7wsqFW5LK6LSxEjfvEhJypi0XzrFkFzMvABEBAAG0H1NhbSBKdWRkIDxzYW0u
+YS5qdWRkQGdtYWlsLmNvbT65AQ0EU+wYkgEIALu35o9Q309zBBZD6WLTMvFt/X+N
+6S/cUrNLMv3YvR/Bo1mtDxsYwmzodWOHo6TNthWm1FIkDhHUMB58q9oHzL2/JIL2
+k/jCULOhj+YAT2N5fQwvZ2WBtWtfsuFYFO5y7UKKUqo+2Dhnk8YuorPbKjVXELrH
+FIq0IRlKEKnDfNrkxwHBpfeU4QaCUcCW+OjRZFsgZVVc8ZjhvvKd9/vX4Jt/c4/O
+52Ym+YEYtZaiawcNYFAdMhaiwSF+dof+v2e6BIYOJrBifZuILqA87XsHQyBCABO1
+zhspt5X2QGGqkjVHiFJnYiTwqYX72n1OpoMOklJZ+ShbbGpCst81i7lyz28AEQEA
+AYkBHwQYAQIACQUCU+wYkgIbDAAKCRAm50todK7hJ8OJCACtdgGnPNmYILYJ3jyX
+h+WPDvxr3y3yMKmC0pRhgs/WxGK6cmRV/ej8OB5aIWCaoWeJ03twgqiaSMbn+7ON
+kr1DbPLzqQGY+QJBJEvLE9m9YcAdBMHCT0fn9Op0AYQhoInOPcKLD6NFO+c91uLB
+Og0q316Wlpl0p3ULH526a2YVPeKwmjCVlhrQSoHgxagNrol4gC8bfpypsjTwCccj
+esiYMOPPU6eyHelFAAGEuVDmkh9gGb9wOqgum0vJEummqOStTopEGr63PoWVMXSQ
+bkrTrayCcxjSiKRfK10myhIGFU2npCL9QbIT7Aw2vZ5VjIm6fWIOPJJz4dsRuYL9
+Ar8c
+=LpN7
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    280D66A55F5316C5
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFOOGVgBCACiDwUZOc6943aBGUrxikkfUnsyZfHtF9jihYmA1pSgfsye+JxR
+oG9QWW9+3qx4L/d4ZEqBftTWpsjyrY7NyMaeXtJEjE0vhiWNehgXB1z4XTJ66zCX
+nhlMvixGLQtfZANqCxOmtUGoSXw+oRFY/SExAioSS19HlSxApSaUzc0prdujqp9k
+vOKKIBWTBIUELdDTA4+enfzkAnIINUX9LcMTmO+Fh0AvfjDbq4fr8rBglyVUSCqt
+TOT4oGZlbpsq9TOKrTXh5go0rm5KJcbgKvX78ZErK6pcpTgNA+XFXCz1rQ9nkIQt
+HxWaEMJtpSkIvHIBz9qoAroGtNFzz2oF4ElRABEBAAE=
+=1QGy
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    29579F18FA8FD93B
+sub    9DF7F2349731D55B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFYFiMABCADYpblWssqGxbjTwsyroPh48BwdSKl59zbFKoEHDw87NeWq7fik
+h95RkbdeWsQSvduXWgQZsUDq9cLOkuS/ChAMkAAd3MPp1NMdFmAqS7BX5wU5s5I7
+XD+/p51SWLMvgrLxoenmoE04EuQqQiXd4DbU+HGPseiNx+mN0cxPssaZMBBsmi2r
+RjwcQrFTaC1iffzh8FKLQvoTDzci//b5bWcxCLbsY9dYcUaDCbBAkL8HzyZUKNE9
+XwXh/Rq8wDakI/VEg/905a9c4xq6Rss6Yn5E4V2SAo2+B3hYmvHFsefaM9kkqvXk
+MQ6zjx83LAtzavOzmthjhhPIgCAfoQ5Q5oDzABEBAAG5AQ0EVgWIwAEIAJ29KWGH
+aEt7gXV8EweJkrYd02nwjc1LyjUT2TRwEzZ9N9qUiVqfpkgnZn4mpHCToxFoqkHa
+iv/QDfj7cp8jbZJa2wjaUkDbH2pZqLBGJ0sUUBZ1KNPM2uhhWRzAnmF/bIo3+Yfl
+hGINLNqoevkYoo9cdelP3hepef4+PUuPmKmeo856uknmaWQ89LPwLlV7oj6wiqMY
+p22sHqTGAgXeR/fSLMK7d0vSPm+57LZed5ECoRMeqYFUwSMV64RjTMkKPsvFBGvR
+hppJ+uWQiMjFFuFq2DFeNBVtueHSdgCHx1TP9i+x+7JmYsmFFmRwnEdbxO3THFXa
+gFQGr4ima+oOjLcAEQEAAYkBHwQYAQIACQUCVgWIwAIbDAAKCRApV58Y+o/ZO+ZZ
+CACL1DlaVyRNjNxzC+30X6xGykPwCdwMRF3CRjoeIicss2pBJRaIdTYFpg3bCZKJ
+J5KDC6s+03zmd3ddnKEq1fEfRcoLZ9PNBYF3IESHnNPlR68RL2cjMgq6segbhOxa
+v13ZcOIOnyrWzgbVw0ZgN8P3vCllFtifwvuF50vTshIRY11G8Gluu+GZ7tfSkPww
+Eo+pRd8scdol62aUUo6a71rDOMg2XPULz0l2hxKWfeUsksT5EY03seZd3CYqOacL
+R+jaHyOc5Nh6R1MzcRz65YTwzVbKplXtZjOghMh+rS4eDIjEKlo456M4spKFBbTf
+Ub+QS9kCkBU8csUzwF0nk/oP
+=SZ35
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    296CD27F60EED12C
+uid    Charles Lee <ckl@google.com>
+
+sub    D95ECEC170500D9F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBFsHC7gBDADlkoJglNVbX9MShcAm6jvS5atCZwWT63gSasObXFxswsJQd1NK
+qryHNcj9tKBfLbSpMOoHeyyIKDdwdxN+6+N9Hi4hf0j1Ub6deJyI8ace8VERWaxF
+oWE2hKVLuY6GzlNEve421WJSThDtG3Y1jcCB8sQ9NLEhzB8Qh/eoqBP5IGNMM+XP
+XsMDIg+15sqMpEN3oTb0WUNNaAoiWVaRJAYbQG6DsqGSBZQEo1o7K4o8xrIP3Hft
+aHn0eaQqPSxK/D0bLLDaeRxxo4u8lefVSy1dYW/70A5+kZKbHkR95zUU+GoSHBIC
+9hh+U9pcdf8Q1iDiN/BAuMtYBqG6I61UZDqaEUsxrR3iTa2RpHpclbqb7kED5kFH
+ggaXMBP3w2PLZ7iZAOd6eBPP3T0pOMDnNduAecFC34vYgPqXeN/0wV1VQWAc1FlB
+l8e10i4fcrCCq2YO9up55M3ZiX0OINabpZsPfTj11C9n6olTR0TiTsHiJKViL+Jr
+tAscFDboH3HXC1cAEQEAAbQcQ2hhcmxlcyBMZWUgPGNrbEBnb29nbGUuY29tPrkB
+jQRbBwu4AQwA2w0BcLAcrBNFxYaqgR/u+I8OZkLRw9ArcDm4SQHJ+JSODDpmCyb7
+gOUs24Nx0P3za6dag4TLGXXcDfv7TgFlSzeUcvz0whyAWfJMkuXs5+BlFe8+puDb
+Ladcj9IfwWQfct8N8MjAiRxduGCAKQHqSD+raepPNaC0NPEvGXYaYCT9MzDOJtMF
+nxVxwhhmSBNQjm4kOWbnwdZVdP2qkBQ2XxVy+/nDbOCzno/chjBla2pgBAN4Wi9n
+mUGdTiFN6gOlAOb5awaKWz5KsDwCGkgoXwoA7/pAcUT7MaRcoOyr/VnAyIq3jAMX
+kLmm9VUlOJh1oemY6KohREJU4yMMcoqsS6Pd9icii2iHMcbLyC+RH/Z7scPWRq8y
+lWuD78n7kORCf10m+Ey7CpBwb29cDNIzBYiwNBOUF1L+m9UuSX0XIy43/YbcXTSt
+ZaPO+3t3422YWKSxkjF93cIQ8zrel6b51SzqFhKs1VfY1P929S6qW92C1sqAeA12
+PtJVg/XBJyrvABEBAAGJAbwEGAEKACYWIQRL95uCWQB7Vm0vzoIpbNJ/YO7RLAUC
+WwcLuAIbDAUJCWYBgAAKCRApbNJ/YO7RLOm/DADUL72DZSb/0ZXeAnyaT/Op59qa
+G9KxpKbPXYEaYto0AhEMDWEeAN4nHxsl/nNJEG1nf+qdDtrVhd6E2ORFv4Y0LIrD
+NN7vp5mUo4Stsbn6AXL+UYtqS9ChWCLnds8dfOJTq6xOr9XKbWoIoqGWxFfjrYFE
+YdQ5vbdUfj6xpy2dS5b2bBkLoRpfsAz4ViDfZC+uzO9uHhsI9C/YzrO7KqaMB4aH
+L2iB/Na5c+VuT39NZ/PhLvnYSJ0DgpBg+EMEKXS3d7+wTZbIeAEMQsB5w1SFoGm/
+eUlTnitvot2rIn+zzkKBfetYFqrxFM8YnP30R6KLBVJeTR9siRFdVUOcvCheWCt3
+nT9l9JJNP1ceUe7e8TrcBC4qNvEPE6ZRQi6kD4fdC6dzM2X77CDLsmuKMcSqg388
+wfg286OSdKsoCgj1YDvUQqWe61UbjRPE7NArAK2gx/bMv9iz1kdOKxHCq3agJjuB
+OAF0H5MI/eTLpbySzrh5PAD5/2W6CzkFMpH6a6E=
+=ZqRe
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2A742740E08E7F8D
+uid    Terence Parr <parrt@antlr.org>
+
+sub    74C249541619FF0B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+KuT+DCAd1uFvcTw=
+=nEuq
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2B172E3E156466E8
+uid    Tamas Cservenak (ASF) (Release key) <cstamas@apache.org>
+
+sub    673B436865B87E35
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+9Ii8
+=Dnyj
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2BE5D98F751F4136
+sub    C7FDDD147FA73F44
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBEwMV84BCAD0u42clJ3hghKlMGwFA8PPlPgSEZjyvs2dRCF+dKWBaPUnR88K
+kGfWB66jX6PBtHzeiVRa078lL002S1lSth2A+s1UfYGS5wVbE938wO6PCMwgoXJ6
+0MCLsTLP54MDlly4tq5qV0Zme1wH+9n/AC0fbKkLsEWbqXhNJLJ7F8TUh6hPziko
+mLAZCb297KeEDJ3tFN2zkzjx7V79/nkA1sKHQC9INdj5jXxkglTwZhcJgPbxYzCz
+nbGeczPxwzNrN/elx0DDnKEpEms/nURfXETsnd7t2xuUuAYhpGIadZOM+LojhP/A
+Wp0KDHsiSc5tQ0oJE//ydBksCEKid0Tu2bXPABEBAAG5AQ0ETAxXzgEIANGJ24GM
+VmW0QcuT6ykJXtjrgXW4HjOEyylQ6LQJZcCt42tNA95ZhAAiNgB0CBBUuOne7y7H
+5IW0wxnrO8qOStqvjbkUWVheqA3G0AlokZVWQRk1LjmBlABJVeHNBle0248pwrXe
+0lY3NVVywxPE1ol9DOasldSv+nKyMcRFgkZ7rPFnVaLRLoozuAIDwXXaRPczN3pg
+iegwo9BLqYV5+0Ncs24+G0hO6iTToX4166GvjWa0e0YHuJ/zztXPy9CAJ6FMJy4Q
+2ZpyfmIPua653srMDty1igFdR3TVNd7xIvyhw+laJY9GxWM0G86JOCpZhrTWDDZi
+BhgL+sF1iNPcC8kAEQEAAYkBHwQYAQIACQUCTAxXzgIbDAAKCRAr5dmPdR9BNoGn
+CADj7y3qDzkFxiHbfX6RlWJfaJ7wvz2r5D7WOiiyWL2y++zMVPVEhpPSw26b8Car
+4CjRxoG9TqR8GTO8yLlgQ1mPWovaxcmfNzJ1GBQGKD564fKCJLwVMaMgMz8jEANd
+FQNA5Ka25MdixHIYafKgY4TDATQYAHSs4MXW3Y1B+54LCJcL218vdWPxQ7k8AYLQ
+Suei1+1yA4p+tpjxhr+HUuFv8tA2HUk8RcoyRfUH9fqAEuR/u+xWm4kmE4qMIgio
+665T8WuTGYLkUDJEh7F8+L+r+f0nmCxfPhIWenVOrjpyzyjPlNfaweqk2dvHG4wZ
+ulntJIX+jkiE3IPFPSOU3gs7
+=s65m
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2C7B12F2A511E325
+sub    10DA72CD7FBFA159
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE+ZO+EBCAC3fZOOuYKthr0GcUge0PH2bh18sbM9XUmPKQz/W15l1NA/2ARS
+2gUXM0R+SunMlun9KsqjnojJ2ObVPvbm1Hg/66JSRgR3JWfIpSlJxLicpfu8rCfN
+bOjh4v9ZipD+px8w3o/RNrnZH/KRsoJg9yER6pf+pUZqTJfdg5lXezc1WF+/1qVo
+ypldMGfrkfLsPrUZTT689ubbig978e7eYmJEqldtaIwaAzHQnB70wIJyg/rEwFUM
+ldsvs6t6czSuJ4zPMvmh8TMpTg9e6+DMktPl1CWRONl8RPpgYMIC96gb4OnfDDjk
+Ex6clSCwgbDwdeAyOjjR6pVq+pCNTo1Pcj5jABEBAAG5AQ0ET5k74QEIALaxogmJ
+1t7arw82krV7ILlcOu6aLuuXTuy03K1/jU73oyWfUqwvPSbH4igcLb8kt1/6ogfk
+u0T9tTx+0mDsvqK8A8NZ2nDTXok3T58UAg0FTXlqUqZmy5QPtG+it2j3/xGgip3V
+5p0Ml1TqEl2SfW6gHtLptDUWzuzPi9SgK1ZFlueprPg7xwHmWhp0gwx0KSSOYWlK
+oEllj/1aDxFNcdKogWcGN5aJEsETCEguBP7olL75u6732wc3zola4zTy5bFT4kEY
+Dk30Du3VGQJrdsqlibdQpZYm8uH4AVXDmFMdEAjIs/DGRrUgde/oUqwtgm9U+p9M
+qcbmMoeLFdi7ajEAEQEAAYkBHwQYAQIACQUCT5k74QIbDAAKCRAsexLypRHjJV9F
+CACkvuGQCqxhvY21n800w27vc85F4Fdd7LjA/l3Bs9dA5HZbk1AV4/MFpadvPX1z
+ZuBOPYqbDSvnXGfoDgE41L29S5Yeg+mx89UDO6JcQQnlNn3k5mGCgR/BmGPSWc3w
+FzTEIXDYoj4/p7Wanj8vxBQOLmRzO1nu75dnOwgXAwKtTTXhHM6NCrxuwFrekKGj
+FZm7wNeBCmnTc65hMvWqZGoNQSr8M1yJ2AryBzGvWaonDklHCOUAmLuU7n7yBOxK
+tyoYdhMdRYjmhAPueyzK7ejbEil6wfCTWGyOaahNa8SV2Z2Lcd2aTwABHy4z3YtQ
+DpFob4bKD5ohhQunm2EOXlWy
+=Y1SU
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2E2010F8A7FF4A41
+sub    E4D15F24364C7906
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEnOgPURBADYutfvXAtNgf67BQ2gWTI6+nKfILIwMPzCbQPMd7pykzF5nPMu
+Nswt3E7efo5IP1Zsv6DRrLafAW0OJSmL/oo8/ta0AfqcxCCbJ6CUyViifRZ5T4nU
+WfuWTZiaKRQ57jtt0WnNpFNFf00gDbYJWs5b4RU5Vac/0B0WDQ0wvOJfBwCgylAw
+LrDQmwyOZcws9VbpvZvz9pMEAMRkV6DN8kvmfktpbUnHNuZJOps5botqKyffQVj/
+b2zh9mQ9yFpaSWESdFgpJNeBGtQJEDOz2G/q9ydTrYyCD8ILMKmsUlj/DAjaE7mU
+/NmSpHBUO97NJN/fdMgkkbkSlk4j64lGaVovQph9ehw3DsuSTF8IPvr/DXV9nuIc
+duxTBACUE6vsxZlzB9dXe5HjKCoPGr90kUm8uCG/CVu6fBVpZZa9B6+OM6NhEkLG
+FA/EKgKc/tvNIlPsRwX1R2RoV9/tR9N772ZjhLcEBKV2UO9mb5iAWWZaMJtQ06SI
+Ws9fyd+Zx3GGY1+iwWPUxZ2lSGLlfg3Sunl7Cni86tb0fTHTrrkCDQRJzoD1EAgA
+lYw+EWr/t9pNqJhzVpAZ9u3LMKJfrGopbO+jOW0T58mIdVF4oMF5WZ4lHPTgHrRL
+KxXNcGlzaxjxBKtkUbnjRTSGk7ExzGIcWoqq65RI8JgONif1VpBaS4Y8WwX/akQB
+nCAL+eV7UwHttVUKEmt4xUW5CNa4BgCFKtVdiomvdxnBHBCgfWNHXpNnQLWhuOGJ
+ZVyqq1ZAh0/vIxUBDSJZPxmEh5235+2CDK8Zu4FCcsi409zrLTtga+ggsN4tp22x
+vRgNs6nwARsk4paFII3OMkdMVJlGqU0oQ+H5I5PADBFSUYwpcIYne/+k19+QMR1x
+Ik+7EavzdOribLC/nwaLFwADBQf+INE8jnD6qg3g1gRN3S9MNh+PAPEsrM/7Gw0N
+CAhaf3METVwSzZfwVNiXM8DVEGjaBAPTBpuJdveHpTG43E4eibjXWTe7j5A5QSUx
+O7p3W4AXNTKldFnlKkVs+6ZKCkKeasY2/7do6Cf2Ed6lL1CDXEYcZRZ6BbkXruI/
+HqT/IP2mTw1i53S5Gxj3gaG/jOroXN5cBZnRoaPJQpuri9hdUJVqPNIDhe8dz3Zx
+kHEgVPMoanp8xti86ErSjgvsxGs6xjjuxC9CNjMjyod7d6E1NSt7gvVdksX3vok3
+QvIqQKDO6l777R9LQcxEStPz91mrBRTAyO6b7AtCk4/5S2hTdYhJBBgRAgAJBQJJ
+zoD1AhsMAAoJEC4gEPin/0pBVNMAoLT0LzbZNVmium/JNdBhDhufgi7JAJ9s7DMy
+snT2e4S6/VitgWdoI9iCfA==
+=sgte
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    2F566D4221D3EC52
+uid    Ryan Harter <ryanjharter@gmail.com>
+
+sub    C4725C965E0455E9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFPSiQsBCADcgBiaKkIG5jVFbQ0NyG//y18S84/OT1X1I82OwtTryxNqxT9A
+q6HuTJqRPi5Qd0BwmQB6dG0mug9AEp58L8W5udiDysHeUvBKY6zTOprSSFvFg/Y8
+S7i9D3pM6k7L7lGahUQqVAAU4RSky90nJfcT3qTNpmsO24EelMf61XvdFHdyPAjS
+aAO9W+QWquxNqXd0FVQqpHKRB43oR64oeAAE/N/H4lvemuxK6aWEq0/KJo0KYHkt
+H60Jo+djdNhHD/EQwCp9m8pKd3FuAAI9/ypvE/a8LeH/8AcLqnrPq63vxVe678nZ
+yePb1Xl7zQUsMw/ZD4urlkcTrOLl9yfIg7wBABEBAAG0I1J5YW4gSGFydGVyIDxy
+eWFuamhhcnRlckBnbWFpbC5jb20+uQENBFPSiQsBCADt3ycVnpTw4NeU+q1rt6+a
+BrOQfcdRrTAxAwhilKEo+jD1kufJLfcDooqEYZ6l4B9Sw91/zECNmIyqRiMlMTDt
+ZOniuv/fFgxKSzHIstVDjO6tlY1RDqjzQUSb5uHMTfToTDrLki9KJfHIHfHSgOvf
+a1l3FmX4vt9ro8X8f+wfZg8jHY2paWW5RfhVprR2/A91nzgs5a3wdPQi9Bl6YRZK
+SJKNvgktsm18LMhwLqvuBpQ1ongTQdUVY9VLIkDc7Tn/V5x+2mWCAf7HrJg9UnZK
+0JoKjop4ZwR7MQ0DoBh2K1Hd6RFHrmKjpCmKA3TZVAe5C1Ntloby7un2FOL7zZfv
+ABEBAAGJAR8EGAECAAkFAlPSiQsCGwwACgkQL1ZtQiHT7FL7Xwf+PM0DHB+7ENW+
+1HbkEXZRVF3hNHSWFWj1AySvSrUeXm4z5I2Edq0zDdTQPmi/aEhYgXVzsOWXi+Mi
+nkNHXerzt6YHIfbeJJ6dX5IL7XwqrsDRxpg/J7MoWL826FUXZ6CePBfGoEA1Ijhk
+eSkyKvLm4aLv9vfC4MVuLHRbsx3nnp4ZkMVvLBSnBSeBTLaINvhlp15NLyHweE1K
+htAqVuiisWm86n9kqIXjfoj+DFuBkK9cE/YCU0sNFELYgmLVVoTjxxtY9mPsROt+
+KJxIDS9BQ8mjeifXbYwkHERnOTKxNzgwWngWLQBG5cIsQ4b80Hzl5AF5ApOcC5iu
+6Z5e2OWW+Q==
+=4YSk
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    30E6F80434A72A7F
+sub    C30F4CB428DDFC28
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEaNL+QRBACYhfwZdDNXVeU9G5/XsxrUgQGKkhfOaB1CyPHAd02Jyc5oHR0a
+nu7dHb6QBlY8b47pX8ii+uTCOX2yyFlJt2cuKYqN1TwHrMspDTC9K1x8WJMmKdM5
+KUtWchFQ/zmFgIcXM8Vm1851k0aOOP3Pkexv51u4kZ6tbAK2iqYAawB93wCgkv/X
+YpZR9qL0FWip23gsjjxf01ED/3cHs+5L6hm0vP4x8xbsei31/4yHPIRytLhkS3CP
+tPZGANloRi05FlPxNXMQdeI4tUk//V3Yew5LkJC7Ue0zkAKAxjyWYBBsbl20grmq
+89ZKcj0/pZBw9Gzm4indpORfPRT7BBc+F8+2TUD9jpha+W6paCLp9pFJR++OyiZ+
+hNwfBACIyapWUmoEmV4XG869hsnico6vF4WzuhHe/PfityhlHX2M/DDX0KrMqNeM
+muxYNsKoSw3EU8BS+g6bHYvxDFePPhpFIMwbtEEOul533V1sGbPYhBIiSBpnb7FX
+AnbVIYk06T5mKfaK8n9XB4BIrt/pz9gxDjb9KBuIHE0H8OkfzbkCDQRGjS/kEAgA
+madPbo/cLInRyG4EezfSMDw3wNw3Je3+Ozy12FgQE7aaUQ6a4YRLkWeldmTtOBlV
+XqRUV1MrGQ0+C1bWEAXPsrdzzInM8NiXz4d5kCVNa8WzfnA5Fe46hxUqUawSEt6P
+9QpT02mzYQZhazDMJqgGWFHoMHKQVtAqTlKH8W0D0YPRdV6Qn/VYZ2ZRW2mk0tU4
+/xBMLprmcQCrDYXYPC/apl3tXuzXqs/FA60lKZzzE+KqW53G7qSbSSN59IRCpk0N
+X5hFMZJ+/oBItH37Z5V/pVhRGytEfA9yv3IELpJ1CLtFZVS7lJTY7hsr74qRhbCC
+JAkjR1Ywz1/Ya29NUjF18wADBgf/SXXHiYR4XasV+LOngRzA/yw8yG+1gBhF/5LF
+NidGG1NnkUVk9t0APwgd5pubPagIrVqJVbr3UfFjU8lZQOLUigadk+JJ3NnhRQkQ
+NZtkvN9a53vZeORGWNDoxqnIm4RDLJjjf4pfI8tORRwNyqxWxNB4bAc+k9ysXEO+
+4qbQQmCFKzXjCaxWCsl6dXuRvQ4SKzoi63pN05o9/YG+wh/c8QCM7rZVDqIVDoqz
+hHrsWszUyHvr8Vg2uYOaIbxnWXhaNPb9R4h+DV2dITCeIrOj+Ey3MRl+vXNDqx4B
+nEq2SxFS6PXWTjqp7xE0ITKv5rppyrR231RLmY5lQxSbm0PEE4hJBBgRAgAJBQJG
+jS/kAhsMAAoJEDDm+AQ0pyp/2Z0AnRYlvIQAMoO33jBp6ZEd8GQ8iARZAJ4323AS
+sjiqTZMbrvYrk4fWvFzxXg==
+=z07+
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    32AC66C4FBF15ECB
+uid    Charles Honton <chas@honton.org>
+
+sub    D79E291A1BF549DC
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+qlu5Ow==
+=NOoV
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    34918B7D3969D2F5
+uid    Brad Corso <bcorso@google.com>
+
+sub    5CE9BCD2ED28F793
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF0vfHYBDADEDPY9ub98c7jQe4yMbPke3A/sxNHnn0WuA9JN880DPs3L7lrv
+9VHTOlFXslDNBPYSbgFXH5YlMGg8ZY8bhngjc+Z3dtrCX1cAjUXOnibi7fBFomLB
+xvKzTHyWprguV6B2YAldKpqA4DtecJEF6jusNPptSpMN2olZGcxVrTB1s75eO5Lr
+MRIvZoWxvkH76KxisytDh/Z3MJMi9fFD+2OMsC/WynOs0TIih1T5U2jCz25dwkez
+zb3Bd4G6E85fS+weJPXMRiezimF8WyFN+dDrFgpwWqgA24jbKG/tfF6sAuvGmPgw
+aKIv2VFrdstqfCVC9p2nzuchIDS85f/D+fEjBsSj8spUzA15rD0T1/9BHxtW+L92
+fcTs0rTGT4sP5HPl2aD9R/NP03Ywg8bDqcBWofTuCMtfDz5lUBpeOPngByDiKtQC
+tpsB0PyhPoMkrn701QSkMXPO6yLP6VZH5f9qhpvWrHLqsd4GEA+PoRuBJbYoDErq
+5hLW0Sgi9qDyzLMAEQEAAbQeQnJhZCBDb3JzbyA8YmNvcnNvQGdvb2dsZS5jb20+
+uQGNBF0vfHYBDADQCIbElrNvg2km9F/xYNvj9JQmOcJcUiADJcYqJKjwPMtPZav4
+YO3t6E8q73cQEumDIONrl4ZnVTIb4KBEFvKsxlboOxqRJJxoPt4R8qLPSUJqJDRo
+aMMqscaxRv6KTS3hpBJ6ga4ti5F2dOvqhyREWCXfjEhVcrBOn4naeoPNfzZTPQLK
+Gp2RHK/kRTuVbLsVu6Ep1MyPutj4s1NBs7Ne3JTuxEkOP1mrG6hU2eNZMz7ooUHu
+lasgnDZvq6qrYKoBPyxm7VytpPB6+jW8JsjvJZFB1KoQZM83uliGNLKdIY62ANc3
+n+iEp0wQZzIskgjPvClXKgqbCzqAYSiz9Nl546SpChnvlYDKYL2fjso9c0Ji3Kwi
+6cLEmA3HqtIVT4haBOy4PbVaW7W62tscwCeDGFDKF+z0X4P5QhmvmnL0N4UTvcjn
+mLVhZQDELxo0gYrLTsxOyFiGiyTGQ2tFMMBXM56+oLnfeoMsURrcLAfEr+6UeKn0
+dWazDXA3i0YvLp8AEQEAAYkBvAQYAQoAJhYhBE+P7GeF9hHZpxLqJzSRi305adL1
+BQJdL3x2AhsMBQkDwmcAAAoJEDSRi305adL15/ML/iz3yusafhsG4zh1KJhVuyQK
+DinmReoBfrTBuETu2y6fwb1qwCpx454mT7aRgtFaEQHtNQW+7rQjDwn8CMgu2xP4
+2I26E0xlAfs5vcstJ3WdOrcbfIFEnSrQWEUumX4fWoMr1m2uOC1cy8uSdGTRPjCS
+vOTxmmGWBbgAevhnh3P+4egb1aBEgfvz7rcklodxqftJcKlnHehqWdS8+SyM1z+v
+i3Kk4SczMMgCgUNb3ZJjmL0F1kAHAXlolxhZjiODoB+WpyHHXw8ahGiqLz9pz6DL
+VGe6el0xK9Gf6KDg5jfBvD03p9RBqNKc+gYZ5oTUoYQILmHmx9LvPdU9CYmIeg/e
+sDcK4hd0+GJq2GzJNIZkoBQM/bi5xrpHh9ZJnwWrAJq7zIcxxJWPFK4zhpvZGlCY
+9/9dnCinH+epV0d4POb7SUfCz+XfrOYdTYs/G5UCggCVrBxCqdq9wdIoPgi18pUq
+K0rLXbIe/0Q1MkLjnJ9MqcnGGPSNV5d2f/Q9Y8U9EA==
+=6FcK
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    353A436E043E3145
+uid    Garvin LeClaire <garvin.leclaire@gmail.com>
+
+sub    7494750BDF4F8FAE
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE1/v9YBCADaUiBecDzwU5g9Gmn3T9pAa17OlUl2iH0zn8tNTUg++bW/A9m3
+lWykQBlvPOi32lqZ5q7yewSNBGHl/pHRRVsIE6hhkVigNQbMztRFPshKCU/0RvKu
+29cew2T37crxYFGShYFwiJgOdQmXqhgIai0S2sW0Iavf5/PJJjXbrM1YIqUqkf73
+unns/lIDEiIDXCnGRNJKzGWTPsbt5R3hVo9mFraPUxapw3b9C/2GGDT/mwR51IOf
+rHkQby7Uh6XzDC8jWIH/BrFT6gFRZgKn9BRi3meB5vPip0rvcxPQnmvi2R4iUIyg
+DvCsUpXr6RpAEK6/p4k17JeglxCDlAbTDLUHABEBAAG0K0dhcnZpbiBMZUNsYWly
+ZSA8Z2FydmluLmxlY2xhaXJlQGdtYWlsLmNvbT65AQ0ETX+/1gEIAJsFRfWMDIoJ
+MsLPltDrrPsg1lpl2RFQuPqjZfPM0AAiAJTB/UhRfoMoijggV/m5r0y9d6LH4XhC
+ynm+2VC/6TTxkvMKHAQroZFKzBKjvpCKXYaLgiMNi0XfsQ8p7/0nEUA1XXZDOrol
+9JJQ+3XxaQv3+64u+ZiZY7JrcH9MtytyVcsqOnQe8ST02pnpjwOIqh0TZt+HB17P
+WraDWRETspAMfbmoZSB9vEBiHsSoELZYywFxcsxB+nbMunYONTjp/14MRKKlxeTL
+lH7CfJwaGV/2rvN+dKOymbg2uA4y/wrZrOJVE3G7IP5ehQ/Pitcb1TP6Q5LISdAo
+7zGFslS9iD8AEQEAAYkBHwQYAQIACQUCTX+/1gIbDAAKCRA1OkNuBD4xRZ+QB/45
+ejZ9k7v3Yh4MtyY0th94E2h8UK3gT1axDIEyeWqQZaVxqvA8gG2kXhFP97c/WINU
+ScMcdOCqTpUWRnQaZgcvD39/AFc5Bb3kN8Mo69YoOGkRRkvsY28NhRQBjn96QKUB
+mc4vGNBLV/XCsbhSD8T5KJdFszVcTHg5q237mYucSzDfU9/0EUeSuFwwtng93Y4R
+t5nDTm1MLcnBi5CTGw6Q1FL9orGNHi6OXcwXDGKK1iiWjUjrmXwpgp5Zv+A4WcmG
+2dZHADjBlsgeHhfWCfxdJeMNZ5BOLL6SHLRuKiw6HUKNYs6BZNNdPQXapzKhCpSu
+FHW+84/4S2jX89AAfhTk
+=6k1l
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    358A4ABAE72947C2
+uid    Jens Nyman <jnyman@google.com>
+
+sub    B8EB751F2C19011D
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGA2h7oBDADtWcow8HEnabHf+poCBJR+MG8JybFpgOQ5ns1e6b3xnD51kzqv
+0I1orkmIfhCVU4nPGp2jy0JHQUvf3NDIDobt/O/C7+3BvNanfw7sJeHXrCy90o3I
+qKqOHfUk73eNqh3yYffBUnRg7PXd6c/IqVJ9tOsx0Pgwnu0Egf+8wYEhxEhP49CP
+8uTdZQr2NUIhtDlcypbSGDPWF+f9aQwC8Pu6ctYHq2e3I3xDs11hGpOLsltecPVz
+gUE//YnSPpZJj4JwQ07/eu8MVZM0ekwE7PtadLd9gQIy6O8oB1VmhLY1bAquOmGT
+JmcmWmwTxH57MmhPeorVDVPUM1oQG7/kdFUUKqk26uxVG7KlTiddtGE78xbepc29
+swo5eNQNlWWo1ezRcxwLti0w5HMwne6Lg+uRkEc5OUUoIoZFwHJx7f/maXTvfDDo
+6DfZ/A5CZf6ai/mkWu0crZ2FpiFXAza/CO0l1bkcszzsXP1svqW9o3Lh1rqki5Ed
+LQXjfwjjN3SuoekAEQEAAbQeSmVucyBOeW1hbiA8am55bWFuQGdvb2dsZS5jb20+
+uQGNBGA2h7oBDADnO8hCrrxvfc31rG1SgP9P6rUYMMJ+aBlKx63f5ZLt5Uc7iQHv
+p33lj7/EviWojsyYXc13huFuGKsVjH2Q24+z+0Pmiuf1Wsk3YFb1lYCaNdkIBCpq
+9h6eY3hziuN0SvdsHDacX+MHN56TnHsKDcw2G+wFQ7MBHY88Wr60cYeRZfi5NA42
+k7/f8hwhST6/GBvXJLUMLuvPEgW9WOG94gDh70hBC48QhVEJCSGsIWkmBldcHKEU
+PR50q2yI3J9leWZ5mtSSp/ikoikw1QkMcc9Jv+EI5VUbYTB04Q2bZLfuGkCS8Kgn
+YZthxmUqTwCmTN3V1fZQL3dXJTjrUMGll9LooYFZwhOnVmpESylPQWcpq6zLtrY3
+9kiYZQAuSshuvTD2lz9UWo10FNYvSB+YFLwX5L1M+8hvIL5RZt3G1BH/8cqcJpYb
+Vj7hl+IVpnueDQYldhnYIkEvxhBhKk08gaaYz++s6nrv9orYAumd0AEeFg38uwX+
+wKdG98ChTik4QnMAEQEAAYkBvAQYAQoAJhYhBOi/Yzs4a33c8eGpszWKSrrnKUfC
+BQJgNoe6AhsMBQkDwmcAAAoJEDWKSrrnKUfCjz8MAKGbZqcyBnVxQI1U7jd22k+A
++6THsnUzSmhHHo6Ma17arp/HphvqzC7PHD67Oh1Y7ElTfUoXG4IX7qRd1iRvU7HN
+ILtV6rMxbJ9uLXaDDwtoEw1ano3LYpNp/8nNxZTX3iTVaUUZ0j7T/QfqWXVwdwlj
+2a7v8tW/WEiP9UyppJ0OTn7+qfOGS1K/qdGijsFNR7XUoJMrE6Zbh4RMkvqr6L9W
+RJO9zb7kKeuCH71BnnMuI2uf1WvpKteVfS3GD/KCNRuTATRdpRUvxI+C+kPpJHHn
+B+S+e8X0PQoteqErKCceYYl4YraZAtAMRx3ylfG3+5CyPJOTjj8xJAA1XJZP1H3R
+GTmN8yJx4Ph9vE128oHXlcAk47Y1o2/hv63rTwSG3dmJwbjgbBoP3JwdYGGUtDJK
+6RgVsV1u0wN5MBcgDHVimXlcCl5HGSLWfF3hPMzDBOwAjelf5iv32+LWoOcy7N7K
+a2Rawm3+gXQyFFbW42hpI8TDRfB4oHWyTsM6zYXNXw==
+=br/e
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    3595395EB3D8E1BA
+uid    Ralph Goers (CODE SIGNING KEY) <rgoers@apache.org>
+
+sub    FE694B892910DD22
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBErygmoBEADbs8zVUn5ZwbsG3tqT4x6U7SZYOtd3WXOtHjuu9Cyp74rZ19Pi
+XNbYwIAoCgOI/nXVWwuOrNJH0pHaQ73slbNzLxo2ahQIkw9PbK4V3YXLai1r/W6T
+xU94s7WECoiH8uuRAZFwbei87/xwwTVnfwQjKBThom05LbOebtIGHkSg4Xl3b+Me
+5iqHYiw/QOujiKOqm05s1aTWtm45KB3/u80/5y+2+/vn9HXor61gibDkC/oclDuj
+J1GYPCIAUvj95vw5n6Eq46I6aoed3BWCLD+qXBz3QJjwIKTYLOHO9iTCjPk1UmAq
+NQhrENV7eeahFIDgL+b9wsm6CwuH36B7cdobsOltqBegpMczM+kwTbeaVwyI+S6Y
+jQflqUclFctJCRxZYzUUL3C5X/yvb8Bj+WmoEjm3mSMEPUC+KwWeVGaXIrdw/yzX
+Vziqu+PVWZYovNKsLGlL5zUJt3nV0xmDJdPuLRgheIfB2t4oqn0Ki/PzMLQhhX9+
+9zWc9WD9V8cIZtiSs1hRny5Ns33nQr0KkdGOj1lfVcZVrDv64VUSzofH2nGEWS+f
+h9gkgD3aLHppt2XCH7tJK+wU/NlR5/0j+j3QwAfG5pziD0zMjvnKREfJ3aqqu9jj
+8FgdJ5vJvo7hlq0zakD7qTUO0OJiELHcf8q0jfFdiqaocs4HZp1OO1w8hQARAQAB
+tDJSYWxwaCBHb2VycyAoQ09ERSBTSUdOSU5HIEtFWSkgPHJnb2Vyc0BhcGFjaGUu
+b3JnPrkCDQRK8oJqARAAzqD0AESdZa2wPgtiSQwRd+vn6YelEW52J3O9mP5HXVnQ
+oVwJwikTeUAHWXiEFhGCp6RAo6kv1Jx/hOOpdcF0oPmHcxb6X1kxhqnZgs3DDPaK
+FfALQb7VHr288GuIwVk09VY69gcFlWotidM5jSZ0N74rJmQJdbtaj9gyUz5+aW1Y
+iuZ6IfFE34j4psfvk3Db7RsQuGb7pmmFjQHXnBgcVo6h8N9un4P75hwer34sXDm9
+rutERzL1MZMEuG7FE8SYDO+x6+pvlCSowSgo+SinzAM4f+4AEfCaOUv/Hw/dhL4d
+Yi75XMI42B+mrD0+llfMKbMLofglRtxBA/oqgMkRAeg5LND+KoxqFBk6ztDrGjXI
+lf6TxPH5MY2pkizyYVQGt3GgSXnz/LuzwmIQfZDmHe15QE6r+I06AY1ViICoMz7N
+iPdgfVS9E3BlkPhs6OlsIgWE4pPnpuzuBo5CLQIHmMl+5IdJgFN+SNVV+4+stx4U
+RMkaiUkcp0Mm8oupuyB28VG/fOpOqg1VBjFrFutYMja86mRY3Bg7Xg64Jj7dqoFX
+KjvPUfjxEuIamlEmNZM2n8pSsaPXPFAJG1H9y+yrVfa7L7ynAiqzWx8KrE3SnlKu
+Eo/5ZVF3xR1vdsJ38BCY+DYlzixVDaPM7qCBzCVGxVDZ6rPsEfwgBTPAGP2BzW0A
+EQEAAYkCHwQYAQoACQUCSvKCagIbDAAKCRA1lTles9jhulznD/oD95V8OrQuxY0+
+Af6DjLaZENjUcOhYElu+WNT9neH2bu0JLiO8y3ZjY1mT0XBHZaBnNKfhjfjSlQRO
+0ipojQ2cDQxnQ4gIkRn7Iz2wRcm6UJHOiCGR1w+DYAwVI/j33rrztg+yfpaET3s8
+k0wEOceWj8lb7WII7ek7xhIZ/d0hNFwy92/UnuuKSmDfFClIwTzPShy3CB0oFQR3
+SMbhquaIZ8+tOzYDDN9tQ00sO461VRgwmJ9fauieL/rLNRegigZrF0BYY4XusM1B
+c2pXG/DVflePMoNQTx9J+dqx9Wk5SjEQ0dZsFwpz5WrweWMpNBhZaBkjfWL7EsYN
+ChaN7n7uy8JgbO9FmRb4DPWvxk5otFqUv3fIPbt/X/XeFbV33eWp7kSDb9DL+YkX
+qBef4QLVBOBGeIJhQgm0rTKtxFl+YLuiFM167F56IHTnv9bKEv3Un1puPGgWnCpn
+F6zBx5Xg/3La4A01vkVydsb0P0Cx+ETPWCZzyRenut5dQLUAQEXz+G8HjdRf+aK8
+24Mx4WAfpV8zkCkVae+se/txEFxedb/Y5jfejMqFX4M07ZuAydoFkeyCMaxin7WZ
+I4ZUW1+st7nSMQipZuv2XsTu6tbilQOccWm+5zILmBsSD7RT1+ek7F8ib130sFVs
+E4MKxXh0DGLPEPiyStLVF41310m6rA==
+=n4Zz
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    36D4E9618F3ADAB5
+sub    C4935FA8AC763C70
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGGiftwBDAC94Yhhh/5yO8jYFkg01MPnooXKZEPwxAbAg9wn5iM0tHxhEpkU
+zJVYZ+JYq013+Ldp8Of7A/d6hKTtZ0xwSeY7S/WFykIk6tc0P5j0sfFS3pGPDk+W
+D3DwUa+8m0PriF7iA57vCOE51znO/IUIA3PG2YAK6jv2/i8MDXOOq3qB7VrbvKGB
+kIPubp5PbjvP+LFhLuUReU9m2y/3q9lNFXdd9kE2iScqGmu3FDhRJxBK/WQ2kqiv
+sJZjAYeHEVNcc88Ah6vXI73uYrvWVGCErzswYy9UrxCAQ/x2OxUdLw7NTHwjZSYC
+JvH5JPPTlDxMgfwTIsmaECtw4QgiVmvDp+RVa9zyrdI++RNr0InsXv9gWMv3p3yf
+TF20ZL8znFYVUi6XkeQhZjT4fHwDqDVnxhSAFe3E0cwHFJBQe2EFLljwNy6VYnio
+wBr7HrAxczRRqlUy4a3bH5KwiNwwvxgqfdMj9KTVpP9t98/TA36bIohwGFRWB7W4
+i395S90NsTbCh/cAEQEAAbkBjQRhon7cAQwAtPmKcM1/z8sMJnt4sHe3ndXsOdSq
+TJbRkAcdyDO1F4qgj5z9wkrlVVKGuVtmJS3qmR901Q+oH+JqM6UeGqhNig4IQvME
+iQjjelvKXMX9PPVzlP+ga5Y1/2mnUmgmYXK406CU7aaQ3hs7++XDonnQUt5nWF9d
+XT+xK/SDLYMk5i1TNqPVFZBPm44HpIjKGNJXD7Vv/5z62+hKswpLXgYt8Rz95ByG
+ncjQ1Lo2M1T1Y/EuwlRoc9RTdyABavSQWVLKIz6kKM4LejajjRvLnybMUug0CJl5
+mni4cHXx9t0pMlG5DE2O3mZLwTgWcJ8cu2CtPxA9iLfVvFAThxk3ZitkEhChBtG9
+/V8D4DiTIht6bd49xkHP5pxtB/fuo9lNb0axSBaOAeant3KA6F6vki+chnGhOFqV
+1KJHcxYG7VsG1hYhy5IbZsg4GdcXfTwwF1/mq8kvHfyTkBy6HMDGwpr0ATNnrxO7
+tJTiVqDuxfviGQUjqJIQDns6fM9BI4OfpXyjABEBAAGJAbYEGAEIACAWIQRH62g2
+JF0tQOid+0E21OlhjzratQUCYaJ+3AIbDAAKCRA21OlhjzratRBcDACCfhsaCFvM
+JTls5lT/dcTqSCYJYZyDj95DlTiaRNkXnAGrTyE45PnmJLv6FFZzSZdu/eLE8ls2
+MY/KWqnZYYV2Mct/pwDDLSjdAN/NSRe9HeAh2OS1kNeN2SIcoL55gEodKBNSMisY
+9N3ylLMxHZPa5LNBo+j9wftEaVi2fTX8LDJFQvUOZ3f7cz3f6u42FeHUqaLm2alH
+QSkfTB3yIu8Hmo2EXHh4UfwTmS55OBGLQ91d8neu7PcimqCeadeHW+qY5g5hr5NN
+LxMA+n+vwPGcQNxg0lH2XBdlFBbAELEGxMcKbW51QL2h+EdwGzT/nK3Iia/qm3N5
+0Z12j/hhzohlf7TQjhzB43Wbxef94JbKacvng8t/hG3+n8UASQzizCSn/oMkXQom
+XdQe5JFgJCroU2CfrdFmZfbkkq9mAi80BLUEAGNTUQrg/W39VX1/klGiXiWtpU8g
+q/tSGRQHXTwG53qejlUtKI315ZizOhJiniSDx4fZaK2zB9RlZkrnd1Y=
+=KPJF
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    379CE192D401AB61
+sub    0CFE993CDBE1D0A2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+N9IFsU1/E/XhP4QkRJrZI1F/
+=N8tg
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    3A1959EEF8726006
@@ -14921,423 +6239,1877 @@
 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
-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
-9Q==
-=PprS
+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
+=jgEl
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    7C7D8456294423BA
-uid    Henri Tremblay <henri.tremblay@gmail.com>
+pub    3AD93C3C677A106E
+uid    Carl Mastrangelo <carl@carlmastrangelo.com>
 
-sub    9842FE565AA0601E
+sub    9B2A1B698A113AAD
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEvsZw4RBADH20nX+H1xvMBYmXRj1Aae4dRr6Y6qI7QRWHO6Z7/dxr9bk/NN
-Yjq5KsVOQxZzloVdtqx75rznT7fZq98g7Nq9IeEtB6k4tnh6XQLhljJMk0a3mzdt
-q3VzdxeVbwCaPJ0zixv8XPTAH6MpRJUvP9XjzxwaYHrjwcQ1LslW4TrIzwCgi5rf
-jChLCyKcaL05gqUjl4lmefED/iqOwYZw5pJ8+X+OHUViiOB43wsJt1brAhPj4KgB
-ODStcE6WlHFKi7YzcYNLzYMebSGYn6bj65b3qNf6rybWD1hGUFK4122Q7+HCH9Ic
-J+rr8HwjGFo/yxI0/mkyaF0BthXYPy4WtdsdTM2kgx8Zr3Q2rSt1jBPuV3q8d27z
-FZMiA/9cWPkRx0RfAJmBPKmKkbBkEtBbNau3G7MY1OEAkEkRnzmnyyjr5IP84A7K
-RdjTCvkbiQrOQH00Ki4sHIg+9Xv1gDg1XLkFDzRARKA1TxjL0OeS4RWF3iia7Swk
-MOnTdhR50pjb18W8kB4mEMZY7duP4nwDfQwHMwbFZGHrjImaurQpSGVucmkgVHJl
-bWJsYXkgPGhlbnJpLnRyZW1ibGF5QGdtYWlsLmNvbT6IYAQTEQIAIAUCS+xnDgIb
-AwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEHx9hFYpRCO6PVEAn2zcXoOXcW0I
-7Ht0qnUs4ZMM84ahAKCAKHGR83czneSiWoCsXKJQo9ZQ3LkCDQRL7GcQEAgAthrb
-FDDbIGq97dbX1ZEwNGpjILdeumxZzaCc5PgldHGA86TL2V9iPpONJtv7/Csr1c/r
-vH0IA/BFu+0Kde9UP+z9JycmfJpIsd2Qtxfhn9R4+Td0VtN9NNkpt1+JcThbzyQq
-4UU82uBKwSG/wzubOI4Fn+7ypIuNgDkqK0STIL3ucKF/RV77PsOBeLHkCGKIVhUU
-fY1D51BWZKKB1efaVK7PLdnsi64lAhbaexA43dwUUtVwQOvDzJVtkycV2IMwXwyH
-onlK+4vbcwIH2BAU46LIZy+VFaI+lNNmR9+xeWH49oJYnMWIXif4RzvO1ag2KKwl
-G2sacuVTtpWVqKayBwADBQf7BGl4POKtluAbX3a/KGnX1YyibPT2e4pdOxqbKTwu
-Rc7ILIK/LVcejVuLd+eOF1QmjToI7Y3qjlzvtaxSemfkxbIQpdus0SyHEEAGH/qj
-NuTs8ZwEl9tPPrKaJHbJ9kQrlDPwkufA0NDAXTE76UhcHPY0DeykAKEw2ravEqI7
-Y0nXR2WSmRLFChmQ+aNTm/9UGI/IoRdS/dgo1eaLD/7RLFeL5tGDe+2nj+B6j+52
-nZEmaRCWWU7O9jYL1cQu5WTurtneCLtIqehLsjuVz9ihBysYuUcTOV/6W0AIclQo
-MEiFR9Kyv0owDk6LtX2DgibJuAvvLlnajsiGm5nyVh3G1IhJBBgRAgAJBQJL7GcQ
-AhsMAAoJEHx9hFYpRCO6iXUAnRcLw17lBhe/WcKFRkzETSxaJcjIAJ4/P1NNOn/e
-ScLdx27sje7q3sBENw==
-=TjvQ
+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
+=qc4l
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    F42E87F9665015C9
-uid    Jonathan Hedley <jonathan@hedley.net>
-
-sub    6064B04A9DC688E0
+pub    3C0A8F4744F37328
+sub    D17266C6E05F9993
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEtsF2oRBACcai1CJgjBfgteTh61OuTg4dxFwvLSxXy8uM1ouJw5sMx+OKR9
-Uq6pAZ1+NAUckUrha9J6qhQ+WQtaO5PI1Cz2f9rY+FBRx3O+jeTaCgGxM8mGUM5e
-9lFqWQOAuCIWB1XPzoy5iTRDquD2q9NrgldpcwLX3EVtloIPKF7QLq72cwCgrb5X
-R25dB8PUdZKUt2TtJbjB+SMD/1UzAPirgX0/RpL9wUR1i14yIrTfpFP/yM9PE4ij
-qcZ1yafVdw64E1k5W4k+Pyl4D8DvSJvbJHvYjg8/G9V66WzaKcv+987fetUuePvY
-/rwxBPztqq8y6+hjBc8QVhZGWmAoGGEFO6MIGsSyN5ohqPMpNXkczIo+NMvDxGzz
-ld5ZA/9awGTsigBdpBK2F6GOmbvBv+Xebu9rbaJvBvP+npNx01s/f5sHPCxmBTFk
-m1vtaMdZ29RovrWPSZRj8WWes0bcisw80250r1CBlYzGzqEVZ7b0Hh2RfkfaxbYh
-wikyfTfA2iX8TUGBgirsZbyegjUadElhwFNDASnvLTEuQKeVLLQlSm9uYXRoYW4g
-SGVkbGV5IDxqb25hdGhhbkBoZWRsZXkubmV0Poh3BBMRAgAgBQJLbBdqAhsDBgsJ
-CAcDAgQVAggDBBYCAwECHgECF4AAIQkQ9C6H+WZQFckWIQTzGEvNVfTQFuMNTJv0
-Lof5ZlAVyUaVAJ98o4QsLXrRWAe4qp2AePIJa5pRhgCdGrNdOEgEImKoSwS00vWE
-RiojY0W5Ag0ES2wXahAIANLGdCWb1qCiBm/qOjDsCOqd7jG/olgcHWH6IdkT51GX
-QcBoSY6d9gok7dmN6mBHKguTbxeRVncdZuSjkHtTvkBaKjypwtWz4/bmToy1ape8
-ebUsAnjyGjDQfnzMRIeYWMC1rQc/J63Qj4MJvpwMHnKBPGH66Zq12ZP2C2pOeBTn
-hMC2Gj/BOLthR4hKjflpijIyEcC81aWAK1kQm0y4UkiskQcu1MRKL1B/ZiGuGLlO
-D29keuC8KKTBwgZuaMNFPJAsPL6VuNBqwXP9nmiHlwl9lye+xPbPWT4FujKCeiHN
-cVer6CySiBFfLeOHXijUsA31TWR8cnpmimvPxoKY1OcAAwUH/1My+ZV0Zsk3Sakb
-xyH1Fd4OAN1++3d7zq6Gm/CisODBcti4k4qDe27SisRPeyY6dtWGRXeyqZn7tov5
-K/UFSaPg0sXtqdsXEKM8kvpWsjyvIf+tS4cofL481eQFFgOWbqfj+yYf1kZYfRsb
-NJNL4pmDBSiJsN5ma+BAPFAo9nvOVyBzRwXdAdVSLpKuDo1OEIUa7rTXmyMtxmd+
-cpXGl0+b9fEav4kSQLiRaAs11GhPdP1ff9qG/ANQmBChi6HLzkIAbI+/toD+Vjj/
-lsSOE1jxDUSjFXIVQRPM1fu2GYmoTwsDkK/U0FjGlCCcWfOcq+zvA4STgV9wexBy
-H6aAA12IYAQYEQIACQUCS2wXagIbDAAhCRD0Lof5ZlAVyRYhBPMYS81V9NAW4w1M
-m/Quh/lmUBXJfs8AnAyiCC2xgVDR0RmOe5pmecSjFmwrAJ0W5jNfBpStUykXDnKq
-hD1krrLqx4hgBBgRAgAJBQJLbBdqAhsMACEJEPQuh/lmUBXJFiEE8xhLzVX00Bbj
-DUyb9C6H+WZQFcl+zwCfc7b8hD9OHMusz/ZR7dKl3a7nA34AoIdTiFJNKRczWAbd
-z17znsg+RUG5
-=8yMs
+mQENBFSQ6LEBCADnoAfQsg2uDYMnEPqt7tlnZxzyLVKiHXdJzT6OHA0FUdsB9H/9
+vWI863v20dsk4+tf1pXLa1AWBusInf7FM1JBCQBc/By3fR3JRhJU0QSoEcwtOQSa
+MmktLQx6s5V3hee6pJDJicY3fESWqrVygiUeyuRJupbBOOh3V4GkKnk1s48ZBesl
+viHzOjz8ysZKbn3h7mDuR4NaMx54U9x008NKs4Ry4ztAXbf2FqkmhkU1aE+1v1vz
+/mShXXuwGjYuv4OnQyP6ONHJPOclc4mDFU3yuUg328AUCbWHPg1kAMbpZLiEnBgN
+anC0K9BxYfVdQV55XSMMrdPfC4dNAwMEuzkRABEBAAG5AQ0EVJDosQEIAN9tyXFa
+CMYODFVn/vTf/9+Am9AoNvTtvoulLoC3VsamyIel3QI7ek9rppLi6G/lww9q1EYy
+3F0dR4ciqN8meMnGCbl0KhXCn2IJLp3MabaG4BmMbdskAGoqd2P3lynhbOnjQMBV
+RMcXFWqHPMfpAB4/5RM3wsgOn3vn/eDNBWPbGiHk297EUxGhooVmyb+1mbVXuNDE
+8S9KsiLus3Yq0vytlUI6DoPZoTMaO4GGJG4aOUw0abK6zPfPylzDaFXoryTaRhhJ
+lb4HONVT3GNFOT2Ob+ntgFx0I0cPfKKHDqJhcZl/CAWUMNyQb5/+u7uybyBGHzJw
+fydRH28FC9+m/xEAEQEAAYkBHwQYAQIACQUCVJDosQIbDAAKCRA8Co9HRPNzKJQj
+CACofWbBHPEPNj5mqVtJf/HuViQYib4PlIZKvcKsl2TVXkDdARzW38MV18ZDKUm7
+XECp1BPST0pwKvf1auq1/25X1BOtNC9FIFs8649K4U6RouDbXPo4hyzB0Og+608b
+KC8MN311Cqth+MuWy7rHjBZytNR8CW6e1XQBxJjW/G+1SYRM57g56S9IoPiTMDsW
+8jMQaYyNY7/Getddzfl4EZmjiiOysN3FQrrwF1tUGczLaDiaTO+db/FEGJpzBVmW
+WkxFGLuAjlkSPvBW+ijlTMnWwTnd3Ps/iBHWXLb2StrDV2vmhVln2gw3uR1qML90
+iwdK19eTAhhc+QJ28/SKBcyA
+=F4/Q
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    BF984B4145EA13F7
-sub    84761D363E7B0FC4
+pub    3C27D97B0C83A85C
+sub    4BC7B9A81C39EBA0
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBF7rgogBCADU9OwoEFdIgN5U0JU5pI7s3T1T1LeDMzAQ8l2Hq4jFrhnrjcEA
-ieDSut1YIv5NTBoZv4CrklaKvvQNUXPvKrFImA4OKhBodKV3wsq2efCATDGa1JAw
-VEJx6nJxxMsCLCJvmZsD+YE8/DIBI6jjnjh8jagZVkxkSRPvUIxlZCxytIyqXI0t
-O8pLh8+8p5e0PgGb9OoszxEQZdBavsixdpe+0feU9cz0l0jJYx3W4ErZeCGGwNat
-UUiW0ctb3iz7BkNhhoV9zepxkSLzCf5zBeyA+WfD34028pAfPpyAfDYXF4x55sVP
-/3MdWGB6eU6KzPG2/QV/6or5E+C1yCMrnMy1ABEBAAG5AQ0EXuuCiAEIAMExiS4A
-u6FPSlMyjCaT8EfxP05ey79rYSSZd/ixmqyVzJkXYbf/SJCBeX9+NtWU3LEuL0L9
-WXgAA9Ys18NaJzBMC4kiQJfyXK6Kak7sUfZWWvx3Ad3It35X4svJNuR9GoqgsOvC
-D1SPgK7MfTcAF8e4j2UUqgRnjM5S6dRa6AH2s3bCj8GE+YSH9Ag2osNcKBgosNiv
-w04tYh+sjx8W5ehKaOEMrBDO8OMYVeiIEOvBIjsCZpJgAnOBPh/7zIQ72tPa9Ou3
-nAWBwdiPBgqv5FTIVmHWMfAJKRRCW4ri2hN6toHGrjJMgobtwW56vTibb82EGLdY
-3BF41DQT2MEiM1UAEQEAAYkBPAQYAQgAJhYhBB0Ki153xninxyREWr+YS0FF6hP3
-BQJe64KIAhsMBQkDwmcAAAoJEL+YS0FF6hP3VWoH/1Uhih+Q/iJIddvBatWdzpgO
-e03ppK9pCWZ2KepukILbR8bpX3cqUiTbFD3W+ybrrY0k4Oe9hXcm3re0N2GAfEWf
-tRknxXH0TMeyWoBlldfSM5DjrljM88XAIkk/T2wcARv1PC59IIZGKOpixItF5Pps
-YII4YzlripU98sXBTSlJLU1/UZaT7XNOZ9O1/PVxADpVIeH6MVdWh4W7AV/dYZ5j
-d31NbXDTtyDJBUYoiq2hu10+RNoqq28WmJQGD8aqIuKOpeBA8EirLcRoDGELSqYT
-lQyC8nl8P5PgkEZ5CHcGymZlpzihR3ECrPJTk39Sb7D3SxCW4WrChV3kVfmLgvc=
-=WqT9
+mQGNBGEdX1MBDACuRDzoPMh3CyUHQydFo363R6OdXqMZ8mJQMdysIJCXOXZGRwUC
+uyPOUfH6uSG24RU2zvD72D2SGAehQKLXLQeN6XCt9PRAszP18dJADm10xgkXJm+G
+GJm69bRYP0GIskQI0D2hXoUlSyXFKZa154pkVzmeM40UXo90FrMC/YjH5dLp7uDn
+QtZbsASlHiy7lXFX0IoJHSHZFppmHcW2KOmFfKwgE9dpku7CdTdySY9BXiLC/Erb
+l2WjwzSDEkQbnq6Jm3/wb/AXxDEu9H2SE6kOxrERqXBfc1ycaEsJMxpLxYpk/kGz
+U6YXqXiOla1SYC78/SnSV8Dkj4/hN1/XtFmkmLUn/WgctmPnsE+fMN/ALXrH2OE7
+pUYLTy7jxJ46dChpjIPJ6Tp5z7EbxdsXR9JwLFQP+Fyp/anqLO/uLkZhZGhI3r6t
+lvFyZW8zoAuf6UpKL6bIvxld9SDuEqahbU1RcLsK/7Lwh8gFYXvq6k9siV2Fs4K+
+UWyVrn5cdSMErMMAEQEAAbkBjQRhHV9TAQwA0zBHsAralWNrZBdCkXHvNI0VqeJf
+Ix1c6AMqFW6FN73153uan6AYkpeBSWz9iHgchZY5UXgaKwx75eW+89X4X0SBU2Lb
+B39584+VDdjieynrW4HH2Fv8VJicioyMYyB/16ERidkIPRAREN3K6SuDXRkkzIZF
+LbHhRZZ6XByKDXeAZ/U56TPgsvYEsdFoj7vn+44ZP1GaAeje5v7nqXiHB1lNrpFw
+T7NV7YQXSpkqQJ4ADaL4jzGHS7umGjY5/T4dy+43qTPIrDSakHFGElfNfW5y46ta
+JiA+Hv4BowILjDMHska9hXM123CCuUS8ZQYmouYleKTCcfp34xxXuKRNDJgY8oiB
+sjXokdCoaRhdcS/PrlQvWfCA/D49XLGCeXdC5veOeGJF9W5fk5qv8Bq1vD/jnapH
+Uf92VkCJ+aVqynf0pPTKrctf0fNsttstGrPSGg+RW6NnQ20B4zgqwZAYME+z9w2z
+jmmLjm78BRJ+nzVvgll8aHy5bel56OdSldK7ABEBAAGJAbwEGAEKACYWIQRvZWt/
+a/sjjTis+B88J9l7DIOoXAUCYR1fUwIbDAUJA8JnAAAKCRA8J9l7DIOoXBx7DACt
+p4W4buVzQKYLZM0Fxucb8AgzJyrMU/01n4ys/hHBLNlCHj/Ar49PPxJ97M/QnI8q
+7yqNWOXPGecU+slBmK9biTHtHnaRhkcC/NhZsIwPNhw0H6QGGYi55VSuUPqpus3F
+fPBQ5uhGpSCy9dfux+9swNl1ZhMj2qO+m0flVf8t1JWLqTPs9giRTWAZfHuGGFdQ
+g/I+3LMyqmcphe/ysTlashiLyusQS3x8OpNhReXjZiyU44bVO5F8K+CZ28404OZi
+rg/TV/mtrH5t5A5rniev4r1FBzLTaqEXslSrvGzZhnZyKefHNL7HMiSWe6AkJBOu
+MNzPX3/PKRjhnZlLM9wpDSpG9Z66cNDDFzUwtDYx5O7gbLFib0OrjIz7q0rhm1h9
+nWky+RZ+dRuNR6HV9OlPcS5OizxbdZ9dgjy4fUuMK7G1gXyifGEXKJCXFW1whs0n
+DOOaC87hGOpfZWMBVF1mbtI+Mhb6xY5pv4UXfmVBNUZLdT8RShMJOwemBJjUkyc=
+=f4Sq
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    E93671C7272B7B3F
-uid    Rolf Lear (JDOM) (Used to sign JDOM Packages) <jdom@tuis.net>
+pub    3D12CA2AC19F3181
+uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
+
+sub    575D6C921D84AC76
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+96Um/Inf
+=ec6I
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    3E3D777C909A447C
+uid    Dino Oliva <dpo@google.com>
+
+sub    7ECD484BE871E4BC
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFhV2aoBCACyHcEuTUn5nVo1ODvWvgBgV8b6Aju4cVAhMNIvAdcOYf+N9Rgo
+Y/669/P371uN2hc4SxJeORBjHyzkAX2sJZQj+FwdvGl60YX9Zv/NQaTzC1WFMRp2
+rb0QGj8yia+WA+If6hatbZmCg87CtDVpzpPIZUzX4UO+DRQEhezflt9uZ4YrFoYq
+PmbL7znqm7/3kpenKrNoinGnzFG7wnOrDfMrBrZgL0Vt95zvs/PBTyE2r4GWCNms
+PH6n50oTck5Lif0EtnIp26o9+vgkVVAFcHLUDy2y90g67j137SNnYu/47FD/rS8R
+A2Y8wRd6lXXxI/n5Wyj+P0Vai5zq6BIFPMbpABEBAAG0G0Rpbm8gT2xpdmEgPGRw
+b0Bnb29nbGUuY29tPrkBDQRYVdmqAQgAuTKXw+m5HveJjH7uTGdkmX37rkOX7Kl6
+cyPutq21tbG9cGhrOplTJN9lDoK97km2YOs16SGVlKTEQtJ7CLAQGRLW1qPATMlW
+6gJ5+KAAY1GFej+DZOLYy+RjxxdT+gDSIXt8kQwAlETwSNgymp53TrU1dDGPMjod
+0AfFbawJtxp/gaI/Sb+MkzLRS+NA7g1fDNAsy6twjxwmL5lvCUO+JMtlG8vXlIoi
+P7N6hXk4PYzYFCI4JR1H4aNhIBk04MoUngJj2WNXfPJYQef3DqAJrzaQpuiCdQAq
+6F9GgldMHyv0ujHpA2JBikcxlR1rdUdo2Yqnc90pd5KB6IO4TfN8twARAQABiQEf
+BBgBAgAJBQJYVdmqAhsMAAoJED49d3yQmkR8SNoH+wRfWyXUFPVDNN4UrAi5HEY/
+Ca10AGuREkzacZSVz4dYtofNOAxxRVfOAoZr1NUECNvWgyxIZ8ZkeQi8fGN8uS3b
+ecIVAWmkji8l9jDRpC3DPs/g/7wL4A5VGzvp4GdD6jHk7KCVPiEk1DzRajI3sAnt
+mpTKL9LNB9LpP4NdWiFA8TPMEHIgSqMuv1Jzycngjd0Zr9joSJvhIU+j38FvL/F+
+l/ooa7TKpRv6f2eAlyls0K1V9bUha9KhGsyjXqolyxHZ25Gc3VnxEKIZS6R5QrxV
+bnXPmd/SV6MI4fBSrcrNgR91iH9Xr1elbwcAFltomc9/3/7xXmHMaEfaxJnY5mk=
+=6xRw
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    3F00DB67AE236E2E
+uid    Pete Bentley <prb@google.com>
+
+sub    6B7EF7B18190F4A9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+8NDEEKe1MmtJ2sOJrXaEDaeIBbaVgX76
+=+Uvr
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    3F36885C24DF4B75
+sub    97859F2FE8EAEB26
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFmfSwYBCADdZEuR8cs2ejLLW3+Glxiq15rVbHbxaWmmZApGNijFro/LzFrR
+z+99N1mnA5+Ar/yKmn8lsCiTWukGQzWbdH/QSRUdyHtzxbCSeONdMhdKl3sJY1h2
+jW28oYL6iOMtNYe8qKoCrHRtyTl7oqYtYuhMwdNedGrkVWPrInmg0ILUSz9RufCh
+6KW3V3eAwz0LbckpSi9ZNyCNssjINvr6bRf10HMucViAB0O1DjrwO6aiFnatTCyO
+ig5MMZjgRPKjMASsPG8Ri1xivBYS/tpgamQzq+htWkbEydNv9+g31S5sN0pPw2km
+e8SjKp3C8RkSgz+dJz+P6tQrmGvZNs+pm2M9ABEBAAG5AQ0EWZ9LBgEIAL3j10Fr
+ODkE7yVreTlYs7UrZGaJwdx8stENYdHHA7MmDIMkVnjAOkzAwW4zRXdtFHqICLUO
+L4ZRnAiGuyxiwvxXM7NuGgCfC94M2w58xf2JREaCmU5kII/O3KOv60y8+QixFZl/
+c7p3YOGwOQEEit5445chxYwM88Bq+LgkXAn9zNnZbOyUv+E4gx17khkyZOXP+Z2P
+d606+KRvENLlFbrlVaJ7vzGiLhvIr62I4g3hJj/ob5nXT2tZSyMN19bJOtOd48R6
+NXFDmVC3uLWBgqLK1UgV5SylyKg6N32CUdds6E43DHLVUipawknN4QDc3s+ok6j3
+nN688afjFCLQVE8AEQEAAYkBHwQYAQIACQUCWZ9LBgIbDAAKCRA/NohcJN9LdaVO
+CAC7wk7tKsSNDxLhcq+Oa6TrE3JDQUYx6xlVsw0ZOq+TIbk2D7S/4phY+YSUUqWZ
+rp2vpFlszbcJXx41+s/ljfNnkMVjoU6D/A3R0az9weFfmq0J8CoJeP86CNxCiRIX
+d1rZ6wHlc67QJZe/aaYzxOO8vkzkeEiDaXjvmaSoADucbF1c6KjQms/yJ9nFz/Mk
+FPRxWntD1UkxNLh8UQZhIZFrAmhpgdDa0xq0VCJwL1ZLEo+cm6wKTZb6iRnSqPbu
+fwS6/GYF9IKUp/WVQvhZ952mwzfrz9r1PbTg/fOo+MOGywdBZpEEPTL5pvfrrOYg
+5q0kixiYviNzHBn/YKmH2ibE
+=xwpz
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    3FAAD2CD5ECBB314
+sub    3260CB2DEF74135B
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+xZG1NzW9unRL1j8/o6QtwZ1S
+=cP6l
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    40A3C4432BD7308C
+uid    Michael Schierl (Maven Project Release Key) <schierlm@users.sourceforge.net>
+
+sub    C0B9C2CC3DD97C16
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE5zrtcBCADFfU0ugIGUCM44fqPJKrsB3TaDu5EpauvFfYqUfyookzMHSKtB
+4YqBSKzBEiZ1rFB/KCn7XJTh5epoCau4DsG4U0XZjsx+esDR4ZtL42LEzeMTuluV
+9eybw5EvW9GnvUrSOq4U1xFdQgCmBcRBPpLrP4hWUXgNlRTEpgHemnDmZIV7Jcyx
+KZYQFoddPbUbIOutoMecl5flaa5uHe2kHp+R+PJ8DlQIKa7qsxsAwZhuamfApX8M
+NYQmY/M473IVH3ByD8bQ7uc9HM/0q3f32KeEVHEYTKLs4/wTY5mZTDxndQeMpjF+
+8+LHbr4n0zDJERJnrOzgOoCW/bFa8YQv4ErhABEBAAG0TE1pY2hhZWwgU2NoaWVy
+bCAoTWF2ZW4gUHJvamVjdCBSZWxlYXNlIEtleSkgPHNjaGllcmxtQHVzZXJzLnNv
+dXJjZWZvcmdlLm5ldD65AQ0ETnOu1wEIAKOf1gsFUdUylLyP6hzc4RAgoFr2eHDo
+a3w49fdcBflq84QSIjGkrcLggLvAP4eqJnaUhJh+8a4CBRg4FrW1bs/nhdC9rbzF
+SXkbr3oG0RafTcTtGuP2JzoVXifY5OfNnia2fHIptex2hJofoh83yCiU36MaFgQN
+lorK7/c+K733aEk4KBzMfAU3JiKrKsSTE92Vd1yh4pQ9gMANAPzPqMfcg9XiIKos
+8d1XDQtndQSWccBNs5EZWMct++XPYOdZI4bwsmj+ayuJPbJOYG1T0HEA9x0vBwSC
+fGEoyq6+ZqlCrxcAiuEqpYMUlPz3ZONUfC/C29Zb/0Q4AuZQPug2fvkAEQEAAYkB
+HwQYAQIACQUCTnOu1wIbDAAKCRBAo8RDK9cwjNsdCAC12L1h5yiApA8v1nJ2YEGt
+CHciX9B4J9iGnOHeU6XTquPmCgzANd65yLaeA90E//CikAtlHUgiz7+fGyrGbXUD
+zS9yu97YP6L8Gfha8UylBr0Hm1bIFuNjG2C+SUU9DPfdeqd+Bh0ygYwnB6DCufrb
+B9R0ElvqUDttyiJq9m1k9gCSELKMLjV/1F1F1XA+2k8PjcZKDgAXrLUpu/boCcr+
+8ozuTBTyxcL21w1nW7VignaRRt9DfvHlsli+5W/+LpSuq4XcaAgcX8rikT9YEsJo
+UOXnXPP7mF30ChAY5F7mJ9BTe9RZZmnjA2cUdtHLvchd4fiFbu191pbeIk/BSf10
+=hyVS
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    41321490758AAD6F
+uid    Groovy Operator (Groovy Language Continuous Integration Server) <ci@groovy-lang.org>
+
+sub    01F3A913FB698736
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFLmWO0BCADfxkkFnwj5uOALP07g8yArQpu6zbNr+5dtDvJe8Y51V1leb74U
+Eh4U1IeosCRdKUCg0XlAjDmjrUkG6W/5AMUZM676JVHL5tVG1F+dsKhCrFOZoMHj
++oLOMT7+159maGVlTbp+CarWjp9HWguCVYYAgmP96EZVILG+U7iFzLveEDHmWHyP
+QgZeJPbiiZPEPVDYll821zajCsPj6qse050IIiKfsyveCk4j/eEm2EtBDbQeI8Ul
+Y47TRSBvrtUaUUFe9P6uNoNQmbasyFdD/2yKCoZHCMhAdP4QydflybQdDrF9p7UF
+kCRk+uVIyxXDSn/XMHNhYG09+sy2CoQynF43ABEBAAG0VEdyb292eSBPcGVyYXRv
+ciAoR3Jvb3Z5IExhbmd1YWdlIENvbnRpbnVvdXMgSW50ZWdyYXRpb24gU2VydmVy
+KSA8Y2lAZ3Jvb3Z5LWxhbmcub3JnPrkBDQRS5ljtAQgA0Wh7L36Agn5UEoNg5kgr
+m3uzQnd+aBhqwG3647Jytn9SZl+PcjnTaLidhW2PB1YlkWnQsuHgb4Fru4s11NgS
+JI4SjCNzHIGva29yT3zAMYIqQuSJ6yuDQhQznpkYGpS9z6FqV75sqhNXf4fBZ+Hw
+i76lE8eU1FQaktOcDBq1B/Xewm6R9EPy9cp2Ph6b0K0yNtNuxUEt0lc09HNlXvnN
+8fUM4YdPG8dgoNGxUpSYxmfgkT6Annnl0hjHKCNigHpXmhBUjLqG53f12GGqY94J
+ANjVtS7hUlAFUlmHpYzn7Waq5zpI60n0JYnjM6TuFRtay1qU6SeKkDMggxcPjXX4
++wARAQABiQEfBBgBAgAJBQJS5ljtAhsMAAoJEEEyFJB1iq1vAZYIAIzyvdma+vU9
+m8vrfZ7M2D8a4Udzl3hLYmgQR5Z6DypMsBOc650vi60EMazVlDQXZtsvE70N+efk
+O7HMEKHg5Sa1C7tBbNKpkIB3osIXaFVT/0XLs1PAA70kppNipKRS9xraBEV7n1P9
+thithugcgqgneBNDS9N7nGrrJjYkAj7C8TxuKHB0Y3AliUZ0UU97OSyW+oDFlh7I
+VuTNPh4eYCwsobBmX1lNZWmC319HR/ASDOEt8DZSdJtuWrwtRVmdorBnuAjkcT7u
+RakpdpESTALYfjjTLQlMpT/rfU7yor59oU96nLptJ96PrnnIk10Ps4EOOB/8ssA/
+jfDQGVY4ZIY=
+=iMij
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    42575E0CCD6BA16A
+uid    Taro L. Saito <leo@xerial.org>
+
+sub    47624A56526BF2F2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFAZ8yMBCAD+elPZR4dx7RHLErbQadUXmxxh15JTZ7A/OmARW0ZA1kbkRven
+4b3rXQKtWhZqxHh9Vb1FMgOnrbOi9984J3REJzLWEFM+REB6GJ3/ZAQvaAmrjDtV
+sTX4u2rl+UaHnrUEtvzS9QpGwkf8Mq5ww8BvKF92fMIJ0qZ1rO6tVtlsAcEEx3E/
+SktC5rXfOdkkDLcXHs56KZPJ0BAtWmTk2dSLFumSyXB/48oF5TgVvcfwGt2nFkBJ
+2TxoFzzShNqh5iRhuBSM4e8IXXziqKJ48O64qk8xhB4UxYnhP69p7hsj4t5sYhmF
+Za6c5rxJ01yNG/C9QaElKd2bWndoLDHIUK5XABEBAAG0HlRhcm8gTC4gU2FpdG8g
+PGxlb0B4ZXJpYWwub3JnPrkBDQRQGfMjAQgAwAt8MVhTzjh73/DOb/uRHv+/htKw
+nN2a8795Fy5mfpDhQr0YHSu83qUfG6VxFbAo20mkRLw360Pi8gIozql6Hd1DrI4Z
+UUIdG6kYR6CE1aSrWptvNcw2Hyck/eDUupcYoHGmqZhIyudaPGiXoyjDlqU+mWeJ
+Wls6Nq/8UX3trCfYVIA68Q96ZloKkahLYi5ReILRxgUBonASiEpYDN0fN+O8tZDA
+oa16f6IRU0+LWEkJxZq6Yog/W7KxTXlgHaJDQnskm15ZTCtxGjNzAeRv2YUFzbEt
+8sSr2pHJDvd8OoqD+3tI79jtSQpMFrIhjdvIGqvOZCCM4IBTbo+in51qDQARAQAB
+iQEfBBgBAgAJBQJQGfMjAhsMAAoJEEJXXgzNa6FqEJQH/jLVsHAyWOs0qE10eB27
+5WPe27RmPsnO0wiG7L0wgVYw3gK5mRUiRQyKcqEm9+pP4g6ITSiF+5TWpVzU3ISZ
+0gc4HCImE/lsHPZfwU586cCH97A/8PzeYNnU3nHaXUTiaEp3R7+3/qgpk11hrwEp
+J50QD5vFwMhaTMkDXCQ5P/9NGqtKB7LwBV8eIhkLVIfcxag+6fNG60HJ1epd3AOc
+tIqokiFghuuLC04ipOsCjQc/tMizVERDRkrDHXSE+b72Z/KIO4GZvpvHTegod3Xq
+EAvR6dLYi6ZDtlTCEms4kQ+hLz9RRgJ1Oz2dxgd41c9QexbdGGXDw//qTpi7wNt+
+HL8=
+=0Cd5
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    429C8816DEA04CDB
+uid    Taro L. Saito <leo@xerial.org>
+
+sub    8A57131A07E0911E
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGB980QBEADLBOfY981RbUf7zI9AoXcxGignXkYbeSvxIMML9vAbnhmuHwa6
+h+81ZTY2XK7Rz211y129YidPykkiLX9mY+OWvJsj7dTyVTcIm6MU5ETDvovfmKWg
+5sJRrANAnkZ73UVJIKTQC9HonBIpiPLmDEBfReHkNsXtYqS4fyZO5tkjy9ejaw2p
+5qpOS9WixIvZT43OfzH+8O4ecmDrOZ20azogcWqLCQ/ZDbfnyHFH+BvA8bn4bS6y
+304655N6cxDbShHrLWP6erbGozmLu/hVabCMSJgGRRb8NcUzJQ5rwh27SvKyMGKE
+8u1ek57d2wv2pI+sACBMzYlrP1S9MTcpUsQ4YvDQi9Ic1QDw7f2KkEsEnxs7h17h
+AhbBwEvNWqpFkKjI4ApYsM+/fPo0/lsT0lskjKrCnoEL9+sLKDcp85cR1dPC5ELf
+b2bhgjqccIk2gASrjmTiryF7gUiMTgZVU5PF9f0+p1pGqC4GIjJOf/JGhhGEyzVt
+BNvJWUgImqWbSFOKWfvnmdjZyULAVouxrrxF1vPN2U7KFurmSQV6tq/1Uf/qccR9
+/uhEI30ypv4OrVi+8WoVsEamag/AlnRLFCEjdfB0oUy7V/lPqMxRoxmhiTX+cCjM
+QkFfcspJt830vwct0pi4rtYt9pk1Roh9tOKh2UKRDGL5DE3rZbJYs+6TAQARAQAB
+tB5UYXJvIEwuIFNhaXRvIDxsZW9AeGVyaWFsLm9yZz65Ag0EYH3zRAEQAN+bpqWu
+uIuOsMvAGVAMhrIT9ILKJ5mV8Kx1wza1ycUXx3OccykOKaR7s2Znthim5KLiKbr3
+bQPeiYBFUEcT4koBwhyEJE9FMfRm9tXHtvN2I/O1z/qy71gno1slLzUyTlzakB3D
+p7Sp3pnD3xpXKN9x3wPLja64F9CsdK5hilfLySf5ZnvOi7t3QJWyS96XwaGo+yFj
+hXCbxoENevJ0QigRiGWGfNBNSZXKVoctACcpImaRYIqjtRSQfUHa99NlcAhU63Wr
+7luRHzYBP3kmPknMp+id6h5d4jAghuP6PvLUUzjh7dUOGNjtOw3i3I6rMxFnn/oZ
+xWkn1mezfmj6katVrTYJRAUR1kWsfV8XzgyCXJ1GAclCwW6o5S3lxCBGlcwCG79p
+7H5jVgGPJY+pEW0iokyp6MtFnZIYDFBY5c6tbyclDT7aV4uwWGBs6+1hEj00GbaQ
+9miYeeseaYbkRoHCM67TFc8wSigggJR8I+Wqaidck0g+ballenuB4n3NXtvzeJaQ
+krhioizhQzvxPWRvYRQeC4BH55LuRzxnTArGfSf/V7uVPn+GWntlHvCf+qOvdIBH
+pGN8h69qQPW0rXOPjAmA9aZOetp7LLOs4KrvPi00aAZlK9KspZyRviHfmJISzqZw
+ARVGvMHpr74cEaVMI5BD+Kz/S5QWvjI/lHuhABEBAAGJAjYEGAEIACAWIQRWtQXc
+iinGkTikMLlCnIgW3qBM2wUCYH3zRAIbDAAKCRBCnIgW3qBM21ZfD/sHaK1wbxqA
+sDtL6VapwpwJOzGKGFYjevXeXIM16eluyNlq9hBvumLkXSHcci9yzHWjREKU+nLI
+GQiwfmjEB6ZWT0k6W0yQ4pUiJhsdjaukdj4KGQv0qIjl1YYjkYw5PvSNDR9mH/DO
+tUzpgTQLYis8RuQCMf8E+8WiAbA8uCFe/LQup3MMIfKCUWHtzCWcQ9zGm5hFUl+Z
+xKcuyMNkt3q798rYGAcWaeaCmRCTw21tsRedcUZVfr0JTSCwFXfiRz6lTKdRmCk3
+LYG3RBh7XS54eXMtl+/JdZlk3OzNhqMbGv1wSdJE1GyzbqTHAx7BhjNWgbuxJUuj
+YLMmG4I17P5LXiU0vS1bMNBhCbuLw466JJOTfgtDL5pNjjAr9AVTyvgpr1JEP6cX
+LWqrSXoI/YdOAdKf13reGSTA34+6dHtbCB/WLZhNq8re4Ft9Y4OlgINAsWGMmiOd
+sgCWZUsdoarkFJvzWmybtRu0wZKmpGQ46aIV79pilPvolzqgkOSsGWf2TsIvuv4M
+lMobjCzLP67zO1IsTByHv4cQLhwZmZJV3dIdPTkJ1Kmg2rqrgXn+186ep1tbbWvA
+WAXb+JKwWDWNsTVMCOBDU1Z8680C7VGh4VOF+73p1Br4tWpR0AjWsL3CABlRbEKI
+cHTbyQzX3/0LQiL3A4W64yIUApDoir2W+A==
+=sGos
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    43203BE58F49479D
+uid    Viktor Klang <viktor.klang@gmail.com>
+
+sub    1364C5E2DF3E99C5
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=JZti
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    438E9634A2319637
+uid    Constantin Rack <constantin@rack.li>
+
+sub    2C8E4A350000730C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBFQMn6cBEACn5RegEd6pYnrIwFMpf/SKP1aIp+rF657o4zP2eQtCyU2Kxiyd
+VXyvUqIN9kv8exnNUOHnjQzUyVFmcaYaQTxf6D+DVkSlusHk4yq+6I4K7g42Ghvw
+okUldrVhQUTyZKpR8CUzEOsdhZJftMzxZp2QCHKuRoA8QWKGcbUrp7SQ91uHRxVs
+56egdQcNYiBX0QrxrYaI4lFAdpUa7LJNrggk5AAloqalD/fWskJCmBp7NNSQWNT1
+oOk0hEPNrGcETZxvYXHZ95wbqe+ZXCBydk1UhJnLSmqjmEufYyHdVQJVQCpEVMAO
+xUonaK8VHb4Trdp2D0V3ZcKNhukdllQL7Rv3L34tmN2fXPBQUU6uisKbMHK4ZdQw
+weCITIzfvLcIppEhhOTBI6RsRJtxiNMuH+DoeDWl6CoYiKleQy2T4Ed76sPDBm1E
+NuKDnGooal7QhzSpUrZ71fRfBWY6taEegCns14pBRpDvQKgAURpIOIaD13K6tngY
+dQOXyZP5+nyc+p7Bo7vVd1+gNbdLeYBusntf/UqJFJnJPyGIjcTrCsELDltl1Ifg
+Yz6gfzcc/Euhh6SJVciv/bItQaViaQIJyIuXsPKV4BtUgTisZj+5L2JGa/LQi5bJ
+UZx+hz2dHThtck6I93eDEUya5Vk3gRlex02RLopAKOtr/9nkDbl0D4dqowARAQAB
+tCRDb25zdGFudGluIFJhY2sgPGNvbnN0YW50aW5AcmFjay5saT65Ag0EVAyfpwEQ
+AMEgdON/oj/4Uf8sIBLwxd75L/wm8T+cbZeehTUYaKuitJhJirgvf7+aqa+cctsa
+IBNCogQ2onCpjKaRlKooVuniBRbR99ocCXoqoePAMPs4v+Gl/XF2prjo9v31REvk
+d1/eRi6VTId0G8WlC6wlqHqHpxi8wTjVs2yuJxntpegoI9o5ch7QS8CoazsyDEYn
+dCtZK6ElWxmTUXFaFUj4hvHvyylDkWDfjieBUM+bZm/e0pqMRG/hWOAuDa9BB0q9
+gH/lUW6sNceuYG0nGY+rDtMcaW1fhkPWAZkVrjJLySZO/cV9P6DMU+1zsUmxAMJg
+mlpNWdDxdQq6b17pu8vWm4QgwYPucY8QKed3+C3nvEnFdx5Bl6ufKTA82WyvhmZR
+XDDKYuDct7vAGIzlSp0pRsU54RB4F6saXcDhCR1LfMASZ1yUIkshayA4YV41EgRz
+KBjkOfoShHXW1Ekn5ufvvSMJlfxWlqHinppA1k7i4GRv0XapGLZjSvulLg78owMq
+Xqd8DtShHwtHW8a7kzsqIf5YZpN113YvspBHg6QOk4M2+tdZKUojmQ+18CtGpJSh
+d5/RbD+Y3hPSzznY7aJG7ANPZIKOQMVBxhoVOJX8NdHdlfFW/z4JBj+AVi6cOleO
+M2oy5QAAQNiGotNgkoNkP15VUJ7JoWEzyVmvstj46sZLABEBAAGJAh8EGAECAAkF
+AlQMn6cCGwwACgkQQ46WNKIxljdbaRAAly8/0f28bV9FXjSwWiUv8eYf/LifiKvu
+WAsigbyW/upQANfOByoLq1pY9zWvm7qjGKdscbLMsU7sNEWLo3MMnCXX8SEIzfNo
+tKJ6oKQHGVLqDn4bPrS+XpeuxDh5F2+1YUpG90kDEJiXO8m2uwzpqsPculpQZx4W
+heeAibe67SSsYvCkTnSBriywrW9ghoypc1kwtVqPRE/NQhJBpg78zQ9jfqHaTSUk
+QfVKmHs1ofQLYA84s827qNtu0HpVXP/br3QSucP93q83EnrEB9Ce13cJDkXMirYO
+aXqvdaPH+D7g21+XK1eCk3Xsu4GqwpE/dG9+5cDMsSn5kFoHrjt0FFYRdSVDKJGe
+qYc5ZwHWlMB/NY4Ckg/OLhxy+p7sSh3hhZqY7fAem5otK3bX4lyeciMRbhJ84FmF
+JaRHQJuUB0wK1sOvYONi8lTtuxPJDiRjKjeOCtjuAcOtqCpuywIXAADB0w/HAtIs
+MURDnLjtW+THCqbVnQI5viQzRDq65753+P+d1sxnIU8KhNr72EQpWyFWZ1iaXDsa
+jiZwfUTfKBw9EP6EvXbFmEDeX74thDh/TmDEvB7kboNYdVub8zjLdOqlBBW+FdiA
+rG+Z+U8AivDmzb03YcjKCFWUoWlaQ9pvl2KvpEcA/rBW6m3tAIsqzlrJZHq55y3/
+dptoFzWpL0U=
+=I5Bp
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    44CE7BF2825EA2CD
+sub    E01173141D06B1BF
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBEzQQMUBCACbwbw7tuTWgwPsDAdQTWGO355jP75oBLHwGgEwV+OCKtxkNXNw
+wrJqXst83vmD1dEJyHflQww+d+Olj90IefQGfR+K7O005C2nky7eNGIomxaP52Y/
+90+tmw8qtsI4nsPWPuVj4WdFvlFgUwIZ0SmX4CauVzg0Ris8f0taxg7PH9zEvICs
+G/WAXdB9em08WDD6ruhMAvDF4W8Yy7mpGmdWiFD+B9OC006tv+GzYAvUHRFeCnnT
+SoKRiBeLejW+t4kpdMnEfC9ILAYBEEjNYvBIyPdPKBwNfy0yjRebsUf0eNmjGTpk
+VPlfofjVaUaOZytUOQvntYpocMX+377DGQIdABEBAAG5AQ0ETNBAxQEIANp35mwg
+ILWWQI36F2SyWFTFF8zupjzqlcF4Vx1Mjs2rQYErv1qs09TJfO+uxPRAva0fKik9
+PFmZ0vLM7UAveZgaknzjTQveOaAJuT5OjudoyptG81ilHO66+e9RnuyV6gSINnt6
+wnq4n8KRPoEmI/nxMhvmBCPw+YmxG3ZcU5Zko4GtjLA4J01nag7jY+LH08qFfPcK
+sADmx7EtCRuBcXgQ202kF3o7BjULcLV3R8vni3jp5nljH0vJG5USSY2ZR1bFiLtT
+CMO8cm+jIuay25iWil5DaejASIXzbzTtSYg9Skxet29AWjlrt1+zKZsMSLPbKJ6q
+hdW5XNU4Qo9ycx0AEQEAAYkBHwQYAQIACQUCTNBAxQIbDAAKCRBEznvygl6izZwg
+B/4gOqGHc0Cc165PZggwbf1nyJZ+af0QiKWasgoUzo4a7OSIISmBYPGnW/VP4EMs
+aNEhnqWK3Tu+cuidW6z7MWHRsqLcvYUKeiZE2IhnMP85ad2S14UOHE8cbkLwfIGe
++rIu+zYpzyc5bcRYqeLvd5Dk1H/eW0/hsadW9qpSWQRGxWPEsMqaAhiret0ntlGH
+2igswZ7SYNYLNtK78wppFqqFHfFvnVu1XNmiTDDuk2IokPIGRjeWO59eSR/kotg0
+zox4S+CJbRdQdPq2ofDNqKCIEtg6y4yM+dc7c7n1Txk53fMBMzXfGnLGfbTFLo1h
+pYdC5sepAZA1XWLRgZ3+5+vD
+=HSWu
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    461A804F2609FD89
+sub    8067ECAA8D58321C
+sub    750F9A735EECF640
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBFkgff4BEADQW10I1gEirYflEkNU9ukvBD/UFzsNxtKKxiDB58O1j9/o8bJN
+uM56B/skfFg1V4Gkpmnf9sJyakI8jHIvZ720dPHB8nVRBKV+sUD7hoI2QYVJMJMV
+gVEvDfVP6wGn9ED8tPBIcWyNzZxGSXNorlWLnxyaCja/CqZw9OWnNkpR7YfJz3bQ
+uROJ+0jxA3Q5U0MN12oEe1Bctma8AlKd8xKlecps0uaRLx08LGjkfBrLHt0xkxMd
+8ykIdB4UP4vvAUQ3vuPErzL8ScUVZbjxN9k/oilRjJ4ELPEgWKCUs2RejbPbbnzv
+fAwxwFnGr1lyJ1k6Mgx3VZojE4PXHVE4xjGJ8zp16qtAEicYTvZe/E5z+AsfQa9U
+QrOc7zrIN8MXdI5F5M5ZqkyAKsgCtqEto6oCT3OxYrsORRHhGr6mynCvJDly4dgB
+5SP3WfX8CBX/T22GFaSRdGr45yYe3jvI/IFv98o7aIamctFN4mZvKe/si9Xfo0Gg
+twoFDuAlLSWbkMZ6TxJadGWiqT61linN3U6Kmhw96ZmpF4UQ1hZIw/hj1V74xZK6
+MfU+76BjoTbjtRJ8amy0MCNr02LavyGgdCqkPBH54OtF0Yzg7Vx2TouqWExXLJKd
+QYdsGV2THSWDI1c60gWsHtnrUVtOrnEG62FE6SaRBGUDYyp2rsu2bUHqbwARAQAB
+uQINBFkgf8UBEADP5J79GAJ/dFcxqIbAPiGinK/PJAtIw30BhHzr/MSxF8HjCm3v
+4JRaWnladehjg5mwEHCRXMFkxqtVXC1IXQFLFxRplbYMJ362awE+2GYItACWti9i
+RoVxh9Pse3/eNLAHAwbFNtDHBPIvmrmUU+/q6XPPTbojRtfLsKW6uKcvF82mZjRJ
+GtkUkmO8uMLWJzJDiDYvfXtXsclosdFn+qgGtDU7KVMFCKKUrujTBXsXIKZ02hLC
+kI/tVs5iAdEuLjk8Ig1u/3334XiyFEOUctdBGVgjgLg0AUBu75OftG4qJTMadWLe
+LU8TvnF7JQaT2ydVCyZxmI5B80xhtmTWWPi7sQWAM353oWfay3lX3cGRbtaAO1bb
+NgA8yAIeOU4HO5+zBoP8UZ3aBVArF0eSLUdEdFAaKiP7La/5v2YC5ouE5NRigvb/
+6fVkaRlTd0/8ofBKK1eMLTf5JWQz8MahSHSPzG98Q+Rfq+/GCvyatm9Hw7fGS7p9
+iaJjh4mdNakJ72dhndYJ4vIyfJyn/EI2tkKXB3K6bCm6OUkc3jyTSyRK2IkCVEGO
+qZYntPtlmZd34qoosou7UCz2MTiutypHWMezl+t4QJ5VJSqMed/qI4VLpQqg8cTW
+O4f6y6LXcto9i31Kps2Tjn8bHkuZJzkMaBFSbX0POtVAJKW2/PmtmVprCQARAQAB
+iQI2BBgBCAAgFiEEFgp6nPRiIaVrBq1kRhqATyYJ/YkFAlkgf8UCGyAACgkQRhqA
+TyYJ/Ynchg//XTvqG0zyUAA97Gn3sTfu3XAu2bIWZjLTYv0Intjnlhl9zMCspasi
+MzO9xf85sSAyTsg+MmupNg1IQfUg8IwJAVA64lx33QjOEgcE4quDqJQEj0LNLM0k
+/RxB7DTC7+whw93O39AAIodUzoLsrCD8dAByVrFydPgkTlponC2r5jUF9L0IDRDA
+lx34WGM37oktU86hHFgD2jjY2bLqThl8/vVudxeFzDYQVcZzfNkch7Mgtvu3BzMc
+AHZ4/g/QMXlvzcel0Hq0BTkTVXjuoE2yXkfYUolrXM9u0+kjTL9hiHl+0BBnWDnj
+b0bdYpRQdCC2ZDnd4f72lwa4jeSvjvZmm86YNK6fMUPa8Xr/TT0nfDDbJa/FvoXs
+KfHfLpXP8M2PC7Zm6QKbzq3QqqDQQ4isQhy8GmErWhQ1RBd/MVm0gYfaXWMJCpmd
+Pm4lzlRnh0BVygJ+d02PzS914LFjRwspyGD83xTQQxcxGAzwS8tW6ez374BSCwzN
+ImndtXV8J8k17WQRIC1XhsoVvY/d0Xpf1LTwYSpiHnW43uf63X4OYLo0Au20lH26
+nH4/qfDMphrFINJrbb1lVQ4QkjnthgAODwO8vz5cuSU0t1y7H8Fcs4pchcsuIa17
+AFI71oTmusNTxYywv8FV4/mqT8VboM/oEOabj9YjJHQJ+g/dDafr8FC5Ag0EWSB9
+/gEQAMd2uqUse7rkjD/IAHA5yrxWoQyR45/x3tb/mkqjvLiVwXeJDy7/43hfvbx/
+8c3tS6WMajd6p/1gHEe8tzOmU7MLK8Li3xJVgssOY0DO64J+nq4xdjNhrsB/1SoR
+6C3gQn6hWgItaah5DCzKIqR/DMhEl8OETmhFylULOupOPjLisLgwBQ34V304xjq8
+0xAuw4W6PhDjYxSeetGcqTOrscMVvxP7dGJHXkuy5Ll6JM369vX190yFPlsfL2YK
+lOHk8zdCn724ACxlNGhyubN+tazAkD7EbmD4zmv0dpcjuKj5Bf2lrfYXEPJlcGNG
+rihYk2x50CJm5EfgVpjpaXZBu6Kx+F4A5Ps1llhU03dWAF4Bph7TJiNytLHywrSs
+8PZP0yYr3dWEHQlxe1MG7jwCx71HEVfu0n4/DbuMlS2RiH8y0x2iBhPNTpgnC9xi
+D1pXkAVaGrHQEGHvK4SnYF4vPfjTxwroASIOryeGKMyReX1ZmPaH6aSNk1Bvmp8f
+HshMd9+fiEBCLUtzcGqiq6yVmtOKphu0n6u7fSvhvG2BNDlV2cjYdvGsCSCsDT0u
+vCl33bv4iONRLmLKVrS0o+8Hfdxbrll0jj10t1rXocRZUmsR2iYrQZr/Dn2JHTs9
+hPsMDzwzbW0ur89MqkLosyETVXo3RJTJkNLiZHQrwsfMW4f5ABEBAAGJAjYEGAEI
+ACAWIQQWCnqc9GIhpWsGrWRGGoBPJgn9iQUCWSB9/gIbDAAKCRBGGoBPJgn9iRys
+EACZxvrIh12ygAShH+cJphU5YQAUul0o4umwCN/dMclvqmcPfAJE1A5RK1+z6sc2
+1YxrxvMDTMo51/stUaiJhlst2HBtu0RVa9StchPBxyPnTJcYAJVBGLsvE4T1y0QG
+YEFfPsbzxY2JFwsnOJtwhSVjBldXdNgAY/mqz1W8RBxHrfIF5Krc/NRzJjhXAFIG
+HT3UBv2nKGvTThj/SCDHeREF1BuKdOf+UhkXYKCV6g2vwczDUmEtcf63n6h/9Njv
+o21iOCYxO3FKAQEZ+ZRk+MBK6kfIeXxmjW0vTyMueevXYuDFVmKYJPyD0OIY2SlL
+z93n54maCuAF1CZi/ZDp3sXwGTDq2YKlXxoIURQMyy8vzMyoAw0TBJsssSDJ0hyC
+rw+0hBJdNWFxf7pABccdxzLviAry4Ged5DrVchxxtXC8rpwSfg71QA2D93goVGzH
+431+uiDZUamAsgf3p/iicIJKRXM3VKUsf4S4dK/xpoVUhOCj6P5mulMaT7HKpB8X
+HoIPT+kzhgPVNmmsrlccTIxOGLdH2O9nQWpEGIo4x1SMxjoJ64uTVGKmJWGfR7WE
+iStoDQe1nmex9fvuSxSPpfAZ1ckrjewoPXfz67g920l4MDCSJD7Mg+LaBFcNskpg
+Dc1WgNgnqOol5kPCMhJK1Sq2UzYAIqi/rMkLRCh1OrdzEg==
+=QNgn
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    47586A1B75EF0DE5
+uid    Benoit Quenaudon <oldering@gmail.com>
+
+sub    D74B959DFA1D84F2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFkW7RoBCAC7NMtr/e27nrUuIcEZEJBZS3TbZYId80UNQXgYmqPhy/sfCyMc
+87eKzOalauwLbr5+VGuKqhvKrihV1WCt2+FUjOtnCf1GutpAUH9plfSs8IpRog0h
+i9IpApPeR0Q37fHhc/fSLDxoHIylML0058K2X9js/VNg9xospjvRBi0vXmNaMWuo
+qMQXXVJrDDtDlxljx78Fk7b/qiFuqBgIPM3U5OPyaQ9Qks8wactSYo9pcqIZx9BF
+/XR//WvPwQ5MEAPCkwXnNIlrePDGMule7QRRmDvNkcD8V2xSOM+fhVd3UpuCpMEG
+h3MpiaFq9TF9O1Fv22Cs4eM3mnYOEHjAGyNzABEBAAG0JUJlbm9pdCBRdWVuYXVk
+b24gPG9sZGVyaW5nQGdtYWlsLmNvbT65AQ0EWRbtGgEIANflXvzNKnvTyd0RAoe0
+9txiBkEkNqs/O+2CrdGbM0Uajt88p/qHWU5Q1e3TX1rguL2X82O7TLPuFaWIohQR
+pxJmZIAnNLqSuSLh60vR8Lg91XDsOnvUqZjoGJCWCpo7TQjc+wSKGAiLvj2M2rnj
+9dg1wiKHe24o/PrJkWqJ9CJA4+EqhwC8Z2++fi/TECmsU35Dsmw1i34c/aMX1LTt
+krSx5RlZPEOhlQISiSKem2RgwP0t5h8fwGR51bC/KPfKGESLsCxT8XgGGrmOnIMK
+A//RWKZEEpcW7C7I3vB0U9Z781ioT+DcGRQ5JhFrCjoiGIFfZUFqJqXC6aixX5qd
+KT8AEQEAAYkBHwQYAQoACQUCWRbtGgIbDAAKCRBHWGobde8N5d2aB/0WAbdmogIa
+240LXsgOQqTWelfI0a7ncxBwf26CRxZwVBjYcww3rvRaCRq0fK+ALy8iYKoogEzd
+/3qyhImSP3D/MAX846DATPTImC4EYDWsL6C3dN6BFKvOekmwsFtPehhOpv3i3E9+
+9+fmiHITAB0moBz/XCLlq/rd/ltM+TFEVTnu9W39k0skl4W3aeBNOV40YAMHUHIl
+tJ/EgioEaaTvwriFolMr7eSQgq38WIBDjIOf8BBkUrjUu2LWAfdggYCz0O0pqTUj
+FGNx774PgG5Uu7MTww772O8IRytlOOiyUMewajxak5hj3xW0rdvON6q8jaY2wCMz
+KZtFguNC77y1
+=eEqn
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    476634A4694E716A
+uid    Simon Mittermueller (none) <simon.mittermueller@gmail.com>
+
+sub    4CE6E05D128BCFAD
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFE0soEBCADAy/iIRT/lpb+vfDjWs/k1XQNU3mzXoMm1mmS/Z8VOc0jF7sVB
+A5z2pC6u2OmEr1oJkhWefX+mU//7kXs6VvUCReE4uheGBlisg/ELEXkTm342TcwS
+K+tR/NMk5h1DwxeGR2qc0+zhFcrITiYqCpdaggRVx92syhuYWrG2DtRI3eEz+fys
+2WLhAd/AqBTR0ENDZssp5S6tEBcLvU/jAvKv33/+ydg+1Bsw37CqCOO0bR388+ow
+uSXSARDJaesnBpUcXT9pbog3Wm9pSzJ2fX1FyFaf3rqIIYEqGk1rEND+AkT2CB08
+BykABpDx0mgR6/pAgQVywCatPuc7wneiZY+LABEBAAG0OlNpbW9uIE1pdHRlcm11
+ZWxsZXIgKG5vbmUpIDxzaW1vbi5taXR0ZXJtdWVsbGVyQGdtYWlsLmNvbT65AQ0E
+UTSygQEIANTGYOD4HupAmugS69txMTAW4GvRQ0s8Li/r/QQQUWPpjo3IkJDA0+kP
+Ce2JRamNJJ2plzndeGUpQIZn+HJSN8fGRjZG56HG6l0BJmQRFHD/6CzNOOKK6z+8
+e306DAwQPqDdDpUgpBmbPHZDhCs7tvrOhrUesfLQla15MM7n1DEtII9y+AsMGfwr
+ZCd2PeigiRC+/NH/lYObLUPc+NL6GrC1ZHrpGoOR+9GQ6voVNY5EIxVlNgoVBxn3
+ufcFvvghmZe0WyudBHK9ByWeioBItHQW5n7eGpljcCUbTpsJmErhjH6KBKSuxPQs
+yV4TkQMqcsymGW0jhdHXc1/tStF3L0kAEQEAAYkBHwQYAQIACQUCUTSygQIbDAAK
+CRBHZjSkaU5xamOiB/9r943gZZy9FJv/NGPnNxCvI3ZusQfntgRfVyIFZLIUeaYD
+ab6RqKTD8ZRgyfO2rmO73DiQ2bntzmSPHeAlpKAIhTXfty0g5UICLjr27KocLNt2
+34BKii6go+CDo2+lLUPUAe3cJPFqZrtJ3pYLFwS7O43wwhRaO9A7L1uyruoCqql6
+5B6CJcymMEsDnCizRVEAsE2lxenufxcM8JIaQlczXTsHYf23vnmLjlXm5HvEAfXE
+0s7iHo9BMlSLxHWWEqeyrbwMdnn/gT8lHGw+SHO173THvhtGuKGkrglD2CA9G5d1
+ZWgAz3il0fLdBenLH6t1m0x3+P6h4sUJ04LlldPb
+=Ctqs
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    479D601F3A7B5C1A
+uid    AJ Alt <ajalt@users.noreply.github.com>
+
+sub    868FF6CCEF26A83C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF5CDMYBCADC1/aWU6ZbGZEphRbmjUPNfqh3N5goSnDCou97mmQ9Uq8iBuKS
+UXJnGSOHudXK56f+Drx5lGZdLAzveZdqaqb1o3yLFO3PJxwj3Ulhab3O3uTG2eR0
+2Xo7GKjRW13kEfphJrfVIaQq/TiyIG8IQ1dbm9Vuzc5NLDIeC4jxYD2S3hUqCLGQ
+BiZAEH9un2cPax+hiT+9MGzdfQwdVrSQ9aEA9mtMhEGsk80XtxXJnd+hw2va6l5s
+lSErmH5nMtyKh/n9uo/ap1CfPl98n5VUI8dDtUfWVrqRrkyHgdX+MII0t0nABV5X
+rJLneg4dVy5Yw/+FVbLWB1Ta21reyytcIYQXABEBAAG0J0FKIEFsdCA8YWphbHRA
+dXNlcnMubm9yZXBseS5naXRodWIuY29tPrkBDQReQgzGAQgA1oQHEM6wP40xPfpa
+YBBRAWVoEj/CbAV6BooApSqQkV0cocM9wK905az2FmlKn4WTZyNwiA2eHjHlevsI
+jKuHJWhSDVhulcKDi0cD6wTcjctcDWm7M3tvaICbieZQXPH7lju5Ct80kBo5ojdJ
+oXGD72kVhSuiF8vOrAOiLOXP8+bpCpY4+LZ4qt3XjSnrkZq+h/vcy9crwuzuFlSL
+wMRltOvfirrK/CSQZZtqG2PbT30CWFQ61DLo4DkXeNG1fKpnOaDAMaCedt+pNCAQ
+1Vdzy1vT9b85LtOH/CmhumjM3S6x/VWwWZVBXi2xVLFCkm3LlWioSvVs6Na0Vvaq
+0WDsbwARAQABiQE2BBgBCAAgFiEEA8EjA4wgqunihshXR51gHzp7XBoFAl5CDMYC
+GwwACgkQR51gHzp7XBpoYQgAjnYuxyXaFSbCc2EFWDrBA8+OnlbSgJ3etaIOoLQH
++Czv6+wLYc9snZDBm+IvbzEi3tXfi1TKcRI5ii9wDkti0KcVFrR2tpuXDLWYIF92
+cSC7VyBiyT/aZpm0zX8qP8tjRZvy7mewbnoit1R6ea5UifSLvO0bHqNoswfgv90s
+rnuUYMY8tv1sSo4j0f0zre/k4QT8sCTeMDsLsviMIvy1Wls1IPRo1SW1euGGGvCo
+bxgke8Dw5QgumudwPqehOZVOkIbuddgcur55ZFFeitMOqdRoXkrGod9v6hYY1Jz8
+W/Y2tzZmWsedFIc4ahuAeZG6cH6Ac8prHrQEz6lSbZ0flg==
+=td3S
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    47DCFC2A59F59B5B
+uid    Kevin Wooten <kevin@wooten.com>
+
+sub    FCB1A11865F6A17A
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFVB0KABCAC8YRgcTIomAMw865DHxS/tbFgqN9i7M+tgpih1ETJbb4enhIBj
+Upeq+MoFCtxN86zGu2gsA4DOMEXVCReJ4O5n0F8E03+NUraCnJjbXLW9eEyRQRaU
+sYXDn/3SpXQyZGP0XemHUfG2Gok77mqiqbYGO5PwQoTX09X1a1wvM/GUYS8I5dUh
+UY6MwB3IEXaoNIccuNs3exm9ojmnvLO4VZuXcLOizlqxq6+8VbEP9qr06UNLsPDH
+vdqLxIUpZWSyYnUQZIrkctsUvlxQMnB/PpzAN9hKvyps6quQv8tD+dyPreT1TJGM
+ej4OcJXkQNmDxXu0/GP7X5yPsunKy3MLabutABEBAAG0H0tldmluIFdvb3RlbiA8
+a2V2aW5Ad29vdGVuLmNvbT65AQ0EVUHQoAEIAO5EGsMHzoamrTlkeCb1kTqYJN00
+BPUCRijj5CJZGsU8LNHMmqeInTHGaERE1alwqRYlnMFasA204UFIScd+hBp9z+Jg
+cjTdsC2MNOXzeJ6H4rjO9PL+4Rukldg3LGB8il0+nXO6WQ1ksgrRDL9N0k/d60z2
+hozPl9JY+4AYDg8mCwLR3AIDrgBZA2VNpNQnxlp5tOkGfFI/hAX+nxqdLHPWskhk
+MfWrMleqVWvrZLC7iVQrB3rE+1KdNXMLWwULH0g4eHgLmHpqjYh0tB/BCPDxKM8L
+A3ZiWLV8BsqD9K716I7979KYKyYH7HCbMj63O2o7FljDD/x7D0K+g1eDnFMAEQEA
+AYkBHwQYAQoACQUCVUHQoAIbDAAKCRBH3PwqWfWbWywLB/9eLiVoRupsRtvJSGlq
+rDW7+n3ERVQStfNp9mc4k2Ufc74Kr3RWQl+JiQNeCbWz1e0jJeCbecAnI/pay9mY
+PcsArKRlw6fYA0XM2HhuLmRzlDrj9bBdEB7Y1DwpeL683IKPQR8eNLYPN2KpJeOv
+OCZNRrFxpo1/ZK53V6WKWcY6r2RMvlHK5c3wcAMTIhVj2x8UWlMgJSQAxfOwAvNw
+srYQp3vPjMJ0edYDcF+lQfXuRvAiYSiO/TJeDcbvW7ISYr0x+F9YR8tVmeEU6WIf
+fkIl/5lFqREi/9zBxNufP+LeJEppmbomyB+/DO+nuT38lY2QXQHYHLkAWBidKfXO
+6kjO
+=6Afl
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    4896F7312A5ACE4D
+uid    Chengyuan Zhang <chengyuanzhang@google.com>
+
+sub    3EA98BD451E4B457
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF36fYEBCADU+1b8TH2AhJuJXebg5D3UbR9rk8/9kEfiF7ifbb3nCB9tnF5M
+7NnNocEdAq3XezNuSj9LtEpWUu6P4JdpXcfZiQO6wrobzSJRUWDc7X8D8NyhGpd8
+/7EMbAHH8MfMrwb1+00wdCeDXRpDtH8e+9I/mvdkkBgCrJwG2IG5FMSdQkMa44cs
+asquM705q5349n38F6zOFbS2CHtRw+dsGym1xHWX96E/kuAMIh0rlAK1vIh5hlmD
+2d1VQyx1IDQuAMR7YvByzpXvhwGm8neMaPgKvi3EHoySE8goFfo3UUotZBBv8h59
+h56lu4YfV0EOT3rUESOes2bZiRdLrnFPw9ebABEBAAG0K0NoZW5neXVhbiBaaGFu
+ZyA8Y2hlbmd5dWFuemhhbmdAZ29vZ2xlLmNvbT65AQ0EXfp9gQEIAMHnlDuynEc8
+UAGJOVZjuJaVnooglh1Gb7JkatYAtirTlsv5QZ87Wq5d5I+hlqmQ06n3ZE/cVKfE
+ndLYYVeW/wCqMS4HetRxar7SDR/9w+r8w5gE9P1GDNhT7YFKa2c6g72MSawME8AD
+yDXVMhv9iCUeZ6QTDs7e3vqJ5uiXdBgTEdnToiKEpsfuQxCWA4Z5Yg9HWeIlu9sT
+5V8VGE3OXbGMgwRyDxy7ecIrvHPhLA9clNklCOMmtSh6eXpYW1ItXPMv0pA7S8fL
+NG/1wRRRTyelbPQ280wDrB5dhUZL1luNoAyBnTg8AykS6KJiawQ0Wk/gXdL/Jzry
+jR0V4TdmpQ8AEQEAAYkBNgQYAQgAIBYhBMiIuZVYFeqDtIUxeEiW9zEqWs5NBQJd
++n2BAhsMAAoJEEiW9zEqWs5NU3QIAMacL5fIXkU5FkKUEW2PMMjlbJGGorR4G/lg
+N8KIGcf68KulHOSzrKWygd65GQsEzLI38YPKLe8tr/jNvrl6RnOwNZE5HnPOmIGE
+jmwoF6RLdcsR3zVxhvyYNUWqfhyCsBNR4bPRSkdjTCbltV6XcUanBj02lkod+FD1
+QBM2bg4lwnLA800I8yMVTKP9etfCokMOw9p9V7Anao7OJ+VJe3vlMSizrGaLRgHN
+5gvtFtfTtCySdgX7fVOOypsCBmzGBEp57F7sOxIv3sG9JpTIHxfsaHHDZTAT707D
+l2QIaWTFKcoTtZMqLWKzWLOIHh5gcsxbUEpVrMh652kJ/IqaaHM=
+=CjYu
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    4B1E11D5A4B91E89
+uid    Adam Cozzette <acozzette@google.com>
+
+sub    726F4E5C34CFD750
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF8QwXwBDADKNLAHhjWUqnLYiO+ws3Hy1du6tMvkR3nfsnIDqpCvSjb+3/rI
+OHSyq8TbaGLLuHOM4K/KvrKgjhTbXQxvx1WR5IpoylcINzI959yAbaywBj6gVQB3
+JX1xeZqiep8ZOD5V8YfwFOF5pOidVhabwdkC3xw03ZG9N0izgx4gyou1u8ovpa/T
+clEvZh3OnmT8FU+NtwdCDBHhQ6CpYqUzslw3Lcr7gNWJrecdqH4aZdVetGPwJXqU
++9KOog9JNtgOb3FRUSOGiaYBnReioqTvI4giLxKHqast0xilHGUKJvkVgiKBJj7m
+kEwwhlKsym2RWVMm69cdk9wOfdLP/gHvqWqw9+eh2cQ8d4p9dqMdehkZ/KMbzeyi
+hM11wMNTz+QEAIG9xzYe/tGgoIK8Nn8Ts3jSNNQaY40tJJRzheWZrnUXrpFwAh7W
+TDUyHOS2QFCoSLZ//n1YTT1qhLeXLTkX9KpwPZWYl/qJOJhp1P4XfQLEAtfiCVhy
+HZA8CJDH1uJPuq0AEQEAAbQkQWRhbSBDb3p6ZXR0ZSA8YWNvenpldHRlQGdvb2ds
+ZS5jb20+uQGNBF8QwXwBDADkcS7lqcf5rVllBe2TN4ICFhmIw9AimWRN+FQ84DKQ
+mXleF2vkE+13g4YMt2EK5Kz7KWYMzX/EjJPaNCz/YjPStxs1YoLK79AxE0qj7zN0
+KLD43SC5SkC+9neTLuCYR/gkZY0DfF4DgMfNC0pA0jI4Han7yiP945u2UojPmsXW
+UQBPdIRJ8XtVizGI0SGIV9HWICL3XEAfOqLdvziyaX2o53SkhY4eB/u1vaJxOql3
+uJnOFXvvb27sQRntf/7CLc0XJ4Kfl0kOZSEu5jj5E+BGyIRdZHfZuVK/+ILrOZku
+XKHvcP+jLS9nzjo8HV/AYxZYmRFMR2sf5Kz7ADkHqIA2qqSW0y+dUqp9f+f5KLna
+RkppZ23DUJuiIO5Ogn8v4XNru1lwwtQDe//TUVO/kUCRBiSxpTcBwFIkMPUP4fuB
+H6xFyjCNFR7BQxvtxxKbuW5YcFcOxdV8WkQ4ncoZEVJ4CKjI2d0qGM/F+frmXAfT
+rlkixP/ThJbyDL49bO7GkgUAEQEAAYkBvAQYAQoAJhYhBPGlHgUfUn4MjiTVTUse
+EdWkuR6JBQJfEMF8AhsMBQkDwmcAAAoJEEseEdWkuR6Jf1IL/jS/by4WkRkfEgAC
+FSVi4sLsb45MjXMsQir62TZ7QOTAIVA2FiUio8Y2hHNMNcs8icpzlMGWZb8vtPKw
+zFfCqhQuJmHrPHhTwISn3r2FGJ2nvUzu1uqMAHdVENPWQd94vBxL/9ZC2S8I6df3
+46DrGZNs/lL7VeAUfebg/Zd698J2aZs+mERLnqAAazAxXcRSlR4DwWuSv+4/7+Fj
+vxPIjU55QHlf3pE2bELntMR5siFvCKL3wMHorzcw1fJsSeJRTt7tIqFd58klu4IZ
+3qvFuxbhmOaaMUDIFJeGKJ9UUp3m4Tvuz3wCIAWiqT/OA6E2dK3R3owOYZLMyPIl
+TkXNOSowlAbFwVXHh3dI2+Rbf8KgjeZo9gu2PDSe1JnLc9FvGsFaHHDD/y0puIKW
+VPqpelEi+SOEo9tvgUEUUDwigvpiT7WzKit5B0Icbg+moRvY6a0FZPSvsZZx8V2J
+AGg2/CyrKszDpsR8R04jHL/ZAxrodA4Awc3BTpNxQDPfdRPc8w==
+=SIQO
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    4DB7BC57DFDBCEA4
+uid    Timothy Wall <twall@users.sf.net>
+
+sub    25EB2A6CB1459233
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFBm+zUBCACsrBpO6mOsZ/B6PdPPV/Hj87m2GHeEYEHt2o2l8X2BdbZKbVW1
+FIKnpYe3+TsFCe/qNxlR6vk0Jpy3ChD3nW/J0rmU0ju1SZnS7rdSMj3AI5M5xxpy
+Vn03vCbYyFWw4Bj9avYmiz8kC7yImfGfTLv5XPmlHhUQaxW8+s+393n1mHZsIZTt
++luPftSLCkcmKGHn+PUkFaHHD+q+TTaG98nDkkaCXS0JwXzujYDJDQgV+6HB6PO3
+gJJW4QcUHWa5uUY4CfqGcYGBvzlfII2psyKFIHqrx1uHxbhjLlIwif6I+Q9OFcdq
+qq4JgVnWti2dEBgOVunb5S0KnN40VcH0v3VVABEBAAG0IVRpbW90aHkgV2FsbCA8
+dHdhbGxAdXNlcnMuc2YubmV0PrkBDQRQZvs1AQgAumH3wbBy7RYBaRjaWjN90OKc
+pXuJ0MTIzkgC/JtNexIVtzFdrfmHPOEZESYyLVk0E5YU5i3ux+K9ARi+bWrst3s1
+iiPfebeNCRU0lmxI7fih/r+PxcTTdJnHAoZUNBK1ZzjlTgXacradjS1LGFX5+52g
+TgFVNlYXvI3qPKQFb+Vfz3x4LwOI10ipnqZK61D/FC96JD0osEFJkmFvI5n00Vww
+XXRoeefN44Guvs58nf6MNi9ZA11iQlK2a8CswAuHJTndkQejVq5D1+ejVVmt27mH
+5RhG1xoNZ6FSkha+Y3ImTpxQMJzdbkOtMzj1S2VIt8ZcrV/6dt+yCAskTFW/ewAR
+AQABiQEfBBgBAgAJBQJQZvs1AhsMAAoJEE23vFff286kd/gH/2Wz5zWkcvk8ReH1
+Ke9vYH2gee0qtXIrCjtV1WBOTy0NLm0S4Bx/uFjbFUbqNK0nKjTix4mAe9KrVJwN
+47mXVGxG5N79KkiS8lj+YM8WOUIe5tkDovzEfqFukzgpHBY3CXjiojugxVv6cEe1
+GLnEEOYJlezZj02HS0D1eEeIdu7aV6f6xPFAo2q94aavz8cC01IXrnccUfuDtBJE
+VqdZmVoc/5tUZf/dU2m5ga62U7yaVbiimP2NXIL2tzGLgyUaT73E3e+EXzfcpJaO
+rBqbcs+2HPfAjBm/km/0EC3ET0r2Vqoq40hP3fQqLSC/LYK6Vbuc/l5M0I1QxhJ1
+njCEin0=
+=vfDB
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    4DBF5995D492505D
+uid    Sean Leary <stleary@gmail.com>
+
+sub    BE0F021FCB5F68A0
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGBFmccBDADIusjFY82nMHFXYxY1b5eIWtyaXTQxv/bXfjR2Yb16dURgFjai
+OeuYzapF7vVqNV8/H7Sya0W9z4OWf0ZttWhtQFcmhF90586OArXEikKcFgO8EL+l
+u3CrufcWEsbr8P1EKRWJnfdZ0wgJlvvJ7HfF8lr9Wu56vVgfohdgsWfADWkUbg3X
+XGwyxfYmXtvrSUEsuDwjzNvlbD5GijvC9/T0TeQosfaX7AyeXXwbxolFGFtxitBz
+Afkym8nQCOF5jfSj7fzafmhtngQBfeenSsoxpkTxOx6+SdVMksWswBBueQWTYBCI
+lULMmuRRkCHWgQ9+LDu3eypqCS9k0RU+EXkgpMLK63QYWj3pkZSdnR/HROTDvNTc
+DCoRHWZm+ytdQVefFNpLybnMJacfdle2v8QcSgp4utplhz4sNn7/lyis4cMpvqxL
+bB4jzNsd4jqvgBZUmjoVumppHhEqnj5HrMoP+Soq7zNgCFXVDazxWaKV7G666yVL
+Kfh7wjV3cJmdqAkAEQEAAbQeU2VhbiBMZWFyeSA8c3RsZWFyeUBnbWFpbC5jb20+
+uQGNBGBFmccBDADoQoRd+G8n4axz1k8ynj1Xl6ClWaEOP+T6c0GZ+/MjsUtzxz/R
+XxKQdgxvz7ECNHN41U/73SWisDBuYppUg/72urhzL9kPs6ePq6XMrV+1hWs4oK8F
+0ECMw6yn80HIHmtEIDMuzZkjtxfsBPYpcKnoNDtVuqPxsMmmsetutKfInXrhbMWO
+xutvxIKqBtVL+7Va18WdNIXPiS3K8kdpWa59h/wgWIb/GveVnqWACEvkaRyCeZrn
+WYqznrM9lJDtFDNFPDh+PfGiuYsL8D8sT7U1eh9K3ms3KE5z63Ic5pjJuULsMgFg
+fhnfZGAQqLSW2wsBWJEmX2u0c53njT5KRZRxvjPU8WvKQGMMrBT+ddyKRFj3+PaJ
+qmTCRy04b0+RQC8ZiIGeYFK+JqAq8e4bDyXSVRhi30lpo38CXVry/InNmnOxqWcR
+JF4xw9MaJt/TAO+/IZTgwRSX+1IH8SW8928is+5LLhvWKfSApZb9D254NqvFFO15
+UDxIoC/chcQXV5UAEQEAAYkBvAQYAQgAJhYhBIZhbNPE8IA+czdKQ02/WZXUklBd
+BQJgRZnHAhsMBQkDwmcAAAoJEE2/WZXUklBdfmkL/1kUYZbreYCriYE4kQteZ0na
+rPcGmAEJVxRzKBIMhnMF3r+kVBq1QZU4b3bI72YDj6MEfRcMsNtd2aLFfsnlHF++
+fyEhxtga9Y3tn4kuGb03sUE0YQhYqER70d4jzizMrMy7x98bYsTK82IdS1tBggzG
+AWX+0NsMhoxTydXjkUenDd2/Kdh2PSijLLvwSNb1xTbTX2fpzD0bmwLQ4ZW62nYp
+RpZ9uPHZj0NUSHd069EtlJQnY7b26AOFVWghL0qshq2AeVLdbCjzZ1HTgzf8Ow6r
+unKpYRmeHDGbhOXpdPlUB3QKB154zkYYSX4U7t8yVZTc5QwkL0f1U2C4N0f+xIwP
+LBqHWcOXH1B2SAILfV8oxpXbBnbHUKoi3C1nHGJZbC2DHy/1veXGWRSOZVmSu4Zp
+oimb3DVP/jAM0OqTDNdwq4qS9nNs1kB4+DsACLWnwjVPQh+r4ejqH21EwmyxRCq5
+gX+dSFnfiXn5nGg4NAU6QuXCv40L42QGWo2w0iHMVw==
+=wBmj
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5208812E1E4A6DB0
+uid    Gradle Inc. <info@gradle.com>
+
+sub    33AEBC1F01C98081
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFxaxWYBCADI4/gRCJYfXwZYdUoEGlAlCfRgABy90rvebzcs8MKtolAbPVkG
+iqnjftXd28sZhEDx9YJrUfmzspdrYmU7hy1kgV1/WGIcWyTExTH3bqlnaIWnnTxA
+HD0x4NJ2AzmX5VO8LxhqGID+BErrv7uGZvVmJT6trqUIcKeNEq7mzdDJKqTBY4cw
+q+Dm8P0vs4IFTD8q5f1Vr78FmUth2srIBmsIH1wNV1nAUTmQppNBFlCmcvnWTYI1
+0UMcsFFrJ2pFT1yP2AEGUNl4Lgj4hmVHZwX38/lu9pQ7iWtHSLOwZsfuC34/goS+
+ldFt63JqDV7ZaqwAgk7Iq6jbr4pSVsB4VdglABEBAAG0HUdyYWRsZSBJbmMuIDxp
+bmZvQGdyYWRsZS5jb20+uQENBFxaxWYBCADe16jph/XeYDGdbg2WhAZTpoxa1xMB
+ti29uLMXQTRJx6mq2FwVui7gUY375hBTSPN/sS1zSGYf+DGbNFhJ0DvaVKbnyFbU
+iS+RjUlBSf5VP/00KwA/++dJ8FvkvkmQL6C1+DbqkgEl2YBA0Ar8hhTYLiAMqnxa
+Ik/sO/szoi4Q6eNGaQy8fB3IWMwq9MmWdLKV2mxzoRxeUXnnNCfjE3RzMP9t7TWI
+fwHVJsVQskbV29eYdNAH6dNUGRj6ttFQgFWrP1mhy5N8l4tnocOVzF9umM9fY08l
+WqEMoBWae6G6R67modMyBQCnEDeogKnPGSnQ2IvASmZ8Qeb/zZpJkxcJABEBAAGJ
+ATYEGAEIACACGwwWIQQxT+guWkxTd7yi7exSCIEuHkptsAUCXFrGrwAKCRBSCIEu
+HkptsEXdB/9m9GutEADMthk9kQi/Zd3RNt27qdYDGlGX9iILeoNJXM8m9piNzE92
+kNhIW2k2Yupuh69OpKP11E1EzGbdOdbwB2yKIhCOJxNb2QiZoxikdcD4vE2n0e5S
+gSq0H2pDt4v9Dy0pWOtyyi3muo+P28k/IgY4nRd3DR2FaBiXXl863kpPt8c1aTo5
+y2u1qDWfNNPtpkfmQcBNOigT/jrqzHjgeTRqtSPWppPl0H0bElerBcTBK7+AX7wL
+kXtlCgFZ7fWs32+gMhKJXVhsefwgjAfKBIRS7oOmZtmlWA6gC2HXpXkcn4xDOQo1
+wc/ZbMFjyklLBAm1WETBiqR+k5uwXmJ8
+=Ubrp
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    55C7E5E701832382
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mI0EVdDLQQEEAJMtYCaTA56YsP5RzQzPvqVTaR2nZ27qRk36blHB9WmXK+NHpGeH
+PHgq59mLPVueo2/M5k/fFrCe36jHePP31gYpFtueeYDfsofHwod0WhsHyC7JfG8d
+jEnSczTCmOHRZ3ed9ef6SeWUozYCQAX/tAbpoCthe0lTDYhFhkzVCe/FABEBAAE=
+=45ZY
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    56028DF552BA32E2
+sub    7EC19439E4D4C2A0
+sub    D89D05374952262B
+sub    B5681E477AD61C38
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF+7lwIBDACcXIXAwFDoWvCCWn+OImyyJQvSnnte93Mc1ZJtlArkrjeGU7Mu
+5giUH+FOyiXlj7CU4G9RTnAzDgM8XPncWOERgRG2dXtO03Li7iUEX4Z8PCUGsTxP
+2VKGuCF4Je1ZPGxeKG49N0L3IIBBxfCzumE37LP3diw7Ups8xJUhZE1ecF/Ow4uE
+y6lBOyaJM8VJN65GLOdlbjOTKaFKR6aY7lPcEGyClh+SnMcGTocLf9joBpDI8WZM
+NQoQlVtiT6ItvbxjxJmA2hsodm1Ix/xX2xo3hdXH+opmsxlNGSK26hOSMKTMQXXR
+m96Slky889SPpT+Rnbp+zPSsWqUJBzTT83DAfH7PJ210bRuzHJZzSox/2iiVbm09
+e8rny09ju/OTA5sVvg0ibNscO2wyGsFjoBTFB4x27Bl+4bloBot2lBO7mRkhOIaT
+KxDkKPSw6vQnhA3a7p5nGMo20MgNhP09ui9CwO5Yh3kwnA81clldlMcjQMLy35ch
+kSoqW9jnqm2CI5EAEQEAAbkBjQRfu5fdAQwAmmCsHQ/BHcphS2HGtT7O9m+HmBHd
+a6aqzvl0OtOyCLPq4NPTlgSZ+UQ7z+W+9lCZ1CS/pE/WtGOVCxkRiO3qeXPCGWCf
+dMUhdqBQxR+rf18OnQSrVbhjaEJ+T+M57xgySdisUj1MaMB/BfS39tnZVg4TUUST
+XtcE10Jz/K+uBO0XpdKYQ6gJa/7YcZ882jYzVzBf7AnjdNk7aPEc7H//UMZX+CQu
+iprdip7dk3BYpWfBqmep/CWas0kLjZjboy2whriS2w5RGkqAAHW5Dugq16y9oqHd
+fBbrm2C/SQx6LGC9tG2ulDeEOT4f2Ia0irH4L/U2/N+ghrx8qJvLgPz6tePlL6CO
+3BVmtjW3Tn3BBIMk0JaYPg8b9GijBjN0mbB8PFQym1zKAnrJh+femxNsYXcdX/SN
+TOqsoPOIuMKwrOF3YvFxrvUi1BhssOMKwj12KJbtTSz4zY8Eia8NTxRbCqemuKYs
+JWGwytECBpNviZSAUXwygrhBtEKlY4nPiOgJABEBAAGJAbwEGAEKACYWIQTFNqKL
+yJ+yUCcsn39WAo31Uroy4gUCX7uX3QIbIAUJA8JnAAAKCRBWAo31Uroy4nVAC/4r
+G2ObxKmF6BwRvRoCuffNlLpnOfzqoZvtAJmq1YAIGjb90PFongyvaPFMeXoPC8tJ
+P94tTCgCaIRwU/ukit7EXDOm9CVpJk/VXyeewiNqoW551O4AP0kTyqEUDfT2mt46
+SAgLAG4BHSAJql4+vrJffJYf4eYK4jmVvm4J6dCsi67wKSykUND/nMYQWNg8ysfe
+4fvTiuKcPc4AlynBzeItqDchEe0Wm2N4ukb/6olRc3AyQjL3hRZGTtifbEVAoTEn
+kEvA2daEzPSkjJa/KCz4bYD6BQ4yn1RhtErkAPDVMdmQg4FeUIrsSHBmANPLRIC/
+mciFiVdEvW211y3D1kJgkb+lltQp6px5RBg4QPkx25ltYAFtoz1R52nqSiZhguUo
+fjCNF/colWgPDeNlpra9zgSKmK1nfoltsg4LWkF+XZHJ7QcPUILTJS55/Q4X+Koq
+iSlGZhZj9DfF4oHbQQxZKA/XFrV7BW5rsgu8fcH/2P1sgfym8Iv3sH9nWh+E7A65
+AY0EX7uXwQEMAMX5JX6q/39NrSgYzCIcXj0y+0fVrf2BF4bWwu3xN5hAMiwtpZMT
+AW7aOkS+giK6/h2IAkFEr6eFQaEuCuNNq7ohLzy6fFU6HwfghiyYJ1MEkMecHK11
+fDi8w5DGteICBnWdgshnfrhywt1IKe6LXZbE9k94JBm4pLSvYYCeS4ufdWopB49p
+g3OC0A+M+fn0GJw5W+Lv4fJitKdbsuJ/oxmMTNEjkkaJ7B5KYXqbBB/+rHrlAoNU
+NpvVV5hlW+saKZR4fxMyPtm3AOh2APf2gWbEly7/W2RIjlaURAeypuLY+GWLXAFO
+ALXmwWvfFDWJ3JWGyih2i0oBjzaOeISz75QXAdfzbjdj3sgojagjyu/GuhXXhVfK
+QGnZFvZUctGFUks9ScaWHq2VzFjZWv+h1tyaxwa9Jf95/QeLN/9YAWagOAggxi09
+mG3OjycmblPFcTRsozbhEJC+uZG269gIUZ6fOGerp1HmA1tcj4tdKlGZU7hvDbYt
+3tvMZ5aNaOv+9QARAQABiQNyBBgBCgAmFiEExTaii8ifslAnLJ9/VgKN9VK6MuIF
+Al+7l8ECGwIFCQPCZwABwAkQVgKN9VK6MuLA9CAEGQEKAB0WIQSYRlMBpJOcAnny
+6EfYnQU3SVImKwUCX7uXwQAKCRDYnQU3SVImK6YtDACk0V8OnO6hfl4B18tBWuDi
+ogS0Xprevd5Dq24rSD92KvnMR7KLKAl17piV2TO5NohpDnDEA47P/E4dsqNJSTOp
+z2Wo+F39/+EMmX1Ck2otN7CyvxXZ++ATssRPjPVWBZNT7gxluqbRf2eTmYeyq7m/
+pJ5oTOO/UemHkNLUB99Nt9lddSJXc0n1iRrocOAkVlKB6CtRimWfKeGrX+DyB0jS
+N79HZdhhZeAMEY+Bzj+TezIVtU3BIeASfx2g/mW637K8QGd3ao8sw1xZysbA/P+O
+4ueliatuWvCkH2d691Cw9bMC4+VdbzCSBwzRVr11O6buGZo+QuWK8LDAJPsdv89m
+JdTtwYfMUqWvxeb3YiTJMFR2cLY6bgvWqMhKfaYs24Lk8mkhvo45RY5j7KAq9/As
+j6jew8+IWiQa/OFfnIaEycuIz1VKINPxvbqANYdOLgNEnlNodAzTjMbeMyVNkP9P
+HKgqLausTuQCL8n0dpTHcVP6rk1bNdTDVAnBx93OTB1pWwwAmRE1Qhj4Jfll/wDI
+kmjxqzhwdAmDTo3TDoyRVsaAUxku28f7QxkVfvUhyPjoIbKH0ptOooXJAui9bG16
+VeHPTtrPQt9TBg8hqJsh/nJO4Ajocs6gZmQo1ehUNLk0ETugJp7C631i1AD7phhR
+MTO91bSML3bal9g5w7Q1oNO/JMJghgwMADXIhEldhqjakK2JVNg/zLw7NjgSd776
+my+PhIyZ9DE3KQVuklxUM3fihUI/IxjUvEoH5S4zmhRLVnLrKNea/zcBEbSePpuO
+QgmxqeBWYCT5k7tCco8SJ80MSYr3/dq+nyI9Xg7UGCj9RC6cHWJ2+V4sVa6weFVb
+kqlM0G+p2fosh9I9Wa83BTiCwMf8vmp467EsVFgXtULW3vYQ7eSy2evKM9XNw35Q
+N8SISNG7dnTDQKNAccshCMqdaYdsjw8Zpv8Cg2U6/gRdZYMV+cKAcFGZbGAHoXjJ
+2nm8EbOSNjk/jJ1TUWIB4P5X2uoURgRwrOZ/lXdU6n1Ds16tuQGNBF+7l4oBDADn
+6/0WyY1WFixEPArc1+N1eyuX/mpM8RFItkdPZKImllKyyUsASQWH6tHvt6N4+bH9
+3hSMBHORCpjEL6Rm9EbBdyeGAojv8BLD2/xnd0ucF9VmJwrz+3uoENlfLpsqJteq
+faJq9uoDnsEm+OPcqwYdR6WwAFI0S9TfRfMXW1vA74hGvZZMDcWjxGE8INCHs0yl
+ImlH/xuaWcw9oTZSiVSbMeYuJ7V1XQgcpMkoOU8vsCZF8OsJ7mwTtMlpNiGf0JR+
+KZQrhZC7MOO1Pb9jqAr+IxmaUVC45x5qqKyJ8oBxdoXou0j5agkcp7OaRDRBimjx
+1B1JQ85Cdx00R0FJ1VDjXYMAcCb1RFxcBXJzhpO4/Zr8bGVDfKrxPBW5jXBZjybl
+emvc6ozabKZhZ7jNz9IJ/llzWQeHka8fGMZWU0XYMXx20MMD52uqe9w6hkEPOgxn
+uK+2Ev2o6sJIRKltGmNvkgo/eRNxlNAHqy+CfhDB1h+X1FexyhmyioZvuRxjrHcA
+EQEAAYkBvAQYAQoAJhYhBMU2oovIn7JQJyyff1YCjfVSujLiBQJfu5eKAhsMBQkD
+wmcAAAoJEFYCjfVSujLiPQIL/3r6U64559x9reGK7rF+qFiKtMid3Rg+bkHn/6+1
+wa164sAc2yH+MII0u/SiP++ydZ2QOnQwRkJmfHubtAayhnF+UCeKSO1pg6QsT1KB
+unSBJ5s00pxprIECAh0qWVNZ5eLK858I5OERqr9ZMNRS9IGH17pmcgQT7kk3wNOp
+Y3Cd3Kkf32207B41FgX9b3r4oFrJ2NkDQH3NWrv2Xmu/1Yu3x+a8X+9w4ZCTK2ZE
+VMAN/ZigBuzt4AGNpzhmLaH2WHlvQPBarMRQT9wetE6HG2JtK7y3t5LzrlDmdUuU
+XeaI/c7kqsrKDwP6w94W3EQN3k9cdbuB3kwp3n7YzHoZR9qlWWbYjVzwaRTsJxvL
+M1kAHbA2OPJdougZeiohmLzYhJyV60udf4z18scZgS3nc6PqeDWC2bvvvLDn40gt
+XY66vjIUs3ySXgpmQAwf9KmRMlXn8kMtTDO0E/vlayaTh7qaMdyLLllj0ZmV5/nc
+5KzrCgVUcXxeOohqkl0SRuYxdQ==
+=UvWw
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    571A5291E827E1C7
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBE9iFawRBACJb4OMk3zqMDNvSJKYZ8fGYrPq7yCcf/ykKDkGb2dtPnAZGkSp
+3mmNlTsU6s9ARn7BtkhIuM5TdbLs+z+okX62h3F0WW3h+CpfIXyKSgl7uWbhZ5G8
+RSCCRr7A8m6y83npkTVDW6m2oFN2cjFwPLm/vxg1gu5pO+NCwz5iBRHdewCg1idO
+Gl6gBAZVNteCRMVnGnX4EhMD/RaYBO2j511h7gR+p+6BBeJTEIA1+tsi+GhTBkS9
+mUMGuD9Z8PyvwL7quGQyXJ/kTe3eB6iyDFn0oemB1w736FQe3vcIX6eePOEiDZs5
+1Uepv7bXI4wn1i3Z3kzynXNKcjCd5ZxAmML5VlQ0zWeE0W18reCjt1P5q5xxBFjw
+0L8WA/9aPi4d5VPakzuDvxfKK29BogScTLn2C3fpEnqWsTfpoWSkNXkRsoB4jUU4
+oIqRFMTxwsjUmjVUPOG+YqoeAaVpj+RBpp+V+CqgfNWpnH4caxzODE9f+6RYRCGm
+LSq/6OmgZg6t38M5XWVpvk7Ixygs6Vrd99VZyIQPJwSBM/pvAw==
+=dENk
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5796E91EE6619C69
+sub    153E7A3C2B4E5118
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=IF9r
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    586654072EAD6677
+uid    Joel Orlina (Sonatype, Inc.) <jorlina@sonatype.com>
+
+sub    2E74CACB6918A897
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBE1VSkkRBACkCgvt26sMi+0X+EOJDMqdK0Sziy06k47LJf1jOg4tTZ2T9QtP
+OZ8fD+va/O5+q8Kna993jzcO5n0Nv+R/K3+MvUqSmdITshCIjBt3cC0n6FWndGyl
+jY7rOmzdNnvSkMGE3V2fQ18stkJRleqk3EuWwv+EwpxcYeVfCO+UCJGz5wCgtqnZ
+JYdRHcDkDYaIZ4eizpbV4d0D/3cgBdpcbSrwIGtft+lDxacaJrWpT5Jh5P0gLlYu
++6PFz8ZIC4+/aOSi4S4mgZxk8dBL8ZBqLqcW9rc//CYKNtPq33sdf9vxcusMIXvS
+PBODjDpoOsTJwy51fgCEL14qnp0v14y9p7ejjN5+GipiNY/JHo9S9kTdVhMYqt6x
+6a6MA/40vMejIbZ4q3Ia63jbHPi348fLDq3Gp8Wos7Sh2HnLC+pRdC46qX/5wL4t
+Vzj78yW9FdH5yeeE6nQLOBWh7PnSfMt2wYHoarEnkkkycP7WLpRME7qsBYqkNUNa
+2EQZSy8DnGiayYDij1YPNUHI9kpK6H/e3puhmgNkzrZj26T85LQzSm9lbCBPcmxp
+bmEgKFNvbmF0eXBlLCBJbmMuKSA8am9ybGluYUBzb25hdHlwZS5jb20+uQINBE1V
+SlkQCADrG964NxqHiAULSXYEVH1CwlTRILkiTBEkL/cZyoBBnkF/SLVX3TC67y23
++MksiCdUoQUfJPNF5PDOgtlwPnNeAFVK7T1B5rHjud02NJ9lY2Q+ZrO0zmP3Kvg4
+XkwS85cTbCvOatI2VzitvkpYr/WkQSJf/N3NYkuZATO+n8y1marIrqkLC1LxL6Ap
+lCNlks4Sd7OLN5whx7avrEJHGi2qdxTB9SD6MxRSVkpSUrCHhOtgMUeF63xrNcum
+MQPQBIbv+kFgNtE+eZaFfU0+IHgy8sMROvHrtqzPOuwZdnH1OvrVuEVtErINjmJr
+//nTXtWBK0YCpuSQI1kcadCc3OO7AAMFCADoDnwynvulS0K1WF8FGfOIqQRoKfyc
+Kmoz88WvGKHTx9AnfG38Nt+kHHfUeTLsozW4uDNkSd6S5TRmrCArdqpaDzSagpok
+3FRl13mit4Whuw7um16O3miZfqTF0aM9yU63UzyxzoT4DexHlrZAL/0G2zjabJzX
+Morr7p3dSl9SWqBo+9dsZOyKwzuO3gO1XPqZctPKMCJZ47Tt1xtKOBm5GcexIImh
+vNOY20VM/UOBR5yBNw4rZqOAay7MuqRtpCcr9GJEjOqQUhaXPyvOVg1eHxMD3QEt
+4ZdK5U4RbsYEhzx9WezqjXQ52wCqfMRCpwJm/94cdeO31PlaBXd6nLnXiEkEGBEC
+AAkFAk1VSlkCGwwACgkQWGZUBy6tZndAQwCgs/qSu+5vFRvBeGVsg7YSIxOHf8wA
+oLIHbQ4IMkRivPgSpuxw53Hofe7A
+=9YZ+
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    59A252FB1199D873
+uid    Tagir Valeev <lany@ngs.ru>
+
+sub    92BD2D0B5B21ABA2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFUBG7QBCADRWXf0Fw05qRhM4cRnGKlOW1ecue1DCxHAtFwoqmAXyTCO+tI0
+MEW5SyXUkX6FsWLl6A2y+KgOs669ogzfQ0rnZMEt4HisRp8wpgk3GWR1/9aKYz/c
+ymy2N3BP9cz2fJ9+3PpBccUPL+ydFKpcnEnIwiQK+p9JjEWzJBlrdUc/UEJ0R+n/
+5r/+0+BHiTEMvjAF6/SwyntpTWpu7iEzLv/pfdCuhFKa4yn+9Ciwe3wGtSiue+dh
+tqKcd4YxED3oAswObBca3CC2HWWsUEH6EmfT1jUdfy1cq4X5x7AZ26oFYfG+odqW
+W5dcB+13VkJtJRzQTO/2HKtITJYC65a1jKt3ABEBAAG0GlRhZ2lyIFZhbGVldiA8
+bGFueUBuZ3MucnU+uQENBFUBG7QBCADbCC7lPXB/xCBC/jqcCGnK/8t/+ixvqJPE
+igxyJRenEqbrErFjOi/kRnGYLwg0dEtBBIneOMsvMBTL6GEpbFxyzeEqh/66SyHO
+Ag/A3Qi1q2imkWa4baszVkrGMRIKqO59cTuvnLFNe1SQK56ZBjx6AO6KGZWhq3NM
+v65ZE1x/viyqofJ4jvQ2qeOqSxa3YL7sim6tQen2gH9iTEcr6stvn7sH1Rk3OwxF
+FBbcBoOxZ4gxdM5ft6xRtbnfZB/FFs/hsAsBU+qoVYJYDprSYMNQkmDXg7ELwweG
+EyTZzJ3jEnTOgpBHEYS6dvpc/dPsEdCv2vUARNTT7mwGkQdrkEeFABEBAAGJAR8E
+GAECAAkFAlUBG7QCGwwACgkQWaJS+xGZ2HNriQgAxxwfwZnOPGHtcZek+p2zRIjA
+nZqSG2viTRZxFnLnquMZNMaF11EqQZ4y2lj0K1WSh13TMZpkdwY4bRb7C4Hmo8qS
+1JFQ5SjJHRkLbFly9Gm6+HDaDA4l1EcZW14MWfPoSLP6yklirbq6wg9leDFy7EFe
+MQK4dXs5CRRAwN7URs444M4OTMJq5i+x+T3Her1dSnutAZrxWL740cE+FMNTg9F5
+brjzmmok4m4TxAnOcy8Qc/fnkUrEW8XHDRMz2CUvF5ffoSMO2OzndfOHDqHscXaC
+PyudpB+wOcnxI9pFwmZubWMpcir4BqXM1nWbqFd7tcYPre/0JYIUzKCQANB+Rg==
+=NhW5
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    59E05CE618187ED4
+uid    Taro L. Saito (For GitHub Actions) <leo@xerial.org>
+
+sub    8857595B73BFD468
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mDMEYuRVGhYJKwYBBAHaRw8BAQdA2Dp4m1Yhtb1g94pQzzL24FuP6b9KXF8lP9Dh
+hZnynhe0M1Rhcm8gTC4gU2FpdG8gKEZvciBHaXRIdWIgQWN0aW9ucykgPGxlb0B4
+ZXJpYWwub3JnPrg4BGLkVRoSCisGAQQBl1UBBQEBB0Atu9kejBi+6wfOT0a9z/LY
+EEdNXM/VX6xt1onKToPPdQMBCAeIeAQYFgoAIBYhBMHLp17JvQuvgGGTVFngXOYY
+GH7UBQJi5FUaAhsMAAoJEFngXOYYGH7UlMABAKyRCazhVyUFg5FOpAnmckBY38Ca
+MGPPLXVyY8Kr6dYFAP9wYLu7nsDZCOXkAgS+et4Pk1WZCggoYUkxsX1o0KZXBQ==
+=7Gio
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5A68A2249128E2C6
+uid    Tink Developers (Signing key for Maven artifacts) <tink-dev@google.com>
+
+sub    4E5C59DBFF7DACF9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGPcwwABEADTw/gqmHh4LTSDsBP0KMoXFtFQnv7xmVPPrPjt0NxGn3w2WIou
+7UaLUTViKkgm92h72gyM7N9JfNBLcYrqVf9ed75MPdGQgzIhkVg3SLWZGFoIQUJ4
+VznKuqJmd0dSRtApXL9ZoVXf1mLnbLkOvfLfw2hVIsMJcW9/G4It7pPY82IiwTLn
+XG/pw6+wLa5FGCM4mldPnyBDR935nSkgnZzQJyDESXZKS1uiU1rMcGWkVLJ1UYfg
+fT5c6jAk+75vhyQEvHReoa1T8fgBPD0jAlE7T80460x8dramshhAAIOZLnlAuiBN
+A7KPY7cUDxDyFNLdhj7lGjPP1UTv5mdcZc0H6tgaapOB8QzqnkAJN7GrPHjAWnu7
+ujdiT+lmng+waiBfoQN7HQyJXng8Skj1tVYjuAUNgUuA6p1hL30k9Ny9wO2BBg23
+OXYn8yLptZCUg4T31w2ko2PReSxMeEI6S2jWTALP9HH1Q1sinQnlJ8SfPAssG8wn
+qjaV4PtS8bO+Gy2NosG389dzibrmVJAHqymTLlaviWgeqAXEwZhbVcSOv+B3JgAX
+h1dI2zDJUMGV7jNbKa+UNGb+di8T3J5JEXCNM/Zvm3KNudfZFbcNS1pEzNRzm4gh
+kmNHQEtknSm6NHaWIP5eMIxsKGUA6qTR8XE9qrvpwV35rwbxmPHSowHzzwARAQAB
+tEdUaW5rIERldmVsb3BlcnMgKFNpZ25pbmcga2V5IGZvciBNYXZlbiBhcnRpZmFj
+dHMpIDx0aW5rLWRldkBnb29nbGUuY29tPrkCDQRj3MMAARAA4f777lq9j5ecQ/4B
+dbyiHcvrDU02ncexKALHZ62EobT9471Dy/VQ726chyvQesBRLpVDNN+y+wTpfZIY
+PaDuBvzV5VN8IiCZOHSOLQa49SABQ+896kNkoKcv207AUWWQsDoltvCMakLMeQxO
+IuWGDhI48qmYs2uPyN03ISjdLBDsG++zBFK2EtQlHpaZf8xZWGTRl0/6A4ySNm1b
+NabwjLW9okFu5uibwxGNMWe86EZtqyQOeu6Fd1gDurtk9raQM37tUmCUUT21LeOa
+Xc1kmVMwkMHAdGUwLkGyuJyLIzxr+qAD5tz4KRKVtjwRz7sflBzdN5P7xKW+Vyy0
+wbliHYLV0cw9r0pBDuwOggZGE2OE2OVKHS4FfrM2JRvjdNJtIdkjn//RRIo0SANl
+zHzWGehPMdyNAA15jhBNTH3QRkhLZP082/zV/AW/P85NbSkSNNLxM9W4zk7IkWUO
+gKHfoVHAj2rE1ACiIE6Xt9M3db9ZKxeJXlUVx1iW1JqbK+wqCUSKygYIZD+ytLy1
+EM3rNHY8ZfyfQvEbu24zOjXY5sufqEgjDDycif1qXfnxFmcYCLpAJ4y7bmU1FXjB
+Esz9QpFHjb/mhmnTzRsPe1UQBRH5OudPIoYPk1RIshTkVf542FAfuM5v/mnM3eii
+k9uLegyFXZtRZEnbPEqXA0/BItMAEQEAAYkCNgQYAQoAIBYhBHOXbJw5wUebhOJk
+GlpooiSRKOLGBQJj3MMAAhsMAAoJEFpooiSRKOLGwHUQAJcwO5CwsxZwkmK9k4An
+0BKCPMrJZzy9H5au4IcOcgSuDnVG2KFAWAa6GTCS8IT78mhHad7et0pf/RrGDX7m
+/kwDiQOuFrkbTk9UGzoevlOU+1+crzzNxQBlLmDpZNQAbkwLWzllvojzqRO7GWmo
+tI/cx9rz8r4gamehrb7LlU+8p0W62Llnvddu2ZCXresz8xl6MkxPhWhjnb/8Hfvb
+tUI5P5WKMDaEO8V1m5xeIw96OpTOerjoLz1BaEp827HdXwl3H0OMI/jt8hKDA1Wt
+SvXiK0s+06y+SuFc3zsWh8T4dqKxPHRYI18tFZvygl0znPQ3CVwo6iVYfUaA8U2j
+ZI1n5DftW6vTVGj2rkXbjMJZG5PdOMoF8TCePOYZubkmgijPHmAaeMvwncDnJ6Jw
+RIPpUt61SHHw1Acka4puaTrCJUnt39jl97cTGEL1yYr2DgOKYSkqZ7aeEw8xpGXy
+2wiKWhaMEd6cf3NiyrkJk5q/lZfL+VuJAYEBhA3cWGu44WMfR2y4prUBtl3Agvo2
+r8Hbm0/yLR633AAegfnVdIkQOW+EAxrVNArA/bWNzaGk0gnmHO12nuWAl6974h/L
+1j2qffOF2ViyWVzNrNlZtV3XgU0MVghlREfXZ8xhhA7BzTmaMt1KbC/hkPgDkRrB
+AIzlSUJwo6lIe4LQfHMIj76b
+=D4HZ
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5B05CCDE140C2876
+sub    9D29AE4A6B50E01F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQMuBEwVZOURCADNnKQzSjFuI9/IGj3WTJcPU2B/H8NbZaTsz5WE91WumgZulK2q
+YeD4u6zdOyFK7DEScgxk7dicox9cNEgYKQnQXctDhfqER9bnvA2iJ+AFxjRAWyvs
+en3ClYLXT5UVx0H1ZfDVKCvmaZVirZInfkqbi3OiPQoWrUfu02c3DiHQJ+Y34kdB
+egH2sIShNH8WLfEZ3YDQ4XaWHVuN1C7VwCBM8R3OeTTfyDrTsuyqJ0SeZXRR/6df
+2pEckjF9DNSXyjzFg24MrZhuhgbnj0oR1zmRh1EF+KlBfF4DF4acfxWqqcJVJx/3
+FTtOkLe3Xjj+inyJgxOW52gD4DsJpyf1tIbjAQDZvOdlRRCqZB4FnzzIb/1GmkGD
+JpDLC4MQmqgxkm0n8wgAmmHLpqDTdmuyJXvdX9RdGycpW64sljd1mpzTWJ8UKDhj
+uFQVHSSEdLoHoVj8ItnBV2kXd2uoQ/tWzbxFBST7wE/tX0e9G5XWaPKogvOKeDus
+u9XTIds2krYp80UTYWFZ88oNwGikdIrEYURSYDsYt15miROtKHWbSOHeLVbZqgVx
+dtWPqQVfH4gJGEH97/OSmozqDVog1aZDKBLGZQosng5h4j2RAQpjkaIdxKl8m7CQ
+x0Yi9tA8yD1QhRGggANQIb4n00G/vm7RMU/7NBvvjAQ/nAFjbsyO5oX1rBY1M6Xo
+NFqIBrHSBzV9MmhS3nXU+ZjAktCRhyJ7TsoHM0OYEAf8CduM5Zzp5w02iVYkFQBB
+wAoKHMpycW5LhMMMS4w7gmOfP7y04rtg6+zVe41y6bOqn/SxHCcCgnE/nhdexlzH
+ElYE1H7+HpphoI5vEwS6uElF67CoO5r74Zrb6nshGEj2AoOqjbrsdQm0noBBNYAu
+f9RsjU0sQQFzLW8+2xahqK3oZkLWOkSxzLtVwJbm7EGaGIYxEBjg87OnGQkAi9vv
+tVPwdO3VWyvgKLuPHudLDhTpeH3AMbzKgnru1Pnh/ZpiRhPzsbuFtFPEX8PMuCyE
+n4OLzUALl98kXuPjG5ww+24UsNgKMbKbu8qq/zRu7IHlpZvd730RoCWU2/i18tnY
+zLkCDQRMFWTlEAgA+MQFGIhyA4Ww9g7J8ZiEltwSzRblrjM1q9anexsBIGsWH37A
+92rlVK1RzMVfhj5yl+BzIBGO+zHbgycX7iB5/Fwsm+6R/2Uich6NDm1Qai9rc/jg
+3MS0phOAQzgxlGKOTS2GzdbDJCBQMijDObNe+Cs5DNB/E29/nzzCTQvtRzSeplZN
+r+8Q8lWz6efXmm5EeeZxN4x1YXjjzMJCHbc3yGxOjTgYQOs962yUYsg9UDRJm1OH
+9NKZe1m3dTRIMUcZvL12dq/kyiHHR9V/6CkdiNw1AFMi3tvEdvX4D1k1/Qr/2ORZ
+E4lRzgug4sKkpgaclLnkJZ9EMczmUFTGbbkx3wADBQf/Y+2nZCJSuHiDv/+SdhQh
+OBapZ2hYPDvg29mpPqin/LwH7eFTNv/oos1wzuzGtTHHGEP5mUQLOxjwdAXsWMMj
+scSbCs66ytTN7X4O8qh+1yN7vrM6ZBL12Ix7Ku40cgkWyvTVLBXKaEGm4ElhAmSL
+Fpu+/fJw0riR6rIuwHcGB4R1IJtMWcj+b1odgw9QmJ8AGpHh2WVdXspoCGnTUN4m
+DEswZjplkKXCgLypU13SrHVOqhjd4caK5GNZUfWtCKtwNcJMnvgp2truMvh9BBn6
+widfK48hEknQtXzGjui+bZz2/AD7/OT/T1CqDspB8IQlBCMBn8J4U1grSrZ1wTJf
+HIhnBBgRCAAPBQJMFWTlAhsMBQkLRzUAAAoJEFsFzN4UDCh23wsBANDSDn2KWz7H
+b5geDwUTX4T8Uqn21eFbp54tFTfopCd/AP4nTdX1iahsClr9q6G+CWQBuQWHVmq3
+FlPU/jTn6vXQwA==
+=dKtU
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5D67BFFCBA1F9A39
+sub    DBE749136BF76809
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFUHdtcBCAC5xFdAcSc5qQsPkujcRdzeldrESZBo1/SfGwFV0T+lgp99QJuI
+LDwZ1OEG/lQck59J0JRdAgxlUj1um5LzNYexIJSdxRz2DffQ/z9R+hw4DF2h0fyP
+0lXPOb/sIYJyQIMaY7Rw6NJ9iiP2Q+yAd/rL34NbaelOjNy00rQkVNBixp88iZB8
+WjzHAZnCy9nz5nL7fDz6c518PaHMwVnQtt6Aza+fZ/4Na5NmKMvLC01SLFSKqV8+
+j1T0bh50vss+7rLBIYjuq024WpNdZjIUdbzsLFRZTgmv6nUKtamlDVu++qDV2tWE
+POV3OyXAPCxim2+kwVoBCsJbhFC2NMo0P28pABEBAAG5AQ0EVQd21wEIAK88nihe
+mV8Hm1g95BXaqc1UCRxXOnYT2wOmeS7nkOQlFzQNSsn6FIRCbSYUae6Q2Wv7NqvJ
+OGmiBCaKXgMSq8iEEPrbY3Ed9BTqiFtoA2smBswA2Do6SjWg9kiuXv+sRLiOMTKf
+jitErkL9Wi5CNnERoD09jICcEcMHeZbzvjslADzJz1iW4cSRmbJC+tY9Tf9LMwUe
+etTmeXYJSv2w34vxuT0zzosN9ucEElmdE1oQXQ1Ryrts4Gyv354R7+raIzEPIcGd
+4fbub+x69G5Xxy3AKI9DbVapwskME7oENwotlxzLm0or/1vVC9tOnjVh1HSd1u5T
+M4DeCQ/7wgxl8Z0AEQEAAYkBHwQYAQIACQUCVQd21wIbDAAKCRBdZ7/8uh+aOduc
+B/9wmTVaPsUtaC7+tsFBf+EM6zVsVgMe6aY8/AG1llwX1IujYRyhs8YvqD+cc9/7
+CvK3GlT2wJyBrRaiHZXE9u0COJUgBHyuIvnV0W7fE8aD5AoPCVMacKxZWoRTY4xe
+r+gde8NpAp5f2AKu8kEquXOiIymG8kXJlUqgvZmQWSFYOWF+j7Xx7iRp2+0j2f6k
+nayvHLvyvMGygvNzzhLYKl5zZMks6XMTk6daVt6WbgaSuT0le5LfpxB/k7p7xMOe
+yW0bFgNhSQMDmPJ2iTnW+iliBXOntGQda/W/uWE3LZ03Z2xTq+2SlXtDllVh6Ma2
+QaYKBnGzozJvTcMbyP/aZ3lj
+=kPmv
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5E1F79A7C298661E
+uid    David P. Baker <dpb@google.com>
+
+sub    A7CC6488427379A4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFgRFtYBCADud9fmvTI8Dbs+9GcZUIVzxkL84QYHSDxI9fF+sxfAviq1U+YJ
+a+ZLIW7HsXx8vpn3hqIqAbDxHjrb6MEJ3OWD5Ks7O9Lq7HOhtqAT/mpV3fZmf6pF
+zdEw7c4UrfbtKyBY2kSBpKzTfu6HD3q4OBDm59Ezs2XFhKrXtlNC0fQ30ysBpIvm
+vZH/opwlBgyELKnAYJ6eCmdW1iiju7DPKDBOrGi6zgvslToLpnZeSg6hzSyjM15n
+Gx6Dgby0GNR4VEVze/UdOpsFVTSfP9qXgdt5ZOWQqW2Jg5V/ezvk+3Ok+ecfHWRz
+q8tHkagnqn0SfP6mLqUNvmvAH7xp8crH8L/TABEBAAG0H0RhdmlkIFAuIEJha2Vy
+IDxkcGJAZ29vZ2xlLmNvbT65AQ0EWBEW1gEIAMuetYIGcqEC7KdfWn6EKmO7Zucf
+OEirvo+WXclo48WX0Eo0gsTghKPGTS2kOzglwn/wYCbBVKzYaOngZljIcrR47hJi
+Y/u7OH7EjiCiB0sh5WuEqOaCPPFo8lCA1+SBPAF+c1d7SfIEABL/WCc6e1rkKhe7
+wkBSclspL8YQUG3cr5G/cSCGOV69TsCqq7rtezjkSsfE5dxmcs39Ouur7hs25DKe
+hufUA5bV2i51v49WIuTE8x53VfInYsJyeRs7f4sx3hmkwN+EL2mo1YFymGwEkp8i
+B0Jtrpsevl4AFOajl6X4IrdLn6+XSok/1mzIm+t1ZHokQ3mUWe5FC9c1Y1MAEQEA
+AYkBHwQYAQIACQUCWBEW1gIbDAAKCRBeH3mnwphmHv59CACEnAU1vbN4qxquAzNu
+aalyV6Hyx9olUQqPHopRGBA2ulPs0l+gtAXz5USotNsh3Ai5j39Y4J+qxN3HuDts
+cxEReogawzOo/B+1IKuGuuTzvL6fU6ZFUnEosxChAKwJo9eS5xlyenyumTcXx5yB
+/5X5nqTes6tcZlDcEefh7K5IaazwE5caITBX0ze8g7WQzRxyN+vuhY30U7P8TTKx
+AsavdSBVIb+Hp0e2W2S5T3ogXaGkIi5qllr9uhfX+E9zLxJJKfJot33ix647mPwp
+Xxo7K6teo2rkwOTQij1sEe2sbMZiKZkn4rYSgLpZiVLPiDYuP3RTuHnFenYROA/Y
+cDvA
+=Sagc
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    5E2F2B3D474EFE6B
+uid    Sebastiano Vigna <vigna@di.unimi.it>
 
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFCPD00BCAC4tY8wMQTsCKyII/mMkUDAkXA2cLM47fY1Wn+iohtgtalUdA0v
-AhGvTdFU6/St35rOKNoyLC7Sy30FBYpAEfMB/x9j/CaQtdtGhaQU0hCvtWGhhS3J
-BJb3BIzhKuP2mx+6tgSPtP/meiF/K1GV8x4s+4JyrVxSFtqz+yp5szFNbIXA46cg
-UWOkzPhwA567Jf/8dUWysXb3lp59DG9anp2BQENwh/EmUhuhlPoM3PeUIPcZAiyD
-SMJCR/KooLzE78lAOK14oD8eV0qg3tT0R5RlsNKfFRRoo2bwwPhz0SUVqJlt7ehd
-By6ztFKej4M4ZKonnWUiVJhKEGm3dVoEAJTZABEBAAG0PVJvbGYgTGVhciAoSkRP
-TSkgKFVzZWQgdG8gc2lnbiBKRE9NIFBhY2thZ2VzKSA8amRvbUB0dWlzLm5ldD6J
-ATgEEwECACIFAlCPD00CGw8GCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEOk2
-cccnK3s/HJMIALDETleTycLBl02uRg9ZRwPNWANajpfeJK9yY/SgpVfVn0ExXtY3
-/1Sgc0kZn66c1ohjv3DhLJYTL0GgSfb6FmAkvXMTDfFcm3hMMQKBPTUxRKw+gmgX
-ITrrZbXZcEprlF8GWlAcpv/9X+m5X+u24C0nR8tOtwZkwQa9oUKyUajYrt5KUJUN
-JoVpd8ZDWspXw7HkdQaC+tMjU1i8rypptfpnSvHFXSgH49pe/EAT1C88mx74eGMR
-XGJKL4VdzvNi+m8ECrM1GE9+EHBBLExL7NEd17N75ZYQq5HTQYKEpWZRCewOFJS6
-+QWMp+oawQ7VUApo9bhGSH1E7X0IcVsqVr8=
-=bCVv
+mQENBFijpzMBCACxAT3jijwXbI6b7LIF/k8oSGyM8ZNJpb6AQvPqKIqCzxNFXzow
+EBCasKMhIWgGy+293Tpt/DY4btJie4u+igMBS86iXrF8CUnOLPgTlAIyil/oREGJ
+1GFkHsf0Yj88zCo9H9GNiUZRNSHdf55gsgjzzFVdZ6x0MoN7Yopbvl71bcTSbe25
+AZM6K4gIf5TTo66smG9FgwDkMxc61ixRty44gkfWapzdob5d0cli0Ze0mu+2PHJ0
+Fdt2sUX/4M0Bpxk7eaGVecyb9sm6KkRaGziJ+XVByZ0UMdrEEJscLaX/UpfK+Wek
+aPQjDdyYLW90PJofKFPt4h2DBQyf9DSZ8NfJABEBAAG0JFNlYmFzdGlhbm8gVmln
+bmEgPHZpZ25hQGRpLnVuaW1pLml0Pg==
+=t3gx
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    34918B7D3969D2F5
-uid    Brad Corso <bcorso@google.com>
+pub    5E975CB00C643DBF
+uid    Xiaoming Jia <xiaoming.m.jia@gmail.com>
 
-sub    5CE9BCD2ED28F793
+sub    91A4BA316974A467
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-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
-QuOcn0ypycYY9I1Xl3Z/9D1jxT0Q
-=pU+S
+mQGNBGHvIbQBDACpPdbz5UIVIWR4cfXyyZEMOG0ayCzJQPsT4eq8XR0o5Y9egfAq
+dRXC8paInsaF/iVL8BJY6CNq4B3dUfJwKDcJiCiPbiQgknqF1HDBqQtCb4akW8f4
+Am1Q6qWxTcJBUtVjjlTMoWcCRwFNP1229ICL6XdfM5djqxOuIcCMIHC55YTldrDK
+5WWgcXC2NZgUbRn7/8dpaCn8iFAyhYjYKAk1lS8kSxCDvQNU9DtdAWtaCosoWBZ7
+mWWIeWp21erk4jgC145GujHYeqynf7VmdIB80u5OeIV6CwJx2ap8AgrKcOCON3Kp
+kYa7fsDGxq6Lbzbc0rzaIfK1wyGo56dMySDK1eZuOY9Es/wzaYfpzx88gn3rrcaw
+HwTKBoug+9z09m/rWy1DThW1gruYMUrxjeyhcdXlEeVrv9EdNCbbfKcg6MbrZ1mu
+Wc9DIAfSQ40Lv2sKxTyubZXxvoyEhD5LTqSKC0tRt9xKjHWWWSG+cyhXu/2hYmp1
+Dq7XvS1p8NKjD6cAEQEAAbQnWGlhb21pbmcgSmlhIDx4aWFvbWluZy5tLmppYUBn
+bWFpbC5jb20+uQGNBGHvIbQBDADNSRxyLYyzfkdxF55RktDmgSKq9tskfR1QcrQg
+Wvi96fJekLYL/a2hmJnbfUbqaILnkyUmIf7zONlCFv10U81prG9wxfXUTMuabpp+
+eXUFdbCZMc7R9JGXw5iaRWje+jh/GaeB8xY3cPbtfHkXZ7nWkQaq7b8DutJrAqo3
+9NuprRaaujfU9PXj93tunJExqi2w++fjT1aQ36PaplXRZ2qWiRxAkaIUGxjVgLuO
+Y1FWZJjWX2XMypMesUSfUCV9IwlKCc8+55m4jfbtblPQHkbe5zvstxxfHdYQkGng
+p1rNWLHHSCT+Tf4Y4aR2J/E3mp6wSBVxgfguS3u9h1mY9fEfe2vSHWkWmYNm4iDA
+msPn8KTuccbZlB/cKIFS3AET8ZHwHqHuCb4TvUy8febp4yo5ZRniTVQSf2aA/izu
+wmKSmq0bX0hjGRBVdGR2jlD2ND73lkJXU7+3sIwY1ebNVzvl75Y7slmJNHsij24f
+keZtcSmRQ7BL7ZpZ3fYiyi1/MxsAEQEAAYkBvAQYAQoAJhYhBNX0a8C4avXcVt9Y
+8F6XXLAMZD2/BQJh7yG0AhsMBQkDwmcAAAoJEF6XXLAMZD2/kY4MAKDX+NsPosjH
+t95895Z2H8A6JXOEt2F/LqUZ6XOqW1AAeLj+cGMWBDDQYNp/IkizV4iMynmlHlzg
+YivT+52xrUvEzOqMRUrDNTPrbkLUjc/Wm+TA2J2ZGUSjZZUmP1sBTqSIa1NCqWl1
+VRWZcmbckCHz5oyoeXKM0EKGnPwOZP0lf8M7f6QDUJY5DS/5RTIp+6BxHhtRi5uZ
+BN5QLcamhIADwR9fIlfoFfXEwEAQl5Z2YTnyMf/6/5FWVgAS1PPFqvI9H0HiWPx+
+XSfgJV6K10GwRTtdhT12M4teNFsFUNhngsvO8WCZKsxz4CV+Ai8bSMmWpNsYk72C
+bRMoEHMrHuVXKKaKv70eFd+BaGTuLPd8hZgsDuKxU83OpS+LGOYV7Lb3sZNEeqWa
+sWMqjeQC/CzEAE+Qfj0RuucswEZGZ2NWvwouGJcTvLAKaUelMr5IuWTkTZYmXww7
+ffu+Fps7qSMnU+mxOl6TkfoQw/cNRpZdMqwI/7119TnFeK5/AORupA==
+=YL2l
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    056ACA74D46000BF
-uid    Norman Maurer <norman@apache.org>
-
-sub    DECB4AA7ECD68C0E
+pub    5ED22F661BBF0ACC
+sub    31ADCD8BFCB760B4
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQGiBEoo3BYRBACXE2oGRA58Ml6s+kvfk6n/AJ+5OFeRT/Xelco/cpdxOVF5LkRk
-yd+vR2+F9ldBlH7CSTCmrdZIN3M3zrcWndrk/OQkCxNWVnE/a1li7L3G9nYr011k
-MwMM8MLkdf1Wr+FBunf1qpxPYuydfjWGFL749hYr4uQ8RbFDRQcmWLYCRwCgl+ur
-E28AmiICPcje59DNKHZZxd8D/Rk1LcZojARyMPjEsPOVSOh6kOaJQ/FOKN0j97k7
-ZqA+4C+OnIONSy22uMia9xO5g8oMLyHaRiA4S7JSIypYfX7JMCmwQCSLM/oQ5zct
-tsY7tGzCRBA7UVmW8uCDDZGmmzYIGQ7h1vcabgOFQ8wsteMHW3F0tU1K6oQut71x
-5KowA/9LeDjhl3tKizJn5hKf+NR8kTMcFFVMk8tf9/ZdqCG2gVTuB0EFimH47j1+
-YFWftvKg2IwF0qRnYuhpXn3kAtkzSwDr2T4r5CpDjttq+oBwhJ+N6lcPRoU26ijr
-nQ61Ek0jFFE5vfU7UODSLYXYbjf8McM6BtksY1SWfFBU5cVzgrQhTm9ybWFuIE1h
-dXJlciA8bm9ybWFuQGFwYWNoZS5vcmc+iGAEExECACAFAkoo3BYCGwMGCwkIBwMC
-BBUCCAMEFgIDAQIeAQIXgAAKCRAFasp01GAAvwh2AJ9HdFLGMuAGkk/wSv6dr6gM
-Xw32iACaA/Ez8jdn6/8kp/RpqMtUnl9c/Pq5AQ0ESijcFhAEAJIGBbVgN1O73XVP
-oGlZdqPd9n5QOjIy9cF6h5GBXEUDy3T+iVh1ak6Oqn1g3Wd0v2XgQ40gKWe/8O3M
-FhWkJbLENKhGyc9dLIpXDt9WIKfV3PNbblI/FmEYFqeJDNZUfaf/F3L3Lw0Z2YE1
-f0Kr3J64xuxJACUjAzXkssEqVUQ7AAMGA/9Tfa8rJD06apF3u22qd7DNao6UlUeo
-RIdluCpHfZQ10nEDTnFz5wNzHBlZDDoaketUZ5IY72hRKMcLMWRI5MaktQb9XvFp
-zhiGplsFGnzCBI99AqTsxy3m45AdVxbcVy2Lfeh9gzS+ZnL6m49Xf7mQuqQJatIX
-mWyplftyWc3XDYhJBBgRAgAJBQJKKNwWAhsMAAoJEAVqynTUYAC/qnQAoI/8QMuu
-PGrvivKDTCk2tA60w51gAJ9brzNybLCs1HYoPtjY97nOEy0tmw==
-=2BgH
+mQGiBExyNhsRBAC/W5cMapoP7NUn8S22iWG5bPw0bconApJHP4kQdT17gT2JgNJz
+BmuGWV59ZOGQkc6woeFKc1s6twlsgIL51jMeVOtgLJRGTS4So2hthNqDcgO4j8Lm
+yXpqbTkbD7/ZlRzL2hhedrMz4NQOZCvsZpQ1RaCDrr2hxDq/HhD2omGdlwCg/9Mt
+JNc7897LgfCMmtPOvAFt+rsD/0K87nvW37nlRqHdEtzvwUlyLJmYxdW9hDr8tm4Q
+Y/8rDvNFlhKV/yXmxQuhtgQ1qpBo75dwD86aJmzIMIWM0iei9Ecfu2DsWiWvArq1
+heDjMYSeQl6k37cmD59afo6e/jQmg2/ALC6mRf3912SfmqV5spw0k+NYdFxAnbot
+9jOfA/41shIdZloZ0aDcJDTNe22wFFh2sW8RwWtJJO8rmOCgh3MmkPn7LHPI9idJ
+bSdD1dRcR7UTyeigEeDTu0PAKfKZutc91lfcIGSZdk39SEEhUkL2JdPKVRBotiZZ
+Jsi+NxDdsprF/yQtr00XSGJYzh2TW/Srnb5nZQm2Iyokod3M1rkCDQRMcjYbEAgA
+k0wzZq25ZX73DIlxw30u8Qmy0HM2cVmRe45Pj857FlSQsO82YNPOMxSkACCmHAAT
+3pACuMCf5Z0HO5iLbHrxegFPGWLkNE3CJ5yga1zIiFgzNc9qNqWtPQISJIQjABit
+4SseMY8i+3t6A89NjWc/AOK1BloHdjAmtvT54oYtqFYCMlNMtCLaR6ioSUH38qLV
+jXtFvmTY4OqokNaz6JXxzTymyo8gJff9JRpcm2S2Xksr0dLNYm5QwJEN7KX4E8iH
+8Rz8TWxfAhrf0zn45D7bgHOk3JFPEXzKGV1l96Tb5h/yy9wuN4JePyXDGfigub+1
+grV5DBKQ3srkEwy6iwAYwwADBQf+LXoUj24Evhce+OJ9ZCaPEppmV6xJ+LaU/9D1
+hwMkQ6CXc0IH3oeNGAbbOHhXM2GymRfg8nmzbIHVueTP8ISeO7Dc+gMr7l7l5kB1
+W7IstMlS1xI3Vdg9D8HaPJa5gB3qEGrIPdDP1KRRwJflw+DmQXB5jOj4vW1xECqX
+0bGY9XNFFaSMhkr5XRVT3xgQ8d0wuCB9otuUZC9pxmwFiH2w/FvKzMTKMRwK4IRO
+n5FPhSO2VBHBnlvF/mSbED22jjB7DngUC4rF0fE1MrA6DDJIAKrsDlk0VI7x/tIO
+YbkEOyypDgBf4JLrxgrI6jn3iCRdmi51hS7dtXX3ZIkmDVJrOYhJBBgRAgAJBQJM
+cjYbAhsMAAoJEF7SL2YbvwrMplIAoP5GSTgknFm3ONZ/W59iK+l+XJWhAJ9Bru7L
+aSKZGs7jwqXqGNrZ0ZzxNw==
+=HDKU
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    EB9D04A9A679FE18
-uid    Uber Technologies Inc. (Uber Technologies Inc.) <developer@uber.com>
+pub    5F69AD087600B22C
+uid    Eric Bruneton <ebruneton@free.fr>
 
-sub    34CF779A8B04720E
+sub    0440006D577EAE4B
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQINBFYC8RoBEADCz+haHo3OuO5kVDhQ1W+GtVcYLuORKvKPaymrD7VSkYyUdkNS
-EGkrk7g5ih/SpgrOxND+Sw3gjwzFr8pjktVkh2bkc1QLRdBcFgqpbmVpVXNodAt0
-4Ie16av2YJpE4tqNaSX8BiBGRdMi1NvbR+EzKQMC5VLUAlbIBPVzHsR6ppbCWPBv
-/Do+QP9OnjiSRUoDlJ2ddCnWiXSM2dcoyd/UOGCS6uXybIJxtGRG1QgbhCYdDc3b
-9XbKcJ/TC9C3hFAUkCQEyqMry5mSl16KTVvYeKacKsTOQV/W5PFbxkVNjGWF3k9q
-f+7IWVi26COlg1Dp5xxY+L5QbFUANNQK221Sk29hHy4hRKqRz5ozOFFI8z7t4VSa
-p2J5cyuN8ojti8DMssGrX83dvN8HLnKPXBGTZBXErBJIRPKMcX0W+nFnYJxOi0O1
-18rVm+7GNUMhV6lsgq8xUZ3lOxQZo3XMbO2aof+31KLDRpVzdvnp/OCZMWmSyP77
-SurcrS0IHaJy9c07WVkcx89KnXiaXp8WesP4nfCB07JZAifIypB0j5I2Jv0WsCJz
-cVWYk4reMmuW/hVZHrGairelhAaTw6Vc5eixouNa5X4rCqCuK714lNjmbVelrFVp
-5YNaMNA6WPAgM5wv2UwG7k5tQI5pFQER60g8SwHr1obK+OrrCyh6/kMQGwARAQAB
-tERVYmVyIFRlY2hub2xvZ2llcyBJbmMuIChVYmVyIFRlY2hub2xvZ2llcyBJbmMu
-KSA8ZGV2ZWxvcGVyQHViZXIuY29tPokCVAQTAQoAPgIbAwULCQgHAwUVCgkICwUW
-AgMBAAIeAQIXgBYhBNT7C3tejBjJk6ijhuudBKmmef4YBQJe+p2kBQkMuhOKAAoJ
-EOudBKmmef4YLRUP/RJ3KiFWj7sDa4eX8pGPf7vuKVlWxN2Bc/TgLsG7A2KjtkA8
-dX8Bc+MoCaJp4o2UGPRHx1mc/+mo44bFntiBafLSE1ugoeA+klLDGPqU/XGKEdIq
-uUR9PVd719iLdY9CD4wQEFJ1TMDbs1gHXIuq3XzCx3P2eG9i1BmmifwF8nDxE1oi
-agykXKQu1RfY6Vwywt9oZWVM0pU4CJn+AG9b4A2ZbixGq+GSEeATzH4ZCXAAdyxB
-JU6I1dAU+8D267eJEcDPdFEt+RzhjgscEtyFAJElhD37ZqTCf834GwFcCSYrvthz
-bjCyu/Rp/Cp+Ru7c5V3oYEd80HcQhlS4IJtHjBiGjNoQtrbttYRp9ASpcLlwMP8u
-ENZ4PapKT6Eq0otmeLYvftdViGeUyj0h3Tyf5NtHZ9ZZu37IGO1mC+D/AR0RRloc
-rqRpzmqQ5R9KUwD7n3dV+z7ohUI0Besnc9PxjpdLGCnB1A6hSIVgObBtpL1l4QvN
-8+Lp/4CiWaeqf8CpZglYdXkBRn2koIHtgUxrqI4j/SAcsapw/ePBgMTXPaeGIxs5
-qBYpKzX8UsI27GYtXEdnpaxP1fFbvKVTgjlM/1u4XHA/qjVsCsBwSExj1dBmp9hN
-G+dV44XPv4sXnqStLAx2HgrK0md4L92xNIrlTaAXqu8mHA8ibyYf6qdWcCbtiQI9
-BBMBCgAnBQJWAvEaAhsDBQkHhh+ABQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAAAoJ
-EOudBKmmef4YQ84P/2uUcUJ/zPbLR4sg6L5Wg9FMMSDJ4JECtSlHo83jI18NopIz
-2W0TkCwCCOxbg9scS2v6EAlDfXnjAK6iW2yw+ew2eTPDs2PJTb7jMayNhPSAnDz5
-PJzAS0zLfliFdk8l8LbsbY+AufHgVdlfmB7AFGCHFnueBmDkjV4jSf1NUrnHjKWI
-bwDuAEcbNJcfZi9js+cty8/+9LfIDoCcIzKJiOUm9iFNjUGPbOFl7NZTRQmJdPwN
-sjGWSvnk6zKCol19o3UXzrohh/R5MDfJyh48brJyf6vh2y9VX6Z2Nta6bfuOWWM3
-dksk520J/uqn9ANh6kqbz+ZUh8og7/rtea8Oznzloq6XvdwEbrKjU+BMpXskUpQ5
-vTtbzOjcAhJFXG2fmVldd8/JxxLIB6JSuKPiKrb9a0Gf4FKmUWwrwnADt+sscO9q
-Fvl6N2M93g7IVm/xNSI7uEbinjf1jCquH6NXwBJzvddeXq8z1ECh5gcti9H2IE5U
-uFOgTEvQv3oTwuLrY2GH+V0puyO9jLHbGSnuFi7Qm7KdLMmpplc6f09tF/OJxP9W
-hbqhYpeOV+sTnZonsuTZeZGd4ViMtYYBfJSZAI5nBqTZT5ksBgdSIIo6IAV1k9v+
-o9VnTxtYF3Fc/BlkLQ4W/imqLyLGd7dQJOKsAd+QN4R+gAWw5DQsQ4KdWGj1uQIN
-BFYC8RoBEADYBV65EK51IB8hgLTpYo4rIm2o8cvgsGQa1EcqDT7Fnw/mlaMTj1Zg
-btOoPyZ4gkiW6Mfyq7qg9YNmhZB0arut2TzyAeA54BdIuwPA0EitHGXIfqUFuFo3
-P0kZRh23aO9oAuVIxFKfjO8HYaJZMxx/mg99ilRWJbb+7aOH1vF48KZ04ZVntKX6
-Z2E2ZgC6hiN8xCAqOVsPGePTeWw4RPV42wlZWZhdw8dsIdMr8L3GB+ENmOMbuVSP
-lv/a/HhOiEZrK3rFndC24nKYRDFIvkQdcrM+M1HuuqhrepnmBAOM3pM513MGGeYv
-8UQfMvaOf8zjEpEt6zbn8IomeBDQwIEwv+NP8uapUC5x/qniO0qaHzXKGnTEKODG
-ex/7DCgNhjsLUa60RudxF9n9tz6P7BME+7jKqDZoxFp5HZuxcZ60QpztXBcqB5v3
-1hrNIEj419XxQdZV5labDT62TQ6qwh0hdbdeqzNhUTn2INXSFin54zitZZT/KfHz
-ppe3X18EuHUEoovi1XReWhj/24Gr+AHKgtMl3KSEXVTxwFovB97Frm7E6kWzXjDo
-uPrcdcYOcujX0tCkbjDDNCYXYCt/JCEDPKk/mlRmE72futz5GLWUoyNi6kjueHMz
-tUxA3ki53I28BW4szSbweRZ7osBb2SNWQMEJcR9Uh0DlmDay0xM/UwARAQABiQIl
-BBgBCgAPBQJWAvEaAhsMBQkHhh+AAAoJEOudBKmmef4YqfkP/Anh81E3l5zxDvum
-K6JeZv6QdYNllnXXyI9jg0Dirg3bJWAE9llzFnQRf5z1DPh5yCdsTGVdIfTmOaGi
-0qwFMcCWdydHRsdgBQR09ew/MfzyGM7Da8NP19/XlaJ4FO9FLEv4WaJvymVjIIEJ
-yE/JBU0cSs3TQKNSepVeXYfCsjxaTBspQA0LTBGhum6YT3/grey70KofsJ2s8W1w
-o8pkqSPKdevBQW+/MfYaHKey8IkdcHj2XSIhaI0kKvb6qMus796qngghfIqwcgdI
-2aG0Uv7PoqUoFlUdms7OOObQsWIxLb7dsli1IU4AuT6xvPnAb7GOLSG5ur/rqkhO
-NEERAaW2ZwoJWrXTGeBtWNyicXw8TezbIcFsXsj3yYgFm1YeKpCFy7D8iSQYDhKh
-pYJsnfgL1ia9n5nUY3IxueFGccf65hiIwdUXBmkCDcv/OHuhI6SuD2IzQvHOozVC
-1yU1tQXStPl34PlkRRpaK3pg6byYg9zacY0P4g5F2gdnuyp4R+r6G0uLuneuaFSI
-vtsXdKwPLDpmjEu0nxiwOC/OHvZMD6Zt/YMo9WdAETxvPT/+MaVndzWk61hpw3aK
-rox8Pi1+pvF7beqSdVimcjh6FK+pjlTr6YvfjYCntIInNDBlY+7ixF2kDedA9kG4
-/L0JP8xoZoZjEnr7raXD2r3sv32/
-=fPJO
+mQENBE7JURcBCADO+9Dc4/JnB+wX+fq+Fr2zUGSPOT6/qjE5kXL4FEbJKsqDSAKG
+VnbtRrsIUdmNIFQmz71bBDFhRBbrSrkz927k8eUPhYtxE2NmmWSuKgrjF4qviPQv
+m/7SqGx378m/qw4EvpgGUB8EYif98LYdWp5vsU/zx0Ps9auqvetAzJaL9489oE0F
+q8FVhve6BMfUUV7zOTCmJnf438YO68upjU0PVBdfFE6Qx4cgCeWbQGy2cooW5azN
+iIenhuYU1qikmxMHq2xZzN4uSTWLGDpimPyz+Y1aTSYJ/bgn9gPStbI9sojWo9SS
+5gvNK3XqJzMwxwFow86UcIE0vPD2T6ZlBAXRABEBAAG0IUVyaWMgQnJ1bmV0b24g
+PGVicnVuZXRvbkBmcmVlLmZyPrkBDQROyVEXAQgA2uNV77VI+ARj1d97b5cY3/er
+0Mcc8/Q9ctMY+5YpSYDOQF100QBdOQ8q3IJsfhZeF/iMFlHIUikuSgatb/Ih4lk1
++irnERPuV2MNoAw3Fvn3/vwl/Jy0ZsQCBSXO54U42TcOXSwNLkYOJaomDiiuo61R
+xj7jqijpnydwoFvEi84v6q/Uota3MijGMbzU9QyTX8J9OKMeCSUq0uVuk4ezebjv
+/bwA/ax/qQRIrEHDOOB1LJ5JyLacK4+h5J8tMkEmWxEQv7MNokRLgbaePqv+tdf1
+gee4f2fSE3EXKFxjTO2wjLPXCrHSSI5gecsilQn7ZNxH9g2YUJipn9yj3ywMxQAR
+AQABiQEfBBgBAgAJBQJOyVEXAhsMAAoJEF9prQh2ALIsrWwH/3s8uN8/gDnbcbTX
++7N/ZfQBXJZ+H9GGikmYRJE1xoOeEt9MOqZyGDTZfGM/qNKeDGfar7pcRQlMK/A4
+Nts5E6d1OX8fBkUBtYanyyjNLlT3yDjO6VaV0SCsgAzNjUZqc4lxS9atN6md5m6l
+WLAdHghrXuV6LsiKOS+96htchoCvTvm7mcPI7w146yJRSyCC5+PybG3ult5Y6QAS
+kwI3ZWB0u0PKUoqglwWngplu+0Fib2rxQvL32is4YrYaZ+XwoR6u/Bgv0ZvZiypk
+17Uk17rDb/JfeLqDn7oW6Hlgi9KOLbRRIg7vwZVo2Ixco7aGxZp5c4zSfaPvn241
+v813ZcA=
+=a3mq
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    BEABCFBEE059E4E5
-sub    6579F3D193AD0019
+pub    5F7786DF73E61F56
+uid    Ting-Yuan Huang <laszio@google.com>
+
+sub    73F7734B17EC71F4
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFOv78cBCACj4w72ksYDdLAY3GzwpRa1fo6S4aF7r96PitlETY83ct7AVF7j
-XaBGk5ylNAZXan3vlsSAKtxlI7skZOE5iKjqDo7SUfohs1WXdmL765mUNsSmkbG+
-WMOwDneg7Z6+licSC780OUFbifiPOKpgzGuaj91vrNigOmtyA+cbIHckhy+t3/PQ
-w4fO0S3RyJvQM/aQeDsyvhhBf2QzrUN7RQSfS69n0gtlVcu8usM7FZwOlBDGVPqi
-2Pauuj9QEyQIqnn07uWAUTzKrWF/WtcAXmLMxs59VuVRC3xnPVxekQTcJeCKas2L
-Aaic1HKp3AfTOT7+Ao2RRg4GpIiFhaJpul0dABEBAAG5AQ0EU6/vxwEIALyM80xq
-kaopZN0A1tNL6KUnoLZx/Tme1qp10JQ+AtYP5eFqPpM2yQIkFgWoQFFRZ3saPsqE
-jYlAAeyrRLOJ65PGRycHckckdhyEmGFCbHl4bJl3qnfJZuAqOSUlmxMwvhFTi7Hc
-BCOcWOqCBm99Y91IIy6NGeB+D5Oe7RGox4a9iDDh/NfyYCTTRo1vR6GW4JK5y/oJ
-GfWGx0U3CkzrwPw5efhCgSXmo0U+tQyUSWKl+J9DtdR+kP5mNoWOOxYMN3w4D68A
-IDXdD9ECEAXZKcKAlEXQ3AkVQ+Gfi24S4z5ewsHm8he6HFOsYb+FYtEByeydskWl
-U829LN49xrG2sm0AEQEAAYkBHwQYAQIACQUCU6/vxwIbDAAKCRC+q8++4Fnk5S9M
-B/wLDuqtJf1ANTTf7pyQBmjyeD9QE/Tzv606tnLxZwkZKqtEa/+3EJuPJLYOVHkn
-XpWl4VlMdJv6DEg4DrOQuJDEvv0R7YrIRqKZcZNRn+9donI6PI9jqrbY+8ZWsoA1
-kom+hU2VEoutPgxkZsZPHMj3LfWTGouTa3/HEOP5cxi5leiqJmYLKKBXJs4iMNBO
-BsqNQQjD/0rLeyh1JlVF/bpsapQJJ2kijowt5Yqg0rPOC2qq7EQUV54EVhiq4+40
-iyn5JNPmXaRHH8lFCavNWLNUh9HxNZHUOb7/UmFG9T77reY4ATTl0hZUYKdCYHeX
-eOq2bxXEhHlRB6yktjak7zk8
-=y0Hp
+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
+=w18e
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    EE9E7DC9D92FC896
-sub    3B7272A25F20140F
+pub    604F437C1682DDE5
+sub    F664BA5FCF7560B9
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBE/oyDcBCACgYsHtmWmtUzqyr/JN+orfJaTl2363qiS+NJ1lt2CNxUWOqldc
-VcIGyjmzokxTRpGdCFmT1Lh/hzZhcDPLjrtxf+f6njIibt80OiEbX39gjwZRIikd
-Uv44Z7zAGE/upTM87/s+1+M1h9NFHPUg4SOOHwk3hYvCbvde3bZaUDhhn2asrYb2
-wlUbPBZROtFWlxZXHGXsMnER6ZScxK3ckrJkikM5L8tGFrJlBb/lG2vS00lcZDoR
-7v7XtmHqOBxPFf4RIMP/HimGl4lEuBhc25eAt4QxoVmoqb2C4vCUWxwfAURkJzI2
-JU3l5YP0rSgO9rwrXGlTvASCuEoQyPDjwKGLABEBAAG5AQ0ET+jINwEIANpeqMgb
-VzzRnT60rHPxCM40VfwVTYFEspNZV4g9Byb/Cu4UqHtdOApqIS0XQDgT+042x4Jt
-I6OZ7fUzOpN6Xb673LnB746J9cOlDL9JkqUwD/sjFg9YYFMROvhOOB023moPDsPk
-9jSDDxWmMfpr0NWGba4xWG/R6FHAbK023oRZO1BACBcNF59M9y6iJ3Edb6qfiGXF
-fnJrvwOYfGEqzOA+5YJZHPI59RoxAMm7NT1EwhgnD3qw5qCBHBDzaI7qinAy5Zs2
-jtZIEZHlV37CAKjeXjmjCnAnYD/Tlh9vOY9ku3UK5uH5CGxYDKdd5bX5bNmWK2mb
-pRk7C6MSTGX9tTUAEQEAAYkBHwQYAQIACQUCT+jINwIbDAAKCRDunn3J2S/IluSv
-B/4o0x3rrIK3T9WK2Ylvh6eRLbB18fEiYj5B/aWRTYTHJRfGa+Tziwm55stRnQjZ
-ZMC36K7LjPQjqjAW0011azO8oFKFbJnVmmOTUrosVdkxYBdW6fcOXmFcFi2c/M4U
-At6Mb9qg7vVW1DUk5+W5OU3TC33WCBKClb3usf8Uv0hZ5TRs+gt35EWBYpHuQIhq
-W4+1ntttT9gF6+MruoAKy8ViEsPQ/tpLG0eOTc2XjWg9z2wVl0KVKJN32IQKwje8
-RtLK0bY1KEeKXo1FCUVTg9IWDaNsi2tWPL8CLpP/Hq4Qx9SX32Io/3rJxy3h+sg+
-hN0x6m3QjnijzvokolnfxsAb
-=RmVV
+mQENBFv2vg0BCADQzzfU42MkbydOEese82s5wyfs/qkUZOQatjwPMyEMlK/H7LZc
+Bk2ZOgBMaDDdEZv2Vq+6oUa/rD/Xmr71gCEk5U1rqeZZ4HuvyEZjjIisjnVrMCT8
+py93im2MJb1zifvY+rgiveiVBNCjSkfqX1/g7HmGiYL30romA/io3jvtWOo6PkQf
+GYzifOKz/5j9oWm1yqdXuhVmPD1aUkpXZeoxfWDpaPS+iUm4Db38umVj7GY55okB
+rrfQAdAUuOG9dyseIgI4HPZMB562Qy2tww5q+PvSxs9ydgSbFHFu1ejCmlViSeXL
+leGPJEoiRdyu9zMW5sU68lxhErtFRpa3IORjABEBAAG5AQ0EW/a+DQEIAMiknjyN
+qHzzG07PNE68DSlUuMvraoyJSkcA6Sjsg1nTgcp9jubqekXW+ZHnNYWZJSxZx4RZ
+wloo3+A4skthmDVh2UN/FO9Vwx1EGkJuyaKELmIVBRSC4IBrVrQ/4/nUXMtG9NhL
+Qmgug3glnlXYg5gqlQc2YjNiWI1zdYmR7pHTxBhDYLB1hweA8X7SH690HDevqhiy
+/qT8YAHZzMZaauj/xQHpvn4uN5xpGm1eQw47tormy7I/1QaDW3pbS4YIC+Q7gdYd
+IA217tTgN5OA8+kXuPJJQKDMG0WtEGegYjMMuNh266HMtfekJVSlJTRdIFQT1j1U
+0OLjrk9WRK/ZcrcAEQEAAYkBJQQYAQIADwUCW/a+DQIbDAUJAeEzgAAKCRBgT0N8
+FoLd5RodB/4pZu8Segyb2VhGYbl0jgmZFqMZDI9iPINx7oZ+09Ck32R6UJgaiaTw
+KT0qeEssum3oj7zz3r5D0s1k5pwvd0w5TLL8CeQ7NxTy+hE+8cHZbFfoMBlnr73c
+UhedkZk+Cf7dm/GVkv1ERr/XnL46wLO3OAMamh2wwo9Od2GP58ZFgFd3jhroIuTt
+YtBVeB21JO5eaktP1ZLi7zsGWcP2mPkQAnd7BtQGwjh6x6M+Xhs/mZEmLP2/nLEf
+oX3eaWU6uE54giiHDC33rBGerBuHGeW0WT7wzatKPz9S51w7mqPXLYNmw7/Qwfvi
+Ca2w4l1R/HAaNTH5suZ1HGKy1nNcY6aA
+=fcxU
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    B0F3710FA64900E7
-uid    ?amonn McManus <eamonn@mcmanus.net>
+pub    62BA9C275D14234E
+uid    Pierre Yves Ricau <py.ricau@gmail.com>
 
-sub    7892707E9657EBD4
+sub    FD2D3AEF63B97A64
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFdbSfIBCACrFI0ai/abnV2U2Wa9QQZwGk3Fegc8laiuTKc0GoYdyptd83/H
-hD5S61ppdkOugBjVTHdgda3xJ7zBZdnwjZvV/TyayQltbh6hU+BMlEolzXLgyvY7
-cAzKE+iKWbLLwfhRn1iuC7s5l1NLPsh44IUt3xDaFXNQrPO5OnRz8bqsGFVawxmu
-2bPqIjkhxEiYpxwaZZbDkgBR6rbBth6A7QOadQcj/9wNdekoM9dyg+olOUmnLrtA
-nMBhrvvbm2fZxTps3SZHlLV7+iSu71B5SqU/kT54/49n8vxrQiGvzp9K+t7c7EP2
-w4Ax1nYpRkCxYdHOX3YBdayUiP9ZaYH/YHtLABEBAAG0I8NhbW9ubiBNY01hbnVz
-IDxlYW1vbm5AbWNtYW51cy5uZXQ+iQE3BBMBCgAhBQJXW0nyAhsDBQsJCAcDBRUK
-CQgLBRYCAwEAAh4BAheAAAoJELDzcQ+mSQDnRqcH/Am3OQSYYBFrtOT3Zrf2NEma
-ojd48oWZ5xODFmqSs5ksd3op9qakbqkxITzq7BP6CkFbi2NEWYVbPp+jiSiGr02L
-yNA9ipiMBDyVZ7CXTBYqCQZ/3yQKOFN38U8R1SnoH1gDq/YdxDkSkWZEWQlXj4T9
-QR/fXWObN/oIdVDNONL99nqU0+xSvsE+toVHTH7upY7RcdDdnBEarKrifYjbCvpU
-0yiOgB1WOj91z/BrfpBFyJ6/qW2/qJun1Ja1bdpKPm0ZbTCupYOALJhf8dcznNDn
-gVCEB6L1+s693SuU2ZzFkdykpU/8WxlhjJcSqTpp8BIlwlFyOmZC7jrxArr2Jk65
-AQ0EV1tJ8gEIAJVavNan4WxxlwLwvnBj3/wcEWqN+kfMHENMSjmRWOYSmC332hhG
-LmTDi++BPWt2OOvHUusJV8dZP5D9yUBRFsKozIpyXyS76C5VYGMY8WZ6kyqn/mLC
-iwmnkOJ24kXLaaHPsQjv6i5f2KliDVhAGUHmNMJgH8o/GL7zZ03Mb8ZlKFZobp0d
-n+/lxoOtQSzR+cBz8NvMBkOKD8r4PJA6BxCR1HVEHsq4xSnjr/UZOYvh+Kaxfnop
-7Rn9in5MoY2rCY+PV59Xbx4grqNpjupyHEf1MHodJRj85JiClnLZk7dNJ/kr+zgg
-wbsd12/GHkBt/pxuWhe0eFcAOJmvqC3c4pUAEQEAAYkBHwQYAQoACQUCV1tJ8gIb
-DAAKCRCw83EPpkkA54FACACFZB2Tk96FQkr8+WHOz93CJs4UD88PosLaKmiXKP68
-arjH3y5jhNLBzqteZo0Crfw75DYWIZChdf5uLGKCWXBEytF4uoHOy9Lv/3emoSee
-nluFVcNjL7CIOQDRmqw1t/LjnsLbgvlwHix5f7I6Txu/J0HKJbq0XpoTqCzFK6sx
-EPHH3gZto+XfHk85haKd73SOM4edkmJx+jDXES1wb3K3SpYibt+uPVfLYXWxK7xA
-aztESTIqZ9RnYHzd/7z6DO4z//lfB7IVAqvM8ga7Qj58ObeqZxx2iVit5WUZ4cE3
-0crNGyXH/HKlAp+B9EvENnwr++TI1CGYthPLFHFc831L
-=MZeq
+mQGNBF/kpOgBDADKuK/xrCb39AAmyzVkFTP03ZNCAVhDnmx/1bSHTwvXFWQ2topE
+IgqlMpKmjuEH03gfOP2ibbgeJ3WOJcijqfeHNZ7wGDcslbKOnFVrcN7DuJx9LDYc
+1bjyuNIi+L/UCdrciDpFbPwMoeCZrVuxTBH6iHuhNETuA7c7NUJmlwUhQ7+qzdni
+TufaIeQK9kP4zeygqOWfZNk7zZ3FS8ft2mjhAKYG9RtMcNVbSUjYpF2nQvrhDUzJ
+qrAvtULH9TMLfE64n9S9fC3Zzq5OXBm2U/oL4SyVwfJGB/zPDdLIn9k57/Kx1Abn
+3r3AgfiFqRH2rSaMmQwLeVt9iEZVfmCsiwJ1iwyenRTxQTKHWk3vqUMRiH64C6Er
+QHwAVjn1DVgvCVRtb/gwl/3lMAdAV8Yfo9ljUZhGkGrzaHe0fEWseOiJ/auCBzWj
+HfXBDMQRJ8OCfqyUCGoDpUEtZA2mrXechdAxacwPnQQXPAN2vEOJrS3wVWSAwhNG
+ce83S+v8zkq0RNUAEQEAAbQmUGllcnJlIFl2ZXMgUmljYXUgPHB5LnJpY2F1QGdt
+YWlsLmNvbT65AY0EX+Sk6AEMALMIROt8lYitFNu8dNaNvhxqIANd7rT14ywe46YA
+Yg55xFGCGv1NIlgpdu+QzCW3MZr23kxQYTE0dLomq7YmIhiq4+bqRtzon2im9ygP
+Tnv3itkv7wOBw6dRIz8A1pl+0h5OYAohY8jUvKtpPsoT34o+A4oeDFiiGSN+B6WW
+Ptl/imit7lh8K7nvyGOcggLqwqQMN3uw+Wd6gtyo1sxngItPMaDV8JjymufuhpWI
+w250TAaZTBDDJh8HZU7jAnT4jtSP3LggFkDVdTnFJKbFng7x4N4qPscnmNHGnMm1
+HiXynG8MjX6hnyRTaIoX4HsNFVP+960lkAO2+fT0hv+apYn9oYnVTHuDeB7nGMk8
+fkwZpy5Om0k9Gbxre2RgADim/0zV7zMAcxVLwB0eiy/Jms+vep84oiS41QLdwYnm
+NDI6SM9ydJyfkip+vLuaQ/NnAQlMWA/gZkiYBzV0offSpMAzPoxLnkDzp/m4oh8j
+iO9ltvpHKH+/OuNcDLLxmKvY4wARAQABiQG8BBgBCAAmFiEEBOmy4fBuy74O0KrF
+YrqcJ10UI04FAl/kpOgCGwwFCQPCZwAACgkQYrqcJ10UI07KOwv+ILdBSAqr9Rfo
+DyoxdDxJIwDLC2E0GVsvd2uVX61Ke4QYnUt77z+xzFyf6et/RmCA/opxhQZyQ58f
+wggUDNrayL/DFCUM9eAYCoAPS68NPs4dLtBPbM29mDvuBCEiTgfCcwl5MKY/2A5h
+oDl1Dt2vemf2mjbHB4oOzwb27JUVOKoE68qr2yRv9rWwbJ2+ebDrmJ6LzLeLQcvy
+Pi72NaHZ2JmCebFoPDP8YMbAvudzuYmPq1ARX7mBhUKuRsFj1squb+q59oIYFcjt
+V2EkyHHEJDPWP5oKEAuKZravlQruk/R9i5xzJagA9DG7osWidwO1F8aIB3eDvnxf
+nrkcJq9dlg8z0OZuVBkxldl5hyckQhq/4ZmF5GbT/Sel8Iz3PivPYkoDol7N9Btt
+eKQiLj0k1/bFjsIJDsheAG7kuYgvv1OD6J32TVaHA3WNu/1WxgA8QRIQCJDdaWt5
+NFnnXLjkZEX74K846L8IOXtYDpCyqGyRe8sCBjlAVPvrZ/QBLs3c
+=xBjz
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    62C82E50836EB3EE
+sub    2AC7BF2F3349DE80
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+egz57oSj4I+NT33hA64x6jicEKyBNxNI
+=T3Bh
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6425559C47CC79C4
+uid    java_re <GF_RELEASE_WW@oracle.com>
+
+sub    D547B4A01F74AC1E
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBE3XFIUBCADcj1zw8m1evCgEMqxgOfl6L8y1tsYWsX7tVPvHEkYlXHrdcpkB
+fGuWPrauvhBmB9sBkFfxzU98Ilz3Xk9pfISYiaMUk9Mk1ZxsCoYPVhxvOSvk5LgS
+sviDzjYdZfZtskUM0sRmjmoQL//fVQbfLxJ2zses21za2VHuS3puUbdcm8+UIl/q
+oyneDbzM7j2nYXXJPNXJOfvyVxi1+rsc7xcjMvAj5ievYlWwYlAIgYbAiz969NdL
+RkoA1Wg+cQg+59k7Wvi6xwTfzMsO4jfkV2p24xn4fpcch9J49UhADh6O7XEls1Xr
+80WjysMJWTOX1O2oTtV/BMjpI4gj08SgZRhzABEBAAG0ImphdmFfcmUgPEdGX1JF
+TEVBU0VfV1dAb3JhY2xlLmNvbT65AQ0ETdcUhQEIALq5+uXjS4IHZBmOWOBSf6R1
+EnU4pUqEza0uwgIX5Xr2uSaaCMPCm5xrbtf/Iv45VEuR8zGKb8/0dV74me6nXnOe
+qD27pkkliVE5nMPQnqKAUQmrA5aDR7Tzmey46Bmc+IFrvbWqiyA3yZwUpi1FKZR5
+VLEYhMGI0qOyoaa1NWjD3LDL7/AmQESe9QLCtT6QhNhmj/QWByRpmuIhayNyPGlh
+5osFyiGgVcinlZE7x12uG76C1V7jo9eYrkjl/uHJHRqfB628oLubDFimKl1raYCl
+RZ63jkbZBfC1fRYzxk6356mAxlB2OVDH3aYB97KKZkU8cX22IMawk4aBhCyhX8sA
+EQEAAYkBHwQYAQIACQUCTdcUhQIbDAAKCRBkJVWcR8x5xIbAB/9HU+RuaFxAIVwy
+SrAvBwycrq5qb850RU9+KgrKo8CSCKTLdmphgBSE3pCMr6A/Q1QtOUndbm7SSq+X
+qODhij4FfUx0Kz669iPEVEZgZCausY7LH9aTmTJCRM+Ey2eM32Skz+ur0T812dN3
+iNd8HtC/iaJAoGFAnWRHetcH03QMEuogZp80NBg0CHV5Is8x0uh8JRHi8hWD1f6v
+Vq9/GwbgRsDOppVa8Z2BgyHOsBDoec/fYC3i4iF8rHuuSGqajswzG9SnFN1zLcGh
+LEUEOJzeDCANb1b2sJO2r9xEvfNcswj6ksY5lgItE1roCI61unkajH4ViHheqLZ/
+7wRm6eOF
+=Tyvm
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6449005F96BC97A3
+sub    D3DBC823BE4819ED
+sub    0162FE0CF6E18BD4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+FPjHFhRiWd3YGlydu4Dtzwfkmu43CTGp
+=Pq8A
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    64A16FAAEC16A4BE
+uid    Evan Ward <evanward@apache.org>
+
+sub    1E8F1D57A4450BCB
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFbqsT0BCADwERe1Rc9qNWwXOvwZHsjauVDy0TpqNVY8I3S+OYm4rX1dkjyh
++6bTEH1ys6bKevvR+PLhYzTGKboHnMT0RIINY/DQQSzHr/GRyCiiRlRvULbt9Fnz
+kJJDgH2BcbNSmWJlrCqYk+E3GAyQial+szkEZED+02wXHsbs0z3vozjQGHy0RVOj
+Gc5Shwk7Hr/F3vw9EQKa1nNffWmcGEx9B+WcC9ALPVd/fpQVXvlqfbi+kaIbqv2x
+NHQr7BL8j3SpN6vhfZM/3zeghlxQ5HYWER983XwkmvbNdMxt5HWsMKWZ0utt4ocK
+TnQP8NFGlPWEQhPvRRFNb9BI0wvGD0NUb1gjABEBAAG0H0V2YW4gV2FyZCA8ZXZh
+bndhcmRAYXBhY2hlLm9yZz65AQ0EVuqxPQEIAOPl0cr0rbuuaQWxwNjrHnfDgv9f
+oBgqZW7tCiXtWFH7Va1leDFloszEPGPlEriw04iqHpHe8QyUBVL6JhvNqEj8DR9x
+JyIKgsKCMkoJHdJOdO7aTQP8w7SVr7AX9sY9rRQAMYgktEKNqWSXm6/hzvNlvIud
+GXxr1dJzzVynZYlPFp9kmUmQU5ThzJ7DAW4fSnAy9z1abCGSHkh4EXrDwCyPvszl
+vMkg1djG0owZgDnTrrT0eu83T6uht+DHgCrLiEYqypcyxJmK48O9t20feAhFXw09
+1hGr51CD+C/bbZjcbXGmsNVuXUDUIIeVpSpPaUgU+i+OgHY7ZIF5f3EpEnMAEQEA
+AYkBHwQYAQIACQUCVuqxPQIbDAAKCRBkoW+q7BakvjJrB/9YMjhWouRH1Gppfdqb
++RLzjzWlk9ZlSUIIvuM40Htft4YGK38WOZBbN8vmdYAQHmqGbaqoKC+C0+ZXEKtA
+sQJWZoaYMWaEYgWHxNCxi9Ak8rodkPFmP3uVQqwb+iM5jhkCu9mexcFToL3rdBRk
+X4/lQvnafWkT8HIxXVHd6cR+tghf7BmyU7Hm5EU5Hx2BSkb+iGHa+QUJooPoolAe
+boLmUYGBQ2oYwXGnWeScolo2piqO+KmmbopyhxYBF9MfHpebeYGrGKCamxqVQoAa
+mNyzGwgRjqOec3/mLnLVd6iRNjzp+oS3Y5IVKRaICmqrqXExGW5OKrfdtKq5PFKi
+Yp9B
+=P9s8
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6525FD70CC303655
+uid    Stephane Nicoll <snicoll@apache.org>
+
+sub    DCF4B49B4D5845D2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEmhev8RBACz56FVQ9l701+PE7Nr6+6Lsoy5tK6wmV89pEvUDgDjT0VTs4EI
+dupAk4a0dLn8Lu87AloEYuSzbCxv5cH5vyDcvLDK6g3/sRC1LPQPydD+UlCvG8LI
+jCmzJYSJj8joVqTBLL2RBdR7xUie34e1RTvAM5b0UHnnvmsvEwwFRsb6CwCg7VFi
+5CrOZlhNeWcWqSpPZCTV4ikD/2xEBh5fUlpfo6qoWeYx2pLg7X7TIriD6IVSREmT
+ewrVXK/C5N9jcJ1zCERjkPOinyZh11MX9dau6M7I+72bapVj7Za49VHiPutDCb8t
+3OPS+ksddfTccQw0iHGDjSusJM+hX6wmHDBgY++WBCYX9TkZxz/cFutqOZ+HBYUW
+QiEjA/9p5vk/gpSB2UtmUn0StfAnwsqpiiwV4weS3sbn66qRYq3jbbAjS5v+jGwf
+KZjPpUyBitKW2Jx+BgPnFy6yk+u19gv7MOiKwikqeDqyF6M0fAjJflproQFLyHZQ
+7YFfIvhB0k76t7qSeCU9MA2wbU/DvDS/TmsMiMFqBuhjB6T8wbQkU3RlcGhhbmUg
+Tmljb2xsIDxzbmljb2xsQGFwYWNoZS5vcmc+uQINBEmhev8QCACgmZKuW7i4ej1G
+EK1SZI05zMZ/3baP3kt2i7bQ0qZEp3oySL10Z0K39MlIJpYVQt+hDusoNDLwhGs/
+XzFon8rOEbp+OH264DS/3H05GwQcHleKHez2C39OoLo1Z45J3xFl4bpjpKC0VwD7
+lrdQ/3IVJejTFLYi3jx/8KUHX8jVX6JCNVcLeluzcvAYmVpyU0RXxE6RcOHJg/Bb
+otCRYQNrTjd1IoI4V7oWfK0P/2+/3bB44V7ulKW0QmIePP2qlmUCrcIA2yOqyqpk
+lTfr7yunKIl9KIddx2OAKINDLN1CbkdCXRxTV7X4Jpsysv/z71foLVrh1Je7740N
+eBtUHmGfAAQNB/9neRSpK+mu0pmOHaiuJqWySRDqNCUZNIKhf+hQCwG+exVJ0/QI
+dScjSZh8iHhaG6InAeCa9N+OsDNTYl/DDD2CXDo6WFc/iaC8zbesX9GT+CkBpR/B
+5LLpNiXKd/MUdDoc8hgRmoaYs8n+fxriuwgZJZxbb5ML44QjtGBi8L4sm6hdOiqf
+a09DcC/cl4Rs7yd6eTdIm2tHvRy7kXvoA0nCAK7C6D/KXO8zvvgO5dB3i88V3iMX
+G+P8C8qzmK1AAZFoid8LGfi4dxRlzZaIbLtPbwKkPVDem1TJuz+iDIMIpr/FUcpe
+73BEXiix/xTUN0OmN9pt0pYbX5ExvHTzMft1iEkEGBECAAkFAkmhev8CGwwACgkQ
+ZSX9cMwwNlWvSgCguZkdMJHf1/AklOvdwAHP+eOM1C8AoNIKAHiqrqGbgZvSl1Fp
+Q3i7h7uk
+=KWYu
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6601E5C08DCCBB96
+uid    Popma Remko <remkop@yahoo.com>
+
+sub    0AC07D0BBD11498C
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGBVUWMBDACXALXWXSrB2V95lR1L+i+sQsTQt8tCIgX0iX9UZ7Vw2K/lLnLw
+WYtM3oTxYox4OdgkK9tK6771EdCH5wQtRdUQJjlsBfZDPMiGqmh1jrAxAugEkFyC
+anVQ8VL1Z7uPeqw4UbtqA7Or/E0aOhF3zkkmhaiE9Yrp+I3KXWH4F0Cj3X9IUcf5
+Z93CPcEFQx7ajxSJ1xw/mSgbU4AtKZXUdK1ehnFAhH3rcMVW9paFSYaXD8f+vUbj
+hdJOp3e9UYEFShsdwo2X0FRqI318ef3gPDpbTATyCaz6NMIybDgRGo9WOGwF+Ysf
+snXwLU2UnT44kpAzHjFdjZhQGcY1w7d8yGNrYX4qw/RMPhmuVefuF2yodBtRxhWW
+09dwNiIYFVuGS4S03vlnEfYZlhmRgvWZK9PDJXm0vE5GI7LdOKlqwZxvoznjGmUU
+lscRU57DtrNlAjyXMZaGdNfPIG85B+ijJmIb0REHbszvG6csX4g1MiZ+i0WID8Jl
+20YpJTUkkvIztXkAEQEAAbQeUG9wbWEgUmVta28gPHJlbWtvcEB5YWhvby5jb20+
+uQGNBGBVUWMBDACp9Vpf+IvWC5bHXRe6bYRYm4LO74f5GICC3cqfHNe0xzwnhDM1
+X8Kve87djZrWp/Q07yjh03iccddZsH1Wfme0b1Ue3UdrhYMuvvMQPI2k+IR7+wut
+AsDlMPbyRcgnhaAO5URhn7PW0Hq2RxmRTPHrXzajEJUodT2VgjEC9DOD5cDAU2gc
+SUJgBANOvIoPEQAMBsYMRgYUczjvr8wTPP3kuqBq0MhZrETpENIGOeNIDjhkewkb
+BweOubP5FeAWeFCML/3LBLM1lA1bNaPJL2qAuYgSQcxvqYP95AesYDlLK8SWogkw
+y9etGmegbWXYUWI2frTDK4H4XO1/H1iAqUknB0t+YMNBO5UidotTmJMq9ln26Hx6
+RqO1ifc1QRu8A3VIryCdapNGFUib/TBwF201WJPK1MfsIzQvS/HgVmmu7tzYrIVD
+HYbj/RXEiiULMfPZE4PezahFO8/oHmvkR0KLOuwnOuMyWO/DWGn30Cdd8k+00zJ4
+crCR/FVfwrGeTacAEQEAAYkBtgQYAQgAIBYhBKpBdze9gFRW2zy93mYB5cCNzLuW
+BQJgVVFjAhsMAAoJEGYB5cCNzLuW3OcL/15j9/sQ7mzMVeAQPQlhMaFhtrheMPyf
+0eOorklsJ9afcBPsYPCtY33vibJzm43MiPeys+tW42B07i3wWnrcS0ZChgCHzGoq
+nF1QRu+O+G8hZ7EARNXMu+GAmY2sxCdF6vJtgEY5tIM82I9dtMMlaqvx6hKsVox9
+YZkvK2yL4x0F/nVD1VQTf3zUvZNrrdrowIf3cIuBTzkgTE7FrfaLsvdBZC2sNYuu
+NAY94zHsfqlppCGNjSB5Ig70S/YqPp1WYxU6yiXPRMY6qyNIO4NkAmtIJFEEDveY
+bbpvMBYYo8vcVjEXuCOQWQuMbfnMWu70jCC/3E0zn8RebEI5kdXxk0D4+pDh3TFV
+nqgi40dbwmHEv4p06IBCzaSoyzDfYH0Y5i9kZ4zUM1S9GEOtFwgEWxD80g1YU+Wg
+Mr9k+0YfV/wXDbIPLodc1J9OCnwqrzJnxZiRO0q/xM719KVhsJqR0I9e5trpPrft
+AA4fEAfsK22q/zZWGn1aDs1RyzdSprcN2g==
+=CEC3
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    66B50994442D2D40
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGDoYisBEACqUDZnT4h6ma6XIzdC6KR++uDbR2VKdhCuv0Og/sHEKkm6ZbG0
+OFB8tAaQx/WlsoQyf3DlLfUEOGDai875Aqor3fbM+E1hrZbQNfsOySKEE52k7PYe
+0qGWlnAzINuQaEuZwNw+pjZqPraMlwc/hwzJB8yFNHCv25pCFohK7KXvFGr5Fc6y
+NHBp6pM3pnDQ1kbkloDr32YZY2LdrfdkRqwa9STNMcZtM724aaInValFpVGEHolF
+dklo9MIsMI6mVHlxi6UwFSSLltUfTXGYY+rt2Q2sLNnEKzK1GvVhK996vrNWCvpr
+cdtbTzGE3WK4f2knhqzlaX99OLmkM1ah+p2EkK7HgWM9oEO7SYpNxKe/F/QfRNRS
+4W0aokPsEtfKCD7vQ3cRWQXdqFwvksilv+b6pcSrwfAsaCzVuhB3lcIra4MevJcH
+ZEbPrfGMi5/MIVtLayglLHSPoZtjQBhlqo8w3nuADR/aFlIUZ6NGOwaz5yXIGVEs
+6E1wiuILRAd7ecJ3Zyr/URHjawfHfKMM2tNCJKl48cScBMY61FJ1EmYzwhDw+at5
+D4pCk75eM5/t6VdYQ1cDWm7J3LGXEANMU5aSZMqgVnb4SQEmRxkW7oq3Z+GIkQQf
+Sj4OK6Oi4cUpM7b0m7Cbcsoqb6nD27VKD3J5KTYEq3e+78h0VRjhoi0Z+QARAQAB
+=UUB8
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    66D68DAA073BE985
+uid    Ceki Gulcu <ceki@qos.ch>
+
+sub    A1766BE5F812AC2E
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mJMEYvEGpBMFK4EEACMEIwQA6knc/2gtbqDhPh5EzrymR4Hwi1Xf2S0aqMopA1zg
+IeZzBgSfL+4fEfpXL4eAzvrk29jIXSizDEOgFpw3PW3Om1gASxub4Jo6EQrRgOdd
+OlJl1bajIRC4pAoZafDzhOb+FkjJ61lEJzJ6pQtG0Yi24QWDBfXHkSiQSbZFvcC/
+FTJpZua0GENla2kgR3VsY3UgPGNla2lAcW9zLmNoPriXBGLxBqQSBSuBBAAjBCME
+AdqQOy84O/j7xo1rAaMB3jGHCn42wBJF8nMVZ1oh6WRN8d33JP0ojCpCK9oe3lyx
+jZRvBsVkFhOF5lsb72kqR34hALXmZvhwFhzNoQlz4NuDLg6aQjAQEyiS7NqI2SVT
+qbGoyIE6yg2ZLuv2svxk1dNlvtqtfOnmoeIZG3pybRRhyuIVAwEKCYi6BBgTCgAg
+FiEEYCAKxK52HxYU1sRnZtaNqgc76YUFAmLxBqQCGwwACgkQZtaNqgc76YUkLAIH
+aAcCM1niPs/kj3NEmFl3P9ivExlWa6Q45l8qPgitCLO2v932TElX+ux8O+fv0Ax2
+XJezAj+eMV+lYScyvXpmzbwCB36nuPmtsCJ31kYLXhN2WIJWPvPVesreI/GQUq0W
+uAngfd6DOtCKYtNKP7xqDu/2bMU23cxGaRj2ToH4RfCClg1B
+=rv9Q
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    685C46769DBB5E5D
+uid    Egor Andreevici <egor@squareup.com>
+
+sub    CA7AE93399B1ED99
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFqHCi8BCACgRpCaVCiJ2MccCN01SbHYowmM255nSYKOnfItBmXYAMtc4rL9
+n1y1qFtc4LBbkIrPH8CO2zpEImUTZel4W93BQkluPOO3EX/hLCTCFfXrO89L1u4V
+XL4siS8vZl3DVDdY7m9G4vcpiIsggGF683KNctN2KXZ0D3tu9C1X7eJk3GyDo6W7
+MJwiiCm10968VqFqIFn1rTkvtGtXGP61Vqy7kLTdiBrKbo1HkZDbryl6nvCmT++E
+auJXEDYH9R+vsODy10a5in0n0EzQD4DYadL6cQTbwP2SvMbRRRQ7AnNtys6cNCCb
+CIJ8iySLaHYi65w6FEbiBM2XQ2hzf8Dek9yDABEBAAG0I0Vnb3IgQW5kcmVldmlj
+aSA8ZWdvckBzcXVhcmV1cC5jb20+uQENBFqHCi8BCADNge2accRlVp3VOHZzygWv
+f9BoftQ/tfP6WErJiCr8WwqaRDLzyrFzFNfiQx9IHyywoV1oK0FAjrKkVW9pSbyO
+fUsLR1U9kkcoc50MSIt2DsHbRs/N1jTHn5hq/tImNgirndXemQkZnIc/0K9n8vm4
+nn7awXHWePWrIrUVZXHZVmTZOwWYvh+mICLpI5dGgZUuU7SwKpS+UfZ5Hzvf/W7l
+hrfzsSfiStae7RP50fKDn/G71LZDtcqY7sbIRRdGdewk+6voLBelRqh6hchzJ2l2
+OX5NHvQ6DHIAayt9BhU2M+9FUrjJS/zf1fPyYIinbUJGxyzHUgh6yEwGpEZcijwF
+ABEBAAGJATwEGAEIACYWIQRoL3Ze6nGNJQu9svFoXEZ2nbteXQUCWocKLwIbDAUJ
+A8JnAAAKCRBoXEZ2nbteXasIB/0TDKcnc9vvQ9xJVugajMUKdJrIT5z9JuhIrYK6
+N/DUXLZCvRiLNcvhEATiNfMj5jcRhmlwntczFSF4FNmvE7wAK8ysDCYwLa9/USgz
+cNBWnKhUK/l3U4hjqtgKPId4FPivCyXwYtln2+yMZakj2bwlymLeOEyKH7N+t1pg
+mkXO7kwDbL91XdpifSSk4O435ZVZHIX/eOEsJm2s0Wdlvel+tL+NwMz6R2LKof3A
+TqLK8jFfxGTtr7UfTMWYpA163F0xA9g4NRJdAS7KBdpkXOb5t9ZT4T3H4cKl5mqY
+6kFCB2EVkURf6u73uzTuQExVSVYzizi4RM0osjDOQCTYWVsb
+=RQ46
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    689CBE64F4BC997F
+uid    Szczepan Faber <szczepiq@gmail.com>
+
+sub    C0058C509A81C102
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBGAofm8BDADhvXfCdHebhi2I1nd+n+1cTk0Kfv8bq4BQ1T2O85XlFpp1jaIR
+70GAm2MOt8+eEXt/TuPkVBWnJovDpBbkUfYWxSIpPxJzcxWV+4WJi/25fBOq2EuP
+QQhkqHQRECQ0CsogzsqI/Tn3FksiGKB7v67hAetM3KpwZ5IlG8chLoaeDf7k3P3S
+fBWO9MFxYW/7K5G3vqARKXHvzq/jYiXziMDeWIKswwTPqfeDc89tsEdE6GMT6m2u
+ECaulbHlzEzazSAh322/yyf/nfVZ/yZhK1y0MjvwpOhGxFbay5hA7L4bHAwR3qb9
+YGiPIL+K97TYY1G5+3X0TSvTIg4VsW5VDu50oB2iYK7uGE08GhT4uc73tiDlZm8L
+BUwT/KtKT7g++LYwAMeZJ5+rfIKKxblXUN06vz9stylo1rNVhTXftuqqO+x5uVGG
+KlOWzx3p9N3nqrufwuoQNvIMzCAvJZNm99j/Y/40wsrUkBxVBGNs6nEpQ6c5lvf3
+24Dfk3nY/7Fts1cAEQEAAbQjU3pjemVwYW4gRmFiZXIgPHN6Y3plcGlxQGdtYWls
+LmNvbT65AY0EYCh+bwEMALVHwkeMzw/wcUboKcEUmmXmiGgwDn4xac47U9x75JgC
+OqQE1+4Hxu5qULrPlCLLP1PDmD2PK/QUwbGpjjEuw4YxI6JjuOQ9sQa7HbzRVOmw
+0kd0T4hr4Xa37D3E4oAxqwpeXcPsUWewtpjoqjLpTDBuaRpp/x3sFFmM9+s2ci4S
+614yppuWqu4X/u7w5CbWFYMKl/N5aqK5RYYMAgPUqsI4J0NKwb5UszFuatFevTvD
+MuwOf9LfW7kun13s0Z+/+hWGlNhk38ahIR8PSr4yT1pR271dUQKCTtZUFC6ObVAY
+WAaEzrJ2XuJMnbHjpciv9WqaXFLpda7eE4TucmjU3+W29kWer9ts48EkD8Hv+a8T
+BXXzK8KBi0ACUJi6uma1DWdUk6tqe2CniwirRzR1mWhKfOmQqr487pH5h0jMSPN8
+Dhyyuw4Ef2BLmTQmvbDYv9bwkeisskKjg108OoWOid1tbXudFdPQWqNc8FVPMlde
+kza4cC4qBd+vjVcKHrEx3wARAQABiQG8BBgBCAAmFiEEFHtpGhkJdiSQL06paJy+
+ZPS8mX8FAmAofm8CGwwFCQPCZwAACgkQaJy+ZPS8mX9PxQwAn+LmPCqO6ig0fsgi
+nOhUaoM2QX6A//IiFDXa2pY3bKaWf5LAYpuvRAyMsGPI3ceAnwfFSMXjktlssmD5
+bQKFisEuCuFQ0B+dlMO/+BZ1Id1Nldi8yKRTfcffgONO4kuKGKN7MKWPBX6/cJfA
+pwHV7QubGEl/b/UNjPVFv34QCLU1ZFhVKHO582m0N94dwkwThaQQZX/op+cT2kSC
+DWn7zl38KoYSy/6ThxKyIWKimiEpug0VeRHDoYw2NUyVvidj/F3jsnbEiNTH1Rpp
+DzXuJbN7c/fxaAAhlAgxnt/hvrECPylnA98CPd1tBl8Q6IDcgbXmIa/jLS+Rqv5Q
+xUNYlwhcFP9WxU8RwzxIHo9SiVRUaLcqit5eVI+eZbcL+TZP5b8wtLoKr199Ej2F
+xNkL3+InFdjTH2Ir6RZpmqeY4NI6ujL41iUru20RzTNCAQA8jgmCMq9kDxaykpzd
+SvFHnyijywCZB1jblPtxo2UqRO/qhPfqSkoVcpWmxgiPUFOr
+=E7F7
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    69B8E32E23138662
@@ -15354,61 +8126,172 @@
 iyALtqtIyMOQgO/qrtyxLC1f4If176Ylhd8d/Yk90OYN4N1mWCXBRBY9yQyOMyys
 ISyEA2GjxmLxgMLoMCfUOczcoLEqgkSXGvGvABEBAAG0RkdhcnkgTydOZWFsbCAo
 R1BHIEtleSBjcmVhdGVkIG9uIEF1ZyAyNiAyMDE2KSA8Z2FyeUBzb3VyY2VhdWRp
-dG9yLmNvbT6JATkEEwEIACMFAlfAYzkCGwMHCwkIBwMCAQYVCAIJCgsEFgIDAQIe
-AQIXgAAKCRBpuOMuIxOGYkwrCAC6JjooHvdxUuAEGtJIj2PRqHv0CDzoJOp3ZMxC
-X9mxqepCQYU+UyQS9gcjOwk9MKNE1loJ334Sv2xXfbewRHbuEZhyy9Qay22JAdOl
-QNoW67eKC6gO5iC8dcH2njn5tW2KGtlRItu7MjIEO72YzKgPFU1KvDQP0DxdRj5H
-IU61Vk+tiZAzZjZ0PCI9S19F3fpt3eJ0wgM1nCKiZfInkBwXzFP8SIMbr8K/qu08
-X+xFzNrz7tOMkxPhQmlxcUx3Cp72B6+Kzqyq5c/rR0oCo70uXB6tmAE3TAClnIjo
-tgOL9uTPYNozwilQCEzGpO7i+W4UI+irlJ4DkIrzq67q5X0puQENBFfAYzkBCADQ
-wzS0Qw4IfrBpO2O8oVLmuGn7vcrJwecMK353HJgLq5nPLOyeq91ry2Id14zklv/F
-/8xeUod8Nb9uZBVQTKLynfoCcPwDvJLkKoEpMasT1B1npoz1npQQraNWBaaqa6Ci
-98J12lE+leV9zdu+cRN6SZwETtSmO9NmL+4zZuRpfpni6grEhia9z3lQYslCxovl
-j1VE10S93BqNovY6fchP4RXplNBQdBwRHdR96k1+vKjuLYyDloRW8VsTSvBIdprM
-2xijCbujsq4QVi8rvvEEMFKRt6kipbMCDkK5WqMTCdPQCMjBrFv1fb4s7W0/lf9T
-OZ/LKx7ZZE5EMncW/2eBABEBAAGJAR8EGAEIAAkFAlfAYzkCGwwACgkQabjjLiMT
-hmJEjAgAiom48h2A8uSRGf6rR9AMKnMXQumwk4W3eoXMhygLvozxqJ5YMI6euNs8
-gF5ehK4OwPOIyDEkZbkp0MgldD3zdlhjAN/rxmMBSItUQfgPwwgC5f89vpZJNwUW
-l018OicikDUo60ecswWzwXCUfIzV3OqKc9IB+NQZYrjMnOu4zLewPTawpUfrW5Fw
-9EBn20ktBUXOo+d0qyqi4hzjKs2tjQbGyTphU8adrNtG0hpjOXsLG7cHWY968Ew+
-pc051SPs7QqRgrL5bLw1FsUP7kvoGGSzf6J2UtU9O0qY4erXSl9219qGmGSzb8jd
-b0ZlGu3RAziliAj6KR2YKGp0fCBndA==
-=lNGi
+dG9yLmNvbT65AQ0EV8BjOQEIANDDNLRDDgh+sGk7Y7yhUua4afu9ysnB5wwrfncc
+mAurmc8s7J6r3WvLYh3XjOSW/8X/zF5Sh3w1v25kFVBMovKd+gJw/AO8kuQqgSkx
+qxPUHWemjPWelBCto1YFpqproKL3wnXaUT6V5X3N275xE3pJnARO1KY702Yv7jNm
+5Gl+meLqCsSGJr3PeVBiyULGi+WPVUTXRL3cGo2i9jp9yE/hFemU0FB0HBEd1H3q
+TX68qO4tjIOWhFbxWxNK8Eh2mszbGKMJu6OyrhBWLyu+8QQwUpG3qSKlswIOQrla
+oxMJ09AIyMGsW/V9viztbT+V/1M5n8srHtlkTkQydxb/Z4EAEQEAAYkBHwQYAQgA
+CQUCV8BjOQIbDAAKCRBpuOMuIxOGYkSMCACKibjyHYDy5JEZ/qtH0AwqcxdC6bCT
+hbd6hcyHKAu+jPGonlgwjp642zyAXl6Erg7A84jIMSRluSnQyCV0PfN2WGMA3+vG
+YwFIi1RB+A/DCALl/z2+lkk3BRaXTXw6JyKQNSjrR5yzBbPBcJR8jNXc6opz0gH4
+1BliuMyc67jMt7A9NrClR+tbkXD0QGfbSS0FRc6j53SrKqLiHOMqza2NBsbJOmFT
+xp2s20bSGmM5ewsbtwdZj3rwTD6lzTnVI+ztCpGCsvlsvDUWxQ/uS+gYZLN/onZS
+1T07Spjh6tdKX3bX2oaYZLNvyN1vRmUa7dEDOKWICPopHZgoanR8IGd0
+=CuU1
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    5E1F79A7C298661E
-uid    David P. Baker <dpb@google.com>
+pub    6A65176A0FB1CD0B
+uid    Paul King <paulk@apache.org>
 
-sub    A7CC6488427379A4
+sub    EA8543C570FAF804
+sub    CA890A5FA09CFD80
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBFgRFtYBCADud9fmvTI8Dbs+9GcZUIVzxkL84QYHSDxI9fF+sxfAviq1U+YJ
-a+ZLIW7HsXx8vpn3hqIqAbDxHjrb6MEJ3OWD5Ks7O9Lq7HOhtqAT/mpV3fZmf6pF
-zdEw7c4UrfbtKyBY2kSBpKzTfu6HD3q4OBDm59Ezs2XFhKrXtlNC0fQ30ysBpIvm
-vZH/opwlBgyELKnAYJ6eCmdW1iiju7DPKDBOrGi6zgvslToLpnZeSg6hzSyjM15n
-Gx6Dgby0GNR4VEVze/UdOpsFVTSfP9qXgdt5ZOWQqW2Jg5V/ezvk+3Ok+ecfHWRz
-q8tHkagnqn0SfP6mLqUNvmvAH7xp8crH8L/TABEBAAG0H0RhdmlkIFAuIEJha2Vy
-IDxkcGJAZ29vZ2xlLmNvbT6JATgEEwECACIFAlgRFtYCGwMGCwkIBwMCBhUIAgkK
-CwQWAgMBAh4BAheAAAoJEF4feafCmGYepYQH/AoDwA/N5Zq0z686DtrAu3KeQCap
-YbI4oNQ/yhCuCivJy9ORkqOLRZDhrfkmwFmetOmDeg8GAfoMEDUSvgXLqqli4wMS
-UNNlRA18X6g8N/FS7w/rWP0wp68boPK/Ry9Q/f7SFmMxrObT7aSX4hnhzWZfWTZy
-YkhWN9Y3+nXFtaT/XViZtHoxLZP0Ei92N0zcWGkKs/drH84OS+XMVRktCNExyXUY
-wD/cyD9n6r6f/TGtaL8cpXqu46IhLpeaPMPWqikZCLX/2KGSwiO4H2juTkkhQn8E
-bCZziDmfDY6RAa5xrsOnFeLYGbqbkoK7BfR9d+tMFtkgkXxqpHFMjW3a4QG5AQ0E
-WBEW1gEIAMuetYIGcqEC7KdfWn6EKmO7ZucfOEirvo+WXclo48WX0Eo0gsTghKPG
-TS2kOzglwn/wYCbBVKzYaOngZljIcrR47hJiY/u7OH7EjiCiB0sh5WuEqOaCPPFo
-8lCA1+SBPAF+c1d7SfIEABL/WCc6e1rkKhe7wkBSclspL8YQUG3cr5G/cSCGOV69
-TsCqq7rtezjkSsfE5dxmcs39Ouur7hs25DKehufUA5bV2i51v49WIuTE8x53VfIn
-YsJyeRs7f4sx3hmkwN+EL2mo1YFymGwEkp8iB0Jtrpsevl4AFOajl6X4IrdLn6+X
-Sok/1mzIm+t1ZHokQ3mUWe5FC9c1Y1MAEQEAAYkBHwQYAQIACQUCWBEW1gIbDAAK
-CRBeH3mnwphmHv59CACEnAU1vbN4qxquAzNuaalyV6Hyx9olUQqPHopRGBA2ulPs
-0l+gtAXz5USotNsh3Ai5j39Y4J+qxN3HuDtscxEReogawzOo/B+1IKuGuuTzvL6f
-U6ZFUnEosxChAKwJo9eS5xlyenyumTcXx5yB/5X5nqTes6tcZlDcEefh7K5Iaazw
-E5caITBX0ze8g7WQzRxyN+vuhY30U7P8TTKxAsavdSBVIb+Hp0e2W2S5T3ogXaGk
-Ii5qllr9uhfX+E9zLxJJKfJot33ix647mPwpXxo7K6teo2rkwOTQij1sEe2sbMZi
-KZkn4rYSgLpZiVLPiDYuP3RTuHnFenYROA/YcDvA
-=qbvN
+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
+=DRFY
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6B1B008864323B92
+uid    Terence Parr (ANTLR Project Lead) <parrt@antlr.org>
+
+sub    FA6831EE37606774
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFTDM4oBCAC9cUMAjkP1dD7tt0JUI5kVORKagn4/zG6+Y2MUwGgJs481xsFC
+jXPuNZMucAVtXmw5Sl7FbsfSxR/9jJ2pnbXL918eRFbUqY4LnuOTZjcgNWo8PWPc
+0NLmqoLj3HXaLrpB5cRIXaQvzmfoWxt8o/ZWq1zSfDJDePuQb6qlWmnoDz/S2YJb
+f2AILPsljTE8kYIBHORGilKtUXtQRjs0SCqnbx+DSDAVKSnqYHWDMmxgBMMQsSE/
+RQ/EZ7I4eGRLLfONCxox0fuIt4kOLuMNqGWQlqiG2Kp6Uulx5SepToSrPZLyDGVA
+MgefKrKe/lzKiLeppmx7ELXOKBXlIvTFZBuzABEBAAG0M1RlcmVuY2UgUGFyciAo
+QU5UTFIgUHJvamVjdCBMZWFkKSA8cGFycnRAYW50bHIub3JnPrkBDQRUwzOKAQgA
+y86UOqIrhAeN34v5QKv2ZGWWNc6rWi7ieC+dnx2D4kmvn+BLaCX7hJCyNL1ex2Tv
+ZlhXt8cgA8jAVgN5+aHTaJwpcTHUpzx2p5UIe9oBAEq20NyjF3P9o7lt1C5V1b71
+EKMTwTOSfWUcK0Skz4G/+gkhNjSVfxYwZO1v+Ce4mRCCRi6x8pFGHdyukVR0wJ/o
+8yKvQijUciGMEbnpDC76N1eAQgd0wo79WWGZty+w/qQSknXwTTJ028LlumuVV8Ul
+YxZ/eYYSrtK2t2w+6UG16TqHATDFlEyShzYJCer2H1fmSGWncZZ4ODQCkNzNWirP
+n+q/Rr8CBo7PlMUV06OKZQARAQABiQEfBBgBAgAJBQJUwzOKAhsMAAoJEGsbAIhk
+MjuSZOMH/2V3TM9qXvwiGsmO2msbIta9b2MbvdlIj7EfI9rt2azPjYTLiQcYWWnt
+KN6tYmB61kK3qzARwcW8pJQ0FiOoXEG8jqwHUz3bIxF8ftbq3peLUJi03PDQoNlT
+pKRuj5EvV7M1f1uZGaKU5W8+BVVxOq8exMeyDU+8PifHmW9S1iFPqq0gPqjljlzz
+cIZH/JM7pq59uoj3YuNz2X3PreQPXVaz607JXUhxJ4MIEqEy/qjD5OGZRKQr44eS
+xk7938j80OcBa/1IbbjvGs5oi2IYgEzpV3KGDU+kSDHVuKcwloU5qMC1Vvhrkild
+b23wtFBRYIpgke6HBcaQOIivCatSbBI=
+=erSL
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6CCC36CC6C69FC17
+sub    C694465FAACEE66F
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBEtrDFABCADLXGAhjPxdh+naC6XU5kficZYEVAURNRa8MTnaMKr+31v2zcAk
+nyqyjihcXGQBCeaNsz2mQkc/MrKdnFNVSwp715JcmcqDJGfR9aIDMUs9PvoNkkqv
+IDtx9Tn73piqbplT2xQxd7HjFvaVuy7oXI68gwcyAGDvQZeiFUodcbAsKrVwFT+R
+94JU6UODFqE/Ihq15Za8Sc8WhWitm8XTQsCsLeh8abGhkvNEmRLi56fh8/Bz8LHv
+8T7r8zkROoQFlUEYaOR2wH5bbipww9+HEg64hrcak2w5smNt0NJUXZ2O1l00u3sF
+Qdu54hM9nZ51xxcqvo+tGft9kIr2AfTrJ28ZABEBAAG5AQ0ES2sMUAEIAOqnjBPR
+FjX47AxlF9NJhzOUECJ2QaoezMOcKQ7RTnDhOiDi/Tzl0MXJoo7ktkeSAMlPIXlb
+K/C2qrM2hT62O/5GSRy1dPErTZx53mNIWTsT0wjQCgxeiAs/+5bqceahRO4PES0L
+J7VR+wiCUP33CIK/Ea2c6ODB97OSly0/RY97jWbM1xwKuzeHH5H0QKTJky1CIdg+
+avdfeeHBDEpCi3BZA55JiAKMuFNYl+Q4yf/FoYI0ZqKFhIwK0OQLY+unIPlX+qPy
+B6TkPIj9tcK/cebpN3VcFvNzVkcqYXdxwUU9G0GyzC3Be437oyzm3SJWw1DRd2Fj
+wFeiL0fWOjwcfvkAEQEAAYkBHwQYAQIACQUCS2sMUAIbDAAKCRBszDbMbGn8F0LE
+B/9O8wwEDuRjidsflZTopMs2drKS/TN/EB/leBFsOqtw712+dYSNhM/LJVZchWS8
+y0RLHQMAd6aX89ooJpvmkijJvJhB9YtuHwmGfT40uco7ATqbo6tYW/aA1rfOs9HA
+jLb1UWQvEsL+96WsiQRLwIoX6AaKebG6mLYikiKKji4LJRp5HVdXpTxRaX/nSPSL
+aau62V7XKJXaVgFvSTy4xn2eph4eRVACKym/psNkXbRyj1maf4a1sdq3WMdiDRHS
+n3rRKsUGVv7HxE45vR7W7hqN0Bna4VzOgNEocRCKO9pDEiOmXsKXUvDJBOrvTddJ
+VHX3/m585HZda1drtSgEv3Rs
+=VojG
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    6EFF5EF5523052D4
+uid    Thilo Schuchort <t.schuchort@googlemail.com>
+
+sub    E2F840B227D3C024
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF2ClL8BCADs2bbaF1ZMiMkTUUb59NTlyAbOOVWoIh7cnKeNjMWBUTP0kLFI
+XpoKiyccQLP4rFdbP2yI6h+LJR0Kj/lJmKpCaAooNlooxfIyPUX5TMvDTRutzwBO
+c38DafLBAJTUl5BMYsbWTGSvmpC3/qmZ9uJAQH6BVEQxmGNO6jpPsgi/YA2AhrN9
+w1F5Pm5Capc8QQ9fEj+AohXGtpOA6aMhnPLjJ45h0VEwYskRIva0AoqbM660YVi7
+HZPNEqspOtmCrR5yzvRmlDmQQ4uKp4InSQ2Sz0OMw3G9cuZy5AzfAL+/SG+iL626
+S1UeIGAjsCu2GGIFDVRuj4KvfmUZz1H/US5DABEBAAG0LFRoaWxvIFNjaHVjaG9y
+dCA8dC5zY2h1Y2hvcnRAZ29vZ2xlbWFpbC5jb20+uQENBF2ClL8BCADTHfDxM3GQ
+a5cwRfENxEhdDngpEXi6nLw/V7Gsk96dW60MC80l4cvFz+7CsB88ZxH8MgkJYttC
+/RPfpbCNBKlb5UHFfjUjn9hGunUFGpS1PWv0XHkqh2kb5zQ2yOzapK6O77/1EjlP
+K75875uBh+458+rUT0fs84e7fcbPkVqntkHtWZE/Dm4A5TZ6/rtCr51x9wqxuHRN
+TCQSsZ3OnkelyykS0fGhAKlzplflO2iPkVL3q839Ug6e/CBWPE0wSZ4KPAeRxcmS
+RwUbCQkLaWlnHvL9S/lE+N4ougmgooeh9G60vvbeYY5F7+6P/Slh8vKB/C1pP2Sa
+xZltnA0KsK5BABEBAAGJATwEGAEIACYWIQQqT1XZzaWHdzH750Zu/171UjBS1AUC
+XYKUvwIbDAUJA8Mj4QAKCRBu/171UjBS1FHHCACOpCkLg4vSKDKwmAjFxJQB2W0n
+TzQ+j15RyvGzMhqQfd9h6436+0qLfs1tMjwHGW1tcNkLcnEXZWrGSqLqjDplOTc0
+xLRHjYO+QGM7gMa+kgXUX7iuSIXn7DcIkcfIQlga8G3gwZDYi+unWuwL9UprOAbs
+GSXXrSawyrlMxQC9U65OfekyWNVRyxAsPEry8C9ojaKjHd061aPTDSt1zc5aa58K
+Xtb9EOJw/Veuh2bZCsdld+0MQyvqoH4e+R6xYKdz/KoK4KvVReqxOwnnb3VTelnR
+EKXxpMXCWhJy3DBC8bFbFPi5cPVt6onW0YrKgHWTOHBefO4IGvMJyZiHdybX
+=s0iv
 -----END PGP PUBLIC KEY BLOCK-----
 
 pub    72385FF0AF338D52
@@ -15453,37 +8336,387 @@
 =NN0Q
 -----END PGP PUBLIC KEY BLOCK-----
 
-pub    353A436E043E3145
-uid    Garvin LeClaire <garvin.leclaire@gmail.com>
-
-sub    7494750BDF4F8FAE
+pub    7457CA33C3CE9E15
+sub    ABE9F3126BB741C1
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
 
-mQENBE1/v9YBCADaUiBecDzwU5g9Gmn3T9pAa17OlUl2iH0zn8tNTUg++bW/A9m3
-lWykQBlvPOi32lqZ5q7yewSNBGHl/pHRRVsIE6hhkVigNQbMztRFPshKCU/0RvKu
-29cew2T37crxYFGShYFwiJgOdQmXqhgIai0S2sW0Iavf5/PJJjXbrM1YIqUqkf73
-unns/lIDEiIDXCnGRNJKzGWTPsbt5R3hVo9mFraPUxapw3b9C/2GGDT/mwR51IOf
-rHkQby7Uh6XzDC8jWIH/BrFT6gFRZgKn9BRi3meB5vPip0rvcxPQnmvi2R4iUIyg
-DvCsUpXr6RpAEK6/p4k17JeglxCDlAbTDLUHABEBAAG0K0dhcnZpbiBMZUNsYWly
-ZSA8Z2FydmluLmxlY2xhaXJlQGdtYWlsLmNvbT6JATgEEwECACIFAk1/v9YCGwMG
-CwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEDU6Q24EPjFFHoQIAJXH6gRuS250
-q/EBG6vHSSqVWsck3vDwo22zGwAXOmuZ1YH7kCdzyfs9i3LnmtTyMUymvCBE0y94
-Bn2fFbin6CQsPS5U40NiquBo1wxyR8qO9pFpANlq4old1qW8t9mZBkwBjBpN6Pmf
-L5vbrgCECN46wVGqarPxseBgVjK7BB9E3qv9ymUrUJ8DSvL3b6vUwNEIqXDcZHKn
-xn4EX611YigPYiQazByw8UNq0a8kR262JN2ND64IxjBtFikdjuP5nck9Iz/yQ++V
-YpS2QfsaToCJfl8DhsVcht6N6pgo5FfDPOOhZyuDPCC+8j83JaeRS5sw6NcK03rk
-tNsnz4hef+u5AQ0ETX+/1gEIAJsFRfWMDIoJMsLPltDrrPsg1lpl2RFQuPqjZfPM
-0AAiAJTB/UhRfoMoijggV/m5r0y9d6LH4XhCynm+2VC/6TTxkvMKHAQroZFKzBKj
-vpCKXYaLgiMNi0XfsQ8p7/0nEUA1XXZDOrol9JJQ+3XxaQv3+64u+ZiZY7JrcH9M
-tytyVcsqOnQe8ST02pnpjwOIqh0TZt+HB17PWraDWRETspAMfbmoZSB9vEBiHsSo
-ELZYywFxcsxB+nbMunYONTjp/14MRKKlxeTLlH7CfJwaGV/2rvN+dKOymbg2uA4y
-/wrZrOJVE3G7IP5ehQ/Pitcb1TP6Q5LISdAo7zGFslS9iD8AEQEAAYkBHwQYAQIA
-CQUCTX+/1gIbDAAKCRA1OkNuBD4xRZ+QB/45ejZ9k7v3Yh4MtyY0th94E2h8UK3g
-T1axDIEyeWqQZaVxqvA8gG2kXhFP97c/WINUScMcdOCqTpUWRnQaZgcvD39/AFc5
-Bb3kN8Mo69YoOGkRRkvsY28NhRQBjn96QKUBmc4vGNBLV/XCsbhSD8T5KJdFszVc
-THg5q237mYucSzDfU9/0EUeSuFwwtng93Y4Rt5nDTm1MLcnBi5CTGw6Q1FL9orGN
-Hi6OXcwXDGKK1iiWjUjrmXwpgp5Zv+A4WcmG2dZHADjBlsgeHhfWCfxdJeMNZ5BO
-LL6SHLRuKiw6HUKNYs6BZNNdPQXapzKhCpSuFHW+84/4S2jX89AAfhTk
-=S97J
+mQENBFIXyRQBCADe285y3Pu7KzoKyP6wqeNXtvvuwMatAmPm5x/i+S8MlryqzsYa
+x6twUmXV1yKjjtGrO+9fHvTOWBfSSP+fP9KTaTQYSasoJq2Mw4cQDy1i0zrxNZUw
+N4/BiyjQA25sdfaOolhO0sFlZuTZpYy5wG72KkA1ygNq0L+8aBKhEF6zDU61YzCC
+AxjcgTftgTeeoqkJtYa06lNz3jmJDN+zUQignfRa3ymoGtFHTzoXR9maE8RWDty4
+y+DY+8ibdGgSgKPZ0byTCDyNojgU1YTlADa/1/NY1ShYg617O1xicLNo0JEJlf2U
+Tu4Ymql36+xSkYSISU97Q6Utgq27XMuZvDUDABEBAAG5AQ0EUhfJFAEIAN9NHRd2
+bYP/3CDi+n1ilSChld0NR3DUBgS/AdqQ7IoAUfj7skyI/WyaMdV4uy6vRh5YgNg2
+g01nd0LLZR8Gf2Ck+D6F88CdZaTxlkcxHV/dXMZ8yBO+0D6yFRZEL7Imsv8Ig4QX
+OVwfuiXEPk/Ef5Dy9SdAVhcoErTGGR6BOGVVvexGtBwefsjMaOG0khkRbWIQ32Wx
+fUFuAv5XBQ0ckLrlKvYWUYhOlXg27GtFKH2EBBF0Z5ZWu7gaBFwSV0oLp9EWcD+C
++WEwUSfBdqfRJtyXvgf4kZdwdQ5caM8P2/Sdncl2l/LU1At2Smc+plr6zhIhDlLh
+lrzKGa16oARSBdUAEQEAAYkCPgQYAQoACQUCUhfJFAIbLgEpCRB0V8ozw86eFcBd
+IAQZAQoABgUCUhfJFAAKCRCr6fMSa7dBwURMCADHrqwRNHkbG1QsXJr9oUK6KVkL
+sPhcngIhxRLlqe89omg9G7eGNauzs2PKsB3txotCFc7ROVNv/TAuSDYzkPos8G46
+p3bGesjfJb24zc6GMT4RGIJoh1oNG1IciafIIHjp2ZJHRmEDwmvZG24OHJ+mlHLj
+aedtqlWu+zwwhH2VZrI/U3gW/x4imbk9UyyzciEIxrAc+fc19xl5PkUVcSDVC0cA
+qGpeZz8+SxFaf3Rr0aGnSbeuHRjNupmoxkQOAey1ztmdWiCPf5RFfmFD+fENh+/x
+qYiGorYpcIN7UAsMkvD5UHc5ZG2tTD41jM99w9Lm/xHJ9ks8gNwZESwIzr6ABKIH
+/1ulsflI216qPz5o7uUxlTm8NfTyATfCUuZEDMYGOjDQPqQa8hFebqjWWYBUq2Sl
+aKD2xMeEuEXV+M5k88Cx6T2nvaZWMsrD7uGj+tTsFaKBGxP5p2OSEWOTETKKv6Cx
+7vcMTQmrqSFo47bFKlNSs+aVM48UnQeFtTDyOhwa5jvtqtst4eQHwHWQ99BK0TEy
+mNx0vF0nPjWA76CRrfopOwXKdxJgoKq4MrxE92ot5I82AZBPeiWVJ+6wECeK/GoB
+IXZ5jEUqrQmmzIboWA5G5PMJ8egzLJNRJjTWHjCWrUTnwNcqaD4/qZxIlW4Lt0uv
+Glx6pKOJQ05u+9X/BzoVWrw=
+=ajY9
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    78178478013521D0
+uid    Ktfmt Team <ktfmt@fb.com>
+
+sub    FA84183FDD6A6B98
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBF6RvwcBCADIVU7oxOiljoWxNTkZ00PKVwyqhahYpN/4lamULtECCS+HAF+J
+DsNy/6QCl7lKAGrSyn9dvsI56KEkGvUJfpQrpRlg+uIQDMxS8JF7p9n49DNc8Q88
+XuCaiv7pv9hhCN3Mn5qcuzTR2gGP7ToZ4fQW9W/PSJBSOeO6JK6xXNyiKcyEoXp/
+jGSRqqbDkAT4OYEUy9RfG9BeJEGUbDK4RIaH5Bo0bdahq3mfdlKYXMwRWGV9D3KN
+4iLE/26h3y6tQZS5zHQGjIIJedaKGWEiMsF+b7Jjf5OEC//FoH1IS7nDz2GK9BjW
+iELtSnmyDIDiFAvMY0pGsn8AQFn4JxEP3TMTABEBAAG0GUt0Zm10IFRlYW0gPGt0
+Zm10QGZiLmNvbT65AQ0EXpG/BwEIAPuROTIEOMOtp07cZ0bYwuPEsX40TJNFPOxg
+ak9Mx9RSfzhSNnQ0HaxaGc7O+HelsE6xeWtivbuHWjveWUvoxvkjaoYQ9WVtDN/s
+Bh2kwxS26BkvlxbbA25ZDgjk+M0xCqwkB0WX2O5PoV17+KJUhrxU9ySKe4ROCTnT
+zLIgfTvlaL1nzsJd/NWDN5RhzBKe9Uv9pcxZAmZySDXmn6z62B55TXyeyvzQZWaH
+acHb4DYdCE7tPkfVY+7kV+LvaLOsWsBf5v+Eo4yQb1EFc4Yd/jgMTq8GUAnN8isS
+HeQ14Sb1r3mHSPA+/8Q/SGZ5s+NJc13/RS2Q8OhiOE007JO2nDEAEQEAAYkBPAQY
+AQgAJhYhBGSBkJluwJMKbX1JqXgXhHgBNSHQBQJekb8HAhsMBQkDwmcAAAoJEHgX
+hHgBNSHQXSsH/jmg51oPLs8Qu0USx4aHVgmD0F3//9xssxx3/SW5l6iR8UPKoxUy
+2uUOAZ8xSrDa8arNxfrSf1h5WRrJ0GqiKMJm8eeVDuLaFnGYX1LuMgC2qCrfNlQ0
+9DdFEHYHnxyEoyjBPWgqcZpa/bYMTiOjbHz+HEQs7gUBGEEuWh2zezp5MX6a50zB
+D7whEN9qwzVz1fxdAwb5Xl+iXqQZ+mYvQo+TBqbM/KNcDb3a6hv904Fcdzy0Seb3
+aXWb3uzaQDSJEEJxxEgWjUG9uEuS+eMD4TJqrsfg6TqN6ykXvdbXTHO2cD0DFFZN
+zO5quWpqxTLMSgNswFB4mjvd0mS3bUK4DhM=
+=P/Qk
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    79752DB6C966F0B8
+uid    Rob Manning <robert.m.manning@gmail.com>
+
+sub    AC9F6F1991913E30
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=obDX
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    79E193516BE7998F
+uid    Filip Jirs?k <filip@jirsak.org>
+
+sub    9F7335D63326E7F9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFWdcSoBCADK8j+0eVZKUGctZo/VaJ/K2Wppx4jEFgih8xiIWREQ9B3QEugJ
+mJMWZHhrnHB+sjVx5No482ch6sVhYmC+VMyTdzepItZ8beYa0pnNGJnrFT+HcTOS
+g21Ef5e6BRORNho2j9YTvxvjof29XxU4SJFVgffs48jGeJzN1EDmOz4OlZupKGU+
+98o+kMKCiFjcf6Vu03asuml97b2fMOJ09n+UQVlZbBR/Yo407ZLkL2Elx47Fz+82
+iO+M8w2qNnxT4PA/TLgaVzkVHaR/JIDlQQ4DfuyloQI1hBpMB8f60oukVr5dBGuS
+1dPZ1H7td975sLegWoj7CCOFZXrDzYUXwwXPABEBAAG0IEZpbGlwIEppcnPDoWsg
+PGZpbGlwQGppcnNhay5vcmc+uQENBFWdcSoBCACidgjpeAycovmOPWf/eRXEoD7i
+bTOdKgy60rcHYPeB6pPMVaUMhZQQ4QTTRTaYEw9SJtD2itu7khittctHq3RA5EmI
+e50/cvF22MipcJqB3MJ7AnQp+92lH9rrl2xQsu7j6/xHsoEf6UFWzRo3TPx7nf1l
+qgY8JVpaWLJtsfByvLi04y73DIF0+W3SmSpDvL5h6teAc76Fz26tBVj3MdUFF7Un
+a+rMU42K0WUPkGhPfzqnPy0GLRbfYnjqdOBF66TMlYtu1Xnd/FgAVSugDth3LbFg
+pDbJWoGr02tpQ2pt22USElENLdZ5CziK22D6jIy6Yh02NJtSVsNfQ7sQ/XopABEB
+AAGJAR8EGAEIAAkFAlWdcSoCGwwACgkQeeGTUWvnmY8ABQf+K0Uy8ar+uLVqVFeE
+tuHHz8ebAEGSBLzAK7+ggg8RnhaNEHwR8RgAxuaq2ZsYVz+UvZBLG+oByxQYWVWp
+F75TH0uKVDH/zjO8Ppob3R5PN8Wk1QeSAE5LumhFsOCBVoJK4NgqLJNzTuEc2XiJ
+k43dVKI5pd//ivNsjO/SfSzBzSzTQ3UhzAj+k/7vi362Z8fg9SNnBQLpxccwdJ+8
+iYA7aE8wBt3esn9k79lXCM2hyNHl9CP8xI6CXmGJcSS4F2iqgPSVMkxgLA+DA8Y1
+wGvbF5c4rF4iVtgbCH+PcCwrQ6m6pQl9nnC8ANt2Zyj7o+JqefWrRa+F+ZFqJ7sg
+8ba0HQ==
+=DwAM
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7A01B0F236E5430F
+uid    Inderjeet Singh <inder@alumni.stanford.edu>
+
+sub    C3E640F38D845FA2
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFZUsiQBCADGmoidvh3VvXWGdwbAtHPtDPKEebE/MfFVO+QTRbjJxphzKwAt
+mxHruikafaSTnC9FWizj99e/Yc45YZHcnt5Htmy0a7DSOQXL37rrnieZxg86tYmC
+4PxvvzC/s7xF8wmxDo4A+mRyoSF0NF/fQTZAr3ri5l0G/vntH7w8AbiiyerpLobW
+/TqQn1tpMh7XfZZ+XqQKANVRECUiCYT4iJKWMqcBpLZW8aa+iYW8yCQ1xfmNXjrx
+jpTqFCiQjvwCw4dDffNe/A1Dbq0wE6mw3YHW3OC1fnLiP+TEM9P9v02bZyem6uW2
++krrToLTTHSqIGF9wUUF6S3Ikrw2EtJiRQtnABEBAAG0K0luZGVyamVldCBTaW5n
+aCA8aW5kZXJAYWx1bW5pLnN0YW5mb3JkLmVkdT65AQ0EVlSyJAEIAL0+8UoJuUsC
+3jDE60tmrApu/hK+dCbe5UJnR8z93aQ/1AfEX6So6JZzBlxID/HCOvRjJbauL6Lr
+vw2xgSnrnOzRLf1StvBPASfJk1Zdo9LZon6Xofzg34qCLUQLkDyntgXQaYF3Yw/x
+fiqqTC/yav29VTzKnf0Nri8aXGsHOycJ8nTO7I0p4xuRirFu7Bkvd7bK99/tDxtt
+YkvUnG3BUGlr85UX4uODh3EcVcgVQteawYbmsf4F00IBoTAycutCOdbP2RAgP6kg
+FxLcGz4zVqu93QjSjEdTegF1SUXcGpzvDR8T8zRsQbBCZ32A/UJqmx+EIPPFHNkL
+ijDp+f5mkJcAEQEAAYkBHwQYAQIACQUCVlSyJAIbDAAKCRB6AbDyNuVDD2xjCACq
+L670xI/26dWsz66ZyHQ2yJI7DNQxoiU3OZs2bfrRZxLpGP9Q6YWCehb+iucvmFFv
+LZBoGGWzffmVBisD2Yz3mHtF3wLx+2zJXHt1Xz7H6W89M54T3qUhQTTV6pl5f5/J
+CXK1DP9iC0y453ORY5B60byrGIUvBAv+qWXBPn3ECZ/3oEkErb5ZGof+gJjffqvW
+RAN3Li0WBRj0ldXpJoP/YE8naDJ7UdPfzcnh3tnOTfUDvFer1Nh00ilMmf6EYznR
+waN9whc9W/1HwvDeXrijrc6/1U7Hp1r5b1DddTtx6aHxpWrcwYw1yXGcm82fjXnR
+domz6nBt2DF400YubAZR
+=RPJ7
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7A8860944FAD5F62
+uid    Sebastian Bazley (ASF CODE SIGNING KEY) <sebb@apache.org>
+
+sub    C189C86B813330C4
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+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
+=9dUG
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7C25280EAE63EBE5
+uid    Oleg Kalnichevski <oleg@ural.ru>
+
+sub    926DFB2EDB329089
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEPonucRBACtbhYckAoyz1tuSXYX4XiqGa5390gIMcxe2hJ+Ncx9o3zX09Im
+f8PW27BnMrz7EIydgB2wphhjfK4vkNNtm5ZDWH/zJStsk1Fe7lNuuxs8XorX1+8D
+bhhFEuc2B85vNf2o9Y4V5GFwbD+tFNy4u24n7zg6/VgE2WDvYJ8JRqCEkwCggyLj
+ba0lsZ2XtSINh/W8ok+9f0sD/A8WhqBfDTEBuG9gnuCYXM0j7XBBPdPS+FXmmfea
+zyP+URKRprLCdt0ThZAMllIxZJrkbv7aeXVpM6KSZ/XvvaFQ/gha4o4iJFvpoKt1
+Er2j4Tz/STKztHGsMt6pqfrMNPWovu4tLuLZQmojtbIk+IwmcYxMy99owH8oV1WC
+U4HeA/9MlUxzmlmrQF7VLqFTGEEqQaEJqz95wNPj/t1DmI97hshPzXLD4zwKwa9m
+qZJPStRHM0a6xW2dztF12aXhrmYg1gIGNnsHtq+t8ZhfINZUurSWn0m65WT5notA
+15s6hwyDACHWWOgFQ9jmWuGDh0ZpiaBe7BxeTV+MsswY81sOn7QgT2xlZyBLYWxu
+aWNoZXZza2kgPG9sZWdAdXJhbC5ydT65Ag0EQ+ifBxAIALIr1cwH89+EBPkuFk1w
+rpJ5mIkhBJ8k8JPWsG+dr62JYaENrdhIUQpXP7UekG4TTIWjMT7dTmHrrTr2TeKt
+teiBNksGcyAw03IWAKT/26wXSA3+C/1xlhSKn7Qkp/r529CwM2DVbjV7TcEZ4tqv
+32d4NcJ4lTGydjKyTbdlYS6z/Sv4qRc+yQiYrbTJ4Jpgxe5hCoZ66gUTi7mxbFHz
+Zs9akQuj4hMMsggnRvuJvHyIksqp2twjJGa/1GlX8bhmR1jPB2BpokI2n6ni6qPG
+km1nq8w2LRdvr+IQALfXg8HYGMvKDcVxL8O0PhuZYsfuklDGFejSizVGwWH35vcI
+1bsAAwUH/A2wO0ac4mVi7+wx40d9QAOZ5xhHrndHQkTvK8H0DZ2kL7iavLIkZlN7
+jwC9jcA4DGmtHE9cbe6eP/P0VNDfaLVap85CzFE7qqv8LUK0LdDlrBCUcsXplhcI
+i/WaVOHk4OPXHzkF44Nqt328fQ9V6+gbvz5+1A1PK/Rmw0rRie0d2dJJIbQhK1px
+jV27qpVXfLhLMnjNh2KTO+gZh//LzION5TicsoeiHdtGU59x4Fs0SOUGgydSWAYT
+LlQoW0z1AnDKMfqoIh+CrUSAI7fpt8NAMY7KqNxBT8HlhqUX6jMolHBEreF/2fVd
+jX+NTR/p0O+L90b6T+xFin/RXxLRaa+IRgQYEQIABgUCQ+ifBwAKCRB8JSgOrmPr
+5Te9AJ9XRqxecT5oej+N1PfmcCTLZNfGiQCfdH3+RPBbKSQofz2bGx7/niTd9qg=
+=dQMM
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7C30F7B1329DBA87
+uid    Ktor Release <ktor@jetbrains.com>
+
+sub    72FF58594F983302
+sub    3967D4EDA591B991
+sub    0588BC69A286FF16
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGNBF+TCd4BDACbIA94MfIWL0SpvZwBddXgx36Lp9GYOWNgGoQCWSvk9vaMrLaI
+rEll0xnoP98CfBQYrVSAmHDMhSLBCjNB3V1Sdz8GRdOG7HUffF7Cqwbm3Fxo3H/h
++Tsrodv23NuvKsDpgglUL6nJy5e/FO8y9dcxLXRRVdPFDhJubi08SiUJy9FQbnfA
+yb2LuTzXtjDmjEsMZpdpQUlQkk0xNDkrrq+2miwxemVd35cnVQCFP0K7c4T0ksGg
+Rf9A2r45DBbPfvwTL+ZbrGtCssUpCneWhPl79UsMxeY+vJjEggqqqRqbHRn6nOQd
+3gKSaEqdALZURPzvkKxLUeUUtMk/tkFdsNe/ea7edk6G3MI4dbUY7p0XLS54S9cB
+1JUAHNEFtuJQKGWNuwWO58Yun1EBtOdUEvnIIoQ+CIN/XeKrnEIXE3LSblB8BR3H
+bqX54BMe9AzsmDQtc5pUOm2pfvCoiv8xFXQznBg24dGqo2A/jMoUnGj6oRj7k8mt
+i9AdPLigldr0S0sAEQEAAbQhS3RvciBSZWxlYXNlIDxrdG9yQGpldGJyYWlucy5j
+b20+uQGNBF+TCpABDADRarOqvERlpMCJjNXGZpK5sV7Umndyu1rwVOfEBhINkRX1
+vzzFJFciIfWEZ2c+vSNnXZC+vFuAYtwnHqTWwyodHU+/jwHeEWQ9WcD2buSwJvps
+kSei7ZMSWx7zAGWM4ae0FmjJrVHEQhM1CgeDwrxIzJqoOhrC26IorT7bGB5M2Z2n
+NStGz9fen71jNeyo0fHvvy9xkcEWsfDd9A5V0odRb5y1yKiHH4Puz+o6Gys43/PQ
+Gzf2NBx1sjzQjmJrrufvMIzRWrJwySYJQZkr/qdJyqbKZgbA/BWTmpN9POranNd0
+YO2/lbD7eiDkBflNGnWcb305VVzyZSD1kXXeLAc+y4cQugj+FkA/9Tv2c75sIhXP
+QAlZAG3ldj8WSiAlyyVuuWZh3eyxxH8J9LKDXJpBqvNvzucso1PQS2HzKhT98GxX
+45LRTsZo6yM5XAFgqw42KqTmcOy97mzluVCos090d25zYwCYsFoSaIX06wYz1GuS
+sW/JHXyUwsG6BWScgqMAEQEAAYkBvAQYAQoAJhYhBDlMtDbFaRb8Ae6kp3ww97Ey
+nbqHBQJfkwqQAhsgBQkDwmcAAAoJEHww97EynbqHLfcMAJY5nEjYg5u3l9hBcEFT
+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
+KMUFPmME
+=a5Ea
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7C7D8456294423BA
+uid    Henri Tremblay <henri.tremblay@gmail.com>
+
+sub    9842FE565AA0601E
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQGiBEvsZw4RBADH20nX+H1xvMBYmXRj1Aae4dRr6Y6qI7QRWHO6Z7/dxr9bk/NN
+Yjq5KsVOQxZzloVdtqx75rznT7fZq98g7Nq9IeEtB6k4tnh6XQLhljJMk0a3mzdt
+q3VzdxeVbwCaPJ0zixv8XPTAH6MpRJUvP9XjzxwaYHrjwcQ1LslW4TrIzwCgi5rf
+jChLCyKcaL05gqUjl4lmefED/iqOwYZw5pJ8+X+OHUViiOB43wsJt1brAhPj4KgB
+ODStcE6WlHFKi7YzcYNLzYMebSGYn6bj65b3qNf6rybWD1hGUFK4122Q7+HCH9Ic
+J+rr8HwjGFo/yxI0/mkyaF0BthXYPy4WtdsdTM2kgx8Zr3Q2rSt1jBPuV3q8d27z
+FZMiA/9cWPkRx0RfAJmBPKmKkbBkEtBbNau3G7MY1OEAkEkRnzmnyyjr5IP84A7K
+RdjTCvkbiQrOQH00Ki4sHIg+9Xv1gDg1XLkFDzRARKA1TxjL0OeS4RWF3iia7Swk
+MOnTdhR50pjb18W8kB4mEMZY7duP4nwDfQwHMwbFZGHrjImaurQpSGVucmkgVHJl
+bWJsYXkgPGhlbnJpLnRyZW1ibGF5QGdtYWlsLmNvbT65Ag0ES+xnEBAIALYa2xQw
+2yBqve3W19WRMDRqYyC3XrpsWc2gnOT4JXRxgPOky9lfYj6TjSbb+/wrK9XP67x9
+CAPwRbvtCnXvVD/s/ScnJnyaSLHdkLcX4Z/UePk3dFbTfTTZKbdfiXE4W88kKuFF
+PNrgSsEhv8M7mziOBZ/u8qSLjYA5KitEkyC97nChf0Ve+z7DgXix5AhiiFYVFH2N
+Q+dQVmSigdXn2lSuzy3Z7IuuJQIW2nsQON3cFFLVcEDrw8yVbZMnFdiDMF8Mh6J5
+SvuL23MCB9gQFOOiyGcvlRWiPpTTZkffsXlh+PaCWJzFiF4n+Ec7ztWoNiisJRtr
+GnLlU7aVlaimsgcAAwUH+wRpeDzirZbgG192vyhp19WMomz09nuKXTsamyk8LkXO
+yCyCvy1XHo1bi3fnjhdUJo06CO2N6o5c77WsUnpn5MWyEKXbrNEshxBABh/6ozbk
+7PGcBJfbTz6ymiR2yfZEK5Qz8JLnwNDQwF0xO+lIXBz2NA3spAChMNq2rxKiO2NJ
+10dlkpkSxQoZkPmjU5v/VBiPyKEXUv3YKNXmiw/+0SxXi+bRg3vtp4/geo/udp2R
+JmkQlllOzvY2C9XELuVk7q7Z3gi7SKnoS7I7lc/YoQcrGLlHEzlf+ltACHJUKDBI
+hUfSsr9KMA5Oi7V9g4ImybgL7y5Z2o7IhpuZ8lYdxtSISQQYEQIACQUCS+xnEAIb
+DAAKCRB8fYRWKUQjuol1AJ0XC8Ne5QYXv1nChUZMxE0sWiXIyACePz9TTTp/3knC
+3cdu7I3u6t7ARDc=
+=xYLL
+-----END PGP PUBLIC KEY BLOCK-----
+
+pub    7FE9900F412D622E
+uid    Wouter van Oortmerssen <aardappel@gmail.com>
+
+sub    AE6B5325E74ED034
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFnyVlkBCACe8zGkIlDV0dUKmk9PWe2Hw8qM9DdPbtpUOpmUOidGY5svQDL3
+eqvHk85TbxqFEe3Qbjjt+R+iApFuXy5kmueXTvwCm7nAU+k/pZtPuzHyhDs3iFFH
+8LCI/dOpd04LXLpuoeLCjBqPlOM+Pxiiu9h9tEnJaJzuXcw9SY3I/puj7qIEwxsJ
+W23gdPtYij9If1ht9gtTsDq9s7VbCM5vL0ofM8JVPilnE4oWuw9hjgIfT/QotbuS
+wPo+1ExZUfaKYPvMxi2kY3LZU3hlp6P5AxU+eI31yaYjtL+0lu66jTD6s8lwmF87
+QqjjxiHwic05//tp2Pk3PIZCoQurfEL6ZHhhABEBAAG0LFdvdXRlciB2YW4gT29y
+dG1lcnNzZW4gPGFhcmRhcHBlbEBnbWFpbC5jb20+uQENBFnyVlkBCACk/9GoJK23
+GwRKF8kx4h2oOkb63mP7DSPmsgBGCxvhH04oE9Rg+SPWKTjx7E0XFytyCuBYn9Bo
+yGVPp45X5k4Vvj6sNJsSuyW7ExJf1AA7Xqa0mo1tjsUPSeAWyhruZCTaHGmnY6Cl
+A3Bsy4E1C8sC0UapW9dNAf66SDp0jWeEkU366fa0RZexz92nIDCTQv4YZkYROX63
+P6Se7hNtontmKA6JajD+46OLGgNVgdSKZpO0PMyD8VMg5RUN8PXHqZ68gJ1ihjUJ
+499sXFuAaXKcxkbb+ajD6fYPQ2jy4S1tQpUGmBKAdvthMenEShmwk6lsTN86yH5q
+9tTNwMWjTbqFABEBAAGJAR8EGAECAAkFAlnyVlkCGwwACgkQf+mQD0EtYi7nngf/
+aPDwJQG7NICIuMue/QlWCUG4zW2FZL1iCKMYhfVnz29lM/5AG4Y0SlcRkgEigizB
+QUkeLVHaj3obLlxr1I5yrjaOwD/fruk3roC1pi+1i0sv0/eZJvyVN3Ta3pjzYDT/
+Qw09Ao5py7HksJsvAM8tIbw5hnmxq091M8/zdgIi/H38QFBWKNYaPkC6WMxWv0M4
+7Kttcfv1DBF/NmsMzts45BDoE98CVB/5M2eLVVrbHlj4QqpLDTeSYwcTb7JVSKrN
+byp2Ws27l1oNhMexztBivHz1OLxGJY8odrCtuxK3JMllDdln/HHdwrp6h7SDRdxR
+6llX74zIdctZVsii8eJHvA==
+=DZ0u
 -----END PGP PUBLIC KEY BLOCK-----
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 2c9bedec..774ff87 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -463,19 +463,19 @@
       </trusted-keys>
    </configuration>
    <components>
-      <component group="" name="kotlin-native-prebuilt-linux-x86_64" version="1.9.0">
-         <artifact name="kotlin-native-prebuilt-linux-x86_64-1.9.0.tar.gz">
-            <sha256 value="31737a9739fc37208e1f532b7472c3fbbf0d753f3621c9dfc1d72a69d5bc35c0" origin="Hand-built using sha256sum kotlin-native-prebuilt-linux-x86_64-1.9.0.tar.gz" reason="Artifact is not signed"/>
+      <component group="" name="kotlin-native-prebuilt-linux-x86_64" version="1.9.10">
+         <artifact name="kotlin-native-prebuilt-linux-x86_64-1.9.10.tar.gz">
+            <sha256 value="0e10e98c9310cf458dd58f3cce01bd6287b7101a14f57ffa233afbae6282e165" origin="Hand-built using sha256sum kotlin-native-prebuilt-linux-x86_64-1.9.0.tar.gz" reason="Artifact is not signed"/>
          </artifact>
       </component>
-      <component group="" name="kotlin-native-prebuilt-macos-aarch64" version="1.9.0">
-         <artifact name="kotlin-native-prebuilt-macos-aarch64-1.9.0.tar.gz">
-            <sha256 value="cbb700baef01980b9b9a6d499da7adff5c611dc61ed247efdf649a073c4dbb3c" origin="Hand-built using sha256sum kotlin-native-prebuilt-macos-aarch64-1.9.0.tar.gz"/>
+      <component group="" name="kotlin-native-prebuilt-macos-aarch64" version="1.9.10">
+         <artifact name="kotlin-native-prebuilt-macos-aarch64-1.9.10.tar.gz">
+            <sha256 value="5edce17e755f49915e82e9702c030f77b568e742511bcff5aada1de8b9f01335" origin="Hand-built using sha256sum kotlin-native-prebuilt-macos-aarch64-1.9.0.tar.gz"/>
          </artifact>
       </component>
-      <component group="" name="kotlin-native-prebuilt-macos-x86_64" version="1.9.0">
-         <artifact name="kotlin-native-prebuilt-macos-x86_64-1.9.0.tar.gz">
-            <sha256 value="ab02e67bc82d986875941036e147179e2812502bd2d6a8d8b3c511a93a8dbd1d" origin="Hand-built using sha256sum kotlin-native-prebuilt-macos-x86_64-1.9.0.tar.gz"/>
+      <component group="" name="kotlin-native-prebuilt-macos-x86_64" version="1.9.10">
+         <artifact name="kotlin-native-prebuilt-macos-x86_64-1.9.10.tar.gz">
+            <sha256 value="f19eeb858a76631d6b6691354d6975afe6b50f381fa527051f73e1d42daa0aaa" origin="Hand-built using sha256sum kotlin-native-prebuilt-macos-x86_64-1.9.0.tar.gz"/>
          </artifact>
       </component>
       <component group="aopalliance" name="aopalliance" version="1.0">
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
index a918e61..20dc04b 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/lowlatency/CanvasFrontBufferedRendererTest.kt
@@ -20,6 +20,7 @@
 import android.graphics.Canvas
 import android.graphics.Color
 import android.os.Build
+import android.view.SurfaceHolder
 import android.view.SurfaceView
 import androidx.annotation.RequiresApi
 import androidx.core.os.BuildCompat
@@ -766,6 +767,102 @@
         }
     }
 
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.Q)
+    @Test
+    fun testFrontBufferRenderAfterActivityResume() {
+        var renderCount = 0
+        val surfaceChangedLatch = CountDownLatch(1)
+        val renderStartLatch = CountDownLatch(1)
+        val renderCountLatch = CountDownLatch(2)
+        val callbacks = object : CanvasFrontBufferedRenderer.Callback<Any> {
+            override fun onDrawFrontBufferedLayer(
+                canvas: Canvas,
+                bufferWidth: Int,
+                bufferHeight: Int,
+                param: Any
+            ) {
+                renderStartLatch.countDown()
+                // Intentionally simulate slow rendering by waiting for a surface change callback
+                // this helps verify the scenario where a change in surface
+                // (ex Activity stop -> resume)
+                surfaceChangedLatch.await(3000, TimeUnit.MILLISECONDS)
+                renderCount++
+                renderCountLatch.countDown()
+            }
+
+            override fun onDrawMultiBufferedLayer(
+                canvas: Canvas,
+                bufferWidth: Int,
+                bufferHeight: Int,
+                params: Collection<Any>
+            ) {
+                // no-op
+            }
+        }
+        var renderer: CanvasFrontBufferedRenderer<Any>? = null
+        val stopLatch = CountDownLatch(1)
+        var testActivity: SurfaceViewTestActivity? = null
+        var surfaceView: SurfaceViewTestActivity.TestSurfaceView? = null
+        val scenario = ActivityScenario.launch(SurfaceViewTestActivity::class.java)
+            .moveToState(Lifecycle.State.CREATED)
+            .onActivity {
+                testActivity = it
+                surfaceView = it.getSurfaceView()
+                renderer = CanvasFrontBufferedRenderer(surfaceView!!, callbacks)
+            }
+
+        scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+            renderer!!.renderFrontBufferedLayer(Any())
+        }
+        Assert.assertTrue(renderStartLatch.await(3000, TimeUnit.MILLISECONDS))
+        // Go back to the Activity stop state to simulate an application moving to the background
+        scenario.moveToState(Lifecycle.State.CREATED).onActivity {
+            stopLatch.countDown()
+        }
+
+        Assert.assertTrue(stopLatch.await(3000, TimeUnit.MILLISECONDS))
+        surfaceView!!.holder.addCallback(object : SurfaceHolder.Callback {
+
+            override fun surfaceCreated(holder: SurfaceHolder) {
+                // NO-OP
+            }
+
+            override fun surfaceChanged(
+                holder: SurfaceHolder,
+                format: Int,
+                width: Int,
+                height: Int
+            ) {
+                // On Activity resume, a surface change callback will be invoked. At this point
+                // a render is still happening. After this is signalled the render will complete
+                // and the release callback will be invoked after we are tearing down/ recreating
+                // the front buffered renderer state.
+                surfaceChangedLatch.countDown()
+            }
+
+            override fun surfaceDestroyed(holder: SurfaceHolder) {
+                // NO-OP
+            }
+        })
+
+        scenario.moveToState(Lifecycle.State.RESUMED).onActivity {
+            renderer!!.renderFrontBufferedLayer(Any())
+        }
+
+        try {
+            // Verify that after resuming, we did not unintentionally release the newly created
+            // front buffered renderer and the subsequent render request does occur
+            Assert.assertTrue(renderCountLatch.await(3000, TimeUnit.MILLISECONDS))
+            Assert.assertEquals(2, renderCount)
+        } finally {
+            renderer?.release(true)
+            val destroyLatch = CountDownLatch(1)
+            testActivity!!.setOnDestroyCallback { destroyLatch.countDown() }
+            scenario.moveToState(Lifecycle.State.DESTROYED)
+            Assert.assertTrue(destroyLatch.await(3000, TimeUnit.MILLISECONDS))
+        }
+    }
+
     @RequiresApi(Build.VERSION_CODES.Q)
     private fun CanvasFrontBufferedRenderer<*>?.blockingRelease(timeoutMillis: Long = 3000) {
         if (this != null) {
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLFrameBufferRendererTest.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLFrameBufferRendererTest.kt
index 1d69de6..ac06484 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLFrameBufferRendererTest.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/GLFrameBufferRendererTest.kt
@@ -431,18 +431,27 @@
                 renderLatch.countDown()
             }
         }
+        var activity: SurfaceViewTestActivity? = null
         var renderer: GLFrameBufferRenderer? = null
         var surfaceView: SurfaceView?
         try {
             val scenario = ActivityScenario.launch(SurfaceViewTestActivity::class.java)
                 .moveToState(Lifecycle.State.CREATED)
                 .onActivity {
+                    activity = it
                     surfaceView = it.getSurfaceView()
                     renderer = GLFrameBufferRenderer.Builder(surfaceView!!, callbacks).build()
                 }
 
             scenario.moveToState(Lifecycle.State.RESUMED)
             assertTrue(renderLatch.await(3000, TimeUnit.MILLISECONDS))
+
+            val destroyLatch = CountDownLatch(1)
+            activity?.setOnDestroyCallback {
+                destroyLatch.countDown()
+            }
+            scenario.moveToState(Lifecycle.State.DESTROYED)
+            assertTrue(destroyLatch.await(3000, TimeUnit.MILLISECONDS))
         } finally {
             renderer.blockingRelease()
         }
diff --git a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SurfaceViewTestActivity.kt b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SurfaceViewTestActivity.kt
index d21b990..831cc8b 100644
--- a/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SurfaceViewTestActivity.kt
+++ b/graphics/graphics-core/src/androidTest/java/androidx/graphics/opengl/SurfaceViewTestActivity.kt
@@ -36,6 +36,8 @@
         setContentView(surfaceView, ViewGroup.LayoutParams(WIDTH, HEIGHT))
     }
 
+    private var mOnDestroyCallback: (() -> Unit)? = null
+
     fun getSurfaceView(): TestSurfaceView = mSurfaceView
 
     companion object {
@@ -76,4 +78,13 @@
             }
         }
     }
+
+    fun setOnDestroyCallback(callback: (() -> Unit)?) {
+        mOnDestroyCallback = callback
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        mOnDestroyCallback?.invoke()
+    }
 }
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt
index 1fa2a84..cf33292 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/MultiBufferedCanvasRenderer.kt
@@ -17,6 +17,7 @@
 package androidx.graphics
 
 import android.annotation.SuppressLint
+import android.graphics.Canvas
 import android.graphics.HardwareRenderer
 import android.graphics.PixelFormat
 import android.graphics.RenderNode
@@ -85,6 +86,12 @@
 
     private var mIsReleased = false
 
+    inline fun record(block: (canvas: Canvas) -> Unit) {
+        val canvas = renderNode.beginRecording()
+        block(canvas)
+        renderNode.endRecording()
+    }
+
     fun renderFrame(
         executor: Executor,
         bufferAvailable: (HardwareBuffer, SyncFenceCompat?) -> Unit
@@ -191,6 +198,7 @@
 
     fun release() {
         if (!mIsReleased) {
+            renderNode.discardDisplayList()
             closeBuffers()
             mImageReader.close()
             mHardwareRenderer?.let { renderer ->
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
index 4649af3..04a0ed0 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/CanvasFrontBufferedRenderer.kt
@@ -67,12 +67,7 @@
     private val mHandlerThread = HandlerThreadExecutor("CanvasRenderThread")
 
     /**
-     * RenderNode used to draw the entire multi buffered scene
-     */
-    private var mMultiBufferNode: RenderNode? = null
-
-    /**
-     * Renderer used to draw [mMultiBufferNode] into a [HardwareBuffer] that is used to configure
+     * Renderer used to draw [RenderNode] into a [HardwareBuffer] that is used to configure
      * the parent SurfaceControl that represents the multi-buffered scene
      */
     private var mMultiBufferedCanvasRenderer: MultiBufferedCanvasRenderer? = null
@@ -126,8 +121,7 @@
         }
     }
 
-    private var inverse = BufferTransformHintResolver.UNKNOWN_TRANSFORM
-    private val mBufferTransform = BufferTransformer()
+    private var mInverse = BufferTransformHintResolver.UNKNOWN_TRANSFORM
     private val mParentLayerTransform = android.graphics.Matrix()
     private var mWidth = -1
     private var mHeight = -1
@@ -181,19 +175,35 @@
     internal fun update(surfaceView: SurfaceView, width: Int, height: Int) {
         val transformHint = mTransformResolver.getBufferTransformHint(surfaceView)
         if ((mTransform != transformHint || mWidth != width || mHeight != height) && isValid()) {
-            mTransform = transformHint
-            mWidth = width
-            mHeight = height
             releaseInternal(true)
 
-            inverse = mBufferTransform.invertBufferTransform(transformHint)
-            mBufferTransform.computeTransform(width, height, inverse)
+            val bufferTransform = BufferTransformer()
+            val inverse = bufferTransform.invertBufferTransform(transformHint)
+            bufferTransform.computeTransform(width, height, inverse)
             updateMatrixTransform(width.toFloat(), height.toFloat(), inverse)
 
-            mPersistedCanvasRenderer = SingleBufferedCanvasRenderer.create<T>(
+            val parentSurfaceControl = SurfaceControlCompat.Builder()
+                .setParent(surfaceView)
+                .setName("MultiBufferedLayer")
+                .build()
+                .apply {
+                    // SurfaceControl is not visible by default so make it visible right
+                    // after creation
+                    SurfaceControlCompat.Transaction()
+                        .setVisibility(this, true)
+                        .commit()
+                }
+
+            val frontBufferSurfaceControl = SurfaceControlCompat.Builder()
+                .setParent(parentSurfaceControl)
+                .setName("FrontBufferedLayer")
+                .build()
+
+            var singleBufferedCanvasRenderer: SingleBufferedCanvasRenderer<T>? = null
+            singleBufferedCanvasRenderer = SingleBufferedCanvasRenderer.create<T>(
                 width,
                 height,
-                mBufferTransform,
+                bufferTransform,
                 mHandlerThread,
                 object : SingleBufferedCanvasRenderer.RenderCallbacks<T> {
 
@@ -210,70 +220,49 @@
                         hardwareBuffer: HardwareBuffer,
                         syncFenceCompat: SyncFenceCompat?
                     ) {
-                        mPersistedCanvasRenderer?.isVisible = true
-                        mFrontBufferSurfaceControl?.let { frontBufferSurfaceControl ->
-                            val transaction = SurfaceControlCompat.Transaction()
-                                .setLayer(frontBufferSurfaceControl, Integer.MAX_VALUE)
-                                .setBuffer(
-                                    frontBufferSurfaceControl,
-                                    hardwareBuffer,
-                                    syncFenceCompat
-                                )
-                                .setVisibility(frontBufferSurfaceControl, true)
-                                .reparent(frontBufferSurfaceControl, mParentSurfaceControl)
-                            if (inverse != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
-                                transaction.setBufferTransform(
-                                    frontBufferSurfaceControl,
-                                    inverse
-                                )
-                            }
-                            callback.onFrontBufferedLayerRenderComplete(
-                                frontBufferSurfaceControl, transaction)
-                            transaction.commit()
-                            syncFenceCompat?.close()
+                        singleBufferedCanvasRenderer?.isVisible = true
+                        val transaction = SurfaceControlCompat.Transaction()
+                            .setLayer(frontBufferSurfaceControl, Integer.MAX_VALUE)
+                            .setBuffer(
+                                frontBufferSurfaceControl,
+                                hardwareBuffer,
+                                syncFenceCompat
+                            )
+                            .setVisibility(frontBufferSurfaceControl, true)
+                            .reparent(frontBufferSurfaceControl, parentSurfaceControl)
+                        if (inverse != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
+                            transaction.setBufferTransform(
+                                frontBufferSurfaceControl,
+                                inverse
+                            )
                         }
+                        callback.onFrontBufferedLayerRenderComplete(
+                            frontBufferSurfaceControl, transaction)
+                        transaction.commit()
+                        syncFenceCompat?.close()
                     }
                 })
 
-            val parentSurfaceControl = SurfaceControlCompat.Builder()
-                .setParent(surfaceView)
-                .setName("MultiBufferedLayer")
-                .build()
-                .apply {
-                    // SurfaceControl is not visible by default so make it visible right
-                    // after creation
-                    SurfaceControlCompat.Transaction()
-                        .setVisibility(this, true)
-                        .commit()
-                }
-
             val multiBufferNode = RenderNode("MultiBufferNode").apply {
-                setPosition(0, 0, mBufferTransform.glWidth, mBufferTransform.glHeight)
-                mMultiBufferNode = this
+                setPosition(0, 0, bufferTransform.glWidth, bufferTransform.glHeight)
             }
             mMultiBufferedCanvasRenderer = MultiBufferedCanvasRenderer(
                 multiBufferNode,
-                mBufferTransform.glWidth,
-                mBufferTransform.glHeight,
+                bufferTransform.glWidth,
+                bufferTransform.glHeight,
                 usage = FrontBufferUtils.BaseFlags
             ).apply { preserveContents = false }
 
-            mFrontBufferSurfaceControl = SurfaceControlCompat.Builder()
-                .setParent(parentSurfaceControl)
-                .setName("FrontBufferedLayer")
-                .build()
-
+            mFrontBufferSurfaceControl = frontBufferSurfaceControl
+            mPersistedCanvasRenderer = singleBufferedCanvasRenderer
             mParentSurfaceControl = parentSurfaceControl
+            mTransform = transformHint
+            mWidth = width
+            mHeight = height
+            mInverse = inverse
         }
     }
 
-    private inline fun RenderNode.record(block: (canvas: Canvas) -> Unit): RenderNode {
-        val canvas = beginRecording()
-        block(canvas)
-        endRecording()
-        return this
-    }
-
     /**
      * Render content to the front buffered layer providing optional parameters to be consumed in
      * [Callback.onDrawFrontBufferedLayer].
@@ -349,11 +338,17 @@
     fun isValid() = !mIsReleased
 
     @SuppressLint("WrongConstant")
-    internal fun setParentSurfaceControlBuffer(buffer: HardwareBuffer, fence: SyncFenceCompat?) {
-        val frontBufferSurfaceControl = mFrontBufferSurfaceControl
-        val parentSurfaceControl = mParentSurfaceControl
+    internal fun setParentSurfaceControlBuffer(
+        frontBufferSurfaceControl: SurfaceControlCompat?,
+        parentSurfaceControl: SurfaceControlCompat?,
+        persistedCanvasRenderer: SingleBufferedCanvasRenderer<T>?,
+        multiBufferedCanvasRenderer: MultiBufferedCanvasRenderer,
+        inverse: Int,
+        buffer: HardwareBuffer,
+        fence: SyncFenceCompat?
+    ) {
         if (frontBufferSurfaceControl != null && parentSurfaceControl != null) {
-            mPersistedCanvasRenderer?.isVisible = false
+            persistedCanvasRenderer?.isVisible = false
             val transaction = SurfaceControlCompat.Transaction()
                 .setVisibility(frontBufferSurfaceControl, false)
                 // Set a null buffer here so that the original front buffer's release callback
@@ -361,7 +356,7 @@
                 .setBuffer(frontBufferSurfaceControl, null)
                 .setVisibility(parentSurfaceControl, true)
                 .setBuffer(parentSurfaceControl, buffer, fence) { releaseFence ->
-                    mMultiBufferedCanvasRenderer?.releaseBuffer(buffer, releaseFence)
+                    multiBufferedCanvasRenderer.releaseBuffer(buffer, releaseFence)
                 }
 
             if (inverse != BufferTransformHintResolver.UNKNOWN_TRANSFORM) {
@@ -380,14 +375,32 @@
     fun clear() {
         if (isValid()) {
             mParams.clear()
-            mPersistedCanvasRenderer?.cancelPending()
-            mPersistedCanvasRenderer?.clear()
+            val persistedCanvasRenderer = mPersistedCanvasRenderer?.apply {
+                cancelPending()
+                clear()
+            }
+            val inverse = mInverse
+            val frontBufferSurfaceControl = mFrontBufferSurfaceControl
+            val parentSurfaceControl = mParentSurfaceControl
+            val multiBufferedCanvasRenderer = mMultiBufferedCanvasRenderer
             mHandlerThread.execute {
-                mMultiBufferNode?.record { canvas ->
-                    canvas.drawColor(Color.BLACK, BlendMode.CLEAR)
-                }
-                mMultiBufferedCanvasRenderer?.renderFrame(mHandlerThread) { buffer, fence ->
-                    setParentSurfaceControlBuffer(buffer, fence)
+                multiBufferedCanvasRenderer?.let { multiBufferRenderer ->
+                    with(multiBufferRenderer) {
+                        record { canvas ->
+                            canvas.drawColor(Color.BLACK, BlendMode.CLEAR)
+                        }
+                        renderFrame(mHandlerThread) { buffer, fence ->
+                            setParentSurfaceControlBuffer(
+                                frontBufferSurfaceControl,
+                                parentSurfaceControl,
+                                persistedCanvasRenderer,
+                                multiBufferRenderer,
+                                inverse,
+                                buffer,
+                                fence
+                            )
+                        }
+                    }
                 }
             }
         } else {
@@ -417,23 +430,42 @@
      */
     private fun commitInternal(onComplete: Runnable? = null) {
         if (isValid()) {
-            mPersistedCanvasRenderer?.cancelPending()
+            val persistedCanvasRenderer = mPersistedCanvasRenderer?.apply {
+                cancelPending()
+            }
             val params = mParams
             mParams = ArrayList<T>()
             val width = surfaceView.width
             val height = surfaceView.height
+            val frontBufferSurfaceControl = mFrontBufferSurfaceControl
+            val parentSurfaceControl = mParentSurfaceControl
+            val multiBufferedCanvasRenderer = mMultiBufferedCanvasRenderer
+            val inverse = mInverse
+            val transform = mParentLayerTransform
             mHandlerThread.execute {
                 mPendingClear = true
-                mMultiBufferNode?.record { canvas ->
-                    canvas.save()
-                    canvas.setMatrix(mParentLayerTransform)
-                    callback.onDrawMultiBufferedLayer(canvas, width, height, params)
-                    canvas.restore()
-                }
-                params.clear()
-                mMultiBufferedCanvasRenderer?.renderFrame(mHandlerThread) { buffer, fence ->
-                    setParentSurfaceControlBuffer(buffer, fence)
-                    onComplete?.run()
+                multiBufferedCanvasRenderer?.let { multiBufferedRenderer ->
+                    with(multiBufferedRenderer) {
+                        record { canvas ->
+                            canvas.save()
+                            canvas.setMatrix(transform)
+                            callback.onDrawMultiBufferedLayer(canvas, width, height, params)
+                            canvas.restore()
+                        }
+                        params.clear()
+                        renderFrame(mHandlerThread) { buffer, fence ->
+                            setParentSurfaceControlBuffer(
+                                frontBufferSurfaceControl,
+                                parentSurfaceControl,
+                                persistedCanvasRenderer,
+                                multiBufferedCanvasRenderer,
+                                inverse,
+                                buffer,
+                                fence
+                            )
+                            onComplete?.run()
+                        }
+                    }
                 }
             }
         } else {
@@ -488,13 +520,15 @@
     }
 
     internal fun releaseInternal(cancelPending: Boolean, releaseCallback: (() -> Unit)? = null) {
-        mPersistedCanvasRenderer?.release(cancelPending) {
-            mMultiBufferNode?.discardDisplayList()
-            mFrontBufferSurfaceControl?.release()
-            mParentSurfaceControl?.release()
-            mMultiBufferedCanvasRenderer?.release()
+        val renderer = mPersistedCanvasRenderer
+        if (renderer != null) {
+            // Store a local copy of the corresponding SurfaceControls and renderers to make sure
+            // the release callback is not invoked on potentially newly created dependencies
+            // if we are in the middle of a render request and we get a surface changed event
+            val frontBufferSurfaceControl = mFrontBufferSurfaceControl
+            val parentSurfaceControl = mParentSurfaceControl
+            val multiBufferRenderer = mMultiBufferedCanvasRenderer
 
-            mMultiBufferNode = null
             mFrontBufferSurfaceControl = null
             mParentSurfaceControl = null
             mPersistedCanvasRenderer = null
@@ -502,7 +536,15 @@
             mWidth = -1
             mHeight = -1
             mTransform = BufferTransformHintResolver.UNKNOWN_TRANSFORM
-            releaseCallback?.invoke()
+
+            renderer.release(cancelPending) {
+                frontBufferSurfaceControl?.release()
+                parentSurfaceControl?.release()
+                multiBufferRenderer?.release()
+                releaseCallback?.invoke()
+            }
+        } else if (releaseCallback != null) {
+            mHandlerThread.execute(releaseCallback)
         }
     }
 
diff --git a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt
index 9a75f29..d3f7574 100644
--- a/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt
+++ b/graphics/graphics-core/src/main/java/androidx/graphics/lowlatency/SingleBufferedCanvasRendererV29.kt
@@ -39,14 +39,6 @@
     private val callbacks: SingleBufferedCanvasRenderer.RenderCallbacks<T>,
 ) : SingleBufferedCanvasRenderer<T> {
 
-    private val mRenderNode = RenderNode("renderNode").apply {
-        setPosition(
-            0,
-            0,
-            bufferTransformer.glWidth,
-            bufferTransformer.glHeight)
-    }
-
     private val mRenderQueue = RenderQueue(
             handlerThread,
             object : RenderQueue.FrameProducer {
@@ -95,7 +87,13 @@
     }
 
     private val mBufferedRenderer = MultiBufferedCanvasRenderer(
-        mRenderNode,
+        RenderNode("renderNode").apply {
+            setPosition(
+                0,
+                0,
+                bufferTransformer.glWidth,
+                bufferTransformer.glHeight)
+        },
         bufferTransformer.glWidth,
         bufferTransformer.glHeight,
         usage = FrontBufferUtils.obtainHardwareBufferUsageFlags(),
@@ -111,15 +109,15 @@
         }
 
         override fun execute() {
-            val canvas = mRenderNode.beginRecording()
-            canvas.save()
-            canvas.setMatrix(mTransform)
-            for (pendingParam in mPendingParams) {
-                callbacks.render(canvas, width, height, pendingParam)
+            mBufferedRenderer.record { canvas ->
+                canvas.save()
+                canvas.setMatrix(mTransform)
+                for (pendingParam in mPendingParams) {
+                    callbacks.render(canvas, width, height, pendingParam)
+                }
+                canvas.restore()
+                mPendingParams.clear()
             }
-            canvas.restore()
-            mPendingParams.clear()
-            mRenderNode.endRecording()
         }
 
         override val id: Int = RENDER
@@ -127,9 +125,7 @@
 
     private val clearRequest = object : RenderQueue.Request {
         override fun execute() {
-            val canvas = mRenderNode.beginRecording()
-            canvas.drawColor(Color.BLACK, BlendMode.CLEAR)
-            mRenderNode.endRecording()
+            mBufferedRenderer.record { canvas -> canvas.drawColor(Color.BLACK, BlendMode.CLEAR) }
         }
 
         override val id: Int = CLEAR
diff --git a/graphics/graphics-shapes/api/current.txt b/graphics/graphics-shapes/api/current.txt
index 55829f0..b2e61e0 100644
--- a/graphics/graphics-shapes/api/current.txt
+++ b/graphics/graphics-shapes/api/current.txt
@@ -14,31 +14,26 @@
   public static final class CornerRounding.Companion {
   }
 
-  public final class Cubic {
-    ctor public Cubic(androidx.graphics.shapes.Cubic cubic);
+  public class Cubic {
     ctor public Cubic(float anchor0X, float anchor0Y, float control0X, float control0Y, float control1X, float control1Y, float anchor1X, float anchor1Y);
-    method public static androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
-    method public operator androidx.graphics.shapes.Cubic div(float x);
-    method public operator androidx.graphics.shapes.Cubic div(int x);
-    method public float getAnchor0X();
-    method public float getAnchor0Y();
-    method public float getAnchor1X();
-    method public float getAnchor1Y();
-    method public float getControl0X();
-    method public float getControl0Y();
-    method public float getControl1X();
-    method public float getControl1Y();
-    method public static androidx.graphics.shapes.Cubic interpolate(androidx.graphics.shapes.Cubic start, androidx.graphics.shapes.Cubic end, float t);
-    method public operator androidx.graphics.shapes.Cubic plus(androidx.graphics.shapes.Cubic o);
-    method public android.graphics.PointF pointOnCurve(float t);
-    method public android.graphics.PointF pointOnCurve(float t, optional android.graphics.PointF result);
-    method public androidx.graphics.shapes.Cubic reverse();
-    method public kotlin.Pair<androidx.graphics.shapes.Cubic,androidx.graphics.shapes.Cubic> split(float t);
-    method public static androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
-    method public operator androidx.graphics.shapes.Cubic times(float x);
-    method public operator androidx.graphics.shapes.Cubic times(int x);
-    method public void transform(android.graphics.Matrix matrix);
-    method public void transform(android.graphics.Matrix matrix, optional float[] points);
+    method public static final androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
+    method public final operator androidx.graphics.shapes.Cubic div(float x);
+    method public final operator androidx.graphics.shapes.Cubic div(int x);
+    method public final float getAnchor0X();
+    method public final float getAnchor0Y();
+    method public final float getAnchor1X();
+    method public final float getAnchor1Y();
+    method public final float getControl0X();
+    method public final float getControl0Y();
+    method public final float getControl1X();
+    method public final float getControl1Y();
+    method public final operator androidx.graphics.shapes.Cubic plus(androidx.graphics.shapes.Cubic o);
+    method public final androidx.graphics.shapes.Cubic reverse();
+    method public final kotlin.Pair<androidx.graphics.shapes.Cubic,androidx.graphics.shapes.Cubic> split(float t);
+    method public static final androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
+    method public final operator androidx.graphics.shapes.Cubic times(float x);
+    method public final operator androidx.graphics.shapes.Cubic times(int x);
+    method public final androidx.graphics.shapes.Cubic transformed(androidx.graphics.shapes.PointTransformer f);
     property public final float anchor0X;
     property public final float anchor0Y;
     property public final float anchor1X;
@@ -52,54 +47,43 @@
 
   public static final class Cubic.Companion {
     method public androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
-    method public androidx.graphics.shapes.Cubic interpolate(androidx.graphics.shapes.Cubic start, androidx.graphics.shapes.Cubic end, float t);
     method public androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
   }
 
-  public final class CubicShape {
-    ctor public CubicShape(androidx.graphics.shapes.CubicShape sourceShape);
-    ctor public CubicShape(java.util.List<androidx.graphics.shapes.Cubic> cubics);
-    method public android.graphics.RectF getBounds();
-    method public java.util.List<androidx.graphics.shapes.Cubic> getCubics();
-    method public android.graphics.Path toPath();
-    method public void transform(android.graphics.Matrix matrix);
-    method public void transform(android.graphics.Matrix matrix, optional float[] points);
-    property public final android.graphics.RectF bounds;
-    property public final java.util.List<androidx.graphics.shapes.Cubic> cubics;
-  }
-
-  public final class CubicShapeKt {
-    method public static void drawCubicShape(android.graphics.Canvas, androidx.graphics.shapes.CubicShape shape, android.graphics.Paint paint);
-  }
-
   public final class Morph {
     ctor public Morph(androidx.graphics.shapes.RoundedPolygon start, androidx.graphics.shapes.RoundedPolygon end);
     method public java.util.List<androidx.graphics.shapes.Cubic> asCubics(float progress);
-    method public android.graphics.Path asPath(float progress);
-    method public android.graphics.Path asPath(float progress, optional android.graphics.Path path);
-    method public android.graphics.RectF getBounds();
-    method public void transform(android.graphics.Matrix matrix);
-    property public final android.graphics.RectF bounds;
+    method public kotlin.sequences.Sequence<androidx.graphics.shapes.MutableCubic> asMutableCubics(float progress);
+    method public kotlin.sequences.Sequence<androidx.graphics.shapes.MutableCubic> asMutableCubics(float progress, optional androidx.graphics.shapes.MutableCubic mutableCubic);
   }
 
-  public final class MorphKt {
-    method public static void drawMorph(android.graphics.Canvas, androidx.graphics.shapes.Morph morph, android.graphics.Paint paint, optional float progress);
+  public final class MutableCubic extends androidx.graphics.shapes.Cubic {
+    method public void transform(androidx.graphics.shapes.PointTransformer f);
+  }
+
+  public interface MutablePoint {
+    method public float getX();
+    method public float getY();
+    method public void setX(float);
+    method public void setY(float);
+    property public abstract float x;
+    property public abstract float y;
+  }
+
+  public fun interface PointTransformer {
+    method public void transform(androidx.graphics.shapes.MutablePoint);
   }
 
   public final class RoundedPolygon {
-    ctor public RoundedPolygon(androidx.graphics.shapes.RoundedPolygon source);
-    ctor public RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX, optional float centerY);
-    ctor public RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
-    method public android.graphics.RectF getBounds();
+    method public float[] calculateBounds(optional float[] bounds);
     method public float getCenterX();
     method public float getCenterY();
-    method public void setBounds(android.graphics.RectF);
-    method public androidx.graphics.shapes.CubicShape toCubicShape();
-    method public android.graphics.Path toPath();
-    method public void transform(android.graphics.Matrix matrix);
-    property public final android.graphics.RectF bounds;
+    method public java.util.List<androidx.graphics.shapes.Cubic> getCubics();
+    method public androidx.graphics.shapes.RoundedPolygon normalized();
+    method public androidx.graphics.shapes.RoundedPolygon transformed(androidx.graphics.shapes.PointTransformer f);
     property public final float centerX;
     property public final float centerY;
+    property public final java.util.List<androidx.graphics.shapes.Cubic> cubics;
     field public static final androidx.graphics.shapes.RoundedPolygon.Companion Companion;
   }
 
@@ -107,7 +91,18 @@
   }
 
   public final class RoundedPolygonKt {
-    method public static void drawPolygon(android.graphics.Canvas, androidx.graphics.shapes.RoundedPolygon polygon, android.graphics.Paint paint);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(androidx.graphics.shapes.RoundedPolygon source);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX, optional float centerY);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
   }
 
   public final class ShapesKt {
diff --git a/graphics/graphics-shapes/api/restricted_current.txt b/graphics/graphics-shapes/api/restricted_current.txt
index 55829f0..b2e61e0 100644
--- a/graphics/graphics-shapes/api/restricted_current.txt
+++ b/graphics/graphics-shapes/api/restricted_current.txt
@@ -14,31 +14,26 @@
   public static final class CornerRounding.Companion {
   }
 
-  public final class Cubic {
-    ctor public Cubic(androidx.graphics.shapes.Cubic cubic);
+  public class Cubic {
     ctor public Cubic(float anchor0X, float anchor0Y, float control0X, float control0Y, float control1X, float control1Y, float anchor1X, float anchor1Y);
-    method public static androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
-    method public operator androidx.graphics.shapes.Cubic div(float x);
-    method public operator androidx.graphics.shapes.Cubic div(int x);
-    method public float getAnchor0X();
-    method public float getAnchor0Y();
-    method public float getAnchor1X();
-    method public float getAnchor1Y();
-    method public float getControl0X();
-    method public float getControl0Y();
-    method public float getControl1X();
-    method public float getControl1Y();
-    method public static androidx.graphics.shapes.Cubic interpolate(androidx.graphics.shapes.Cubic start, androidx.graphics.shapes.Cubic end, float t);
-    method public operator androidx.graphics.shapes.Cubic plus(androidx.graphics.shapes.Cubic o);
-    method public android.graphics.PointF pointOnCurve(float t);
-    method public android.graphics.PointF pointOnCurve(float t, optional android.graphics.PointF result);
-    method public androidx.graphics.shapes.Cubic reverse();
-    method public kotlin.Pair<androidx.graphics.shapes.Cubic,androidx.graphics.shapes.Cubic> split(float t);
-    method public static androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
-    method public operator androidx.graphics.shapes.Cubic times(float x);
-    method public operator androidx.graphics.shapes.Cubic times(int x);
-    method public void transform(android.graphics.Matrix matrix);
-    method public void transform(android.graphics.Matrix matrix, optional float[] points);
+    method public static final androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
+    method public final operator androidx.graphics.shapes.Cubic div(float x);
+    method public final operator androidx.graphics.shapes.Cubic div(int x);
+    method public final float getAnchor0X();
+    method public final float getAnchor0Y();
+    method public final float getAnchor1X();
+    method public final float getAnchor1Y();
+    method public final float getControl0X();
+    method public final float getControl0Y();
+    method public final float getControl1X();
+    method public final float getControl1Y();
+    method public final operator androidx.graphics.shapes.Cubic plus(androidx.graphics.shapes.Cubic o);
+    method public final androidx.graphics.shapes.Cubic reverse();
+    method public final kotlin.Pair<androidx.graphics.shapes.Cubic,androidx.graphics.shapes.Cubic> split(float t);
+    method public static final androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
+    method public final operator androidx.graphics.shapes.Cubic times(float x);
+    method public final operator androidx.graphics.shapes.Cubic times(int x);
+    method public final androidx.graphics.shapes.Cubic transformed(androidx.graphics.shapes.PointTransformer f);
     property public final float anchor0X;
     property public final float anchor0Y;
     property public final float anchor1X;
@@ -52,54 +47,43 @@
 
   public static final class Cubic.Companion {
     method public androidx.graphics.shapes.Cubic circularArc(float centerX, float centerY, float x0, float y0, float x1, float y1);
-    method public androidx.graphics.shapes.Cubic interpolate(androidx.graphics.shapes.Cubic start, androidx.graphics.shapes.Cubic end, float t);
     method public androidx.graphics.shapes.Cubic straightLine(float x0, float y0, float x1, float y1);
   }
 
-  public final class CubicShape {
-    ctor public CubicShape(androidx.graphics.shapes.CubicShape sourceShape);
-    ctor public CubicShape(java.util.List<androidx.graphics.shapes.Cubic> cubics);
-    method public android.graphics.RectF getBounds();
-    method public java.util.List<androidx.graphics.shapes.Cubic> getCubics();
-    method public android.graphics.Path toPath();
-    method public void transform(android.graphics.Matrix matrix);
-    method public void transform(android.graphics.Matrix matrix, optional float[] points);
-    property public final android.graphics.RectF bounds;
-    property public final java.util.List<androidx.graphics.shapes.Cubic> cubics;
-  }
-
-  public final class CubicShapeKt {
-    method public static void drawCubicShape(android.graphics.Canvas, androidx.graphics.shapes.CubicShape shape, android.graphics.Paint paint);
-  }
-
   public final class Morph {
     ctor public Morph(androidx.graphics.shapes.RoundedPolygon start, androidx.graphics.shapes.RoundedPolygon end);
     method public java.util.List<androidx.graphics.shapes.Cubic> asCubics(float progress);
-    method public android.graphics.Path asPath(float progress);
-    method public android.graphics.Path asPath(float progress, optional android.graphics.Path path);
-    method public android.graphics.RectF getBounds();
-    method public void transform(android.graphics.Matrix matrix);
-    property public final android.graphics.RectF bounds;
+    method public kotlin.sequences.Sequence<androidx.graphics.shapes.MutableCubic> asMutableCubics(float progress);
+    method public kotlin.sequences.Sequence<androidx.graphics.shapes.MutableCubic> asMutableCubics(float progress, optional androidx.graphics.shapes.MutableCubic mutableCubic);
   }
 
-  public final class MorphKt {
-    method public static void drawMorph(android.graphics.Canvas, androidx.graphics.shapes.Morph morph, android.graphics.Paint paint, optional float progress);
+  public final class MutableCubic extends androidx.graphics.shapes.Cubic {
+    method public void transform(androidx.graphics.shapes.PointTransformer f);
+  }
+
+  public interface MutablePoint {
+    method public float getX();
+    method public float getY();
+    method public void setX(float);
+    method public void setY(float);
+    property public abstract float x;
+    property public abstract float y;
+  }
+
+  public fun interface PointTransformer {
+    method public void transform(androidx.graphics.shapes.MutablePoint);
   }
 
   public final class RoundedPolygon {
-    ctor public RoundedPolygon(androidx.graphics.shapes.RoundedPolygon source);
-    ctor public RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX, optional float centerY);
-    ctor public RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
-    method public android.graphics.RectF getBounds();
+    method public float[] calculateBounds(optional float[] bounds);
     method public float getCenterX();
     method public float getCenterY();
-    method public void setBounds(android.graphics.RectF);
-    method public androidx.graphics.shapes.CubicShape toCubicShape();
-    method public android.graphics.Path toPath();
-    method public void transform(android.graphics.Matrix matrix);
-    property public final android.graphics.RectF bounds;
+    method public java.util.List<androidx.graphics.shapes.Cubic> getCubics();
+    method public androidx.graphics.shapes.RoundedPolygon normalized();
+    method public androidx.graphics.shapes.RoundedPolygon transformed(androidx.graphics.shapes.PointTransformer f);
     property public final float centerX;
     property public final float centerY;
+    property public final java.util.List<androidx.graphics.shapes.Cubic> cubics;
     field public static final androidx.graphics.shapes.RoundedPolygon.Companion Companion;
   }
 
@@ -107,7 +91,18 @@
   }
 
   public final class RoundedPolygonKt {
-    method public static void drawPolygon(android.graphics.Canvas, androidx.graphics.shapes.RoundedPolygon polygon, android.graphics.Paint paint);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(androidx.graphics.shapes.RoundedPolygon source);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(float[] vertices, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding, optional float centerX, optional float centerY);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding);
+    method public static androidx.graphics.shapes.RoundedPolygon RoundedPolygon(@IntRange(from=3L) int numVertices, optional float radius, optional float centerX, optional float centerY, optional androidx.graphics.shapes.CornerRounding rounding, optional java.util.List<androidx.graphics.shapes.CornerRounding>? perVertexRounding);
   }
 
   public final class ShapesKt {
diff --git a/graphics/graphics-shapes/build.gradle b/graphics/graphics-shapes/build.gradle
index e1d55cb..db58bca 100644
--- a/graphics/graphics-shapes/build.gradle
+++ b/graphics/graphics-shapes/build.gradle
@@ -15,21 +15,54 @@
  */
 
 import androidx.build.LibraryType
+import androidx.build.PlatformIdentifier
 
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
-    id("org.jetbrains.kotlin.android")
 }
 
-dependencies {
-    api(libs.kotlinStdlib)
-    implementation("androidx.annotation:annotation:1.4.0")
-    implementation("androidx.core:core-ktx:1.10.0-rc01")
-    androidTestImplementation(libs.testExtJunit)
-    androidTestImplementation(libs.testCore)
-    androidTestImplementation(libs.testRunner)
-    androidTestImplementation(libs.testRules)
+androidXMultiplatform {
+    android()
+
+    defaultPlatform(PlatformIdentifier.ANDROID)
+
+    sourceSets {
+        all {
+            languageSettings.optIn("kotlin.RequiresOptIn")
+            languageSettings.optIn("kotlin.contracts.ExperimentalContracts")
+        }
+
+        commonMain {
+            dependencies {
+                api(libs.kotlinStdlib)
+                implementation 'androidx.annotation:annotation:1.7.0-alpha02'
+            }
+        }
+
+        commonTest {
+            dependencies {
+            }
+        }
+
+        androidMain {
+            dependsOn(commonMain)
+            dependencies {
+                implementation("androidx.core:core-ktx:1.10.0-rc01")
+                implementation("androidx.core:core-ktx:1.8.0")
+            }
+        }
+
+        androidAndroidTest {
+            dependsOn(commonTest)
+            dependencies {
+                implementation(libs.testExtJunit)
+                implementation(libs.testCore)
+                implementation(libs.testRunner)
+                implementation(libs.testRules)
+            }
+        }
+    }
 }
 
 android {
diff --git a/graphics/graphics-shapes/src/androidTest/AndroidManifest.xml b/graphics/graphics-shapes/src/androidAndroidTest/AndroidManifest.xml
similarity index 100%
rename from graphics/graphics-shapes/src/androidTest/AndroidManifest.xml
rename to graphics/graphics-shapes/src/androidAndroidTest/AndroidManifest.xml
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CornerRoundingTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/CornerRoundingTest.kt
similarity index 100%
rename from graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CornerRoundingTest.kt
rename to graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/CornerRoundingTest.kt
diff --git a/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/CubicTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/CubicTest.kt
new file mode 100644
index 0000000..b422df5
--- /dev/null
+++ b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/CubicTest.kt
@@ -0,0 +1,187 @@
+/*
+ * 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.shapes
+
+import androidx.test.filters.SmallTest
+import kotlin.math.max
+import kotlin.math.min
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+@SmallTest
+class CubicTest {
+
+    // These points create a roughly circular arc in the upper-right quadrant around (0,0)
+    private val zero = Point(0f, 0f)
+    private val p0 = Point(1f, 0f)
+    private val p1 = Point(1f, .5f)
+    private val p2 = Point(.5f, 1f)
+    private val p3 = Point(0f, 1f)
+    val cubic = Cubic(p0, p1, p2, p3)
+
+    @Test
+    fun constructionTest() {
+        assertEquals(p0, Point(cubic.anchor0X, cubic.anchor0Y))
+        assertEquals(p1, Point(cubic.control0X, cubic.control0Y))
+        assertEquals(p2, Point(cubic.control1X, cubic.control1Y))
+        assertEquals(p3, Point(cubic.anchor1X, cubic.anchor1Y))
+    }
+
+    @Test
+    fun circularArcTest() {
+        val arcCubic = Cubic.circularArc(zero.x, zero.y, p0.x, p0.y, p3.x, p3.y)
+        assertEquals(p0, Point(arcCubic.anchor0X, arcCubic.anchor0Y))
+        assertEquals(p3, Point(arcCubic.anchor1X, arcCubic.anchor1Y))
+    }
+
+    @Test
+    fun divTest() {
+        var divCubic = cubic / 1f
+        assertCubicsEqualish(cubic, divCubic)
+        divCubic = cubic / 1
+        assertCubicsEqualish(cubic, divCubic)
+        divCubic = cubic / 2f
+        assertPointsEqualish(p0 / 2f, Point(divCubic.anchor0X, divCubic.anchor0Y))
+        assertPointsEqualish(p1 / 2f, Point(divCubic.control0X, divCubic.control0Y))
+        assertPointsEqualish(p2 / 2f, Point(divCubic.control1X, divCubic.control1Y))
+        assertPointsEqualish(p3 / 2f, Point(divCubic.anchor1X, divCubic.anchor1Y))
+        divCubic = cubic / 2
+        assertPointsEqualish(p0 / 2f, Point(divCubic.anchor0X, divCubic.anchor0Y))
+        assertPointsEqualish(p1 / 2f, Point(divCubic.control0X, divCubic.control0Y))
+        assertPointsEqualish(p2 / 2f, Point(divCubic.control1X, divCubic.control1Y))
+        assertPointsEqualish(p3 / 2f, Point(divCubic.anchor1X, divCubic.anchor1Y))
+    }
+
+    @Test
+    fun timesTest() {
+        var timesCubic = cubic * 1f
+        assertEquals(p0, Point(timesCubic.anchor0X, timesCubic.anchor0Y))
+        assertEquals(p1, Point(timesCubic.control0X, timesCubic.control0Y))
+        assertEquals(p2, Point(timesCubic.control1X, timesCubic.control1Y))
+        assertEquals(p3, Point(timesCubic.anchor1X, timesCubic.anchor1Y))
+        timesCubic = cubic * 1
+        assertEquals(p0, Point(timesCubic.anchor0X, timesCubic.anchor0Y))
+        assertEquals(p1, Point(timesCubic.control0X, timesCubic.control0Y))
+        assertEquals(p2, Point(timesCubic.control1X, timesCubic.control1Y))
+        assertEquals(p3, Point(timesCubic.anchor1X, timesCubic.anchor1Y))
+        timesCubic = cubic * 2f
+        assertPointsEqualish(p0 * 2f, Point(timesCubic.anchor0X, timesCubic.anchor0Y))
+        assertPointsEqualish(p1 * 2f, Point(timesCubic.control0X, timesCubic.control0Y))
+        assertPointsEqualish(p2 * 2f, Point(timesCubic.control1X, timesCubic.control1Y))
+        assertPointsEqualish(p3 * 2f, Point(timesCubic.anchor1X, timesCubic.anchor1Y))
+        timesCubic = cubic * 2
+        assertPointsEqualish(p0 * 2f, Point(timesCubic.anchor0X, timesCubic.anchor0Y))
+        assertPointsEqualish(p1 * 2f, Point(timesCubic.control0X, timesCubic.control0Y))
+        assertPointsEqualish(p2 * 2f, Point(timesCubic.control1X, timesCubic.control1Y))
+        assertPointsEqualish(p3 * 2f, Point(timesCubic.anchor1X, timesCubic.anchor1Y))
+    }
+
+    @Test
+    fun plusTest() {
+        val offsetCubic = cubic * 2f
+        var plusCubic = cubic + offsetCubic
+        assertPointsEqualish(p0 + Point(offsetCubic.anchor0X, offsetCubic.anchor0Y),
+            Point(plusCubic.anchor0X, plusCubic.anchor0Y))
+        assertPointsEqualish(p1 + Point(offsetCubic.control0X, offsetCubic.control0Y),
+            Point(plusCubic.control0X, plusCubic.control0Y))
+        assertPointsEqualish(p2 + Point(offsetCubic.control1X, offsetCubic.control1Y),
+            Point(plusCubic.control1X, plusCubic.control1Y))
+        assertPointsEqualish(p3 + Point(offsetCubic.anchor1X, offsetCubic.anchor1Y),
+            Point(plusCubic.anchor1X, plusCubic.anchor1Y))
+    }
+
+    @Test
+    fun reverseTest() {
+        val reverseCubic = cubic.reverse()
+        assertEquals(p3, Point(reverseCubic.anchor0X, reverseCubic.anchor0Y))
+        assertEquals(p2, Point(reverseCubic.control0X, reverseCubic.control0Y))
+        assertEquals(p1, Point(reverseCubic.control1X, reverseCubic.control1Y))
+        assertEquals(p0, Point(reverseCubic.anchor1X, reverseCubic.anchor1Y))
+    }
+
+    private fun assertBetween(end0: Point, end1: Point, actual: Point) {
+        val minX = min(end0.x, end1.x)
+        val minY = min(end0.y, end1.y)
+        val maxX = max(end0.x, end1.x)
+        val maxY = max(end0.y, end1.y)
+        assertTrue(minX <= actual.x)
+        assertTrue(minY <= actual.y)
+        assertTrue(maxX >= actual.x)
+        assertTrue(maxY >= actual.y)
+    }
+
+    @Test
+    fun straightLineTest() {
+        val lineCubic = Cubic.straightLine(p0.x, p0.y, p3.x, p3.y)
+        assertEquals(p0, Point(lineCubic.anchor0X, lineCubic.anchor0Y))
+        assertEquals(p3, Point(lineCubic.anchor1X, lineCubic.anchor1Y))
+        assertBetween(p0, p3, Point(lineCubic.control0X, lineCubic.control0Y))
+        assertBetween(p0, p3, Point(lineCubic.control1X, lineCubic.control1Y))
+    }
+
+    @Test
+    fun splitTest() {
+        val (split0, split1) = cubic.split(.5f)
+        assertEquals(Point(cubic.anchor0X, cubic.anchor0Y),
+            Point(split0.anchor0X, split0.anchor0Y))
+        assertEquals(Point(cubic.anchor1X, cubic.anchor1Y),
+            Point(split1.anchor1X, split1.anchor1Y))
+        assertBetween(Point(cubic.anchor0X, cubic.anchor0Y),
+            Point(cubic.anchor1X, cubic.anchor1Y),
+            Point(split0.anchor1X, split0.anchor1Y))
+        assertBetween(Point(cubic.anchor0X, cubic.anchor0Y),
+            Point(cubic.anchor1X, cubic.anchor1Y),
+            Point(split1.anchor0X, split1.anchor0Y))
+    }
+
+    @Test
+    fun pointOnCurveTest() {
+        var halfway = cubic.pointOnCurve(.5f)
+        assertBetween(Point(cubic.anchor0X, cubic.anchor0Y),
+            Point(cubic.anchor1X, cubic.anchor1Y), halfway)
+        val straightLineCubic = Cubic.straightLine(p0.x, p0.y, p3.x, p3.y)
+        halfway = straightLineCubic.pointOnCurve(.5f)
+        val computedHalfway = Point(p0.x + .5f * (p3.x - p0.x), p0.y + .5f * (p3.y - p0.y))
+        assertPointsEqualish(computedHalfway, halfway)
+    }
+
+    @Test
+    fun transformTest() {
+        var transform = identityTransform()
+        var transformedCubic = cubic.transformed(transform)
+        assertCubicsEqualish(cubic, transformedCubic)
+
+        transform = scaleTransform(3f, 3f)
+        transformedCubic = cubic.transformed(transform)
+        assertCubicsEqualish(cubic * 3f, transformedCubic)
+
+        val tx = 200f
+        val ty = 300f
+        val translationVector = Point(tx, ty)
+        transform = translateTransform(tx, ty)
+        transformedCubic = cubic.transformed(transform)
+        assertPointsEqualish(Point(cubic.anchor0X, cubic.anchor0Y) + translationVector,
+            Point(transformedCubic.anchor0X, transformedCubic.anchor0Y))
+        assertPointsEqualish(Point(cubic.control0X, cubic.control0Y) + translationVector,
+            Point(transformedCubic.control0X, transformedCubic.control0Y))
+        assertPointsEqualish(Point(cubic.control1X, cubic.control1Y) + translationVector,
+            Point(transformedCubic.control1X, transformedCubic.control1Y))
+        assertPointsEqualish(Point(cubic.anchor1X, cubic.anchor1Y) + translationVector,
+            Point(transformedCubic.anchor1X, transformedCubic.anchor1Y))
+    }
+}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/FloatMappingTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/FloatMappingTest.kt
similarity index 100%
rename from graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/FloatMappingTest.kt
rename to graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/FloatMappingTest.kt
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonMeasureTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/PolygonMeasureTest.kt
similarity index 100%
rename from graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonMeasureTest.kt
rename to graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/PolygonMeasureTest.kt
diff --git a/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/PolygonTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/PolygonTest.kt
new file mode 100644
index 0000000..ec0b2d0
--- /dev/null
+++ b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/PolygonTest.kt
@@ -0,0 +1,165 @@
+/*
+ * 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.shapes
+
+import androidx.test.filters.SmallTest
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+@SmallTest
+class PolygonTest {
+    val square = RoundedPolygon(4)
+
+    @Test
+    fun constructionTest() {
+        // We can't be too specific on how exactly the square is constructed, but
+        // we can at least test whether all points are within the unit square
+        var min = Point(-1f, -1f)
+        var max = Point(1f, 1f)
+        assertInBounds(square.cubics, min, max)
+
+        val doubleSquare = RoundedPolygon(4, 2f)
+        min = min * 2f
+        max = max * 2f
+        assertInBounds(doubleSquare.cubics, min, max)
+
+        val offsetSquare = RoundedPolygon(4, centerX = 1f, centerY = 2f)
+        min = Point(0f, 1f)
+        max = Point(2f, 3f)
+        assertInBounds(offsetSquare.cubics, min, max)
+
+        val squareCopy = RoundedPolygon(square)
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(squareCopy.cubics, min, max)
+
+        val p0 = Point(1f, 0f)
+        val p1 = Point(0f, 1f)
+        val p2 = Point(-1f, 0f)
+        val p3 = Point(0f, -1f)
+        val manualSquare = RoundedPolygon(floatArrayOf(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y,
+            p3.x, p3.y))
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(manualSquare.cubics, min, max)
+
+        val offset = Point(1f, 2f)
+        val p0Offset = p0 + offset
+        val p1Offset = p1 + offset
+        val p2Offset = p2 + offset
+        val p3Offset = p3 + offset
+        val manualSquareOffset = RoundedPolygon(
+            vertices = floatArrayOf(p0Offset.x, p0Offset.y, p1Offset.x, p1Offset.y,
+                p2Offset.x, p2Offset.y, p3Offset.x, p3Offset.y),
+            centerX = offset.x, centerY = offset.y)
+        min = Point(0f, 1f)
+        max = Point(2f, 3f)
+        assertInBounds(manualSquareOffset.cubics, min, max)
+    }
+
+    @Test
+    fun boundsTest() {
+        val bounds = square.calculateBounds()
+        assertEqualish(-1f, bounds[0]) // Left
+        assertEqualish(-1f, bounds[1]) // Top
+        assertEqualish(1f, bounds[2]) // Right
+        assertEqualish(1f, bounds[3]) // Bottom
+    }
+
+    @Test
+    fun centerTest() {
+        assertPointsEqualish(Point(0f, 0f), Point(square.centerX, square.centerY))
+    }
+
+    @Test
+    fun transformTest() {
+        // First, make sure the shape doesn't change when transformed by the identity
+        val squareCopy = square.transformed(identityTransform())
+        val n = square.cubics.size
+
+        assertEquals(n, squareCopy.cubics.size)
+        for (i in 0 until n) {
+            assertCubicsEqualish(square.cubics[i], squareCopy.cubics[i])
+        }
+
+        // Now create a function which translates points by (1, 2) and make sure
+        // the shape is translated similarly by it
+        val offset = Point(1f, 2f)
+        val squareCubics = square.cubics
+        val translator = translateTransform(offset.x, offset.y)
+        val translatedSquareCubics = square.transformed(translator).cubics
+
+        for (i in squareCubics.indices) {
+            assertPointsEqualish(Point(squareCubics[i].anchor0X,
+                squareCubics[i].anchor0Y) + offset,
+                Point(translatedSquareCubics[i].anchor0X, translatedSquareCubics[i].anchor0Y))
+            assertPointsEqualish(Point(squareCubics[i].control0X,
+                squareCubics[i].control0Y) + offset,
+                Point(translatedSquareCubics[i].control0X, translatedSquareCubics[i].control0Y))
+            assertPointsEqualish(Point(squareCubics[i].control1X,
+                squareCubics[i].control1Y) + offset,
+                Point(translatedSquareCubics[i].control1X, translatedSquareCubics[i].control1Y))
+            assertPointsEqualish(Point(squareCubics[i].anchor1X,
+                squareCubics[i].anchor1Y) + offset,
+                Point(translatedSquareCubics[i].anchor1X, translatedSquareCubics[i].anchor1Y))
+        }
+    }
+
+    @Test
+    fun featuresTest() {
+        val squareFeatures = square.features
+
+        // Verify that cubics of polygon == cubics of features of that polygon
+        assertTrue(square.cubics == squareFeatures.flatMap { it.cubics })
+
+        // Same as above but with rounded corners
+        val roundedSquare = RoundedPolygon(4, rounding = CornerRounding(.1f))
+        val roundedFeatures = roundedSquare.features
+        assertTrue(roundedSquare.cubics == roundedFeatures.flatMap { it.cubics })
+
+        // Same as the first polygon test, but with a copy of that polygon
+        val squareCopy = RoundedPolygon(square)
+        val squareCopyFeatures = squareCopy.features
+        assertTrue(squareCopy.cubics == squareCopyFeatures.flatMap { it.cubics })
+
+        // Test other elements of Features
+        val translator = translateTransform(1f, 2f)
+        val features = square.features
+        val preTransformVertices = mutableListOf<Point>()
+        val preTransformCenters = mutableListOf<Point>()
+        for (feature in features) {
+            if (feature is Feature.Corner) {
+                // Copy into new Point objects since the ones in the feature should transform
+                preTransformVertices.add(Point(feature.vertex.x, feature.vertex.y))
+                preTransformCenters.add(Point(feature.roundedCenter.x, feature.roundedCenter.y))
+            }
+        }
+        val transformedFeatures = square.transformed(translator).features
+        val postTransformVertices = mutableListOf<Point>()
+        val postTransformCenters = mutableListOf<Point>()
+        for (feature in transformedFeatures) {
+            if (feature is Feature.Corner) {
+                postTransformVertices.add(feature.vertex)
+                postTransformCenters.add(feature.roundedCenter)
+            }
+        }
+        assertNotEquals(preTransformVertices, postTransformVertices)
+        assertNotEquals(preTransformCenters, postTransformCenters)
+    }
+}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/RoundedPolygonTest.kt
similarity index 81%
rename from graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt
rename to graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/RoundedPolygonTest.kt
index 0df251f..2ac9a18 100644
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt
+++ b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/RoundedPolygonTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.graphics.shapes
 
-import android.graphics.PointF
-import androidx.core.graphics.times
 import androidx.test.filters.SmallTest
 import org.junit.Assert
 import org.junit.Assert.assertEquals
@@ -36,32 +34,32 @@
         }
 
         val square = RoundedPolygon(4)
-        var min = PointF(-1f, -1f)
-        var max = PointF(1f, 1f)
-        assertInBounds(square.toCubicShape(), min, max)
+        var min = Point(-1f, -1f)
+        var max = Point(1f, 1f)
+        assertInBounds(square.cubics, min, max)
 
         val doubleSquare = RoundedPolygon(4, 2f)
         min *= 2f
         max *= 2f
-        assertInBounds(doubleSquare.toCubicShape(), min, max)
+        assertInBounds(doubleSquare.cubics, min, max)
 
         val squareRounded = RoundedPolygon(4, rounding = rounding)
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(squareRounded.toCubicShape(), min, max)
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(squareRounded.cubics, min, max)
 
         val squarePVRounded = RoundedPolygon(4, perVertexRounding = perVtxRounded)
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(squarePVRounded.toCubicShape(), min, max)
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(squarePVRounded.cubics, min, max)
     }
 
     @Test
     fun verticesConstructorTest() {
-        val p0 = PointF(1f, 0f)
-        val p1 = PointF(0f, 1f)
-        val p2 = PointF(-1f, 0f)
-        val p3 = PointF(0f, -1f)
+        val p0 = Point(1f, 0f)
+        val p1 = Point(0f, 1f)
+        val p2 = Point(-1f, 0f)
+        val p3 = Point(0f, -1f)
         val verts = floatArrayOf(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y)
 
         Assert.assertThrows(IllegalArgumentException::class.java) {
@@ -69,32 +67,32 @@
         }
 
         val manualSquare = RoundedPolygon(verts)
-        var min = PointF(-1f, -1f)
-        var max = PointF(1f, 1f)
-        assertInBounds(manualSquare.toCubicShape(), min, max)
+        var min = Point(-1f, -1f)
+        var max = Point(1f, 1f)
+        assertInBounds(manualSquare.cubics, min, max)
 
-        val offset = PointF(1f, 2f)
+        val offset = Point(1f, 2f)
         val offsetVerts = floatArrayOf(p0.x + offset.x, p0.y + offset.y,
             p1.x + offset.x, p1.y + offset.y, p2.x + offset.x, p2.y + offset.y,
             p3.x + offset.x, p3.y + offset.y)
         val manualSquareOffset = RoundedPolygon(offsetVerts, centerX = offset.x, centerY = offset.y)
-        min = PointF(0f, 1f)
-        max = PointF(2f, 3f)
-        assertInBounds(manualSquareOffset.toCubicShape(), min, max)
+        min = Point(0f, 1f)
+        max = Point(2f, 3f)
+        assertInBounds(manualSquareOffset.cubics, min, max)
 
         val manualSquareRounded = RoundedPolygon(verts, rounding = rounding)
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(manualSquareRounded.toCubicShape(), min, max)
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(manualSquareRounded.cubics, min, max)
 
         val manualSquarePVRounded = RoundedPolygon(verts,
             perVertexRounding = perVtxRounded)
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(manualSquarePVRounded.toCubicShape(), min, max)
+        min = Point(-1f, -1f)
+        max = Point(1f, 1f)
+        assertInBounds(manualSquarePVRounded.cubics, min, max)
     }
 
-    fun pointsToFloats(points: List<PointF>): FloatArray {
+    private fun pointsToFloats(points: List<Point>): FloatArray {
         val result = FloatArray(points.size * 2)
         var index = 0
         for (point in points) {
@@ -106,9 +104,9 @@
 
     @Test
     fun roundingSpaceUsageTest() {
-        val p0 = PointF(0f, 0f)
-        val p1 = PointF(1f, 0f)
-        val p2 = PointF(0.5f, 1f)
+        val p0 = Point(0f, 0f)
+        val p1 = Point(1f, 0f)
+        val p2 = Point(0.5f, 1f)
         val pvRounding = listOf(
             CornerRounding(1f, 0f),
             CornerRounding(1f, 1f),
@@ -121,8 +119,8 @@
 
         // Since there is not enough room in the p0 -> p1 side even for the roundings, we shouldn't
         // take smoothing into account, so the corners should end in the middle point.
-        val lowerEdgeFeature = polygon.features.first { it is RoundedPolygon.Edge }
-            as RoundedPolygon.Edge
+        val lowerEdgeFeature = polygon.features.first { it is Feature.Edge }
+            as Feature.Edge
         assertEquals(1, lowerEdgeFeature.cubics.size)
 
         val lowerEdge = lowerEdgeFeature.cubics.first()
@@ -211,10 +209,10 @@
         // Corner rounding parameter for vertex 3 (bottom left)
         rounding3: CornerRounding = CornerRounding(0.5f)
     ) {
-        val p0 = PointF(0f, 0f)
-        val p1 = PointF(5f, 0f)
-        val p2 = PointF(5f, 1f)
-        val p3 = PointF(0f, 1f)
+        val p0 = Point(0f, 0f)
+        val p1 = Point(5f, 0f)
+        val p2 = Point(5f, 1f)
+        val p3 = Point(0f, 1f)
 
         val pvRounding = listOf(
             rounding0,
@@ -226,7 +224,7 @@
             vertices = pointsToFloats(listOf(p0, p1, p2, p3)),
             perVertexRounding = pvRounding
         )
-        val (e01, _, _, e30) = polygon.features.filterIsInstance<RoundedPolygon.Edge>()
+        val (e01, _, _, e30) = polygon.features.filterIsInstance<Feature.Edge>()
         val msg = "r0 = ${show(rounding0)}, r3 = ${show(rounding3)}"
         assertEqualish(expectedV0SX, e01.cubics.first().anchor0X, msg)
         assertEqualish(expectedV0SY, e30.cubics.first().anchor1Y, msg)
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/ShapesTest.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/ShapesTest.kt
similarity index 74%
rename from graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/ShapesTest.kt
rename to graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/ShapesTest.kt
index 34abff59..702f971 100644
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/ShapesTest.kt
+++ b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/ShapesTest.kt
@@ -16,8 +16,6 @@
 
 package androidx.graphics.shapes
 
-import android.graphics.PointF
-import androidx.core.graphics.minus
 import androidx.test.filters.SmallTest
 import kotlin.AssertionError
 import kotlin.math.sqrt
@@ -32,10 +30,10 @@
 @SmallTest
 class ShapesTest {
 
-    val Zero = PointF(0f, 0f)
+    private val Zero = Point(0f, 0f)
     val Epsilon = .01f
 
-    fun distance(start: PointF, end: PointF): Float {
+    private fun distance(start: Point, end: Point): Float {
         val vector = end - start
         return sqrt(vector.x * vector.x + vector.y * vector.y)
     }
@@ -44,11 +42,11 @@
      * Test that the given point is radius distance away from [center]. If two radii are provided
      * it is sufficient to lie on either one (used for testing points on stars).
      */
-    fun assertPointOnRadii(
-        point: PointF,
+    private fun assertPointOnRadii(
+        point: Point,
         radius1: Float,
         radius2: Float = radius1,
-        center: PointF = Zero
+        center: Point = Zero
     ) {
         val dist = distance(center, point)
         try {
@@ -58,14 +56,14 @@
         }
     }
 
-    fun assertCubicOnRadii(
+    private fun assertCubicOnRadii(
         cubic: Cubic,
         radius1: Float,
         radius2: Float = radius1,
-        center: PointF = Zero
+        center: Point = Zero
     ) {
-        assertPointOnRadii(PointF(cubic.anchor0X, cubic.anchor0Y), radius1, radius2, center)
-        assertPointOnRadii(PointF(cubic.anchor1X, cubic.anchor1Y), radius1, radius2, center)
+        assertPointOnRadii(Point(cubic.anchor0X, cubic.anchor0Y), radius1, radius2, center)
+        assertPointOnRadii(Point(cubic.anchor1X, cubic.anchor1Y), radius1, radius2, center)
     }
 
     /**
@@ -73,7 +71,7 @@
      * center, compared to the requested radius. The test is very lenient since the Circle shape is
      * only a 4x cubic approximation of the circle and varies from the true circle.
      */
-    fun assertCircularCubic(cubic: Cubic, radius: Float, center: PointF) {
+    private fun assertCircularCubic(cubic: Cubic, radius: Float, center: Point) {
         var t = 0f
         while (t <= 1f) {
             val pointOnCurve = cubic.pointOnCurve(t)
@@ -83,8 +81,8 @@
         }
     }
 
-    fun assertCircleShape(shape: CubicShape, radius: Float = 1f, center: PointF = Zero) {
-        for (cubic in shape.cubics) {
+    private fun assertCircleShape(shape: List<Cubic>, radius: Float = 1f, center: Point = Zero) {
+        for (cubic in shape) {
             assertCircularCubic(cubic, radius, center)
         }
     }
@@ -96,20 +94,20 @@
         }
 
         val circle = RoundedPolygon.circle()
-        assertCircleShape(circle.toCubicShape())
+        assertCircleShape(circle.cubics)
 
         val simpleCircle = RoundedPolygon.circle(3)
-        assertCircleShape(simpleCircle.toCubicShape())
+        assertCircleShape(simpleCircle.cubics)
 
         val complexCircle = RoundedPolygon.circle(20)
-        assertCircleShape(complexCircle.toCubicShape())
+        assertCircleShape(complexCircle.cubics)
 
         val bigCircle = RoundedPolygon.circle(radius = 3f)
-        assertCircleShape(bigCircle.toCubicShape(), radius = 3f)
+        assertCircleShape(bigCircle.cubics, radius = 3f)
 
-        val center = PointF(1f, 2f)
+        val center = Point(1f, 2f)
         val offsetCircle = RoundedPolygon.circle(centerX = center.x, centerY = center.y)
-        assertCircleShape(offsetCircle.toCubicShape(), center = center)
+        assertCircleShape(offsetCircle.cubics, center = center)
     }
 
     /**
@@ -120,26 +118,26 @@
     @Test
     fun starTest() {
         var star = RoundedPolygon.star(4, innerRadius = .5f)
-        var shape = star.toCubicShape()
+        var shape = star.cubics
         var radius = 1f
         var innerRadius = .5f
-        for (cubic in shape.cubics) {
+        for (cubic in shape) {
             assertCubicOnRadii(cubic, radius, innerRadius)
         }
 
-        val center = PointF(1f, 2f)
+        val center = Point(1f, 2f)
         star = RoundedPolygon.star(4, innerRadius = innerRadius,
             centerX = center.x, centerY = center.y)
-        shape = star.toCubicShape()
-        for (cubic in shape.cubics) {
+        shape = star.cubics
+        for (cubic in shape) {
             assertCubicOnRadii(cubic, radius, innerRadius, center)
         }
 
         radius = 4f
         innerRadius = 2f
         star = RoundedPolygon.star(4, radius, innerRadius)
-        shape = star.toCubicShape()
-        for (cubic in shape.cubics) {
+        shape = star.cubics
+        for (cubic in shape) {
             assertCubicOnRadii(cubic, radius, innerRadius)
         }
     }
@@ -152,21 +150,21 @@
             rounding, innerRounding, rounding, innerRounding)
 
         var star = RoundedPolygon.star(4, innerRadius = .5f, rounding = rounding)
-        val min = PointF(-1f, -1f)
-        val max = PointF(1f, 1f)
-        assertInBounds(star.toCubicShape(), min, max)
+        val min = Point(-1f, -1f)
+        val max = Point(1f, 1f)
+        assertInBounds(star.cubics, min, max)
 
         star = RoundedPolygon.star(4, innerRadius = .5f, innerRounding = innerRounding)
-        assertInBounds(star.toCubicShape(), min, max)
+        assertInBounds(star.cubics, min, max)
 
         star = RoundedPolygon.star(
             4, innerRadius = .5f, rounding = rounding,
             innerRounding = innerRounding
         )
-        assertInBounds(star.toCubicShape(), min, max)
+        assertInBounds(star.cubics, min, max)
 
         star = RoundedPolygon.star(4, innerRadius = .5f, perVertexRounding = perVtxRounded)
-        assertInBounds(star.toCubicShape(), min, max)
+        assertInBounds(star.cubics, min, max)
 
         assertThrows(IllegalArgumentException::class.java) {
             star = RoundedPolygon.star(
diff --git a/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/TestUtils.kt b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/TestUtils.kt
new file mode 100644
index 0000000..64a4684
--- /dev/null
+++ b/graphics/graphics-shapes/src/androidAndroidTest/kotlin/androidx/graphics/shapes/TestUtils.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.shapes
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+
+private val Epsilon = 1e-4f
+
+// Test equality within Epsilon
+internal fun assertPointsEqualish(expected: Point, actual: Point) {
+    val msg = "$expected vs. $actual"
+    assertEquals(msg, expected.x, actual.x, Epsilon)
+    assertEquals(msg, expected.y, actual.y, Epsilon)
+}
+
+internal fun assertCubicsEqualish(expected: Cubic, actual: Cubic) {
+    assertPointsEqualish(Point(expected.anchor0X, expected.anchor0Y),
+        Point(actual.anchor0X, actual.anchor0Y))
+    assertPointsEqualish(Point(expected.control0X, expected.control0Y),
+        Point(actual.control0X, actual.control0Y))
+    assertPointsEqualish(Point(expected.control1X, expected.control1Y),
+        Point(actual.control1X, actual.control1Y))
+    assertPointsEqualish(Point(expected.anchor1X, expected.anchor1Y),
+        Point(actual.anchor1X, actual.anchor1Y))
+}
+
+internal fun assertPointGreaterish(expected: Point, actual: Point) {
+    assertTrue(actual.x >= expected.x - Epsilon)
+    assertTrue(actual.y >= expected.y - Epsilon)
+}
+
+internal fun assertPointLessish(expected: Point, actual: Point) {
+    assertTrue(actual.x <= expected.x + Epsilon)
+    assertTrue(actual.y <= expected.y + Epsilon)
+}
+
+internal fun assertEqualish(expected: Float, actual: Float, message: String? = null) {
+    assertEquals(message ?: "", expected, actual, Epsilon)
+}
+
+internal fun assertInBounds(shape: List<Cubic>, minPoint: Point, maxPoint: Point) {
+    for (cubic in shape) {
+        assertPointGreaterish(minPoint, Point(cubic.anchor0X, cubic.anchor0Y))
+        assertPointLessish(maxPoint, Point(cubic.anchor0X, cubic.anchor0Y))
+        assertPointGreaterish(minPoint, Point(cubic.control0X, cubic.control0Y))
+        assertPointLessish(maxPoint, Point(cubic.control0X, cubic.control0Y))
+        assertPointGreaterish(minPoint, Point(cubic.control1X, cubic.control1Y))
+        assertPointLessish(maxPoint, Point(cubic.control1X, cubic.control1Y))
+        assertPointGreaterish(minPoint, Point(cubic.anchor1X, cubic.anchor1Y))
+        assertPointLessish(maxPoint, Point(cubic.anchor1X, cubic.anchor1Y))
+    }
+}
+
+internal fun identityTransform() = PointTransformer { }
+
+internal fun scaleTransform(sx: Float, sy: Float) = PointTransformer {
+    x *= sx
+    y *= sy
+}
+
+internal fun translateTransform(dx: Float, dy: Float) = PointTransformer {
+    x += dx
+    y += dy
+}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicShapeTest.kt b/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicShapeTest.kt
deleted file mode 100644
index 422b636..0000000
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicShapeTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Matrix
-import android.graphics.PointF
-import androidx.test.filters.SmallTest
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotNull
-import org.junit.Test
-
-@SmallTest
-class CubicShapeTest {
-
-    // ~circular arc from (1, 0) to (0, 1)
-    val point0 = PointF(1f, 0f)
-    val point1 = PointF(1f, .5f)
-    val point2 = PointF(.5f, 1f)
-    val point3 = PointF(0f, 1f)
-
-    // ~circular arc from (0, 1) to (-1, 0)
-    val point4 = PointF(0f, 1f)
-    val point5 = PointF(-.5f, 1f)
-    val point6 = PointF(-.5f, .5f)
-    val point7 = PointF(-1f, 0f)
-
-    val cubic0 = Cubic(point0, point1, point2, point3)
-    val cubic1 = Cubic(point4, point5, point6, point7)
-
-    fun getClosingCubic(first: Cubic, last: Cubic): Cubic {
-        return Cubic(last.anchor1X, last.anchor1Y, last.anchor1X, last.anchor1Y,
-            first.anchor0X, first.anchor0Y, first.anchor0X, first.anchor0Y)
-    }
-
-    @Test
-    fun constructionTest() {
-        var shape = CubicShape(listOf(cubic0, getClosingCubic(cubic0, cubic0)))
-        assertNotNull(shape)
-
-        shape = CubicShape(listOf(cubic0, cubic1, getClosingCubic(cubic0, cubic1)))
-        assertNotNull(shape)
-        val shape1 = CubicShape(shape)
-        assertEquals(shape, shape1)
-    }
-
-    @Test
-    fun pathTest() {
-        val shape = CubicShape(listOf(cubic0, cubic1, getClosingCubic(cubic0, cubic1)))
-        val path = shape.toPath()
-        assertFalse(path.isEmpty)
-    }
-
-    @Test
-    fun boundsTest() {
-        val shape = CubicShape(listOf(cubic0, cubic1, getClosingCubic(cubic0, cubic1)))
-        val bounds = shape.bounds
-        assertPointsEqualish(PointF(-1f, 0f), PointF(bounds.left, bounds.top))
-        assertPointsEqualish(PointF(1f, 1f), PointF(bounds.right, bounds.bottom))
-    }
-
-    @Test
-    fun cubicsTest() {
-        val shape = CubicShape(listOf(cubic0, cubic1, getClosingCubic(cubic0, cubic1)))
-        val cubics = shape.cubics
-        assertCubicsEqua1ish(cubic0, cubics[0])
-        assertCubicsEqua1ish(cubic1, cubics[1])
-    }
-
-    @Test
-    fun transformTest() {
-        val shape = CubicShape(listOf(cubic0, getClosingCubic(cubic0, cubic0)))
-
-        // First, make sure the shape doesn't change when transformed by the identity
-        val identity = Matrix()
-        shape.transform(identity)
-        val cubics = shape.cubics
-        assertCubicsEqua1ish(cubic0, cubics[0])
-
-        // Now create a matrix which translates points by (1, 2) and make sure
-        // the shape is translated similarly by it
-        val translator = Matrix()
-        translator.setTranslate(1f, 2f)
-        val translatedPoints = floatArrayOf(point0.x, point0.y, point1.x, point1.y,
-            point2.x, point2.y, point3.x, point3.y)
-        translator.mapPoints(translatedPoints)
-        shape.transform(translator)
-        val cubic = shape.cubics[0]
-        assertPointsEqualish(PointF(translatedPoints[0], translatedPoints[1]),
-            PointF(cubic.anchor0X, cubic.anchor0Y))
-        assertPointsEqualish(PointF(translatedPoints[2], translatedPoints[3]),
-            PointF(cubic.control0X, cubic.control0Y))
-        assertPointsEqualish(PointF(translatedPoints[4], translatedPoints[5]),
-            PointF(cubic.control1X, cubic.control1Y))
-        assertPointsEqualish(PointF(translatedPoints[6], translatedPoints[7]),
-            PointF(cubic.anchor1X, cubic.anchor1Y))
-    }
-}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicTest.kt b/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicTest.kt
deleted file mode 100644
index 78b58c2..0000000
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/CubicTest.kt
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Matrix
-import android.graphics.PointF
-import androidx.core.graphics.div
-import androidx.core.graphics.plus
-import androidx.core.graphics.times
-import androidx.test.filters.SmallTest
-import kotlin.math.max
-import kotlin.math.min
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-@SmallTest
-class CubicTest {
-
-    // These points create a roughly circular arc in the upper-right quadrant around (0,0)
-    val zero = PointF(0f, 0f)
-    val p0 = PointF(1f, 0f)
-    val p1 = PointF(1f, .5f)
-    val p2 = PointF(.5f, 1f)
-    val p3 = PointF(0f, 1f)
-    val cubic = Cubic(p0, p1, p2, p3)
-
-    @Test
-    fun constructionTest() {
-        assertEquals(p0, PointF(cubic.anchor0X, cubic.anchor0Y))
-        assertEquals(p1, PointF(cubic.control0X, cubic.control0Y))
-        assertEquals(p2, PointF(cubic.control1X, cubic.control1Y))
-        assertEquals(p3, PointF(cubic.anchor1X, cubic.anchor1Y))
-    }
-
-    @Test
-    fun copyTest() {
-        val copy = Cubic(cubic)
-        assertEquals(p0, PointF(copy.anchor0X, copy.anchor0Y))
-        assertEquals(p1, PointF(copy.control0X, copy.control0Y))
-        assertEquals(p2, PointF(copy.control1X, copy.control1Y))
-        assertEquals(p3, PointF(copy.anchor1X, copy.anchor1Y))
-        assertEquals(PointF(cubic.anchor0X, cubic.anchor0Y),
-            PointF(copy.anchor0X, copy.anchor0Y))
-        assertEquals(PointF(cubic.control0X, cubic.control0Y),
-            PointF(copy.control0X, copy.control0Y))
-        assertEquals(PointF(cubic.control1X, cubic.control1Y),
-            PointF(copy.control1X, copy.control1Y))
-        assertEquals(PointF(cubic.anchor1X, cubic.anchor1Y),
-            PointF(copy.anchor1X, copy.anchor1Y))
-    }
-
-    @Test
-    fun circularArcTest() {
-        val arcCubic = Cubic.circularArc(zero.x, zero.y, p0.x, p0.y, p3.x, p3.y)
-        assertEquals(p0, PointF(arcCubic.anchor0X, arcCubic.anchor0Y))
-        assertEquals(p3, PointF(arcCubic.anchor1X, arcCubic.anchor1Y))
-    }
-
-    @Test
-    fun divTest() {
-        var divCubic = cubic / 1f
-        assertCubicsEqua1ish(cubic, divCubic)
-        divCubic = cubic / 1
-        assertCubicsEqua1ish(cubic, divCubic)
-        divCubic = cubic / 2f
-        assertPointsEqualish(p0 / 2f, PointF(divCubic.anchor0X, divCubic.anchor0Y))
-        assertPointsEqualish(p1 / 2f, PointF(divCubic.control0X, divCubic.control0Y))
-        assertPointsEqualish(p2 / 2f, PointF(divCubic.control1X, divCubic.control1Y))
-        assertPointsEqualish(p3 / 2f, PointF(divCubic.anchor1X, divCubic.anchor1Y))
-        divCubic = cubic / 2
-        assertPointsEqualish(p0 / 2f, PointF(divCubic.anchor0X, divCubic.anchor0Y))
-        assertPointsEqualish(p1 / 2f, PointF(divCubic.control0X, divCubic.control0Y))
-        assertPointsEqualish(p2 / 2f, PointF(divCubic.control1X, divCubic.control1Y))
-        assertPointsEqualish(p3 / 2f, PointF(divCubic.anchor1X, divCubic.anchor1Y))
-    }
-
-    @Test
-    fun timesTest() {
-        var timesCubic = cubic * 1f
-        assertEquals(p0, PointF(timesCubic.anchor0X, timesCubic.anchor0Y))
-        assertEquals(p1, PointF(timesCubic.control0X, timesCubic.control0Y))
-        assertEquals(p2, PointF(timesCubic.control1X, timesCubic.control1Y))
-        assertEquals(p3, PointF(timesCubic.anchor1X, timesCubic.anchor1Y))
-        timesCubic = cubic * 1
-        assertEquals(p0, PointF(timesCubic.anchor0X, timesCubic.anchor0Y))
-        assertEquals(p1, PointF(timesCubic.control0X, timesCubic.control0Y))
-        assertEquals(p2, PointF(timesCubic.control1X, timesCubic.control1Y))
-        assertEquals(p3, PointF(timesCubic.anchor1X, timesCubic.anchor1Y))
-        timesCubic = cubic * 2f
-        assertPointsEqualish(p0 * 2f, PointF(timesCubic.anchor0X, timesCubic.anchor0Y))
-        assertPointsEqualish(p1 * 2f, PointF(timesCubic.control0X, timesCubic.control0Y))
-        assertPointsEqualish(p2 * 2f, PointF(timesCubic.control1X, timesCubic.control1Y))
-        assertPointsEqualish(p3 * 2f, PointF(timesCubic.anchor1X, timesCubic.anchor1Y))
-        timesCubic = cubic * 2
-        assertPointsEqualish(p0 * 2f, PointF(timesCubic.anchor0X, timesCubic.anchor0Y))
-        assertPointsEqualish(p1 * 2f, PointF(timesCubic.control0X, timesCubic.control0Y))
-        assertPointsEqualish(p2 * 2f, PointF(timesCubic.control1X, timesCubic.control1Y))
-        assertPointsEqualish(p3 * 2f, PointF(timesCubic.anchor1X, timesCubic.anchor1Y))
-    }
-
-    @Test
-    fun plusTest() {
-        val offsetCubic = cubic * 2f
-        var plusCubic = cubic + offsetCubic
-        assertPointsEqualish(p0 + PointF(offsetCubic.anchor0X, offsetCubic.anchor0Y),
-            PointF(plusCubic.anchor0X, plusCubic.anchor0Y))
-        assertPointsEqualish(p1 + PointF(offsetCubic.control0X, offsetCubic.control0Y),
-            PointF(plusCubic.control0X, plusCubic.control0Y))
-        assertPointsEqualish(p2 + PointF(offsetCubic.control1X, offsetCubic.control1Y),
-            PointF(plusCubic.control1X, plusCubic.control1Y))
-        assertPointsEqualish(p3 + PointF(offsetCubic.anchor1X, offsetCubic.anchor1Y),
-            PointF(plusCubic.anchor1X, plusCubic.anchor1Y))
-    }
-
-    @Test
-    fun reverseTest() {
-        val reverseCubic = cubic.reverse()
-        assertEquals(p3, PointF(reverseCubic.anchor0X, reverseCubic.anchor0Y))
-        assertEquals(p2, PointF(reverseCubic.control0X, reverseCubic.control0Y))
-        assertEquals(p1, PointF(reverseCubic.control1X, reverseCubic.control1Y))
-        assertEquals(p0, PointF(reverseCubic.anchor1X, reverseCubic.anchor1Y))
-    }
-
-    fun assertBetween(end0: PointF, end1: PointF, actual: PointF) {
-        val minX = min(end0.x, end1.x)
-        val minY = min(end0.y, end1.y)
-        val maxX = max(end0.x, end1.x)
-        val maxY = max(end0.y, end1.y)
-        assertTrue(minX <= actual.x)
-        assertTrue(minY <= actual.y)
-        assertTrue(maxX >= actual.x)
-        assertTrue(maxY >= actual.y)
-    }
-
-    @Test
-    fun straightLineTest() {
-        val lineCubic = Cubic.straightLine(p0.x, p0.y, p3.x, p3.y)
-        assertEquals(p0, PointF(lineCubic.anchor0X, lineCubic.anchor0Y))
-        assertEquals(p3, PointF(lineCubic.anchor1X, lineCubic.anchor1Y))
-        assertBetween(p0, p3, PointF(lineCubic.control0X, lineCubic.control0Y))
-        assertBetween(p0, p3, PointF(lineCubic.control1X, lineCubic.control1Y))
-    }
-
-    @Test
-    fun interpolateTest() {
-        val twiceCubic = cubic + cubic * 2f
-        val quadCubic = cubic + cubic * 4f
-        val halfway = Cubic.interpolate(cubic, quadCubic, .5f)
-        assertCubicsEqua1ish(twiceCubic, halfway)
-    }
-
-    @Test
-    fun splitTest() {
-        val (split0, split1) = cubic.split(.5f)
-        assertEquals(PointF(cubic.anchor0X, cubic.anchor0Y),
-            PointF(split0.anchor0X, split0.anchor0Y))
-        assertEquals(PointF(cubic.anchor1X, cubic.anchor1Y),
-            PointF(split1.anchor1X, split1.anchor1Y))
-        assertBetween(PointF(cubic.anchor0X, cubic.anchor0Y),
-            PointF(cubic.anchor1X, cubic.anchor1Y),
-            PointF(split0.anchor1X, split0.anchor1Y))
-        assertBetween(PointF(cubic.anchor0X, cubic.anchor0Y),
-            PointF(cubic.anchor1X, cubic.anchor1Y),
-            PointF(split1.anchor0X, split1.anchor0Y))
-    }
-
-    @Test
-    fun pointOnCurveTest() {
-        var halfway = cubic.pointOnCurve(.5f)
-        assertBetween(PointF(cubic.anchor0X, cubic.anchor0Y),
-            PointF(cubic.anchor1X, cubic.anchor1Y), halfway)
-        val straightLineCubic = Cubic.straightLine(p0.x, p0.y, p3.x, p3.y)
-        halfway = straightLineCubic.pointOnCurve(.5f)
-        val computedHalfway = PointF(p0.x + .5f * (p3.x - p0.x), p0.y + .5f * (p3.y - p0.y))
-        assertPointsEqualish(computedHalfway, halfway)
-    }
-
-    @Test
-    fun transformTest() {
-        val matrix = Matrix()
-        var transformedCubic = Cubic(cubic)
-        transformedCubic.transform(matrix)
-        assertCubicsEqua1ish(cubic, transformedCubic)
-
-        transformedCubic = Cubic(cubic)
-        matrix.setScale(3f, 3f)
-        transformedCubic.transform(matrix)
-        assertCubicsEqua1ish(cubic * 3f, transformedCubic)
-
-        val tx = 200f
-        val ty = 300f
-        val translationVector = PointF(tx, ty)
-        transformedCubic = Cubic(cubic)
-        matrix.setTranslate(tx, ty)
-        transformedCubic.transform(matrix)
-        assertPointsEqualish(PointF(cubic.anchor0X, cubic.anchor0Y) + translationVector,
-            PointF(transformedCubic.anchor0X, transformedCubic.anchor0Y))
-        assertPointsEqualish(PointF(cubic.control0X, cubic.control0Y) + translationVector,
-            PointF(transformedCubic.control0X, transformedCubic.control0Y))
-        assertPointsEqualish(PointF(cubic.control1X, cubic.control1Y) + translationVector,
-            PointF(transformedCubic.control1X, transformedCubic.control1Y))
-        assertPointsEqualish(PointF(cubic.anchor1X, cubic.anchor1Y) + translationVector,
-            PointF(transformedCubic.anchor1X, transformedCubic.anchor1Y))
-    }
-}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt b/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
deleted file mode 100644
index cb3780e..0000000
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Matrix
-import android.graphics.PointF
-import androidx.core.graphics.plus
-import androidx.core.graphics.times
-import androidx.test.filters.SmallTest
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNotEquals
-import org.junit.Assert.assertTrue
-import org.junit.Test
-
-@SmallTest
-class PolygonTest {
-
-    val square = RoundedPolygon(4)
-
-    @Test
-    fun constructionTest() {
-        // We can't be too specific on how exactly the square is constructed, but
-        // we can at least test whether all points are within the unit square
-        var min = PointF(-1f, -1f)
-        var max = PointF(1f, 1f)
-        assertInBounds(square.toCubicShape(), min, max)
-
-        val doubleSquare = RoundedPolygon(4, 2f)
-        min = min * 2f
-        max = max * 2f
-        assertInBounds(doubleSquare.toCubicShape(), min, max)
-
-        val offsetSquare = RoundedPolygon(4, centerX = 1f, centerY = 2f)
-        min = PointF(0f, 1f)
-        max = PointF(2f, 3f)
-        assertInBounds(offsetSquare.toCubicShape(), min, max)
-
-        val squareCopy = RoundedPolygon(square)
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(squareCopy.toCubicShape(), min, max)
-
-        val p0 = PointF(1f, 0f)
-        val p1 = PointF(0f, 1f)
-        val p2 = PointF(-1f, 0f)
-        val p3 = PointF(0f, -1f)
-        val manualSquare = RoundedPolygon(floatArrayOf(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y,
-            p3.x, p3.y))
-        min = PointF(-1f, -1f)
-        max = PointF(1f, 1f)
-        assertInBounds(manualSquare.toCubicShape(), min, max)
-
-        val offset = PointF(1f, 2f)
-        val p0Offset = p0 + offset
-        val p1Offset = p1 + offset
-        val p2Offset = p2 + offset
-        val p3Offset = p3 + offset
-        val manualSquareOffset = RoundedPolygon(
-            vertices = floatArrayOf(p0Offset.x, p0Offset.y, p1Offset.x, p1Offset.y,
-                p2Offset.x, p2Offset.y, p3Offset.x, p3Offset.y),
-            centerX = offset.x, centerY = offset.y)
-        min = PointF(0f, 1f)
-        max = PointF(2f, 3f)
-        assertInBounds(manualSquareOffset.toCubicShape(), min, max)
-    }
-
-    @Test
-    fun pathTest() {
-        val shape = square.toCubicShape()
-        val path = shape.toPath()
-        assertFalse(path.isEmpty)
-    }
-
-    @Test
-    fun boundsTest() {
-        val shape = square.toCubicShape()
-        val bounds = shape.bounds
-        assertPointsEqualish(PointF(-1f, 1f), PointF(bounds.left, bounds.bottom))
-        assertPointsEqualish(PointF(1f, -1f), PointF(bounds.right, bounds.top))
-    }
-
-    @Test
-    fun centerTest() {
-        assertPointsEqualish(PointF(0f, 0f), PointF(square.centerX, square.centerY))
-    }
-
-    @Test
-    fun transformTest() {
-        // First, make sure the shape doesn't change when transformed by the identity
-        val squareCopy = RoundedPolygon(square)
-        val identity = Matrix()
-        square.transform(identity)
-        assertEquals(square, squareCopy)
-
-        // Now create a matrix which translates points by (1, 2) and make sure
-        // the shape is translated similarly by it
-        val translator = Matrix()
-        val offset = PointF(1f, 2f)
-        translator.setTranslate(offset.x, offset.y)
-        square.transform(translator)
-        val squareCubics = square.toCubicShape().cubics
-        val squareCopyCubics = squareCopy.toCubicShape().cubics
-        for (i in 0 until squareCubics.size) {
-            assertPointsEqualish(PointF(squareCopyCubics[i].anchor0X,
-                squareCopyCubics[i].anchor0Y) + offset,
-                PointF(squareCubics[i].anchor0X, squareCubics[i].anchor0Y))
-            assertPointsEqualish(PointF(squareCopyCubics[i].control0X,
-                squareCopyCubics[i].control0Y) + offset,
-                PointF(squareCubics[i].control0X, squareCubics[i].control0Y))
-            assertPointsEqualish(PointF(squareCopyCubics[i].control1X,
-                squareCopyCubics[i].control1Y) + offset,
-                PointF(squareCubics[i].control1X, squareCubics[i].control1Y))
-            assertPointsEqualish(PointF(squareCopyCubics[i].anchor1X,
-                squareCopyCubics[i].anchor1Y) + offset,
-                PointF(squareCubics[i].anchor1X, squareCubics[i].anchor1Y))
-        }
-    }
-
-    @Test
-    fun featuresTest() {
-        val squareFeatures = square.features
-
-        // Verify that cubics of polygon == cubics of features of that polygon
-        assertTrue(square.toCubicShape().cubics == squareFeatures.flatMap { it.cubics })
-
-        // Same as above but with rounded corners
-        val roundedSquare = RoundedPolygon(4, rounding = CornerRounding(.1f))
-        val roundedFeatures = roundedSquare.features
-        assertTrue(roundedSquare.toCubicShape().cubics == roundedFeatures.flatMap { it.cubics })
-
-        // Same as the first polygon test, but with a copy of that polygon
-        val squareCopy = RoundedPolygon(square)
-        val squareCopyFeatures = squareCopy.features
-        assertTrue(squareCopy.toCubicShape().cubics == squareCopyFeatures.flatMap { it.cubics })
-
-        // Test other elements of Features
-        val copy = RoundedPolygon(square)
-        val matrix = Matrix()
-        matrix.setTranslate(1f, 2f)
-        val features = copy.features
-        val preTransformVertices = mutableListOf<PointF>()
-        val preTransformCenters = mutableListOf<PointF>()
-        for (feature in features) {
-            if (feature is RoundedPolygon.Corner) {
-                // Copy into new Point objects since the ones in the feature should transform
-                preTransformVertices.add(PointF(feature.vertex.x, feature.vertex.y))
-                preTransformCenters.add(PointF(feature.roundedCenter.x, feature.roundedCenter.y))
-            }
-        }
-        copy.transform(matrix)
-        val postTransformVertices = mutableListOf<PointF>()
-        val postTransformCenters = mutableListOf<PointF>()
-        for (feature in features) {
-            if (feature is RoundedPolygon.Corner) {
-                postTransformVertices.add(feature.vertex)
-                postTransformCenters.add(feature.roundedCenter)
-            }
-        }
-        assertNotEquals(preTransformVertices, postTransformVertices)
-        assertNotEquals(preTransformCenters, postTransformCenters)
-    }
-}
diff --git a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt b/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt
deleted file mode 100644
index 1cce6ad6..0000000
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.PointF
-import org.junit.Assert.assertEquals
-import org.junit.Assert.assertTrue
-
-private val Epsilon = 1e-4f
-
-// Test equality within Epsilon
-fun assertPointsEqualish(expected: PointF, actual: PointF) {
-    assertEquals(expected.x, actual.x, Epsilon)
-    assertEquals(expected.y, actual.y, Epsilon)
-}
-
-fun assertCubicsEqua1ish(expected: Cubic, actual: Cubic) {
-    assertPointsEqualish(PointF(expected.anchor0X, expected.anchor0Y),
-        PointF(actual.anchor0X, actual.anchor0Y))
-    assertPointsEqualish(PointF(expected.control0X, expected.control0Y),
-        PointF(actual.control0X, actual.control0Y))
-    assertPointsEqualish(PointF(expected.control1X, expected.control1Y),
-        PointF(actual.control1X, actual.control1Y))
-    assertPointsEqualish(PointF(expected.anchor1X, expected.anchor1Y),
-        PointF(actual.anchor1X, actual.anchor1Y))
-}
-
-fun assertPointGreaterish(expected: PointF, actual: PointF) {
-    assertTrue(actual.x >= expected.x - Epsilon)
-    assertTrue(actual.y >= expected.y - Epsilon)
-}
-
-fun assertPointLessish(expected: PointF, actual: PointF) {
-    assertTrue(actual.x <= expected.x + Epsilon)
-    assertTrue(actual.y <= expected.y + Epsilon)
-}
-
-fun assertEqualish(expected: Float, actual: Float, message: String? = null) {
-    assertEquals(message ?: "", expected, actual, Epsilon)
-}
-
-fun assertInBounds(shape: CubicShape, minPoint: PointF, maxPoint: PointF) {
-    val cubics = shape.cubics
-    for (cubic in cubics) {
-        assertPointGreaterish(minPoint, PointF(cubic.anchor0X, cubic.anchor0Y))
-        assertPointLessish(maxPoint, PointF(cubic.anchor0X, cubic.anchor0Y))
-        assertPointGreaterish(minPoint, PointF(cubic.control0X, cubic.control0Y))
-        assertPointLessish(maxPoint, PointF(cubic.control0X, cubic.control0Y))
-        assertPointGreaterish(minPoint, PointF(cubic.control1X, cubic.control1Y))
-        assertPointLessish(maxPoint, PointF(cubic.control1X, cubic.control1Y))
-        assertPointGreaterish(minPoint, PointF(cubic.anchor1X, cubic.anchor1Y))
-        assertPointLessish(maxPoint, PointF(cubic.anchor1X, cubic.anchor1Y))
-    }
-}
diff --git a/graphics/graphics-shapes/src/main/androidx/graphics/shapes/androidx-graphics-graphics-shapes-documentation.md b/graphics/graphics-shapes/src/commonMain/androidx/graphics/shapes/androidx-graphics-graphics-shapes-documentation.md
similarity index 100%
rename from graphics/graphics-shapes/src/main/androidx/graphics/shapes/androidx-graphics-graphics-shapes-documentation.md
rename to graphics/graphics-shapes/src/commonMain/androidx/graphics/shapes/androidx-graphics-graphics-shapes-documentation.md
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CornerRounding.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/CornerRounding.kt
similarity index 100%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CornerRounding.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/CornerRounding.kt
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Cubic.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Cubic.kt
new file mode 100644
index 0000000..4ab4abd
--- /dev/null
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Cubic.kt
@@ -0,0 +1,325 @@
+/*
+ * 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.shapes
+
+import kotlin.math.sqrt
+
+/**
+ * This class holds the anchor and control point data for a single cubic Bézier curve,
+ * with anchor points ([anchor0X], [anchor0Y]) and ([anchor1X], [anchor1Y]) at either end
+ * and control points ([control0X], [control0Y]) and ([control1X], [control1Y]) determining
+ * the slope of the curve between the anchor points.
+ */
+open class Cubic internal constructor(internal val points: FloatArray = FloatArray(8)) {
+    init { require(points.size == 8) }
+
+    /**
+     * The first anchor point x coordinate
+     */
+    val anchor0X get() = points[0]
+
+    /**
+     * The first anchor point y coordinate
+     */
+    val anchor0Y get() = points[1]
+
+    /**
+     * The first control point x coordinate
+     */
+    val control0X get() = points[2]
+
+    /**
+     * The first control point y coordinate
+     */
+    val control0Y get() = points[3]
+
+    /**
+     * The second control point x coordinate
+     */
+    val control1X get() = points[4]
+
+    /**
+     * The second control point y coordinate
+     */
+    val control1Y get() = points[5]
+
+    /**
+     * The second anchor point x coordinate
+     */
+    val anchor1X get() = points[6]
+
+    /**
+     * The second anchor point y coordinate
+     */
+    val anchor1Y get() = points[7]
+
+    /**
+     * This class holds the anchor and control point data for a single cubic Bézier curve,
+     * with anchor points ([anchor0X], [anchor0Y]) and ([anchor1X], [anchor1Y]) at either end
+     * and control points ([control0X], [control0Y]) and ([control1X], [control1Y]) determining
+     * the slope of the curve between the anchor points.
+     *
+     * This object is immutable.
+     *
+     * @param anchor0X the first anchor point x coordinate
+     * @param anchor0Y the first anchor point y coordinate
+     * @param control0X the first control point x coordinate
+     * @param control0Y the first control point y coordinate
+     * @param control1X the second control point x coordinate
+     * @param control1Y the second control point y coordinate
+     * @param anchor1X the second anchor point x coordinate
+     * @param anchor1Y the second anchor point y coordinate
+     */
+    constructor(
+        anchor0X: Float,
+        anchor0Y: Float,
+        control0X: Float,
+        control0Y: Float,
+        control1X: Float,
+        control1Y: Float,
+        anchor1X: Float,
+        anchor1Y: Float
+    ) : this(floatArrayOf(anchor0X, anchor0Y, control0X, control0Y,
+        control1X, control1Y, anchor1X, anchor1Y))
+
+    internal constructor(anchor0: Point, control0: Point, control1: Point, anchor1: Point) :
+        this(anchor0.x, anchor0.y, control0.x, control0.y,
+            control1.x, control1.y, anchor1.x, anchor1.y)
+
+    /**
+     * Returns a point on the curve for parameter t, representing the proportional distance
+     * along the curve between its starting point at anchor0 and ending point at anchor1.
+     *
+     * @param t The distance along the curve between the anchor points, where 0 is at anchor0 and
+     * 1 is at anchor1
+     */
+    internal fun pointOnCurve(t: Float): Point {
+        val u = 1 - t
+        return Point(anchor0X * (u * u * u) + control0X * (3 * t * u * u) +
+            control1X * (3 * t * t * u) + anchor1X * (t * t * t),
+            anchor0Y * (u * u * u) + control0Y * (3 * t * u * u) +
+                control1Y * (3 * t * t * u) + anchor1Y * (t * t * t)
+        )
+    }
+
+    /**
+     * Returns two Cubics, created by splitting this curve at the given
+     * distance of [t] between the original starting and ending anchor points.
+     */
+    // TODO: cartesian optimization?
+    fun split(t: Float): Pair<Cubic, Cubic> {
+        val u = 1 - t
+        val pointOnCurve = pointOnCurve(t)
+        return Cubic(
+            anchor0X, anchor0Y,
+            anchor0X * u + control0X * t, anchor0Y * u + control0Y * t,
+            anchor0X * (u * u) + control0X * (2 * u * t) + control1X * (t * t),
+            anchor0Y * (u * u) + control0Y * (2 * u * t) + control1Y * (t * t),
+            pointOnCurve.x, pointOnCurve.y
+        ) to Cubic(
+            // TODO: should calculate once and share the result
+            pointOnCurve.x, pointOnCurve.y,
+            control0X * (u * u) + control1X * (2 * u * t) + anchor1X * (t * t),
+            control0Y * (u * u) + control1Y * (2 * u * t) + anchor1Y * (t * t),
+            control1X * u + anchor1X * t, control1Y * u + anchor1Y * t,
+            anchor1X, anchor1Y
+        )
+    }
+
+    /**
+     * Utility function to reverse the control/anchor points for this curve.
+     */
+    fun reverse() = Cubic(anchor1X, anchor1Y, control1X, control1Y, control0X, control0Y,
+        anchor0X, anchor0Y)
+
+    /**
+     * Operator overload to enable adding Cubic objects together, like "c0 + c1"
+     */
+    operator fun plus(o: Cubic) = Cubic(FloatArray(8) { points[it] + o.points[it] })
+
+    /**
+     * Operator overload to enable multiplying Cubics by a scalar value x, like "c0 * x"
+     */
+    operator fun times(x: Float) = Cubic(FloatArray(8) { points[it] * x })
+
+    /**
+     * Operator overload to enable multiplying Cubics by an Int scalar value x, like "c0 * x"
+     */
+    operator fun times(x: Int) = times(x.toFloat())
+
+    /**
+     * Operator overload to enable dividing Cubics by a scalar value x, like "c0 / x"
+     */
+    operator fun div(x: Float) = times(1f / x)
+
+    /**
+     * Operator overload to enable dividing Cubics by a scalar value x, like "c0 / x"
+     */
+    operator fun div(x: Int) = div(x.toFloat())
+
+    override fun toString(): String {
+        return "anchor0: ($anchor0X, $anchor0Y) control0: ($control0X, $control0Y), " +
+            "control1: ($control1X, $control1Y), anchor1: ($anchor1X, $anchor1Y)"
+    }
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (javaClass != other?.javaClass) return false
+
+        other as Cubic
+
+        return points.contentEquals(other.points)
+    }
+
+    /**
+     * Transforms the points in this [Cubic] with the given [PointTransformer] and returns a new
+     * [Cubic]
+     *
+     * @param f The [PointTransformer] used to transform this [Cubic]
+     */
+    fun transformed(f: PointTransformer): Cubic {
+        val newCubic = MutableCubic()
+        points.copyInto(newCubic.points)
+        newCubic.transform(f)
+        return newCubic
+    }
+
+    override fun hashCode() = points.contentHashCode()
+
+    companion object {
+        /**
+         * Generates a bezier curve that is a straight line between the given anchor points.
+         * The control points lie 1/3 of the distance from their respective anchor points.
+         */
+        @JvmStatic
+        fun straightLine(x0: Float, y0: Float, x1: Float, y1: Float): Cubic {
+            return Cubic(
+                x0, y0,
+                interpolate(x0, x1, 1f / 3f),
+                interpolate(y0, y1, 1f / 3f),
+                interpolate(x0, x1, 2f / 3f),
+                interpolate(y0, y1, 2f / 3f),
+                x1, y1
+            )
+        }
+
+        // TODO: consider a more general function (maybe in addition to this) that allows
+        // caller to get a list of curves surpassing 180 degrees
+        /**
+         * Generates a bezier curve that approximates a circular arc, with p0 and p1 as
+         * the starting and ending anchor points. The curve generated is the smallest of
+         * the two possible arcs around the entire 360-degree circle. Arcs of greater than 180
+         * degrees should use more than one arc together. Note that p0 and p1 should be
+         * equidistant from the center.
+         */
+        @JvmStatic
+        fun circularArc(
+            centerX: Float,
+            centerY: Float,
+            x0: Float,
+            y0: Float,
+            x1: Float,
+            y1: Float
+        ): Cubic {
+            val p0d = directionVector(x0 - centerX, y0 - centerY)
+            val p1d = directionVector(x1 - centerX, y1 - centerY)
+            val rotatedP0 = p0d.rotate90()
+            val rotatedP1 = p1d.rotate90()
+            val clockwise = rotatedP0.dotProduct(x1 - centerX, y1 - centerY) >= 0
+            val cosa = p0d.dotProduct(p1d)
+            if (cosa > 0.999f) /* p0 ~= p1 */ return straightLine(x0, y0, x1, y1)
+            val k = distance(x0 - centerX, y0 - centerY) * 4f / 3f *
+                (sqrt(2 * (1 - cosa)) - sqrt(1 - cosa * cosa)) / (1 - cosa) *
+                if (clockwise) 1f else -1f
+            return Cubic(
+                x0, y0, x0 + rotatedP0.x * k, y0 + rotatedP0.y * k,
+                x1 - rotatedP1.x * k, y1 - rotatedP1.y * k, x1, y1
+            )
+        }
+    }
+}
+
+/**
+ * This interface is used refer to Points that can be modified, as a scope to
+ * [PointTransformer]
+ */
+interface MutablePoint {
+    /**
+     * The x coordinate of the Point
+     */
+    var x: Float
+
+    /**
+     * The y coordinate of the Point
+     */
+    var y: Float
+}
+
+/**
+ * Interface for a function that can transform (rotate/scale/translate/etc.) points
+ */
+fun interface PointTransformer {
+    /**
+     * Transform the given [MutablePoint] in place.
+     */
+    fun MutablePoint.transform()
+}
+
+/**
+
+ * This is a Mutable version of [Cubic], used mostly for performance critical paths so we can
+ * avoid creating new [Cubic]s
+ *
+ * This is used in Morph.asMutableCubics, reusing a [MutableCubic] instance to avoid creating
+ * new [Cubic]s.
+ */
+class MutableCubic internal constructor() : Cubic() {
+    internal val anchor0 = ArrayMutablePoint(points, 0)
+    internal val control0 = ArrayMutablePoint(points, 2)
+    internal val control1 = ArrayMutablePoint(points, 4)
+    internal val anchor1 = ArrayMutablePoint(points, 6)
+
+    fun transform(f: PointTransformer) {
+        with(f) {
+            anchor0.transform()
+            control0.transform()
+            control1.transform()
+            anchor1.transform()
+        }
+    }
+}
+
+/**
+ * Implementation of [MutablePoint] backed by a [FloatArray], at a given position.
+ * Note that the same [FloatArray] can be used to back many [ArrayMutablePoint],
+ * see [MutableCubic]
+ */
+internal class ArrayMutablePoint(internal val arr: FloatArray, internal val ix: Int) :
+    MutablePoint {
+    init { require(arr.size >= ix + 2) }
+
+    override var x: Float
+        get() = arr[ix]
+        set(v) {
+            arr[ix] = v
+        }
+    override var y: Float
+        get() = arr[ix + 1]
+        set(v) {
+            arr[ix + 1] = v
+        }
+}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FeatureMapping.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/FeatureMapping.kt
similarity index 84%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FeatureMapping.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/FeatureMapping.kt
index a761ae3..c13017d 100644
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FeatureMapping.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/FeatureMapping.kt
@@ -20,22 +20,23 @@
  * MeasuredFeatures contains a list of all features in a polygon along with the [0..1] progress
  * at that feature
  */
-internal typealias MeasuredFeatures = List<Pair<Float, RoundedPolygon.Feature>>
+internal typealias MeasuredFeatures = List<ProgressableFeature>
+internal data class ProgressableFeature(val progress: Float, val feature: Feature)
 
 /**
  * featureMapper creates a mapping between the "features" (rounded corners) of two shapes
  */
 internal fun featureMapper(features1: MeasuredFeatures, features2: MeasuredFeatures): DoubleMapper {
     // We only use corners for this mapping.
-    val filteredFeatures1 = features1.filter { it.second is RoundedPolygon.Corner }
-    val filteredFeatures2 = features2.filter { it.second is RoundedPolygon.Corner }
+    val filteredFeatures1 = features1.filter { it.feature is Feature.Corner }
+    val filteredFeatures2 = features2.filter { it.feature is Feature.Corner }
 
     val (m1, m2) = if (filteredFeatures1.size > filteredFeatures2.size) {
         doMapping(filteredFeatures2, filteredFeatures1) to filteredFeatures2
     } else {
         filteredFeatures1 to doMapping(filteredFeatures1, filteredFeatures2)
     }
-    val mm = m1.zip(m2).map { (f1, f2) -> f1.first to f2.first }
+    val mm = m1.zip(m2).map { (f1, f2) -> f1.progress to f2.progress }
 
     debugLog(LOG_TAG) { mm.joinToString { "${it.first} -> ${it.second}" } }
     return DoubleMapper(*mm.toTypedArray()).also { dm ->
@@ -54,10 +55,10 @@
  * This information is used to determine how to map features (and the curves that make up
  * those features).
  */
-internal fun featureDistSquared(f1: RoundedPolygon.Feature, f2: RoundedPolygon.Feature): Float {
+internal fun featureDistSquared(f1: Feature, f2: Feature): Float {
     // TODO: We might want to enable concave-convex matching in some situations. If so, the
     //  approach below will not work
-    if (f1 is RoundedPolygon.Corner && f2 is RoundedPolygon.Corner && f1.convex != f2.convex) {
+    if (f1 is Feature.Corner && f2 is Feature.Corner && f1.convex != f2.convex) {
         // Simple hack to force all features to map only to features of the same concavity, by
         // returning an infinitely large distance in that case
         debugLog(LOG_TAG) { "*** Feature distance ∞ for convex-vs-concave corners" }
@@ -82,7 +83,7 @@
  */
 internal fun doMapping(f1: MeasuredFeatures, f2: MeasuredFeatures): MeasuredFeatures {
     // Pick the first mapping in a greedy way.
-    val ix = f2.indices.minBy { featureDistSquared(f1[0].second, f2[it].second) }
+    val ix = f2.indices.minBy { featureDistSquared(f1[0].feature, f2[it].feature) }
 
     val m = f1.size
     val n = f2.size
@@ -94,7 +95,7 @@
         // Leave enough items in f2 to pick matches for the items left in f1.
         val last = (ix - (m - i)).let { if (it > lastPicked) it else it + n }
         val best = (lastPicked + 1..last).minBy {
-            featureDistSquared(f1[i].second, f2[it % n].second)
+            featureDistSquared(f1[i].feature, f2[it % n].feature)
         }
         ret.add(f2[best % n])
         lastPicked = best
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Features.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Features.kt
new file mode 100644
index 0000000..8d2774d
--- /dev/null
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Features.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023 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.shapes
+
+/**
+ * This class holds information about a corner (rounded or not) or an edge of a given
+ * polygon. The features of a Polygon can be used to manipulate the shape with more context
+ * of what the shape actually is, rather than simply manipulating the raw curves and lines
+ * which describe it.
+ */
+internal abstract class Feature(val cubics: List<Cubic>) {
+    internal abstract fun transformed(f: PointTransformer): Feature
+
+    /**
+     * Edges have only a list of the cubic curves which make up the edge. Edges lie between
+     * corners and have no vertex or concavity; the curves are simply straight lines (represented
+     * by Cubic curves).
+     */
+    internal class Edge(cubics: List<Cubic>) : Feature(cubics) {
+        override fun transformed(f: PointTransformer) =
+            Edge(cubics.map { it.transformed(f) })
+
+        override fun toString(): String = "Edge"
+    }
+
+    /**
+     * Corners contain the list of cubic curves which describe how the corner is rounded (or
+     * not), plus the vertex at the corner (which the cubics may or may not pass through, depending
+     * on whether the corner is rounded) and a flag indicating whether the corner is convex.
+     * A regular polygon has all convex corners, while a star polygon generally (but not
+     * necessarily) has both convex (outer) and concave (inner) corners.
+     */
+    internal class Corner(
+        cubics: List<Cubic>,
+        val vertex: Point,
+        val roundedCenter: Point,
+        val convex: Boolean = true
+    ) : Feature(cubics) {
+        override fun transformed(f: PointTransformer): Feature {
+            return Corner(
+                cubics.map { it.transformed(f = f) },
+                vertex.transformed(f),
+                roundedCenter.transformed(f),
+                convex
+            )
+        }
+
+        override fun toString(): String {
+            return "Corner: vertex=$vertex, center=$roundedCenter, convex=$convex"
+        }
+    }
+}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FloatMapping.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/FloatMapping.kt
similarity index 100%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/FloatMapping.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/FloatMapping.kt
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Morph.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Morph.kt
new file mode 100644
index 0000000..2280462
--- /dev/null
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Morph.kt
@@ -0,0 +1,241 @@
+/*
+ * 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.shapes
+
+import kotlin.math.min
+
+/**
+ * This class is used to animate between start and end polygons objects.
+ *
+ * Morphing between arbitrary objects can be problematic because it can be difficult to
+ * determine how the points of a given shape map to the points of some other shape.
+ * [Morph] simplifies the problem by only operating on [RoundedPolygon] objects, which
+ * are known to have similar, contiguous structures. For one thing, the shape of a polygon
+ * is contiguous from start to end (compared to an arbitrary Path object, which could have
+ * one or more `moveTo` operations in the shape). Also, all edges of a polygon shape are
+ * represented by [Cubic] objects, thus the start and end shapes use similar operations. Two
+ * Polygon shapes then only differ in the quantity and placement of their curves.
+ * The morph works by determining how to map the curves of the two shapes together (based on
+ * proximity and other information, such as distance to polygon vertices and concavity),
+ * and splitting curves when the shapes do not have the same number of curves or when the
+ * curve placement within the shapes is very different.
+ */
+class Morph(
+    start: RoundedPolygon,
+    end: RoundedPolygon
+) {
+    // morphMatch is the structure which holds the actual shape being morphed. It contains
+    // all cubics necessary to represent the start and end shapes (the original cubics in the
+    // shapes may be cut to align the start/end shapes)
+    private var morphMatch = match(start, end)
+
+    /**
+     * Returns a representation of the morph object at a given [progress] value as a list of Cubics.
+     * Note that this function causes a new list to be created and populated, so there is some
+     * overhead.
+     *
+     * @param progress a value from 0 to 1 that determines the morph's current
+     * shape, between the start and end shapes provided at construction time. A value of 0 results
+     * in the start shape, a value of 1 results in the end shape, and any value in between
+     * results in a shape which is a linear interpolation between those two shapes.
+     * The range is generally [0..1] and values outside could result in undefined shapes, but
+     * values close to (but outside) the range can be used to get an exaggerated effect
+     * (e.g., for a bounce or overshoot animation).
+     */
+    fun asCubics(progress: Float) = morphMatch.map { match ->
+        Cubic(FloatArray(8) {
+            interpolate(
+                match.first.points[it],
+                match.second.points[it],
+                progress
+            )
+        })
+    }
+
+    /**
+     * Returns a representation of the morph object at a given [progress] value as an Iterator of
+     * [MutableCubic]. This function is faster than [asCubics], since it doesn't allocate new
+     * [Cubic] instances, but to do this it reuses the same [MutableCubic] instance during
+     * iteration.
+     *
+     * @param progress a value from 0 to 1 that determines the morph's current
+     * shape, between the start and end shapes provided at construction time. A value of 0 results
+     * in the start shape, a value of 1 results in the end shape, and any value in between
+     * results in a shape which is a linear interpolation between those two shapes.
+     * The range is generally [0..1] and values outside could result in undefined shapes, but
+     * values close to (but outside) the range can be used to get an exaggerated effect
+     * (e.g., for a bounce or overshoot animation).
+     * @param mutableCubic An instance of [MutableCubic] that will be used to set each cubic in
+     * time.
+     */
+    @JvmOverloads
+    fun asMutableCubics(progress: Float, mutableCubic: MutableCubic = MutableCubic()):
+        Sequence<MutableCubic> = morphMatch.asSequence().map { match ->
+            repeat(8) {
+                mutableCubic.points[it] = interpolate(
+                    match.first.points[it],
+                    match.second.points[it],
+                    progress
+                )
+            }
+            mutableCubic
+        }
+
+    internal companion object {
+        /**
+         * [match], called at Morph construction time, creates the structure used to animate between
+         * the start and end shapes. The technique is to match geometry (curves) between the shapes
+         * when and where possible, and to create new/placeholder curves when necessary (when
+         * one of the shapes has more curves than the other). The result is a list of pairs of
+         * Cubic curves. Those curves are the matched pairs: the first of each pair holds the
+         * geometry of the start shape, the second holds the geometry for the end shape.
+         * Changing the progress of a Morph object simply interpolates between all pairs of
+         * curves for the morph shape.
+         *
+         * Curves on both shapes are matched by running the [Measurer] to determine where
+         * the points are in each shape (proportionally, along the outline), and then running
+         * [featureMapper] which decides how to map (match) all of the curves with each other.
+         */
+        @JvmStatic
+        internal fun match(
+            p1: RoundedPolygon,
+            p2: RoundedPolygon
+        ): List<Pair<Cubic, Cubic>> {
+            if (DEBUG) {
+                repeat(2) { polyIndex ->
+                    debugLog(LOG_TAG) {
+                        listOf("Initial start:\n", "Initial end:\n")[polyIndex] +
+                            listOf(p1, p2)[polyIndex].features.joinToString("\n") { feature ->
+                                "${feature.javaClass.name.split("$").last()} - " +
+                                    ((feature as? Feature.Corner)?.convex?.let {
+                                        if (it) "Convex - " else "Concave - " } ?: "") +
+                                    feature.cubics.joinToString("|")
+                            }
+                    }
+                }
+            }
+
+            // Measure polygons, returns lists of measured cubics for each polygon, which
+            // we then use to match start/end curves
+            val measuredPolygon1 = MeasuredPolygon.measurePolygon(
+                AngleMeasurer(p1.centerX, p1.centerY), p1)
+            val measuredPolygon2 = MeasuredPolygon.measurePolygon(
+                AngleMeasurer(p2.centerX, p2.centerY), p2)
+
+            // features1 and 2 will contain the list of corners (just the inner circular curve)
+            // along with the progress at the middle of those corners. These measurement values
+            // are then used to compare and match between the two polygons
+            val features1 = measuredPolygon1.features
+            val features2 = measuredPolygon2.features
+
+            // Map features: doubleMapper is the result of mapping the features in each shape to the
+            // closest feature in the other shape.
+            // Given a progress in one of the shapes it can be used to find the corresponding
+            // progress in the other shape (in both directions)
+            val doubleMapper = featureMapper(features1, features2)
+
+            // cut point on poly2 is the mapping of the 0 point on poly1
+            val polygon2CutPoint = doubleMapper.map(0f)
+            debugLog(LOG_TAG) { "polygon2CutPoint = $polygon2CutPoint" }
+
+            // Cut and rotate.
+            // Polygons start at progress 0, and the featureMapper has decided that we want to match
+            // progress 0 in the first polygon to `polygon2CutPoint` on the second polygon.
+            // So we need to cut the second polygon there and "rotate it", so as we walk through
+            // both polygons we can find the matching.
+            // The resulting bs1/2 are MeasuredPolygons, whose MeasuredCubics start from
+            // outlineProgress=0 and increasing until outlineProgress=1
+            val bs1 = measuredPolygon1
+            val bs2 = measuredPolygon2.cutAndShift(polygon2CutPoint)
+
+            if (DEBUG) {
+                (0 until bs1.size).forEach { index ->
+                    debugLog(LOG_TAG) { "start $index: ${bs1.getOrNull(index)}" }
+                }
+                (0 until bs2.size).forEach { index ->
+                    debugLog(LOG_TAG) { "End $index: ${bs2.getOrNull(index)}" }
+                }
+            }
+
+            // Match
+            // Now we can compare the two lists of measured cubics and create a list of pairs
+            // of cubics [ret], which are the start/end curves that represent the Morph object
+            // and the start and end shapes, and which can be interpolated to animate the
+            // between those shapes.
+            val ret = mutableListOf<Pair<Cubic, Cubic>>()
+            // i1/i2 are the indices of the current cubic on the start (1) and end (2) shapes
+            var i1 = 0
+            var i2 = 0
+            // b1, b2 are the current measured cubic for each polygon
+            var b1 = bs1.getOrNull(i1++)
+            var b2 = bs2.getOrNull(i2++)
+            // Iterate until all curves are accounted for and matched
+            while (b1 != null && b2 != null) {
+                // Progresses are in shape1's perspective
+                // b1a, b2a are ending progress values of current measured cubics in [0,1] range
+                val b1a = if (i1 == bs1.size) 1f else b1.endOutlineProgress
+                val b2a = if (i2 == bs2.size) 1f else doubleMapper.mapBack(
+                    positiveModulo(b2.endOutlineProgress + polygon2CutPoint, 1f)
+                )
+                val minb = min(b1a, b2a)
+                debugLog(LOG_TAG) { "$b1a $b2a | $minb" }
+                // minb is the progress at which the curve that ends first ends.
+                // If both curves ends roughly there, no cutting is needed, we have a match.
+                // If one curve extends beyond, we need to cut it.
+                val (seg1, newb1) = if (b1a > minb + AngleEpsilon) {
+                    debugLog(LOG_TAG) { "Cut 1" }
+                    b1.cutAtProgress(minb)
+                } else {
+                    b1 to bs1.getOrNull(i1++)
+                }
+                val (seg2, newb2) = if (b2a > minb + AngleEpsilon) {
+                    debugLog(LOG_TAG) { "Cut 2" }
+                    b2.cutAtProgress(positiveModulo(doubleMapper.map(minb) - polygon2CutPoint, 1f))
+                } else {
+                    b2 to bs2.getOrNull(i2++)
+                }
+                debugLog(LOG_TAG) { "Match: $seg1 -> $seg2" }
+                ret.add(seg1.cubic to seg2.cubic)
+                b1 = newb1
+                b2 = newb2
+            }
+            require(b1 == null && b2 == null)
+
+            if (DEBUG) {
+                // Export as SVG path.
+                val showPoint: (Point) -> String = {
+                    "%.3f %.3f".format(it.x * 100, it.y * 100)
+                }
+                repeat(2) { listIx ->
+                    val points = ret.map { if (listIx == 0) it.first else it.second }
+                    debugLog(LOG_TAG) {
+                        "M " + showPoint(Point(points.first().anchor0X,
+                            points.first().anchor0Y)) + " " +
+                            points.joinToString(" ") {
+                                "C " + showPoint(Point(it.control0X, it.control0Y)) + ", " +
+                                    showPoint(Point(it.control1X, it.control1Y)) + ", " +
+                                    showPoint(Point(it.anchor1X, it.anchor1Y))
+                            } + " Z"
+                    }
+                }
+            }
+            return ret
+        }
+    }
+}
+
+private val LOG_TAG = "Morph"
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Point.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Point.kt
new file mode 100644
index 0000000..d371fa1
--- /dev/null
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Point.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2023 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:Suppress("NOTHING_TO_INLINE")
+
+package androidx.graphics.shapes;
+
+import kotlin.math.sqrt
+
+/**
+ * Constructs a Point from the given relative x and y coordinates
+ */
+internal fun Point(x: Float = 0f, y: Float = 0f) = Point(packFloats(x, y))
+
+/**
+ * An immutable 2D floating-point Point.
+ *
+ * This can be used to represent either points on a 2D plane, or also distances.
+ *
+ * Creates a Point. The first argument sets [x], the horizontal component,
+ * and the second sets [y], the vertical component.
+ */
+@kotlin.jvm.JvmInline
+internal value class Point internal constructor(internal val packedValue: Long) {
+    val x: Float
+        get() = unpackFloat1(packedValue)
+
+    val y: Float
+        get() = unpackFloat2(packedValue)
+
+    operator fun component1(): Float = x
+
+    operator fun component2(): Float = y
+
+    /**
+     * Returns a copy of this Point instance optionally overriding the
+     * x or y parameter
+     */
+    fun copy(x: Float = this.x, y: Float = this.y) = Point(x, y)
+
+    companion object { }
+
+    /**
+     * The magnitude of the Point, which is the distance of this point from (0, 0).
+     *
+     * If you need this value to compare it to another [Point]'s distance,
+     * consider using [getDistanceSquared] instead, since it is cheaper to compute.
+     */
+    fun getDistance() = sqrt(x * x + y * y)
+
+    /**
+     * The square of the magnitude (which is the distance of this point from (0, 0)) of the Point.
+     *
+     * This is cheaper than computing the [getDistance] itself.
+     */
+    fun getDistanceSquared() = x * x + y * y
+
+    fun dotProduct(other: Point) = x * other.x + y * other.y
+
+    fun dotProduct(otherX: Float, otherY: Float) = x * otherX + y * otherY
+
+    /**
+     * Compute the Z coordinate of the cross product of two vectors, to check if the second vector is
+     * going clockwise ( > 0 ) or counterclockwise (< 0) compared with the first one.
+     * It could also be 0, if the vectors are co-linear.
+     */
+    fun clockwise(other: Point) = x * other.y - y * other.x > 0
+
+    /**
+     * Returns unit vector representing the direction to this point from (0, 0)
+     */
+    fun getDirection() = run {
+        val d = this.getDistance()
+        require(d > 0f)
+        this / d
+    }
+
+    /**
+     * Unary negation operator.
+     *
+     * Returns a Point with the coordinates negated.
+     *
+     * If the [Point] represents an arrow on a plane, this operator returns the
+     * same arrow but pointing in the reverse direction.
+     */
+    operator fun unaryMinus(): Point = Point(-x, -y)
+
+    /**
+     * Binary subtraction operator.
+     *
+     * Returns a Point whose [x] value is the left-hand-side operand's [x]
+     * minus the right-hand-side operand's [x] and whose [y] value is the
+     * left-hand-side operand's [y] minus the right-hand-side operand's [y].
+     */
+    operator fun minus(other: Point): Point = Point(x - other.x, y - other.y)
+
+    /**
+     * Binary addition operator.
+     *
+     * Returns a Point whose [x] value is the sum of the [x] values of the
+     * two operands, and whose [y] value is the sum of the [y] values of the
+     * two operands.
+     */
+    operator fun plus(other: Point): Point = Point(x + other.x, y + other.y)
+
+    /**
+     * Multiplication operator.
+     *
+     * Returns a Point whose coordinates are the coordinates of the
+     * left-hand-side operand (a Point) multiplied by the scalar
+     * right-hand-side operand (a Float).
+     */
+    operator fun times(operand: Float): Point = Point(x * operand, y * operand)
+
+    /**
+     * Division operator.
+     *
+     * Returns a Point whose coordinates are the coordinates of the
+     * left-hand-side operand (a Point) divided by the scalar right-hand-side
+     * operand (a Float).
+     */
+    operator fun div(operand: Float): Point = Point(x / operand, y / operand)
+
+    /**
+     * Modulo (remainder) operator.
+     *
+     * Returns a Point whose coordinates are the remainder of dividing the
+     * coordinates of the left-hand-side operand (a Point) by the scalar
+     * right-hand-side operand (a Float).
+     */
+    operator fun rem(operand: Float) = Point(x % operand, y % operand)
+
+    override fun toString() = "Offset(%.1f, %.1f)".format(x, y)
+}
+
+/**
+ * Linearly interpolate between two Points.
+ *
+ * The [fraction] argument represents position on the timeline, with 0.0 meaning
+ * that the interpolation has not started, returning [start] (or something
+ * equivalent to [start]), 1.0 meaning that the interpolation has finished,
+ * returning [stop] (or something equivalent to [stop]), and values in between
+ * meaning that the interpolation is at the relevant point on the timeline
+ * between [start] and [stop]. The interpolation can be extrapolated beyond 0.0 and
+ * 1.0, so negative values and values greater than 1.0 are valid (and can
+ * easily be generated by curves).
+ *
+ * Values for [fraction] are usually obtained from an [Animation<Float>], such as
+ * an `AnimationController`.
+ */
+internal fun interpolate(start: Point, stop: Point, fraction: Float): Point {
+    return Point(
+        interpolate(start.x, stop.x, fraction),
+        interpolate(start.y, stop.y, fraction)
+    )
+}
+
+/**
+ * Packs two Float values into one Long value for use in inline classes.
+ */
+internal inline fun packFloats(val1: Float, val2: Float): Long {
+    val v1 = val1.toBits().toLong()
+    val v2 = val2.toBits().toLong()
+    return v1.shl(32) or (v2 and 0xFFFFFFFF)
+}
+
+/**
+ * Unpacks the first Float value in [packFloats] from its returned Long.
+ */
+internal inline fun unpackFloat1(value: Long): Float {
+    return Float.fromBits(value.shr(32).toInt())
+}
+
+/**
+ * Unpacks the second Float value in [packFloats] from its returned Long.
+ */
+internal inline fun unpackFloat2(value: Long): Float {
+    return Float.fromBits(value.and(0xFFFFFFFF).toInt())
+}
+
+internal class MutablePointImpl(override var x: Float, override var y: Float) : MutablePoint
+
+internal fun Point.transformed(f: PointTransformer): Point {
+    val m = MutablePointImpl(x, y)
+    with(f) { m.transform() }
+    return Point(m.x, m.y)
+}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/PolygonMeasure.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
similarity index 94%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/PolygonMeasure.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
index b060afb..6c1c032 100644
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/PolygonMeasure.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
@@ -16,18 +16,17 @@
 
 package androidx.graphics.shapes
 
-import android.graphics.PointF
 import androidx.annotation.FloatRange
 import kotlin.math.abs
 
 internal class MeasuredPolygon : AbstractList<MeasuredPolygon.MeasuredCubic> {
     private val measurer: Measurer
     private val cubics: List<MeasuredCubic>
-    val features: List<Pair<Float, RoundedPolygon.Feature>>
+    val features: List<ProgressableFeature>
 
     private constructor(
         measurer: Measurer,
-        features: List<Pair<Float, RoundedPolygon.Feature>>,
+        features: List<ProgressableFeature>,
         cubics: List<Cubic>,
         outlineProgress: List<Float>
     ) {
@@ -217,7 +216,7 @@
 
         // Shift the feature's outline progress too.
         val newFeatures = features.map { (outlineProgress, feature) ->
-            positiveModulo(outlineProgress - cuttingPoint, 1f) to feature
+            ProgressableFeature(positiveModulo(outlineProgress - cuttingPoint, 1f), feature)
         }
 
         // Filter out all empty cubics (i.e. start and end anchor are (almost) the same point.)
@@ -233,13 +232,13 @@
     companion object {
         internal fun measurePolygon(measurer: Measurer, polygon: RoundedPolygon): MeasuredPolygon {
             val cubics = mutableListOf<Cubic>()
-            val featureToCubic = mutableListOf<Pair<RoundedPolygon.Feature, Int>>()
+            val featureToCubic = mutableListOf<Pair<Feature, Int>>()
 
             // Get the cubics from the polygon, at the same time, extract the features and keep a
             // reference to the representative cubic we will use.
             polygon.features.forEach { feature ->
                 feature.cubics.forEachIndexed { index, cubic ->
-                    if (feature is RoundedPolygon.Corner &&
+                    if (feature is Feature.Corner &&
                         index == feature.cubics.size / 2) {
                         featureToCubic.add(feature to cubics.size)
                     }
@@ -256,8 +255,8 @@
 
             val features = featureToCubic.map { featureAndIndex ->
                 val ix = featureAndIndex.second
-                (outlineProgress[ix] + outlineProgress[ix + 1]) / 2 to
-                    featureAndIndex.first
+                ProgressableFeature((outlineProgress[ix] + outlineProgress[ix + 1]) / 2,
+                    featureAndIndex.first)
             }
 
             return MeasuredPolygon(measurer, features, cubics, outlineProgress)
@@ -298,9 +297,6 @@
  */
 internal class AngleMeasurer(val centerX: Float, val centerY: Float) : Measurer {
 
-    // Holds temporary pointOnCurve result, avoids re-allocations
-    private val tempPoint = PointF()
-
     /**
      * The measurement for a given cubic is the difference in angles between the start
      * and end points (first and last anchors) of the cubic.
@@ -319,7 +315,7 @@
         val angle0 = angle(c.anchor0X - centerX, c.anchor0Y - centerY)
         // TODO: use binary search.
         return findMinimum(0f, 1f, tolerance = 1e-5f) { t ->
-            val curvePoint = c.pointOnCurve(t, tempPoint)
+            val curvePoint = c.pointOnCurve(t)
             val angle = angle(curvePoint.x - centerX, curvePoint.y - centerY)
             abs(positiveModulo(angle - angle0, TwoPi) - m)
         }
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt
new file mode 100644
index 0000000..a872789
--- /dev/null
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/RoundedPolygon.kt
@@ -0,0 +1,543 @@
+/*
+ * 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.shapes
+
+import androidx.annotation.IntRange
+import kotlin.math.abs
+import kotlin.math.max
+import kotlin.math.min
+import kotlin.math.sqrt
+
+/**
+ * The RoundedPolygon class allows simple construction of polygonal shapes with optional rounding
+ * at the vertices. Polygons can be constructed with either the number of vertices
+ * desired or an ordered list of vertices.
+ *
+ */
+class RoundedPolygon internal constructor(
+    internal val features: List<Feature>,
+    val centerX: Float,
+    val centerY: Float
+) {
+    /**
+     * A flattened version of the [Feature]s, as a List<Cubic>.
+     */
+    val cubics = features.flatMap { it.cubics }
+
+    init {
+        var prevCubic = cubics[cubics.size - 1]
+        debugLog("RoundedPolygon") { "Cubic-1 = $prevCubic" }
+        cubics.forEachIndexed { index, cubic ->
+            if (abs(cubic.anchor0X - prevCubic.anchor1X) > DistanceEpsilon ||
+                abs(cubic.anchor0Y - prevCubic.anchor1Y) > DistanceEpsilon) {
+                debugLog("RoundedPolygon") { "Cubic = $cubic" }
+                debugLog("RoundedPolygon") {
+                    "Ix: $index | (${cubic.anchor0X},${cubic.anchor0Y}) vs " +
+                        "$prevCubic"
+                }
+                throw IllegalArgumentException("RoundedPolygon must be contiguous, with the " +
+                    "anchor points of all curves matching the anchor points of the preceding " +
+                    "and succeeding cubics")
+            }
+            prevCubic = cubic
+        }
+    }
+
+    /**
+     * Transforms (scales/translates/etc.) this [RoundedPolygon] with the given [PointTransformer]
+     * and returns a new [RoundedPolygon].
+     * This is a low level API and there should be more platform idiomatic ways to transform
+     * a [RoundedPolygon] provided by the platform specific wrapper.
+     *
+     * @param f The [PointTransformer] used to transform this [RoundedPolygon]
+     */
+    fun transformed(f: PointTransformer): RoundedPolygon {
+        val center = Point(centerX, centerY).transformed(f)
+        return RoundedPolygon(features.map { it.transformed(f) }, center.x, center.y)
+    }
+
+    /**
+     * Creates a new RoundedPolygon, moving and resizing this one, so it's completely inside the
+     * (0, 0) -> (1, 1) square, centered if there extra space in one direction
+     */
+    fun normalized(): RoundedPolygon {
+        val bounds = calculateBounds()
+        val width = bounds[2] - bounds[0]
+        val height = bounds[3] - bounds[1]
+        val side = max(width, height)
+        // Center the shape if bounds are not a square
+        val offsetX = (side - width) / 2 - bounds[0] /* left */
+        val offsetY = (side - height) / 2 - bounds[1] /* top */
+        return transformed {
+            x = (x + offsetX) / side
+            y = (y + offsetY) / side
+        }
+    }
+
+    override fun toString(): String = "[RoundedPolygon." +
+        " Cubics = " + cubics.joinToString() +
+        " || Features = " + features.joinToString() +
+        " || Center = ($centerX, $centerY)]"
+
+    /**
+     * Calculates estimated bounds of the object, using the min/max bounding box of
+     * all points in the cubics that make up the shape.
+     * This is a library-internal API, prefer the appropriate wrapper in your platform.
+     */
+    fun calculateBounds(bounds: FloatArray = FloatArray(4)): FloatArray {
+        require(bounds.size >= 4)
+        var minX = Float.MAX_VALUE
+        var minY = Float.MAX_VALUE
+        var maxX = Float.MIN_VALUE
+        var maxY = Float.MIN_VALUE
+        for (bezier in cubics) {
+            if (bezier.anchor0X < minX) minX = bezier.anchor0X
+            if (bezier.anchor0Y < minY) minY = bezier.anchor0Y
+            if (bezier.anchor0X > maxX) maxX = bezier.anchor0X
+            if (bezier.anchor0Y > maxY) maxY = bezier.anchor0Y
+
+            if (bezier.control0X < minX) minX = bezier.control0X
+            if (bezier.control0Y < minY) minY = bezier.control0Y
+            if (bezier.control0X > maxX) maxX = bezier.control0X
+            if (bezier.control0Y > maxY) maxY = bezier.control0Y
+
+            if (bezier.control1X < minX) minX = bezier.control1X
+            if (bezier.control1Y < minY) minY = bezier.control1Y
+            if (bezier.control1X > maxX) maxX = bezier.control1X
+            if (bezier.control1Y > maxY) maxY = bezier.control1Y
+            // No need to use x3/y3, since it is already taken into account in the next
+            // curve's x0/y0 point.
+        }
+        bounds[0] = minX
+        bounds[1] = minY
+        bounds[2] = maxX
+        bounds[3] = maxY
+        return bounds
+    }
+
+    companion object {}
+
+    override fun equals(other: Any?): Boolean {
+        if (this === other) return true
+        if (other !is RoundedPolygon) return false
+
+        return features == other.features
+    }
+
+    override fun hashCode(): Int {
+        return features.hashCode()
+    }
+}
+
+/**
+ * This constructor takes the number of vertices in the resulting polygon. These vertices are
+ * positioned on a virtual circle around a given center with each vertex positioned [radius]
+ * distance from that center, equally spaced (with equal angles between them). If no radius
+ * is supplied, the shape will be created with a default radius of 1, resulting in a shape
+ * whose vertices lie on a unit circle, with width/height of 2. That default polygon will
+ * probably need to be rescaled using [transformed] into the appropriate size for the UI in
+ * which it will be drawn.
+ *
+ * The [rounding] and [perVertexRounding] parameters are optional. If not supplied, the result
+ * will be a regular polygon with straight edges and unrounded corners.
+ *
+ * @param numVertices The number of vertices in this polygon.
+ * @param radius The radius of the polygon, in pixels. This radius determines the
+ * initial size of the object, but it can be transformed later by using the [transformed] function.
+ * @param centerX The X coordinate of the center of the polygon, around which all vertices
+ * will be placed. The default center is at (0,0).
+ * @param centerY The Y coordinate of the center of the polygon, around which all vertices
+ * will be placed. The default center is at (0,0).
+ * @param rounding The [CornerRounding] properties of all vertices. If some vertices should
+ * have different rounding properties, then use [perVertexRounding] instead. The default
+ * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
+ * themselves in the final shape and not curves rounded around the vertices.
+ * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
+ * parameter is not null, then it must have [numVertices] elements. If this parameter
+ * is null, then the polygon will use the [rounding] parameter for every vertex instead. The
+ * default value is null.
+ *
+ * @throws IllegalArgumentException If [perVertexRounding] is not null and its size is not
+ * equal to [numVertices].
+ * @throws IllegalArgumentException [numVertices] must be at least 3.
+ */
+@JvmOverloads
+fun RoundedPolygon(
+    @IntRange(from = 3) numVertices: Int,
+    radius: Float = 1f,
+    centerX: Float = 0f,
+    centerY: Float = 0f,
+    rounding: CornerRounding = CornerRounding.Unrounded,
+    perVertexRounding: List<CornerRounding>? = null
+) = RoundedPolygon(
+    verticesFromNumVerts(numVertices, radius, centerX, centerY),
+    rounding = rounding,
+    perVertexRounding = perVertexRounding,
+    centerX = centerX,
+    centerY = centerY)
+
+/**
+ * Creates a copy of the given [RoundedPolygon]
+ */
+fun RoundedPolygon(source: RoundedPolygon) =
+    RoundedPolygon(source.features, source.centerX, source.centerY)
+
+/**
+ * This function takes the vertices (either supplied or calculated, depending on the
+ * constructor called), plus [CornerRounding] parameters, and creates the actual
+ * [RoundedPolygon] shape, rounding around the vertices (or not) as specified. The result
+ * is a list of [Cubic] curves which represent the geometry of the final shape.
+ *
+ * @param vertices The list of vertices in this polygon specified as pairs of x/y coordinates in
+ * this FloatArray. This should be an ordered list (with the outline of the shape going from each
+ * vertex to the next in order of this list), otherwise the results will be undefined.
+ * @param rounding The [CornerRounding] properties of all vertices. If some vertices should
+ * have different rounding properties, then use [perVertexRounding] instead. The default
+ * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
+ * themselves in the final shape and not curves rounded around the vertices.
+ * @param perVertexRounding The [CornerRounding] properties of all vertices. If this
+ * parameter is not null, then it must have the same size as [vertices]. If this parameter
+ * is null, then the polygon will use the [rounding] parameter for every vertex instead. The
+ * default value is null.
+ * @param centerX The X coordinate of the center of the polygon, around which all vertices
+ * will be placed. The default center is at (0,0).
+ * @param centerY The Y coordinate of the center of the polygon, around which all vertices
+ * will be placed. The default center is at (0,0).
+ * @throws IllegalArgumentException if the number of vertices is less than 3 (the [vertices]
+ * parameter has less than 6 Floats). Or if the [perVertexRounding] parameter is not null and the
+ * size doesn't match the number vertices.
+ */
+@JvmOverloads
+fun RoundedPolygon(
+    vertices: FloatArray,
+    rounding: CornerRounding = CornerRounding.Unrounded,
+    perVertexRounding: List<CornerRounding>? = null,
+    centerX: Float = Float.MIN_VALUE,
+    centerY: Float = Float.MIN_VALUE
+): RoundedPolygon {
+    if (vertices.size < 6) {
+        throw IllegalArgumentException("Polygons must have at least 3 vertices")
+    }
+    if (vertices.size % 2 == 1) {
+        throw IllegalArgumentException("The vertices array should have even size")
+    }
+    if (perVertexRounding != null && perVertexRounding.size * 2 != vertices.size) {
+        throw IllegalArgumentException("perVertexRounding list should be either null or " +
+            "the same size as the number of vertices (vertices.size / 2)")
+    }
+    val corners = mutableListOf<List<Cubic>>()
+    val n = vertices.size / 2
+    val roundedCorners = mutableListOf<RoundedCorner>()
+    for (i in 0 until n) {
+        val vtxRounding = perVertexRounding?.get(i) ?: rounding
+        val prevIndex = ((i + n - 1) % n) * 2
+        val nextIndex = ((i + 1) % n) * 2
+        roundedCorners.add(
+            RoundedCorner(
+                Point(vertices[prevIndex], vertices[prevIndex + 1]),
+                Point(vertices[i * 2], vertices[i * 2 + 1]),
+                Point(vertices[nextIndex], vertices[nextIndex + 1]),
+                vtxRounding
+            )
+        )
+    }
+
+    // For each side, check if we have enough space to do the cuts needed, and if not split
+    // the available space, first for round cuts, then for smoothing if there is space left.
+    // Each element in this list is a pair, that represent how much we can do of the cut for
+    // the given side (side i goes from corner i to corner i+1), the elements of the pair are:
+    // first is how much we can use of expectedRoundCut, second how much of expectedCut
+    val cutAdjusts = (0 until n).map { ix ->
+        val expectedRoundCut = roundedCorners[ix].expectedRoundCut +
+            roundedCorners[(ix + 1) % n].expectedRoundCut
+        val expectedCut = roundedCorners[ix].expectedCut +
+            roundedCorners[(ix + 1) % n].expectedCut
+        val vtxX = vertices[ix * 2]
+        val vtxY = vertices[ix * 2 + 1]
+        val nextVtxX = vertices[((ix + 1) % n) * 2]
+        val nextVtxY = vertices[((ix + 1) % n) * 2 + 1]
+        val sideSize = distance(vtxX - nextVtxX, vtxY - nextVtxY)
+
+        // Check expectedRoundCut first, and ensure we fulfill rounding needs first for
+        // both corners before using space for smoothing
+        if (expectedRoundCut > sideSize) {
+            // Not enough room for fully rounding, see how much we can actually do.
+            sideSize / expectedRoundCut to 0f
+        } else if (expectedCut > sideSize) {
+            // We can do full rounding, but not full smoothing.
+            1f to (sideSize - expectedRoundCut) / (expectedCut - expectedRoundCut)
+        } else {
+            // There is enough room for rounding & smoothing.
+            1f to 1f
+        }
+    }
+    // Create and store list of beziers for each [potentially] rounded corner
+    for (i in 0 until n) {
+        // allowedCuts[0] is for the side from the previous corner to this one,
+        // allowedCuts[1] is for the side from this corner to the next one.
+        val allowedCuts = (0..1).map { delta ->
+            val (roundCutRatio, cutRatio) = cutAdjusts[(i + n - 1 + delta) % n]
+            roundedCorners[i].expectedRoundCut * roundCutRatio +
+                (roundedCorners[i].expectedCut - roundedCorners[i].expectedRoundCut) * cutRatio
+        }
+        corners.add(
+            roundedCorners[i].getCubics(
+                allowedCut0 = allowedCuts[0],
+                allowedCut1 = allowedCuts[1]
+            )
+        )
+    }
+    // Finally, store the calculated cubics. This includes all of the rounded corners
+    // from above, along with new cubics representing the edges between those corners.
+    val tempFeatures = mutableListOf<Feature>()
+    for (i in 0 until n) {
+        // Determine whether corner at this vertex is concave or convex, based on the
+        // relationship of the prev->curr/curr->next vectors
+        // Note that these indices are for pairs of values (points), they need to be
+        // doubled to access the xy values in the vertices float array
+        val prevVtxIndex = (i + n - 1) % n
+        val nextVtxIndex = (i + 1) % n
+        val currVertex = Point(vertices[i * 2], vertices[i * 2 + 1])
+        val prevVertex = Point(vertices[prevVtxIndex * 2], vertices[prevVtxIndex * 2 + 1])
+        val nextVertex = Point(vertices[nextVtxIndex * 2], vertices[nextVtxIndex * 2 + 1])
+        val convex = (currVertex - prevVertex).clockwise(nextVertex - currVertex)
+        tempFeatures.add(
+            Feature.Corner(
+                corners[i], currVertex, roundedCorners[i].center,
+                convex
+            )
+        )
+        tempFeatures.add(
+            Feature.Edge(
+                listOf(
+                    Cubic.straightLine(
+                        corners[i].last().anchor1X, corners[i].last().anchor1Y,
+                        corners[(i + 1) % n].first().anchor0X, corners[(i + 1) % n].first().anchor0Y
+                    )
+                )
+            )
+        )
+    }
+
+    val (cx, cy) = if (centerX == Float.MIN_VALUE || centerY == Float.MIN_VALUE) {
+        calculateCenter(vertices)
+    } else {
+        Point(centerX, centerY)
+    }
+    return RoundedPolygon(tempFeatures, cx, cy)
+}
+
+/**
+ * Calculates an estimated center position for the polygon, returning it.
+ * This function should only be called if the center is not already calculated or provided.
+ * The Polygon constructor which takes `numVertices` calculates its own center, since it
+ * knows exactly where it is centered, at (0, 0).
+ *
+ * Note that this center will be transformed whenever the shape itself is transformed.
+ * Any transforms that occur before the center is calculated will be taken into account
+ * automatically since the center calculation is an average of the current location of
+ * all cubic anchor points.
+ */
+private fun calculateCenter(vertices: FloatArray): Point {
+    var cumulativeX = 0f
+    var cumulativeY = 0f
+    var index = 0
+    while (index < vertices.size) {
+        cumulativeX += vertices[index++]
+        cumulativeY += vertices[index++]
+    }
+    return Point(cumulativeX / vertices.size / 2, cumulativeY / vertices.size / 2)
+}
+
+/**
+ * Private utility class that holds the information about each corner in a polygon. The shape
+ * of the corner can be returned by calling the [getCubics] function, which will return a list
+ * of curves representing the corner geometry. The shape of the corner depends on the [rounding]
+ * constructor parameter.
+ *
+ * If rounding is null, there is no rounding; the corner will simply be a single point at [p1].
+ * This point will be represented by a [Cubic] of length 0 at that point.
+ *
+ * If rounding is not null, the corner will be rounded either with a curve approximating a circular
+ * arc of the radius specified in [rounding], or with three curves if [rounding] has a nonzero
+ * smoothing parameter. These three curves are a circular arc in the middle and two symmetrical
+ * flanking curves on either side. The smoothing parameter determines the curvature of the
+ * flanking curves.
+ *
+ * This is a class because we usually need to do the work in 2 steps, and prefer to keep state
+ * between: first we determine how much we want to cut to comply with the parameters, then we are
+ * given how much we can actually cut (because of space restrictions outside this corner)
+ *
+ * @param p0 the vertex before the one being rounded
+ * @param p1 the vertex of this rounded corner
+ * @param p2 the vertex after the one being rounded
+ * @param rounding the optional parameters specifying how this corner should be rounded
+ */
+private class RoundedCorner(
+    val p0: Point,
+    val p1: Point,
+    val p2: Point,
+    val rounding: CornerRounding? = null
+) {
+    val d1 = (p0 - p1).getDirection()
+    val d2 = (p2 - p1).getDirection()
+    val cornerRadius = rounding?.radius ?: 0f
+    val smoothing = rounding?.smoothing ?: 0f
+
+    // cosine of angle at p1 is dot product of unit vectors to the other two vertices
+    val cosAngle = d1.dotProduct(d2)
+    // identity: sin^2 + cos^2 = 1
+    // sinAngle gives us the intersection
+    val sinAngle = sqrt(1 - square(cosAngle))
+    // How much we need to cut, as measured on a side, to get the required radius
+    // calculating where the rounding circle hits the edge
+    // This uses the identity of tan(A/2) = sinA/(1 + cosA), where tan(A/2) = radius/cut
+    val expectedRoundCut =
+        if (sinAngle > 1e-3) { cornerRadius * (cosAngle + 1) / sinAngle } else { 0f }
+    // smoothing changes the actual cut. 0 is same as expectedRoundCut, 1 doubles it
+    val expectedCut: Float
+        get() = ((1 + smoothing) * expectedRoundCut)
+    // the center of the circle approximated by the rounding curve (or the middle of the three
+    // curves if smoothing is requested). The center is the same as p0 if there is no rounding.
+    var center: Point = Point()
+
+    @JvmOverloads
+    fun getCubics(allowedCut0: Float, allowedCut1: Float = allowedCut0):
+        List<Cubic> {
+        // We use the minimum of both cuts to determine the radius, but if there is more space
+        // in one side we can use it for smoothing.
+        val allowedCut = min(allowedCut0, allowedCut1)
+        // Nothing to do, just use lines, or a point
+        if (expectedRoundCut < DistanceEpsilon ||
+            allowedCut < DistanceEpsilon ||
+            cornerRadius < DistanceEpsilon
+        ) {
+            center = p1
+            return listOf(Cubic.straightLine(p1.x, p1.y, p1.x, p1.y))
+        }
+        // How much of the cut is required for the rounding part.
+        val actualRoundCut = min(allowedCut, expectedRoundCut)
+        // We have two smoothing values, one for each side of the vertex
+        // Space is used for rounding values first. If there is space left over, then we
+        // apply smoothing, if it was requested
+        val actualSmoothing0 = calculateActualSmoothingValue(allowedCut0)
+        val actualSmoothing1 = calculateActualSmoothingValue(allowedCut1)
+        // Scale the radius if needed
+        val actualR = cornerRadius * actualRoundCut / expectedRoundCut
+        // Distance from the corner (p1) to the center
+        val centerDistance = sqrt(square(actualR) + square(actualRoundCut))
+        // Center of the arc we will use for rounding
+        center = p1 + ((d1 + d2) / 2f).getDirection() * centerDistance
+        val circleIntersection0 = p1 + d1 * actualRoundCut
+        val circleIntersection2 = p1 + d2 * actualRoundCut
+        val flanking0 = computeFlankingCurve(
+            actualRoundCut, actualSmoothing0, p1, p0,
+            circleIntersection0, circleIntersection2, center, actualR
+        )
+        val flanking2 = computeFlankingCurve(
+            actualRoundCut, actualSmoothing1, p1, p2,
+            circleIntersection2, circleIntersection0, center, actualR
+        ).reverse()
+        return listOf(
+            flanking0,
+            Cubic.circularArc(center.x, center.y, flanking0.anchor1X, flanking0.anchor1Y,
+                flanking2.anchor0X, flanking2.anchor0Y),
+            flanking2
+        )
+    }
+
+    /**
+     * If allowedCut (the amount we are able to cut) is greater than the expected cut
+     * (without smoothing applied yet), then there is room to apply smoothing and we
+     * calculate the actual smoothing value here.
+     */
+    private fun calculateActualSmoothingValue(allowedCut: Float): Float {
+        return if (allowedCut > expectedCut) {
+            smoothing
+        } else if (allowedCut > expectedRoundCut) {
+            smoothing * (allowedCut - expectedRoundCut) / (expectedCut - expectedRoundCut)
+        } else {
+            0f
+        }
+    }
+
+    /**
+     * Compute a Bezier to connect the linear segment defined by corner and sideStart
+     * with the circular segment defined by circleCenter, circleSegmentIntersection,
+     * otherCircleSegmentIntersection and actualR.
+     * The bezier will start at the linear segment and end on the circular segment.
+     *
+     * @param actualRoundCut How much we are cutting of the corner to add the circular segment
+     * (this is before smoothing, that will cut some more).
+     * @param actualSmoothingValues How much we want to smooth (this is the smooth parameter,
+     * adjusted down if there is not enough room).
+     * @param corner The point at which the linear side ends
+     * @param sideStart The point at which the linear side starts
+     * @param circleSegmentIntersection The point at which the linear side and the circle intersect.
+     * @param otherCircleSegmentIntersection The point at which the opposing linear side and the
+     * circle intersect.
+     * @param circleCenter The center of the circle.
+     * @param actualR The radius of the circle.
+     *
+     * @return a Bezier cubic curve that connects from the (cut) linear side and the (cut) circular
+     * segment in a smooth way.
+     */
+    private fun computeFlankingCurve(
+        actualRoundCut: Float,
+        actualSmoothingValues: Float,
+        corner: Point,
+        sideStart: Point,
+        circleSegmentIntersection: Point,
+        otherCircleSegmentIntersection: Point,
+        circleCenter: Point,
+        actualR: Float
+    ): Cubic {
+        // sideStart is the anchor, 'anchor' is actual control point
+        val sideDirection = (sideStart - corner).getDirection()
+        val curveStart = corner + sideDirection * actualRoundCut * (1 + actualSmoothingValues)
+        // We use an approximation to cut a part of the circle section proportional to 1 - smooth,
+        // When smooth = 0, we take the full section, when smooth = 1, we take nothing.
+        // TODO: revisit this, it can be problematic as it approaches 180 degrees
+        val p = interpolate(circleSegmentIntersection,
+            (circleSegmentIntersection + otherCircleSegmentIntersection) / 2f,
+            actualSmoothingValues)
+        // The flanking curve ends on the circle
+        val curveEnd = circleCenter +
+            directionVector(p.x - circleCenter.x, p.y - circleCenter.y) * actualR
+        // The anchor on the circle segment side is in the intersection between the tangent to the
+        // circle in the circle/flanking curve boundary and the linear segment.
+        val circleTangent = (curveEnd - circleCenter).rotate90()
+        val anchorEnd = lineIntersection(sideStart, sideDirection, curveEnd, circleTangent)
+            ?: circleSegmentIntersection
+        // From what remains, we pick a point for the start anchor.
+        // 2/3 seems to come from design tools?
+        val anchorStart = (curveStart + anchorEnd * 2f) / 3f
+        return Cubic(curveStart, anchorStart, anchorEnd, curveEnd)
+    }
+
+    /**
+     * Returns the intersection point of the two lines d0->d1 and p0->p1, or null if the
+     * lines do not intersect
+     */
+    private fun lineIntersection(p0: Point, d0: Point, p1: Point, d1: Point): Point? {
+        val rotatedD1 = d1.rotate90()
+        val den = d0.dotProduct(rotatedD1)
+        if (abs(den) < AngleEpsilon) return null
+        val k = (p1 - p0).dotProduct(rotatedD1) / den
+        return p0 + d0 * k
+    }
+}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Shapes.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
similarity index 98%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Shapes.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
index 24c1e9c..ef4d25b 100644
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Shapes.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
@@ -57,7 +57,7 @@
  *
  * As with all [RoundedPolygon] objects, if this shape is created with default dimensions and
  * center, it is sized to fit within the 2x2 bounding box around a center of (0, 0) and will
- * need to be scaled and moved using [RoundedPolygon.transform] to fit the intended area
+ * need to be scaled and moved using [RoundedPolygon.transformed] to fit the intended area
  * in a UI.
  *
  * @param width The width of the rectangle, default value is 2
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Utils.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Utils.kt
similarity index 69%
rename from graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Utils.kt
rename to graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Utils.kt
index 9ed7748..0c3b2b0 100644
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Utils.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Utils.kt
@@ -18,11 +18,6 @@
 
 package androidx.graphics.shapes
 
-import android.graphics.PointF
-import android.util.Log
-import androidx.core.graphics.div
-import androidx.core.graphics.plus
-import androidx.core.graphics.times
 import kotlin.math.atan2
 import kotlin.math.cos
 import kotlin.math.sin
@@ -32,40 +27,24 @@
  * This class has all internal methods, used by Polygon, Morph, etc.
  */
 
-internal fun interpolate(start: Float, stop: Float, fraction: Float) =
-    (start * (1 - fraction) + stop * fraction)
-
-internal fun PointF.getDistance() = sqrt(x * x + y * y)
-
-internal fun PointF.dotProduct(other: PointF) = x * other.x + y * other.y
-internal fun PointF.dotProduct(otherX: Float, otherY: Float) = x * otherX + y * otherY
-
-/**
- * Compute the Z coordinate of the cross product of two vectors, to check if the second vector is
- * going clockwise ( > 0 ) or counterclockwise (< 0) compared with the first one.
- * It could also be 0, if the vectors are co-linear.
- */
-internal fun PointF.clockwise(other: PointF) = x * other.y - y * other.x > 0
-
-/**
- * Returns unit vector representing the direction to this point from (0, 0)
- */
-internal fun PointF.getDirection() = run {
-    val d = this.getDistance()
-    require(d > 0f)
-    this / d
-}
-
 internal fun distance(x: Float, y: Float) = sqrt(x * x + y * y)
 
 /**
  * Returns unit vector representing the direction to this point from (0, 0)
  */
-internal fun directionVector(x: Float, y: Float): PointF {
+internal fun directionVector(x: Float, y: Float): Point {
     val d = distance(x, y)
     require(d > 0f)
-    return PointF(x / d, y / d)
+    return Point(x / d, y / d)
 }
+
+internal fun directionVector(angleRadians: Float) = Point(cos(angleRadians), sin(angleRadians))
+
+internal fun angle(x: Float, y: Float) = ((atan2(y, x) + TwoPi) % TwoPi)
+
+internal fun radialToCartesian(radius: Float, angleRadians: Float, center: Point = Zero) =
+    directionVector(angleRadians) * radius + center
+
 /**
  * These epsilon values are used internally to determine when two points are the same, within
  * some reasonable roundoff error. The distance epsilon is smaller, with the intention that the
@@ -74,27 +53,22 @@
 internal const val DistanceEpsilon = 1e-4f
 internal const val AngleEpsilon = 1e-6f
 
-internal fun PointF.rotate90() = PointF(-y, x)
+internal fun Point.rotate90() = Point(-y, x)
 
-internal val Zero = PointF(0f, 0f)
+internal val Zero = Point(0f, 0f)
 
 internal val FloatPi = Math.PI.toFloat()
 
 internal val TwoPi: Float = 2 * Math.PI.toFloat()
 
-internal fun directionVector(angleRadians: Float) = PointF(cos(angleRadians), sin(angleRadians))
-
 internal fun square(x: Float) = x * x
 
-internal fun PointF.copy(x: Float = Float.NaN, y: Float = Float.NaN) =
-    PointF(if (x.isNaN()) this.x else x, if (y.isNaN()) this.y else y)
-
-internal fun PointF.angle() = ((atan2(y, x) + TwoPi) % TwoPi)
-
-internal fun angle(x: Float, y: Float) = ((atan2(y, x) + TwoPi) % TwoPi)
-
-internal fun radialToCartesian(radius: Float, angleRadians: Float, center: PointF = Zero) =
-    directionVector(angleRadians) * radius + center
+/**
+ * Linearly interpolate between [start] and [stop] with [fraction] fraction between them.
+ */
+internal fun interpolate(start: Float, stop: Float, fraction: Float): Float {
+    return (1 - fraction) * start + fraction * stop
+}
 
 internal fun positiveModulo(num: Float, mod: Float) = (num % mod + mod) % mod
 
@@ -135,7 +109,7 @@
     var arrayIndex = 0
     for (i in 0 until numVertices) {
         val vertex = radialToCartesian(radius, (FloatPi / numVertices * 2 * i)) +
-            PointF(centerX, centerY)
+            Point(centerX, centerY)
         result[arrayIndex++] = vertex.x
         result[arrayIndex++] = vertex.y
     }
@@ -153,20 +127,22 @@
     var arrayIndex = 0
     for (i in 0 until numVerticesPerRadius) {
         var vertex = radialToCartesian(radius, (FloatPi / numVerticesPerRadius * 2 * i)) +
-            PointF(centerX, centerY)
+            Point(centerX, centerY)
         result[arrayIndex++] = vertex.x
         result[arrayIndex++] = vertex.y
         vertex = radialToCartesian(innerRadius, (FloatPi / numVerticesPerRadius * (2 * i + 1))) +
-            PointF(centerX, centerY)
+            Point(centerX, centerY)
         result[arrayIndex++] = vertex.x
         result[arrayIndex++] = vertex.y
     }
     return result
 }
 
-// Used to enable debug logging in the library
-internal val DEBUG = false
+internal const val DEBUG = false
 
 internal inline fun debugLog(tag: String, messageFactory: () -> String) {
-    if (DEBUG) messageFactory().split("\n").forEach { Log.d(tag, it) }
+    // TODO: Re-implement properly when the library goes KMP using expect/actual
+    if (DEBUG) {
+        println("$tag: ${messageFactory()}")
+    }
 }
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Cubic.kt b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Cubic.kt
deleted file mode 100644
index a99d457..0000000
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Cubic.kt
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Matrix
-import android.graphics.PointF
-import kotlin.math.sqrt
-
-/**
- * This class holds the anchor and control point data for a single cubic Bézier curve,
- * with anchor points ([anchor0X], [anchor0Y]) and ([anchor1X], [anchor1Y]) at either end
- * and control points ([control0X], [control0Y]) and ([control1X], [control1Y]) determining
- * the slope of the curve between the anchor points.
- *
- * @param anchor0X the first anchor point x coordinate
- * @param anchor0Y the first anchor point y coordinate
- * @param control0X the first control point x coordinate
- * @param control0Y the first control point y coordinate
- * @param control1X the second control point x coordinate
- * @param control1Y the second control point y coordinate
- * @param anchor1X the second anchor point x coordinate
- * @param anchor1Y the second anchor point y coordinate
- */
-class Cubic(
-    anchor0X: Float,
-    anchor0Y: Float,
-    control0X: Float,
-    control0Y: Float,
-    control1X: Float,
-    control1Y: Float,
-    anchor1X: Float,
-    anchor1Y: Float
-) {
-
-    /**
-     * The first anchor point x coordinate
-     */
-    var anchor0X: Float = anchor0X
-        private set
-
-    /**
-     * The first anchor point y coordinate
-     */
-    var anchor0Y: Float = anchor0Y
-        private set
-
-    /**
-     * The first control point x coordinate
-     */
-    var control0X: Float = control0X
-        private set
-
-    /**
-     * The first control point y coordinate
-     */
-    var control0Y: Float = control0Y
-        private set
-
-    /**
-     * The second control point x coordinate
-     */
-    var control1X: Float = control1X
-        private set
-
-    /**
-     * The second control point y coordinate
-     */
-    var control1Y: Float = control1Y
-        private set
-
-    /**
-     * The second anchor point x coordinate
-     */
-    var anchor1X: Float = anchor1X
-        private set
-
-    /**
-     * The second anchor point y coordinate
-     */
-    var anchor1Y: Float = anchor1Y
-        private set
-
-    internal constructor(p0: PointF, p1: PointF, p2: PointF, p3: PointF) :
-        this(p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y)
-
-    /**
-     * Copy constructor which creates a copy of the given object.
-     */
-    constructor(cubic: Cubic) : this(
-        cubic.anchor0X, cubic.anchor0Y, cubic.control0X, cubic.control0Y,
-        cubic.control1X, cubic.control1Y, cubic.anchor1X, cubic.anchor1Y,
-    )
-
-    override fun toString(): String {
-        return "p0: ($anchor0X, $anchor0Y) p1: ($control0X, $control0Y), " +
-            "p2: ($control1X, $control1Y), p3: ($anchor1X, $anchor1Y)"
-    }
-
-    /**
-     * Returns a point on the curve for parameter t, representing the proportional distance
-     * along the curve between its starting ([anchor0X], [anchor0Y]) and ending
-     * ([anchor1X], [anchor1Y]) anchor points.
-     *
-     * @param t The distance along the curve between the anchor points, where 0 is at
-     * ([anchor0X], [anchor0Y]) and 1 is at ([control0X], [control0Y])
-     * @param result Optional object to hold the result, can be passed in to avoid allocating a
-     * new PointF object.
-     */
-    @JvmOverloads
-    fun pointOnCurve(t: Float, result: PointF = PointF()): PointF {
-        val u = 1 - t
-        result.x = anchor0X * (u * u * u) + control0X * (3 * t * u * u) +
-            control1X * (3 * t * t * u) + anchor1X * (t * t * t)
-        result.y = anchor0Y * (u * u * u) + control0Y * (3 * t * u * u) +
-            control1Y * (3 * t * t * u) + anchor1Y * (t * t * t)
-        return result
-    }
-
-    /**
-     * Returns two Cubics, created by splitting this curve at the given
-     * distance of [t] between the original starting and ending anchor points.
-     */
-    // TODO: cartesian optimization?
-    fun split(t: Float): Pair<Cubic, Cubic> {
-        val u = 1 - t
-        val pointOnCurve = pointOnCurve(t)
-        return Cubic(
-            anchor0X, anchor0Y,
-            anchor0X * u + control0X * t, anchor0Y * u + control0Y * t,
-            anchor0X * (u * u) + control0X * (2 * u * t) + control1X * (t * t),
-            anchor0Y * (u * u) + control0Y * (2 * u * t) + control1Y * (t * t),
-            pointOnCurve.x, pointOnCurve.y
-        ) to Cubic(
-            // TODO: should calculate once and share the result
-            pointOnCurve.x, pointOnCurve.y,
-            control0X * (u * u) + control1X * (2 * u * t) + anchor1X * (t * t),
-            control0Y * (u * u) + control1Y * (2 * u * t) + anchor1Y * (t * t),
-            control1X * u + anchor1X * t, control1Y * u + anchor1Y * t,
-            anchor1X, anchor1Y
-        )
-    }
-
-    /**
-     * Utility function to reverse the control/anchor points for this curve.
-     */
-    fun reverse() = Cubic(anchor1X, anchor1Y, control1X, control1Y, control0X, control0Y,
-        anchor0X, anchor0Y)
-
-    /**
-     * Operator overload to enable adding Cubic objects together, like "c0 + c1"
-     */
-    operator fun plus(o: Cubic) = Cubic(
-        anchor0X + o.anchor0X, anchor0Y + o.anchor0Y,
-        control0X + o.control0X, control0Y + o.control0Y,
-        control1X + o.control1X, control1Y + o.control1Y,
-        anchor1X + o.anchor1X, anchor1Y + o.anchor1Y
-    )
-
-    /**
-     * Operator overload to enable multiplying Cubics by a scalar value x, like "c0 * x"
-     */
-    operator fun times(x: Float) = Cubic(
-        anchor0X * x, anchor0Y * x,
-        control0X * x, control0Y * x,
-        control1X * x, control1Y * x,
-        anchor1X * x, anchor1Y * x
-    )
-
-    /**
-     * Operator overload to enable multiplying Cubics by an Int scalar value x, like "c0 * x"
-     */
-    operator fun times(x: Int) = times(x.toFloat())
-
-    /**
-     * Operator overload to enable dividing Cubics by a scalar value x, like "c0 / x"
-     */
-    operator fun div(x: Float) = times(1f / x)
-
-    /**
-     * Operator overload to enable dividing Cubics by a scalar value x, like "c0 / x"
-     */
-    operator fun div(x: Int) = div(x.toFloat())
-
-    /**
-     * This function transforms this curve (its anchor and control points) with the given
-     * Matrix.
-     *
-     * @param matrix The matrix used to transform the curve
-     * @param points Optional array of Floats used internally. Supplying this array of floats saves
-     * allocating the array internally when not provided. Must have size equal to or larger than 8.
-     * @throws IllegalArgumentException if [points] is provided but is not large enough to
-     * hold 8 values.
-     */
-    @JvmOverloads
-    fun transform(matrix: Matrix, points: FloatArray = FloatArray(8)) {
-        if (points.size < 8) {
-            throw IllegalArgumentException("points array must be of size >= 8")
-        }
-        points[0] = anchor0X
-        points[1] = anchor0Y
-        points[2] = control0X
-        points[3] = control0Y
-        points[4] = control1X
-        points[5] = control1Y
-        points[6] = anchor1X
-        points[7] = anchor1Y
-        matrix.mapPoints(points)
-        anchor0X = points[0]
-        anchor0Y = points[1]
-        control0X = points[2]
-        control0Y = points[3]
-        control1X = points[4]
-        control1Y = points[5]
-        anchor1X = points[6]
-        anchor1Y = points[7]
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (javaClass != other?.javaClass) return false
-
-        other as Cubic
-
-        if (anchor0X != other.anchor0X) return false
-        if (anchor0Y != other.anchor0Y) return false
-        if (control0X != other.control0X) return false
-        if (control0Y != other.control0Y) return false
-        if (control1X != other.control1X) return false
-        if (control1Y != other.control1Y) return false
-        if (anchor1X != other.anchor1X) return false
-        if (anchor1Y != other.anchor1Y) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        var result = anchor0X.hashCode()
-        result = 31 * result + anchor0Y.hashCode()
-        result = 31 * result + control0X.hashCode()
-        result = 31 * result + control0Y.hashCode()
-        result = 31 * result + control1X.hashCode()
-        result = 31 * result + control1Y.hashCode()
-        result = 31 * result + anchor1X.hashCode()
-        result = 31 * result + anchor1Y.hashCode()
-        return result
-    }
-
-    companion object {
-        /**
-         * Generates a bezier curve that is a straight line between the given anchor points.
-         * The control points lie 1/3 of the distance from their respective anchor points.
-         */
-        @JvmStatic
-        fun straightLine(x0: Float, y0: Float, x1: Float, y1: Float): Cubic {
-            return Cubic(
-                x0, y0,
-                interpolate(x0, x1, 1f / 3f),
-                interpolate(y0, y1, 1f / 3f),
-                interpolate(x0, x1, 2f / 3f),
-                interpolate(y0, y1, 2f / 3f),
-                x1, y1
-            )
-        }
-
-        // TODO: consider a more general function (maybe in addition to this) that allows
-        // caller to get a list of curves surpassing 180 degrees
-        /**
-         * Generates a bezier curve that approximates a circular arc, with p0 and p1 as
-         * the starting and ending anchor points. The curve generated is the smallest of
-         * the two possible arcs around the entire 360-degree circle. Arcs of greater than 180
-         * degrees should use more than one arc together. Note that p0 and p1 should be
-         * equidistant from the center.
-         */
-        @JvmStatic
-        fun circularArc(
-            centerX: Float,
-            centerY: Float,
-            x0: Float,
-            y0: Float,
-            x1: Float,
-            y1: Float
-        ): Cubic {
-            val p0d = directionVector(x0 - centerX, y0 - centerY)
-            val p1d = directionVector(x1 - centerX, y1 - centerY)
-            val rotatedP0 = p0d.rotate90()
-            val rotatedP1 = p1d.rotate90()
-            val clockwise = rotatedP0.dotProduct(x1 - centerX, y1 - centerY) >= 0
-            val cosa = p0d.dotProduct(p1d)
-            if (cosa > 0.999f) /* p0 ~= p1 */ return straightLine(x0, y0, x1, y1)
-            val k = distance(x0 - centerX, y0 - centerY) * 4f / 3f *
-                (sqrt(2 * (1 - cosa)) - sqrt(1 - cosa * cosa)) / (1 - cosa) *
-                if (clockwise) 1f else -1f
-            return Cubic(
-                x0, y0, x0 + rotatedP0.x * k, y0 + rotatedP0.y * k,
-                x1 - rotatedP1.x * k, y1 - rotatedP1.y * k, x1, y1
-            )
-        }
-
-        /**
-         * Creates and returns a new Cubic which is a linear interpolation between
-         * [start] AND [end]. This can be used, for example, in animations to smoothly animate a
-         * curve from one location and size to another.
-         */
-        @JvmStatic
-        fun interpolate(start: Cubic, end: Cubic, t: Float): Cubic {
-            return (Cubic(
-                interpolate(start.anchor0X, end.anchor0X, t),
-                interpolate(start.anchor0Y, end.anchor0Y, t),
-                interpolate(start.control0X, end.control0X, t),
-                interpolate(start.control0Y, end.control0Y, t),
-                interpolate(start.control1X, end.control1X, t),
-                interpolate(start.control1Y, end.control1Y, t),
-                interpolate(start.anchor1X, end.anchor1X, t),
-                interpolate(start.anchor1Y, end.anchor1Y, t),
-            ))
-        }
-    }
-}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CubicShape.kt b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CubicShape.kt
deleted file mode 100644
index 84d5007..0000000
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/CubicShape.kt
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Canvas
-import android.graphics.Matrix
-import android.graphics.Paint
-import android.graphics.Path
-import android.graphics.RectF
-
-/**
- * This shape is defined by the list of [Cubic] curves with which it is created.
- * The list is contiguous. That is, a path based on this list
- * starts at the first anchor point of the first cubic, with each new cubic starting
- * at the end of each current cubic (i.e., the second anchor point of each cubic
- * is the same as the first anchor point of the next cubic). The final
- * cubic ends at the first anchor point of the initial cubic.
- */
-class CubicShape internal constructor() {
-
-    /**
-     * Constructs a [CubicShape] with the given list of [Cubic]s. The list is copied
-     * internally to ensure immutability of this shape.
-     * @throws IllegalArgumentException The last point of each cubic must match the
-     * first point of the next cubic (with the final cubic's last point matching
-     * the first point of the first cubic in the list).
-     */
-    constructor(cubics: List<Cubic>) : this() {
-        val copy = mutableListOf<Cubic>()
-        var prevCubic = cubics[cubics.size - 1]
-        for (cubic in cubics) {
-            if (cubic.anchor0X != prevCubic.anchor1X || cubic.anchor0Y != prevCubic.anchor1Y) {
-                throw IllegalArgumentException("CubicShapes must be contiguous, with the anchor " +
-                        "points of all curves matching the anchor points of the preceding and " +
-                        "succeeding cubics")
-            }
-            prevCubic = cubic
-            copy.add(Cubic(cubic))
-        }
-        updateCubics(copy)
-    }
-
-    constructor(sourceShape: CubicShape) : this(sourceShape.cubics)
-
-    /**
-     * The ordered list of cubic curves that define this shape.
-     */
-    lateinit var cubics: List<Cubic>
-        private set
-
-    /**
-     * The bounds of a shape are a simple min/max bounding box of the points in all of
-     * the [Cubic] objects. Note that this is not the same as the bounds of the resulting
-     * shape, but is a reasonable (and cheap) way to estimate the bounds. These bounds
-     * can be used to, for example, determine the size to scale the object when drawing it.
-     */
-    var bounds: RectF = RectF()
-        internal set
-
-    /**
-     * This path object is used for drawing the shape. Callers can retrieve a copy of it with
-     * the [toPath] function. The path is updated automatically whenever the shape's
-     * [cubics] are updated.
-     */
-    private val path: Path = Path()
-
-    /**
-     * Transforms (scales, rotates, and translates) the shape by the given matrix.
-     * Note that this operation alters the points in the shape directly; the original
-     * points are not retained, nor is the matrix itself. Thus calling this function
-     * twice with the same matrix will composite the effect. For example, a matrix which
-     * scales by 2 will scale the shape by 2. Calling transform twice with that matrix
-     * will have the effect os scaling the shape size by 4.
-     *
-     * @param matrix The matrix used to transform the curve
-     * @param points Optional array of Floats used internally. Supplying this array of floats saves
-     * allocating the array internally when not provided. Must have size equal to or larger than 8.
-     * @throws IllegalArgumentException if [points] is provided but is not large enough to
-     * hold 8 values.
-     */
-    @JvmOverloads
-    fun transform(matrix: Matrix, points: FloatArray = FloatArray(8)) {
-        if (points.size < 8) {
-            throw IllegalArgumentException("points array must be of size >= 8")
-        }
-        for (cubic in cubics) {
-            cubic.transform(matrix, points)
-        }
-        updateCubics(cubics)
-    }
-
-    /**
-     * This is called by Polygon's constructor. It should not generally be called later;
-     * CubicShape should be immutable.
-     */
-    internal fun updateCubics(cubics: List<Cubic>) {
-        this.cubics = cubics
-        calculateBounds()
-        updatePath()
-    }
-
-    /**
-     * A CubicShape is rendered as a [Path]. A copy of the underlying [Path] object can be
-     * retrieved for use outside of this class. Note that this function returns a copy of
-     * the internal [Path] to maintain immutability, thus there is some overhead in retrieving
-     * and using the path with this function.
-     */
-    fun toPath(): Path {
-        return Path(path)
-    }
-
-    /**
-     * Internal function to update the Path object whenever the cubics are updated.
-     * The Path should not be needed until drawing (or being retrieved via [toPath]),
-     * but might as well update it immediately since the cubics should not change
-     * in the meantime.
-     */
-    private fun updatePath() {
-        path.rewind()
-        if (cubics.isNotEmpty()) {
-            path.moveTo(cubics[0].anchor0X, cubics[0].anchor0Y)
-            for (bezier in cubics) {
-                path.cubicTo(
-                    bezier.control0X, bezier.control0Y,
-                    bezier.control1X, bezier.control1Y,
-                    bezier.anchor1X, bezier.anchor1Y
-                )
-            }
-        }
-        path.close()
-    }
-
-    internal fun draw(canvas: Canvas, paint: Paint) {
-        canvas.drawPath(path, paint)
-    }
-
-    /**
-     * Calculates estimated bounds of the object, using the min/max bounding box of
-     * all points in the cubics that make up the shape.
-     */
-    private fun calculateBounds() {
-        var minX = Float.MAX_VALUE
-        var minY = Float.MAX_VALUE
-        var maxX = Float.MIN_VALUE
-        var maxY = Float.MIN_VALUE
-        for (bezier in cubics) {
-            if (bezier.anchor0X < minX) minX = bezier.anchor0X
-            if (bezier.anchor0Y < minY) minY = bezier.anchor0Y
-            if (bezier.anchor0X > maxX) maxX = bezier.anchor0X
-            if (bezier.anchor0Y > maxY) maxY = bezier.anchor0Y
-
-            if (bezier.control0X < minX) minX = bezier.control0X
-            if (bezier.control0Y < minY) minY = bezier.control0Y
-            if (bezier.control0X > maxX) maxX = bezier.control0X
-            if (bezier.control0Y > maxY) maxY = bezier.control0Y
-
-            if (bezier.control1X < minX) minX = bezier.control1X
-            if (bezier.control1Y < minY) minY = bezier.control1Y
-            if (bezier.control1X > maxX) maxX = bezier.control1X
-            if (bezier.control1Y > maxY) maxY = bezier.control1Y
-            // No need to use x3/y3, since it is already taken into account in the next
-            // curve's x0/y0 point.
-        }
-        bounds.set(minX, minY, maxX, maxY)
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (javaClass != other?.javaClass) return false
-
-        return cubics == (other as CubicShape).cubics
-    }
-
-    override fun hashCode(): Int {
-        return cubics.hashCode()
-    }
-}
-
-/**
- * Extension function which draws the given [CubicShape] object into this [Canvas]. Rendering
- * occurs by drawing the underlying path for the object; callers can optionally retrieve the
- * path and draw it directly via [CubicShape.toPath] (though that function copies the underlying
- * path. This extension function avoids that overhead when rendering).
- *
- * @param shape The object to be drawn
- * @param paint The attributes
- */
-fun Canvas.drawCubicShape(shape: CubicShape, paint: Paint) {
-    shape.draw(this, paint)
-}
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Morph.kt b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Morph.kt
deleted file mode 100644
index 54452d9..0000000
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Morph.kt
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Canvas
-import android.graphics.Matrix
-import android.graphics.Paint
-import android.graphics.Path
-import android.graphics.PointF
-import android.graphics.RectF
-import kotlin.math.min
-
-/**
- * This class is used to animate between start and end polygons objects.
- *
- * Morphing between arbitrary objects can be problematic because it can be difficult to
- * determine how the points of a given shape map to the points of some other shape.
- * [Morph] simplifies the problem by only operating on [RoundedPolygon] objects, which
- * are known to have similar, contiguous structures. For one thing, the shape of a polygon
- * is contiguous from start to end (compared to an arbitrary [Path] object, which could have
- * one or more `moveTo` operations in the shape). Also, all edges of a polygon shape are
- * represented by [Cubic] objects, thus the start and end shapes use similar operations. Two
- * Polygon shapes then only differ in the quantity and placement of their curves.
- * The morph works by determining how to map the curves of the two shapes together (based on
- * proximity and other information, such as distance to polygon vertices and concavity),
- * and splitting curves when the shapes do not have the same number of curves or when the
- * curve placement within the shapes is very different.
- */
-class Morph(
-    start: RoundedPolygon,
-    end: RoundedPolygon
-) {
-    // morphMatch is the structure which holds the actual shape being morphed. It contains
-    // all cubics necessary to represent the start and end shapes (the original cubics in the
-    // shapes may be cut to align the start/end shapes)
-    private var morphMatch = match(start, end)
-
-    // path is used to draw the object
-    // It is cached to avoid recalculating it if the progress has not changed
-    private val path = Path()
-
-    // last value for which the cached path was constructed. We cache this and the path
-    // to avoid recreating the path for the same progress value
-    private var currentPathProgress: Float = Float.MIN_VALUE
-
-    /**
-     * The bounds of the morph object are estimated by control and anchor points of all cubic curves
-     * representing the shape.
-     */
-    val bounds = RectF()
-
-    init {
-        calculateBounds(bounds)
-    }
-
-    /**
-     * Rough bounds of the object, based on the min/max bounds of all cubics points in morphMatch
-     */
-    private fun calculateBounds(bounds: RectF) {
-        // TODO: Maybe using just the anchors (p0 and p3) is sufficient and more correct than
-        // also using the control points (p1 and p2)
-        var minX = Float.MAX_VALUE
-        var minY = Float.MAX_VALUE
-        var maxX = Float.MIN_VALUE
-        var maxY = Float.MIN_VALUE
-        for (pair in morphMatch) {
-            if (pair.first.anchor0X < minX) minX = pair.first.anchor0X
-            if (pair.first.anchor0Y < minY) minY = pair.first.anchor0Y
-            if (pair.first.anchor0X > maxX) maxX = pair.first.anchor0X
-            if (pair.first.anchor0Y > maxY) maxY = pair.first.anchor0Y
-
-            if (pair.second.anchor0X < minX) minX = pair.second.anchor0X
-            if (pair.second.anchor0Y < minY) minY = pair.second.anchor0Y
-            if (pair.second.anchor0X > maxX) maxX = pair.second.anchor0X
-            if (pair.second.anchor0Y > maxY) maxY = pair.second.anchor0Y
-
-            if (pair.first.control0X < minX) minX = pair.first.control0X
-            if (pair.first.control0Y < minY) minY = pair.first.control0Y
-            if (pair.first.control0X > maxX) maxX = pair.first.control0X
-            if (pair.first.control0Y > maxY) maxY = pair.first.control0Y
-
-            if (pair.second.control0X < minX) minX = pair.second.control0X
-            if (pair.second.control0Y < minY) minY = pair.second.control0Y
-            if (pair.second.control0X > maxX) maxX = pair.second.control0X
-            if (pair.second.control0Y > maxY) maxY = pair.second.control0Y
-
-            if (pair.first.control1X < minX) minX = pair.first.control1X
-            if (pair.first.control1Y < minY) minY = pair.first.control1Y
-            if (pair.first.control1X > maxX) maxX = pair.first.control1X
-            if (pair.first.control1Y > maxY) maxY = pair.first.control1Y
-
-            if (pair.second.control1X < minX) minX = pair.second.control1X
-            if (pair.second.control1Y < minY) minY = pair.second.control1Y
-            if (pair.second.control1X > maxX) maxX = pair.second.control1X
-            if (pair.second.control1Y > maxY) maxY = pair.second.control1Y
-            // Skip x3/y3 since every last point is the next curve's first point
-        }
-        bounds.set(minX, minY, maxX, maxY)
-    }
-
-    /**
-     * This function updates the [path] object which holds the rendering information for the
-     * morph shape, using the current [progress] property for the morph.
-     */
-    private fun getPath(progress: Float): Path {
-        // Noop if we have already
-        if (progress == currentPathProgress) return path
-
-        // In a future release, Path interpolation may be possible through the Path API
-        // itself. Until then, we have to rewind and repopulate with the new/interpolated
-        // values
-        path.rewind()
-
-        // If the list is not empty, do an initial moveTo using the first element of the match.
-        morphMatch.firstOrNull()?. let { first ->
-            path.moveTo(
-                interpolate(first.first.anchor0X, first.second.anchor0X, progress),
-                interpolate(first.first.anchor0Y, first.second.anchor0Y, progress)
-            )
-        }
-
-        // And one cubicTo for each element, including the first.
-        for (i in 0..morphMatch.lastIndex) {
-            val element = morphMatch[i]
-            path.cubicTo(
-                interpolate(element.first.control0X, element.second.control0X, progress),
-                interpolate(element.first.control0Y, element.second.control0Y, progress),
-                interpolate(element.first.control1X, element.second.control1X, progress),
-                interpolate(element.first.control1Y, element.second.control1Y, progress),
-                interpolate(element.first.anchor1X, element.second.anchor1X, progress),
-                interpolate(element.first.anchor1Y, element.second.anchor1Y, progress),
-            )
-        }
-        path.close()
-        currentPathProgress = progress
-        return path
-    }
-
-    /**
-     * Transforms (scales, rotates, and translates) the shape by the given matrix.
-     * Note that this operation alters the points in the shape directly; the original
-     * points are not retained, nor is the matrix itself. Thus calling this function
-     * twice with the same matrix will composite the effect. For example, a matrix which
-     * scales by 2 will scale the shape by 2. Calling transform twice with that matrix
-     * will have the effect of scaling the original shape by 4.
-     */
-    fun transform(matrix: Matrix) {
-        for (pair in morphMatch) {
-            pair.first.transform(matrix)
-            pair.second.transform(matrix)
-        }
-        calculateBounds(bounds)
-        // Reset cached progress value to force recalculation due to transform change
-        currentPathProgress = Float.MIN_VALUE
-    }
-
-    /**
-     * Morph is rendered as a [Path]. A copy of the underlying [Path] object can be
-     * retrieved for use outside of this class. Note that this function returns a copy of
-     * the internal [Path] to maintain immutability, thus there is some overhead in retrieving
-     * the path with this function.
-     *
-     * @param progress a value from 0 to 1 that determines the morph's current
-     * shape, between the start and end shapes provided at construction time. A value of 0 results
-     * in the start shape, a value of 1 results in the end shape, and any value in between
-     * results in a shape which is a linear interpolation between those two shapes.
-     * The range is generally [0..1] and values outside could result in undefined shapes, but
-     * values close to (but outside) the range can be used to get an exaggerated effect
-     * (e.g., for a bounce or overshoot animation).
-     * @param path optional Path object to be used to hold the resulting Path data. If provided,
-     * that Path's data will be replaced with the internal Path data for the Morph. If none
-     * is provided, new Path object will be created and used instead.
-     */
-    @JvmOverloads
-    fun asPath(progress: Float, path: Path = Path()): Path {
-        path.set(getPath(progress))
-        return path
-    }
-
-    /**
-     * Returns a representation of the morph object at a given [progress] value as a list of Cubics.
-     * Note that this function causes a new list to be created and populated, so there is some
-     * overhead.
-     *
-     * @param progress a value from 0 to 1 that determines the morph's current
-     * shape, between the start and end shapes provided at construction time. A value of 0 results
-     * in the start shape, a value of 1 results in the end shape, and any value in between
-     * results in a shape which is a linear interpolation between those two shapes.
-     * The range is generally [0..1] and values outside could result in undefined shapes, but
-     * values close to (but outside) the range can be used to get an exaggerated effect
-     * (e.g., for a bounce or overshoot animation).
-     */
-    fun asCubics(progress: Float) =
-        mutableListOf<Cubic>().apply {
-            clear()
-            for (pair in morphMatch) {
-                add(Cubic.interpolate(pair.first, pair.second, progress))
-            }
-        }
-
-    internal companion object {
-        /**
-         * [match], called at Morph construction time, creates the structure used to animate between
-         * the start and end shapes. The technique is to match geometry (curves) between the shapes
-         * when and where possible, and to create new/placeholder curves when necessary (when
-         * one of the shapes has more curves than the other). The result is a list of pairs of
-         * Cubic curves. Those curves are the matched pairs: the first of each pair holds the
-         * geometry of the start shape, the second holds the geometry for the end shape.
-         * Changing the progress of a Morph object simply interpolates between all pairs of
-         * curves for the morph shape.
-         *
-         * Curves on both shapes are matched by running the [Measurer] to determine where
-         * the points are in each shape (proportionally, along the outline), and then running
-         * [featureMapper] which decides how to map (match) all of the curves with each other.
-         */
-        @JvmStatic
-        internal fun match(
-            p1: RoundedPolygon,
-            p2: RoundedPolygon
-        ): List<Pair<Cubic, Cubic>> {
-            if (DEBUG) {
-                repeat(2) { polyIndex ->
-                    debugLog(LOG_TAG) {
-                        listOf("Initial start:\n", "Initial end:\n")[polyIndex] +
-                            listOf(p1, p2)[polyIndex].features.joinToString("\n") { feature ->
-                                "${feature.javaClass.name.split("$").last()} - " +
-                                    ((feature as? RoundedPolygon.Corner)?.convex?.let {
-                                        if (it) "Convex - " else "Concave - " } ?: "") +
-                                    feature.cubics.joinToString("|")
-                            }
-                    }
-                }
-            }
-
-            // Measure polygons, returns lists of measured cubics for each polygon, which
-            // we then use to match start/end curves
-            val measuredPolygon1 = MeasuredPolygon.measurePolygon(
-                AngleMeasurer(p1.centerX, p1.centerY), p1)
-            val measuredPolygon2 = MeasuredPolygon.measurePolygon(
-                AngleMeasurer(p2.centerX, p2.centerY), p2)
-
-            // features1 and 2 will contain the list of corners (just the inner circular curve)
-            // along with the progress at the middle of those corners. These measurement values
-            // are then used to compare and match between the two polygons
-            val features1 = measuredPolygon1.features
-            val features2 = measuredPolygon2.features
-
-            // Map features: doubleMapper is the result of mapping the features in each shape to the
-            // closest feature in the other shape.
-            // Given a progress in one of the shapes it can be used to find the corresponding
-            // progress in the other shape (in both directions)
-            val doubleMapper = featureMapper(features1, features2)
-
-            // cut point on poly2 is the mapping of the 0 point on poly1
-            val polygon2CutPoint = doubleMapper.map(0f)
-            debugLog(LOG_TAG) { "polygon2CutPoint = $polygon2CutPoint" }
-
-            // Cut and rotate.
-            // Polygons start at progress 0, and the featureMapper has decided that we want to match
-            // progress 0 in the first polygon to `polygon2CutPoint` on the second polygon.
-            // So we need to cut the second polygon there and "rotate it", so as we walk through
-            // both polygons we can find the matching.
-            // The resulting bs1/2 are MeasuredPolygons, whose MeasuredCubics start from
-            // outlineProgress=0 and increasing until outlineProgress=1
-            val bs1 = measuredPolygon1
-            val bs2 = measuredPolygon2.cutAndShift(polygon2CutPoint)
-
-            if (DEBUG) {
-                (0 until bs1.size).forEach { index ->
-                    debugLog(LOG_TAG) { "start $index: ${bs1.getOrNull(index)}" }
-                }
-                (0 until bs2.size).forEach { index ->
-                    debugLog(LOG_TAG) { "End $index: ${bs2.getOrNull(index)}" }
-                }
-            }
-
-            // Match
-            // Now we can compare the two lists of measured cubics and create a list of pairs
-            // of cubics [ret], which are the start/end curves that represent the Morph object
-            // and the start and end shapes, and which can be interpolated to animate the
-            // between those shapes.
-            val ret = mutableListOf<Pair<Cubic, Cubic>>()
-            // i1/i2 are the indices of the current cubic on the start (1) and end (2) shapes
-            var i1 = 0
-            var i2 = 0
-            // b1, b2 are the current measured cubic for each polygon
-            var b1 = bs1.getOrNull(i1++)
-            var b2 = bs2.getOrNull(i2++)
-            // Iterate until all curves are accounted for and matched
-            while (b1 != null && b2 != null) {
-                // Progresses are in shape1's perspective
-                // b1a, b2a are ending progress values of current measured cubics in [0,1] range
-                val b1a = if (i1 == bs1.size) 1f else b1.endOutlineProgress
-                val b2a = if (i2 == bs2.size) 1f else doubleMapper.mapBack(
-                    positiveModulo(b2.endOutlineProgress + polygon2CutPoint, 1f)
-                )
-                val minb = min(b1a, b2a)
-                debugLog(LOG_TAG) { "$b1a $b2a | $minb" }
-                // minb is the progress at which the curve that ends first ends.
-                // If both curves ends roughly there, no cutting is needed, we have a match.
-                // If one curve extends beyond, we need to cut it.
-                val (seg1, newb1) = if (b1a > minb + AngleEpsilon) {
-                    debugLog(LOG_TAG) { "Cut 1" }
-                    b1.cutAtProgress(minb)
-                } else {
-                    b1 to bs1.getOrNull(i1++)
-                }
-                val (seg2, newb2) = if (b2a > minb + AngleEpsilon) {
-                    debugLog(LOG_TAG) { "Cut 2" }
-                    b2.cutAtProgress(positiveModulo(doubleMapper.map(minb) - polygon2CutPoint, 1f))
-                } else {
-                    b2 to bs2.getOrNull(i2++)
-                }
-                debugLog(LOG_TAG) { "Match: $seg1 -> $seg2" }
-                ret.add(Cubic(seg1.cubic) to Cubic(seg2.cubic))
-                b1 = newb1
-                b2 = newb2
-            }
-            require(b1 == null && b2 == null)
-
-            if (DEBUG) {
-                // Export as SVG path
-                val showPoint: (PointF) -> String = {
-                    "%.3f %.3f".format(it.x * 100, it.y * 100)
-                }
-                repeat(2) { listIx ->
-                    val points = ret.map { if (listIx == 0) it.first else it.second }
-                    debugLog(LOG_TAG) {
-                        "M " + showPoint(PointF(points.first().anchor0X,
-                            points.first().anchor0Y)) + " " +
-                            points.joinToString(" ") {
-                                "C " + showPoint(PointF(it.control0X, it.control0Y)) + ", " +
-                                    showPoint(PointF(it.control1X, it.control1Y)) + ", " +
-                                    showPoint(PointF(it.anchor1X, it.anchor1Y))
-                            } + " Z"
-                    }
-                }
-            }
-            return ret
-        }
-    }
-
-    /**
-     * Draws the Morph object. This is called by the public extension function
-     * [Canvas.drawMorph]. By default, it simply calls [Canvas.drawPath].
-     */
-    internal fun draw(canvas: Canvas, paint: Paint, progress: Float) {
-        val path = getPath(progress)
-        canvas.drawPath(path, paint)
-    }
-}
-
-/**
- * Extension function which draws the given [Morph] object into this [Canvas]. Rendering
- * occurs by drawing the underlying path for the object; callers can optionally retrieve the
- * path and draw it directly via [Morph.asPath] (though that function copies the underlying
- * path. This extension function avoids that overhead when rendering).
- *
- * @param morph The object to be drawn
- * @param paint The drawing attributes to be used when rendering the morph object
- * @param progress a value from 0 to 1 that determines the morph's current
- * shape, between the start and end shapes provided at construction time. A value of 0 results
- * in the start shape, a value of 1 results in the end shape, and any value in between
- * results in a shape which is a linear interpolation between those two shapes.
- * The range is generally [0..1] and values outside could result in undefined shapes, but
- * values close to (but outside) the range can be used to get an exaggerated effect
- * (e.g., for a bounce or overshoot animation).
- */
-fun Canvas.drawMorph(morph: Morph, paint: Paint, progress: Float = 0f) {
-    morph.draw(this, paint, progress)
-}
-
-private val LOG_TAG = "Morph"
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt
deleted file mode 100644
index 18af8d2..0000000
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * 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.shapes
-
-import android.graphics.Canvas
-import android.graphics.Matrix
-import android.graphics.Paint
-import android.graphics.Path
-import android.graphics.PointF
-import android.graphics.RectF
-import androidx.annotation.IntRange
-import androidx.core.graphics.div
-import androidx.core.graphics.minus
-import androidx.core.graphics.plus
-import androidx.core.graphics.times
-import kotlin.math.abs
-import kotlin.math.min
-import kotlin.math.sqrt
-
-/**
- * The RoundedPolygon class allows simple construction of polygonal shapes with optional rounding
- * at the vertices. Polygons can be constructed with either the number of vertices
- * desired or an ordered list of vertices.
- */
-class RoundedPolygon {
-
-    /**
-     * A RoundedPolygon is essentially a CubicShape, which handles all of the functionality around
-     * cubic Beziers that are used to create and render the geometry. But subclassing from
-     * CubicShape causes a bit of naming confusion, since an actual polygon, in geometry,
-     * is a shape with straight edges and hard corners, whereas CubicShape obviously allows for
-     * more general, curved shapes. Therefore, we delegate to CubicShape as an internal
-     * implementation detail, and RoundedPolygon has no superclass.
-     */
-    private val cubicShape = CubicShape()
-
-    /**
-     * Features are the corners (rounded or not) and edges of a polygon. Retaining the list of
-     * per-vertex corner (and the edges between them) allows manipulation of a RoundedPolygon with
-     * more context for the structure of that polygon, rather than just the list of cubic beziers
-     * which are calculated for rendering purposes.
-     */
-    internal lateinit var features: List<Feature>
-        private set
-
-    // TODO center point should not be mutable
-    /**
-     * The X coordinated of the center of this polygon.
-     * The center is determined at construction time, either calculated
-     * to be an average of all of the vertices of the polygon, or passed in as a parameter. This
-     * center may be used in later operations, to help determine (for example) the relative
-     * placement of points along the perimeter of the polygon.
-     */
-    var centerX: Float
-        private set
-
-    /**
-     * The Y coordinated of the center of this polygon.
-     * The center is determined at construction time, either calculated
-     * to be an average of all of the vertices of the polygon, or passed in as a parameter. This
-     * center may be used in later operations, to help determine (for example) the relative
-     * placement of points along the perimeter of the polygon.
-     */
-    var centerY: Float
-        private set
-
-    /**
-     * The bounds of a shape are a simple min/max bounding box of the points in all of
-     * the [Cubic] objects. Note that this is not the same as the bounds of the resulting
-     * shape, but is a reasonable (and cheap) way to estimate the bounds. These bounds
-     * can be used to, for example, determine the size to scale the object when drawing it.
-     */
-    var bounds: RectF by cubicShape::bounds
-
-    companion object {}
-
-    /**
-     * Constructs a RoundedPolygon object from a given list of vertices, with optional
-     * corner-rounding parameters for all corners or per-corner.
-     *
-     * A RoundedPolygon without any rounding parameters is equivalent to a [RoundedPolygon]
-     * constructed with the same [vertices] and ([centerX], [centerY]) values.
-     *
-     * @param vertices The list of vertices in this polygon. This should be an ordered list
-     * (with the outline of the shape going from each vertex to the next in order of this
-     * list), otherwise the results will be undefined.
-     * @param rounding The [CornerRounding] properties of every vertex. If some vertices should
-     * have different rounding properties, then use [perVertexRounding] instead. The default
-     * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
-     * themselves in the final shape and not curves rounded around the vertices.
-     * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
-     * parameter is not null, then it must have the same size as [vertices]. If this parameter
-     * is null, then the polygon will use the [rounding] parameter for every vertex instead. The
-     * default value is null.
-     * @param centerX The X coordinate of an optionally declared center of the polygon. If either
-     * [centerX] or [centerY] is not supplied, both will be calculated based on the supplied
-     * vertices.
-     * @param centerY The Y coordinate of an optionally declared center of the polygon. If either
-     * [centerX] or [centerY] is not supplied, both will be calculated based on the supplied
-     * vertices.
-     *
-     * @throws IllegalArgumentException If [perVertexRounding] is not null, it must be
-     * the same size as the [vertices] list.
-     * @throws IllegalArgumentException [vertices] must have a size of at least three.
-     */
-    constructor(
-        vertices: FloatArray,
-        rounding: CornerRounding = CornerRounding.Unrounded,
-        perVertexRounding: List<CornerRounding>? = null,
-        centerX: Float = Float.MIN_VALUE,
-        centerY: Float = Float.MIN_VALUE
-    ) {
-        if (centerX == Float.MIN_VALUE || centerY == Float.MIN_VALUE) {
-            val center = PointF()
-            calculateCenter(vertices, center)
-            this.centerX = center.x
-            this.centerY = center.y
-        } else {
-            this.centerX = centerX
-            this.centerY = centerY
-        }
-        setupPolygon(vertices, rounding, perVertexRounding)
-    }
-
-    /**
-     * This constructor takes the number of vertices in the resulting polygon. These vertices are
-     * positioned on a virtual circle around a given center with each vertex positioned [radius]
-     * distance from that center, equally spaced (with equal angles between them). If no radius
-     * is supplied, the shape will be created with a default radius of 1, resulting in a shape
-     * whose vertices lie on a unit circle, with width/height of 2. That default polygon will
-     * probably need to be rescaled using [transform] into the appropriate size for the UI in
-     * which it will be drawn.
-     *
-     * The [rounding] and [perVertexRounding] parameters are optional. If not supplied, the result
-     * will be a regular polygon with straight edges and unrounded corners.
-     *
-     * @param numVertices The number of vertices in this polygon.
-     * @param radius The radius of the polygon, in pixels. This radius determines the
-     * initial size of the object, but it can be transformed later by setting
-     * a matrix on it.
-     * @param centerX The X coordinate of the center of the polygon, around which all vertices
-     * will be placed. The default center is at (0,0).
-     * @param centerY The Y coordinate of the center of the polygon, around which all vertices
-     * will be placed. The default center is at (0,0).
-     * @param rounding The [CornerRounding] properties of every vertex. If some vertices should
-     * have different rounding properties, then use [perVertexRounding] instead. The default
-     * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
-     * themselves in the final shape and not curves rounded around the vertices.
-     * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
-     * parameter is not null, then it must have [numVertices] elements. If this parameter
-     * is null, then the polygon will use the [rounding] parameter for every vertex instead. The
-     * default value is null.
-     *
-     * @throws IllegalArgumentException If [perVertexRounding] is not null, it must have
-     * [numVertices] elements.
-     * @throws IllegalArgumentException [numVertices] must be at least 3.
-     */
-    constructor(
-        @IntRange(from = 3) numVertices: Int,
-        radius: Float = 1f,
-        centerX: Float = 0f,
-        centerY: Float = 0f,
-        rounding: CornerRounding = CornerRounding.Unrounded,
-        perVertexRounding: List<CornerRounding>? = null
-    ) : this(
-        verticesFromNumVerts(numVertices, radius, centerX, centerY),
-        rounding = rounding,
-        perVertexRounding = perVertexRounding,
-        centerX = centerX,
-        centerY = centerY)
-
-    constructor(source: RoundedPolygon) {
-        val newCubics = mutableListOf<Cubic>()
-        for (cubic in source.cubicShape.cubics) {
-            newCubics.add(Cubic(cubic))
-        }
-        val tempFeatures = mutableListOf<Feature>()
-        for (feature in source.features) {
-            if (feature is Edge) {
-                tempFeatures.add(Edge(feature))
-            } else {
-                tempFeatures.add(Corner(feature as Corner))
-            }
-        }
-        features = tempFeatures
-        centerX = source.centerX
-        centerY = source.centerY
-        cubicShape.updateCubics(newCubics)
-    }
-
-    /**
-     * This function takes the vertices (either supplied or calculated, depending on the
-     * constructor called), plus [CornerRounding] parameters, and creates the actual
-     * [RoundedPolygon] shape, rounding around the vertices (or not) as specified. The result
-     * is a list of [Cubic] curves which represent the geometry of the final shape.
-     *
-     * @param vertices The list of vertices in this polygon. This should be an ordered list
-     * (with the outline of the shape going from each vertex to the next in order of this
-     * list), otherwise the results will be undefined.
-     * @param rounding The [CornerRounding] properties of every vertex. If some vertices should
-     * have different rounding properties, then use [perVertexRounding] instead. The default
-     * rounding value is [CornerRounding.Unrounded], meaning that the polygon will use the vertices
-     * themselves in the final shape and not curves rounded around the vertices.
-     * @param perVertexRounding The [CornerRounding] properties of every vertex. If this
-     * parameter is not null, then it must have the same size as [vertices]. If this parameter
-     * is null, then the polygon will use the [rounding] parameter for every vertex instead. The
-     * default value is null.
-     */
-    private fun setupPolygon(
-        vertices: FloatArray,
-        rounding: CornerRounding = CornerRounding.Unrounded,
-        perVertexRounding: List<CornerRounding>? = null
-    ) {
-        if (vertices.size < 6) {
-            throw IllegalArgumentException("Polygons must have at least 3 vertices")
-        }
-        if (perVertexRounding != null && perVertexRounding.size != vertices.size / 2) {
-            throw IllegalArgumentException("perVertexRounding list should be either null or " +
-                    "the same size as the number of vertices (2 * vertices.size)")
-        }
-        val cubics = mutableListOf<Cubic>()
-        val corners = mutableListOf<List<Cubic>>()
-        val n = vertices.size / 2
-        val roundedCorners = mutableListOf<RoundedCorner>()
-        for (i in 0 until n) {
-            val vtxRounding = perVertexRounding?.get(i) ?: rounding
-            val prevIndex = ((i + n - 1) % n) * 2
-            val nextIndex = ((i + 1) % n) * 2
-            roundedCorners.add(
-                RoundedCorner(
-                    PointF(vertices[prevIndex], vertices[prevIndex + 1]),
-                    PointF(vertices[i * 2], vertices[i * 2 + 1]),
-                    PointF(vertices[nextIndex], vertices[nextIndex + 1]),
-                    vtxRounding
-                )
-            )
-        }
-
-        // For each side, check if we have enough space to do the cuts needed, and if not split
-        // the available space, first for round cuts, then for smoothing if there is space left.
-        // Each element in this list is a pair, that represent how much we can do of the cut for
-        // the given side (side i goes from corner i to corner i+1), the elements of the pair are:
-        // first is how much we can use of expectedRoundCut, second how much of expectedCut
-        val cutAdjusts = (0 until n).map { ix ->
-            val expectedRoundCut = roundedCorners[ix].expectedRoundCut +
-                roundedCorners[(ix + 1) % n].expectedRoundCut
-            val expectedCut = roundedCorners[ix].expectedCut +
-                    roundedCorners[(ix + 1) % n].expectedCut
-            val vtxX = vertices[ix * 2]
-            val vtxY = vertices[ix * 2 + 1]
-            val nextVtxX = vertices[((ix + 1) % n) * 2]
-            val nextVtxY = vertices[((ix + 1) % n) * 2 + 1]
-            val sideSize = distance(vtxX - nextVtxX, vtxY - nextVtxY)
-
-            // Check expectedRoundCut first, and ensure we fulfill rounding needs first for
-            // both corners before using space for smoothing
-            if (expectedRoundCut > sideSize) {
-                // Not enough room for fully rounding, see how much we can actually do.
-                sideSize / expectedRoundCut to 0f
-            } else if (expectedCut > sideSize) {
-                // We can do full rounding, but not full smoothing.
-                1f to (sideSize - expectedRoundCut) / (expectedCut - expectedRoundCut)
-            } else {
-                // There is enough room for rounding & smoothing.
-                1f to 1f
-            }
-        }
-        // Create and store list of beziers for each [potentially] rounded corner
-        for (i in 0 until n) {
-            // allowedCuts[0] is for the side from the previous corner to this one,
-            // allowedCuts[1] is for the side from this corner to the next one.
-            val allowedCuts = (0..1).map { delta ->
-                val (roundCutRatio, cutRatio) = cutAdjusts[(i + n - 1 + delta) % n]
-                roundedCorners[i].expectedRoundCut * roundCutRatio +
-                    (roundedCorners[i].expectedCut - roundedCorners[i].expectedRoundCut) * cutRatio
-            }
-            corners.add(
-                roundedCorners[i].getCubics(
-                    allowedCut0 = allowedCuts[0],
-                    allowedCut1 = allowedCuts[1]
-                )
-            )
-        }
-        // Finally, store the calculated cubics. This includes all of the rounded corners
-        // from above, along with new cubics representing the edges between those corners.
-        val tempFeatures = mutableListOf<Feature>()
-        for (i in 0 until n) {
-            val cornerIndices = mutableListOf<Int>()
-            for (cubic in corners[i]) {
-                cornerIndices.add(cubics.size)
-                cubics.add(cubic)
-            }
-            // Determine whether corner at this vertex is concave or convex, based on the
-            // relationship of the prev->curr/curr->next vectors
-            // Note that these indices are for pairs of values (points), they need to be
-            // doubled to access the xy values in the vertices float array
-            val prevVtxIndex = (i + n - 1) % n
-            val nextVtxIndex = (i + 1) % n
-            val currVertex = PointF(vertices[i * 2], vertices[i * 2 + 1])
-            val prevVertex = PointF(vertices[prevVtxIndex * 2], vertices[prevVtxIndex * 2 + 1])
-            val nextVertex = PointF(vertices[nextVtxIndex * 2], vertices[nextVtxIndex * 2 + 1])
-            val convex = (currVertex - prevVertex).clockwise(nextVertex - currVertex)
-            tempFeatures.add(Corner(cornerIndices, currVertex, roundedCorners[i].center,
-                convex))
-            tempFeatures.add(Edge(listOf(cubics.size)))
-            cubics.add(Cubic.straightLine(corners[i].last().anchor1X, corners[i].last().anchor1Y,
-                corners[(i + 1) % n].first().anchor0X, corners[(i + 1) % n].first().anchor0Y))
-        }
-        features = tempFeatures
-        cubicShape.updateCubics(cubics)
-    }
-
-    /**
-     * Transforms (scales, rotates, and translates) the polygon by the given matrix.
-     * Note that this operation alters the points in the polygon directly; the original
-     * points are not retained, nor is the matrix itself. Thus calling this function
-     * twice with the same matrix will composite the effect. For example, a matrix which
-     * scales by 2 will scale the polygon by 2. Calling transform twice with that matrix
-     * will have the effect os scaling the shape size by 4.
-     *
-     * Note that [RoundedPolygon] objects created with default radius and center values will
-     * probably need to be scaled and repositioned using [transform] to be displayed correctly
-     * in the UI. Polygons are created by default on the unit circle around a center
-     * of (0, 0), so the resulting geometry has a bounding box width and height of 2x2; It should
-     * be resized to fit where it will be displayed appropriately.
-     *
-     * @param matrix The matrix used to transform the polygon
-     */
-    fun transform(matrix: Matrix) {
-        cubicShape.transform(matrix)
-        val point = scratchTransformPoint
-        point[0] = centerX
-        point[1] = centerY
-        matrix.mapPoints(point)
-        centerX = point[0]
-        centerY = point[1]
-        for (feature in features) {
-            feature.transform(matrix)
-        }
-    }
-
-    /**
-     * Internally, the Polygon is stored as a [CubicShape] object. This function returns a copy
-     * of that object.
-     */
-    fun toCubicShape(): CubicShape {
-        return CubicShape(cubicShape)
-    }
-
-    /**
-     * A Polygon is rendered as a [Path]. A copy of the underlying [Path] object can be
-     * retrieved for use outside of this class. Note that this function returns a copy of
-     * the internal [Path] to maintain immutability, thus there is some overhead in retrieving
-     * and using the path with this function.
-     */
-    fun toPath(): Path {
-        return cubicShape.toPath()
-    }
-
-    internal fun draw(canvas: Canvas, paint: Paint) {
-        cubicShape.draw(canvas, paint)
-    }
-
-    /**
-     * Calculates an estimated center position for the polygon, storing it in the [centerX]
-     * and [centerY] properties.
-     * This function should only be called if the center is not already calculated or provided.
-     * The Polygon constructor which takes `numVertices` calculates its own center, since it
-     * knows exactly where it is centered, at (0, 0).
-     *
-     * Note that this center will be transformed whenever the shape itself is transformed.
-     * Any transforms that occur before the center is calculated will be taken into account
-     * automatically since the center calculation is an average of the current location of
-     * all cubic anchor points.
-     */
-    private fun calculateCenter(vertices: FloatArray, result: PointF) {
-        var cumulativeX = 0f
-        var cumulativeY = 0f
-        var index = 0
-        while (index < vertices.size) {
-            cumulativeX += vertices[index++]
-            cumulativeY += vertices[index++]
-        }
-        result.x = cumulativeX / vertices.size / 2
-        result.y = cumulativeY / vertices.size / 2
-    }
-
-    /**
-     * This class holds information about a corner (rounded or not) or an edge of a given
-     * polygon. The features of a Polygon can be used to manipulate the shape with more context
-     * of what the shape actually is, rather than simply manipulating the raw curves and lines
-     * which describe it.
-     */
-    internal open inner class Feature(protected val cubicIndices: List<Int>) {
-        val cubics: List<Cubic>
-            get() = cubicIndices.map { toCubicShape().cubics[it] }
-
-        open fun transform(matrix: Matrix) {}
-    }
-    /**
-     * Edges have only a list of the cubic curves which make up the edge. Edges lie between
-     * corners and have no vertex or concavity; the curves are simply straight lines (represented
-     * by Cubic curves).
-     */
-    internal inner class Edge(indices: List<Int>) : Feature(indices) {
-        constructor(source: Edge) : this(source.cubicIndices)
-    }
-
-    /**
-     * Corners contain the list of cubic curves which describe how the corner is rounded (or
-     * not), plus the vertex at the corner (which the cubics may or may not pass through, depending
-     * on whether the corner is rounded) and a flag indicating whether the corner is convex.
-     * A regular polygon has all convex corners, while a star polygon generally (but not
-     * necessarily) has both convex (outer) and concave (inner) corners.
-     */
-    internal inner class Corner(
-        cubicIndices: List<Int>,
-        // TODO: parameters here should be immutable
-        val vertex: PointF,
-        val roundedCenter: PointF,
-        val convex: Boolean = true
-    ) : Feature(cubicIndices) {
-        constructor(source: Corner) : this(
-            source.cubicIndices,
-            source.vertex,
-            source.roundedCenter,
-            source.convex
-        )
-
-        override fun transform(matrix: Matrix) {
-            val tempPoints = floatArrayOf(vertex.x, vertex.y, roundedCenter.x, roundedCenter.y)
-            matrix.mapPoints(tempPoints)
-            vertex.set(tempPoints[0], tempPoints[1])
-            roundedCenter.set(tempPoints[2], tempPoints[3])
-        }
-
-        override fun toString(): String {
-            return "Corner: vtx, center, convex = $vertex, $roundedCenter, $convex"
-        }
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (this === other) return true
-        if (other !is RoundedPolygon) return false
-
-        if (cubicShape != other.cubicShape) return false
-
-        return true
-    }
-
-    override fun hashCode(): Int {
-        return cubicShape.hashCode()
-    }
-}
-
-/**
- * Private utility class that holds the information about each corner in a polygon. The shape
- * of the corner can be returned by calling the [getCubics] function, which will return a list
- * of curves representing the corner geometry. The shape of the corner depends on the [rounding]
- * constructor parameter.
- *
- * If rounding is null, there is no rounding; the corner will simply be a single point at [p1].
- * This point will be represented by a [Cubic] of length 0 at that point.
- *
- * If rounding is not null, the corner will be rounded either with a curve approximating a circular
- * arc of the radius specified in [rounding], or with three curves if [rounding] has a nonzero
- * smoothing parameter. These three curves are a circular arc in the middle and two symmetrical
- * flanking curves on either side. The smoothing parameter determines the curvature of the
- * flanking curves.
- *
- * This is a class because we usually need to do the work in 2 steps, and prefer to keep state
- * between: first we determine how much we want to cut to comply with the parameters, then we are
- * given how much we can actually cut (because of space restrictions outside this corner)
- *
- * @param p0 the vertex before the one being rounded
- * @param p1 the vertex of this rounded corner
- * @param p2 the vertex after the one being rounded
- * @param rounding the optional parameters specifying how this corner should be rounded
- */
-private class RoundedCorner(
-    val p0: PointF,
-    val p1: PointF,
-    val p2: PointF,
-    val rounding: CornerRounding? = null
-) {
-    val d1 = (p0 - p1).getDirection()
-    val d2 = (p2 - p1).getDirection()
-    val cornerRadius = rounding?.radius ?: 0f
-    val smoothing = rounding?.smoothing ?: 0f
-
-    // cosine of angle at p1 is dot product of unit vectors to the other two vertices
-    val cosAngle = d1.dotProduct(d2)
-    // identity: sin^2 + cos^2 = 1
-    // sinAngle gives us the intersection
-    val sinAngle = sqrt(1 - square(cosAngle))
-    // How much we need to cut, as measured on a side, to get the required radius
-    // calculating where the rounding circle hits the edge
-    // This uses the identity of tan(A/2) = sinA/(1 + cosA), where tan(A/2) = radius/cut
-    val expectedRoundCut =
-        if (sinAngle > 1e-3) { cornerRadius * (cosAngle + 1) / sinAngle } else { 0f }
-    // smoothing changes the actual cut. 0 is same as expectedRoundCut, 1 doubles it
-    val expectedCut: Float
-        get() = ((1 + smoothing) * expectedRoundCut)
-    // the center of the circle approximated by the rounding curve (or the middle of the three
-    // curves if smoothing is requested). The center is the same as p0 if there is no rounding.
-    lateinit var center: PointF
-
-    @JvmOverloads
-    fun getCubics(allowedCut0: Float, allowedCut1: Float = allowedCut0):
-        List<Cubic> {
-        // We use the minimum of both cuts to determine the radius, but if there is more space
-        // in one side we can use it for smoothing.
-        val allowedCut = min(allowedCut0, allowedCut1)
-        // Nothing to do, just use lines, or a point
-        if (expectedRoundCut < DistanceEpsilon ||
-            allowedCut < DistanceEpsilon ||
-            cornerRadius < DistanceEpsilon
-        ) {
-            center = p1
-            return listOf(Cubic.straightLine(p1.x, p1.y, p1.x, p1.y))
-        }
-        // How much of the cut is required for the rounding part.
-        val actualRoundCut = min(allowedCut, expectedRoundCut)
-        // We have two smoothing values, one for each side of the vertex
-        // Space is used for rounding values first. If there is space left over, then we
-        // apply smoothing, if it was requested
-        val actualSmoothing0 = calculateActualSmoothingValue(allowedCut0)
-        val actualSmoothing1 = calculateActualSmoothingValue(allowedCut1)
-        // Scale the radius if needed
-        val actualR = cornerRadius * actualRoundCut / expectedRoundCut
-        // Distance from the corner (p1) to the center
-        val centerDistance = sqrt(square(actualR) + square(actualRoundCut))
-        // Center of the arc we will use for rounding
-        center = p1 + ((d1 + d2) / 2f).getDirection() * centerDistance
-        val circleIntersection0 = p1 + d1 * actualRoundCut
-        val circleIntersection2 = p1 + d2 * actualRoundCut
-        val flanking0 = computeFlankingCurve(
-            actualRoundCut, actualSmoothing0, p1, p0,
-            circleIntersection0, circleIntersection2, center, actualR
-        )
-        val flanking2 = computeFlankingCurve(
-            actualRoundCut, actualSmoothing1, p1, p2,
-            circleIntersection2, circleIntersection0, center, actualR
-        ).reverse()
-        return listOf(
-            flanking0,
-            Cubic.circularArc(center.x, center.y, flanking0.anchor1X, flanking0.anchor1Y,
-                flanking2.anchor0X, flanking2.anchor0Y),
-            flanking2
-        )
-    }
-
-    /**
-     * If allowedCut (the amount we are able to cut) is greater than the expected cut
-     * (without smoothing applied yet), then there is room to apply smoothing and we
-     * calculate the actual smoothing value here.
-     */
-    private fun calculateActualSmoothingValue(allowedCut: Float): Float {
-        return if (allowedCut > expectedCut) {
-            smoothing
-        } else if (allowedCut > expectedRoundCut) {
-            smoothing * (allowedCut - expectedRoundCut) / (expectedCut - expectedRoundCut)
-        } else {
-            0f
-        }
-    }
-
-    /**
-     * Compute a Bezier to connect the linear segment defined by corner and sideStart
-     * with the circular segment defined by circleCenter, circleSegmentIntersection,
-     * otherCircleSegmentIntersection and actualR.
-     * The bezier will start at the linear segment and end on the circular segment.
-     *
-     * @param actualRoundCut How much we are cutting of the corner to add the circular segment
-     * (this is before smoothing, that will cut some more).
-     * @param actualSmoothingValues How much we want to smooth (this is the smooth parameter,
-     * adjusted down if there is not enough room).
-     * @param corner The point at which the linear side ends
-     * @param sideStart The point at which the linear side starts
-     * @param circleSegmentIntersection The point at which the linear side and the circle intersect.
-     * @param otherCircleSegmentIntersection The point at which the opposing linear side and the
-     * circle intersect.
-     * @param circleCenter The center of the circle.
-     * @param actualR The radius of the circle.
-     *
-     * @return a Bezier cubic curve that connects from the (cut) linear side and the (cut) circular
-     * segment in a smooth way.
-     */
-    private fun computeFlankingCurve(
-        actualRoundCut: Float,
-        actualSmoothingValues: Float,
-        corner: PointF,
-        sideStart: PointF,
-        circleSegmentIntersection: PointF,
-        otherCircleSegmentIntersection: PointF,
-        circleCenter: PointF,
-        actualR: Float
-    ): Cubic {
-        // sideStart is the anchor, 'anchor' is actual control point
-        val sideDirection = (sideStart - corner).getDirection()
-        val curveStart = corner + sideDirection * actualRoundCut * (1 + actualSmoothingValues)
-        // We use an approximation to cut a part of the circle section proportional to 1 - smooth,
-        // When smooth = 0, we take the full section, when smooth = 1, we take nothing.
-        // TODO: revisit this, it can be problematic as it approaches 19- degrees
-        val px = interpolate(circleSegmentIntersection.x,
-            (circleSegmentIntersection.x + otherCircleSegmentIntersection.x) / 2f,
-            actualSmoothingValues)
-        val py = interpolate(circleSegmentIntersection.y,
-            (circleSegmentIntersection.y + otherCircleSegmentIntersection.y) / 2f,
-            actualSmoothingValues)
-        // The flanking curve ends on the circle
-        val curveEnd = circleCenter +
-            directionVector(px - circleCenter.x, py - circleCenter.y) * actualR
-        // The anchor on the circle segment side is in the intersection between the tangent to the
-        // circle in the circle/flanking curve boundary and the linear segment.
-        val circleTangent = (curveEnd - circleCenter).rotate90()
-        val anchorEnd = lineIntersection(sideStart, sideDirection, curveEnd, circleTangent)
-            ?: circleSegmentIntersection
-        // From what remains, we pick a point for the start anchor.
-        // 2/3 seems to come from design tools?
-        val anchorStart = (curveStart + anchorEnd * 2f) / 3f
-        return Cubic(curveStart, anchorStart, anchorEnd, curveEnd)
-    }
-
-    /**
-     * Returns the intersection point of the two lines d0->d1 and p0->p1, or null if the
-     * lines do not intersect
-     */
-    private fun lineIntersection(p0: PointF, d0: PointF, p1: PointF, d1: PointF): PointF? {
-        val rotatedD1 = d1.rotate90()
-        val den = d0.dotProduct(rotatedD1)
-        if (abs(den) < AngleEpsilon) return null
-        val k = (p1 - p0).dotProduct(rotatedD1) / den
-        return p0 + d0 * k
-    }
-}
-
-/**
- * Extension function which draws the given [RoundedPolygon] object into this [Canvas]. Rendering
- * occurs by drawing the underlying path for the object; callers can optionally retrieve the
- * path and draw it directly via [RoundedPolygon.toPath] (though that function copies the underlying
- * path. This extension function avoids that overhead when rendering).
- *
- * @param polygon The object to be drawn
- * @param paint The attributes
- */
-fun Canvas.drawPolygon(polygon: RoundedPolygon, paint: Paint) {
-    polygon.draw(this, paint)
-}
-
-private val scratchTransformPoint = floatArrayOf(0f, 0f)
-
-private val LOG_TAG = "Polygon"
diff --git a/graphics/integration-tests/testapp-compose/src/main/AndroidManifest.xml b/graphics/integration-tests/testapp-compose/src/main/AndroidManifest.xml
index 91ec203..4652d53 100644
--- a/graphics/integration-tests/testapp-compose/src/main/AndroidManifest.xml
+++ b/graphics/integration-tests/testapp-compose/src/main/AndroidManifest.xml
@@ -18,7 +18,7 @@
 
     <application>
         <activity android:name=".MainActivity"
-            android:label="Graphics Shapes Test"
+            android:label="Graphics Shapes Test - Compose"
             android:exported="true"
             android:theme="@android:style/Theme.Material.Light.NoActionBar">
             <intent-filter>
diff --git a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/Compose.kt b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/Compose.kt
new file mode 100644
index 0000000..8d75ae8
--- /dev/null
+++ b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/Compose.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2023 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:Suppress("NOTHING_TO_INLINE")
+
+package androidx.graphics.shapes.testcompose
+
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.graphics.Matrix
+import androidx.compose.ui.graphics.Path
+import androidx.graphics.shapes.Cubic
+import androidx.graphics.shapes.MutableCubic
+import androidx.graphics.shapes.RoundedPolygon
+
+/**
+ * Utility functions providing more idiomatic ways of transforming RoundedPolygons and
+ * transforming shapes into a compose Path, for drawing them.
+ *
+ * This should in the future move into the compose library, maybe with additional API that makes
+ * it easier to create, draw, and animate from Compose apps.
+ *
+ * This code is just here for now prior to integration into compose
+ */
+
+/**
+ * Scales a shape (given as a Sequence) in place.
+ * As this works in Sequences, it doesn't create the whole list at any point, only one
+ * MutableCubic is (re)used.
+ */
+fun Sequence<MutableCubic>.scaled(scale: Float) = map {
+    it.transform {
+        x *= scale
+        y *= scale
+    }
+    it
+}
+
+/**
+ * Scales a shape (given as a List), creating a new List.
+ */
+fun List<Cubic>.scaled(scale: Float) = map {
+    it.transformed {
+        x *= scale
+        y *= scale
+    }
+}
+
+/**
+ * Transforms a [RoundedPolygon] with the given [Matrix]
+ */
+fun RoundedPolygon.transformed(matrix: Matrix): RoundedPolygon =
+    transformed {
+        val transformedPoint = matrix.map(Offset(x, y))
+        x = transformedPoint.x
+        y = transformedPoint.y
+    }
+
+/**
+ * Calculates and returns the bounds of this [RoundedPolygon] as a [Rect]
+ */
+fun RoundedPolygon.getBounds() = calculateBounds().let { Rect(it[0], it[1], it[2], it[3]) }
+
+/**
+ * Function used to create a Path from some Cubics.
+ * Note that this takes an Iterator, so it could be used on Lists, Sequences, etc.
+ */
+fun Iterator<Cubic>.toPath(path: Path = Path()): Path {
+    path.reset()
+    var first = true
+    while (hasNext()) {
+        var bezier = next()
+        if (first) {
+            path.moveTo(bezier.anchor0X, bezier.anchor0Y)
+            first = false
+        }
+        path.cubicTo(
+            bezier.control0X, bezier.control0Y,
+            bezier.control1X, bezier.control1Y,
+            bezier.anchor1X, bezier.anchor1Y
+        )
+    }
+    path.close()
+    return path
+}
+
+/**
+ * Transforms the Sequence into a [Path].
+ */
+fun Sequence<Cubic>.toPath(path: Path = Path()) = iterator().toPath(path)
+
+internal const val DEBUG = false
+
+internal inline fun debugLog(message: String) {
+    if (DEBUG) {
+        println(message)
+    }
+}
diff --git a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt
index 62c3fdc..e7e55d7 100644
--- a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt
+++ b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/DebugDraw.kt
@@ -16,79 +16,33 @@
 
 package androidx.graphics.shapes.testcompose
 
-import android.graphics.Path
-import android.graphics.PointF
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asComposePath
 import androidx.compose.ui.graphics.drawscope.DrawScope
 import androidx.compose.ui.graphics.drawscope.Stroke
 import androidx.graphics.shapes.Cubic
-import androidx.graphics.shapes.CubicShape
-import androidx.graphics.shapes.Morph
 
-internal fun DrawScope.debugDraw(morph: Morph, progress: Float) =
-    debugDraw(morph.asCubics(progress), morph.asPath(progress))
+internal fun DrawScope.debugDraw(shape: Sequence<Cubic>) {
+    drawPath(shape.toPath(), Color.Green, style = Stroke(2f))
 
-internal fun DrawScope.debugDraw(cubicShape: CubicShape) =
-    debugDraw(cubicShape.cubics, cubicShape.toPath())
-
-internal fun DrawScope.debugDraw(cubics: List<Cubic>, path: Path) {
-    drawPath(path.asComposePath(), Color.Green, style = Stroke(2f))
-
-    for (bezier in cubics) {
+    for (bezier in shape) {
         // Draw red circles for start and end.
-        drawCircle(bezier.anchor0X, bezier.anchor0Y, 6f, Color.Red, strokeWidth = 2f)
-        drawCircle(bezier.anchor1X, bezier.anchor1Y, 8f, Color.Magenta, strokeWidth = 2f)
+        drawCircle(Color.Red, radius = 6f, center = bezier.anchor0(), style = Stroke(2f))
+        drawCircle(Color.Magenta, radius = 8f, center = bezier.anchor1(), style = Stroke(2f))
+
         // Draw a circle for the first control point, and a line from start to it.
         // The curve will start in this direction
+        drawLine(Color.Yellow, bezier.anchor0(), bezier.control0(), strokeWidth = 0f)
+        drawCircle(Color.Yellow, radius = 4f, center = bezier.control0(), style = Stroke(2f))
 
-        drawLine(bezier.anchor0X, bezier.anchor0Y, bezier.control0X, bezier.control0Y, Color.Yellow,
-            strokeWidth = 0f)
-        drawCircle(bezier.control0X, bezier.control0Y, 4f, Color.Yellow, strokeWidth = 2f)
         // Draw a circle for the second control point, and a line from it to the end.
         // The curve will end in this direction
-        drawLine(bezier.control1X, bezier.control1Y, bezier.anchor1X, bezier.anchor1Y, Color.Yellow,
-            strokeWidth = 0f)
-        drawCircle(bezier.control1X, bezier.control1Y, 4f, Color.Yellow, strokeWidth = 2f)
+        drawLine(Color.Yellow, bezier.control1(), bezier.anchor1(), strokeWidth = 0f)
+        drawCircle(Color.Yellow, radius = 4f, center = bezier.control1(), style = Stroke(2f))
     }
 }
 
-/**
- * Utility extension functions to bridge OffsetF as points to Compose's Offsets.
- */
-private fun PointF.asOffset() = Offset(x, y)
-
-private fun DrawScope.drawCircle(
-    center: PointF,
-    radius: Float,
-    color: Color,
-    strokeWidth: Float = 2f
-) {
-    drawCircle(color, radius, center.asOffset(), style = Stroke(strokeWidth))
-}
-
-private fun DrawScope.drawCircle(
-    centerX: Float,
-    centerY: Float,
-    radius: Float,
-    color: Color,
-    strokeWidth: Float = 2f
-) {
-    drawCircle(color, radius, Offset(centerX, centerY), style = Stroke(strokeWidth))
-}
-
-private fun DrawScope.drawLine(start: PointF, end: PointF, color: Color, strokeWidth: Float = 2f) {
-    drawLine(color, start.asOffset(), end.asOffset(), strokeWidth = strokeWidth)
-}
-
-private fun DrawScope.drawLine(
-    startX: Float,
-    startY: Float,
-    endX: Float,
-    endY: Float,
-    color: Color,
-    strokeWidth: Float = 2f
-) {
-    drawLine(color, Offset(startX, startY), Offset(endX, endY), strokeWidth = strokeWidth)
-}
+private fun Cubic.anchor0() = Offset(anchor0X, anchor0Y)
+private fun Cubic.control0() = Offset(control0X, control0Y)
+private fun Cubic.control1() = Offset(control1X, control1Y)
+private fun Cubic.anchor1() = Offset(anchor1X, anchor1Y)
diff --git a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/MainActivity.kt b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/MainActivity.kt
index f174290..a88e2c4 100644
--- a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/MainActivity.kt
+++ b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/MainActivity.kt
@@ -16,9 +16,6 @@
 
 package androidx.graphics.shapes.testcompose
 
-import android.graphics.Matrix
-import android.graphics.PointF
-import android.graphics.RectF
 import android.os.Bundle
 import androidx.activity.compose.setContent
 import androidx.compose.animation.core.Animatable
@@ -52,12 +49,11 @@
 import androidx.compose.ui.draw.drawWithContent
 import androidx.compose.ui.geometry.Size
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.asComposePath
 import androidx.compose.ui.unit.dp
 import androidx.fragment.app.FragmentActivity
+import androidx.graphics.shapes.Cubic
 import androidx.graphics.shapes.Morph
 import androidx.graphics.shapes.RoundedPolygon
-import kotlin.math.abs
 import kotlin.math.min
 import kotlinx.coroutines.launch
 
@@ -67,56 +63,15 @@
 
 @Composable
 private fun MorphComposable(
-    sizedMorph: SizedMorph,
+    morph: Morph,
     progress: Float,
     modifier: Modifier = Modifier,
     isDebug: Boolean = false
-) = MorphComposableImpl(sizedMorph, modifier, isDebug, progress)
-
-internal fun calculateMatrix(bounds: RectF, width: Float, height: Float): Matrix {
-    val originalWidth = bounds.right - bounds.left
-    val originalHeight = bounds.bottom - bounds.top
-    val scale = min(width / originalWidth, height / originalHeight)
-    val newLeft = bounds.left - (width / scale - originalWidth) / 2
-    val newTop = bounds.top - (height / scale - originalHeight) / 2
-    val matrix = Matrix()
-    matrix.setTranslate(-newLeft, -newTop)
-    matrix.postScale(scale, scale)
-    return matrix
-}
-
-internal fun PointF.transform(
-    matrix: Matrix,
-    dst: PointF = PointF(),
-    floatArray: FloatArray = FloatArray(2)
-): PointF {
-    floatArray[0] = x
-    floatArray[1] = y
-    matrix.mapPoints(floatArray)
-    dst.x = floatArray[0]
-    dst.y = floatArray[1]
-    return dst
-}
-
-private val TheBounds = RectF(0f, 0f, 1f, 1f)
-
-private class SizedMorph(val morph: Morph) {
-    var width = 1f
-    var height = 1f
-
-    fun resizeMaybe(newWidth: Float, newHeight: Float) {
-        if (abs(width - newWidth) > 1e-4 || abs(height - newHeight) > 1e-4) {
-            val matrix = calculateMatrix(RectF(0f, 0f, width, height), newWidth, newHeight)
-            morph.transform(matrix)
-            width = newWidth
-            height = newHeight
-        }
-    }
-}
+) = MorphComposableImpl(morph, modifier, isDebug, progress)
 
 @Composable
 private fun MorphComposableImpl(
-    sizedMorph: SizedMorph,
+    morph: Morph,
     modifier: Modifier = Modifier,
     isDebug: Boolean = false,
     progress: Float
@@ -126,37 +81,42 @@
             .fillMaxSize()
             .drawWithContent {
                 drawContent()
-                sizedMorph.resizeMaybe(size.width, size.height)
+                val scale = min(size.width, size.height)
+                val shape = morph
+                    .asMutableCubics(progress)
+                    .scaled(scale)
+
                 if (isDebug) {
-                    debugDraw(sizedMorph.morph, progress = progress)
+                    debugDraw(shape)
                 } else {
-                    drawPath(sizedMorph.morph.asPath(progress).asComposePath(), Color.White)
+                    drawPath(shape.toPath(), Color.White)
                 }
             })
 }
 
 @Composable
 internal fun PolygonComposableImpl(
-    shape: RoundedPolygon,
+    polygon: RoundedPolygon,
     modifier: Modifier = Modifier,
     debug: Boolean = false
 ) {
-    val sizedPolygonCache = remember(shape) {
-        mutableMapOf<Size, RoundedPolygon>()
-    }
+    val sizedShapes = remember(polygon) { mutableMapOf<Size, Sequence<Cubic>>() }
     Box(
         modifier
             .fillMaxSize()
             .drawWithContent {
+                // TODO: Can we use drawWithCache to simplify this?
                 drawContent()
-                val sizedPolygon = sizedPolygonCache.getOrPut(size) {
-                    val matrix = calculateMatrix(TheBounds, size.width, size.height)
-                    RoundedPolygon(shape).apply { transform(matrix) }
+                val scale = min(size.width, size.height)
+                val shape = sizedShapes.getOrPut(size) {
+                    polygon.cubics
+                        .scaled(scale)
+                        .asSequence()
                 }
                 if (debug) {
-                    debugDraw(sizedPolygon.toCubicShape())
+                    debugDraw(shape)
                 } else {
-                    drawPath(sizedPolygon.toPath().asComposePath(), Color.White)
+                    drawPath(shape.toPath(), Color.White)
                 }
             })
 }
@@ -288,13 +248,9 @@
 ) {
     val shapes = remember {
         shapeParams.map { sp ->
-            sp.genShape().also { poly ->
-                val matrix = calculateMatrix(poly.bounds, 1f, 1f)
-                poly.transform(matrix)
-            }
+            sp.genShape().let { poly -> poly.normalized() }
         }
     }
-
     var currShape by remember { mutableStateOf(selectedShape.value) }
     val progress = remember { Animatable(0f) }
 
@@ -304,11 +260,9 @@
         derivedStateOf {
             // NOTE: We need to access this variable to ensure we recalculate the morph !
             debugLog("Re-computing morph / $debug")
-            SizedMorph(
-                Morph(
-                    shapes[currShape],
-                    shapes[selectedShape.value]
-                )
+            Morph(
+                shapes[currShape],
+                shapes[selectedShape.value]
             )
         }
     }
diff --git a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt
index abe70b1c..d86c557 100644
--- a/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt
+++ b/graphics/integration-tests/testapp-compose/src/main/java/androidx/graphics/shapes/testcompose/ShapeEditor.kt
@@ -16,9 +16,6 @@
 
 package androidx.graphics.shapes.testcompose
 
-import android.graphics.Matrix
-import android.graphics.PointF
-import android.util.Log
 import androidx.compose.foundation.background
 import androidx.compose.foundation.border
 import androidx.compose.foundation.layout.Column
@@ -43,26 +40,20 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clipToBounds
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.Matrix
 import androidx.compose.ui.unit.dp
-import androidx.core.graphics.plus
 import androidx.graphics.shapes.CornerRounding
 import androidx.graphics.shapes.RoundedPolygon
 import androidx.graphics.shapes.circle
 import androidx.graphics.shapes.rectangle
 import androidx.graphics.shapes.star
-import kotlin.math.cos
 import kotlin.math.max
 import kotlin.math.min
 import kotlin.math.roundToInt
-import kotlin.math.sin
 
 private val LOG_TAG = "ShapeEditor"
-private val DEBUG = false
-
-internal fun debugLog(message: String) {
-    if (DEBUG) Log.d(LOG_TAG, message)
-}
 
 data class ShapeItem(
     val name: String,
@@ -74,8 +65,6 @@
     val usesInnerParameters: Boolean = true
 )
 
-private val PointZero = PointF(0f, 0f)
-
 class ShapeParameters(
     sides: Int = 5,
     innerRadius: Float = 0.5f,
@@ -114,8 +103,8 @@
     private fun radialToCartesian(
         radius: Float,
         angleRadians: Float,
-        center: PointF = PointZero
-    ) = directionVectorPointF(angleRadians) * radius + center
+        center: Offset = Offset.Zero
+    ) = directionVector(angleRadians) * radius + center
 
     private fun rotationAsString() =
         if (this.rotation.value != 0f)
@@ -180,7 +169,8 @@
                 RoundedPolygon(
                     points,
                     CornerRounding(this.roundness.value, this.smooth.value),
-                    centerX = PointZero.x, centerY = PointZero.y
+                    centerX = 0f,
+                    centerY = 0f
                 )
             },
             debugDump = {
@@ -227,7 +217,8 @@
                         CornerRounding(1f),
                         CornerRounding(1f)
                     ),
-                    centerX = PointZero.x, centerY = PointZero.y
+                    centerX = 0f,
+                    centerY = 0f
                 )
             },
             debugDump = {
@@ -286,18 +277,22 @@
 
     fun selectedShape() = derivedStateOf { shapes[shapeIx] }
 
-    fun genShape(autoSize: Boolean = true) = selectedShape().value.shapegen().apply {
-        transform(Matrix().apply {
+    fun genShape(autoSize: Boolean = true) = selectedShape().value.shapegen().let { poly ->
+        poly.transformed(Matrix().apply {
             if (autoSize) {
+                val bounds = poly.getBounds()
                 // Move the center to the origin.
-                postTranslate(-(bounds.left + bounds.right) / 2, -(bounds.top + bounds.bottom) / 2)
+                translate(
+                    x = -(bounds.left + bounds.right) / 2,
+                    y = -(bounds.top + bounds.bottom) / 2
+                )
 
                 // Scale to the [-1, 1] range
-                val scale = 2f / max(bounds.width(), bounds.height())
-                postScale(scale, scale)
+                val scale = 2f / max(bounds.width, bounds.height)
+                scale(x = scale, y = scale)
             }
             // Apply the needed rotation
-            postRotate(rotation.value)
+            rotateZ(rotation.value)
         })
     }
 }
@@ -349,10 +344,11 @@
                 .border(1.dp, Color.White)
                 .padding(2.dp)
         ) {
-            PolygonComposableImpl(params.genShape(autoSize = autoSize).also { poly ->
+            PolygonComposableImpl(params.genShape(autoSize = autoSize).let { poly ->
                 if (autoSize) {
-                    val matrix = calculateMatrix(poly.bounds, 1f, 1f)
-                    poly.transform(matrix)
+                    poly.normalized()
+                } else {
+                    poly
                 }
             }, debug = debug)
         }
@@ -417,12 +413,4 @@
     }
 }
 
-// TODO: remove this when it is integrated into Ktx
-operator fun PointF.times(factor: Float): PointF {
-    return PointF(this.x * factor, this.y * factor)
-}
-
 private fun squarePoints() = floatArrayOf(1f, 1f, -1f, 1f, -1f, -1f, 1f, -1f)
-
-internal fun directionVectorPointF(angleRadians: Float) =
-    PointF(cos(angleRadians), sin(angleRadians))
diff --git a/graphics/integration-tests/testapp/src/main/AndroidManifest.xml b/graphics/integration-tests/testapp/src/main/AndroidManifest.xml
index c29b15e..47fbd2d 100644
--- a/graphics/integration-tests/testapp/src/main/AndroidManifest.xml
+++ b/graphics/integration-tests/testapp/src/main/AndroidManifest.xml
@@ -18,7 +18,7 @@
 
     <application>
         <activity android:name=".ShapeActivity"
-            android:label="Graphics Shapes Test"
+            android:label="Graphics Shapes Test - Views"
             android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/Android.kt b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/Android.kt
new file mode 100644
index 0000000..ff68f78
--- /dev/null
+++ b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/Android.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2023 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.shapes.test
+
+import android.graphics.Canvas
+import android.graphics.Matrix
+import android.graphics.Paint
+import android.graphics.Path
+import androidx.core.graphics.scaleMatrix
+import androidx.graphics.shapes.Cubic
+import androidx.graphics.shapes.RoundedPolygon
+
+fun RoundedPolygon.transformed(matrix: Matrix, tmp: FloatArray = FloatArray(2)):
+    RoundedPolygon = transformed {
+        // TODO: Should we have a fast path for when the MutablePoint is array-backed?
+        tmp[0] = x
+        tmp[1] = y
+        matrix.mapPoints(tmp)
+        x = tmp[0]
+        x = tmp[1]
+    }
+
+/**
+ * Function used to create a Path from this CubicShape.
+ * This usually should only be called once and cached, since CubicShape is immutable.
+ */
+fun Iterator<Cubic>.toPath(path: Path = Path()): Path {
+    path.rewind()
+    var first = true
+    for (bezier in this) {
+        if (first) {
+            path.moveTo(bezier.anchor0X, bezier.anchor0Y)
+            first = false
+        }
+        path.cubicTo(
+            bezier.control0X, bezier.control0Y,
+            bezier.control1X, bezier.control1Y,
+            bezier.anchor1X, bezier.anchor1Y
+        )
+    }
+    path.close()
+    return path
+}
+
+fun Canvas.drawPolygon(shape: RoundedPolygon, scale: Int, paint: Paint) =
+    drawPath(shape.cubics.iterator().toPath().apply {
+        transform(scaleMatrix(scale.toFloat(), scale.toFloat()))
+}, paint)
diff --git a/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeActivity.kt b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeActivity.kt
index bff8b6b..ed34b57 100644
--- a/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeActivity.kt
+++ b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeActivity.kt
@@ -59,13 +59,12 @@
     }
 
     private fun setupShapes() {
+        val tmp = FloatArray(2)
         // Note: all RoundedPolygon(4) shapes are placeholders for shapes not yet handled
         val matrix1 = Matrix().apply { setRotate(-45f) }
         val matrix2 = Matrix().apply { setRotate(45f) }
-        val blobR1 = MaterialShapes.blobR(.19f, .86f)
-        blobR1.transform(matrix1)
-        val blobR2 = MaterialShapes.blobR(.19f, .86f)
-        blobR2.transform(matrix2)
+        val blobR1 = MaterialShapes.blobR(.19f, .86f).transformed(matrix1, tmp)
+        val blobR2 = MaterialShapes.blobR(.19f, .86f).transformed(matrix2, tmp)
 
         //        "Circle" to DefaultShapes.star(4, 1f, 1f),
         shapes.add(RoundedPolygon.circle())
diff --git a/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeView.kt b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeView.kt
index e93bc68..6039e79 100644
--- a/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeView.kt
+++ b/graphics/integration-tests/testapp/src/main/java/androidx/graphics/shapes/test/ShapeView.kt
@@ -19,49 +19,25 @@
 import android.content.Context
 import android.graphics.Canvas
 import android.graphics.Color
-import android.graphics.Matrix
 import android.graphics.Paint
-import android.graphics.RectF
 import android.view.View
 import androidx.graphics.shapes.RoundedPolygon
-import androidx.graphics.shapes.drawPolygon
 import kotlin.math.min
 
-class ShapeView(context: Context, var shape: RoundedPolygon) : View(context) {
-
+class ShapeView(context: Context, shape: RoundedPolygon) : View(context) {
     val paint = Paint()
+    val shape = shape.normalized()
+    var scale = 1
 
     init {
         paint.setColor(Color.WHITE)
     }
 
-    private fun calculateScale(bounds: RectF): Float {
-        val scaleX = width / (bounds.right - bounds.left)
-        val scaleY = height / (bounds.bottom - bounds.top)
-        val scaleFactor = min(scaleX, scaleY)
-        return scaleFactor
-    }
-
-    private fun calculateMatrix(bounds: RectF): Matrix {
-        val scale = calculateScale(bounds)
-        val scaledLeft = scale * bounds.left
-        val scaledTop = scale * bounds.top
-        val scaledWidth = scale * bounds.right - scaledLeft
-        val scaledHeight = scale * bounds.bottom - scaledTop
-        val newLeft = scaledLeft - (width - scaledWidth) / 2
-        val newTop = scaledTop - (height - scaledHeight) / 2
-        val matrix = Matrix()
-        matrix.preTranslate(-newLeft, -newTop)
-        matrix.preScale(scale, scale)
-        return matrix
-    }
-
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
-        val matrix = calculateMatrix(shape.bounds)
-        shape.transform(matrix)
+        scale = min(w, h)
     }
 
     override fun onDraw(canvas: Canvas) {
-        canvas.drawPolygon(shape, paint)
+        canvas.drawPolygon(shape, scale, paint)
     }
 }
diff --git a/health/connect/connect-client-proto/build.gradle b/health/connect/connect-client-proto/build.gradle
index 6d2801c..3b8ef21 100644
--- a/health/connect/connect-client-proto/build.gradle
+++ b/health/connect/connect-client-proto/build.gradle
@@ -16,10 +16,6 @@
 
 import androidx.build.Publish
 
-/*
- * All the following content was derived from :datastore:datastore-core.
- */
-
 plugins {
     id("AndroidXPlugin")
     id("java-library")
@@ -30,10 +26,6 @@
     implementation(libs.protobufLite)
 }
 
-sourceSets {
-    main.java.srcDirs += "$buildDir/generated/source/proto"
-}
-
 protobuf {
     protoc {
         artifact = libs.protobufCompiler.get()
@@ -61,22 +53,6 @@
     }
 }
 
-// Create export artifact for for JarJaring
-def preferencesProtoJarJarTask = tasks.register("exportJar", Jar) {
-    archiveBaseName.set("export")
-    from(sourceSets.main.output)
-    // The proto-lite dependency includes .proto files, which are not used by datastore. When apps
-    // depend on datastore as well as proto-lite directly, these files conflict since jarjar only
-    // renames the java classes. Remove them here since they are unused.
-    exclude("**/*.proto")
-
-    from(zipTree(configurations.detachedConfiguration(
-            dependencies.create(libs.protobufLite.get())).getSingleFile()))
-}
-
-def jarjarConf = configurations.register("export")
-artifacts.add(jarjarConf.name, preferencesProtoJarJarTask.flatMap { it.archiveFile })
-
 androidx {
     name = "Health Connect Client Proto"
     publish = Publish.NONE
diff --git a/health/connect/connect-client/build.gradle b/health/connect/connect-client/build.gradle
index c2438f4..e9a833e 100644
--- a/health/connect/connect-client/build.gradle
+++ b/health/connect/connect-client/build.gradle
@@ -27,7 +27,10 @@
 BundleInsideHelper.forInsideAar(
         project,
         /* from = */ "com.google.protobuf",
-        /* to =   */ "androidx.health.platform.client.proto"
+        /* to =   */ "androidx.health.platform.client.proto",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
@@ -35,7 +38,7 @@
     // Add dependencies here
     api("androidx.activity:activity:1.2.0")
     api("androidx.annotation:annotation:1.2.0")
-    bundleInside(project(path: ":health:connect:connect-client-proto", configuration: "export"))
+    bundleInside(project(":health:connect:connect-client-proto"))
     implementation(libs.guavaListenableFuture)
     implementation(libs.guavaAndroid)
     implementation(libs.kotlinCoroutinesAndroid)
diff --git a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContractTest.kt b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContractTest.kt
index 0c7cdb5d..370aadb 100644
--- a/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContractTest.kt
+++ b/health/connect/connect-client/src/androidTest/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContractTest.kt
@@ -27,6 +27,7 @@
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import com.google.common.truth.Truth.assertThat
+import kotlin.test.assertFailsWith
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -38,8 +39,27 @@
     private val context: Context = ApplicationProvider.getApplicationContext()
 
     @Test
+    fun createIntent_nonHealthPermission_throwsIAE() {
+        val requestPermissionContract = HealthPermissionsRequestContract()
+        assertFailsWith<IllegalArgumentException> {
+            requestPermissionContract.createIntent(
+                context,
+                setOf(HealthPermission.READ_STEPS, "NON_HEALTH_PERMISSION")
+            )
+        }
+    }
+
+    @Test
+    fun createIntent_noPermissions_throwsIAE() {
+        val requestPermissionContract = HealthPermissionsRequestContract()
+        assertFailsWith<IllegalArgumentException> {
+            requestPermissionContract.createIntent(context, setOf())
+        }
+    }
+
+    @Test
     @SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    fun requestHealthPermissions_createIntent_hasPlatformIntentAction() {
+    fun createIntent_hasPlatformIntentAction() {
         val intent =
             HealthPermissionsRequestContract()
                 .createIntent(context, setOf(HealthPermission.READ_STEPS))
@@ -51,7 +71,7 @@
 
     @Test
     @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.TIRAMISU)
-    fun requestHealthPermissions_createIntent_hasApkIntentAction() {
+    fun createIntent_hasApkIntentAction() {
         val intent =
             HealthPermissionsRequestContract()
                 .createIntent(context, setOf(HealthPermission.READ_STEPS))
@@ -61,7 +81,7 @@
 
     @Test
     @SdkSuppress(maxSdkVersion = Build.VERSION_CODES.TIRAMISU)
-    fun requestHealthPermissions_createIntent_hasApkIntentActionAndProvider() {
+    fun createIntent_hasApkIntentActionAndProvider() {
         val intent =
             HealthPermissionsRequestContract("some.provider")
                 .createIntent(context, setOf(HealthPermission.READ_STEPS))
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContract.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContract.kt
index 1251304..679412f 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContract.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/contracts/HealthPermissionsRequestContract.kt
@@ -22,6 +22,7 @@
 import androidx.activity.result.contract.ActivityResultContract
 import androidx.health.connect.client.HealthConnectClient
 import androidx.health.connect.client.permission.HealthDataRequestPermissionsInternal
+import androidx.health.connect.client.permission.HealthPermission
 import androidx.health.connect.client.permission.platform.HealthDataRequestPermissionsUpsideDownCake
 
 /**
@@ -50,6 +51,10 @@
      * @see ActivityResultContract.createIntent
      */
     override fun createIntent(context: Context, input: Set<String>): Intent {
+        require(input.all { it.startsWith(HealthPermission.PERMISSION_PREFIX) }) {
+            "Unsupported health connect permission"
+        }
+        require(input.isNotEmpty()) { "At least one permission is required!" }
         return delegate.createIntent(context, input)
     }
 
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthDataRequestPermissionsInternal.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthDataRequestPermissionsInternal.kt
index 28c1ee5..6ddad08 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthDataRequestPermissionsInternal.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/HealthDataRequestPermissionsInternal.kt
@@ -32,8 +32,7 @@
  * An [ActivityResultContract] to request Health Connect permissions.
  *
  * @param providerPackageName Optional provider package name for the backing implementation of
- * choice.
- *
+ *   choice.
  * @see androidx.activity.ComponentActivity.registerForActivityResult
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY)
@@ -42,8 +41,6 @@
 ) : ActivityResultContract<Set<String>, Set<String>>() {
 
     override fun createIntent(context: Context, input: Set<String>): Intent {
-        require(input.isNotEmpty()) { "At least one permission is required!" }
-
         val protoPermissionList =
             input
                 .asSequence()
diff --git a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCake.kt b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCake.kt
index e6994c5..e4dd720 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCake.kt
+++ b/health/connect/connect-client/src/main/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCake.kt
@@ -20,7 +20,6 @@
 import androidx.activity.result.contract.ActivityResultContract
 import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
 import androidx.annotation.RestrictTo
-import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_PREFIX
 
 /**
  * An [ActivityResultContract] to request Health Connect system permissions.
@@ -33,12 +32,8 @@
 
     private val requestPermissions = RequestMultiplePermissions()
 
-    override fun createIntent(context: Context, input: Set<String>): Intent {
-        require(input.all { it.startsWith(PERMISSION_PREFIX) }) {
-            "Unsupported health connect permission"
-        }
-        return requestPermissions.createIntent(context, input.toTypedArray())
-    }
+    override fun createIntent(context: Context, input: Set<String>): Intent =
+        requestPermissions.createIntent(context, input.toTypedArray())
 
     override fun parseResult(resultCode: Int, intent: Intent?): Set<String> =
         requestPermissions.parseResult(resultCode, intent).filterValues { it }.keys
diff --git a/health/connect/connect-client/src/test/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCakeTest.kt b/health/connect/connect-client/src/test/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCakeTest.kt
index 2bbd4f4..f284bd6a 100644
--- a/health/connect/connect-client/src/test/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCakeTest.kt
+++ b/health/connect/connect-client/src/test/java/androidx/health/connect/client/permission/platform/HealthDataRequestPermissionsUpsideDownCakeTest.kt
@@ -25,7 +25,6 @@
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.google.common.truth.Truth.assertThat
-import kotlin.test.assertFailsWith
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -45,7 +44,9 @@
         val requestPermissionContract = HealthDataRequestPermissionsUpsideDownCake()
         val intent =
             requestPermissionContract.createIntent(
-                context, setOf(HealthPermission.READ_STEPS, HealthPermission.WRITE_DISTANCE))
+                context,
+                setOf(HealthPermission.READ_STEPS, HealthPermission.WRITE_DISTANCE)
+            )
 
         assertThat(intent.action).isEqualTo(RequestMultiplePermissions.ACTION_REQUEST_PERMISSIONS)
         assertThat(intent.getStringArrayExtra(RequestMultiplePermissions.EXTRA_PERMISSIONS))
@@ -54,15 +55,6 @@
     }
 
     @Test
-    fun createIntent_nonHealthPermission_throwsIAE() {
-        val requestPermissionContract = HealthDataRequestPermissionsUpsideDownCake()
-        assertFailsWith<IllegalArgumentException> {
-            requestPermissionContract.createIntent(
-                context, setOf(HealthPermission.READ_STEPS, "NON_HEALTH_PERMISSION"))
-        }
-    }
-
-    @Test
     fun parseIntent() {
         val requestPermissionContract = HealthDataRequestPermissionsUpsideDownCake()
 
@@ -73,14 +65,18 @@
                 HealthPermission.READ_STEPS,
                 HealthPermission.WRITE_STEPS,
                 HealthPermission.WRITE_DISTANCE,
-                HealthPermission.READ_HEART_RATE))
+                HealthPermission.READ_HEART_RATE
+            )
+        )
         intent.putExtra(
             RequestMultiplePermissions.EXTRA_PERMISSION_GRANT_RESULTS,
             intArrayOf(
                 PackageManager.PERMISSION_GRANTED,
                 PackageManager.PERMISSION_DENIED,
                 PackageManager.PERMISSION_GRANTED,
-                PackageManager.PERMISSION_DENIED))
+                PackageManager.PERMISSION_DENIED
+            )
+        )
 
         val result = requestPermissionContract.parseResult(Activity.RESULT_OK, intent)
 
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanFilter.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanFilter.java
index 207b941..91f2d12 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanFilter.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanFilter.java
@@ -52,8 +52,16 @@
     // Measurement matrix
     public @NonNull Matrix H;
 
-    // Kalman gain
-    public @NonNull Matrix K;
+    // Buffers to minimize matrix allocations on every MotionEvent
+    private @NonNull Matrix mBufferXDimOne;
+    private @NonNull Matrix mBufferXDimXDim;
+    private @NonNull Matrix mBufferXDimXDim2;
+    private @NonNull Matrix mBufferXDimZDim;
+    private @NonNull Matrix mBufferXDimZDim2;
+    private @NonNull Matrix mBufferZDimOne;
+    private @NonNull Matrix mBufferZDimXDim;
+    private @NonNull Matrix mBufferZDimZDim;
+    private @NonNull Matrix mBufferZDimTwiceZDim;
 
     public KalmanFilter(int xDim, int zDim) {
         x = new Matrix(xDim, 1);
@@ -62,7 +70,15 @@
         R = Matrix.identity(zDim);
         F = new Matrix(xDim, xDim);
         H = new Matrix(zDim, xDim);
-        K = new Matrix(xDim, zDim);
+        mBufferXDimZDim = new Matrix(xDim, zDim);
+        mBufferXDimZDim2 = new Matrix(xDim, zDim);
+        mBufferXDimOne = new Matrix(xDim, 1);
+        mBufferXDimXDim = new Matrix(xDim, xDim);
+        mBufferXDimXDim2 = new Matrix(xDim, xDim);
+        mBufferZDimOne = new Matrix(zDim, 1);
+        mBufferZDimXDim = new Matrix(zDim, xDim);
+        mBufferZDimZDim = new Matrix(zDim, zDim);
+        mBufferZDimTwiceZDim = new Matrix(zDim, 2 * zDim);
     }
 
     /** Resets the internal state of this Kalman filter. */
@@ -70,7 +86,6 @@
         // NOTE: It is not necessary to reset Q, R, F, and H matrices.
         x.fill(0);
         Matrix.setIdentity(P);
-        K.fill(0);
     }
 
     /**
@@ -78,16 +93,24 @@
      * estimate for the current timestep.
      */
     public void predict() {
-        x = F.dot(x);
-        P = F.dot(P).dotTranspose(F).plus(Q);
+        Matrix originalX = x;
+        x = F.dot(x, mBufferXDimOne);
+        mBufferXDimOne = originalX;
+
+        F.dot(P, mBufferXDimXDim).dotTranspose(F, P).plus(Q);
     }
 
     /** Updates the state estimate to incorporate the new observation z. */
     public void update(@NonNull Matrix z) {
-        Matrix y = z.minus(H.dot(x));
-        Matrix tS = H.dot(P).dotTranspose(H).plus(R);
-        K = P.dotTranspose(H).dot(tS.inverse());
-        x = x.plus(K.dot(y));
-        P = P.minus(K.dot(H).dot(P));
+        z.minus(H.dot(x, mBufferZDimOne));
+        H.dot(P, mBufferZDimXDim)
+                .dotTranspose(H, mBufferZDimZDim)
+                .plus(R)
+                .inverse(mBufferZDimTwiceZDim);
+
+        P.dotTranspose(H, mBufferXDimZDim2).dot(mBufferZDimZDim, mBufferXDimZDim);
+
+        x.plus(mBufferXDimZDim.dot(z, mBufferXDimOne));
+        P.minus(mBufferXDimZDim.dot(H, mBufferXDimXDim).dot(P, mBufferXDimXDim2));
     }
 }
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/matrix/Matrix.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/matrix/Matrix.java
index 0294b18..399263d 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/matrix/Matrix.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/matrix/Matrix.java
@@ -230,27 +230,6 @@
      * Calculates the matrix product of this matrix and {@code that}.
      *
      * @param that the other matrix
-     * @return newly created matrix representing the matrix product of this and that
-     * @throws IllegalArgumentException if the dimensions differ
-     */
-    public @NonNull Matrix dot(@NonNull Matrix that) {
-        try {
-            return dot(that, new Matrix(mRows, that.mCols));
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(
-                    String.format(
-                            Locale.ROOT,
-                            "The matrices dimensions are not conformant for a dot matrix "
-                                    + "operation. this:%s that:%s",
-                            shortString(),
-                            that.shortString()));
-        }
-    }
-
-    /**
-     * Calculates the matrix product of this matrix and {@code that}.
-     *
-     * @param that the other matrix
      * @param result matrix to hold the result
      * @return result, filled with the matrix product
      * @throws IllegalArgumentException if the dimensions differ
@@ -281,15 +260,26 @@
     /**
      * Calculates the inverse of a square matrix
      *
+     * @param scratch the matrix [rows, 2*cols] to hold the temporary information
+     *
      * @return newly created matrix representing the matrix inverse
      * @throws ArithmeticException if the matrix is not invertible
      */
-    public @NonNull Matrix inverse() {
+    public @NonNull Matrix inverse(@NonNull Matrix scratch) {
         if (!(mRows == mCols)) {
             throw new IllegalArgumentException(
                     String.format(Locale.ROOT, "The matrix is not square. this:%s", shortString()));
         }
-        final Matrix scratch = new Matrix(mRows, 2 * mCols);
+
+        if (scratch.mRows != mRows || scratch.mCols != 2 * mCols) {
+            throw new IllegalArgumentException(
+                    String.format(
+                            Locale.ROOT,
+                            "The scratch matrix size is not correct. this:%s",
+                            scratch.shortString()
+                    )
+            );
+        }
 
         for (int i = 0; i < mRows; i++) {
             for (int j = 0; j < mCols; j++) {
@@ -349,27 +339,6 @@
      * Calculates the matrix product with the transpose of a second matrix.
      *
      * @param that the other matrix
-     * @return newly created matrix representing the matrix product of this and that.transpose()
-     * @throws IllegalArgumentException if shapes are not conformant
-     */
-    public @NonNull Matrix dotTranspose(@NonNull Matrix that) {
-        try {
-            return dotTranspose(that, new Matrix(mRows, that.mRows));
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException(
-                    String.format(
-                            Locale.ROOT,
-                            "The matrices dimensions are not conformant for a transpose "
-                                    + "operation. this:%s that:%s",
-                            shortString(),
-                            that.shortString()));
-        }
-    }
-
-    /**
-     * Calculates the matrix product with the transpose of a second matrix.
-     *
-     * @param that the other matrix
      * @param result space to hold the result
      * @return result, filled with the matrix product of this and that.transpose()
      * @throws IllegalArgumentException if shapes are not conformant
diff --git a/kruth/kruth/api/api_lint.ignore b/kruth/kruth/api/api_lint.ignore
index 196437b..4762f9e 100644
--- a/kruth/kruth/api/api_lint.ignore
+++ b/kruth/kruth/api/api_lint.ignore
@@ -13,6 +13,8 @@
     Must avoid boxed primitives (`java.lang.Boolean`)
 AutoBoxing: androidx.kruth.KruthKt#assertThat(Double) parameter #0:
     Must avoid boxed primitives (`java.lang.Double`)
+AutoBoxing: androidx.kruth.KruthKt#assertThat(Integer) parameter #0:
+    Must avoid boxed primitives (`java.lang.Integer`)
 AutoBoxing: androidx.kruth.StandardSubjectBuilder#that(Boolean) parameter #0:
     Must avoid boxed primitives (`java.lang.Boolean`)
 AutoBoxing: androidx.kruth.StandardSubjectBuilder#that(Double) parameter #0:
@@ -25,6 +27,8 @@
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.kruth.StandardSubjectBuilder.about(androidx.kruth.Subject.Factory<? extends S,T>)
 BuilderSetStyle: androidx.kruth.StandardSubjectBuilder#fail():
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.kruth.StandardSubjectBuilder.fail()
+BuilderSetStyle: androidx.kruth.StandardSubjectBuilder#forCustomFailureStrategy(androidx.kruth.FailureStrategy):
+    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.kruth.StandardSubjectBuilder.forCustomFailureStrategy(androidx.kruth.FailureStrategy)
 BuilderSetStyle: androidx.kruth.StandardSubjectBuilder#that(Boolean):
     Builder methods names should use setFoo() / addFoo() / clearFoo() style: method androidx.kruth.StandardSubjectBuilder.that(Boolean)
 BuilderSetStyle: androidx.kruth.StandardSubjectBuilder#that(Double):
@@ -47,12 +51,6 @@
     androidx.kruth.StandardSubjectBuilder does not declare a `build()` method, but builder classes are expected to
 
 
-MissingJvmstatic: androidx.kruth.Fact#fact(String, Object):
-    A Kotlin method with default parameter values should be annotated with @JvmOverloads for better Java interoperability; see https://android.github.io/kotlin-guides/interop.html#function-overloads-for-defaults
-MissingJvmstatic: androidx.kruth.Fact.Companion#fact(String, Object):
-    A Kotlin method with default parameter values should be annotated with @JvmOverloads for better Java interoperability; see https://android.github.io/kotlin-guides/interop.html#function-overloads-for-defaults
-
-
 TopLevelBuilder: androidx.kruth.SimpleSubjectBuilder:
     Builder should be defined as inner class: androidx.kruth.SimpleSubjectBuilder
 TopLevelBuilder: androidx.kruth.StandardSubjectBuilder:
diff --git a/kruth/kruth/api/current.ignore b/kruth/kruth/api/current.ignore
index 2adc0e5..a8eda3a 100644
--- a/kruth/kruth/api/current.ignore
+++ b/kruth/kruth/api/current.ignore
@@ -1,6 +1,8 @@
 // Baseline format: 1.0
-AddedFinal: androidx.kruth.ComparableSubject#isEquivalentAccordingToCompareTo(T):
-    Method androidx.kruth.ComparableSubject.isEquivalentAccordingToCompareTo has added 'final' qualifier
+AddedAbstractMethod: androidx.kruth.FailureStrategy#fail(Error):
+    Added method androidx.kruth.FailureStrategy.fail(Error)
+
+
 AddedFinal: androidx.kruth.IterableSubject#isInOrder():
     Method androidx.kruth.IterableSubject.isInOrder has added 'final' qualifier
 AddedFinal: androidx.kruth.IterableSubject#isInStrictOrder():
@@ -43,6 +45,8 @@
     Method androidx.kruth.StandardSubjectBuilder.that has changed return type from androidx.kruth.ClassSubject to androidx.kruth.Subject<T>
 ChangedType: androidx.kruth.StandardSubjectBuilder#that(java.util.Map<K,? extends V>):
     Method androidx.kruth.StandardSubjectBuilder.that has changed return type from androidx.kruth.MapSubject to androidx.kruth.MapSubject<K,V>
+ChangedType: androidx.kruth.Subject#failWithActual(String, Object):
+    Method androidx.kruth.Subject.failWithActual has changed return type from void to Void
 ChangedType: androidx.kruth.Subject.Factory#createSubject(androidx.kruth.FailureMetadata, ActualT):
     Method androidx.kruth.Subject.Factory.createSubject has changed return type from SubjectT (extends androidx.kruth.Subject) to SubjectT (extends androidx.kruth.Subject<? extends ActualT>)
 ChangedType: androidx.kruth.ThrowableSubject#hasCauseThat():
@@ -83,8 +87,6 @@
     Removed class androidx.kruth.FloatSubject
 RemovedClass: androidx.kruth.GuavaOptionalSubject:
     Removed class androidx.kruth.GuavaOptionalSubject
-RemovedClass: androidx.kruth.IntegerSubject:
-    Removed class androidx.kruth.IntegerSubject
 RemovedClass: androidx.kruth.IterableSubject.UsingCorrespondence:
     Removed class androidx.kruth.IterableSubject.UsingCorrespondence
 RemovedClass: androidx.kruth.LongSubject:
@@ -125,8 +127,6 @@
 
 RemovedInterface: androidx.kruth.Fact:
     Class androidx.kruth.Fact no longer implements java.io.Serializable
-RemovedInterface: androidx.kruth.FailureStrategy:
-    Removed class androidx.kruth.FailureStrategy
 
 
 RemovedMethod: androidx.kruth.ComparableSubject#ComparableSubject(androidx.kruth.FailureMetadata, T):
@@ -135,6 +135,10 @@
     Removed method androidx.kruth.ComparableSubject.isIn(com.google.common.collect.Range<T>)
 RemovedMethod: androidx.kruth.ComparableSubject#isNotIn(com.google.common.collect.Range<T>):
     Removed method androidx.kruth.ComparableSubject.isNotIn(com.google.common.collect.Range<T>)
+RemovedMethod: androidx.kruth.FailureStrategy#fail(AssertionError):
+    Removed method androidx.kruth.FailureStrategy.fail(AssertionError)
+RemovedMethod: androidx.kruth.IntegerSubject#IntegerSubject(androidx.kruth.FailureMetadata, Integer):
+    Removed constructor androidx.kruth.IntegerSubject(androidx.kruth.FailureMetadata,Integer)
 RemovedMethod: androidx.kruth.IterableSubject#IterableSubject(androidx.kruth.FailureMetadata, Iterable<?>):
     Removed constructor androidx.kruth.IterableSubject(androidx.kruth.FailureMetadata,Iterable<?>)
 RemovedMethod: androidx.kruth.IterableSubject#comparingElementsUsing(androidx.kruth.Correspondence<? super A,? super E>):
@@ -161,8 +165,6 @@
     Removed method androidx.kruth.MapSubject.formattingDiffsUsing(androidx.kruth.Correspondence.DiffFormatter<? super V,? super V>)
 RemovedMethod: androidx.kruth.StandardSubjectBuilder#about(androidx.kruth.CustomSubjectBuilder.Factory<CustomSubjectBuilderT>):
     Removed method androidx.kruth.StandardSubjectBuilder.about(androidx.kruth.CustomSubjectBuilder.Factory<CustomSubjectBuilderT>)
-RemovedMethod: androidx.kruth.StandardSubjectBuilder#forCustomFailureStrategy(androidx.kruth.FailureStrategy):
-    Removed method androidx.kruth.StandardSubjectBuilder.forCustomFailureStrategy(androidx.kruth.FailureStrategy)
 RemovedMethod: androidx.kruth.StandardSubjectBuilder#withMessage(String, java.lang.Object...):
     Removed method androidx.kruth.StandardSubjectBuilder.withMessage(String,java.lang.Object...)
 RemovedMethod: androidx.kruth.StringSubject#StringSubject(androidx.kruth.FailureMetadata, String):
@@ -189,8 +191,6 @@
     Removed method androidx.kruth.Subject.actualCustomStringRepresentation()
 RemovedMethod: androidx.kruth.Subject#check(String, java.lang.Object...):
     Removed method androidx.kruth.Subject.check(String,java.lang.Object...)
-RemovedMethod: androidx.kruth.Subject#failWithActual(String, Object):
-    Removed method androidx.kruth.Subject.failWithActual(String,Object)
 RemovedMethod: androidx.kruth.Subject#failWithActual(androidx.kruth.Fact, androidx.kruth.Fact...):
     Removed method androidx.kruth.Subject.failWithActual(androidx.kruth.Fact,androidx.kruth.Fact...)
 RemovedMethod: androidx.kruth.Subject#failWithoutActual(androidx.kruth.Fact, androidx.kruth.Fact...):
diff --git a/kruth/kruth/api/current.txt b/kruth/kruth/api/current.txt
index fe55142..74399e0 100644
--- a/kruth/kruth/api/current.txt
+++ b/kruth/kruth/api/current.txt
@@ -9,7 +9,7 @@
   public class ComparableSubject<T extends java.lang.Comparable<? super T>> extends androidx.kruth.Subject<T> {
     method public final void isAtLeast(T? other);
     method public final void isAtMost(T? other);
-    method public final void isEquivalentAccordingToCompareTo(T? expected);
+    method public void isEquivalentAccordingToCompareTo(T? other);
     method public final void isGreaterThan(T? other);
     method public final void isLessThan(T? other);
   }
@@ -37,6 +37,7 @@
   }
 
   public final class Fact {
+    method public static androidx.kruth.Fact fact(String key);
     method public static androidx.kruth.Fact fact(String key, optional Object? value);
     method public String getKey();
     method public String? getValue();
@@ -48,16 +49,34 @@
   }
 
   public static final class Fact.Companion {
+    method public androidx.kruth.Fact fact(String key);
     method public androidx.kruth.Fact fact(String key, optional Object? value);
     method public String makeMessage(java.util.List<java.lang.String> messages, java.util.List<androidx.kruth.Fact> facts);
     method public androidx.kruth.Fact simpleFact(String key);
   }
 
   public final class FailureMetadata {
-    method public java.util.List<java.lang.String> component1();
-    method public androidx.kruth.FailureMetadata copy(java.util.List<java.lang.String> messagesToPrepend);
+    method public androidx.kruth.FailureStrategy component1();
+    method public java.util.List<java.lang.String> component2();
+    method public androidx.kruth.FailureMetadata copy(androidx.kruth.FailureStrategy failureStrategy, java.util.List<java.lang.String> messagesToPrepend);
+    method public static androidx.kruth.FailureMetadata forFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
+    method public androidx.kruth.FailureStrategy getFailureStrategy();
     method public java.util.List<java.lang.String> getMessagesToPrepend();
+    property public final androidx.kruth.FailureStrategy failureStrategy;
     property public final java.util.List<java.lang.String> messagesToPrepend;
+    field public static final androidx.kruth.FailureMetadata.Companion Companion;
+  }
+
+  public static final class FailureMetadata.Companion {
+    method public androidx.kruth.FailureMetadata forFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
+  }
+
+  public fun interface FailureStrategy {
+    method public Void fail(Error failure);
+  }
+
+  public class IntegerSubject extends androidx.kruth.ComparableSubject<java.lang.Integer> {
+    method @Deprecated public void isEquivalentAccordingToCompareTo(Integer? other);
   }
 
   public class IterableSubject<T> extends androidx.kruth.Subject<java.lang.Iterable<? extends T>> {
@@ -96,6 +115,7 @@
     method public static <S extends androidx.kruth.Subject<? extends T>, T> androidx.kruth.SimpleSubjectBuilder<S,T> assertAbout(androidx.kruth.Subject.Factory<? extends S,T> subjectFactory);
     method public static androidx.kruth.BooleanSubject assertThat(Boolean? actual);
     method public static androidx.kruth.DoubleSubject assertThat(Double? actual);
+    method public static androidx.kruth.IntegerSubject assertThat(Integer? actual);
     method public static <T> androidx.kruth.IterableSubject<T> assertThat(Iterable<? extends T>? actual);
     method public static androidx.kruth.StringSubject assertThat(String? actual);
     method public static <K, V> androidx.kruth.MapSubject<K,V> assertThat(java.util.Map<K,? extends V>? actual);
@@ -127,6 +147,7 @@
   public final class StandardSubjectBuilder {
     method public <T, S extends androidx.kruth.Subject<? extends T>> androidx.kruth.SimpleSubjectBuilder<S,T> about(androidx.kruth.Subject.Factory<? extends S,T> subjectFactory);
     method public Void fail();
+    method public static androidx.kruth.StandardSubjectBuilder? forCustomFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
     method public androidx.kruth.BooleanSubject that(Boolean? actual);
     method public androidx.kruth.DoubleSubject that(Double? actual);
     method public <T> androidx.kruth.IterableSubject<T> that(Iterable<? extends T>? actual);
@@ -136,6 +157,11 @@
     method public <T extends java.lang.Comparable<? super T>> androidx.kruth.ComparableSubject<T> that(T? actual);
     method public <T extends java.lang.Throwable> androidx.kruth.ThrowableSubject<T> that(T? actual);
     method public androidx.kruth.StandardSubjectBuilder withMessage(String messageToPrepend);
+    field public static final androidx.kruth.StandardSubjectBuilder.Companion Companion;
+  }
+
+  public static final class StandardSubjectBuilder.Companion {
+    method public androidx.kruth.StandardSubjectBuilder? forCustomFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
   }
 
   public final class StringSubject extends androidx.kruth.ComparableSubject<java.lang.String> {
@@ -160,8 +186,13 @@
     ctor public Subject(T? actual, optional androidx.kruth.FailureMetadata metadata);
     method protected final androidx.kruth.StandardSubjectBuilder check();
     method protected final Void failWithActual(androidx.kruth.Fact... facts);
+    method protected final Void failWithActual(String key);
+    method protected final Void failWithActual(String key, optional Object? value);
     method protected final Void failWithoutActual(androidx.kruth.Fact... facts);
+    method protected final Void failWithoutActual(String key);
+    method protected final Void failWithoutActual(String key, optional Object? value);
     method public final T? getActual();
+    method public final androidx.kruth.FailureMetadata getMetadata();
     method public void isAnyOf(Object? first, Object? second, java.lang.Object?... rest);
     method public void isEqualTo(Object? expected);
     method public void isIn(Iterable<?>? iterable);
@@ -175,6 +206,7 @@
     method public void isNull();
     method public void isSameInstanceAs(Object? expected);
     property public final T? actual;
+    property public final androidx.kruth.FailureMetadata metadata;
   }
 
   public static fun interface Subject.Factory<SubjectT extends androidx.kruth.Subject<? extends ActualT>, ActualT> {
diff --git a/kruth/kruth/api/restricted_current.ignore b/kruth/kruth/api/restricted_current.ignore
index 2adc0e5..a8eda3a 100644
--- a/kruth/kruth/api/restricted_current.ignore
+++ b/kruth/kruth/api/restricted_current.ignore
@@ -1,6 +1,8 @@
 // Baseline format: 1.0
-AddedFinal: androidx.kruth.ComparableSubject#isEquivalentAccordingToCompareTo(T):
-    Method androidx.kruth.ComparableSubject.isEquivalentAccordingToCompareTo has added 'final' qualifier
+AddedAbstractMethod: androidx.kruth.FailureStrategy#fail(Error):
+    Added method androidx.kruth.FailureStrategy.fail(Error)
+
+
 AddedFinal: androidx.kruth.IterableSubject#isInOrder():
     Method androidx.kruth.IterableSubject.isInOrder has added 'final' qualifier
 AddedFinal: androidx.kruth.IterableSubject#isInStrictOrder():
@@ -43,6 +45,8 @@
     Method androidx.kruth.StandardSubjectBuilder.that has changed return type from androidx.kruth.ClassSubject to androidx.kruth.Subject<T>
 ChangedType: androidx.kruth.StandardSubjectBuilder#that(java.util.Map<K,? extends V>):
     Method androidx.kruth.StandardSubjectBuilder.that has changed return type from androidx.kruth.MapSubject to androidx.kruth.MapSubject<K,V>
+ChangedType: androidx.kruth.Subject#failWithActual(String, Object):
+    Method androidx.kruth.Subject.failWithActual has changed return type from void to Void
 ChangedType: androidx.kruth.Subject.Factory#createSubject(androidx.kruth.FailureMetadata, ActualT):
     Method androidx.kruth.Subject.Factory.createSubject has changed return type from SubjectT (extends androidx.kruth.Subject) to SubjectT (extends androidx.kruth.Subject<? extends ActualT>)
 ChangedType: androidx.kruth.ThrowableSubject#hasCauseThat():
@@ -83,8 +87,6 @@
     Removed class androidx.kruth.FloatSubject
 RemovedClass: androidx.kruth.GuavaOptionalSubject:
     Removed class androidx.kruth.GuavaOptionalSubject
-RemovedClass: androidx.kruth.IntegerSubject:
-    Removed class androidx.kruth.IntegerSubject
 RemovedClass: androidx.kruth.IterableSubject.UsingCorrespondence:
     Removed class androidx.kruth.IterableSubject.UsingCorrespondence
 RemovedClass: androidx.kruth.LongSubject:
@@ -125,8 +127,6 @@
 
 RemovedInterface: androidx.kruth.Fact:
     Class androidx.kruth.Fact no longer implements java.io.Serializable
-RemovedInterface: androidx.kruth.FailureStrategy:
-    Removed class androidx.kruth.FailureStrategy
 
 
 RemovedMethod: androidx.kruth.ComparableSubject#ComparableSubject(androidx.kruth.FailureMetadata, T):
@@ -135,6 +135,10 @@
     Removed method androidx.kruth.ComparableSubject.isIn(com.google.common.collect.Range<T>)
 RemovedMethod: androidx.kruth.ComparableSubject#isNotIn(com.google.common.collect.Range<T>):
     Removed method androidx.kruth.ComparableSubject.isNotIn(com.google.common.collect.Range<T>)
+RemovedMethod: androidx.kruth.FailureStrategy#fail(AssertionError):
+    Removed method androidx.kruth.FailureStrategy.fail(AssertionError)
+RemovedMethod: androidx.kruth.IntegerSubject#IntegerSubject(androidx.kruth.FailureMetadata, Integer):
+    Removed constructor androidx.kruth.IntegerSubject(androidx.kruth.FailureMetadata,Integer)
 RemovedMethod: androidx.kruth.IterableSubject#IterableSubject(androidx.kruth.FailureMetadata, Iterable<?>):
     Removed constructor androidx.kruth.IterableSubject(androidx.kruth.FailureMetadata,Iterable<?>)
 RemovedMethod: androidx.kruth.IterableSubject#comparingElementsUsing(androidx.kruth.Correspondence<? super A,? super E>):
@@ -161,8 +165,6 @@
     Removed method androidx.kruth.MapSubject.formattingDiffsUsing(androidx.kruth.Correspondence.DiffFormatter<? super V,? super V>)
 RemovedMethod: androidx.kruth.StandardSubjectBuilder#about(androidx.kruth.CustomSubjectBuilder.Factory<CustomSubjectBuilderT>):
     Removed method androidx.kruth.StandardSubjectBuilder.about(androidx.kruth.CustomSubjectBuilder.Factory<CustomSubjectBuilderT>)
-RemovedMethod: androidx.kruth.StandardSubjectBuilder#forCustomFailureStrategy(androidx.kruth.FailureStrategy):
-    Removed method androidx.kruth.StandardSubjectBuilder.forCustomFailureStrategy(androidx.kruth.FailureStrategy)
 RemovedMethod: androidx.kruth.StandardSubjectBuilder#withMessage(String, java.lang.Object...):
     Removed method androidx.kruth.StandardSubjectBuilder.withMessage(String,java.lang.Object...)
 RemovedMethod: androidx.kruth.StringSubject#StringSubject(androidx.kruth.FailureMetadata, String):
@@ -189,8 +191,6 @@
     Removed method androidx.kruth.Subject.actualCustomStringRepresentation()
 RemovedMethod: androidx.kruth.Subject#check(String, java.lang.Object...):
     Removed method androidx.kruth.Subject.check(String,java.lang.Object...)
-RemovedMethod: androidx.kruth.Subject#failWithActual(String, Object):
-    Removed method androidx.kruth.Subject.failWithActual(String,Object)
 RemovedMethod: androidx.kruth.Subject#failWithActual(androidx.kruth.Fact, androidx.kruth.Fact...):
     Removed method androidx.kruth.Subject.failWithActual(androidx.kruth.Fact,androidx.kruth.Fact...)
 RemovedMethod: androidx.kruth.Subject#failWithoutActual(androidx.kruth.Fact, androidx.kruth.Fact...):
diff --git a/kruth/kruth/api/restricted_current.txt b/kruth/kruth/api/restricted_current.txt
index f2de5fd..ca3e549 100644
--- a/kruth/kruth/api/restricted_current.txt
+++ b/kruth/kruth/api/restricted_current.txt
@@ -9,7 +9,7 @@
   public class ComparableSubject<T extends java.lang.Comparable<? super T>> extends androidx.kruth.Subject<T> {
     method public final void isAtLeast(T? other);
     method public final void isAtMost(T? other);
-    method public final void isEquivalentAccordingToCompareTo(T? expected);
+    method public void isEquivalentAccordingToCompareTo(T? other);
     method public final void isGreaterThan(T? other);
     method public final void isLessThan(T? other);
   }
@@ -37,6 +37,7 @@
   }
 
   public final class Fact {
+    method public static androidx.kruth.Fact fact(String key);
     method public static androidx.kruth.Fact fact(String key, optional Object? value);
     method public String getKey();
     method public String? getValue();
@@ -48,16 +49,34 @@
   }
 
   public static final class Fact.Companion {
+    method public androidx.kruth.Fact fact(String key);
     method public androidx.kruth.Fact fact(String key, optional Object? value);
     method public String makeMessage(java.util.List<java.lang.String> messages, java.util.List<androidx.kruth.Fact> facts);
     method public androidx.kruth.Fact simpleFact(String key);
   }
 
   public final class FailureMetadata {
-    method public java.util.List<java.lang.String> component1();
-    method public androidx.kruth.FailureMetadata copy(java.util.List<java.lang.String> messagesToPrepend);
+    method public androidx.kruth.FailureStrategy component1();
+    method public java.util.List<java.lang.String> component2();
+    method public androidx.kruth.FailureMetadata copy(androidx.kruth.FailureStrategy failureStrategy, java.util.List<java.lang.String> messagesToPrepend);
+    method public static androidx.kruth.FailureMetadata forFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
+    method public androidx.kruth.FailureStrategy getFailureStrategy();
     method public java.util.List<java.lang.String> getMessagesToPrepend();
+    property public final androidx.kruth.FailureStrategy failureStrategy;
     property public final java.util.List<java.lang.String> messagesToPrepend;
+    field public static final androidx.kruth.FailureMetadata.Companion Companion;
+  }
+
+  public static final class FailureMetadata.Companion {
+    method public androidx.kruth.FailureMetadata forFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
+  }
+
+  public fun interface FailureStrategy {
+    method public Void fail(Error failure);
+  }
+
+  public class IntegerSubject extends androidx.kruth.ComparableSubject<java.lang.Integer> {
+    method @Deprecated public void isEquivalentAccordingToCompareTo(Integer? other);
   }
 
   public class IterableSubject<T> extends androidx.kruth.Subject<java.lang.Iterable<? extends T>> {
@@ -96,6 +115,7 @@
     method public static <S extends androidx.kruth.Subject<? extends T>, T> androidx.kruth.SimpleSubjectBuilder<S,T> assertAbout(androidx.kruth.Subject.Factory<? extends S,T> subjectFactory);
     method public static androidx.kruth.BooleanSubject assertThat(Boolean? actual);
     method public static androidx.kruth.DoubleSubject assertThat(Double? actual);
+    method public static androidx.kruth.IntegerSubject assertThat(Integer? actual);
     method public static <T> androidx.kruth.IterableSubject<T> assertThat(Iterable<? extends T>? actual);
     method public static androidx.kruth.StringSubject assertThat(String? actual);
     method public static <K, V> androidx.kruth.MapSubject<K,V> assertThat(java.util.Map<K,? extends V>? actual);
@@ -127,6 +147,7 @@
   public final class StandardSubjectBuilder {
     method public <T, S extends androidx.kruth.Subject<? extends T>> androidx.kruth.SimpleSubjectBuilder<S,T> about(androidx.kruth.Subject.Factory<? extends S,T> subjectFactory);
     method public Void fail();
+    method public static androidx.kruth.StandardSubjectBuilder? forCustomFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
     method public androidx.kruth.BooleanSubject that(Boolean? actual);
     method public androidx.kruth.DoubleSubject that(Double? actual);
     method public <T> androidx.kruth.IterableSubject<T> that(Iterable<? extends T>? actual);
@@ -136,6 +157,11 @@
     method public <T extends java.lang.Comparable<? super T>> androidx.kruth.ComparableSubject<T> that(T? actual);
     method public <T extends java.lang.Throwable> androidx.kruth.ThrowableSubject<T> that(T? actual);
     method public androidx.kruth.StandardSubjectBuilder withMessage(String messageToPrepend);
+    field public static final androidx.kruth.StandardSubjectBuilder.Companion Companion;
+  }
+
+  public static final class StandardSubjectBuilder.Companion {
+    method public androidx.kruth.StandardSubjectBuilder? forCustomFailureStrategy(androidx.kruth.FailureStrategy failureStrategy);
   }
 
   public final class StringSubject extends androidx.kruth.ComparableSubject<java.lang.String> {
@@ -161,8 +187,13 @@
     method protected final androidx.kruth.StandardSubjectBuilder check();
     method @kotlin.PublishedApi internal final void doFail(String message);
     method protected final Void failWithActual(androidx.kruth.Fact... facts);
+    method protected final Void failWithActual(String key);
+    method protected final Void failWithActual(String key, optional Object? value);
     method protected final Void failWithoutActual(androidx.kruth.Fact... facts);
+    method protected final Void failWithoutActual(String key);
+    method protected final Void failWithoutActual(String key, optional Object? value);
     method public final T? getActual();
+    method public final androidx.kruth.FailureMetadata getMetadata();
     method public void isAnyOf(Object? first, Object? second, java.lang.Object?... rest);
     method public void isEqualTo(Object? expected);
     method public void isIn(Iterable<?>? iterable);
@@ -176,6 +207,7 @@
     method public void isNull();
     method public void isSameInstanceAs(Object? expected);
     property public final T? actual;
+    property public final androidx.kruth.FailureMetadata metadata;
   }
 
   public static fun interface Subject.Factory<SubjectT extends androidx.kruth.Subject<? extends ActualT>, ActualT> {
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/BooleanSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/BooleanSubject.kt
index 7352c54..db66115 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/BooleanSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/BooleanSubject.kt
@@ -28,7 +28,7 @@
      * Fails if the subject is false or `null`.
      */
     fun isFalse() {
-        asserter.assertTrue(
+        metadata.assertTrue(
             actual == false,
             "expected to be false, but was $actual"
         )
@@ -38,7 +38,7 @@
      * Fails if the subject is true or `null`.
      */
     fun isTrue() {
-        asserter.assertTrue(
+        metadata.assertTrue(
             actual == true,
             "expected to be true, but was $actual"
         )
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ComparableSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ComparableSubject.kt
index f456f03..71cb36a 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ComparableSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ComparableSubject.kt
@@ -27,20 +27,18 @@
 ) : Subject<T>(actual = actual, metadata = metadata) {
 
     /**
-     * Checks that the subject is equivalent to [expected] according to [Comparable.compareTo],
+     * Checks that the subject is equivalent to [other] according to [Comparable.compareTo],
      * (i.e., checks that `a.comparesTo(b) == 0`).
      *
      * **Note:** Do not use this method for checking object equality. Instead, use [isEqualTo].
      */
-    fun isEquivalentAccordingToCompareTo(expected: T?) {
+    open fun isEquivalentAccordingToCompareTo(other: T?) {
         requireNonNull(actual)
-        requireNonNull(expected)
+        requireNonNull(other)
 
-        asserter(withActual = true).assertEquals(
-            expected = 0,
-            actual = actual.compareTo(expected),
-            message = "Expected value that sorts equal to: $expected",
-        )
+        if (actual.compareTo(other) != 0) {
+            failWithActual("Expected value that sorts equal to", other)
+        }
     }
 
     /**
@@ -52,10 +50,9 @@
         requireNonNull(actual)
         requireNonNull(other)
 
-        asserter(withActual = true).assertTrue(
-            actual > other,
-            message = "Expected to be greater than: $other",
-        )
+        if (actual <= other) {
+            failWithActual("Expected to be greater than", other)
+        }
     }
 
     /**
@@ -68,7 +65,7 @@
         requireNonNull(other) { "Expected to be less than $other, but was $actual" }
 
         if (actual >= other) {
-            asserter.fail("Expected to be less than $other, but was $actual")
+            failWithActual("Expected to be less than", other)
         }
     }
 
@@ -81,7 +78,7 @@
         requireNonNull(actual) { "Expected to be at most $other, but was $actual" }
         requireNonNull(other) { "Expected to be at most $other, but was $actual" }
         if (actual > other) {
-            asserter.fail("Expected to be at most $other, but was $actual")
+            failWithActual("Expected to be at most", other)
         }
     }
 
@@ -94,7 +91,7 @@
         requireNonNull(actual) { "Expected to be at least $other, but was $actual" }
         requireNonNull(other) { "Expected to be at least $other, but was $actual" }
         if (actual < other) {
-            asserter.fail("Expected to be at least $other, but was $actual")
+            failWithActual("Expected to be at least", other)
         }
     }
 }
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Fact.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Fact.kt
index cdc227b..2b7785a 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Fact.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Fact.kt
@@ -16,6 +16,7 @@
 
 package androidx.kruth
 
+import kotlin.jvm.JvmOverloads
 import kotlin.jvm.JvmStatic
 import kotlin.text.padEnd
 import kotlin.text.prependIndent
@@ -31,6 +32,7 @@
          * value." The value is converted to a string by calling [toString] on it.
          */
         @JvmStatic
+        @JvmOverloads
         fun fact(key: String, value: Any? = null): Fact {
             return Fact(key, value.toString())
         }
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailingOrdered.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailingOrdered.kt
index 3ba1a75..593e3cb 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailingOrdered.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailingOrdered.kt
@@ -20,11 +20,11 @@
  * Always fails with the provided error message.
  */
 internal class FailingOrdered(
-    private val asserter: KruthAsserter,
+    private val metadata: FailureMetadata,
     private val message: () -> String,
 ) : Ordered {
 
     override fun inOrder() {
-        asserter.fail(message())
+        metadata.fail(message())
     }
 }
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureMetadata.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureMetadata.kt
index 5d09c3f..d5f9993 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureMetadata.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureMetadata.kt
@@ -16,13 +16,98 @@
 
 package androidx.kruth
 
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.contract
+import kotlin.jvm.JvmStatic
+
+@OptIn(ExperimentalContracts::class)
 data class FailureMetadata internal constructor(
+    val failureStrategy: FailureStrategy = FailureStrategy { failure -> throw failure },
     val messagesToPrepend: List<String> = emptyList(),
 ) {
+    companion object {
+        @JvmStatic
+        fun forFailureStrategy(failureStrategy: FailureStrategy): FailureMetadata {
+            return FailureMetadata(
+                failureStrategy
+            )
+        }
+    }
+
+    internal fun fail(message: String? = null): Nothing {
+        // TODO: change to AssertionError that takes in a cause when upgraded to 1.9.20
+        failureStrategy.fail(AssertionError(formatMessage(message)))
+    }
 
     internal fun withMessage(messageToPrepend: String): FailureMetadata =
         copy(messagesToPrepend = messagesToPrepend + messageToPrepend)
 
     internal fun formatMessage(vararg messages: String?): String =
         (messagesToPrepend + messages.filterNotNull()).joinToString(separator = "\n")
+
+    /**
+     * Asserts that the specified value is `true`.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun assertTrue(actual: Boolean, message: String? = null) {
+        contract { returns() implies actual }
+
+        if (!actual) {
+            fail(message)
+        }
+    }
+
+    /**
+     * Asserts that the specified value is `false`.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun assertFalse(actual: Boolean, message: String? = null) {
+        contract { returns() implies !actual }
+
+        if (actual) {
+            fail(message)
+        }
+    }
+
+    /**
+     * Asserts that the specified values are equal.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun assertEquals(expected: Any?, actual: Any?, message: String? = null) {
+        assertTrue(expected == actual, message)
+    }
+
+    /**
+     * Asserts that the specified values are not equal.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun assertNotEquals(illegal: Any?, actual: Any?, message: String? = null) {
+        assertFalse(illegal == actual, message)
+    }
+
+    /**
+     * Asserts that the specified value is `null`.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun assertNull(actual: Any?, message: String? = null) {
+        contract { returns() implies (actual == null) }
+        assertTrue(actual == null, message)
+    }
+
+    /**
+     * Asserts that the specified value is not `null`.
+     *
+     * @param message the message to report if the assertion fails.
+     */
+    internal fun <T : Any> assertNotNull(actual: T?, message: String? = null): T {
+        contract { returns() implies (actual != null) }
+        assertFalse(actual == null, message)
+
+        return actual
+    }
 }
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureStrategy.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureStrategy.kt
new file mode 100644
index 0000000..0c5d4af
--- /dev/null
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/FailureStrategy.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2023 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.kruth
+
+/**
+ * Defines what to do when a check fails.
+ *
+ * This type does not appear directly in a fluent assertion chain, but you choose a
+ * [FailureStrategy] by choosing which method to call at the beginning of the chain.
+ *
+ * For people extending Kruth
+ *
+ * Custom [FailureStrategy] implementations are unusual. If you think you need one,
+ * consider these alternatives:
+ *
+ *   To test a custom subject, use [ExpectFailure].
+ *   To create subjects for other objects related to your actual value (for chained assertions),
+ *   use [Subject.check], which preserves the existing [FailureStrategy] and other context.
+ *
+ * When you really do need to create your own strategy, rather than expose your [FailureStrategy]
+ * instance to users, expose a [StandardSubjectBuilder] instance using
+ * [StandardSubjectBuilder.forCustomFailureStrategy].
+ */
+fun interface FailureStrategy {
+    /**
+     * Handles a failure. The parameter is an [AssertionError] or subclass thereof, and it
+     * contains information about the failure, which may include:
+     *
+     *   message: [Throwable.message]
+     *   cause: [Throwable.cause]
+     *
+     * We encourage implementations to record as much of this information as practical in the
+     * exceptions they may throw or the other records they may make.
+     */
+    fun fail(failure: Error): Nothing
+}
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IntegerSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IntegerSubject.kt
new file mode 100644
index 0000000..4fb9236
--- /dev/null
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IntegerSubject.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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.kruth
+
+open class IntegerSubject internal constructor(
+    actual: Int?,
+    metadata: FailureMetadata = FailureMetadata(),
+) : ComparableSubject<Int>(actual = actual, metadata = metadata) {
+    @Deprecated(
+        "Use .isEqualTo instead. Long comparison is consistent with equality.",
+        ReplaceWith("this.isEqualTo(other)")
+    )
+    override fun isEquivalentAccordingToCompareTo(other: Int?) {
+        super.isEquivalentAccordingToCompareTo(other)
+    }
+}
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
index 53662ec..10e4d51 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/IterableSubject.kt
@@ -57,7 +57,7 @@
         requireNonNull(actual) { "Expected to be empty, but was null" }
 
         if (!actual.isEmpty()) {
-            asserter.fail("Expected to be empty")
+            failWithoutActual("Expected to be empty")
         }
     }
 
@@ -66,7 +66,7 @@
         requireNonNull(actual) { "Expected not to be empty, but was null" }
 
         if (actual.isEmpty()) {
-            asserter.fail("Expected to be not empty")
+            failWithoutActual("Expected to be not empty")
         }
     }
 
@@ -75,7 +75,7 @@
         require(expectedSize >= 0) { "expectedSize must be >= 0, but was $expectedSize" }
         requireNonNull(actual) { "Expected to have size $expectedSize, but was null" }
 
-        asserter.assertEquals(expectedSize, actual.count())
+        metadata.assertEquals(expectedSize, actual.count())
     }
 
     /** Checks (with a side-effect failure) that the subject contains the supplied item. */
@@ -85,12 +85,12 @@
         if (element !in actual) {
             val matchingItems = actual.retainMatchingToString(listOf(element))
             if (matchingItems.isNotEmpty()) {
-                asserter.fail(
+                failWithoutActual(
                     "Expected to contain $element, but did not. " +
                         "Though it did contain $matchingItems"
                 )
             } else {
-                asserter.fail("Expected to contain $element, but did not")
+                failWithoutActual("Expected to contain $element, but did not")
             }
         }
     }
@@ -100,7 +100,7 @@
         requireNonNull(actual) { "Expected not to contain $element, but was null" }
 
         if (element in actual) {
-            asserter.fail("Expected not to contain $element")
+            failWithoutActual("Expected not to contain $element")
         }
     }
 
@@ -111,7 +111,7 @@
         val duplicates = actual.groupBy { it }.values.filter { it.size > 1 }
 
         if (duplicates.isNotEmpty()) {
-            asserter.fail("Expected not to contain duplicates, but contained $duplicates")
+            failWithoutActual("Expected not to contain duplicates, but contained $duplicates")
         }
     }
 
@@ -134,12 +134,12 @@
 
         val matchingItems = actual.retainMatchingToString(expected)
         if (matchingItems.isNotEmpty()) {
-            asserter.fail(
+            failWithoutActual(
                 "Expected to contain any of $expected, but did not. " +
                     "Though it did contain $matchingItems"
             )
         } else {
-            asserter.fail("Expected to contain any of $expected, but did not")
+            failWithoutActual("Expected to contain any of $expected, but did not")
         }
     }
 
@@ -192,7 +192,7 @@
         if (missing.isNotEmpty()) {
             val nearMissing = actualList.retainMatchingToString(missing)
 
-            asserter.fail(
+            failWithoutActual(
                 """
                     Expected to contain at least $expected, but did not.
                     Missing $missing, though it did contain $nearMissing.
@@ -204,7 +204,7 @@
             return NoopOrdered
         }
 
-        return FailingOrdered(asserter) {
+        return FailingOrdered(metadata) {
             buildString {
                 append("Required elements were all found, but order was wrong.")
                 append("Expected order: $expected.")
@@ -295,7 +295,7 @@
                      * values had multiple elements. Granted, Fuzzy Truth already does this, so maybe it's OK?
                      * But Fuzzy Truth doesn't (yet) make the mismatched value so prominent.
                      */
-                    asserter.fail(
+                    failWithoutActual(
                         "Expected $actualElement to be equal to $requiredElement, but was not"
                     )
                 }
@@ -330,7 +330,7 @@
                      * so return an object that will fail the test if the user calls inOrder().
                      */
 
-                    return FailingOrdered(asserter) {
+                    return FailingOrdered(metadata) {
                         """
                              Contents match. Expected the order to also match, but was not.
                              Expected: $required.
@@ -339,11 +339,10 @@
                     }
                 }
 
-                asserter.fail(
+                failWithActual(
                     """
                         Contents do not match.
                         Expected: $required.
-                        Actual: $actual.
                         Missing: $missing.
                         Unexpected: $extra.
                     """.trimIndent()
@@ -358,22 +357,20 @@
         // extras. If the required iterator has elements, they're missing elements.
 
         if (actualIter.hasNext()) {
-            asserter.fail(
+            failWithActual(
                 """
                     Contents do not match.
                     Expected: $required.
-                    Actual: $actual.
                     Unexpected: ${actualIter.asSequence().toList()}.
                 """.trimIndent()
             )
         }
 
         if (requiredIter.hasNext()) {
-            asserter.fail(
+            failWithActual(
                 """
                     Contents do not match.
                     Expected: $required.
-                    Actual: $actual.
                     Missing: ${requiredIter.asSequence().toList()}.
                 """.trimIndent()
             )
@@ -421,12 +418,7 @@
         val present = excluded.intersect(actual)
 
         if (present.isNotEmpty()) {
-            asserter.fail(
-                """
-                    Expected not to contain any of $excluded but contained $present.
-                    Actual: $actual.
-                """.trimIndent()
-            )
+            failWithActual("Expected not to contain any of $excluded but contained $present.")
         }
     }
 
@@ -466,12 +458,7 @@
 
         verifyInOrder(
             predicate = { a, b -> cmp.compare(a, b) < 0 },
-            message = { a, b ->
-                """
-                    Expected to be in strict order but contained $a followed by $b.
-                    Actual: $actual.
-                """.trimIndent()
-            }
+            message = { a, b -> "Expected to be in strict order but contained $a followed by $b." }
         )
     }
 
@@ -499,12 +486,7 @@
 
         verifyInOrder(
             predicate = { a, b -> cmp.compare(a, b) <= 0 },
-            message = { a, b ->
-                """
-                    Expected to be in order but contained $a followed by $b.
-                    Actual: $actual.
-                """.trimIndent()
-            }
+            message = { a, b -> "Expected to be in order but contained $a followed by $b." }
         )
     }
 
@@ -517,7 +499,7 @@
             .zipWithNext(::Pair)
             .forEach { (a, b) ->
                 if (!predicate(a, b)) {
-                    asserter.fail(message(a, b))
+                    failWithActual(message(a, b))
                 }
             }
     }
@@ -544,7 +526,7 @@
 
         val nonIterables = iterable.filterNot { it is Iterable<*> }
         if (nonIterables.isNotEmpty()) {
-            asserter.fail(
+            failWithoutActual(
                 "The actual value is an Iterable, and you've written a test that compares it to " +
                     "some objects that are not Iterables. Did you instead mean to check " +
                     "whether its *contents* match any of the *contents* of the given values? " +
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Kruth.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Kruth.kt
index 94b79f1..8d671ac 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Kruth.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Kruth.kt
@@ -40,6 +40,10 @@
     return DoubleSubject(actual)
 }
 
+fun assertThat(actual: Int?): IntegerSubject {
+    return IntegerSubject(actual)
+}
+
 fun assertThat(actual: String?): StringSubject {
     return StringSubject(actual)
 }
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/MapSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/MapSubject.kt
index fa369ff..dda178d 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/MapSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/MapSubject.kt
@@ -26,7 +26,7 @@
         requireNonNull(actual) { "Expected to be empty, but was null" }
 
         if (actual.isNotEmpty()) {
-            asserter.fail("Expected to be empty, but was $actual")
+            metadata.fail("Expected to be empty, but was $actual")
         }
     }
 
@@ -35,7 +35,7 @@
         requireNonNull(actual) { "Expected to be not empty, but was null" }
 
         if (actual.isEmpty()) {
-            asserter.fail("Expected to be not empty, but was $actual")
+            metadata.fail("Expected to be not empty, but was $actual")
         }
     }
 
@@ -43,7 +43,7 @@
     fun hasSize(expectedSize: Int) {
         require(expectedSize >= 0) { "expectedSize must be >= 0, but was $expectedSize" }
         requireNonNull(actual) { "Expected to be empty, but was null" }
-        asserter.assertEquals(expectedSize, actual.size)
+        metadata.assertEquals(expectedSize, actual.size)
     }
 
     /** Fails if the map does not contain the given key. */
@@ -51,7 +51,7 @@
         requireNonNull(actual) { "Expected to contain $key, but was null" }
 
         if (!actual.containsKey(key)) {
-            asserter.fail("Expected to contain $key, but was ${actual.keys}")
+            metadata.fail("Expected to contain $key, but was ${actual.keys}")
         }
     }
 
@@ -116,16 +116,13 @@
         val actualSet = actual.mapTo(HashSet()) { (key, value) -> key to value }
 
         if (allowUnexpected) {
-            asserter(withActual = true).assertTrue(
-                actual = actualSet.containsAll(expectedSet),
-                message = "Expected to contain at least: $expectedMap",
-            )
+            if (!actualSet.containsAll(expectedSet)) {
+                failWithActual("Expected to contain at least", expectedSet)
+            }
         } else {
-            asserter(withActual = true).assertEquals(
-                expected = expectedSet,
-                actual = actualSet,
-                message = "Expected: $expectedMap",
-            )
+            if (expectedSet != actualSet) {
+                failWithActual("Expected", expectedMap)
+            }
         }
     }
 
@@ -157,7 +154,7 @@
             val commonFromExpected = expectedMap.keys.intersect(actual.keys).toList()
             val commonFromActual = actual.keys.intersect(expectedMap.keys).toList()
 
-            asserter.assertEquals(
+            metadata.assertEquals(
                 commonFromExpected,
                 commonFromActual,
                 buildString {
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StandardSubjectBuilder.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StandardSubjectBuilder.kt
index dbc50ef..8f24a7c 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StandardSubjectBuilder.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StandardSubjectBuilder.kt
@@ -16,6 +16,8 @@
 
 package androidx.kruth
 
+import kotlin.jvm.JvmStatic
+
 /**
  * In a fluent assertion chain, an object with which you can do any of the following:
  *
@@ -26,6 +28,15 @@
 class StandardSubjectBuilder internal constructor(
     private val metadata: FailureMetadata = FailureMetadata(),
 ) {
+    companion object {
+        /**
+         * Returns a new instance that invokes the given [FailureStrategy] when a check fails.
+         */
+        @JvmStatic
+        fun forCustomFailureStrategy(failureStrategy: FailureStrategy): StandardSubjectBuilder? {
+            return StandardSubjectBuilder(FailureMetadata.forFailureStrategy(failureStrategy))
+        }
+    }
 
     /**
      * Returns a new instance that will output the given message before the main failure message. If
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StringSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StringSubject.kt
index dd3e03a..d43cada 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StringSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/StringSubject.kt
@@ -28,9 +28,9 @@
      * Fails if the string does not contain the given sequence.
      */
     fun contains(charSequence: CharSequence) {
-        asserter.assertNotNull(actual)
+        metadata.assertNotNull(actual)
 
-        asserter.assertTrue(
+        metadata.assertTrue(
             message = "Expected to contain \"$charSequence\", but was: \"$actual\"",
             actual = actual.contains(charSequence),
         )
@@ -38,9 +38,9 @@
 
     /** Fails if the string does not have the given length.  */
     fun hasLength(expectedLength: Int) {
-        asserter.assertNotNull(actual)
+        metadata.assertNotNull(actual)
 
-        asserter.assertTrue(
+        metadata.assertTrue(
             message = "Expected to have length $expectedLength, but was: \"$actual\"",
             actual = actual.length == expectedLength,
         )
@@ -48,9 +48,9 @@
 
     /** Fails if the string is not equal to the zero-length "empty string."  */
     fun isEmpty() {
-        asserter.assertNotNull(actual)
+        metadata.assertNotNull(actual)
         if (actual.isNotEmpty()) {
-            asserter.fail(
+            metadata.fail(
                 """
                     expected to be empty
                     | but was $actual
@@ -61,18 +61,18 @@
 
     /** Fails if the string is equal to the zero-length "empty string."  */
     fun isNotEmpty() {
-        asserter.assertNotNull(actual)
+        metadata.assertNotNull(actual)
         if (actual.isEmpty()) {
-            asserter.fail("expected not to be empty")
+            metadata.fail("expected not to be empty")
         }
     }
 
     /** Fails if the string contains the given sequence.  */
     fun doesNotContain(string: CharSequence) {
-        asserter.assertNotNull(actual, "expected a string that does not contain $string")
+        metadata.assertNotNull(actual, "expected a string that does not contain $string")
 
         if (actual.contains(string)) {
-            asserter.fail(
+            metadata.fail(
                 """
                     expected not to contain $string
                     | but was $actual
@@ -83,10 +83,10 @@
 
     /** Fails if the string does not start with the given string.  */
     fun startsWith(string: String) {
-        asserter.assertNotNull(actual, "expected a string that starts with $string")
+        metadata.assertNotNull(actual, "expected a string that starts with $string")
 
         if (!actual.startsWith(string)) {
-            asserter.fail(
+            metadata.fail(
                 """
                     expected to start with $string
                     | but was $actual
@@ -97,10 +97,10 @@
 
     /** Fails if the string does not end with the given string.  */
     fun endsWith(string: String) {
-        asserter.assertNotNull(actual, "expected a string that ends with $string")
+        metadata.assertNotNull(actual, "expected a string that ends with $string")
 
         if (!actual.endsWith(string)) {
-            asserter.fail(
+            metadata.fail(
                 """
                     expected to end with $string
                     | but was $actual
@@ -132,17 +132,17 @@
         fun isEqualTo(expected: String?) {
             when {
                 (actual == null) && (expected != null) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string equal to \"$expected\" (case is ignored), but was null"
                     )
 
                 (expected == null) && (actual != null) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string that is null (null reference), but was \"$actual\""
                     )
 
                 !actual.equals(expected, ignoreCase = true) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string equal to \"$expected\" (case is ignored), " +
                             "but was \"$actual\""
                     )
@@ -156,12 +156,12 @@
         fun isNotEqualTo(unexpected: String?) {
             when {
                 (actual == null) && (unexpected == null) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string not equal to null (null reference), but it was null"
                     )
 
                 actual.equals(unexpected, ignoreCase = true) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string not equal to \"$unexpected\" (case is ignored), " +
                             "but it was equal. Actual string: \"$actual\"."
                     )
@@ -174,13 +174,13 @@
 
             when {
                 actual == null ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string that contains \"$expected\" (case is ignored), " +
                             "but was null"
                     )
 
                 !actual.contains(expected, ignoreCase = true) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected to contain \"$expected\" (case is ignored), but was \"$actual\""
                     )
             }
@@ -192,13 +192,13 @@
 
             when {
                 actual == null ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string that does not contain \"$expected\" " +
                             "(case is ignored), but was null"
                     )
 
                 actual.contains(expected, ignoreCase = true) ->
-                    asserter.fail(
+                    metadata.fail(
                         "Expected a string that does not contain \"$expected\" " +
                             "(case is ignored), but it was. Actual string: \"$actual\"."
                     )
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Subject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Subject.kt
index c2ac5a1..654cb19 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Subject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/Subject.kt
@@ -16,6 +16,7 @@
 
 package androidx.kruth
 
+import kotlin.jvm.JvmOverloads
 import kotlin.reflect.typeOf
 
 // As opposed to Truth, which limits visibility on `actual` and the generic type, we purposely make
@@ -30,36 +31,11 @@
  */
 open class Subject<out T>(
     val actual: T?,
-    private val metadata: FailureMetadata = FailureMetadata(),
+    val metadata: FailureMetadata = FailureMetadata(),
 ) {
 
     protected fun check(): StandardSubjectBuilder = StandardSubjectBuilder(metadata = metadata)
 
-    internal val asserter: KruthAsserter get() = asserter()
-
-    internal fun asserter(withActual: Boolean = false): KruthAsserter =
-        KruthAsserter(
-            formatMessage = { message ->
-                formatFailureMessage(message = message, withActual = withActual)
-            },
-        )
-
-    private fun formatFailureMessage(message: String?, withActual: Boolean): String =
-        if (withActual) {
-            val actualString = actual.toString()
-            if ('\n' in actualString) {
-                metadata.formatMessage(
-                    message,
-                    "But was:",
-                    actual.toString().prependIndent(),
-                )
-            } else {
-                metadata.formatMessage(message, "But was: $actualString")
-            }
-        } else {
-            metadata.formatMessage(message)
-        }
-
     /**
      *  Fails if the subject is not null.
      */
@@ -109,7 +85,7 @@
     /** Fails if the subject is not the same instance as the given object.  */
     open fun isSameInstanceAs(expected: Any?) {
         if (actual !== expected) {
-            asserter.fail(
+            metadata.fail(
                 "Expected ${actual.toStringForAssert()} to be the same instance as " +
                     "${expected.toStringForAssert()}, but was not"
             )
@@ -119,7 +95,7 @@
     /** Fails if the subject is the same instance as the given object.  */
     open fun isNotSameInstanceAs(unexpected: Any?) {
         if (actual === unexpected) {
-            asserter.fail(
+            metadata.fail(
                 "Expected ${actual.toStringForAssert()} not to be specific instance, but it was"
             )
         }
@@ -143,17 +119,27 @@
         }
     }
 
+    @JvmOverloads
+    protected fun failWithActual(key: String, value: Any? = null): Nothing {
+        failWithActual(Fact.fact(key, value))
+    }
+
     protected fun failWithActual(vararg facts: Fact): Nothing {
-        asserter(withActual = true).fail(
+        metadata.fail(
             Fact.makeMessage(
                 emptyList(),
-                facts.asList(),
+                facts.asList() + Fact.fact("but was", actual.toString()),
                 )
         )
     }
 
+    @JvmOverloads
+    protected fun failWithoutActual(key: String, value: Any? = null): Nothing {
+        failWithoutActual(Fact.fact(key, value))
+    }
+
     protected fun failWithoutActual(vararg facts: Fact): Nothing {
-        asserter(withActual = false).fail(
+        metadata.fail(
             Fact.makeMessage(
                 emptyList(),
                 facts.asList(),
@@ -163,13 +149,13 @@
 
     @PublishedApi
     internal fun doFail(message: String) {
-        asserter.fail(message = message)
+        metadata.fail(message = message)
     }
 
     /** Fails unless the subject is equal to any element in the given [iterable]. */
     open fun isIn(iterable: Iterable<*>?) {
         if (actual !in requireNonNull(iterable)) {
-            asserter.fail("Expected $actual to be in $iterable, but was not")
+            metadata.fail("Expected $actual to be in $iterable, but was not")
         }
     }
 
@@ -181,7 +167,7 @@
     /** Fails if the subject is equal to any element in the given [iterable]. */
     open fun isNotIn(iterable: Iterable<*>?) {
         if (actual in requireNonNull(iterable)) {
-            asserter.fail("Expected $actual not to be in $iterable, but it was")
+            metadata.fail("Expected $actual not to be in $iterable, but it was")
         }
     }
 
@@ -191,14 +177,14 @@
     }
 
     private fun Any?.standardIsEqualTo(expected: Any?) {
-        asserter.assertTrue(
+        metadata.assertTrue(
             compareForEquality(expected),
             "expected: ${expected.toStringForAssert()} but was: ${toStringForAssert()}",
         )
     }
 
     private fun Any?.standardIsNotEqualTo(unexpected: Any?) {
-        asserter.assertFalse(
+        metadata.assertFalse(
             compareForEquality(unexpected),
             "expected ${toStringForAssert()} not be equal to ${unexpected.toStringForAssert()}, " +
                 "but it was",
@@ -246,7 +232,7 @@
     private fun Any?.integralValue(): Long = when (this) {
         is Char -> code.toLong()
         is Number -> toLong()
-        else -> asserter.fail("$this must be either a Char or a Number.")
+        else -> metadata.fail("$this must be either a Char or a Number.")
     }
 
     private fun Any?.toStringForAssert(): String = when {
diff --git a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ThrowableSubject.kt b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ThrowableSubject.kt
index a7d06c1..c0d1a05 100644
--- a/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ThrowableSubject.kt
+++ b/kruth/kruth/src/commonMain/kotlin/androidx/kruth/ThrowableSubject.kt
@@ -21,7 +21,7 @@
  */
 class ThrowableSubject<out T : Throwable> internal constructor(
     actual: T?,
-    private val metadata: FailureMetadata = FailureMetadata(),
+    metadata: FailureMetadata = FailureMetadata(),
 ) : Subject<T>(actual = actual, metadata = metadata) {
 
     /**
@@ -38,7 +38,7 @@
      */
     fun hasCauseThat(): ThrowableSubject<Throwable> {
         if (actual == null) {
-            asserter.fail("Causal chain is not deep enough - add a .isNotNull() check?")
+            metadata.fail("Causal chain is not deep enough - add a .isNotNull() check?")
         }
 
         return ThrowableSubject(actual = actual.cause, metadata = metadata)
diff --git a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ChainingTest.kt b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ChainingTest.kt
index 661ab55..a7971fd 100644
--- a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ChainingTest.kt
+++ b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ChainingTest.kt
@@ -18,8 +18,10 @@
 
 import kotlin.test.Test
 import kotlin.test.assertFailsWith
+import kotlin.test.asserter
 
 class ChainingTest {
+
     @Test
     fun singleChain() {
         assertFailsWith<AssertionError> {
diff --git a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ComparableSubjectTest.kt b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ComparableSubjectTest.kt
index 4e58b3f..9f800da 100644
--- a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ComparableSubjectTest.kt
+++ b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/ComparableSubjectTest.kt
@@ -30,6 +30,7 @@
  */
 class ComparableSubjectTest {
 
+    @Suppress("DEPRECATION") // Testing a deprecated method
     @Test
     fun testNulls() {
         assertFailsWith<NullPointerException> {
diff --git a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/FactTest.kt b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/FactTest.kt
index 47f5f04..5703d64 100644
--- a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/FactTest.kt
+++ b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/FactTest.kt
@@ -110,6 +110,48 @@
     }
 
     @Test
+    fun failWithActual_simpleFact() {
+        val subject =
+            object : Subject<Int>(
+                actual = 0,
+            ) {
+                fun fail() {
+                    failWithActual(simpleFact("Expected something else"))
+                }
+            }
+
+        assertFailsWithMessage(
+            """
+                Expected something else
+                but was: 0
+            """.trimIndent()
+        ) { subject.fail() }
+    }
+
+    @Test
+    fun failWithActual_multipleFacts() {
+        val subject =
+            object : Subject<Int>(
+                actual = 0,
+            ) {
+                fun fail() {
+                    failWithActual(
+                        simpleFact("Expected something else"),
+                        fact("expected", "1"),
+                    )
+                }
+            }
+
+        assertFailsWithMessage(
+            """
+                Expected something else
+                expected: 1
+                but was : 0
+            """.trimIndent()
+        ) { subject.fail() }
+    }
+
+    @Test
     fun failWithoutActual_simpleFact() {
         val subject =
             object : Subject<Int>(
diff --git a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/IntegerSubjectTest.kt b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/IntegerSubjectTest.kt
new file mode 100644
index 0000000..f94d149
--- /dev/null
+++ b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/IntegerSubjectTest.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2023 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.kruth
+
+import kotlin.test.Test
+import kotlin.test.assertFailsWith
+
+class IntegerSubjectTest {
+    @Test
+    fun simpleEquality() {
+        assertThat(4).isEqualTo(4)
+    }
+
+    @Test
+    fun simpleInequality() {
+        assertThat(4).isNotEqualTo(5)
+    }
+
+    @Test
+    fun equalityWithLongs() {
+        assertThat(0).isEqualTo(0L)
+        assertFailsWith<AssertionError> {
+            assertThat(0).isNotEqualTo(0L)
+        }
+    }
+
+    @Test
+    fun equalityFail() {
+        assertFailsWith<AssertionError> {
+            assertThat(4).isEqualTo(5)
+        }
+    }
+
+    @Test
+    fun inequalityFail() {
+        assertFailsWith<AssertionError> {
+            assertThat(4).isNotEqualTo(4)
+        }
+    }
+
+    @Test
+    fun equalityOfNulls() {
+        assertThat(null as Int?).isEqualTo(null)
+    }
+
+    @Test
+    fun equalityOfNullsFail_nullExpected() {
+        assertFailsWith<AssertionError> {
+            assertThat(5).isEqualTo(null)
+        }
+    }
+
+    @Test
+    fun inequalityOfNulls() {
+        assertThat(4).isNotEqualTo(null)
+        assertThat(null as Int?).isNotEqualTo(4)
+    }
+
+    @Test
+    fun overflowOnPrimitives() {
+        assertThat(Long.MIN_VALUE).isNotEqualTo(Int.MIN_VALUE)
+        assertThat(Long.MAX_VALUE).isNotEqualTo(Int.MAX_VALUE)
+        assertThat(Int.MIN_VALUE).isNotEqualTo(Long.MIN_VALUE)
+        assertThat(Int.MAX_VALUE).isNotEqualTo(Long.MAX_VALUE)
+        assertThat(Int.MIN_VALUE).isEqualTo(Int.MIN_VALUE.toLong())
+        assertThat(Int.MAX_VALUE).isEqualTo(Int.MAX_VALUE.toLong())
+    }
+
+    @Test
+    fun overflowOnPrimitives_shouldBeEqualAfterCast_min() {
+        assertFailsWith<AssertionError> {
+            assertThat(Int.MIN_VALUE).isNotEqualTo(Int.MIN_VALUE.toLong())
+        }
+    }
+
+    @Test
+    fun overflowOnPrimitives_shouldBeEqualAfterCast_max() {
+        assertFailsWith<AssertionError> {
+            assertThat(Int.MAX_VALUE).isNotEqualTo(Int.MAX_VALUE.toLong())
+        }
+    }
+
+    @Test
+    fun overflowBetweenIntegerAndLong_shouldBeDifferent_min() {
+        assertFailsWith<AssertionError> {
+            assertThat(Int.MIN_VALUE).isEqualTo(Long.MIN_VALUE)
+        }
+    }
+
+    @Test
+    fun overflowBetweenIntegerAndLong_shouldBeDifferent_max() {
+        assertFailsWith<AssertionError> {
+            assertThat(Int.MAX_VALUE).isEqualTo(Long.MAX_VALUE)
+        }
+    }
+
+    @Test
+    fun testAllCombinations_pass() {
+        assertThat(42).isEqualTo(42L)
+        assertThat(42L).isEqualTo(42)
+    }
+
+    @Test
+    fun testNumericTypeWithSameValue_shouldBeEqual_int_long() {
+        assertFailsWith<AssertionError> {
+            assertThat(42).isNotEqualTo(42L)
+        }
+    }
+
+    @Test
+    fun testNumericTypeWithSameValue_shouldBeEqual_int_int() {
+        assertFailsWith<AssertionError> {
+            assertThat(42).isNotEqualTo(42)
+        }
+    }
+
+    @Test
+    fun testNumericPrimitiveTypes_isNotEqual_shouldFail_intToChar() {
+        assertFailsWith<AssertionError> {
+            assertThat(42).isNotEqualTo(42.toChar())
+        }
+    }
+
+    @Test
+    fun testNumericPrimitiveTypes_isNotEqual_shouldFail_charToInt() {
+        // Uses Object overload rather than Integer.
+        assertFailsWith<AssertionError> {
+            assertThat(42.toChar()).isNotEqualTo(42)
+        }
+    }
+}
diff --git a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
index e133d634..569d382 100644
--- a/kruth/kruth/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
+++ b/kruth/kruth/src/commonTest/kotlin/androidx/kruth/SubjectTest.kt
@@ -716,7 +716,7 @@
                 msg2
                 msg3
                 msg4
-                But was: 0
+                but was: 0
             """.trimIndent()
         ) { subject.fail() }
     }
@@ -739,7 +739,7 @@
                 msg2
                 msg3
                 msg4
-                But was:
+                but was:
                     a
                     b
             """.trimIndent()
diff --git a/leanback/leanback/api/current.txt b/leanback/leanback/api/current.txt
index 91aec39..6712e06 100644
--- a/leanback/leanback/api/current.txt
+++ b/leanback/leanback/api/current.txt
@@ -1898,7 +1898,7 @@
     method public static androidx.leanback.widget.GuidedActionDiffCallback getInstance();
   }
 
-  public class GuidedActionEditText extends android.widget.EditText implements androidx.leanback.widget.GuidedActionAutofillSupport androidx.leanback.widget.ImeKeyMonitor {
+  public class GuidedActionEditText extends androidx.appcompat.widget.AppCompatEditText implements androidx.leanback.widget.GuidedActionAutofillSupport androidx.leanback.widget.ImeKeyMonitor {
     ctor public GuidedActionEditText(android.content.Context!);
     ctor public GuidedActionEditText(android.content.Context!, android.util.AttributeSet!);
     ctor public GuidedActionEditText(android.content.Context!, android.util.AttributeSet!, int);
diff --git a/leanback/leanback/api/restricted_current.txt b/leanback/leanback/api/restricted_current.txt
index 317fbfd..7c962a9e 100644
--- a/leanback/leanback/api/restricted_current.txt
+++ b/leanback/leanback/api/restricted_current.txt
@@ -2105,7 +2105,7 @@
     method public static androidx.leanback.widget.GuidedActionDiffCallback getInstance();
   }
 
-  public class GuidedActionEditText extends android.widget.EditText implements androidx.leanback.widget.GuidedActionAutofillSupport androidx.leanback.widget.ImeKeyMonitor {
+  public class GuidedActionEditText extends androidx.appcompat.widget.AppCompatEditText implements androidx.leanback.widget.GuidedActionAutofillSupport androidx.leanback.widget.ImeKeyMonitor {
     ctor public GuidedActionEditText(android.content.Context!);
     ctor public GuidedActionEditText(android.content.Context!, android.util.AttributeSet!);
     ctor public GuidedActionEditText(android.content.Context!, android.util.AttributeSet!, int);
diff --git a/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java b/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
index 4ede5d5..d572683 100644
--- a/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
+++ b/leanback/leanback/src/androidTest/java/androidx/leanback/widget/GridWidgetTest.java
@@ -2521,6 +2521,7 @@
         verifyBeginAligned();
     }
 
+    @Ignore("b/283480313")
     @Test
     public void testSetSelectedPositionDetached() throws Throwable {
 
diff --git a/leanback/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java b/leanback/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
index f5272f6..4020298 100644
--- a/leanback/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
+++ b/leanback/leanback/src/main/java/androidx/leanback/widget/GuidedActionEditText.java
@@ -26,18 +26,17 @@
 import android.view.MotionEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.autofill.AutofillValue;
-import android.widget.EditText;
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
+import androidx.appcompat.widget.AppCompatEditText;
 import androidx.core.widget.TextViewCompat;
 
 /**
  * A custom EditText that satisfies the IME key monitoring requirements of GuidedStepFragment.
  */
-@SuppressLint("AppCompatCustomView")
-public class GuidedActionEditText extends EditText implements ImeKeyMonitor,
+public class GuidedActionEditText extends AppCompatEditText implements ImeKeyMonitor,
         GuidedActionAutofillSupport {
 
     /**
@@ -109,7 +108,8 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        info.setClassName(isFocused() ? EditText.class.getName() : TextView.class.getName());
+        info.setClassName(isFocused() ?
+                AppCompatEditText.class.getName() : TextView.class.getName());
     }
 
     @Override
diff --git a/leanback/leanback/src/main/res/layout/lb_guidedstep_fragment.xml b/leanback/leanback/src/main/res/layout/lb_guidedstep_fragment.xml
index 766dbcc..9363a4d 100644
--- a/leanback/leanback/src/main/res/layout/lb_guidedstep_fragment.xml
+++ b/leanback/leanback/src/main/res/layout/lb_guidedstep_fragment.xml
@@ -52,7 +52,7 @@
                 android:orientation="horizontal"
                 android:clipToPadding="false"
                 android:clipChildren="false"
-                android:paddingStart="@dimen/lb_guidedactions_section_shadow_width"
+                android:paddingStart="?attr/guidedActionsShadowWidth"
                 android:layout_width="0dp"
                 android:layout_weight="?attr/guidedActionContentWidthWeight"
                 android:layout_height="match_parent" >
diff --git a/leanback/leanback/src/main/res/values/attrs.xml b/leanback/leanback/src/main/res/values/attrs.xml
index 0fc08a4..129cda8 100644
--- a/leanback/leanback/src/main/res/values/attrs.xml
+++ b/leanback/leanback/src/main/res/values/attrs.xml
@@ -375,6 +375,9 @@
              {@link androidx.leanback.R.dimen#lb_guidedactions_elevation}.-->
         <attr name="guidedActionsElevation" format="dimension|reference" />
 
+        <!-- Theme attribute for the left padding for showing shadow of GuidedActions. -->
+        <attr name="guidedActionsShadowWidth" format="dimension|reference" />
+
         <!-- Theme attribute for the background of GuidedActions. Default is
              {@link androidx.leanback.R.color#lb_guidedactions_background}.-->
         <attr name="guidedActionsBackground" format="reference" />
diff --git a/leanback/leanback/src/main/res/values/themes.xml b/leanback/leanback/src/main/res/values/themes.xml
index 8f9597a..2d564df 100644
--- a/leanback/leanback/src/main/res/values/themes.xml
+++ b/leanback/leanback/src/main/res/values/themes.xml
@@ -153,6 +153,7 @@
         <item name="guidanceDescriptionStyle">@style/Widget.Leanback.GuidanceDescriptionStyle</item>
 
         <item name="guidedActionsElevation">@dimen/lb_guidedactions_elevation</item>
+        <item name="guidedActionsShadowWidth">@dimen/lb_guidedactions_section_shadow_width</item>
         <item name="guidedActionsBackground">@color/lb_guidedactions_background</item>
         <item name="guidedActionsBackgroundDark">@color/lb_guidedactions_background_dark</item>
         <item name="guidedActionsListStyle">@style/Widget.Leanback.GuidedActionsListStyle</item>
diff --git a/leanback/leanback/src/main/res/values/themes_appcompat.xml b/leanback/leanback/src/main/res/values/themes_appcompat.xml
index b46e53c..f427184 100644
--- a/leanback/leanback/src/main/res/values/themes_appcompat.xml
+++ b/leanback/leanback/src/main/res/values/themes_appcompat.xml
@@ -157,6 +157,7 @@
         <item name="guidanceDescriptionStyle">@style/Widget.Leanback.GuidanceDescriptionStyle</item>
 
         <item name="guidedActionsElevation">@dimen/lb_guidedactions_elevation</item>
+        <item name="guidedActionsShadowWidth">@dimen/lb_guidedactions_section_shadow_width</item>
         <item name="guidedActionsBackground">@color/lb_guidedactions_background</item>
         <item name="guidedActionsBackgroundDark">@color/lb_guidedactions_background_dark</item>
         <item name="guidedActionsListStyle">@style/Widget.Leanback.GuidedActionsListStyle</item>
diff --git a/libraryversions.toml b/libraryversions.toml
index 3a94f1b..0119dd1 100644
--- a/libraryversions.toml
+++ b/libraryversions.toml
@@ -20,8 +20,8 @@
 CAR_APP = "1.4.0-beta02"
 COLLECTION = "1.4.0-alpha01"
 COMPOSE = "1.6.0-alpha04"
-COMPOSE_COMPILER = "1.5.2"
-COMPOSE_MATERIAL3 = "1.2.0-alpha06"
+COMPOSE_COMPILER = "1.5.3"
+COMPOSE_MATERIAL3 = "1.2.0-alpha07"
 COMPOSE_MATERIAL3_ADAPTIVE = "1.0.0-alpha01"
 COMPOSE_RUNTIME_TRACING = "1.0.0-alpha04"
 CONSTRAINTLAYOUT = "2.2.0-alpha13"
@@ -162,7 +162,7 @@
 WINDOW_EXTENSIONS_CORE = "1.1.0-alpha01"
 WINDOW_SIDECAR = "1.0.0-rc01"
 # Do not remove comment
-WORK = "2.9.0-alpha03"
+WORK = "2.9.0-beta01"
 
 [groups]
 ACTIVITY = { group = "androidx.activity", atomicGroupVersion = "versions.ACTIVITY" }
diff --git a/lifecycle/lifecycle-livedata-ktx/api/current.ignore b/lifecycle/lifecycle-livedata-ktx/api/current.ignore
index d7e55f2..01ef7e3 100644
--- a/lifecycle/lifecycle-livedata-ktx/api/current.ignore
+++ b/lifecycle/lifecycle-livedata-ktx/api/current.ignore
@@ -1,3 +1,3 @@
 // Baseline format: 1.0
-InvalidNullConversion: androidx.lifecycle.LiveDataScope#emit(T, kotlin.coroutines.Continuation<? super kotlin.Unit>) parameter #0:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.lifecycle.LiveDataScope.emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit> arg2)
+RemovedPackage: androidx.lifecycle:
+    Removed package androidx.lifecycle
diff --git a/lifecycle/lifecycle-livedata-ktx/api/current.txt b/lifecycle/lifecycle-livedata-ktx/api/current.txt
index d871976..e6f50d0 100644
--- a/lifecycle/lifecycle-livedata-ktx/api/current.txt
+++ b/lifecycle/lifecycle-livedata-ktx/api/current.txt
@@ -1,25 +1 @@
 // Signature format: 4.0
-package androidx.lifecycle {
-
-  public final class CoroutineLiveDataKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, java.time.Duration timeout, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
-    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
-  }
-
-  public final class FlowLiveDataConversions {
-    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context);
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, java.time.Duration timeout);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs);
-  }
-
-  public interface LiveDataScope<T> {
-    method public suspend Object? emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle>);
-    method public T? getLatestValue();
-    property public abstract T? latestValue;
-  }
-
-}
-
diff --git a/lifecycle/lifecycle-livedata-ktx/api/restricted_current.ignore b/lifecycle/lifecycle-livedata-ktx/api/restricted_current.ignore
index d7e55f2..01ef7e3 100644
--- a/lifecycle/lifecycle-livedata-ktx/api/restricted_current.ignore
+++ b/lifecycle/lifecycle-livedata-ktx/api/restricted_current.ignore
@@ -1,3 +1,3 @@
 // Baseline format: 1.0
-InvalidNullConversion: androidx.lifecycle.LiveDataScope#emit(T, kotlin.coroutines.Continuation<? super kotlin.Unit>) parameter #0:
-    Attempted to change parameter from @Nullable to @NonNull: incompatible change for parameter value in androidx.lifecycle.LiveDataScope.emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit> arg2)
+RemovedPackage: androidx.lifecycle:
+    Removed package androidx.lifecycle
diff --git a/lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt b/lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
index d871976..e6f50d0 100644
--- a/lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
+++ b/lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
@@ -1,25 +1 @@
 // Signature format: 4.0
-package androidx.lifecycle {
-
-  public final class CoroutineLiveDataKt {
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, java.time.Duration timeout, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
-    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
-  }
-
-  public final class FlowLiveDataConversions {
-    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context);
-    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, java.time.Duration timeout);
-    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs);
-  }
-
-  public interface LiveDataScope<T> {
-    method public suspend Object? emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle>);
-    method public T? getLatestValue();
-    property public abstract T? latestValue;
-  }
-
-}
-
diff --git a/lifecycle/lifecycle-livedata/api/current.txt b/lifecycle/lifecycle-livedata/api/current.txt
index da5dac9..06cef73 100644
--- a/lifecycle/lifecycle-livedata/api/current.txt
+++ b/lifecycle/lifecycle-livedata/api/current.txt
@@ -1,6 +1,29 @@
 // Signature format: 4.0
 package androidx.lifecycle {
 
+  public final class CoroutineLiveDataKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(java.time.Duration timeout, optional kotlin.coroutines.CoroutineContext context, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(java.time.Duration timeout, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class FlowLiveDataConversions {
+    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, java.time.Duration timeout, optional kotlin.coroutines.CoroutineContext context);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs);
+  }
+
+  public interface LiveDataScope<T> {
+    method public suspend Object? emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle>);
+    method public T? getLatestValue();
+    property public abstract T? latestValue;
+  }
+
   public class MediatorLiveData<T> extends androidx.lifecycle.MutableLiveData<T> {
     ctor public MediatorLiveData();
     ctor public MediatorLiveData(T!);
diff --git a/lifecycle/lifecycle-livedata/api/restricted_current.txt b/lifecycle/lifecycle-livedata/api/restricted_current.txt
index ea55d7e..356d2ef 100644
--- a/lifecycle/lifecycle-livedata/api/restricted_current.txt
+++ b/lifecycle/lifecycle-livedata/api/restricted_current.txt
@@ -10,6 +10,29 @@
     property public androidx.lifecycle.LiveData<T> liveData;
   }
 
+  public final class CoroutineLiveDataKt {
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(java.time.Duration timeout, optional kotlin.coroutines.CoroutineContext context, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> liveData(java.time.Duration timeout, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs, kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+    method public static <T> androidx.lifecycle.LiveData<T> liveData(kotlin.jvm.functions.Function2<? super androidx.lifecycle.LiveDataScope<T>,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block);
+  }
+
+  public final class FlowLiveDataConversions {
+    method public static <T> kotlinx.coroutines.flow.Flow<T> asFlow(androidx.lifecycle.LiveData<T>);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>);
+    method @RequiresApi(android.os.Build.VERSION_CODES.O) public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, java.time.Duration timeout, optional kotlin.coroutines.CoroutineContext context);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context);
+    method public static <T> androidx.lifecycle.LiveData<T> asLiveData(kotlinx.coroutines.flow.Flow<? extends T>, optional kotlin.coroutines.CoroutineContext context, optional long timeoutInMs);
+  }
+
+  public interface LiveDataScope<T> {
+    method public suspend Object? emit(T value, kotlin.coroutines.Continuation<? super kotlin.Unit>);
+    method public suspend Object? emitSource(androidx.lifecycle.LiveData<T> source, kotlin.coroutines.Continuation<? super kotlinx.coroutines.DisposableHandle>);
+    method public T? getLatestValue();
+    property public abstract T? latestValue;
+  }
+
   public class MediatorLiveData<T> extends androidx.lifecycle.MutableLiveData<T> {
     ctor public MediatorLiveData();
     ctor public MediatorLiveData(T!);
diff --git a/lifecycle/lifecycle-livedata/build.gradle b/lifecycle/lifecycle-livedata/build.gradle
index 4a5df9b..8a935bc 100644
--- a/lifecycle/lifecycle-livedata/build.gradle
+++ b/lifecycle/lifecycle-livedata/build.gradle
@@ -24,9 +24,12 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    implementation("androidx.arch.core:core-common:2.2.0")
+    api(libs.kotlinCoroutinesCore)
     api("androidx.arch.core:core-runtime:2.2.0")
     api(project(":lifecycle:lifecycle-livedata-core"))
+    api(project(":lifecycle:lifecycle-livedata-core-ktx"))
+
+    implementation("androidx.arch.core:core-common:2.2.0")
 
     testImplementation(project(":lifecycle:lifecycle-runtime-testing"))
     testImplementation("androidx.arch.core:core-testing:2.2.0")
@@ -34,6 +37,14 @@
     testImplementation(libs.junit)
     testImplementation(libs.mockitoCore4)
     testImplementation(libs.truth)
+
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.kotlinCoroutinesTest)
+    androidTestImplementation(libs.kotlinCoroutinesAndroid)
 }
 
 androidx {
diff --git a/lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt b/lifecycle/lifecycle-livedata/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
similarity index 100%
rename from lifecycle/lifecycle-livedata-ktx/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
rename to lifecycle/lifecycle-livedata/src/androidTest/java/androidx.lifecycle/FlowAsLiveDataIntegrationTest.kt
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
similarity index 99%
rename from lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
rename to lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
index 49a3ef3..1cdc303 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
+++ b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
@@ -351,6 +351,7 @@
  * ([LiveData.hasActiveObservers]. Defaults to [DEFAULT_TIMEOUT].
  * @param block The block to run when the [LiveData] has active observers.
  */
+@JvmOverloads
 public fun <T> liveData(
     context: CoroutineContext = EmptyCoroutineContext,
     timeoutInMs: Long = DEFAULT_TIMEOUT,
@@ -462,9 +463,10 @@
  * @param block The block to run when the [LiveData] has active observers.
  */
 @RequiresApi(Build.VERSION_CODES.O)
+@JvmOverloads
 public fun <T> liveData(
-    context: CoroutineContext = EmptyCoroutineContext,
     timeout: Duration,
+    context: CoroutineContext = EmptyCoroutineContext,
     block: suspend LiveDataScope<T>.() -> Unit
 ): LiveData<T> = CoroutineLiveData(context, Api26Impl.toMillis(timeout), block)
 
diff --git a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/FlowLiveData.kt
similarity index 97%
rename from lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
rename to lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/FlowLiveData.kt
index 3b05ffd..72d3ef7 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/FlowLiveData.kt
+++ b/lifecycle/lifecycle-livedata/src/main/java/androidx/lifecycle/FlowLiveData.kt
@@ -18,6 +18,7 @@
 
 package androidx.lifecycle
 
+import android.annotation.SuppressLint
 import android.os.Build
 import androidx.annotation.RequiresApi
 import androidx.arch.core.executor.ArchTaskExecutor
@@ -83,6 +84,7 @@
 }.also { liveData ->
     val flow = this
     if (flow is StateFlow<T>) {
+        @SuppressLint("RestrictedApi")
         if (ArchTaskExecutor.getInstance().isMainThread) {
             liveData.value = flow.value
         } else {
@@ -154,6 +156,6 @@
  */
 @RequiresApi(Build.VERSION_CODES.O)
 public fun <T> Flow<T>.asLiveData(
-    context: CoroutineContext = EmptyCoroutineContext,
-    timeout: Duration
+    timeout: Duration,
+    context: CoroutineContext = EmptyCoroutineContext
 ): LiveData<T> = asLiveData(context, Api26Impl.toMillis(timeout))
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
similarity index 99%
rename from lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
rename to lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
index fbb5f3d..8f25ee8 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
+++ b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
@@ -19,6 +19,8 @@
 package androidx.lifecycle
 
 import androidx.annotation.RequiresApi
+import androidx.lifecycle.util.ScopesRule
+import androidx.lifecycle.util.addObserver
 import com.google.common.truth.Truth.assertThat
 import java.time.Duration
 import java.util.concurrent.atomic.AtomicBoolean
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
similarity index 98%
rename from lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
rename to lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
index c1e21b0..c168fdc 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
+++ b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/FlowAsLiveDataTest.kt
@@ -19,6 +19,8 @@
 package androidx.lifecycle
 
 import androidx.annotation.RequiresApi
+import androidx.lifecycle.util.ScopesRule
+import androidx.lifecycle.util.addObserver
 import com.google.common.truth.Truth.assertThat
 import java.time.Duration
 import java.util.concurrent.atomic.AtomicBoolean
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
similarity index 98%
rename from lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
rename to lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
index 5bbe0b0..53806ab 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
+++ b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/LiveDataAsFlowTest.kt
@@ -18,9 +18,9 @@
 
 package androidx.lifecycle
 
+import androidx.lifecycle.util.ScopesRule
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.take
 import kotlinx.coroutines.flow.toList
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataFlowJavaTest.java b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/LiveDataFlowJavaTest.java
similarity index 100%
rename from lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/LiveDataFlowJavaTest.java
rename to lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/LiveDataFlowJavaTest.java
diff --git a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/ScopesRule.kt b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/util/ScopesRule.kt
similarity index 95%
rename from lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/ScopesRule.kt
rename to lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/util/ScopesRule.kt
index 63cd8a1..9ad1b95 100644
--- a/lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/ScopesRule.kt
+++ b/lifecycle/lifecycle-livedata/src/test/java/androidx/lifecycle/util/ScopesRule.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The Android Open Source Project
+ * Copyright 2023 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.
@@ -16,10 +16,12 @@
 
 @file:OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
 
-package androidx.lifecycle
+package androidx.lifecycle.util
 
 import androidx.arch.core.executor.ArchTaskExecutor
 import androidx.arch.core.executor.TaskExecutor
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.Observer
 import com.google.common.truth.Truth
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/lifecycle/lifecycle-runtime-testing/api/current.txt b/lifecycle/lifecycle-runtime-testing/api/current.txt
index c37e888..a7412a6 100644
--- a/lifecycle/lifecycle-runtime-testing/api/current.txt
+++ b/lifecycle/lifecycle-runtime-testing/api/current.txt
@@ -10,6 +10,7 @@
     method public int getObserverCount();
     method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
     method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    method public suspend Object? setCurrentState(androidx.lifecycle.Lifecycle.State state, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     property public final androidx.lifecycle.Lifecycle.State currentState;
     property public androidx.lifecycle.LifecycleRegistry lifecycle;
     property public final int observerCount;
diff --git a/lifecycle/lifecycle-runtime-testing/api/restricted_current.txt b/lifecycle/lifecycle-runtime-testing/api/restricted_current.txt
index c37e888..a7412a6 100644
--- a/lifecycle/lifecycle-runtime-testing/api/restricted_current.txt
+++ b/lifecycle/lifecycle-runtime-testing/api/restricted_current.txt
@@ -10,6 +10,7 @@
     method public int getObserverCount();
     method public void handleLifecycleEvent(androidx.lifecycle.Lifecycle.Event event);
     method public void setCurrentState(androidx.lifecycle.Lifecycle.State);
+    method public suspend Object? setCurrentState(androidx.lifecycle.Lifecycle.State state, kotlin.coroutines.Continuation<? super kotlin.Unit>);
     property public final androidx.lifecycle.Lifecycle.State currentState;
     property public androidx.lifecycle.LifecycleRegistry lifecycle;
     property public final int observerCount;
diff --git a/lifecycle/lifecycle-runtime-testing/build.gradle b/lifecycle/lifecycle-runtime-testing/build.gradle
index d84c9f8..b99b736 100644
--- a/lifecycle/lifecycle-runtime-testing/build.gradle
+++ b/lifecycle/lifecycle-runtime-testing/build.gradle
@@ -15,7 +15,6 @@
  */
 
 import androidx.build.Publish
-import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
 plugins {
     id("AndroidXPlugin")
@@ -32,6 +31,7 @@
     testImplementation(libs.junit)
     testImplementation(libs.kotlinCoroutinesTest)
 
+    androidTestImplementation(libs.kotlinCoroutinesTest)
     androidTestImplementation(libs.truth)
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
diff --git a/lifecycle/lifecycle-runtime-testing/src/androidTest/java/androidx/lifecycle/testing/TestLifecycleOwnerAndroidTest.kt b/lifecycle/lifecycle-runtime-testing/src/androidTest/java/androidx/lifecycle/testing/TestLifecycleOwnerAndroidTest.kt
index d03684b..54f2c3e 100644
--- a/lifecycle/lifecycle-runtime-testing/src/androidTest/java/androidx/lifecycle/testing/TestLifecycleOwnerAndroidTest.kt
+++ b/lifecycle/lifecycle-runtime-testing/src/androidTest/java/androidx/lifecycle/testing/TestLifecycleOwnerAndroidTest.kt
@@ -21,6 +21,13 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -49,4 +56,14 @@
         owner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
         assertThat(owner.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
     }
+
+    @OptIn(ExperimentalCoroutinesApi::class, ExperimentalStdlibApi::class)
+    @Test
+    fun testSetCurrentStateInRunTest() = runTest(timeout = 5000.milliseconds) {
+        Dispatchers.setMain(coroutineContext[CoroutineDispatcher]!!)
+        val owner = TestLifecycleOwner()
+        owner.setCurrentState(Lifecycle.State.RESUMED)
+        assertThat(owner.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+        Dispatchers.resetMain()
+    }
 }
diff --git a/lifecycle/lifecycle-runtime-testing/src/main/java/androidx/lifecycle/testing/TestLifecycleOwner.kt b/lifecycle/lifecycle-runtime-testing/src/main/java/androidx/lifecycle/testing/TestLifecycleOwner.kt
index 7e0f455..1ba0f99 100644
--- a/lifecycle/lifecycle-runtime-testing/src/main/java/androidx/lifecycle/testing/TestLifecycleOwner.kt
+++ b/lifecycle/lifecycle-runtime-testing/src/main/java/androidx/lifecycle/testing/TestLifecycleOwner.kt
@@ -23,6 +23,7 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
 
 /**
  * Create a [LifecycleOwner] that allows changing the state via the
@@ -51,15 +52,18 @@
 
     /**
      * Update the [currentState] by moving it to the state directly after the given [event].
-     * This is safe to call on any thread.
+     * This is safe to mutate on any thread, but will block that thread during execution.
      */
     public fun handleLifecycleEvent(event: Lifecycle.Event) {
         runBlocking(coroutineDispatcher) {
             lifecycleRegistry.handleLifecycleEvent(event)
         }
     }
+
     /**
-     * The current [Lifecycle.State] of this owner. This is safe to mutate on any thread.
+     * The current [Lifecycle.State] of this owner.
+     * This is safe to call on any thread but is thread-blocking and should not be
+     * called from within a coroutine (use [setCurrentState] instead).
      */
     public var currentState: Lifecycle.State
         get() = runBlocking(coroutineDispatcher) {
@@ -72,6 +76,18 @@
         }
 
     /**
+     * Updates the [currentState].
+     * This suspending function is safe to call on any thread and will not block that thread.
+     * If the state should be updated from outside of a suspending function, use [currentState]
+     * property syntax instead.
+     */
+    suspend fun setCurrentState(state: Lifecycle.State) {
+        withContext(coroutineDispatcher) {
+            lifecycleRegistry.currentState = state
+        }
+    }
+
+    /**
      * Get the number of observers.
      */
     public val observerCount: Int get() = lifecycleRegistry.observerCount
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/src/main/java/androidx/lifecycle/SavedStateHandleSupport.kt b/lifecycle/lifecycle-viewmodel-savedstate/src/main/java/androidx/lifecycle/SavedStateHandleSupport.kt
index e2285f3..55bbe1e 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/src/main/java/androidx/lifecycle/SavedStateHandleSupport.kt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/src/main/java/androidx/lifecycle/SavedStateHandleSupport.kt
@@ -22,8 +22,6 @@
 import androidx.annotation.MainThread
 import androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion.VIEW_MODEL_KEY
 import androidx.lifecycle.viewmodel.CreationExtras
-import androidx.lifecycle.viewmodel.initializer
-import androidx.lifecycle.viewmodel.viewModelFactory
 import androidx.savedstate.SavedStateRegistry
 import androidx.savedstate.SavedStateRegistryOwner
 
@@ -106,8 +104,11 @@
 }
 
 internal val ViewModelStoreOwner.savedStateHandlesVM: SavedStateHandlesVM
-    get() = ViewModelProvider(this, viewModelFactory {
-        initializer { SavedStateHandlesVM() }
+    get() = ViewModelProvider(this, object : ViewModelProvider.Factory {
+        override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
+            @Suppress("UNCHECKED_CAST")
+            return SavedStateHandlesVM() as T
+        }
     })[VIEWMODEL_KEY, SavedStateHandlesVM::class.java]
 
 internal val SavedStateRegistryOwner.savedStateHandlesProvider: SavedStateHandlesProvider
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
index 2370b740..6be73f6 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModel.java
@@ -139,11 +139,22 @@
     /**
      * Add a new {@link Closeable} object that will be closed directly before
      * {@link #onCleared()} is called.
-     *
+     * <p>
+     * If onCleared() has already been called, the closeable will not be added,
+     * and will instead be closed immediately.
+     * <p>
      * @param closeable The object that should be {@link Closeable#close() closed} directly before
      *                  {@link #onCleared()} is called.
      */
     public void addCloseable(@NonNull Closeable closeable) {
+        // Although no logic should be done after user calls onCleared(), we will
+        // ensure that if it has already been called, the closeable attempting to
+        // be added will be closed immediately to ensure there will be no leaks.
+        if (mCleared) {
+            closeWithRuntimeException(closeable);
+            return;
+        }
+
         // As this method is final, it will still be called on mock objects even
         // though mCloseables won't actually be created...we'll just not do anything
         // in that case.
@@ -186,6 +197,7 @@
                     closeWithRuntimeException(closeable);
                 }
             }
+            mCloseables.clear();
         }
         onCleared();
     }
diff --git a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelTest.kt b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelTest.kt
index 6e68344..5e97e09 100644
--- a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelTest.kt
+++ b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelTest.kt
@@ -80,6 +80,16 @@
     }
 
     @Test
+    fun testAddCloseableAlreadyClearedVM() {
+        val vm = ViewModel()
+        vm.clear()
+        val impl = CloseableImpl()
+        // This shouldn't crash, even though vm already cleared
+        vm.addCloseable(impl)
+        assertTrue(impl.wasClosed)
+    }
+
+    @Test
     fun testConstructorCloseable() {
         val impl = CloseableImpl()
         val vm = ConstructorArgViewModel(impl)
diff --git a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
index 5ad04f2..02cb445 100644
--- a/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
+++ b/mediarouter/mediarouter/src/main/java/androidx/mediarouter/media/GlobalMediaRouter.java
@@ -360,8 +360,7 @@
 
     /* package */ void addMemberToDynamicGroup(@NonNull MediaRouter.RouteInfo route) {
         if (!(mSelectedRouteController instanceof MediaRouteProvider.DynamicGroupRouteController)) {
-            throw new IllegalStateException(
-                    "There is no currently selected " + "dynamic group route.");
+            throw new IllegalStateException("There is no currently selected dynamic group route.");
         }
         MediaRouter.RouteInfo.DynamicGroupState state = getDynamicGroupState(route);
         if (mSelectedRoute.getMemberRoutes().contains(route)
@@ -376,8 +375,7 @@
 
     /* package */ void removeMemberFromDynamicGroup(@NonNull MediaRouter.RouteInfo route) {
         if (!(mSelectedRouteController instanceof MediaRouteProvider.DynamicGroupRouteController)) {
-            throw new IllegalStateException(
-                    "There is no currently selected " + "dynamic group route.");
+            throw new IllegalStateException("There is no currently selected dynamic group route.");
         }
         MediaRouter.RouteInfo.DynamicGroupState state = getDynamicGroupState(route);
         if (!mSelectedRoute.getMemberRoutes().contains(route)
@@ -396,8 +394,7 @@
 
     /* package */ void transferToRoute(@NonNull MediaRouter.RouteInfo route) {
         if (!(mSelectedRouteController instanceof MediaRouteProvider.DynamicGroupRouteController)) {
-            throw new IllegalStateException(
-                    "There is no currently selected dynamic group " + "route.");
+            throw new IllegalStateException("There is no currently selected dynamic group route.");
         }
         MediaRouter.RouteInfo.DynamicGroupState state = getDynamicGroupState(route);
         if (state == null || !state.isTransferable()) {
diff --git a/navigation/navigation-compose/build.gradle b/navigation/navigation-compose/build.gradle
index 5594c47..30482d2 100644
--- a/navigation/navigation-compose/build.gradle
+++ b/navigation/navigation-compose/build.gradle
@@ -27,12 +27,12 @@
 dependencies {
 
     implementation(libs.kotlinStdlib)
-    implementation("androidx.compose.foundation:foundation-layout:1.5.0")
+    implementation("androidx.compose.foundation:foundation-layout:1.5.1")
     api("androidx.activity:activity-compose:1.7.0")
-    api("androidx.compose.animation:animation:1.5.0")
-    api("androidx.compose.runtime:runtime:1.5.0")
-    api("androidx.compose.runtime:runtime-saveable:1.5.0")
-    api("androidx.compose.ui:ui:1.5.0")
+    api("androidx.compose.animation:animation:1.5.1")
+    api("androidx.compose.runtime:runtime:1.5.1")
+    api("androidx.compose.runtime:runtime-saveable:1.5.1")
+    api("androidx.compose.ui:ui:1.5.1")
     api("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
     api(projectOrArtifact(":navigation:navigation-runtime-ktx"))
 
diff --git a/navigation/navigation-compose/integration-tests/navigation-demos/lint-baseline.xml b/navigation/navigation-compose/integration-tests/navigation-demos/lint-baseline.xml
index 7c35642..7b89361 100644
--- a/navigation/navigation-compose/integration-tests/navigation-demos/lint-baseline.xml
+++ b/navigation/navigation-compose/integration-tests/navigation-demos/lint-baseline.xml
@@ -2,51 +2,6 @@
 <issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="data class ViewInfo("
-        errorLine2="           ~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class ComposeViewAdapter : FrameLayout {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    internal lateinit var clock: PreviewAnimationClock"
-        errorLine2="                          ~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    fun hasAnimations() = hasAnimations"
-        errorLine2="        ~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="class PreviewActivity : ComponentActivity() {"
-        errorLine2="      ~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt"/>
-    </issue>
-
-    <issue
         id="BanThreadSleep"
         message="Uses Thread.sleep()"
         errorLine1="            Thread.sleep(250)"
diff --git a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
index d000958..52c924c 100644
--- a/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
+++ b/navigation/navigation-fragment/src/androidTest/java/androidx/navigation/fragment/NavControllerWithFragmentTest.kt
@@ -21,6 +21,8 @@
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.ViewModelProvider
 import androidx.navigation.NavOptions
@@ -35,7 +37,8 @@
 import androidx.testutils.withActivity
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
-import org.junit.Ignore
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.TimeUnit
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -75,7 +78,7 @@
             .that(navController.currentBackStackEntry!!.lifecycle.currentState)
             .isEqualTo(Lifecycle.State.RESUMED)
     }
-    @Ignore("b/276806142")
+
     @Test
     fun fragmentNavigateClearBackStack() = withNavigationActivity {
         navController.setGraph(R.navigation.nav_simple)
@@ -98,6 +101,14 @@
             TestClearViewModel::class.java
         ]
         val originalFragment = fm?.findFragmentById(R.id.nav_host) as Fragment
+        val destroyCountDownLatch = CountDownLatch(1)
+        originalFragment.lifecycle.addObserver(object : LifecycleEventObserver {
+            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+                if (event == Lifecycle.Event.ON_DESTROY) {
+                    destroyCountDownLatch.countDown()
+                }
+            }
+        })
         val originalFragmentViewModel = ViewModelProvider(originalFragment)[
             TestClearViewModel::class.java
         ]
@@ -125,6 +136,7 @@
         assertThat(fm.findFragmentById(R.id.nav_host)).isEqualTo(currentTopFragment)
         assertThat(navController.currentDestination?.id ?: 0).isEqualTo(R.id.empty_fragment_2)
         assertThat(navigator.backStack.value.size).isEqualTo(2)
+        assertThat(destroyCountDownLatch.await(1000, TimeUnit.MILLISECONDS)).isTrue()
         assertThat(originalFragmentViewModel.cleared).isTrue()
         assertThat(originalEntryViewModel.cleared).isTrue()
     }
diff --git a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
index 998b9f8..e24917a 100644
--- a/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
+++ b/navigation/navigation-safe-args-gradle-plugin/src/main/kotlin/androidx/navigation/safeargs/gradle/SafeArgsPlugin.kt
@@ -106,7 +106,7 @@
         }
 
         forEachVariant(extension) { variant ->
-            val task = project.tasks.create(
+            val task = project.tasks.register(
                 "generateSafeArgs${variant.name.replaceFirstChar {
                     if (it.isLowerCase()) it.titlecase(Locale.US) else it.toString()
                 }}",
@@ -141,7 +141,7 @@
                 task.generateKotlin.set(generateKotlin)
             }
             @Suppress("DEPRECATION") // For BaseVariant should be replaced in later studio versions
-            variant.registerJavaGeneratingTask(task, task.outputDir.asFile.get())
+            variant.registerJavaGeneratingTask(task, task.get().outputDir.asFile.get())
         }
     }
 
diff --git a/paging/paging-common/build.gradle b/paging/paging-common/build.gradle
index 3368c0b..ffd08fb 100644
--- a/paging/paging-common/build.gradle
+++ b/paging/paging-common/build.gradle
@@ -18,13 +18,16 @@
 import androidx.build.PlatformIdentifier
 import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
 import androidx.build.Publish
+import org.jetbrains.kotlin.konan.target.Family
+
 
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
 }
 
-def enableNative = KmpPlatformsKt.enableNative(project)
+def macEnabled = KmpPlatformsKt.enableMac(project)
+def linuxEnabled = KmpPlatformsKt.enableLinux(project)
 
 androidXMultiplatform {
     jvm()
@@ -36,14 +39,11 @@
     defaultPlatform(PlatformIdentifier.JVM)
 
     sourceSets {
-
         commonMain {
             dependencies {
                 api(libs.kotlinStdlib)
                 api(libs.kotlinCoroutinesCore)
                 api("androidx.annotation:annotation:1.7.0-alpha02")
-                implementation(libs.statelyConcurrency)
-                implementation(libs.statelyConcurrentCollections)
             }
         }
 
@@ -95,19 +95,40 @@
             }
         }
 
-        if (enableNative) {
+        if (macEnabled || linuxEnabled) {
             nativeMain {
                 dependsOn(commonMain)
+                dependencies {
+                    implementation(libs.atomicFu)
+                }
             }
             nativeTest {
                 dependsOn(commonTest)
             }
         }
+        if (macEnabled) {
+            darwinMain {
+                dependsOn(nativeMain)
+            }
+        }
+
+        if (linuxEnabled) {
+            linuxMain {
+                dependsOn(nativeMain)
+            }
+        }
 
         targets.all { target ->
             if (target.platformType == KotlinPlatformType.native) {
                 target.compilations["main"].defaultSourceSet {
-                    dependsOn(nativeMain)
+                    def konanTargetFamily = target.konanTarget.family
+                    if (konanTargetFamily == Family.OSX || konanTargetFamily == Family.IOS) {
+                        dependsOn(darwinMain)
+                    } else if (konanTargetFamily == Family.LINUX) {
+                        dependsOn(linuxMain)
+                    } else {
+                        throw new GradleException("unknown native target ${target}")
+                    }
                 }
                 target.compilations["test"].defaultSourceSet {
                     dependsOn(nativeTest)
diff --git a/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/LegacyPageFetcher.jvm.kt b/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/LegacyPageFetcher.jvm.kt
index 9717bdd..cc919f4 100644
--- a/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/LegacyPageFetcher.jvm.kt
+++ b/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/LegacyPageFetcher.jvm.kt
@@ -19,7 +19,7 @@
 import androidx.paging.LoadState.Loading
 import androidx.paging.LoadState.NotLoading
 import androidx.paging.PagingSource.LoadParams
-import co.touchlab.stately.concurrency.AtomicBoolean
+import androidx.paging.internal.AtomicBoolean
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.launch
@@ -45,7 +45,7 @@
     }
 
     val isDetached
-        get() = detached.value
+        get() = detached.get()
 
     private fun scheduleLoad(type: LoadType, params: LoadParams<K>) {
         // Listen on the BG thread if the paged source is invalid, since it can be expensive.
@@ -155,7 +155,7 @@
     }
 
     fun detach() {
-        detached.value = true
+        detached.set(true)
     }
 
     internal interface PageConsumer<V : Any> {
diff --git a/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/internal/Atomics.jvm.kt b/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/internal/Atomics.jvm.kt
new file mode 100644
index 0000000..58b53e9
--- /dev/null
+++ b/paging/paging-common/src/commonJvmAndroidMain/kotlin/androidx/paging/internal/Atomics.jvm.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2023 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:Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316
+package androidx.paging.internal
+
+internal actual typealias ReentrantLock = java.util.concurrent.locks.ReentrantLock
+
+internal actual typealias AtomicInt = java.util.concurrent.atomic.AtomicInteger
+
+internal actual typealias AtomicBoolean = java.util.concurrent.atomic.AtomicBoolean
+
+internal actual typealias CopyOnWriteArrayList<T> = java.util.concurrent.CopyOnWriteArrayList<T>
diff --git a/paging/paging-common/src/commonJvmAndroidTest/kotlin/androidx/paging/GarbageCollectionTestHelper.kt b/paging/paging-common/src/commonJvmAndroidTest/kotlin/androidx/paging/GarbageCollectionTestHelper.kt
index 940fd38..d13dd42 100644
--- a/paging/paging-common/src/commonJvmAndroidTest/kotlin/androidx/paging/GarbageCollectionTestHelper.kt
+++ b/paging/paging-common/src/commonJvmAndroidTest/kotlin/androidx/paging/GarbageCollectionTestHelper.kt
@@ -17,7 +17,7 @@
 package androidx.paging
 
 import androidx.kruth.assertWithMessage
-import co.touchlab.stately.concurrency.AtomicBoolean
+import androidx.paging.internal.AtomicBoolean
 import java.lang.ref.ReferenceQueue
 import java.lang.ref.WeakReference
 import kotlin.concurrent.thread
@@ -45,7 +45,7 @@
                 val arraySize = Random.nextInt(1000)
                 leak.add(ByteArray(arraySize))
                 System.gc()
-            } while (continueTriggeringGc.value)
+            } while (continueTriggeringGc.get())
         }
         var collectedItemCount = 0
         val expectedItemCount = size - expected.sumOf { it.second }
@@ -54,7 +54,7 @@
         ) {
             collectedItemCount++
         }
-        continueTriggeringGc.value = false
+        continueTriggeringGc.set(false)
         val leakedObjects = countLiveObjects()
         val leakedObjectToStrings = references.mapNotNull {
             it.get()
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/FlowExt.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/FlowExt.kt
index beea20a6..a1e281c 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/FlowExt.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/FlowExt.kt
@@ -22,13 +22,12 @@
 import androidx.paging.CombineSource.INITIAL
 import androidx.paging.CombineSource.OTHER
 import androidx.paging.CombineSource.RECEIVER
-import co.touchlab.stately.concurrency.AtomicInt
+import androidx.paging.internal.AtomicInt
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.channels.SendChannel
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.FlowCollector
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.emitAll
 import kotlinx.coroutines.flow.flow
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/HintHandler.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/HintHandler.kt
index 4d35dd4..8f48b22 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/HintHandler.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/HintHandler.kt
@@ -21,8 +21,8 @@
 import androidx.annotation.RestrictTo
 import androidx.paging.LoadType.APPEND
 import androidx.paging.LoadType.PREPEND
-import co.touchlab.stately.concurrency.Lock
-import co.touchlab.stately.concurrency.withLock
+import androidx.paging.internal.ReentrantLock
+import androidx.paging.internal.withLock
 import kotlinx.coroutines.channels.BufferOverflow
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -106,7 +106,7 @@
             get() = prepend.flow
         val appendFlow
             get() = append.flow
-        private val lock = Lock()
+        private val lock = ReentrantLock()
 
         /**
          * Modifies the state inside a lock where it gets access to the mutable values.
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidateCallbackTracker.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidateCallbackTracker.kt
index fea2249..7c83d58 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidateCallbackTracker.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidateCallbackTracker.kt
@@ -17,8 +17,8 @@
 package androidx.paging
 
 import androidx.annotation.VisibleForTesting
-import co.touchlab.stately.concurrency.Lock
-import co.touchlab.stately.concurrency.withLock
+import androidx.paging.internal.ReentrantLock
+import androidx.paging.internal.withLock
 
 /**
  * Helper class for thread-safe invalidation callback tracking + triggering on registration.
@@ -30,7 +30,7 @@
      */
     private val invalidGetter: (() -> Boolean)? = null,
 ) {
-    private val lock = Lock()
+    private val lock = ReentrantLock()
     private val callbacks = mutableListOf<T>()
     internal var invalid = false
         private set
@@ -51,12 +51,12 @@
             return
         }
 
-        var callImmediately = false
-        lock.withLock {
+        val callImmediately = lock.withLock {
             if (invalid) {
-                callImmediately = true
+                true // call immediately
             } else {
                 callbacks.add(callback)
+                false // don't call, not invalid yet.
             }
         }
 
@@ -74,16 +74,16 @@
     internal fun invalidate(): Boolean {
         if (invalid) return false
 
-        var callbacksToInvoke: List<T>? = null
-        lock.withLock {
+        val callbacksToInvoke = lock.withLock {
             if (invalid) return false
 
             invalid = true
-            callbacksToInvoke = callbacks.toList()
-            callbacks.clear()
+            callbacks.toList().also {
+                callbacks.clear()
+            }
         }
 
-        callbacksToInvoke?.forEach(callbackInvoker)
+        callbacksToInvoke.forEach(callbackInvoker)
         return true
     }
 }
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidatingPagingSourceFactory.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidatingPagingSourceFactory.kt
index b8cf8c9..21f520e 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidatingPagingSourceFactory.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/InvalidatingPagingSourceFactory.kt
@@ -17,7 +17,8 @@
 package androidx.paging
 
 import androidx.annotation.VisibleForTesting
-import co.touchlab.stately.collections.ConcurrentMutableList
+import androidx.paging.internal.ReentrantLock
+import androidx.paging.internal.withLock
 
 /**
  * Wrapper class for a [PagingSource] factory intended for usage in [Pager] construction.
@@ -25,24 +26,31 @@
  * Calling [invalidate] on this [InvalidatingPagingSourceFactory] will forward invalidate signals
  * to all active [PagingSource]s that were produced by calling [invoke].
  *
- * This class is backed by a [ConcurrentMutableList], which is thread-safe for concurrent calls to
- * any mutative operations including both [invoke] and [invalidate].
+ * This class is thread-safe for concurrent calls to any mutative operations including both
+ * [invoke] and [invalidate].
  *
  * @param pagingSourceFactory The [PagingSource] factory that returns a PagingSource when called
  */
 public class InvalidatingPagingSourceFactory<Key : Any, Value : Any>(
     private val pagingSourceFactory: () -> PagingSource<Key, Value>
 ) : PagingSourceFactory<Key, Value> {
+    private val lock = ReentrantLock()
+
+    private var pagingSources: List<PagingSource<Key, Value>> = emptyList()
 
     @VisibleForTesting
-    internal val pagingSources = ConcurrentMutableList<PagingSource<Key, Value>>()
+    internal fun pagingSources() = pagingSources
 
     /**
      * @return [PagingSource] which will be invalidated when this factory's [invalidate] method
      * is called
      */
     override fun invoke(): PagingSource<Key, Value> {
-        return pagingSourceFactory().also { pagingSources.add(it) }
+        return pagingSourceFactory().also {
+            lock.withLock {
+                pagingSources = pagingSources + it
+            }
+        }
     }
 
     /**
@@ -50,10 +58,15 @@
      * [InvalidatingPagingSourceFactory]
      */
     public fun invalidate() {
-        pagingSources
-            .filterNot { it.invalid }
-            .forEach { it.invalidate() }
-
-        pagingSources.removeAll { it.invalid }
+        val previousList = lock.withLock {
+            pagingSources.also {
+                pagingSources = emptyList()
+            }
+        }
+        for (pagingSource in previousList) {
+            if (!pagingSource.invalid) {
+                pagingSource.invalidate()
+            }
+        }
     }
 }
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/MutableCombinedLoadStateCollection.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/MutableCombinedLoadStateCollection.kt
index b622a16..755c80d 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/MutableCombinedLoadStateCollection.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/MutableCombinedLoadStateCollection.kt
@@ -19,7 +19,7 @@
 import androidx.paging.LoadState.Error
 import androidx.paging.LoadState.Loading
 import androidx.paging.LoadState.NotLoading
-import co.touchlab.stately.collections.ConcurrentMutableList
+import androidx.paging.internal.CopyOnWriteArrayList
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -35,7 +35,7 @@
  */
 internal class MutableCombinedLoadStateCollection {
 
-    private val listeners = ConcurrentMutableList<(CombinedLoadStates) -> Unit>()
+    private val listeners = CopyOnWriteArrayList<(CombinedLoadStates) -> Unit>()
     private val _stateFlow = MutableStateFlow<CombinedLoadStates?>(null)
     public val stateFlow = _stateFlow.asStateFlow()
 
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/PageFetcherSnapshot.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/PageFetcherSnapshot.kt
index 769adc3..2ca05b6 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/PageFetcherSnapshot.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/PageFetcherSnapshot.kt
@@ -31,7 +31,7 @@
 import androidx.paging.PagingSource.LoadResult
 import androidx.paging.PagingSource.LoadResult.Page
 import androidx.paging.PagingSource.LoadResult.Page.Companion.COUNT_UNDEFINED
-import co.touchlab.stately.concurrency.AtomicBoolean
+import androidx.paging.internal.AtomicBoolean
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.channels.Channel
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataDiffer.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataDiffer.kt
index 6ce5871..4cb2a1f 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataDiffer.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataDiffer.kt
@@ -26,8 +26,8 @@
 import androidx.paging.PageEvent.StaticList
 import androidx.paging.PagePresenter.ProcessPageEventCallback
 import androidx.paging.internal.BUGANIZER_URL
+import androidx.paging.internal.CopyOnWriteArrayList
 import androidx.paging.internal.appendMediatorStatesIfNotNull
-import co.touchlab.stately.collections.ConcurrentMutableList
 import kotlin.coroutines.CoroutineContext
 import kotlin.jvm.Volatile
 import kotlinx.coroutines.Dispatchers
@@ -51,7 +51,7 @@
     private val combinedLoadStatesCollection = MutableCombinedLoadStateCollection().apply {
         cachedPagingData?.cachedEvent()?.let { set(it.sourceLoadStates, it.mediatorLoadStates) }
     }
-    private val onPagesUpdatedListeners = ConcurrentMutableList<() -> Unit>()
+    private val onPagesUpdatedListeners = CopyOnWriteArrayList<() -> Unit>()
 
     private val collectFromRunner = SingleRunner()
 
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/RemoteMediatorAccessor.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/RemoteMediatorAccessor.kt
index f2725a1..60e1cd7 100644
--- a/paging/paging-common/src/commonMain/kotlin/androidx/paging/RemoteMediatorAccessor.kt
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/RemoteMediatorAccessor.kt
@@ -20,8 +20,8 @@
 import androidx.paging.AccessorState.BlockState.REQUIRES_REFRESH
 import androidx.paging.AccessorState.BlockState.UNBLOCKED
 import androidx.paging.RemoteMediator.MediatorResult
-import co.touchlab.stately.concurrency.Lock
-import co.touchlab.stately.concurrency.withLock
+import androidx.paging.internal.ReentrantLock
+import androidx.paging.internal.withLock
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -67,7 +67,7 @@
  * Simple wrapper around the local state of accessor to ensure we don't concurrently change it.
  */
 private class AccessorStateHolder<Key : Any, Value : Any> {
-    private val lock = Lock()
+    private val lock = ReentrantLock()
 
     private val _loadStates = MutableStateFlow(LoadStates.IDLE)
     val loadStates
diff --git a/paging/paging-common/src/commonMain/kotlin/androidx/paging/internal/Atomics.kt b/paging/paging-common/src/commonMain/kotlin/androidx/paging/internal/Atomics.kt
new file mode 100644
index 0000000..1231856
--- /dev/null
+++ b/paging/paging-common/src/commonMain/kotlin/androidx/paging/internal/Atomics.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2023 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.paging.internal
+
+import kotlin.contracts.ExperimentalContracts
+import kotlin.contracts.InvocationKind
+import kotlin.contracts.contract
+
+internal expect class CopyOnWriteArrayList<T>() : Iterable<T> {
+    fun add(value: T): Boolean
+    fun remove(value: T): Boolean
+}
+
+internal expect class ReentrantLock constructor() {
+    fun lock()
+    fun unlock()
+}
+
+internal expect class AtomicInt {
+    constructor(initialValue: Int)
+
+    fun getAndIncrement(): Int
+    fun incrementAndGet(): Int
+    fun decrementAndGet(): Int
+    fun get(): Int
+}
+
+internal expect class AtomicBoolean {
+    constructor(initialValue: Boolean)
+
+    fun get(): Boolean
+    fun set(value: Boolean)
+    fun compareAndSet(expect: Boolean, update: Boolean): Boolean
+}
+
+@OptIn(ExperimentalContracts::class)
+@Suppress("BanInlineOptIn") // b/296638070
+internal inline fun <T> ReentrantLock.withLock(block: () -> T): T {
+    contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
+    try {
+        lock()
+        return block()
+    } finally {
+        unlock()
+    }
+}
diff --git a/paging/paging-common/src/commonTest/kotlin/androidx/paging/CachingTest.kt b/paging/paging-common/src/commonTest/kotlin/androidx/paging/CachingTest.kt
index b739e28..e7112cb 100644
--- a/paging/paging-common/src/commonTest/kotlin/androidx/paging/CachingTest.kt
+++ b/paging/paging-common/src/commonTest/kotlin/androidx/paging/CachingTest.kt
@@ -19,7 +19,7 @@
 import androidx.paging.ActiveFlowTracker.FlowType
 import androidx.paging.ActiveFlowTracker.FlowType.PAGED_DATA_FLOW
 import androidx.paging.ActiveFlowTracker.FlowType.PAGE_EVENT_FLOW
-import co.touchlab.stately.concurrency.AtomicInt
+import androidx.paging.internal.AtomicInt
 import kotlin.test.Test
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
diff --git a/paging/paging-common/src/commonTest/kotlin/androidx/paging/InvalidatingPagingSourceFactoryTest.kt b/paging/paging-common/src/commonTest/kotlin/androidx/paging/InvalidatingPagingSourceFactoryTest.kt
index 28b9cb4..647d7c8 100644
--- a/paging/paging-common/src/commonTest/kotlin/androidx/paging/InvalidatingPagingSourceFactoryTest.kt
+++ b/paging/paging-common/src/commonTest/kotlin/androidx/paging/InvalidatingPagingSourceFactoryTest.kt
@@ -19,6 +19,10 @@
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertTrue
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.runBlocking
 
 class InvalidatingPagingSourceFactoryTest {
 
@@ -26,17 +30,17 @@
     fun getPagingSource() {
         val testFactory = InvalidatingPagingSourceFactory { TestPagingSource() }
         repeat(4) { testFactory() }
-        assertEquals(4, testFactory.pagingSources.size)
+        assertEquals(4, testFactory.pagingSources().size)
     }
 
     @Test
     fun invalidateRemoveFromList() {
         val testFactory = InvalidatingPagingSourceFactory { TestPagingSource() }
         repeat(4) { testFactory() }
-        assertEquals(4, testFactory.pagingSources.size)
+        assertEquals(4, testFactory.pagingSources().size)
 
         testFactory.invalidate()
-        assertEquals(0, testFactory.pagingSources.size)
+        assertEquals(0, testFactory.pagingSources().size)
     }
 
     @Test
@@ -44,7 +48,7 @@
         val invalidateCalls = Array(4) { false }
         val testFactory = InvalidatingPagingSourceFactory { TestPagingSource() }
         repeat(4) { testFactory() }
-        testFactory.pagingSources.forEachIndexed { index, pagingSource ->
+        testFactory.pagingSources().forEachIndexed { index, pagingSource ->
             pagingSource.registerInvalidatedCallback {
                 invalidateCalls[index] = true
             }
@@ -58,14 +62,14 @@
         val testFactory = InvalidatingPagingSourceFactory { TestPagingSource() }
         repeat(4) { testFactory() }
 
-        val pagingSource = testFactory.pagingSources[0]
+        val pagingSource = testFactory.pagingSources()[0]
         pagingSource.invalidate()
 
         assertTrue(pagingSource.invalid)
 
         var invalidateCount = 0
 
-        testFactory.pagingSources.forEach {
+        testFactory.pagingSources().forEach {
             it.registerInvalidatedCallback {
                 invalidateCount++
             }
@@ -92,17 +96,15 @@
     }
 
     @Test
-    fun invalidate_threadSafe() {
+    fun invalidate_threadSafe() = runBlocking<Unit> {
         val factory = InvalidatingPagingSourceFactory { TestPagingSource() }
-
-        // Check for concurrent modification when invalidating paging sources.
-        repeat(2) {
-            factory().registerInvalidatedCallback {
-                factory()
+        (0 until 100).map {
+            async(Dispatchers.Default) {
+                factory().registerInvalidatedCallback {
+                    factory().invalidate()
+                }
                 factory.invalidate()
-                factory()
             }
-        }
-        factory.invalidate()
+        }.awaitAll()
     }
 }
diff --git a/paging/paging-common/src/commonTest/kotlin/androidx/paging/RemoteMediatorAccessorTest.kt b/paging/paging-common/src/commonTest/kotlin/androidx/paging/RemoteMediatorAccessorTest.kt
index 7cc69b1..2c9ebf2 100644
--- a/paging/paging-common/src/commonTest/kotlin/androidx/paging/RemoteMediatorAccessorTest.kt
+++ b/paging/paging-common/src/commonTest/kotlin/androidx/paging/RemoteMediatorAccessorTest.kt
@@ -25,7 +25,7 @@
 import androidx.paging.RemoteMediator.InitializeAction.SKIP_INITIAL_REFRESH
 import androidx.paging.RemoteMediatorMock.LoadEvent
 import androidx.paging.TestPagingSource.Companion.LOAD_ERROR
-import co.touchlab.stately.concurrency.AtomicBoolean
+import androidx.paging.internal.AtomicBoolean
 import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.fail
@@ -500,7 +500,7 @@
                 return try {
                     super.load(loadType, state)
                 } finally {
-                    loading.value = false
+                    loading.set(false)
                 }
             }
         }
@@ -583,7 +583,7 @@
                 return try {
                     super.load(loadType, state)
                 } finally {
-                    loading.value = false
+                    loading.set(false)
                 }
             }
         }
diff --git a/compose/material/material-icons-extended-filled/build.gradle b/paging/paging-common/src/darwinMain/kotlin/androidx/paging/internal/Atomics.darwin.kt
similarity index 75%
copy from compose/material/material-icons-extended-filled/build.gradle
copy to paging/paging-common/src/darwinMain/kotlin/androidx/paging/internal/Atomics.darwin.kt
index 5933def..2f7f7fc 100644
--- a/compose/material/material-icons-extended-filled/build.gradle
+++ b/paging/paging-common/src/darwinMain/kotlin/androidx/paging/internal/Atomics.darwin.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-apply from: "../material-icons-extended/generate.gradle"
+package androidx.paging.internal
 
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
+internal actual val PTHREAD_MUTEX_RECURSIVE: Int = platform.posix.PTHREAD_MUTEX_RECURSIVE
diff --git a/compose/material/material-icons-extended-filled/build.gradle b/paging/paging-common/src/linuxMain/kotlin/androidx/paging/internal/Atomics.linux.kt
similarity index 75%
rename from compose/material/material-icons-extended-filled/build.gradle
rename to paging/paging-common/src/linuxMain/kotlin/androidx/paging/internal/Atomics.linux.kt
index 5933def..22b6f1f 100644
--- a/compose/material/material-icons-extended-filled/build.gradle
+++ b/paging/paging-common/src/linuxMain/kotlin/androidx/paging/internal/Atomics.linux.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2023 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-apply from: "../material-icons-extended/generate.gradle"
+package androidx.paging.internal
 
-android {
-    namespace "androidx.compose.material.icons.extended"
-}
+internal actual val PTHREAD_MUTEX_RECURSIVE: Int = platform.posix.PTHREAD_MUTEX_RECURSIVE.toInt()
diff --git a/paging/paging-common/src/nativeMain/kotlin/androidx/paging/internal/Atomics.native.kt b/paging/paging-common/src/nativeMain/kotlin/androidx/paging/internal/Atomics.native.kt
new file mode 100644
index 0000000..a550430
--- /dev/null
+++ b/paging/paging-common/src/nativeMain/kotlin/androidx/paging/internal/Atomics.native.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2023 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:OptIn(ExperimentalForeignApi::class)
+
+package androidx.paging.internal
+
+import kotlin.native.internal.createCleaner
+import kotlinx.atomicfu.AtomicBoolean as AtomicFuAtomicBoolean
+import kotlinx.atomicfu.AtomicInt as AtomicFuAtomicInt
+import kotlinx.atomicfu.atomic
+import kotlinx.cinterop.Arena
+import kotlinx.cinterop.ExperimentalForeignApi
+import kotlinx.cinterop.alloc
+import kotlinx.cinterop.ptr
+import platform.posix.pthread_mutex_destroy
+import platform.posix.pthread_mutex_init
+import platform.posix.pthread_mutex_lock
+import platform.posix.pthread_mutex_t
+import platform.posix.pthread_mutex_unlock
+import platform.posix.pthread_mutexattr_destroy
+import platform.posix.pthread_mutexattr_init
+import platform.posix.pthread_mutexattr_settype
+import platform.posix.pthread_mutexattr_t
+
+/**
+ * Wrapper for platform.posix.PTHREAD_MUTEX_RECURSIVE which
+ * is represented as kotlin.Int on darwin platforms and kotlin.UInt on linuxX64
+ * See: // https://youtrack.jetbrains.com/issue/KT-41509
+ */
+internal expect val PTHREAD_MUTEX_RECURSIVE: Int
+
+@Suppress("ACTUAL_WITHOUT_EXPECT") // https://youtrack.jetbrains.com/issue/KT-37316
+internal actual class ReentrantLock actual constructor() {
+
+    private val resources = Resources()
+
+    @Suppress("unused") // The returned Cleaner must be assigned to a property
+    @ExperimentalStdlibApi
+    private val cleaner = createCleaner(resources, Resources::destroy)
+
+    actual fun lock() {
+        pthread_mutex_lock(resources.mutex.ptr)
+    }
+
+    actual fun unlock() {
+        pthread_mutex_unlock(resources.mutex.ptr)
+    }
+
+    private class Resources {
+        private val arena = Arena()
+        private val attr: pthread_mutexattr_t = arena.alloc()
+        val mutex: pthread_mutex_t = arena.alloc()
+
+        init {
+            pthread_mutexattr_init(attr.ptr)
+            pthread_mutexattr_settype(attr.ptr, PTHREAD_MUTEX_RECURSIVE)
+            pthread_mutex_init(mutex.ptr, attr.ptr)
+        }
+
+        fun destroy() {
+            pthread_mutex_destroy(mutex.ptr)
+            pthread_mutexattr_destroy(attr.ptr)
+            arena.clear()
+        }
+    }
+}
+
+internal actual class AtomicInt actual constructor(initialValue: Int) {
+    private var delegate: AtomicFuAtomicInt = atomic(initialValue)
+    private var property by delegate
+
+    actual fun getAndIncrement(): Int {
+        return delegate.getAndIncrement()
+    }
+
+    actual fun decrementAndGet(): Int {
+        return delegate.decrementAndGet()
+    }
+
+    actual fun get(): Int = property
+
+    actual fun incrementAndGet(): Int {
+        return delegate.incrementAndGet()
+    }
+}
+
+internal actual class AtomicBoolean actual constructor(initialValue: Boolean) {
+    private var delegate: AtomicFuAtomicBoolean = atomic(initialValue)
+    private var property by delegate
+
+    actual fun get(): Boolean = property
+
+    actual fun set(value: Boolean) {
+        property = value
+    }
+
+    actual fun compareAndSet(expect: Boolean, update: Boolean): Boolean {
+        return delegate.compareAndSet(expect, update)
+    }
+}
+
+internal actual class CopyOnWriteArrayList<T> : Iterable<T> {
+    private var data: List<T> = emptyList()
+    private val lock = ReentrantLock()
+    override fun iterator(): Iterator<T> {
+        return data.iterator()
+    }
+
+    actual fun add(value: T) = lock.withLock {
+        data = data + value
+        true
+    }
+
+    actual fun remove(value: T): Boolean = lock.withLock {
+        val newList = data.toMutableList()
+        val result = newList.remove(value)
+        data = newList
+        result
+    }
+}
diff --git a/paging/paging-compose/integration-tests/paging-demos/lint-baseline.xml b/paging/paging-compose/integration-tests/paging-demos/lint-baseline.xml
index 7c35642..8ce8601 100644
--- a/paging/paging-compose/integration-tests/paging-demos/lint-baseline.xml
+++ b/paging/paging-compose/integration-tests/paging-demos/lint-baseline.xml
@@ -2,51 +2,6 @@
 <issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="data class ViewInfo("
-        errorLine2="           ~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class ComposeViewAdapter : FrameLayout {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    internal lateinit var clock: PreviewAnimationClock"
-        errorLine2="                          ~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="    fun hasAnimations() = hasAnimations"
-        errorLine2="        ~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/ComposeViewAdapter.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="class PreviewActivity : ComponentActivity() {"
-        errorLine2="      ~~~~~~~~~~~~~~~">
-        <location
-            file="src/androidMain/kotlin/androidx/compose/ui/tooling/PreviewActivity.kt"/>
-    </issue>
-
-    <issue
         id="BanThreadSleep"
         message="Uses Thread.sleep()"
         errorLine1="            Thread.sleep(250)"
@@ -82,4 +37,4 @@
             file="src/androidMain/kotlin/androidx/compose/ui/tooling/animation/clock/Utils.kt"/>
     </issue>
 
-</issues>
+</issues>
\ No newline at end of file
diff --git a/paging/paging-compose/src/androidAndroidTest/kotlin/androidx/paging/compose/LazyPagingItemsTest.kt b/paging/paging-compose/src/androidAndroidTest/kotlin/androidx/paging/compose/LazyPagingItemsTest.kt
index b0c4f3b..4399ddd 100644
--- a/paging/paging-compose/src/androidAndroidTest/kotlin/androidx/paging/compose/LazyPagingItemsTest.kt
+++ b/paging/paging-compose/src/androidAndroidTest/kotlin/androidx/paging/compose/LazyPagingItemsTest.kt
@@ -992,7 +992,10 @@
 
         rule.waitUntil {
             dispatcher.scheduler.advanceUntilIdle() // let items load
-            lazyPagingItems.itemCount == maxItem
+            lazyPagingItems.itemCount == maxItem &&
+                lazyPagingItems.loadState.source.refresh is LoadState.NotLoading &&
+                lazyPagingItems.loadState.source.prepend is LoadState.NotLoading &&
+                lazyPagingItems.loadState.source.append is LoadState.NotLoading
         }
 
         assertThat(lazyPagingItems.loadState).isEqualTo(
diff --git a/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/PagerFlowSnapshot.kt b/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/PagerFlowSnapshot.kt
index 0e706ac..825b27b 100644
--- a/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/PagerFlowSnapshot.kt
+++ b/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/PagerFlowSnapshot.kt
@@ -32,10 +32,13 @@
 import androidx.paging.testing.LoaderCallback.CallbackType.ON_CHANGED
 import androidx.paging.testing.LoaderCallback.CallbackType.ON_INSERTED
 import androidx.paging.testing.LoaderCallback.CallbackType.ON_REMOVED
+import kotlin.coroutines.CoroutineContext
 import kotlinx.coroutines.cancelAndJoin
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.debounce
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.filterNotNull
@@ -81,7 +84,7 @@
     }
 
     // PagingDataDiffer will collect from coroutineContext instead of main dispatcher
-    val differ = object : PagingDataDiffer<Value>(callback, coroutineContext) {
+    val differ = object : CompletablePagingDataDiffer<Value>(callback, coroutineContext) {
         override suspend fun presentNewList(
             previousList: NullPaddedList<Value>,
             newList: NullPaddedList<Value>,
@@ -120,6 +123,7 @@
             incrementGeneration(loader)
             differ.collectFrom(it)
         }
+        differ.hasCompleted.value = true
     }
 
     /**
@@ -144,6 +148,36 @@
     differ.snapshot().items
 }
 
+internal abstract class CompletablePagingDataDiffer<Value : Any>(
+    differCallback: DifferCallback,
+    mainContext: CoroutineContext,
+) : PagingDataDiffer<Value>(differCallback, mainContext) {
+    /**
+     * Marker that the underlying Flow<PagingData> has completed - e.g., every possible generation
+     * of data has been loaded completely.
+     */
+    val hasCompleted = MutableStateFlow(false)
+
+    val completableLoadStateFlow = loadStateFlow.combine(
+        hasCompleted
+    ) { loadStates, hasCompleted ->
+        if (hasCompleted) {
+            CombinedLoadStates(
+                refresh = LoadState.NotLoading(true),
+                prepend = LoadState.NotLoading(true),
+                append = LoadState.NotLoading(true),
+                source = LoadStates(
+                    refresh = LoadState.NotLoading(true),
+                    prepend = LoadState.NotLoading(true),
+                    append = LoadState.NotLoading(true)
+                )
+            )
+        } else {
+            loadStates
+        }
+    }
+}
+
 /**
  * Awaits until both source and mediator states are NotLoading. We do not care about the state of
  * endOfPaginationReached. Source and mediator states need to be checked individually because
@@ -155,10 +189,10 @@
  * incoming `Loading` state.
  */
 @OptIn(kotlinx.coroutines.FlowPreview::class)
-internal suspend fun <Value : Any> PagingDataDiffer<Value>.awaitNotLoading(
+internal suspend fun <Value : Any> CompletablePagingDataDiffer<Value>.awaitNotLoading(
     errorHandler: LoadErrorHandler
 ) {
-    val state = loadStateFlow.filterNotNull().debounce(1).filter {
+    val state = completableLoadStateFlow.filterNotNull().debounce(1).filter {
         it.isIdle() || it.hasError()
     }.firstOrNull()
 
diff --git a/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/SnapshotLoader.kt b/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/SnapshotLoader.kt
index 1c3f042..1ebbdbf 100644
--- a/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/SnapshotLoader.kt
+++ b/paging/paging-testing/src/androidMain/kotlin/androidx/paging/testing/SnapshotLoader.kt
@@ -41,7 +41,7 @@
  */
 @VisibleForTesting
 public class SnapshotLoader<Value : Any> internal constructor(
-    private val differ: PagingDataDiffer<Value>,
+    private val differ: CompletablePagingDataDiffer<Value>,
     private val errorHandler: LoadErrorHandler,
 ) {
     internal val generations = MutableStateFlow(Generation())
diff --git a/paging/paging-testing/src/androidTest/kotlin/androidx/paging/testing/PagerFlowSnapshotTest.kt b/paging/paging-testing/src/androidTest/kotlin/androidx/paging/testing/PagerFlowSnapshotTest.kt
index b8fcf62..d4bd050 100644
--- a/paging/paging-testing/src/androidTest/kotlin/androidx/paging/testing/PagerFlowSnapshotTest.kt
+++ b/paging/paging-testing/src/androidTest/kotlin/androidx/paging/testing/PagerFlowSnapshotTest.kt
@@ -16,8 +16,11 @@
 
 package androidx.paging.testing
 
+import androidx.paging.LoadState
+import androidx.paging.LoadStates
 import androidx.paging.Pager
 import androidx.paging.PagingConfig
+import androidx.paging.PagingData
 import androidx.paging.PagingSource
 import androidx.paging.PagingSource.LoadParams
 import androidx.paging.PagingSourceFactory
@@ -25,6 +28,7 @@
 import androidx.paging.cachedIn
 import androidx.paging.insertSeparators
 import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
 import kotlin.test.assertFailsWith
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
@@ -161,6 +165,36 @@
     }
 
     @Test
+    fun initialRefresh_PagingDataFrom_withoutLoadStates() {
+        val data = List(10) { it }
+        val pager = flowOf(PagingData.from(data))
+        testScope.runTest {
+            val snapshot = pager.asSnapshot()
+            // first page + prefetched page
+            assertThat(snapshot).containsExactlyElementsIn(
+                listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            )
+        }
+    }
+
+    @Test
+    fun initialRefresh_PagingDataFrom_withLoadStates() {
+        val data = List(10) { it }
+        val pager = flowOf(PagingData.from(data, LoadStates(
+            refresh = LoadState.NotLoading(true),
+            prepend = LoadState.NotLoading(true),
+            append = LoadState.NotLoading(true)
+        )))
+        testScope.runTest {
+            val snapshot = pager.asSnapshot()
+            // first page + prefetched page
+            assertThat(snapshot).containsExactlyElementsIn(
+                listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            )
+        }
+    }
+
+    @Test
     fun emptyInitialRefresh() {
         val dataFlow = emptyFlow<List<Int>>()
         val pager = createPager(dataFlow)
@@ -245,6 +279,40 @@
     }
 
     @Test
+    fun manualRefresh_PagingDataFrom_withoutLoadStates() {
+        val data = List(10) { it }
+        val pager = flowOf(PagingData.from(data))
+        testScope.runTest {
+            val snapshot = pager.asSnapshot {
+                refresh()
+            }
+            // first page + prefetched page
+            assertThat(snapshot).containsExactlyElementsIn(
+                listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            )
+        }
+    }
+
+    @Test
+    fun manualRefresh_PagingDataFrom_withLoadStates() {
+        val data = List(10) { it }
+        val pager = flowOf(PagingData.from(data, LoadStates(
+            refresh = LoadState.NotLoading(true),
+            prepend = LoadState.NotLoading(true),
+            append = LoadState.NotLoading(true)
+        )))
+        testScope.runTest {
+            val snapshot = pager.asSnapshot {
+                refresh()
+            }
+            // first page + prefetched page
+            assertThat(snapshot).containsExactlyElementsIn(
+                listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            )
+        }
+    }
+
+    @Test
     fun manualEmptyRefresh() {
         val dataFlow = emptyFlow<List<Int>>()
         val pager = createPagerNoPrefetch(dataFlow)
@@ -754,6 +822,75 @@
     }
 
     @Test
+    fun consecutiveGenerations_PagingDataFrom_withoutLoadStates() {
+        val loadDelay = 500 + loadDelay
+        // wait for 500 + loadDelay between each emission
+        val pager = flow {
+            emit(PagingData.empty())
+            delay(loadDelay)
+
+            emit(PagingData.from(List(10) { it }))
+            delay(loadDelay)
+
+            emit(PagingData.from(List(10) { it + 30 }))
+        }
+        testScope.runTest {
+            val snapshot1 = pager.asSnapshot()
+            assertWithMessage("Only the last generation should be loaded without LoadStates")
+                .that(snapshot1).containsExactlyElementsIn(
+                listOf(30, 31, 32, 33, 34, 35, 36, 37, 38, 39)
+            )
+        }
+    }
+
+    @Test
+    fun consecutiveGenerations_PagingDataFrom_withLoadStates() {
+        val loadDelay = 500 + loadDelay
+        // wait for 500 + loadDelay between each emission
+        val pager = flow {
+            emit(PagingData.empty(LoadStates(
+                refresh = LoadState.NotLoading(true),
+                prepend = LoadState.NotLoading(true),
+                append = LoadState.NotLoading(true)
+            )))
+            delay(loadDelay)
+
+            emit(PagingData.from(List(10) { it }, LoadStates(
+                refresh = LoadState.NotLoading(true),
+                prepend = LoadState.NotLoading(true),
+                append = LoadState.NotLoading(true)
+            )))
+            delay(loadDelay)
+
+            emit(PagingData.from(List(10) { it + 30 }, LoadStates(
+                refresh = LoadState.NotLoading(true),
+                prepend = LoadState.NotLoading(true),
+                append = LoadState.NotLoading(true)
+            )))
+        }.cachedIn(testScope.backgroundScope)
+        testScope.runTest {
+            val snapshot1 = pager.asSnapshot()
+            assertThat(snapshot1).containsExactlyElementsIn(
+                emptyList<Int>()
+            )
+
+            delay(loadDelay)
+
+            val snapshot2 = pager.asSnapshot()
+            assertThat(snapshot2).containsExactlyElementsIn(
+                listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+            )
+
+            delay(loadDelay)
+
+            val snapshot3 = pager.asSnapshot()
+            assertThat(snapshot3).containsExactlyElementsIn(
+                listOf(30, 31, 32, 33, 34, 35, 36, 37, 38, 39)
+            )
+        }
+    }
+
+    @Test
     fun consecutiveGenerations_fromSharedFlow_emitAfterRefresh() {
         val dataFlow = MutableSharedFlow<List<Int>>()
         val pager = createPagerNoPrefetch(dataFlow).cachedIn(testScope.backgroundScope)
diff --git a/playground-common/playground.properties b/playground-common/playground.properties
index 1734c38..b3b7970 100644
--- a/playground-common/playground.properties
+++ b/playground-common/playground.properties
@@ -25,6 +25,6 @@
 kotlin.code.style=official
 # Disable docs
 androidx.enableDocumentation=false
-androidx.playground.snapshotBuildId=10533165
+androidx.playground.snapshotBuildId=10710650
 androidx.playground.metalavaBuildId=10621923
 androidx.studio.type=playground
\ No newline at end of file
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
index d21ab11..cc6560b 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/PoolingContainerRecyclerViewTest.kt
@@ -338,10 +338,11 @@
         assertThat(adapter1.creations).isEqualTo(10)
 
         // Scroll to put some views into the shared pool
-        instrumentation.runOnMainSync {
-            rv1.smoothScrollBy(0, 100)
+        repeat(10) {
+            instrumentation.runOnMainSync {
+                rv1.scrollBy(0, 10)
+            }
         }
-        waitForIdleScroll(rv1)
 
         // The RV keeps a couple items in its view cache before returning them to the pool
         val expectedRecycledItems = 10 - itemViewCacheSize
diff --git a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewOnGenericMotionEventTest.java b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewOnGenericMotionEventTest.java
index 84d1fb3..e164745 100644
--- a/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewOnGenericMotionEventTest.java
+++ b/recyclerview/recyclerview/src/androidTest/java/androidx/recyclerview/widget/RecyclerViewOnGenericMotionEventTest.java
@@ -32,7 +32,8 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Px;
-import androidx.core.view.DifferentialMotionFlingHelper;
+import androidx.core.view.DifferentialMotionFlingController;
+import androidx.core.view.DifferentialMotionFlingTarget;
 import androidx.core.view.InputDeviceCompat;
 import androidx.core.view.ViewConfigurationCompat;
 import androidx.test.core.app.ApplicationProvider;
@@ -48,13 +49,13 @@
 public class RecyclerViewOnGenericMotionEventTest {
 
     TestRecyclerView mRecyclerView;
-    TestDifferentialMotionFlingHelper mFlingHelper;
+    TestDifferentialMotionFlingController mFlingController;
 
     @Before
     public void setUp() throws Exception {
         mRecyclerView = new TestRecyclerView(getContext());
-        mFlingHelper = createDummyFlingHelper();
-        mRecyclerView.mDifferentialMotionFlingHelper = mFlingHelper;
+        mFlingController = createDummyFlingController();
+        mRecyclerView.mDifferentialMotionFlingController = mFlingController;
     }
 
     private Context getContext() {
@@ -77,8 +78,8 @@
 
         assertTotalScroll(0, (int) (-2f * getScaledVerticalScrollFactor()),
                 /* assertSmoothScroll= */ false);
-        assertEquals(MotionEvent.AXIS_SCROLL, mFlingHelper.mLastAxis);
-        assertEquals(mRecyclerView.mLastGenericMotionEvent, mFlingHelper.mLastMotionEvent);
+        assertEquals(MotionEvent.AXIS_SCROLL, mFlingController.mLastAxis);
+        assertEquals(mRecyclerView.mLastGenericMotionEvent, mFlingController.mLastMotionEvent);
     }
 
     @Test
@@ -95,8 +96,8 @@
 
         assertTotalScroll((int) (2f * getScaledHorizontalScrollFactor()), 0,
                 /* assertSmoothScroll= */ false);
-        assertEquals(MotionEvent.AXIS_SCROLL, mFlingHelper.mLastAxis);
-        assertEquals(mRecyclerView.mLastGenericMotionEvent, mFlingHelper.mLastMotionEvent);
+        assertEquals(MotionEvent.AXIS_SCROLL, mFlingController.mLastAxis);
+        assertEquals(mRecyclerView.mLastGenericMotionEvent, mFlingController.mLastMotionEvent);
     }
 
     @Test
@@ -109,7 +110,7 @@
                 MotionEvent.AXIS_SCROLL, 2, InputDeviceCompat.SOURCE_ROTARY_ENCODER, mRecyclerView);
         assertTotalScroll(0, (int) (-2f * getScaledVerticalScrollFactor()),
                 /* assertSmoothScroll= */ true);
-        assertNull(mFlingHelper.mLastMotionEvent);
+        assertNull(mFlingController.mLastMotionEvent);
     }
 
     @Test
@@ -145,7 +146,7 @@
                 MotionEvent.AXIS_SCROLL, 2, InputDeviceCompat.SOURCE_ROTARY_ENCODER, mRecyclerView);
         assertTotalScroll((int) (2f * getScaledHorizontalScrollFactor()), 0,
                 /* assertSmoothScroll= */ true);
-        assertNull(mFlingHelper.mLastMotionEvent);
+        assertNull(mFlingController.mLastMotionEvent);
     }
 
     @Test
@@ -341,10 +342,10 @@
         }
     }
 
-    private TestDifferentialMotionFlingHelper createDummyFlingHelper() {
-        return new TestDifferentialMotionFlingHelper(
+    private TestDifferentialMotionFlingController createDummyFlingController() {
+        return new TestDifferentialMotionFlingController(
                 mRecyclerView.getContext(),
-                new DifferentialMotionFlingHelper.DifferentialMotionFlingTarget() {
+                new DifferentialMotionFlingTarget() {
                     @Override
                     public boolean startDifferentialMotionFling(float velocity) {
                         return false;
@@ -360,12 +361,13 @@
                 });
     }
 
-    private static class TestDifferentialMotionFlingHelper extends DifferentialMotionFlingHelper {
+    private static class TestDifferentialMotionFlingController extends
+            DifferentialMotionFlingController {
         MotionEvent mLastMotionEvent;
         int mLastAxis;
 
-        TestDifferentialMotionFlingHelper(Context context,
-                DifferentialMotionFlingHelper.DifferentialMotionFlingTarget target) {
+        TestDifferentialMotionFlingController(Context context,
+                DifferentialMotionFlingTarget target) {
             super(context, target);
         }
 
diff --git a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
index 5e2158a..16d96e4 100644
--- a/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
+++ b/recyclerview/recyclerview/src/main/java/androidx/recyclerview/widget/RecyclerView.java
@@ -72,7 +72,8 @@
 import androidx.core.os.TraceCompat;
 import androidx.core.util.Preconditions;
 import androidx.core.view.AccessibilityDelegateCompat;
-import androidx.core.view.DifferentialMotionFlingHelper;
+import androidx.core.view.DifferentialMotionFlingController;
+import androidx.core.view.DifferentialMotionFlingTarget;
 import androidx.core.view.InputDeviceCompat;
 import androidx.core.view.MotionEventCompat;
 import androidx.core.view.NestedScrollingChild2;
@@ -750,9 +751,9 @@
                 }
             };
 
-    private final DifferentialMotionFlingHelper.DifferentialMotionFlingTarget
+    private final DifferentialMotionFlingTarget
             mDifferentialMotionFlingTarget =
-            new DifferentialMotionFlingHelper.DifferentialMotionFlingTarget() {
+            new DifferentialMotionFlingTarget() {
                 @Override
                 public boolean startDifferentialMotionFling(float velocity) {
                     int vx = 0;
@@ -792,8 +793,8 @@
             };
 
     @VisibleForTesting
-    DifferentialMotionFlingHelper mDifferentialMotionFlingHelper =
-            new DifferentialMotionFlingHelper(getContext(), mDifferentialMotionFlingTarget);
+    DifferentialMotionFlingController mDifferentialMotionFlingController =
+            new DifferentialMotionFlingController(getContext(), mDifferentialMotionFlingTarget);
     public RecyclerView(@NonNull Context context) {
         this(context, null);
     }
@@ -4145,7 +4146,7 @@
             }
 
             if (flingAxis != 0 && !useSmoothScroll) {
-                mDifferentialMotionFlingHelper.onMotionEvent(event, flingAxis);
+                mDifferentialMotionFlingController.onMotionEvent(event, flingAxis);
             }
         }
         return false;
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
index 5d505b9..1503af9 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/XMethodElement.kt
@@ -47,6 +47,11 @@
     val returnType: XType
 
     /**
+     * The property name if this is a setter/getter method for a kotlin property.
+     */
+    val propertyName: String?
+
+    /**
      * The type representation of the method where more type parameters might be resolved.
      */
     override val executableType: XMethodType
@@ -134,6 +139,16 @@
      * the method name matches the property naming convention.
      */
     fun isKotlinPropertyMethod(): Boolean
+
+    /**
+     * Returns true if this method is a Kotlin property setter.
+     */
+    fun isKotlinPropertySetter(): Boolean
+
+    /**
+     * Returns true if this method is a Kotlin property getter.
+     */
+    fun isKotlinPropertyGetter(): Boolean
 }
 
 internal fun <T : XMethodElement> List<T>.filterMethodsByConfig(
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
index 4f87074..4151278 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/JavacMethodElement.kt
@@ -42,6 +42,10 @@
         }
     }
 
+    override val propertyName: String? by lazy {
+        if (isKotlinPropertyMethod()) kotlinMetadata?.propertyName else null
+    }
+
     override val name: String by lazy {
         kotlinMetadata?.name ?: jvmName
     }
@@ -183,4 +187,8 @@
     }
 
     override fun isKotlinPropertyMethod() = kotlinMetadata?.isPropertyFunction() ?: false
+
+    override fun isKotlinPropertySetter() = kotlinMetadata?.isPropertySetter() ?: false
+
+    override fun isKotlinPropertyGetter() = kotlinMetadata?.isPropertyGetter() ?: false
 }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
index 518aac9..0215dc4 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
@@ -223,7 +223,10 @@
     val typeParameters: List<KmTypeParameterContainer>
     val parameters: List<KmValueParameterContainer>
     val returnType: KmTypeContainer
+    val propertyName: String?
 
+    fun isPropertySetter() = false
+    fun isPropertyGetter() = false
     fun isSyntheticMethodForAnnotations() =
         (this as? KmPropertyFunctionContainerImpl)?.syntheticMethodForAnnotations == true
     fun isPropertyFunction() = this is KmPropertyFunctionContainerImpl
@@ -240,6 +243,7 @@
         get() = kmFunction.flags
     override val name: String
         get() = kmFunction.name
+    override val propertyName: String? = null
     override val jvmName: String
         get() = kmFunction.signature!!.name
     override val descriptor: String
@@ -257,9 +261,14 @@
     override val descriptor: String,
     override val parameters: List<KmValueParameterContainer>,
     override val returnType: KmTypeContainer,
+    override val propertyName: String?,
+    val isSetterMethod: Boolean,
+    val isGetterMethod: Boolean,
     val syntheticMethodForAnnotations: Boolean = false
 ) : KmFunctionContainer {
     override val typeParameters: List<KmTypeParameterContainer> = emptyList()
+    override fun isPropertySetter() = isSetterMethod
+    override fun isPropertyGetter() = isGetterMethod
 }
 
 internal class KmConstructorContainer(
@@ -269,6 +278,7 @@
     override val flags: Flags
         get() = kmConstructor.flags
     override val name: String = "<init>"
+    override val propertyName: String? = null
     override val jvmName: String = name
     override val descriptor: String
         get() = checkNotNull(kmConstructor.signature).asString()
@@ -441,6 +451,9 @@
                 descriptor = it.asString(),
                 parameters = emptyList(),
                 returnType = this.returnType.asContainer(),
+                propertyName = this.name,
+                isSetterMethod = false,
+                isGetterMethod = true,
             )
         },
         setter = setterSignature?.let {
@@ -459,6 +472,9 @@
                 descriptor = it.asString(),
                 parameters = listOf(param.asContainer()),
                 returnType = returnType.asContainer(),
+                propertyName = this.name,
+                isSetterMethod = true,
+                isGetterMethod = false,
             )
         },
         syntheticMethodForAnnotations = syntheticMethodForAnnotations?.let {
@@ -471,6 +487,9 @@
                 parameters = emptyList(),
                 returnType = returnType.asContainer(),
                 syntheticMethodForAnnotations = true,
+                propertyName = this.name,
+                isSetterMethod = false,
+                isGetterMethod = false,
             )
         },
     )
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
index c625ec1..e6008e3 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspBasicAnnotationProcessor.kt
@@ -70,13 +70,17 @@
         return emptyList()
     }
 
-    final override fun finish() {
+    final override fun finish() = runLastRound(reportMissingElements = true)
+
+    // Don't report missing elements when there's an error to avoid being too noisy.
+    final override fun onError() = runLastRound(reportMissingElements = false)
+
+    private fun runLastRound(reportMissingElements: Boolean) {
         val xRoundEnv = KspRoundEnv(xEnv, true)
         preRound(xEnv, xRoundEnv)
         val missingElements = commonDelegate.processLastRound()
         postRound(xEnv, xRoundEnv)
-        if (!xProcessingEnv.config.disableAnnotatedElementValidation && !logger.hasError) {
-            // Report missing elements if no error was raised to avoid being noisy.
+        if (!xProcessingEnv.config.disableAnnotatedElementValidation && reportMissingElements) {
             commonDelegate.reportMissingElements(missingElements)
         }
     }
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
index f795303..6e807b2 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspMethodElement.kt
@@ -46,6 +46,8 @@
     override val name: String
         get() = declaration.simpleName.asString()
 
+    override val propertyName = null
+
     @OptIn(KspExperimental::class)
     override val jvmName: String by lazy {
         if (!isKotlinPropertyMethod()) {
@@ -144,6 +146,10 @@
         return env.resolver.overrides(this, other)
     }
 
+    override fun isKotlinPropertySetter() = false
+
+    override fun isKotlinPropertyGetter() = false
+
     override fun isKotlinPropertyMethod() = false
 
     abstract override val returnType: KspType
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index 9f039d6..1247381 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -67,6 +67,8 @@
         accessor
     ) {
 
+    override val propertyName = field.name
+
     @OptIn(KspExperimental::class)
     override val jvmName: String by lazy {
         env.resolver.getJvmName(accessor) ?: error("Cannot find the name for accessor $accessor")
@@ -174,6 +176,10 @@
             filter = NO_USE_SITE_OR_GETTER
         ) {
 
+        override fun isKotlinPropertySetter() = false
+
+        override fun isKotlinPropertyGetter() = true
+
         override val name: String by lazy {
             JvmAbi.computeGetterName(field.declaration.simpleName.asString())
         }
@@ -218,6 +224,10 @@
             filter = NO_USE_SITE_OR_SETTER
         ) {
 
+        override fun isKotlinPropertySetter() = true
+
+        override fun isKotlinPropertyGetter() = false
+
         override val name by lazy {
             JvmAbi.computeSetterName(field.declaration.simpleName.asString())
         }
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
index d956499..fa78733 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XProcessingStepTest.kt
@@ -948,6 +948,63 @@
     }
 
     @Test
+    fun kspProcessingStepLogsError() {
+        val main = Source.kotlin(
+            "Classes.kt",
+            """
+            package foo.bar
+            import androidx.room.compiler.processing.testcode.*
+            @MainAnnotation(
+                typeList = [],
+                singleType = Any::class,
+                intMethod = 3,
+                singleOtherAnnotation = OtherAnnotation("y")
+            )
+            class Main {
+            }
+            @OtherAnnotation("y")
+            class Other {
+            }
+            """.trimIndent()
+        )
+
+        var executedLastRound = false
+        val processorProvider = object : SymbolProcessorProvider {
+            override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
+                return object : KspBasicAnnotationProcessor(environment) {
+                    override fun processingSteps() = listOf(
+                        object : XProcessingStep {
+                            override fun annotations() =
+                              setOf(MainAnnotation::class.qualifiedName!!)
+                            override fun process(
+                                env: XProcessingEnv,
+                                elementsByAnnotation: Map<String, Set<XElement>>,
+                                isLastRound: Boolean
+                            ): Set<XElement> {
+                                if (isLastRound) {
+                                    executedLastRound = true
+                                }
+                                environment.logger.error("logs error")
+                                return emptySet()
+                            }
+                        }
+                    )
+                }
+            }
+        }
+
+        compile(
+            workingDir = temporaryFolder.root,
+            arguments = TestCompilationArguments(
+                sources = listOf(main),
+                symbolProcessorProviders = listOf(processorProvider)
+            )
+        )
+
+        assertThat(executedLastRound).isTrue()
+    }
+
+    @Test
     fun kspAnnotatedElementsByStep() {
         val main = Source.kotlin(
             "Classes.kt",
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index 5b165ae..5633347 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -807,16 +807,46 @@
                     ).containsExactly(
                         "getMutable", "setMutable", "getImmutable"
                     )
-                methods.forEach {
-                    assertWithMessage("${subject.qualifiedName}.${it.jvmName}()")
-                        .that(it.isKotlinPropertyMethod())
-                        .apply {
-                            if (subject.name.contains("Kotlin")) {
-                                isTrue()
-                            } else {
-                                isFalse()
-                            }
-                        }
+
+                subject.getDeclaredMethodByJvmName("getMutable").let {
+                    if (subject.name.contains("Kotlin")) {
+                        assertThat(it.isKotlinPropertyMethod()).isTrue()
+                        assertThat(it.isKotlinPropertySetter()).isFalse()
+                        assertThat(it.isKotlinPropertyGetter()).isTrue()
+                        assertThat(it.propertyName).isEqualTo("mutable")
+                    } else {
+                        assertThat(it.isKotlinPropertyMethod()).isFalse()
+                        assertThat(it.isKotlinPropertySetter()).isFalse()
+                        assertThat(it.isKotlinPropertyGetter()).isFalse()
+                        assertThat(it.propertyName).isNull()
+                    }
+                }
+
+                subject.getDeclaredMethodByJvmName("setMutable").let {
+                    if (subject.name.contains("Kotlin")) {
+                        assertThat(it.isKotlinPropertyMethod()).isTrue()
+                        assertThat(it.isKotlinPropertySetter()).isTrue()
+                        assertThat(it.propertyName).isEqualTo("mutable")
+                    } else {
+                        assertThat(it.isKotlinPropertyMethod()).isFalse()
+                        assertThat(it.isKotlinPropertySetter()).isFalse()
+                        assertThat(it.isKotlinPropertyGetter()).isFalse()
+                        assertThat(it.propertyName).isNull()
+                    }
+                }
+
+                subject.getDeclaredMethodByJvmName("getImmutable").let {
+                    if (subject.name.contains("Kotlin")) {
+                        assertThat(it.isKotlinPropertyMethod()).isTrue()
+                        assertThat(it.isKotlinPropertySetter()).isFalse()
+                        assertThat(it.isKotlinPropertyGetter()).isTrue()
+                        assertThat(it.propertyName).isEqualTo("immutable")
+                    } else {
+                        assertThat(it.isKotlinPropertyMethod()).isFalse()
+                        assertThat(it.isKotlinPropertySetter()).isFalse()
+                        assertThat(it.isKotlinPropertyGetter()).isFalse()
+                        assertThat(it.propertyName).isNull()
+                    }
                 }
             }
         }
@@ -836,9 +866,11 @@
             val subject = it.processingEnv.requireTypeElement("Subject")
             val fields = subject.getDeclaredFields()
             assertThat(fields).isEmpty()
+
             val method = subject.getDeclaredMethodByJvmName("getMyLazy")
             assertThat(method).isNotNull()
             assertThat(method.isKotlinPropertyMethod()).isTrue()
+            assertThat(method.isKotlinPropertySetter()).isFalse()
         }
     }
 
diff --git a/room/room-compiler/build.gradle b/room/room-compiler/build.gradle
index c73ef07..31eeab1 100644
--- a/room/room-compiler/build.gradle
+++ b/room/room-compiler/build.gradle
@@ -19,6 +19,8 @@
 import androidx.build.SdkHelperKt
 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
 
+import java.util.regex.Matcher
+import java.util.regex.Pattern
 import java.util.zip.ZipEntry
 import java.util.zip.ZipFile
 
@@ -49,12 +51,6 @@
     // set classifier to empty string so that it doesn't append anything to the jar.
     archiveClassifier = ""
     configurations = [project.configurations.shadowed]
-    dependencies {
-        // antlr has dependencies on unrelated projects for its gui stuff, do not include them
-        exclude(dependency("org.abego.treelayout:.*"))
-        exclude(dependency("org.glassfish:.*"))
-        exclude(dependency("com.ibm.icu:.*"))
-    }
     relocate("org.antlr", "androidx.room.jarjarred.org.antlr")
     relocate("org.stringtemplate", "androidx.room.jarjarred.org.stringtemplate")
 }
@@ -91,7 +87,12 @@
     implementation(libs.kotlinPoet)
     implementation(libs.kotlinPoetJavaPoet)
     implementation(libs.kspApi)
-    shadowed(libs.antlr4)
+    shadowed(libs.antlr4) {
+        // antlr has dependencies on unrelated projects for its gui stuff, do not include them
+        exclude group: "org.abego.treelayout"
+        exclude group: "com.ibm.icu"
+        exclude group: "org.glassfish"
+    }
     implementation(libs.sqliteJdbc)
     implementation(libs.apacheCommonsCodec)
     implementation(libs.intellijAnnotations)
@@ -226,7 +227,9 @@
             throw new GradleException("Cannot find the pom file for room-compiler")
         }
         def pomContents = pom.newReader().text
-        if (pomContents.contains("antlr")) {
+        Pattern antlrDep = Pattern.compile("<dependency>\\s.*antlr(.*\\s)*</dependency>")
+        Matcher matcher = antlrDep.matcher(pomContents)
+        if (matcher.find()) {
             throw new GradleException("Room-compiler pom file should not depend on antlr.\n" +
                     "Pom Contents:\n $pomContents")
         }
@@ -298,4 +301,8 @@
     type = LibraryType.ANNOTATION_PROCESSOR
     inceptionYear = "2017"
     description = "Android Room annotation processor"
+    license { // jarjared antlr library
+        name = "BSD licence"
+        url = "http://antlr.org/license.html"
+    }
 }
diff --git a/samples/MediaRoutingDemo/src/main/java/com/example/androidx/mediarouting/RoutesManager.java b/samples/MediaRoutingDemo/src/main/java/com/example/androidx/mediarouting/RoutesManager.java
index 94676b4..fff9c40 100644
--- a/samples/MediaRoutingDemo/src/main/java/com/example/androidx/mediarouting/RoutesManager.java
+++ b/samples/MediaRoutingDemo/src/main/java/com/example/androidx/mediarouting/RoutesManager.java
@@ -109,13 +109,13 @@
     }
 
     /**
-     * Gets the route with the passed id or null if not exists.
+     * Gets the route with the passed id, or null if no route with the given id exists.
      *
      * @param id of the route to search for.
-     * @return the route with the passed id or null if not exists.
+     * @return the route with the passed id, or null if it does not exist.
      */
     @Nullable
-    public RouteItem getRouteWithId(@NonNull String id) {
+    public RouteItem getRouteWithId(@Nullable String id) {
         return mRouteItems.get(id);
     }
 
diff --git a/security/security-crypto/gradle/wrapper/gradle-wrapper.jar b/security/security-crypto/gradle/wrapper/gradle-wrapper.jar
deleted file mode 100644
index f6b961f..0000000
--- a/security/security-crypto/gradle/wrapper/gradle-wrapper.jar
+++ /dev/null
Binary files differ
diff --git a/security/security-crypto/gradle/wrapper/gradle-wrapper.properties b/security/security-crypto/gradle/wrapper/gradle-wrapper.properties
deleted file mode 100644
index cd7db12..0000000
--- a/security/security-crypto/gradle/wrapper/gradle-wrapper.properties
+++ /dev/null
@@ -1,6 +0,0 @@
-#Tue Feb 19 15:29:35 UTC 2019
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
diff --git a/security/security-crypto/gradlew b/security/security-crypto/gradlew
deleted file mode 100644
index cccdd3d..0000000
--- a/security/security-crypto/gradlew
+++ /dev/null
@@ -1,172 +0,0 @@
-#!/usr/bin/env sh
-
-##############################################################################
-##
-##  Gradle start up script for UN*X
-##
-##############################################################################
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn () {
-    echo "$*"
-}
-
-die () {
-    echo
-    echo "$*"
-    echo
-    exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-nonstop=false
-case "`uname`" in
-  CYGWIN* )
-    cygwin=true
-    ;;
-  Darwin* )
-    darwin=true
-    ;;
-  MINGW* )
-    msys=true
-    ;;
-  NONSTOP* )
-    nonstop=true
-    ;;
-esac
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
-    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
-        # IBM's JDK on AIX uses strange locations for the executables
-        JAVACMD="$JAVA_HOME/jre/sh/java"
-    else
-        JAVACMD="$JAVA_HOME/bin/java"
-    fi
-    if [ ! -x "$JAVACMD" ] ; then
-        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-    fi
-else
-    JAVACMD="java"
-    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
-    MAX_FD_LIMIT=`ulimit -H -n`
-    if [ $? -eq 0 ] ; then
-        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
-            MAX_FD="$MAX_FD_LIMIT"
-        fi
-        ulimit -n $MAX_FD
-        if [ $? -ne 0 ] ; then
-            warn "Could not set maximum file descriptor limit: $MAX_FD"
-        fi
-    else
-        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
-    fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
-    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
-    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
-    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-    JAVACMD=`cygpath --unix "$JAVACMD"`
-
-    # We build the pattern for arguments to be converted via cygpath
-    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
-    SEP=""
-    for dir in $ROOTDIRSRAW ; do
-        ROOTDIRS="$ROOTDIRS$SEP$dir"
-        SEP="|"
-    done
-    OURCYGPATTERN="(^($ROOTDIRS))"
-    # Add a user-defined pattern to the cygpath arguments
-    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
-        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
-    fi
-    # Now convert the arguments - kludge to limit ourselves to /bin/sh
-    i=0
-    for arg in "$@" ; do
-        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
-        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
-
-        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
-            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
-        else
-            eval `echo args$i`="\"$arg\""
-        fi
-        i=$((i+1))
-    done
-    case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
-    esac
-fi
-
-# Escape application args
-save () {
-    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
-    echo " "
-}
-APP_ARGS=$(save "$@")
-
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
-
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
-  cd "$(dirname "$0")"
-fi
-
-exec "$JAVACMD" "$@"
diff --git a/security/security-crypto/gradlew.bat b/security/security-crypto/gradlew.bat
deleted file mode 100644
index f9553162..0000000
--- a/security/security-crypto/gradlew.bat
+++ /dev/null
@@ -1,84 +0,0 @@
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
diff --git a/settings.gradle b/settings.gradle
index a6dd45a..75096da 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -593,6 +593,7 @@
 includeProject(":compose:material3:material3", [BuildType.COMPOSE])
 includeProject(":compose:material3:benchmark", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-adaptive", [BuildType.COMPOSE])
+includeProject(":compose:material3:material3-adaptive:material3-adaptive-samples", "compose/material3/material3-adaptive/samples", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-lint", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-window-size-class", [BuildType.COMPOSE])
 includeProject(":compose:material3:material3-window-size-class:material3-window-size-class-samples", "compose/material3/material3-window-size-class/samples", [BuildType.COMPOSE])
@@ -602,11 +603,6 @@
 includeProject(":compose:material:material-icons-core", [BuildType.COMPOSE])
 includeProject(":compose:material:material-icons-core:material-icons-core-samples", "compose/material/material-icons-core/samples", [BuildType.COMPOSE])
 includeProject(":compose:material:material-icons-extended", [BuildType.COMPOSE])
-includeProject(":compose:material:material-icons-extended-filled", [BuildType.COMPOSE])
-includeProject(":compose:material:material-icons-extended-outlined", [BuildType.COMPOSE])
-includeProject(":compose:material:material-icons-extended-rounded", [BuildType.COMPOSE])
-includeProject(":compose:material:material-icons-extended-sharp", [BuildType.COMPOSE])
-includeProject(":compose:material:material-icons-extended-twotone", [BuildType.COMPOSE])
 includeProject(":compose:material:material-ripple", [BuildType.COMPOSE])
 includeProject(":compose:material:material-ripple:material-ripple-benchmark", "compose/material/material-ripple/benchmark", [BuildType.COMPOSE])
 includeProject(":compose:material:material:icons:generator", [BuildType.COMPOSE])
@@ -767,7 +763,9 @@
 includeProject(":glance:glance-appwidget", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget-preview", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget-proto", [BuildType.GLANCE])
+includeProject(":glance:glance-appwidget-testing", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget:glance-appwidget-samples", "glance/glance-appwidget/samples", [BuildType.GLANCE])
+includeProject(":glance:glance-appwidget-testing:glance-appwidget-testing-samples", "glance/glance-appwidget-testing/samples", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget:integration-tests:demos", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget:integration-tests:macrobenchmark", [BuildType.GLANCE])
 includeProject(":glance:glance-appwidget:integration-tests:macrobenchmark-target", [BuildType.GLANCE])
@@ -886,7 +884,7 @@
 includeProject(":navigation:navigation-ui", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":navigation:navigation-ui-ktx", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":paging:integration-tests:testapp", [BuildType.MAIN])
-includeProject(":paging:paging-common", [BuildType.MAIN, BuildType.COMPOSE])
+includeProject(":paging:paging-common", [BuildType.MAIN, BuildType.COMPOSE, BuildType.INFRAROGUE, BuildType.KMP])
 includeProject(":paging:paging-common-ktx", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":paging:paging-compose", [BuildType.COMPOSE])
 includeProject(":paging:paging-compose:paging-compose-samples", "paging/paging-compose/samples", [BuildType.COMPOSE])
@@ -1234,8 +1232,11 @@
 // for each size and test runner is happy when there is nothing to test.
 includeProject(":placeholder-tests")
 
-// Workaround for b/203825166
-includeBuild("placeholder")
+// Add includedBuild in most cases for b/203825166
+// Skip adding includeBuild when regenerating signatures for https://github.com/gradle/gradle/issues/26179
+if (!startParameter.projectProperties.containsKey('androidx.update.signatures')) {
+    includeBuild("placeholder")
+}
 
 // ---------------------------------------------------------------------
 // --- there should be no includeProject additions after this line -----
diff --git a/test/screenshot/screenshot-proto/build.gradle b/test/screenshot/screenshot-proto/build.gradle
index 64fcb99..6940586 100644
--- a/test/screenshot/screenshot-proto/build.gradle
+++ b/test/screenshot/screenshot-proto/build.gradle
@@ -44,19 +44,3 @@
         }
     }
 }
-
-// Create export artifact for for JarJaring
-def preferencesProtoJarJarTask = tasks.register("exportJar", Jar) {
-    archiveBaseName.set("export")
-    from(sourceSets.main.output)
-    // The proto-lite dependency includes .proto files, which are not used by screenshots. When apps
-    // depend on screenshot as well as proto-lite directly, these files conflict since jarjar only
-    // renames the java classes. Remove them here since they are unused.
-    exclude("**/*.proto")
-
-    from(zipTree(configurations.detachedConfiguration(
-            dependencies.create(libs.protobufLite.get())).getSingleFile()))
-}
-
-def jarjarConf = configurations.register("export")
-artifacts.add(jarjarConf.name, preferencesProtoJarJarTask.flatMap { it.archiveFile })
\ No newline at end of file
diff --git a/test/screenshot/screenshot/build.gradle b/test/screenshot/screenshot/build.gradle
index 69303c3..e379b51 100644
--- a/test/screenshot/screenshot/build.gradle
+++ b/test/screenshot/screenshot/build.gradle
@@ -26,11 +26,14 @@
 BundleInsideHelper.forInsideAar(
         project,
         /* from = */ "com.google.protobuf",
-        /* to =   */ "androidx.test.screenshot.protobuf"
+        /* to =   */ "androidx.test.screenshot.protobuf",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
-    bundleInside(project(path: ":test:screenshot:screenshot-proto", configuration: "export"))
+    bundleInside(project(":test:screenshot:screenshot-proto"))
     implementation("androidx.annotation:annotation:1.0.0")
     implementation("androidx.core:core:1.5.0-rc02")
 
diff --git a/test/uiautomator/OWNERS b/test/uiautomator/OWNERS
index 5c7f452..2372f21 100644
--- a/test/uiautomator/OWNERS
+++ b/test/uiautomator/OWNERS
@@ -1,4 +1,5 @@
 # Bug component: 833089
 peykov@google.com
 normancheung@google.com
-guran@google.com
+fangqiu@google.com
+yichunli@google.com
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/MultiDisplayTest.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/MultiDisplayTest.java
index 2f5280b..cb2192a 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/MultiDisplayTest.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/MultiDisplayTest.java
@@ -131,7 +131,7 @@
     }
 
     @Test
-    public void testMultiDisplay_orientations() throws Exception {
+    public void testMultiDisplay_orientations() {
         int secondaryDisplayId = getSecondaryDisplayId();
 
         try {
diff --git a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
index 67efd97..c3cb579 100644
--- a/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
+++ b/test/uiautomator/integration-tests/testapp/src/androidTest/java/androidx/test/uiautomator/testapp/UiObject2Test.java
@@ -32,6 +32,7 @@
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 
+import androidx.annotation.NonNull;
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.filters.SdkSuppress;
 import androidx.test.uiautomator.By;
@@ -716,6 +717,12 @@
                         }
                         return false;
                     }
+
+                    @NonNull
+                    @Override
+                    public String toString() {
+                        return "EventCondition[LONG_CLICK]";
+                    }
                 });
         assertNull(result);
         // We still scroll to the end when event condition never occurs.
diff --git a/test/uiautomator/uiautomator/api/current.txt b/test/uiautomator/uiautomator/api/current.txt
index 23d1c7c..331f108 100644
--- a/test/uiautomator/uiautomator/api/current.txt
+++ b/test/uiautomator/uiautomator/api/current.txt
@@ -174,7 +174,7 @@
     method public androidx.test.uiautomator.UiObject findObject(androidx.test.uiautomator.UiSelector);
     method public java.util.List<androidx.test.uiautomator.UiObject2!> findObjects(androidx.test.uiautomator.BySelector);
     method public void freezeRotation() throws android.os.RemoteException;
-    method @RequiresApi(30) public void freezeRotation(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void freezeRotation(int);
     method @Deprecated public String! getCurrentActivityName();
     method public String! getCurrentPackageName();
     method @Px public int getDisplayHeight();
@@ -220,22 +220,22 @@
     method @Deprecated public void setCompressedLayoutHeirarchy(boolean);
     method public void setCompressedLayoutHierarchy(boolean);
     method public void setOrientationLandscape() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationLandscape(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationLandscape(int);
     method public void setOrientationLeft() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationLeft(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationLeft(int);
     method public void setOrientationNatural() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationNatural(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationNatural(int);
     method public void setOrientationPortrait() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationPortrait(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationPortrait(int);
     method public void setOrientationRight() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationRight(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationRight(int);
     method public void sleep() throws android.os.RemoteException;
     method public boolean swipe(android.graphics.Point![], int);
     method public boolean swipe(int, int, int, int, int);
     method public boolean takeScreenshot(java.io.File);
     method public boolean takeScreenshot(java.io.File, float, int);
     method public void unfreezeRotation() throws android.os.RemoteException;
-    method @RequiresApi(30) public void unfreezeRotation(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void unfreezeRotation(int);
     method public <U> U! wait(androidx.test.uiautomator.Condition<? super androidx.test.uiautomator.UiDevice,U!>, long);
     method public <U> U! wait(androidx.test.uiautomator.SearchCondition<U!>, long);
     method public void waitForIdle();
diff --git a/test/uiautomator/uiautomator/api/restricted_current.txt b/test/uiautomator/uiautomator/api/restricted_current.txt
index 23d1c7c..331f108 100644
--- a/test/uiautomator/uiautomator/api/restricted_current.txt
+++ b/test/uiautomator/uiautomator/api/restricted_current.txt
@@ -174,7 +174,7 @@
     method public androidx.test.uiautomator.UiObject findObject(androidx.test.uiautomator.UiSelector);
     method public java.util.List<androidx.test.uiautomator.UiObject2!> findObjects(androidx.test.uiautomator.BySelector);
     method public void freezeRotation() throws android.os.RemoteException;
-    method @RequiresApi(30) public void freezeRotation(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void freezeRotation(int);
     method @Deprecated public String! getCurrentActivityName();
     method public String! getCurrentPackageName();
     method @Px public int getDisplayHeight();
@@ -220,22 +220,22 @@
     method @Deprecated public void setCompressedLayoutHeirarchy(boolean);
     method public void setCompressedLayoutHierarchy(boolean);
     method public void setOrientationLandscape() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationLandscape(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationLandscape(int);
     method public void setOrientationLeft() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationLeft(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationLeft(int);
     method public void setOrientationNatural() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationNatural(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationNatural(int);
     method public void setOrientationPortrait() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationPortrait(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationPortrait(int);
     method public void setOrientationRight() throws android.os.RemoteException;
-    method @RequiresApi(30) public void setOrientationRight(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void setOrientationRight(int);
     method public void sleep() throws android.os.RemoteException;
     method public boolean swipe(android.graphics.Point![], int);
     method public boolean swipe(int, int, int, int, int);
     method public boolean takeScreenshot(java.io.File);
     method public boolean takeScreenshot(java.io.File, float, int);
     method public void unfreezeRotation() throws android.os.RemoteException;
-    method @RequiresApi(30) public void unfreezeRotation(int) throws android.os.RemoteException;
+    method @RequiresApi(30) public void unfreezeRotation(int);
     method public <U> U! wait(androidx.test.uiautomator.Condition<? super androidx.test.uiautomator.UiDevice,U!>, long);
     method public <U> U! wait(androidx.test.uiautomator.SearchCondition<U!>, long);
     method public void waitForIdle();
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
index 005aa1c..742176d 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/GestureController.java
@@ -25,6 +25,8 @@
 import android.view.MotionEvent.PointerCoords;
 import android.view.MotionEvent.PointerProperties;
 
+import androidx.annotation.NonNull;
+
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -282,6 +284,12 @@
         public void run() {
             performGesture(mGestures);
         }
+
+        @NonNull
+        @Override
+        public String toString() {
+            return Arrays.toString(mGestures);
+        }
     }
 
     UiDevice getDevice() {
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/PointerGesture.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/PointerGesture.java
index 173e7e8..7f9bd815 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/PointerGesture.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/PointerGesture.java
@@ -18,6 +18,8 @@
 
 import android.graphics.Point;
 
+import androidx.annotation.NonNull;
+
 import java.util.ArrayDeque;
 import java.util.Deque;
 
@@ -108,6 +110,11 @@
         return mActions.peekLast().end;
     }
 
+    @NonNull
+    @Override
+    public String toString() {
+        return mActions.toString();
+    }
 
     /** A {@link PointerAction} represents part of a {@link PointerGesture}. */
     private static abstract class PointerAction {
@@ -135,6 +142,12 @@
         public Point interpolate(float fraction) {
             return new Point(start);
         }
+
+        @NonNull
+        @Override
+        public String toString() {
+            return String.format("Pause(point=%s, duration=%dms)", start, duration);
+        }
     }
 
     /** Action that moves the pointer between two points at a constant speed. */
@@ -151,6 +164,12 @@
             return ret;
         }
 
+        @NonNull
+        @Override
+        public String toString() {
+            return String.format("Move(start=%s, end=%s, duration=%dms)", start, end, duration);
+        }
+
         private static double calcDistance(final Point a, final Point b) {
             return Math.sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
         }
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiDevice.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiDevice.java
index d114a60..e73b936 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiDevice.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiDevice.java
@@ -846,11 +846,10 @@
      * Freezes the rotation of the display with {@code displayId} at its current state.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void freezeRotation(int displayId) throws RemoteException {
+    public void freezeRotation(int displayId) {
         Log.d(TAG, String.format("Freezing rotation on display %d.", displayId));
         try {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -889,11 +888,10 @@
      * to this method.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void unfreezeRotation(int displayId) throws RemoteException {
+    public void unfreezeRotation(int displayId) {
         Log.d(TAG, String.format("Unfreezing rotation on display %d.", displayId));
         try {
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -929,11 +927,10 @@
      * {@link #setOrientationLandscape()}.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void setOrientationLeft(int displayId) throws RemoteException {
+    public void setOrientationLeft(int displayId) {
         Log.d(TAG, String.format("Setting orientation to left on display %d.", displayId));
         rotateWithCommand(Surface.ROTATION_90, displayId);
     }
@@ -959,11 +956,10 @@
      * {@link #setOrientationLandscape()}.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void setOrientationRight(int displayId) throws RemoteException {
+    public void setOrientationRight(int displayId) {
         Log.d(TAG, String.format("Setting orientation to right on display %d.", displayId));
         rotateWithCommand(Surface.ROTATION_270, displayId);
     }
@@ -987,11 +983,10 @@
      * Consider using {@link #setOrientationPortrait()} and {@link #setOrientationLandscape()}.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void setOrientationNatural(int displayId) throws RemoteException {
+    public void setOrientationNatural(int displayId) {
         Log.d(TAG, String.format("Setting orientation to natural on display %d.", displayId));
         rotateWithCommand(Surface.ROTATION_0, displayId);
     }
@@ -1017,11 +1012,10 @@
      * freezes rotation. Use {@link #unfreezeRotation()} to un-freeze the rotation.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void setOrientationPortrait(int displayId) throws RemoteException {
+    public void setOrientationPortrait(int displayId) {
         Log.d(TAG, String.format("Setting orientation to portrait on display %d.", displayId));
         if (getDisplayHeight(displayId) >= getDisplayWidth(displayId)) {
             freezeRotation(displayId); // Already in portrait orientation.
@@ -1053,11 +1047,10 @@
      * freezes rotation. Use {@link #unfreezeRotation()} to un-freeze the rotation.
      * <p>Note: Only works on Android API level 30 (R) or above, where multi-display is
      * officially supported.
-     * @throws RemoteException never
      * @see Display#getDisplayId()
      */
     @RequiresApi(30)
-    public void setOrientationLandscape(int displayId) throws RemoteException {
+    public void setOrientationLandscape(int displayId) {
         Log.d(TAG, String.format("Setting orientation to landscape on display %d.", displayId));
         if (getDisplayWidth(displayId) >= getDisplayHeight(displayId)) {
             freezeRotation(displayId); // Already in landscape orientation.
diff --git a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
index f0cbd68..c914f837 100644
--- a/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
+++ b/test/uiautomator/uiautomator/src/main/java/androidx/test/uiautomator/UiObject2.java
@@ -308,25 +308,6 @@
         return getVisibleBounds(getAccessibilityNodeInfo());
     }
 
-    /** Returns this object's visible bounds with the margins removed. */
-    private Rect getVisibleBoundsForGestures() {
-        Rect ret = getVisibleBounds();
-        return mMargins.apply(ret);
-    }
-
-    /** Updates a {@code point} to ensure it is within this object's visible bounds. */
-    private boolean clipToGestureBounds(Point point) {
-        final Rect bounds = getVisibleBoundsForGestures();
-        if (bounds.contains(point.x, point.y)) {
-            return true;
-        }
-        Log.d(TAG, String.format("Clipping out-of-bound (%d, %d) into %s.", point.x, point.y,
-                bounds));
-        point.x = Math.max(bounds.left, Math.min(point.x, bounds.right));
-        point.y = Math.max(bounds.top, Math.min(point.y, bounds.bottom));
-        return false;
-    }
-
     /** Returns the visible bounds of a {@code node}. */
     private Rect getVisibleBounds(AccessibilityNodeInfo node) {
         Point displaySize = getDevice().getDisplaySize(getDisplayId());
@@ -337,10 +318,40 @@
     /** Returns a point in the center of this object's visible bounds. */
     @NonNull
     public Point getVisibleCenter() {
-        Rect bounds = getVisibleBounds();
+        return getVisibleCenter(getAccessibilityNodeInfo());
+    }
+
+    /** Returns a point in the center of the {@code node}'s visible bounds. */
+    @NonNull
+    private Point getVisibleCenter(AccessibilityNodeInfo node) {
+        Rect bounds = getVisibleBounds(node);
         return new Point(bounds.centerX(), bounds.centerY());
     }
 
+    /** Returns this object's visible bounds with the margins removed. */
+    private Rect getVisibleBoundsForGestures() {
+        return getVisibleBoundsForGestures(getAccessibilityNodeInfo());
+    }
+
+    /** Returns the {@code node}'s visible bounds with the margins removed. */
+    private Rect getVisibleBoundsForGestures(AccessibilityNodeInfo node) {
+        Rect ret = getVisibleBounds(node);
+        return mMargins.apply(ret);
+    }
+
+    /** Updates a {@code point} to ensure it is within the {@code node}'s visible bounds. */
+    private boolean clipToGestureBounds(Point point, AccessibilityNodeInfo node) {
+        final Rect bounds = getVisibleBoundsForGestures(node);
+        if (bounds.contains(point.x, point.y)) {
+            return true;
+        }
+        Log.d(TAG, String.format("Clipping out-of-bound (%d, %d) into %s.", point.x, point.y,
+                bounds));
+        point.x = Math.max(bounds.left, Math.min(point.x, bounds.right));
+        point.y = Math.max(bounds.top, Math.min(point.y, bounds.bottom));
+        return false;
+    }
+
     /** Returns the class name of this object's underlying {@link View}. */
     @SuppressLint("UnknownNullness") // Avoid unnecessary null checks from nullable testing APIs.
     public String getClassName() {
@@ -482,8 +493,12 @@
 
     /** Clicks on this object's center. */
     public void click() {
-        Point center = getVisibleCenter();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Point center = getVisibleCenter(node);
         Log.d(TAG, String.format("Clicking on (%d, %d).", center.x, center.y));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         mGestureController.performGesture(Gestures.click(center, getDisplayId()));
     }
 
@@ -493,15 +508,23 @@
      * @param point The point to click (clipped to ensure it is within the visible bounds).
      */
     public void click(@NonNull Point point) {
-        clipToGestureBounds(point);
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        clipToGestureBounds(point, node);
         Log.d(TAG, String.format("Clicking on (%d, %d).", point.x, point.y));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         mGestureController.performGesture(Gestures.click(point, getDisplayId()));
     }
 
     /** Clicks on this object's center for {@code duration} milliseconds. */
     public void click(long duration) {
-        Point center = getVisibleCenter();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Point center = getVisibleCenter(node);
         Log.d(TAG, String.format("Clicking on (%d, %d) for %dms.", center.x, center.y, duration));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         mGestureController.performGesture(Gestures.click(center, duration, getDisplayId()));
     }
 
@@ -512,8 +535,12 @@
      * @param duration The click duration in milliseconds.
      */
     public void click(@NonNull Point point, long duration) {
-        clipToGestureBounds(point);
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        clipToGestureBounds(point, node);
         Log.d(TAG, String.format("Clicking on (%d, %d) for %dms.", point.x, point.y, duration));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         mGestureController.performGesture(Gestures.click(point, duration, getDisplayId()));
     }
 
@@ -524,9 +551,13 @@
      * @param timeout   The maximum time in milliseconds to wait for.
      */
     public <U> U clickAndWait(@NonNull EventCondition<U> condition, long timeout) {
-        Point center = getVisibleCenter();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Point center = getVisibleCenter(node);
         Log.d(TAG, String.format("Clicking on (%d, %d) and waiting %dms for %s.", center.x,
                 center.y, timeout, condition));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         return mGestureController.performGestureAndWait(condition, timeout,
                 Gestures.click(center, getDisplayId()));
     }
@@ -541,9 +572,13 @@
      */
     public <U> U clickAndWait(@NonNull Point point, @NonNull EventCondition<U> condition,
             long timeout) {
-        clipToGestureBounds(point);
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        clipToGestureBounds(point, node);
         Log.d(TAG, String.format("Clicking on (%d, %d) and waiting %dms for %s.", point.x,
                 point.y, timeout, condition));
+        if (!node.isClickable()) {
+            Log.w(TAG, String.format("Clicking on non-clickable object: %s", node));
+        }
         return mGestureController.performGestureAndWait(
                 condition, timeout, Gestures.click(point, getDisplayId()));
     }
@@ -575,8 +610,12 @@
 
     /** Performs a long click on this object's center. */
     public void longClick() {
-        Point center = getVisibleCenter();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Point center = getVisibleCenter(node);
         Log.d(TAG, String.format("Long-clicking on (%d, %d).", center.x, center.y));
+        if (!node.isLongClickable()) {
+            Log.w(TAG, String.format("Long-clicking on non-long-clickable object: %s", node));
+        }
         mGestureController.performGesture(Gestures.longClick(center, getDisplayId()));
     }
 
@@ -700,9 +739,13 @@
         final Direction swipeDirection = Direction.reverse(direction);
 
         // Scroll by performing repeated swipes
-        Rect bounds = getVisibleBoundsForGestures();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Rect bounds = getVisibleBoundsForGestures(node);
         Log.d(TAG, String.format("Scrolling %s (bounds=%s, percent=%f) at %dpx/s.",
                 direction.name().toLowerCase(), bounds, percent, speed));
+        if (!node.isScrollable()) {
+            Log.w(TAG, String.format("Scrolling on non-scrollable object: %s", node));
+        }
         for (; percent > 0.0f; percent -= 1.0f) {
             float segment = Math.min(percent, 1.0f);
             PointerGesture swipe = Gestures.swipeRect(
@@ -730,11 +773,16 @@
      */
     public <U> U scrollUntil(@NonNull Direction direction,
             @NonNull Condition<? super UiObject2, U> condition) {
-        Rect bounds = getVisibleBoundsForGestures();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Rect bounds = getVisibleBoundsForGestures(node);
         int speed = (int) (DEFAULT_SCROLL_SPEED * mDisplayDensity);
 
         EventCondition<Boolean> scrollFinished = Until.scrollFinished(direction);
 
+        if (!node.isScrollable()) {
+            Log.w(TAG, String.format("Scrolling on non-scrollable object: %s", node));
+        }
+
         // To scroll, we swipe in the opposite direction
         final Direction swipeDirection = Direction.reverse(direction);
         while (true) {
@@ -771,7 +819,8 @@
      * @return The value obtained after applying the condition.
      */
     public <U> U scrollUntil(@NonNull Direction direction, @NonNull EventCondition<U> condition) {
-        Rect bounds = getVisibleBoundsForGestures();
+        AccessibilityNodeInfo node = getAccessibilityNodeInfo();
+        Rect bounds = getVisibleBoundsForGestures(node);
         int speed = (int) (DEFAULT_SCROLL_SPEED * mDisplayDensity);
 
         // combine the input condition with scroll finished condition.
@@ -791,8 +840,18 @@
             public boolean accept(AccessibilityEvent event) {
                 return condition.accept(event) || scrollFinished.accept(event);
             }
+
+            @NonNull
+            @Override
+            public String toString() {
+                return condition + " || " + scrollFinished;
+            }
         };
 
+        if (!node.isScrollable()) {
+            Log.w(TAG, String.format("Scrolling on non-scrollable object: %s", node));
+        }
+
         // To scroll, we swipe in the opposite direction
         final Direction swipeDirection = Direction.reverse(direction);
         while (true) {
diff --git a/testutils/testutils-paparazzi/build.gradle b/testutils/testutils-paparazzi/build.gradle
index aeb9d21..ff3b18a 100644
--- a/testutils/testutils-paparazzi/build.gradle
+++ b/testutils/testutils-paparazzi/build.gradle
@@ -30,12 +30,15 @@
         // both :internal-testutils-paparazzi and :test:screenshot:screenshot are added to the
         // classpath and picking a different package will cause missing class exceptions due to
         // class shadowing
-        "androidx.test.screenshot.protobuf"
+        "androidx.test.screenshot.protobuf",
+        // proto-lite dependency includes .proto files, which are not used and would clash if
+        // users also use proto library directly
+        /* dropResourcesWithSuffix = */ ".proto"
 )
 
 dependencies {
     api(project(":external:paparazzi:paparazzi"))
-    bundleInside(project(path: ":test:screenshot:screenshot-proto", configuration: "export"))
+    bundleInside(project(path: ":test:screenshot:screenshot-proto"))
 
     testImplementation(libs.junit)
     testImplementation(libs.kotlinTestJunit)
diff --git a/text/text/lint-baseline.xml b/text/text/lint-baseline.xml
index 823d7dd..7bcb892 100644
--- a/text/text/lint-baseline.xml
+++ b/text/text/lint-baseline.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0)" variant="all" version="8.1.0">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
 
     <issue
         id="BanInlineOptIn"
@@ -28,202 +28,4 @@
             file="src/main/java/androidx/compose/ui/text/android/TempListUtils.kt"/>
     </issue>
 
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal open class BaselineShiftSpan(val multiplier: Float) : MetricAffectingSpan() {"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class FontFeatureSpan(val fontFeatureSettings: String) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class IndentationFixSpan : LeadingMarginSpan {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal object LayoutCompat {"
-        errorLine2="                ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal fun Layout.getLineForOffset(@IntRange(from = 0) offset: Int, upstream: Boolean): Int {"
-        errorLine2="                    ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LayoutHelper(val layout: Layout) {"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LayoutIntrinsics("
-        errorLine2="               ~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LetterSpacingSpanEm(val letterSpacing: Float) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LetterSpacingSpanPx(@Px val letterSpacing: Float) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LineHeightSpan("
-        errorLine2="               ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class LineHeightStyleSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class PlaceholderSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal data class Segment("
-        errorLine2="                    ~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal object SegmentBreaker {"
-        errorLine2="                ~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="enum class SegmentType {"
-        errorLine2="           ~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class ShadowSpan("
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal open class SkewXSpan(val skewX: Float) : MetricAffectingSpan() {"
-        errorLine2="                    ~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="object StaticLayoutFactory {"
-        errorLine2="       ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TextDecorationSpan("
-        errorLine2="               ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TextLayout constructor("
-        errorLine2="               ~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/TextLayout.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class TypefaceSpan(val typeface: Typeface) : MetricAffectingSpan() {"
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt"/>
-    </issue>
-
-    <issue
-        id="BanSuppressTag"
-        message="@suppress is not allowed in documentation"
-        errorLine1="internal class WordBoundary("
-        errorLine2="               ~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt"/>
-    </issue>
-
 </issues>
diff --git a/text/text/src/androidTest/java/androidx/compose/ui/text/android/StaticLayoutFactoryTest.kt b/text/text/src/androidTest/java/androidx/compose/ui/text/android/StaticLayoutFactoryTest.kt
index cc2fca4..85aef6d 100644
--- a/text/text/src/androidTest/java/androidx/compose/ui/text/android/StaticLayoutFactoryTest.kt
+++ b/text/text/src/androidTest/java/androidx/compose/ui/text/android/StaticLayoutFactoryTest.kt
@@ -79,10 +79,10 @@
         val end = 5
         val staticLayout = StaticLayoutFactory.create(
             text = text,
-            start = start,
-            end = end,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            start = start,
+            end = end
         )
 
         // width Int.MAX_VALUE therefore should be only one line
@@ -206,9 +206,9 @@
             text = text,
             paint = paint,
             width = width,
+            maxLines = 1,
             ellipsize = TextUtils.TruncateAt.END,
-            ellipsizedWidth = ellipsizedWidth,
-            maxLines = 1
+            ellipsizedWidth = ellipsizedWidth
         )
 
         assertThat(staticLayout.getEllipsisCount(0)).isGreaterThan(0)
@@ -506,9 +506,9 @@
     fun create_withStartNegative_throwsIAE() {
         StaticLayoutFactory.create(
             text = "abc",
-            start = -1,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            start = -1
         )
     }
 
@@ -516,9 +516,9 @@
     fun create_withStartGreaterThanLength_throwsIAE() {
         StaticLayoutFactory.create(
             text = "abc",
-            start = "abc".length + 1,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            start = "abc".length + 1
         )
     }
 
@@ -526,9 +526,9 @@
     fun create_withEndNegative_throwsIAE() {
         StaticLayoutFactory.create(
             text = "abc",
-            end = -1,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            end = -1
         )
     }
 
@@ -536,9 +536,9 @@
     fun create_withEndGreaterThanLength_throwsIAE() {
         StaticLayoutFactory.create(
             text = "abc",
-            end = "abc".length + 1,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            end = "abc".length + 1
         )
     }
 
@@ -546,10 +546,10 @@
     fun create_withStartGreaterThanEnd_throwsIAE() {
         StaticLayoutFactory.create(
             text = "abc",
-            start = 2,
-            end = 1,
             paint = TextPaint(),
-            width = Int.MAX_VALUE
+            width = Int.MAX_VALUE,
+            start = 2,
+            end = 1
         )
     }
 
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt
index af1f1e6..e1f0769 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutCompat.kt
@@ -28,10 +28,7 @@
 /**
  * LayoutCompat class which provides all supported attributes by framework, and also defines
  * default value of those attributes for Compose.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal object LayoutCompat {
     const val ALIGN_NORMAL = 0
     const val ALIGN_OPPOSITE = 1
@@ -172,9 +169,7 @@
  * if the offset it not a line broken offset.
  * @return the line number
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal fun Layout.getLineForOffset(@IntRange(from = 0) offset: Int, upstream: Boolean): Int {
     if (offset <= 0) return 0
     if (offset >= text.length) return lineCount - 1
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt
index 1a1e7c0..ee0c079 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt
@@ -28,9 +28,7 @@
  *
  * This class is not thread-safe. Do not share an instance with multiple threads.
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LayoutHelper(val layout: Layout) {
 
     private val paragraphEnds: List<Int>
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt
index 6fcea24..79afb25 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/LayoutIntrinsics.kt
@@ -28,10 +28,7 @@
 
 /**
  * Computes and caches the text layout intrinsic values such as min/max width.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LayoutIntrinsics(
     private val charSequence: CharSequence,
     private val textPaint: TextPaint,
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt b/text/text/src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt
index 2c7c8d0..088ae9a 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/StaticLayoutFactory.kt
@@ -38,10 +38,6 @@
 
 private const val TAG = "StaticLayoutFactory"
 
-/**
-* @suppress
-*/
-@OptIn(InternalPlatformTextApi::class)
 @InternalPlatformTextApi
 object StaticLayoutFactory {
 
@@ -56,10 +52,10 @@
      */
     fun create(
         text: CharSequence,
-        start: Int = 0,
-        end: Int = text.length,
         paint: TextPaint,
         width: Int,
+        start: Int = 0,
+        end: Int = text.length,
         textDir: TextDirectionHeuristic = LayoutCompat.DEFAULT_TEXT_DIRECTION_HEURISTIC,
         alignment: Alignment = LayoutCompat.DEFAULT_LAYOUT_ALIGNMENT,
         @IntRange(from = 0)
@@ -127,8 +123,7 @@
     }
 }
 
-@OptIn(InternalPlatformTextApi::class)
-private class StaticLayoutParams constructor(
+private class StaticLayoutParams(
     val text: CharSequence,
     val start: Int = 0,
     val end: Int,
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt b/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
index 1f88bd0..456ef29 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/TextLayout.kt
@@ -108,10 +108,8 @@
  * @see StaticLayoutFactory
  * @see BoringLayoutFactory
  *
- * @suppress
  */
 @OptIn(InternalPlatformTextApi::class)
-@InternalPlatformTextApi
 internal class TextLayout constructor(
     charSequence: CharSequence,
     width: Float,
@@ -253,10 +251,10 @@
                 isBoringLayout = false
                 StaticLayoutFactory.create(
                     text = charSequence,
-                    start = 0,
-                    end = charSequence.length,
                     paint = textPaint,
                     width = widthInt,
+                    start = 0,
+                    end = charSequence.length,
                     textDir = frameworkTextDir,
                     alignment = frameworkAlignment,
                     maxLines = maxLines,
@@ -998,10 +996,10 @@
 
         val tmpLayout = StaticLayoutFactory.create(
             text = emptyText,
+            paint = textPaint,
+            width = Int.MAX_VALUE,
             start = 0,
             end = emptyText.length,
-            width = Int.MAX_VALUE,
-            paint = textPaint,
             textDir = frameworkTextDir,
             includePadding = includePadding,
             useFallbackLineSpacing = fallbackLineSpacing
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt b/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt
index 95fe44e..ffdb361 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentBreaker.kt
@@ -18,7 +18,6 @@
 
 import android.text.Layout
 import androidx.compose.ui.text.android.CharSequenceCharacterIterator
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import androidx.compose.ui.text.android.LayoutHelper
 import androidx.compose.ui.text.android.fastForEach
 import androidx.compose.ui.text.android.fastZipWithNext
@@ -40,9 +39,7 @@
  * @param right a graphical right position from the layout origin.
  * @param bottom a graphical bottom position from the layout origin.
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal data class Segment(
     val startOffset: Int,
     val endOffset: Int,
@@ -53,10 +50,8 @@
 )
 
 /**
- * Porvide a segmentation breaker for the text animation.
- * @suppress
+ * Provide a segmentation breaker for the text animation.
  */
-@InternalPlatformTextApi
 internal object SegmentBreaker {
     private fun breakInWords(layoutHelper: LayoutHelper): List<Int> {
         val text = layoutHelper.layout.text
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt b/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt
index afad1e9..e723c16 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/animation/SegmentType.kt
@@ -16,15 +16,10 @@
 
 package androidx.compose.ui.text.android.animation
 
-import androidx.compose.ui.text.android.InternalPlatformTextApi
-
 /**
  * Defines a segmentation rule for text animation
- *
- * @suppress
  */
-@InternalPlatformTextApi
-enum class SegmentType {
+internal enum class SegmentType {
     /**
      * Don't break text and treat whole text as the segment.
      */
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt b/text/text/src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt
index 4ebf2b4..ae6c352 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/selection/WordBoundary.kt
@@ -15,7 +15,6 @@
  */
 package androidx.compose.ui.text.android.selection
 
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import java.text.BreakIterator
 import java.util.Locale
 
@@ -33,9 +32,7 @@
  * [Editor.java](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/widget/Editor.java)
  * @param locale Locale of the input text.
  * @param text The input text to be analyzed.
- * @suppress
  */
-@InternalPlatformTextApi
 internal class WordBoundary(
     locale: Locale,
     text: CharSequence
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt
index 676c6d8..2ca672a 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/BaselineShiftSpan.kt
@@ -18,15 +18,11 @@
 
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import kotlin.math.ceil
 
 /**
  * Span which shifts the vertical position of baseline.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal open class BaselineShiftSpan(val multiplier: Float) : MetricAffectingSpan() {
 
     override fun updateMeasureState(textPaint: TextPaint) {
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt
index 0b3cd18..fd20af3 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/FontFeatureSpan.kt
@@ -18,14 +18,10 @@
 
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * Span that change font feature settings for font.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class FontFeatureSpan(val fontFeatureSettings: String) : MetricAffectingSpan() {
     override fun updateMeasureState(textPaint: TextPaint) {
         textPaint.fontFeatureSettings = fontFeatureSettings
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt
index e8441ad..a6aa6b3 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/IndentationFixSpan.kt
@@ -21,7 +21,6 @@
 import android.text.Layout
 import android.text.Layout.Alignment
 import android.text.style.LeadingMarginSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import androidx.compose.ui.text.android.isLineEllipsized
 import kotlin.math.abs
 
@@ -34,10 +33,7 @@
  * opposite direction.
  *
  * It should be applied to a text only when those three attributes are set.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class IndentationFixSpan : LeadingMarginSpan {
     override fun getLeadingMargin(firstLine: Boolean): Int {
         return 0
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt
index 20c10b4..66a4b31 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanEm.kt
@@ -17,14 +17,10 @@
 
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * Span used to adjust the letter spacing, in the unit of Em.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LetterSpacingSpanEm(val letterSpacing: Float) : MetricAffectingSpan() {
     override fun updateDrawState(textPaint: TextPaint) {
         textPaint.letterSpacing = letterSpacing
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt
index 6637b34..f885ad5 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LetterSpacingSpanPx.kt
@@ -3,14 +3,10 @@
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
 import androidx.annotation.Px
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * Span that sets the letter spacing as [letterSpacing], in the unit of pixel.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LetterSpacingSpanPx(@Px val letterSpacing: Float) : MetricAffectingSpan() {
     private fun TextPaint.updatePaint() {
         // In framework, 1em letterSpacing equals to textSize * textScaleX pixels.
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt
index 76ed455..3e25ca00 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightSpan.kt
@@ -16,7 +16,6 @@
 package androidx.compose.ui.text.android.style
 
 import android.graphics.Paint.FontMetricsInt
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import kotlin.math.ceil
 
 /**
@@ -26,10 +25,7 @@
  * @constructor Create a LineHeightSpan which sets the line height to `height` physical pixels.
  * @param lineHeight The specified line height in pixel unit, which is the space between the
  * baseline of adjacent lines.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LineHeightSpan(
     val lineHeight: Float
 ) : android.text.style.LineHeightSpan {
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
index 5cb33c1..589c410 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/LineHeightStyleSpan.kt
@@ -17,7 +17,6 @@
 
 import android.graphics.Paint.FontMetricsInt
 import androidx.annotation.FloatRange
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import kotlin.math.abs
 import kotlin.math.ceil
 
@@ -40,10 +39,7 @@
  * @param topRatio The percentage on how to distribute the line height for a given line.
  * 0 means all space as a result of line height is applied to the bottom. Similarly, 100 means
  * all space as a result of line height is applied to the top.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class LineHeightStyleSpan(
     val lineHeight: Float,
     private val startIndex: Int,
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt
index 6ea2ff3..ce2a33f 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/PlaceholderSpan.kt
@@ -21,7 +21,6 @@
 import android.graphics.Paint
 import android.text.style.ReplacementSpan
 import androidx.annotation.IntDef
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 import kotlin.math.ceil
 import kotlin.math.max
 import kotlin.math.min
@@ -40,9 +39,7 @@
  * @param pxPerSp The number of pixels 1 Sp equals to.
  * @param verticalAlign How the inline element is aligned with the text.
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class PlaceholderSpan(
     private val width: Float,
     @Unit
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt
index 79ca207..e43cdcd 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/ShadowSpan.kt
@@ -17,14 +17,11 @@
 
 import android.text.TextPaint
 import android.text.style.CharacterStyle
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * A span which applies a shadow effect to the covered text.
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class ShadowSpan(
     val color: Int,
     val offsetX: Float,
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt
index 108d90f..d07af14 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/SkewXSpan.kt
@@ -17,15 +17,12 @@
 
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * Span which shear text in x direction. A pixel at (x, y) will be transfer to (x + y * skewX, y),
  * where y is the distant above baseline.
  *
- * @suppress
  */
-@InternalPlatformTextApi
 internal open class SkewXSpan(val skewX: Float) : MetricAffectingSpan() {
     override fun updateDrawState(textPaint: TextPaint) {
         textPaint.textSkewX = skewX + textPaint.textSkewX
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt
index 528bece7..bc52b89 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/TextDecorationSpan.kt
@@ -18,16 +18,13 @@
 
 import android.text.TextPaint
 import android.text.style.CharacterStyle
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * A span which applies the underline and strike through to the affected text.
  *
  * @property isUnderlineText whether to draw the under for the affected text.
  * @property isStrikethroughText whether to draw strikethrough line for the affected text.
- * @suppress
  */
-@InternalPlatformTextApi
 internal class TextDecorationSpan(
     val isUnderlineText: Boolean,
     val isStrikethroughText: Boolean
diff --git a/text/text/src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt b/text/text/src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt
index 7e7398d..69fd819 100644
--- a/text/text/src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt
+++ b/text/text/src/main/java/androidx/compose/ui/text/android/style/TypefaceSpan.kt
@@ -19,7 +19,6 @@
 import android.graphics.Typeface
 import android.text.TextPaint
 import android.text.style.MetricAffectingSpan
-import androidx.compose.ui.text.android.InternalPlatformTextApi
 
 /**
  * Span that displays text in the given Typeface. In Android Framework, TypefaceSpan that accepts
@@ -28,10 +27,7 @@
  * @constructor Constructs a [android.text.style.TypefaceSpan] from a [Typeface]. The previous
  * style of the TextPaint is overridden and the style of the typeface is used.
  * @param typeface Typeface to render the text with.
- *
- * @suppress
  */
-@InternalPlatformTextApi
 internal class TypefaceSpan(val typeface: Typeface) : MetricAffectingSpan() {
     override fun updateDrawState(ds: TextPaint) {
         updateTypeface(ds)
diff --git a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
index c8953f1..ac7fe19 100644
--- a/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
+++ b/tv/integration-tests/playground/src/main/java/androidx/tv/integration/playground/FeaturedCarousel.kt
@@ -66,8 +66,8 @@
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.Carousel
 import androidx.tv.material3.CarouselDefaults
-import androidx.tv.material3.CarouselState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import androidx.tv.material3.rememberCarouselState
 
 @Composable
 fun FeaturedCarouselContent() {
@@ -122,7 +122,7 @@
         Color.LightGray.copy(alpha = 0.3f),
     )
 
-    val carouselState = remember { CarouselState() }
+    val carouselState = rememberCarouselState()
     var carouselFocused by remember { mutableStateOf(false) }
     Carousel(
         itemCount = backgrounds.size,
@@ -141,9 +141,9 @@
             )
         },
         contentTransformStartToEnd =
-            fadeIn(tween(1000)).togetherWith(fadeOut(tween(1000))),
+        fadeIn(tween(1000)).togetherWith(fadeOut(tween(1000))),
         contentTransformEndToStart =
-            fadeIn(tween(1000)).togetherWith(fadeOut(tween(1000)))
+        fadeIn(tween(1000)).togetherWith(fadeOut(tween(1000)))
     ) { itemIndex ->
         Box(
             modifier = Modifier
diff --git a/tv/integration-tests/presentation/src/main/java/androidx/tv/integration/presentation/FeaturedCarousel.kt b/tv/integration-tests/presentation/src/main/java/androidx/tv/integration/presentation/FeaturedCarousel.kt
index e5fa951..2f07358 100644
--- a/tv/integration-tests/presentation/src/main/java/androidx/tv/integration/presentation/FeaturedCarousel.kt
+++ b/tv/integration-tests/presentation/src/main/java/androidx/tv/integration/presentation/FeaturedCarousel.kt
@@ -33,7 +33,6 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.ArrowRight
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
@@ -44,6 +43,7 @@
 import androidx.tv.material3.CarouselState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
 import androidx.tv.material3.Text
+import androidx.tv.material3.rememberCarouselState
 
 @OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
@@ -51,7 +51,7 @@
     movies: List<Movie> = featuredCarouselMovies,
     modifier: Modifier = Modifier
 ) {
-    val carouselState: CarouselState = remember { CarouselState() }
+    val carouselState: CarouselState = rememberCarouselState()
     val slidesCount = movies.size
 
     Carousel(
diff --git a/tv/samples/src/main/java/androidx/tv/samples/CarouselSamples.kt b/tv/samples/src/main/java/androidx/tv/samples/CarouselSamples.kt
index 320ab30..c3ed957 100644
--- a/tv/samples/src/main/java/androidx/tv/samples/CarouselSamples.kt
+++ b/tv/samples/src/main/java/androidx/tv/samples/CarouselSamples.kt
@@ -52,8 +52,8 @@
 import androidx.compose.ui.unit.dp
 import androidx.tv.material3.Carousel
 import androidx.tv.material3.CarouselDefaults
-import androidx.tv.material3.CarouselState
 import androidx.tv.material3.ExperimentalTvMaterial3Api
+import androidx.tv.material3.rememberCarouselState
 
 @OptIn(ExperimentalTvMaterial3Api::class, ExperimentalAnimationApi::class)
 @Sampled
@@ -142,7 +142,7 @@
         Color.Yellow.copy(alpha = 0.3f),
         Color.Green.copy(alpha = 0.3f)
     )
-    val carouselState = remember { CarouselState() }
+    val carouselState = rememberCarouselState()
 
     Carousel(
         itemCount = backgrounds.size,
diff --git a/tv/tv-foundation/build.gradle b/tv/tv-foundation/build.gradle
index 93f9f90..96e8a5e 100644
--- a/tv/tv-foundation/build.gradle
+++ b/tv/tv-foundation/build.gradle
@@ -46,8 +46,6 @@
     api("androidx.compose.ui:ui-text:$composeVersion")
     api("androidx.compose.ui:ui-util:$composeVersion")
 
-    implementation('androidx.media3:media3-exoplayer:1.0.0-beta03')
-
     androidTestImplementation(libs.truth)
     androidTestImplementation(project(":compose:runtime:runtime"))
     androidTestImplementation(project(":compose:ui:ui-test"))
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayer.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayer.kt
deleted file mode 100644
index 978b0fa..0000000
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayer.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2023 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.tv.foundation.media_player
-
-import androidx.compose.runtime.Composable
-import androidx.media3.exoplayer.ExoPlayer
-
-internal interface MediaPlayer {
-    @Composable
-    fun PlayerView(): Unit
-}
-
-internal class MediaPlayerImpl(val exoPlayer: ExoPlayer) : MediaPlayer {
-    @Composable
-    override fun PlayerView() { TODO("Not yet implemented") }
-}
diff --git a/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayerContainer.kt b/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayerContainer.kt
deleted file mode 100644
index 42b4f61..0000000
--- a/tv/tv-foundation/src/main/java/androidx/tv/foundation/media_player/MediaPlayerContainer.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2023 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.tv.foundation.media_player
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.media3.exoplayer.ExoPlayer
-
-@Composable
-internal fun MediaPlayerContainer(
-    modifier: Modifier = Modifier,
-    background: @Composable (mediaPlayer: MediaPlayer) -> Unit,
-    mediaPlayer: MediaPlayer = MediaPlayerContainerDefaults.exoPlayer,
-    mediaPlayerOverlay: @Composable (mediaPlayer: MediaPlayer) -> Unit
-) {
-    Box(modifier = modifier) {
-        background(mediaPlayer)
-        mediaPlayer.PlayerView()
-        mediaPlayerOverlay(mediaPlayer)
-    }
-}
-
-internal object MediaPlayerContainerDefaults {
-    internal val exoPlayer
-        @Composable get() = kotlin.run {
-            val context = LocalContext.current
-            remember { MediaPlayerImpl(ExoPlayer.Builder(context).build()) }
-        }
-}
diff --git a/tv/tv-material/api/current.txt b/tv/tv-material/api/current.txt
index 3dca4bb..dabf56f 100644
--- a/tv/tv-material/api/current.txt
+++ b/tv/tv-material/api/current.txt
@@ -143,6 +143,7 @@
 
   public final class CarouselKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void Carousel(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.tv.material3.CarouselState carouselState, optional long autoScrollDurationMillis, optional androidx.compose.animation.ContentTransform contentTransformStartToEnd, optional androidx.compose.animation.ContentTransform contentTransformEndToStart, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> carouselIndicator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super java.lang.Integer,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static androidx.tv.material3.CarouselState rememberCarouselState(optional int initialActiveItemIndex);
   }
 
   @SuppressCompatibility @androidx.compose.runtime.Stable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class CarouselState {
@@ -150,6 +151,12 @@
     method public int getActiveItemIndex();
     method public androidx.tv.material3.ScrollPauseHandle pauseAutoScroll(int itemIndex);
     property public final int activeItemIndex;
+    field public static final androidx.tv.material3.CarouselState.Companion Companion;
+  }
+
+  public static final class CarouselState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.tv.material3.CarouselState,?> getSaver();
+    property public final androidx.compose.runtime.saveable.Saver<androidx.tv.material3.CarouselState,?> Saver;
   }
 
   @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class CheckboxColors {
diff --git a/tv/tv-material/api/restricted_current.txt b/tv/tv-material/api/restricted_current.txt
index 3dca4bb..dabf56f 100644
--- a/tv/tv-material/api/restricted_current.txt
+++ b/tv/tv-material/api/restricted_current.txt
@@ -143,6 +143,7 @@
 
   public final class CarouselKt {
     method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static void Carousel(int itemCount, optional androidx.compose.ui.Modifier modifier, optional androidx.tv.material3.CarouselState carouselState, optional long autoScrollDurationMillis, optional androidx.compose.animation.ContentTransform contentTransformStartToEnd, optional androidx.compose.animation.ContentTransform contentTransformEndToStart, optional kotlin.jvm.functions.Function1<? super androidx.compose.foundation.layout.BoxScope,kotlin.Unit> carouselIndicator, kotlin.jvm.functions.Function2<? super androidx.compose.animation.AnimatedContentScope,? super java.lang.Integer,kotlin.Unit> content);
+    method @SuppressCompatibility @androidx.compose.runtime.Composable @androidx.tv.material3.ExperimentalTvMaterial3Api public static androidx.tv.material3.CarouselState rememberCarouselState(optional int initialActiveItemIndex);
   }
 
   @SuppressCompatibility @androidx.compose.runtime.Stable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class CarouselState {
@@ -150,6 +151,12 @@
     method public int getActiveItemIndex();
     method public androidx.tv.material3.ScrollPauseHandle pauseAutoScroll(int itemIndex);
     property public final int activeItemIndex;
+    field public static final androidx.tv.material3.CarouselState.Companion Companion;
+  }
+
+  public static final class CarouselState.Companion {
+    method public androidx.compose.runtime.saveable.Saver<androidx.tv.material3.CarouselState,?> getSaver();
+    property public final androidx.compose.runtime.saveable.Saver<androidx.tv.material3.CarouselState,?> Saver;
   }
 
   @SuppressCompatibility @androidx.compose.runtime.Immutable @androidx.tv.material3.ExperimentalTvMaterial3Api public final class CheckboxColors {
diff --git a/tv/tv-material/lint-baseline.xml b/tv/tv-material/lint-baseline.xml
index 68659db..5087d0f 100644
--- a/tv/tv-material/lint-baseline.xml
+++ b/tv/tv-material/lint-baseline.xml
@@ -1,5 +1,50 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0-beta05" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0-beta05)" variant="all" version="8.1.0-beta05">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabMeasurables.map { it.measure(constraints.copy(minWidth = 0, minHeight = 0)) }"
+        errorLine2="                               ~~~">
+        <location
+            file="src/main/java/androidx/tv/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                separatorMeasurables.map {"
+        errorLine2="                                     ~~~">
+        <location
+            file="src/main/java/androidx/tv/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                (tabMeasurables.maxOfOrNull { it.maxIntrinsicHeight(Constraints.Infinity) } ?: 0)"
+        errorLine2="                                ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/tv/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                tabPlaceables.forEachIndexed { index, tabPlaceable ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/tv/material3/TabRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .forEach {"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/tv/material3/TabRow.kt"/>
+    </issue>
 
     <issue
         id="PrimitiveInLambda"
diff --git a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
index 5538671..5b302d8 100644
--- a/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
+++ b/tv/tv-material/src/androidTest/java/androidx/tv/material3/CarouselTest.kt
@@ -122,7 +122,7 @@
     @Test
     fun carousel_onUserTriggeredPause_stopsScroll() {
         rule.setContent {
-            val carouselState = remember { CarouselState() }
+            val carouselState = rememberCarouselState()
             SampleCarousel(carouselState = carouselState) {
                 BasicText(text = "Text ${it + 1}")
                 LaunchedEffect(carouselState) { carouselState.pauseAutoScroll(it) }
@@ -142,7 +142,7 @@
     fun carousel_onUserTriggeredPauseAndResume_resumeScroll() {
         var pauseHandle: ScrollPauseHandle? = null
         rule.setContent {
-            val carouselState = remember { CarouselState() }
+            val carouselState = rememberCarouselState()
             SampleCarousel(carouselState = carouselState) {
                 BasicText(text = "Text ${it + 1}")
                 LaunchedEffect(carouselState) {
@@ -176,7 +176,7 @@
         var pauseHandle1: ScrollPauseHandle? = null
         var pauseHandle2: ScrollPauseHandle? = null
         rule.setContent {
-            val carouselState = remember { CarouselState() }
+            val carouselState = rememberCarouselState()
             SampleCarousel(carouselState = carouselState) {
                 BasicText(text = "Text ${it + 1}")
                 LaunchedEffect(carouselState) {
@@ -219,7 +219,7 @@
     fun carousel_onRepeatedResumesOnSamePauseHandle_ignoresSubsequentResumeCalls() {
         var pauseHandle1: ScrollPauseHandle? = null
         rule.setContent {
-            val carouselState = remember { CarouselState() }
+            val carouselState = rememberCarouselState()
             var pauseHandle2: ScrollPauseHandle? = null
             SampleCarousel(carouselState = carouselState) {
                 BasicText(text = "Text ${it + 1}")
@@ -429,7 +429,7 @@
                             .fillMaxWidth()
                             .testTag("featured-carousel")
                             .border(2.dp, Color.Black),
-                        carouselState = remember { CarouselState() },
+                        carouselState = rememberCarouselState(),
                         itemCount = 3,
                         autoScrollDurationMillis = delayBetweenItems
                     ) {
@@ -833,7 +833,7 @@
 @OptIn(ExperimentalTvMaterial3Api::class)
 @Composable
 private fun SampleCarousel(
-    carouselState: CarouselState = remember { CarouselState() },
+    carouselState: CarouselState = rememberCarouselState(),
     itemCount: Int = 3,
     timeToDisplayItemMillis: Long = delayBetweenItems,
     content: @Composable AnimatedContentScope.(index: Int) -> Unit
diff --git a/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt b/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
index 2da1c2d..23ffe4e 100644
--- a/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
+++ b/tv/tv-material/src/main/java/androidx/tv/material3/Carousel.kt
@@ -44,6 +44,8 @@
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.runtime.saveable.Saver
+import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
@@ -107,7 +109,7 @@
 fun Carousel(
     itemCount: Int,
     modifier: Modifier = Modifier,
-    carouselState: CarouselState = remember { CarouselState() },
+    carouselState: CarouselState = rememberCarouselState(),
     autoScrollDurationMillis: Long = CarouselDefaults.TimeToDisplayItemMillis,
     contentTransformStartToEnd: ContentTransform = CarouselDefaults.contentTransform,
     contentTransformEndToStart: ContentTransform = CarouselDefaults.contentTransform,
@@ -260,6 +262,7 @@
         carouselState.moveToPreviousItem(itemCount)
         outerBoxFocusRequester.requestFocus()
     }
+
     fun showNextItem() {
         carouselState.moveToNextItem(itemCount)
         outerBoxFocusRequester.requestFocus()
@@ -293,6 +296,7 @@
                 updateItemBasedOnLayout(direction, isLtr)
                 KeyEventPropagation.StopPropagation
             }
+
             else -> KeyEventPropagation.StopPropagation
         }
 
@@ -315,6 +319,7 @@
         when {
             shouldFocusExitCarousel(it, carouselState, itemCount, isLtr) ->
                 FocusRequester.Default
+
             else -> FocusRequester.Cancel
         }
     }
@@ -350,6 +355,22 @@
 }
 
 /**
+ * Creates a [CarouselState] that is remembered across compositions.
+ *
+ * Changes to the provided initial values will **not** result in the state being recreated or
+ * changed in any way if it has already been created.
+ *
+ * @param initialActiveItemIndex the index of the first active item
+ */
+@ExperimentalTvMaterial3Api
+@Composable
+fun rememberCarouselState(initialActiveItemIndex: Int = 0): CarouselState {
+    return rememberSaveable(saver = CarouselState.Saver) {
+        CarouselState(initialActiveItemIndex)
+    }
+}
+
+/**
  * State of the Carousel which allows the user to specify the first item that is shown when the
  * Carousel is instantiated in the constructor.
  *
@@ -410,6 +431,16 @@
         // Go to next item
         activeItemIndex = floorMod(activeItemIndex + 1, itemCount)
     }
+
+    companion object {
+        /**
+         * The default [Saver] implementation for [CarouselState].
+         */
+        val Saver: Saver<CarouselState, *> = Saver(
+            save = { it.activeItemIndex },
+            restore = { CarouselState(it) }
+        )
+    }
 }
 
 @ExperimentalTvMaterial3Api
diff --git a/wear/compose/compose-foundation/lint-baseline.xml b/wear/compose/compose-foundation/lint-baseline.xml
index 83c5cbf..3557074 100644
--- a/wear/compose/compose-foundation/lint-baseline.xml
+++ b/wear/compose/compose-foundation/lint-baseline.xml
@@ -1,5 +1,284 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.1.0-beta02" type="baseline" client="gradle" dependencies="false" name="AGP (8.1.0-beta02)" variant="all" version="8.1.0-beta02">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.maxOfOrNull { it.estimateThickness(maxRadius) } ?: 0f"
+        errorLine2="                 ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val maxSweep = children.maxOfOrNull { child ->"
+        errorLine2="                                ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.forEach { child ->"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedBox.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        maxRadius - children.fold(maxRadius) { currentMaxRadius, node ->"
+        errorLine2="                             ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val weights = childrenInLayoutOrder.map { node ->"
+        errorLine2="                                            ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val extraSpace = parentThickness - childrenInLayoutOrder.mapIndexed { ix, node ->"
+        errorLine2="                                                                 ~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        childrenInLayoutOrder.forEachIndexed { ix, node ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        var maxSweep = childrenInLayoutOrder.maxOfOrNull { it.sweepRadians } ?: 0f"
+        errorLine2="                                             ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.forEach { child ->"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.forEach {"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    ) = children.forEach { node ->"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    override fun DrawScope.draw() = children.forEach { with(it) { draw() } }"
+        errorLine2="                                             ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.forEach { with(it) { placeIfNeeded() } }"
+        errorLine2="                 ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedContainer.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        }.reversed().toTypedArray()),"
+        errorLine2="          ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    }.sortedBy { it.first }"
+        errorLine2="      ~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedDraw.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        children.maxOfOrNull { it.estimateThickness(maxRadius) } ?: 0f"
+        errorLine2="                 ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        var totalSweep = children.sumOf { child ->"
+        errorLine2="                                  ~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val weights = childrenInLayoutOrder.map { node ->"
+        errorLine2="                                            ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val extraSpace = parentSweepRadians - childrenInLayoutOrder.mapIndexed { ix, node ->"
+        errorLine2="                                                                    ~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        childrenInLayoutOrder.forEachIndexed { ix, node ->"
+        errorLine2="                              ~~~~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/CurvedRow.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val placeables = measurables.map { it.measure(constraints) }"
+        errorLine2="                                         ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/Expandable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val currentItem = items.find { it.index == index }"
+        errorLine2="                                    ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .map { animationState.value + it.unadjustedOffset + snapOffset }"
+        errorLine2="                     ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .minByOrNull { abs(it - decayTarget) } ?: decayTarget)"
+        errorLine2="                     ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyColumnSnapFlingBehavior.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.find { it.index == itemIndexToFind }"
+        errorLine2="                         ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.map {"
+        errorLine2="                         ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.find { it.index == itemIndexToFind }"
+        errorLine2="                         ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.map {"
+        errorLine2="                         ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    return this.visibleItemsInfo.find { it.index == index }"
+        errorLine2="                                 ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    visibleItemsInfo.forEach { totalSize += it.unadjustedSize }"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/lazy/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                        awaitPointerEvent(PointerEventPass.Initial).changes.forEach { change ->"
+        errorLine2="                                                                            ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/foundation/SwipeToDismissBox.kt"/>
+    </issue>
 
     <issue
         id="PrimitiveInLambda"
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickable.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickable.kt
deleted file mode 100644
index 545a576..0000000
--- a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickable.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.wear.compose.materialcore
-
-import androidx.compose.foundation.layout.Box
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.junit4.ComposeContentTestRule
-import androidx.compose.ui.test.junit4.createComposeRule
-import androidx.compose.ui.test.onNodeWithTag
-import androidx.compose.ui.test.performTouchInput
-import org.junit.Assert.assertEquals
-import org.junit.Rule
-import org.junit.Test
-
-public class RepeatableClickable {
-    @get:Rule
-    public val rule = createComposeRule()
-
-    @Test
-    fun touch_hold_shorter_than_threshold() {
-        var clickCounter = 0
-
-        boxWithRepeatableClickable(rule, 300) {
-            clickCounter++
-        }
-
-        assertEquals(0, clickCounter)
-    }
-
-    @Test
-    fun touch_hold_equals_to_threshold() {
-        var clickCounter = 0
-
-        boxWithRepeatableClickable(rule, 500) {
-            clickCounter++
-        }
-
-        assertEquals(1, clickCounter)
-    }
-
-    @Test
-    fun touch_hold_longer_than_threshold() {
-        var clickCounter = 0
-
-        boxWithRepeatableClickable(rule, 620) {
-            clickCounter++
-        }
-
-        assertEquals(3, clickCounter)
-    }
-
-    @Test
-    fun touch_hold_disabled() {
-        var clickCounter = 0
-
-        boxWithRepeatableClickable(rule, 500, false) {
-            clickCounter++
-        }
-
-        assertEquals(0, clickCounter)
-    }
-
-    private fun boxWithRepeatableClickable(
-        rule: ComposeContentTestRule,
-        holdDelay: Long,
-        enabled: Boolean = true,
-        initialDelay: Long = 500L,
-        incrementalDelay: Long = 60L,
-        onClick: () -> Unit
-    ) {
-
-        rule.setContent {
-            Box(
-                modifier = Modifier
-                    .testTag(TEST_TAG)
-                    .repeatableClickable(
-                        enabled = enabled,
-                        initialDelay = initialDelay,
-                        incrementalDelay = incrementalDelay
-                    ) {
-                        onClick()
-                    }
-            ) {}
-        }
-
-        rule.onNodeWithTag(TEST_TAG).performTouchInput {
-            down(center)
-            advanceEventTime(holdDelay)
-            up()
-        }
-    }
-}
diff --git a/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt
new file mode 100644
index 0000000..895034c
--- /dev/null
+++ b/wear/compose/compose-material-core/src/androidTest/kotlin/androidx/wear/compose/materialcore/RepeatableClickableTest.kt
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.wear.compose.materialcore
+
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.junit4.ComposeContentTestRule
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onNodeWithTag
+import androidx.compose.ui.test.performTouchInput
+import androidx.compose.ui.unit.dp
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+
+public class RepeatableClickableTest {
+    @get:Rule
+    public val rule = createComposeRule()
+
+    @Test
+    fun touch_hold_shorter_than_threshold_performs_click() {
+        var repeatableClickCounter = 0
+        var clicked = false
+
+        boxWithRepeatableClickable(rule,
+            holdDelay = INITIAL_DELAY / 2,
+            onRepeatableClick = { repeatableClickCounter++ },
+            onClick = { clicked = true }
+        )
+        assertEquals(0, repeatableClickCounter)
+        assertEquals(true, clicked)
+    }
+
+    @Test
+    fun touch_hold_equals_to_threshold_performs_repeatable_click() {
+        var repeatableClickCounter = 0
+        var clicked = false
+
+        boxWithRepeatableClickable(rule,
+            holdDelay = INITIAL_DELAY,
+            onRepeatableClick = { repeatableClickCounter++ },
+            onClick = { clicked = true }
+        )
+        assertEquals(1, repeatableClickCounter)
+        assertEquals(false, clicked)
+    }
+
+    @Test
+    fun touch_hold_longer_than_threshold_performs_multiple_repeatable_clicks() {
+        var repeatableClickCounter = 0
+        var clicked = false
+
+        boxWithRepeatableClickable(rule,
+            holdDelay = INITIAL_DELAY + INCREMENTAL_DELAY * 2,
+            onRepeatableClick = { repeatableClickCounter++ },
+            onClick = { clicked = true }
+        )
+
+        assertEquals(3, repeatableClickCounter)
+        assertEquals(false, clicked)
+    }
+
+    @Test
+    fun touch_hold_disabled() {
+        var repeatableClickCounter = 0
+        var clicked = false
+
+        boxWithRepeatableClickable(rule,
+            holdDelay = INITIAL_DELAY,
+            enabled = false,
+            onRepeatableClick = { repeatableClickCounter++ },
+            onClick = { clicked = true }
+        )
+
+        assertEquals(0, repeatableClickCounter)
+        assertEquals(false, clicked)
+    }
+
+    @Test
+    fun touch_hold_release_outside_of_bounds_shorter_than_threshold() {
+        var repeatableClickCounter = 0
+        var clicked = false
+
+        boxWithRepeatableClickable(rule,
+            holdDelay = INITIAL_DELAY / 2,
+            enabled = true,
+            releaseOutsideOfBox = true,
+            onRepeatableClick = { repeatableClickCounter++ },
+            onClick = { clicked = true }
+        )
+
+        assertEquals(0, repeatableClickCounter)
+        assertEquals(false, clicked)
+    }
+
+    private fun boxWithRepeatableClickable(
+        rule: ComposeContentTestRule,
+        holdDelay: Long,
+        enabled: Boolean = true,
+        initialDelay: Long = INITIAL_DELAY,
+        incrementalDelay: Long = INCREMENTAL_DELAY,
+        releaseOutsideOfBox: Boolean = false,
+        onClick: () -> Unit,
+        onRepeatableClick: () -> Unit
+    ) {
+        rule.setContent {
+            Box(
+                modifier = Modifier
+                    .fillMaxSize()
+            ) {
+                Box(
+                    modifier = Modifier
+                        .testTag(TEST_TAG)
+                        .size(50.dp)
+                        .align(Alignment.Center)
+                        .repeatableClickable(
+                            enabled = enabled,
+                            initialDelay = initialDelay,
+                            incrementalDelay = incrementalDelay,
+                            indication = null,
+                            interactionSource = remember { MutableInteractionSource() },
+                            onClick = onClick,
+                            onRepeatableClick = onRepeatableClick
+                        )
+                ) {}
+            }
+        }
+
+        rule.onNodeWithTag(TEST_TAG).performTouchInput {
+            down(center)
+            advanceEventTime(holdDelay)
+            if (releaseOutsideOfBox) {
+                // Move to -1f,-1f coordinates which are outside of the current component
+                moveTo(Offset(-1f, -1f))
+            }
+            up()
+        }
+    }
+
+    companion object {
+        private const val INITIAL_DELAY = 500L
+        private const val INCREMENTAL_DELAY = 60L
+    }
+}
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
index da01843..b5ac77f 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/RepeatableClickable.kt
@@ -17,46 +17,106 @@
 package androidx.wear.compose.materialcore
 
 import androidx.annotation.RestrictTo
+import androidx.compose.foundation.Indication
+import androidx.compose.foundation.LocalIndication
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.gestures.awaitEachGesture
 import androidx.compose.foundation.gestures.awaitFirstDown
 import androidx.compose.foundation.gestures.waitForUpOrCancellation
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.interaction.PressInteraction
 import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
 import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.semantics.Role
 import kotlinx.coroutines.coroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 
 /**
  * This modifier provides functionality to increment or decrement values repeatedly
- * by holding down the composable
+ * by holding down the composable.
+ * Should be used instead of clickable modifier to achieve clickable and repeatable
+ * clickable behavior. Can't be used along with clickable modifier as it already implements it.
+ *
+ * Callbacks [onClick] and [onRepeatableClick] are different. [onClick] is triggered only
+ * when the hold duration is shorter than [initialDelay] and no repeatable clicks happened.
+ * [onRepeatableClick] is repeatedly triggered when the hold duration is longer
+ * than [initialDelay] with [incrementalDelay] intervals.
+ *
+ * @param interactionSource [MutableInteractionSource] that will be used to dispatch
+ * [PressInteraction.Press] when this clickable is pressed. Only the initial (first) press will be
+ * recorded and dispatched with [MutableInteractionSource].
+ * @param indication indication to be shown when modified element is pressed. By default,
+ * indication from [LocalIndication] will be used. Pass `null` to show no indication, or
+ * current value from [LocalIndication] to show theme default
+ * @param enabled Controls the enabled state. When `false`, [onClick], and this modifier will
+ * appear disabled for accessibility services
+ * @param onClickLabel semantic / accessibility label for the [onClick] action
+ * @param role the type of user interface element. Accessibility services might use this
+ * to describe the element or do customizations
+ * @param initialDelay The initial delay before the click starts repeating, in ms
+ * @param incrementalDelay The delay between each repeated click, in ms
+ * @param onClick will be called when user clicks on the element
+ * @param onRepeatableClick will be called after the [initialDelay] with [incrementalDelay]
+ * between each call until the touch is released
  */
 @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public fun Modifier.repeatableClickable(
-    enabled: Boolean,
+fun Modifier.repeatableClickable(
+    interactionSource: MutableInteractionSource,
+    indication: Indication?,
+    enabled: Boolean = true,
+    onClickLabel: String? = null,
+    role: Role? = null,
     initialDelay: Long = 500L,
     incrementalDelay: Long = 60L,
-    onClick: () -> Unit
+    onClick: () -> Unit,
+    onRepeatableClick: () -> Unit = onClick
 ): Modifier = composed {
-
+    val currentOnRepeatableClick by rememberUpdatedState(onRepeatableClick)
     val currentOnClick by rememberUpdatedState(onClick)
+    // This flag is used for checking whether the onClick should be ignored or not.
+    // If this flag is true, then it means that repeatable click happened and onClick
+    // shouldn't be triggered.
+    var ignoreOnClick by remember { mutableStateOf(false) }
 
-    pointerInput(enabled) {
-        coroutineScope {
-            awaitEachGesture {
-                awaitFirstDown()
-                val repeatingJob = launch {
-                    delay(initialDelay)
-                    while (enabled) {
-                        currentOnClick()
-                        delay(incrementalDelay)
+    // Repeatable logic should always follow the clickable, as the lowest modifier finishes first,
+    // and we have to be sure that repeatable goes before clickable.
+    clickable(
+        interactionSource = interactionSource,
+        indication = indication,
+        enabled = enabled,
+        onClickLabel = onClickLabel,
+        role = role,
+        onClick = {
+            if (!ignoreOnClick) {
+                currentOnClick()
+            }
+            ignoreOnClick = false
+        },
+    )
+        .pointerInput(enabled) {
+            coroutineScope {
+                awaitEachGesture {
+                    awaitFirstDown()
+                    ignoreOnClick = false
+                    val repeatingJob = launch {
+                        delay(initialDelay)
+                        ignoreOnClick = true
+                        while (enabled) {
+                            currentOnRepeatableClick()
+                            delay(incrementalDelay)
+                        }
                     }
+                    // Waiting for up or cancellation of the gesture.
+                    waitForUpOrCancellation()
+                    repeatingJob.cancel()
                 }
-                waitForUpOrCancellation()
-                repeatingJob.cancel()
             }
         }
-    }
 }
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
index 065d3d0..637a82c 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Slider.kt
@@ -18,7 +18,6 @@
 
 import androidx.annotation.RestrictTo
 import androidx.compose.foundation.LocalIndication
-import androidx.compose.foundation.clickable
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxHeight
@@ -48,13 +47,12 @@
         modifier = Modifier
             .width(buttonControlSize)
             .fillMaxHeight()
-            .clickable(
+            .repeatableClickable(
                 enabled = enabled,
                 onClick = onClick,
                 interactionSource = remember { MutableInteractionSource() },
-                indication = LocalIndication.current,
+                indication = LocalIndication.current
             )
-            .repeatableClickable(enabled = enabled, onClick = onClick)
             .then(modifier),
         contentAlignment = contentAlignment
     ) {
diff --git a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
index d1a25d0..70428a4 100644
--- a/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
+++ b/wear/compose/compose-material-core/src/main/java/androidx/wear/compose/materialcore/Stepper.kt
@@ -18,7 +18,6 @@
 
 import androidx.annotation.RestrictTo
 import androidx.compose.foundation.background
-import androidx.compose.foundation.clickable
 import androidx.compose.foundation.indication
 import androidx.compose.foundation.interaction.MutableInteractionSource
 import androidx.compose.foundation.layout.Arrangement
@@ -39,7 +38,6 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.unit.dp
 
 /**
@@ -156,10 +154,12 @@
         modifier = Modifier
             .fillMaxWidth()
             .weight(StepperDefaults.ButtonWeight)
-            .clickable(
-                interactionSource, null, onClick = onClick, enabled = enabled, role = Role.Button
+            .repeatableClickable(
+                enabled = enabled,
+                onClick = onClick,
+                interactionSource = interactionSource,
+                indication = null
             )
-            .repeatableClickable(enabled = enabled, onClick = onClick)
             .wrapContentWidth()
             .indication(interactionSource, rememberRipple(bounded = false))
             .padding(paddingValues),
diff --git a/wear/compose/compose-material/lint-baseline.xml b/wear/compose/compose-material/lint-baseline.xml
index 3ebc76a..11bfe8a 100644
--- a/wear/compose/compose-material/lint-baseline.xml
+++ b/wear/compose/compose-material/lint-baseline.xml
@@ -1,5 +1,176 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.2.0-alpha14" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha14)" variant="all" version="8.2.0-alpha14">
+<issues format="6" by="lint 8.2.0-alpha15" type="baseline" client="gradle" dependencies="false" name="AGP (8.2.0-alpha15)" variant="all" version="8.2.0-alpha15">
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                                    visibleItems.find { info ->"
+        errorLine2="                                                 ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/Picker.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="        val placeables = measurables.map { it.measure(constraints) }"
+        errorLine2="                                     ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/PickerGroup.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            placeables.forEach {"
+        errorLine2="                       ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/PickerGroup.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    placeables.forEach { p ->"
+        errorLine2="               ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/PickerGroup.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val maxChildrenHeight = placeables.maxOf { it.height }"
+        errorLine2="                                       ~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/PickerGroup.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            val currentItem = items.find { it.index == index }"
+        errorLine2="                                    ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyColumn.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .map { animationState.value + it.unadjustedOffset + snapOffset }"
+        errorLine2="                     ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="                    .minByOrNull { abs(it - decayTarget) } ?: decayTarget)"
+        errorLine2="                     ~~~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyColumnSnapFlingBehavior.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.find { it.index == itemIndexToFind }"
+        errorLine2="                         ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.map {"
+        errorLine2="                         ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.find { it.index == itemIndexToFind }"
+        errorLine2="                         ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            visibleItems.map {"
+        errorLine2="                         ~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    return this.visibleItemsInfo.find { it.index == index }"
+        errorLine2="                                 ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    visibleItemsInfo.forEach { totalSize += it.unadjustedSize }"
+        errorLine2="                     ~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScalingLazyListState.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            yPx = scrollState.layoutInfo.visibleItemsInfo.find { it.index == itemIndex }?.let {"
+        errorLine2="                                                          ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScrollAway.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            yPx = scrollState.layoutInfo.visibleItemsInfo.find { it.index == itemIndex }?.let {"
+        errorLine2="                                                          ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScrollAway.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="            yPx = scrollState.layoutInfo.visibleItemsInfo.find { it.index == itemIndex }?.let {"
+        errorLine2="                                                          ~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/ScrollAway.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val a = anchors.filter { it &lt;= offset + 0.001 }.maxOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/Swipeable.kt"/>
+    </issue>
+
+    <issue
+        id="ListIterator"
+        message="Creating an unnecessary Iterator to iterate through a List"
+        errorLine1="    val b = anchors.filter { it >= offset - 0.001 }.minOrNull()"
+        errorLine2="                                                    ~~~~~~~~~">
+        <location
+            file="src/main/java/androidx/wear/compose/material/Swipeable.kt"/>
+    </issue>
 
     <issue
         id="PrimitiveInLambda"
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
index 1ade790..0e1a164 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/SelectionControlsDemo.kt
@@ -20,7 +20,6 @@
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
@@ -34,9 +33,6 @@
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
 import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
-import androidx.wear.compose.integration.demos.common.Centralize
-import androidx.wear.compose.integration.demos.common.ComposableDemo
-import androidx.wear.compose.integration.demos.common.DemoCategory
 import androidx.wear.compose.material3.Checkbox
 import androidx.wear.compose.material3.ListHeader
 import androidx.wear.compose.material3.RadioButton
@@ -47,47 +43,8 @@
 import androidx.wear.compose.material3.samples.RtlSwitchSample
 import androidx.wear.compose.material3.samples.SwitchSample
 
-val selectionControlsDemos = listOf(
-    DemoCategory(
-        "Samples",
-        listOf(
-            ComposableDemo("Checkbox sample") {
-                Centralize(Modifier.padding(horizontal = 10.dp)) {
-                    CheckboxSample()
-                }
-            },
-            ComposableDemo("Switch sample") {
-                Centralize(Modifier.padding(horizontal = 10.dp)) {
-                    SwitchSample()
-                }
-            },
-            ComposableDemo("Rtl Switch sample") {
-                Centralize(Modifier.padding(horizontal = 10.dp)) {
-                    RtlSwitchSample()
-                }
-            },
-            ComposableDemo("RadioButton sample") {
-                Centralize(Modifier.padding(horizontal = 10.dp)) {
-                    RadioButtonSample()
-                }
-            },
-        )
-    ),
-    DemoCategory("Demos", listOf(
-        ComposableDemo("Checkbox demos") {
-            CheckboxDemos()
-        },
-        ComposableDemo("Switch demos") {
-            SwitchDemos()
-        },
-        ComposableDemo("RadioButton demos") {
-            RadioButtonDemos()
-        }
-    ))
-)
-
 @Composable
-private fun CheckboxDemos() {
+fun CheckboxDemos() {
     ScalingLazyColumn(
         modifier = Modifier
             .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
@@ -98,14 +55,11 @@
         }
         item {
             Row {
-                var checked1 by remember { mutableStateOf(false) }
-                Checkbox(checked = checked1, onCheckedChange = {
-                    checked1 = it
-                })
+                CheckboxSample()
                 Spacer(modifier = Modifier.width(10.dp))
-                var checked2 by remember { mutableStateOf(true) }
-                Checkbox(checked = checked2, onCheckedChange = {
-                    checked2 = it
+                var checked by remember { mutableStateOf(true) }
+                Checkbox(checked = checked, onCheckedChange = {
+                    checked = it
                 })
             }
         }
@@ -129,7 +83,7 @@
 }
 
 @Composable
-private fun SwitchDemos() {
+fun SwitchDemos() {
     ScalingLazyColumn(
         modifier = Modifier
             .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
@@ -140,36 +94,15 @@
         }
         item {
             Row {
-                var checked1 by remember { mutableStateOf(false) }
-                Switch(checked = checked1, onCheckedChange = {
-                    checked1 = it
-                })
+                SwitchSample()
                 Spacer(modifier = Modifier.width(10.dp))
-                var checked2 by remember { mutableStateOf(true) }
-                Switch(checked = checked2, onCheckedChange = {
-                    checked2 = it
+                var checked by remember { mutableStateOf(true) }
+                Switch(checked = checked, onCheckedChange = {
+                    checked = it
                 })
             }
         }
         item {
-            ListHeader { Text(text = "RTL Switch") }
-        }
-        item {
-            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
-                Row {
-                    var checked1 by remember { mutableStateOf(true) }
-                    Switch(checked = checked1, onCheckedChange = {
-                        checked1 = it
-                    })
-                    Spacer(modifier = Modifier.width(10.dp))
-                    var checked2 by remember { mutableStateOf(false) }
-                    Switch(checked = checked2, onCheckedChange = {
-                        checked2 = it
-                    })
-                }
-            }
-        }
-        item {
             ListHeader { Text(text = "Disabled Switch") }
         }
         item {
@@ -185,11 +118,26 @@
                 )
             }
         }
+        item {
+            ListHeader { Text(text = "RTL Switch") }
+        }
+        item {
+            CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
+                Row {
+                    var checked by remember { mutableStateOf(true) }
+                    Switch(checked = checked, onCheckedChange = {
+                        checked = it
+                    })
+                    Spacer(modifier = Modifier.width(10.dp))
+                    RtlSwitchSample()
+                }
+            }
+        }
     }
 }
 
 @Composable
-private fun RadioButtonDemos() {
+fun RadioButtonDemos() {
     ScalingLazyColumn(
         modifier = Modifier
             .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally,
@@ -200,14 +148,11 @@
         }
         item {
             Row {
-                var selected1 by remember { mutableStateOf(false) }
-                RadioButton(selected = selected1, onClick = {
-                    selected1 = !selected1
-                })
+                RadioButtonSample()
                 Spacer(modifier = Modifier.width(10.dp))
-                var selected2 by remember { mutableStateOf(true) }
-                RadioButton(selected = selected2, onClick = {
-                    selected2 = !selected2
+                var selected by remember { mutableStateOf(true) }
+                RadioButton(selected = selected, onClick = {
+                    selected = !selected
                 })
             }
         }
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
index da36867..32001cf5 100644
--- a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
@@ -54,6 +54,11 @@
                 },
             )
         ),
+        ComposableDemo("List Header") {
+            Centralize {
+                ListHeaderDemo()
+            }
+        },
         ComposableDemo("Card") {
             CardDemo()
         },
@@ -69,6 +74,19 @@
         ComposableDemo("Icon Toggle Button") {
             IconToggleButtonDemo()
         },
+        ComposableDemo("Checkbox") {
+            CheckboxDemos()
+        },
+        ComposableDemo("Switch") {
+            SwitchDemos()
+        },
+        ComposableDemo("Radio Button") {
+            RadioButtonDemos()
+        },
+        DemoCategory(
+            title = "Toggle Button",
+            toggleButtonDemos
+        ),
         DemoCategory(
             "Stepper",
             listOf(
@@ -92,25 +110,12 @@
             "Slider",
             SliderDemos
         ),
-        ComposableDemo("List Header") {
-            Centralize {
-                ListHeaderDemo()
-            }
-        },
         ComposableDemo(
             title = "Fixed Font Size"
         ) {
             Centralize { FixedFontSize() }
         },
         DemoCategory(
-            title = "Selection Controls",
-            selectionControlsDemos
-        ),
-        DemoCategory(
-            title = "Toggle Button",
-            toggleButtonDemos
-        ),
-        DemoCategory(
             title = "Swipe To Dismiss",
             listOf(
                 ComposableDemo("Simple") { SimpleSwipeToDismissBox(it.navigateBack) },
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
index 6684dec..f9d3804 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardScreenshotTest.kt
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package androidx.wear.compose.material3.test
+package androidx.wear.compose.material3
 
 import android.os.Build
+import androidx.compose.foundation.layout.width
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.testutils.assertAgainstGolden
@@ -28,21 +29,11 @@
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.unit.LayoutDirection
+import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
 import androidx.test.filters.SdkSuppress
 import androidx.test.screenshot.AndroidXScreenshotTestRule
-import androidx.wear.compose.material3.AppCard
-import androidx.wear.compose.material3.Card
-import androidx.wear.compose.material3.CardColors
-import androidx.wear.compose.material3.CardDefaults
-import androidx.wear.compose.material3.OutlinedCard
-import androidx.wear.compose.material3.SCREENSHOT_GOLDEN_PATH
-import androidx.wear.compose.material3.TEST_TAG
-import androidx.wear.compose.material3.TestIcon
-import androidx.wear.compose.material3.Text
-import androidx.wear.compose.material3.TitleCard
-import androidx.wear.compose.material3.setContentWithTheme
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TestName
@@ -82,7 +73,9 @@
         sampleCard(
             colors = CardDefaults.imageCardColors(
                 containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
-                    backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+                    backgroundImagePainter = painterResource(
+                        id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
+                    )
                 )
             )
         )
@@ -123,7 +116,9 @@
         sampleAppCard(
             colors = CardDefaults.imageCardColors(
                 containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
-                    backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+                    backgroundImagePainter = painterResource(
+                        id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
+                    )
                 )
             )
         )
@@ -149,7 +144,9 @@
         sampleTitleCard(
             colors = CardDefaults.imageCardColors(
                 containerPainter = CardDefaults.imageWithScrimBackgroundPainter(
-                    backgroundImagePainter = painterResource(id = R.drawable.backgroundimage1)
+                    backgroundImagePainter = painterResource(
+                        id = androidx.wear.compose.material3.test.R.drawable.backgroundimage1
+                    )
                 )
             )
         )
@@ -164,7 +161,9 @@
             enabled = enabled,
             onClick = {},
             colors = colors,
-            modifier = Modifier.testTag(TEST_TAG),
+            modifier = Modifier
+                .testTag(TEST_TAG)
+                .width(cardWidth),
         ) {
             Text("Card: Some body content")
         }
@@ -177,7 +176,9 @@
         OutlinedCard(
             enabled = enabled,
             onClick = {},
-            modifier = Modifier.testTag(TEST_TAG),
+            modifier = Modifier
+                .testTag(TEST_TAG)
+                .width(cardWidth),
         ) {
             Text("Outlined Card: Some body content")
         }
@@ -196,7 +197,9 @@
             title = { Text("AppCard") },
             colors = colors,
             time = { Text("now") },
-            modifier = Modifier.testTag(TEST_TAG),
+            modifier = Modifier
+                .testTag(TEST_TAG)
+                .width(cardWidth),
         ) {
             Text("Some body content")
             Text("and some more body content")
@@ -214,7 +217,9 @@
             title = { Text("TitleCard") },
             time = { Text("now") },
             colors = colors,
-            modifier = Modifier.testTag(TEST_TAG),
+            modifier = Modifier
+                .testTag(TEST_TAG)
+                .width(cardWidth),
         ) {
             Text("Some body content")
             Text("and some more body content")
@@ -235,4 +240,6 @@
             .captureToImage()
             .assertAgainstGolden(screenshotRule, testName.methodName)
     }
+
+    private val cardWidth = 168.dp
 }
diff --git a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
index 4fa6054..80719e0 100644
--- a/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
+++ b/wear/compose/compose-material3/src/androidTest/kotlin/androidx/wear/compose/material3/CardTest.kt
@@ -425,7 +425,7 @@
         rule.setContentWithTheme {
             expectedAppTextStyle = MaterialTheme.typography.labelSmall
             expectedTimeTextStyle = MaterialTheme.typography.labelSmall
-            expectedTitleTextStyle = MaterialTheme.typography.titleSmall
+            expectedTitleTextStyle = MaterialTheme.typography.titleMedium
             expectedContentTextStyle = MaterialTheme.typography.bodyLarge
 
             AppCard(
@@ -461,7 +461,7 @@
 
         rule.setContentWithTheme {
             expectedTimeTextStyle = MaterialTheme.typography.labelSmall
-            expectedTitleTextStyle = MaterialTheme.typography.titleSmall
+            expectedTitleTextStyle = MaterialTheme.typography.titleMedium
             expectedContentTextStyle = MaterialTheme.typography.bodyLarge
 
             TitleCard(
@@ -497,7 +497,7 @@
         rule.setContentWithTheme {
             expectedAppTextStyle = MaterialTheme.typography.labelSmall
             expectedTimeTextStyle = MaterialTheme.typography.labelSmall
-            expectedTitleTextStyle = MaterialTheme.typography.titleSmall
+            expectedTitleTextStyle = MaterialTheme.typography.titleMedium
             expectedContentTextStyle = MaterialTheme.typography.bodyLarge
 
             AppCard(
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
index 13ed779..34b481c 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/Card.kt
@@ -147,7 +147,7 @@
  * @param appName A slot for displaying the application name, expected to be a single line of start
  * aligned text of [Typography.labelSmall]
  * @param title A slot for displaying the title of the card, expected to be one or two lines of
- * start aligned text of [Typography.titleSmall]
+ * start aligned text of [Typography.titleMedium]
  * @param modifier Modifier to be applied to the card
  * @param enabled Controls the enabled state of the card. When false, this card will not
  * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
@@ -216,7 +216,7 @@
         title = {
             CompositionLocalProvider(
                 LocalContentColor provides colors.titleColor,
-                LocalTextStyle provides MaterialTheme.typography.titleSmall,
+                LocalTextStyle provides MaterialTheme.typography.titleMedium,
             ) {
                 title()
             }
@@ -269,7 +269,7 @@
  *
  * @param onClick Will be called when the user clicks the card
  * @param title A slot for displaying the title of the card, expected to be one or two lines of text
- * of [Typography.titleSmall]
+ * of [Typography.titleMedium]
  * @param modifier Modifier to be applied to the card
  * @param enabled Controls the enabled state of the card. When false, this card will not
  * be clickable and there will be no ripple effect on click. Wear cards do not have any specific
@@ -315,7 +315,7 @@
         title = {
             CompositionLocalProvider(
                 LocalContentColor provides colors.titleColor,
-                LocalTextStyle provides MaterialTheme.typography.titleSmall,
+                LocalTextStyle provides MaterialTheme.typography.titleMedium,
             ) {
                 title()
             }
diff --git a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
index c7bf76b..a3ef21c 100644
--- a/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
+++ b/wear/compose/compose-material3/src/main/java/androidx/wear/compose/material3/SelectionControls.kt
@@ -491,13 +491,9 @@
         checkedCheckmarkColor = checkedCheckmarkColor,
         uncheckedBoxColor = uncheckedBoxColor,
         uncheckedCheckmarkColor = uncheckedCheckmarkColor,
-        disabledCheckedBoxColor = checkedBoxColor.toDisabledColor(
-            disabledAlpha = DisabledContainerAlpha
-        ),
+        disabledCheckedBoxColor = checkedBoxColor.toDisabledColor(),
         disabledCheckedCheckmarkColor = checkedCheckmarkColor.toDisabledColor(),
-        disabledUncheckedBoxColor = uncheckedBoxColor.toDisabledColor(
-            disabledAlpha = DisabledContainerAlpha
-        ),
+        disabledUncheckedBoxColor = uncheckedBoxColor.toDisabledColor(),
         disabledUncheckedCheckmarkColor = uncheckedCheckmarkColor.toDisabledColor()
     )
 }
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index c027722..7fe817a 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -26,8 +26,8 @@
         applicationId "androidx.wear.compose.integration.demos"
         minSdk 25
         targetSdk 30
-        versionCode 16
-        versionName "1.16"
+        versionCode 18
+        versionName "1.18"
     }
 
     buildTypes {
diff --git a/wear/watchface/watchface-complications/api/1.2.0-beta01.txt b/wear/watchface/watchface-complications/api/1.2.0-beta01.txt
index ebc68f2..cb7f48e 100644
--- a/wear/watchface/watchface-complications/api/1.2.0-beta01.txt
+++ b/wear/watchface/watchface-complications/api/1.2.0-beta01.txt
@@ -90,7 +90,6 @@
     field public static final int DATA_SOURCE_TIME_AND_DATE = 3; // 0x3
     field public static final int DATA_SOURCE_UNREAD_NOTIFICATION_COUNT = 7; // 0x7
     field public static final int DATA_SOURCE_WATCH_BATTERY = 1; // 0x1
-    field @RequiresApi(android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final int DATA_SOURCE_WEATHER = 17; // 0x11
     field public static final int DATA_SOURCE_WORLD_CLOCK = 5; // 0x5
     field public static final int NO_DATA_SOURCE = -1; // 0xffffffff
   }
diff --git a/wear/watchface/watchface-complications/api/current.ignore b/wear/watchface/watchface-complications/api/current.ignore
new file mode 100644
index 0000000..069625a
--- /dev/null
+++ b/wear/watchface/watchface-complications/api/current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedField: androidx.wear.watchface.complications.SystemDataSources#DATA_SOURCE_WEATHER:
+    Removed field androidx.wear.watchface.complications.SystemDataSources.DATA_SOURCE_WEATHER
diff --git a/wear/watchface/watchface-complications/api/current.txt b/wear/watchface/watchface-complications/api/current.txt
index ebc68f2..cb7f48e 100644
--- a/wear/watchface/watchface-complications/api/current.txt
+++ b/wear/watchface/watchface-complications/api/current.txt
@@ -90,7 +90,6 @@
     field public static final int DATA_SOURCE_TIME_AND_DATE = 3; // 0x3
     field public static final int DATA_SOURCE_UNREAD_NOTIFICATION_COUNT = 7; // 0x7
     field public static final int DATA_SOURCE_WATCH_BATTERY = 1; // 0x1
-    field @RequiresApi(android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final int DATA_SOURCE_WEATHER = 17; // 0x11
     field public static final int DATA_SOURCE_WORLD_CLOCK = 5; // 0x5
     field public static final int NO_DATA_SOURCE = -1; // 0xffffffff
   }
diff --git a/wear/watchface/watchface-complications/api/restricted_1.2.0-beta01.txt b/wear/watchface/watchface-complications/api/restricted_1.2.0-beta01.txt
index ebc68f2..cb7f48e 100644
--- a/wear/watchface/watchface-complications/api/restricted_1.2.0-beta01.txt
+++ b/wear/watchface/watchface-complications/api/restricted_1.2.0-beta01.txt
@@ -90,7 +90,6 @@
     field public static final int DATA_SOURCE_TIME_AND_DATE = 3; // 0x3
     field public static final int DATA_SOURCE_UNREAD_NOTIFICATION_COUNT = 7; // 0x7
     field public static final int DATA_SOURCE_WATCH_BATTERY = 1; // 0x1
-    field @RequiresApi(android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final int DATA_SOURCE_WEATHER = 17; // 0x11
     field public static final int DATA_SOURCE_WORLD_CLOCK = 5; // 0x5
     field public static final int NO_DATA_SOURCE = -1; // 0xffffffff
   }
diff --git a/wear/watchface/watchface-complications/api/restricted_current.ignore b/wear/watchface/watchface-complications/api/restricted_current.ignore
new file mode 100644
index 0000000..069625a
--- /dev/null
+++ b/wear/watchface/watchface-complications/api/restricted_current.ignore
@@ -0,0 +1,3 @@
+// Baseline format: 1.0
+RemovedField: androidx.wear.watchface.complications.SystemDataSources#DATA_SOURCE_WEATHER:
+    Removed field androidx.wear.watchface.complications.SystemDataSources.DATA_SOURCE_WEATHER
diff --git a/wear/watchface/watchface-complications/api/restricted_current.txt b/wear/watchface/watchface-complications/api/restricted_current.txt
index ebc68f2..cb7f48e 100644
--- a/wear/watchface/watchface-complications/api/restricted_current.txt
+++ b/wear/watchface/watchface-complications/api/restricted_current.txt
@@ -90,7 +90,6 @@
     field public static final int DATA_SOURCE_TIME_AND_DATE = 3; // 0x3
     field public static final int DATA_SOURCE_UNREAD_NOTIFICATION_COUNT = 7; // 0x7
     field public static final int DATA_SOURCE_WATCH_BATTERY = 1; // 0x1
-    field @RequiresApi(android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE) public static final int DATA_SOURCE_WEATHER = 17; // 0x11
     field public static final int DATA_SOURCE_WORLD_CLOCK = 5; // 0x5
     field public static final int NO_DATA_SOURCE = -1; // 0xffffffff
   }
diff --git a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
index c142a0d2..1ae59f1 100644
--- a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
+++ b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/DefaultComplicationDataSourcePolicy.kt
@@ -355,11 +355,6 @@
             }
             val systemDataSourceFallback =
                 parser.getAttributeIntValue(NAMESPACE_APP, "systemDataSourceFallback", 0)
-            require(SystemDataSources.isAllowedOnDevice(systemDataSourceFallback)) {
-                "$nodeName at line ${parser.lineNumber} cannot have the supplied " +
-                    "systemDataSourceFallback value at the current API level."
-            }
-
             require(parser.hasValue("systemDataSourceFallbackDefaultType")) {
                 "A $nodeName must have a systemDataSourceFallbackDefaultType attribute"
             }
diff --git a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
index d0053b3..b3d620f 100644
--- a/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
+++ b/wear/watchface/watchface-complications/src/main/java/androidx/wear/watchface/complications/SystemDataSources.kt
@@ -15,9 +15,7 @@
  */
 package androidx.wear.watchface.complications
 
-import android.os.Build
 import androidx.annotation.IntDef
-import androidx.annotation.RequiresApi
 import androidx.annotation.RestrictTo
 import androidx.wear.watchface.complications.data.ComplicationType
 
@@ -27,7 +25,7 @@
  */
 public class SystemDataSources private constructor() {
     public companion object {
-        // NEXT AVAILABLE DATA SOURCE ID: 18
+        // NEXT AVAILABLE DATA SOURCE ID: 17
 
         /** Specifies that no complication data source should be used. */
         public const val NO_DATA_SOURCE: Int = -1
@@ -179,29 +177,6 @@
          * This complication data source supports only [ComplicationType.SHORT_TEXT].
          */
         public const val DATA_SOURCE_DAY_AND_DATE: Int = 16
-
-        /**
-         * Id for the 'weather' complication complication data source.
-         *
-         * This is a safe complication data source, so if a watch face uses this as a default it
-         * will be able to receive data from it even before the RECEIVE_COMPLICATION_DATA permission
-         * has been granted.
-         *
-         * This complication data source supports the following types:
-         * [ComplicationType.SHORT_TEXT], [ComplicationType.LONG_TEXT],
-         * [ComplicationType.SMALL_IMAGE].
-         */
-        @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-        public const val DATA_SOURCE_WEATHER: Int = 17
-
-        /** Checks if the given data source is implemented by the device. */
-        internal fun isAllowedOnDevice(@DataSourceId systemDataSourceFallback: Int): Boolean {
-            return when {
-                systemDataSourceFallback == DATA_SOURCE_WEATHER &&
-                    Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> false
-                else -> true
-            }
-        }
     }
 
     /** System complication data source id as defined in [SystemDataSources]. */
@@ -218,8 +193,7 @@
         DATA_SOURCE_SUNRISE_SUNSET,
         DATA_SOURCE_DAY_OF_WEEK,
         DATA_SOURCE_FAVORITE_CONTACT,
-        DATA_SOURCE_DAY_AND_DATE,
-        DATA_SOURCE_WEATHER,
+        DATA_SOURCE_DAY_AND_DATE
     )
     @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
     @Retention(AnnotationRetention.SOURCE)
diff --git a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
index 9c8374a..33b865a 100644
--- a/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
+++ b/wear/watchface/watchface-style/src/main/java/androidx/wear/watchface/style/CurrentUserStyleRepository.kt
@@ -420,7 +420,7 @@
  *
  * @param userStyleSettings The user configurable style categories associated with this watch face.
  *   Empty if the watch face doesn't support user styling. Note we allow at most one
- *   [UserStyleSetting.CustomValueUserStyleSetting] in the list. Prior to android T ot most one
+ *   [UserStyleSetting.CustomValueUserStyleSetting] in the list. Prior to android T at most one
  *   [UserStyleSetting.ComplicationSlotsUserStyleSetting] is allowed, however from android T it's
  *   possible with hierarchical styles for there to be more than one, but at most one can be active
  *   at any given time.
diff --git a/wear/watchface/watchface/build.gradle b/wear/watchface/watchface/build.gradle
index 0b9261d..afaabe8 100644
--- a/wear/watchface/watchface/build.gradle
+++ b/wear/watchface/watchface/build.gradle
@@ -45,7 +45,6 @@
     androidTestImplementation(libs.mockitoKotlin)
     androidTestImplementation(libs.dexmakerMockito, excludes.bytebuddy) // DexMaker has it"s own MockMaker
     androidTestImplementation(libs.truth)
-    androidTestImplementation(libs.kotlinTest)
 
     testImplementation(project(":wear:watchface:watchface-complications-rendering"))
     testImplementation(libs.testExtJunit)
diff --git a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
index e47d35f..1973bc0 100644
--- a/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
+++ b/wear/watchface/watchface/src/androidTest/java/androidx/wear/watchface/test/XmlDefinedUserStyleSchemaAndComplicationSlotsTest.kt
@@ -59,11 +59,9 @@
 import androidx.wear.watchface.style.UserStyleSetting.LongRangeUserStyleSetting.LongRangeOption
 import androidx.wear.watchface.style.data.UserStyleWireFormat
 import com.google.common.truth.Truth.assertThat
-import java.lang.IllegalArgumentException
 import java.time.ZonedDateTime
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.TimeUnit
-import kotlin.test.assertFailsWith
 import kotlinx.coroutines.runBlocking
 import org.junit.After
 import org.junit.Assert
@@ -84,14 +82,13 @@
 
 class TestXmlWatchFaceService(
     testContext: Context,
-    private var surfaceHolderOverride: SurfaceHolder,
-    private var xmlWatchFaceResourceId: Int,
+    private var surfaceHolderOverride: SurfaceHolder
 ) : WatchFaceService() {
     init {
         attachBaseContext(testContext)
     }
 
-    override fun getXmlWatchFaceResourceId() = xmlWatchFaceResourceId
+    override fun getXmlWatchFaceResourceId() = R.xml.xml_watchface
 
     override fun getWallpaperSurfaceHolderOverride() = surfaceHolderOverride
 
@@ -159,7 +156,7 @@
 
 @RunWith(AndroidJUnit4::class)
 @MediumTest
-class XmlDefinedUserStyleSchemaAndComplicationSlotsTest {
+public class XmlDefinedUserStyleSchemaAndComplicationSlotsTest {
 
     @get:Rule
     val mocks = MockitoJUnit.rule()
@@ -174,25 +171,25 @@
     private lateinit var interactiveWatchFaceInstance: IInteractiveWatchFace
 
     @Before
-    fun setUp() {
+    public fun setUp() {
         Assume.assumeTrue("This test suite assumes API 29", Build.VERSION.SDK_INT >= 29)
     }
 
     @After
-    fun tearDown() {
+    public fun tearDown() {
         InteractiveInstanceManager.setParameterlessEngine(null)
         if (this::interactiveWatchFaceInstance.isInitialized) {
             interactiveWatchFaceInstance.release()
         }
     }
 
-    private fun setPendingWallpaperInteractiveWatchFaceInstance(instanceId: String) {
+    private fun setPendingWallpaperInteractiveWatchFaceInstance() {
         val existingInstance =
             InteractiveInstanceManager
                 .getExistingInstanceOrSetPendingWallpaperInteractiveWatchFaceInstance(
                     InteractiveInstanceManager.PendingWallpaperInteractiveWatchFaceInstance(
                         WallpaperInteractiveWatchFaceInstanceParams(
-                            instanceId,
+                            INTERACTIVE_INSTANCE_ID,
                             DeviceConfig(false, false, 0, 0),
                             WatchUiState(false, 0),
                             UserStyleWireFormat(emptyMap()),
@@ -221,14 +218,13 @@
         assertThat(existingInstance).isNull()
     }
 
-    private fun createAndMountTestService(
-        xmlWatchFaceResourceId: Int = R.xml.xml_watchface,
-    ): WatchFaceService.EngineWrapper {
+    @Test
+    @Suppress("Deprecation", "NewApi") // userStyleSettings
+    public fun staticSchemaAndComplicationsRead() {
         val service =
             TestXmlWatchFaceService(
-                ApplicationProvider.getApplicationContext(),
-                surfaceHolder,
-                xmlWatchFaceResourceId
+                ApplicationProvider.getApplicationContext<Context>(),
+                surfaceHolder
             )
 
         Mockito.`when`(surfaceHolder.surfaceFrame)
@@ -237,21 +233,11 @@
         Mockito.`when`(surfaceHolder.surface).thenReturn(surface)
         Mockito.`when`(surface.isValid).thenReturn(false)
 
-        setPendingWallpaperInteractiveWatchFaceInstance(
-            "${INTERACTIVE_INSTANCE_ID}_$xmlWatchFaceResourceId"
-        )
+        setPendingWallpaperInteractiveWatchFaceInstance()
 
         val wrapper = service.onCreateEngine() as WatchFaceService.EngineWrapper
         assertThat(initLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue()
 
-        return wrapper
-    }
-
-    @Test
-    @Suppress("Deprecation", "NewApi") // userStyleSettings
-    fun staticSchemaAndComplicationsRead() {
-        val wrapper = createAndMountTestService()
-
         runBlocking {
             val watchFaceImpl = wrapper.deferredWatchFaceImpl.await()
             val schema = watchFaceImpl.currentUserStyleRepository.schema
@@ -409,42 +395,4 @@
                 )
         }
     }
-
-    @Test
-    fun staticSchemaAndComplicationsRead_invalidXml() {
-        // test that when the xml cannot be parsed, the error is propagated and that
-        // the deferred values of the engine wrapper do not hang indefinitely
-        val wrapper = createAndMountTestService(R.xml.xml_watchface_invalid)
-        runBlocking {
-            val exception =
-                assertFailsWith<IllegalArgumentException> { wrapper.deferredValidation.await() }
-            assertThat(exception.message).contains("must have a systemDataSourceFallback attribute")
-            assertThat(wrapper.deferredWatchFaceImpl.isCancelled)
-        }
-    }
-
-    @Test
-    fun readsComplicationWithWeatherDefaultOnApi34() {
-        Assume.assumeTrue("This test runs only on API >= 34", Build.VERSION.SDK_INT >= 34)
-        val wrapper = createAndMountTestService(R.xml.xml_watchface_weather)
-        runBlocking {
-            val watchFaceImpl = wrapper.deferredWatchFaceImpl.await()
-            val complicationSlot = watchFaceImpl.complicationSlotsManager.complicationSlots[10]!!
-            assertThat(complicationSlot.defaultDataSourcePolicy.systemDataSourceFallback)
-                .isEqualTo(SystemDataSources.DATA_SOURCE_WEATHER)
-        }
-    }
-
-    @Test
-    fun throwsExceptionOnReadingComplicationWithWeatherDefaultOnApiBelow34() {
-        Assume.assumeTrue("This test runs only on API < 34", Build.VERSION.SDK_INT < 34)
-        val wrapper = createAndMountTestService(R.xml.xml_watchface_weather)
-
-        runBlocking {
-            val exception =
-                assertFailsWith<IllegalArgumentException> { wrapper.deferredValidation.await() }
-            assertThat(exception.message)
-                .contains("cannot have the supplied systemDataSourceFallback value")
-        }
-    }
 }
diff --git a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_invalid.xml b/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_invalid.xml
deleted file mode 100644
index 7a1fe31..0000000
--- a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_invalid.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  Copyright 2021 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<XmlWatchFace xmlns:app="http://schemas.android.com/apk/res-auto"
-    app:complicationScaleX="10.0"
-    app:complicationScaleY="100.0">
-    <ComplicationSlot
-        app:slotId="@integer/complication_slot_10"
-        app:name="@string/complication_name_one"
-        app:screenReaderName="@string/complication_screen_reader_name_one"
-        app:boundsType="ROUND_RECT"
-        app:supportedTypes="RANGED_VALUE|SHORT_TEXT|SMALL_IMAGE">
-        <ComplicationSlotBounds app:left="3" app:top="70" app:right="7" app:bottom="90"/>
-    </ComplicationSlot>
-</XmlWatchFace>
diff --git a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_weather.xml b/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_weather.xml
deleted file mode 100644
index fdcf220..0000000
--- a/wear/watchface/watchface/src/androidTest/res/xml/xml_watchface_weather.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
-  Copyright 2021 The Android Open Source Project
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-  -->
-<XmlWatchFace xmlns:app="http://schemas.android.com/apk/res-auto"
-    app:complicationScaleX="10.0"
-    app:complicationScaleY="100.0">
-    <ComplicationSlot
-        app:slotId="@integer/complication_slot_10"
-        app:name="@string/complication_name_one"
-        app:screenReaderName="@string/complication_screen_reader_name_one"
-        app:boundsType="ROUND_RECT"
-        app:supportedTypes="RANGED_VALUE|SHORT_TEXT|SMALL_IMAGE"
-        app:systemDataSourceFallback="DATA_SOURCE_WEATHER"
-        app:systemDataSourceFallbackDefaultType="SHORT_TEXT">
-        <ComplicationSlotBounds app:left="3" app:top="70" app:right="7" app:bottom="90"/>
-    </ComplicationSlot>
-</XmlWatchFace>
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 d640a2c..7ff9161 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
@@ -521,7 +521,9 @@
     internal open fun createComplicationSlotsManagerInternal(
         currentUserStyleRepository: CurrentUserStyleRepository,
         resourceOnlyWatchFacePackageName: String?
-    ): ComplicationSlotsManager = createComplicationSlotsManager(currentUserStyleRepository)
+    ): ComplicationSlotsManager = createComplicationSlotsManager(
+        currentUserStyleRepository
+    )
 
     /**
      * Used when inflating [ComplicationSlot]s from XML to provide a
@@ -592,8 +594,10 @@
         currentUserStyleRepository: CurrentUserStyleRepository,
         complicationSlotsManager: ComplicationSlotsManager,
         resourceOnlyWatchFacePackageName: String?
-    ): UserStyleFlavors =
-        createUserStyleFlavors(currentUserStyleRepository, complicationSlotsManager)
+    ): UserStyleFlavors = createUserStyleFlavors(
+        currentUserStyleRepository,
+        complicationSlotsManager
+    )
 
     /**
      * Override this factory method to create your WatchFaceImpl. This method will be called by the
@@ -627,13 +631,12 @@
         complicationSlotsManager: ComplicationSlotsManager,
         currentUserStyleRepository: CurrentUserStyleRepository,
         resourceOnlyWatchFacePackageName: String?
-    ): WatchFace =
-        createWatchFace(
-            surfaceHolder,
-            watchState,
-            complicationSlotsManager,
-            currentUserStyleRepository,
-        )
+    ): WatchFace = createWatchFace(
+        surfaceHolder,
+        watchState,
+        complicationSlotsManager,
+        currentUserStyleRepository,
+    )
 
     /** Creates an interactive engine for WallpaperService. */
     final override fun onCreateEngine(): Engine =
@@ -1542,6 +1545,18 @@
 
         @UiThread
         internal fun setWatchUiState(watchUiState: WatchUiState, fromSysUi: Boolean) {
+            Log.d(TAG,
+                "Setting Watch Ui State with " +
+                "WatchUiState{ interruptionFilter=${watchUiState.interruptionFilter}, " +
+                "inAmbientMode=${watchUiState.inAmbientMode} } and fromSysUi=$fromSysUi. " +
+                "Existing state: " +
+                "firstSetWatchUiState=$firstSetWatchUiState, " +
+                    "systemHasSentWatchUiState=$systemHasSentWatchUiState, " +
+                    "mutableWatchState.interruptionFilter=" +
+                        "${mutableWatchState.interruptionFilter.value}, " +
+                    "mutableWatchState.isAmbient=${mutableWatchState.isAmbient.value}"
+            )
+
             if (
                 firstSetWatchUiState ||
                     watchUiState.inAmbientMode != mutableWatchState.isAmbient.value
@@ -1970,9 +1985,8 @@
         @WorkerThread
         internal fun getComplicationSlotMetadataWireFormats() =
             createComplicationSlotsManagerInternal(
-                    CurrentUserStyleRepository(
-                        createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName)
-                    ),
+                CurrentUserStyleRepository(
+                    createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName)),
                     resourceOnlyWatchFacePackageName
                 )
                 .complicationSlots
@@ -2174,81 +2188,68 @@
                 }
 
             backgroundThreadCoroutineScope.launch {
-                // deferred objects used to signal to the UI thread that some init steps have
-                // finished
+                val timeBefore = System.currentTimeMillis()
+                val currentUserStyleRepository =
+                    TraceEvent("WatchFaceService.createUserStyleSchema").use {
+                        CurrentUserStyleRepository(
+                            createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName)
+                        )
+                    }
+                initStyle(currentUserStyleRepository)
+
+                val complicationSlotsManager =
+                    TraceEvent("WatchFaceService.createComplicationsManager").use {
+                        createComplicationSlotsManagerInternal(
+                            currentUserStyleRepository,
+                            resourceOnlyWatchFacePackageName
+                        )
+                    }
+                complicationSlotsManager.watchFaceHostApi = this@EngineWrapper
+                complicationSlotsManager.watchState = watchState
+                complicationSlotsManager.listenForStyleChanges(uiThreadCoroutineScope)
+                listenForComplicationChanges(complicationSlotsManager)
+                if (!watchState.isHeadless) {
+                    periodicallyWriteComplicationDataCache(
+                        _context,
+                        watchState.watchFaceInstanceId.value,
+                        complicationsFlow
+                    )
+                }
+
+                val userStyleFlavors =
+                    TraceEvent("WatchFaceService.createUserStyleFlavors").use {
+                        createUserStyleFlavorsInternal(
+                            currentUserStyleRepository,
+                            complicationSlotsManager,
+                            resourceOnlyWatchFacePackageName
+                        )
+                    }
+
+                deferredEarlyInitDetails.complete(
+                    EarlyInitDetails(
+                        complicationSlotsManager,
+                        currentUserStyleRepository,
+                        userStyleFlavors
+                    )
+                )
+
                 val deferredWatchFace = CompletableDeferred<WatchFace>()
                 val initComplicationsDone = CompletableDeferred<Unit>()
 
-                // add here all the deferred values completed in the background thread
-                val futuresToCancelOnError =
-                    listOf(
+                // WatchFaceImpl (which registers broadcast observers) needs to be constructed
+                // on the UIThread. Part of this process can be done in parallel with
+                // createWatchFace.
+                uiThreadCoroutineScope.launch {
+                    createWatchFaceImpl(
+                        complicationSlotsManager,
+                        currentUserStyleRepository,
                         deferredWatchFace,
                         initComplicationsDone,
-                        deferredEarlyInitDetails,
-                        this@EngineWrapper.deferredWatchFace,
-                        deferredWatchFaceImpl,
-                        deferredValidation,
+                        watchState
                     )
+                }
 
                 try {
-                    val timeBefore = System.currentTimeMillis()
-                    val currentUserStyleRepository =
-                        TraceEvent("WatchFaceService.createUserStyleSchema").use {
-                            CurrentUserStyleRepository(
-                                createUserStyleSchemaInternal(resourceOnlyWatchFacePackageName)
-                            )
-                        }
-                    initStyle(currentUserStyleRepository)
-
-                    val complicationSlotsManager =
-                        TraceEvent("WatchFaceService.createComplicationsManager").use {
-                            createComplicationSlotsManagerInternal(
-                                currentUserStyleRepository,
-                                resourceOnlyWatchFacePackageName
-                            )
-                        }
-                    complicationSlotsManager.watchFaceHostApi = this@EngineWrapper
-                    complicationSlotsManager.watchState = watchState
-                    complicationSlotsManager.listenForStyleChanges(uiThreadCoroutineScope)
-                    listenForComplicationChanges(complicationSlotsManager)
-                    if (!watchState.isHeadless) {
-                        periodicallyWriteComplicationDataCache(
-                            _context,
-                            watchState.watchFaceInstanceId.value,
-                            complicationsFlow
-                        )
-                    }
-
-                    val userStyleFlavors =
-                        TraceEvent("WatchFaceService.createUserStyleFlavors").use {
-                            createUserStyleFlavorsInternal(
-                                currentUserStyleRepository,
-                                complicationSlotsManager,
-                                resourceOnlyWatchFacePackageName
-                            )
-                        }
-
-                    deferredEarlyInitDetails.complete(
-                        EarlyInitDetails(
-                            complicationSlotsManager,
-                            currentUserStyleRepository,
-                            userStyleFlavors
-                        )
-                    )
-
-                    // WatchFaceImpl (which registers broadcast observers) needs to be constructed
-                    // on the UIThread. Part of this process can be done in parallel with
-                    // createWatchFace.
-                    uiThreadCoroutineScope.launch {
-                        createWatchFaceImpl(
-                            complicationSlotsManager,
-                            currentUserStyleRepository,
-                            deferredWatchFace,
-                            initComplicationsDone,
-                            watchState
-                        )
-                    }
-
                     val surfaceHolder = overrideSurfaceHolder ?: deferredSurfaceHolder.await()
 
                     val watchFace =
@@ -2299,11 +2300,7 @@
                     throw e
                 } catch (e: Exception) {
                     Log.e(TAG, "WatchFace crashed during init", e)
-                    futuresToCancelOnError.forEach {
-                        if (!it.isCompleted) {
-                            it.completeExceptionally(e)
-                        }
-                    }
+                    deferredValidation.completeExceptionally(e)
                 }
 
                 deferredValidation.complete(Unit)
@@ -2930,10 +2927,12 @@
  * WatchFaceRuntimeService is a special kind of [WatchFaceService], which loads the watch face
  * definition from another resource only watch face package (see the
  * `resourceOnlyWatchFacePackageName` parameter passed to [createUserStyleSchema],
- * [createComplicationSlotsManager], [createUserStyleFlavors] and [createWatchFace]).
+ * [createComplicationSlotsManager], [createUserStyleFlavors] and
+ * [createWatchFace]).
  *
  * Note because a WatchFaceRuntimeService loads it's resources from another package, it will need
  * the following permission:
+ *
  * ```
  *     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
  *         tools:ignore="QueryAllPackagesPermission" />
@@ -2994,11 +2993,10 @@
     internal override fun createComplicationSlotsManagerInternal(
         currentUserStyleRepository: CurrentUserStyleRepository,
         resourceOnlyWatchFacePackageName: String?
-    ): ComplicationSlotsManager =
-        createComplicationSlotsManager(
-            currentUserStyleRepository,
-            resourceOnlyWatchFacePackageName!!
-        )
+    ): ComplicationSlotsManager = createComplicationSlotsManager(
+        currentUserStyleRepository,
+        resourceOnlyWatchFacePackageName!!
+    )
 
     @Suppress("DocumentExceptions") // NB this method isn't expected to be called from user code.
     final override fun createComplicationSlotsManager(
@@ -3034,12 +3032,11 @@
         currentUserStyleRepository: CurrentUserStyleRepository,
         complicationSlotsManager: ComplicationSlotsManager,
         resourceOnlyWatchFacePackageName: String?
-    ): UserStyleFlavors =
-        createUserStyleFlavors(
-            currentUserStyleRepository,
-            complicationSlotsManager,
-            resourceOnlyWatchFacePackageName!!
-        )
+    ): UserStyleFlavors = createUserStyleFlavors(
+        currentUserStyleRepository,
+        complicationSlotsManager,
+        resourceOnlyWatchFacePackageName!!
+    )
 
     @Suppress("DocumentExceptions") // NB this method isn't expected to be called from user code.
     final override fun createUserStyleFlavors(
@@ -3084,14 +3081,13 @@
         complicationSlotsManager: ComplicationSlotsManager,
         currentUserStyleRepository: CurrentUserStyleRepository,
         resourceOnlyWatchFacePackageName: String?
-    ): WatchFace =
-        createWatchFace(
-            surfaceHolder,
-            watchState,
-            complicationSlotsManager,
-            currentUserStyleRepository,
-            resourceOnlyWatchFacePackageName!!
-        )
+    ): WatchFace = createWatchFace(
+        surfaceHolder,
+        watchState,
+        complicationSlotsManager,
+        currentUserStyleRepository,
+        resourceOnlyWatchFacePackageName!!
+    )
 
     @Suppress("DocumentExceptions") // NB this method isn't expected to be called from user code.
     final override suspend fun createWatchFace(
diff --git a/wear/watchface/watchface/src/main/res/values/attrs.xml b/wear/watchface/watchface/src/main/res/values/attrs.xml
index 02dacba..3e8d8b2 100644
--- a/wear/watchface/watchface/src/main/res/values/attrs.xml
+++ b/wear/watchface/watchface/src/main/res/values/attrs.xml
@@ -80,7 +80,6 @@
         <enum name="DATA_SOURCE_DAY_OF_WEEK" value="13" />
         <enum name="DATA_SOURCE_FAVORITE_CONTACT" value="14" />
         <enum name="DATA_SOURCE_DAY_AND_DATE" value="16" />
-        <enum name="DATA_SOURCE_WEATHER" value="17" />
     </attr>
 
     <!-- Required. The default [ComplicationType] for the default complication data source.
diff --git a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
index 97204f0..8e9ec40 100644
--- a/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
+++ b/wear/wear/src/main/java/androidx/wear/ambient/AmbientLifecycleObserver.kt
@@ -39,9 +39,10 @@
  *         // ...
  *     }
  *
- *     private val ambientObserver = AmbientLifecycleObserver(this, callbacks)
+ *     private val ambientObserver = AmbientLifecycleObserver(this, mainExecutor, callbacks)
  *
  *     override fun onCreate(savedInstanceState: Bundle) {
+ *         super.onCreate(savedInstanceState)
  *         lifecycle.addObserver(ambientObserver)
  *     }
  * }
@@ -83,9 +84,10 @@
  *         // ...
  *     }
  *
- *     private val ambientObserver = DefaultAmbientLifecycleObserver(this, callbacks)
+ *     private val ambientObserver = AmbientLifecycleObserver(this, callbacks)
  *
  *     override fun onCreate(savedInstanceState: Bundle) {
+ *         super.onCreate(savedInstanceState)
  *         lifecycle.addObserver(ambientObserver)
  *     }
  * }
diff --git a/work/work-gcm/api/2.9.0-beta01.txt b/work/work-gcm/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-gcm/api/2.9.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-gcm/api/res-2.9.0-beta01.txt b/work/work-gcm/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-gcm/api/res-2.9.0-beta01.txt
diff --git a/work/work-gcm/api/restricted_2.9.0-beta01.txt b/work/work-gcm/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-gcm/api/restricted_2.9.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-multiprocess/api/2.9.0-beta01.txt b/work/work-multiprocess/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..bd27cfb
--- /dev/null
+++ b/work/work-multiprocess/api/2.9.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.9.0-beta01.txt b/work/work-multiprocess/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-multiprocess/api/res-2.9.0-beta01.txt
diff --git a/work/work-multiprocess/api/restricted_2.9.0-beta01.txt b/work/work-multiprocess/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..bd27cfb
--- /dev/null
+++ b/work/work-multiprocess/api/restricted_2.9.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.9.0-beta01.txt b/work/work-runtime-ktx/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-runtime-ktx/api/2.9.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-runtime-ktx/api/res-2.9.0-beta01.txt b/work/work-runtime-ktx/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-runtime-ktx/api/res-2.9.0-beta01.txt
diff --git a/work/work-runtime-ktx/api/restricted_2.9.0-beta01.txt b/work/work-runtime-ktx/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/work/work-runtime-ktx/api/restricted_2.9.0-beta01.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/work/work-runtime/api/2.9.0-beta01.txt b/work/work-runtime/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..4c1e9d7
--- /dev/null
+++ b/work/work-runtime/api/2.9.0-beta01.txt
@@ -0,0 +1,606 @@
+// 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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 interface Clock {
+    method public long currentTimeMillis();
+  }
+
+  public final class Configuration {
+    method public androidx.work.Clock getClock();
+    method public int getContentUriTriggerWorkersLimit();
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.core.util.Consumer<java.lang.Throwable>? getInitializationExceptionHandler();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public androidx.core.util.Consumer<java.lang.Throwable>? getSchedulingExceptionHandler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    property public final androidx.work.Clock clock;
+    property public final int contentUriTriggerWorkersLimit;
+    property public final String? defaultProcessName;
+    property public final java.util.concurrent.Executor executor;
+    property public final androidx.core.util.Consumer<java.lang.Throwable>? initializationExceptionHandler;
+    property public final androidx.work.InputMergerFactory inputMergerFactory;
+    property public final int maxJobSchedulerId;
+    property public final int minJobSchedulerId;
+    property public final androidx.work.RunnableScheduler runnableScheduler;
+    property public final androidx.core.util.Consumer<java.lang.Throwable>? schedulingExceptionHandler;
+    property public final java.util.concurrent.Executor taskExecutor;
+    property public final androidx.work.WorkerFactory workerFactory;
+    field public static final androidx.work.Configuration.Companion Companion;
+    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 setClock(androidx.work.Clock clock);
+    method public androidx.work.Configuration.Builder setContentUriTriggerWorkersLimit(int contentUriTriggerWorkersLimit);
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String processName);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor executor);
+    method public androidx.work.Configuration.Builder setInitializationExceptionHandler(androidx.core.util.Consumer<java.lang.Throwable> exceptionHandler);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory inputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int maxSchedulerLimit);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int loggingLevel);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler runnableScheduler);
+    method public androidx.work.Configuration.Builder setSchedulingExceptionHandler(androidx.core.util.Consumer<java.lang.Throwable> schedulingExceptionHandler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor taskExecutor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory workerFactory);
+  }
+
+  public static final class Configuration.Companion {
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+    property public abstract androidx.work.Configuration workManagerConfiguration;
+  }
+
+  public final class Constraints {
+    ctor public Constraints(androidx.work.Constraints other);
+    ctor @androidx.room.Ignore public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow);
+    ctor @RequiresApi(23) @androidx.room.Ignore public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresDeviceIdle, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow);
+    ctor @RequiresApi(24) public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresDeviceIdle, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow, optional long contentTriggerUpdateDelayMillis, optional long contentTriggerMaxDelayMillis, optional java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers);
+    method @RequiresApi(24) public long getContentTriggerMaxDelayMillis();
+    method @RequiresApi(24) public long getContentTriggerUpdateDelayMillis();
+    method @RequiresApi(24) 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 @RequiresApi(24) public final long contentTriggerMaxDelayMillis;
+    property @RequiresApi(24) public final long contentTriggerUpdateDelayMillis;
+    property @RequiresApi(24) 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(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+  }
+
+  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 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 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 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 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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data> inputs);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String className);
+  }
+
+  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 @RequiresApi(31) public final int getStopReason();
+    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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS>);
+  }
+
+  public enum OutOfQuotaPolicy {
+    method public static androidx.work.OutOfQuotaPolicy valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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> inputs);
+  }
+
+  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 @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval, java.time.Duration flexInterval);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexInterval, java.util.concurrent.TimeUnit flexIntervalTimeUnit);
+    method public androidx.work.PeriodicWorkRequest.Builder clearNextScheduleTimeOverride();
+    method public androidx.work.PeriodicWorkRequest.Builder setNextScheduleTimeOverride(long nextScheduleTimeOverrideMillis);
+  }
+
+  public static final class PeriodicWorkRequest.Companion {
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    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);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    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);
+  }
+
+  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 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 {
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo, optional long nextScheduleTimeMillis);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo, optional long nextScheduleTimeMillis, optional int stopReason);
+    method public androidx.work.Constraints getConstraints();
+    method public int getGeneration();
+    method public java.util.UUID getId();
+    method public long getInitialDelayMillis();
+    method public long getNextScheduleTimeMillis();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.WorkInfo.PeriodicityInfo? getPeriodicityInfo();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0L) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method @RequiresApi(31) public int getStopReason();
+    method public java.util.Set<java.lang.String> getTags();
+    property public final androidx.work.Constraints constraints;
+    property public final int generation;
+    property public final java.util.UUID id;
+    property public final long initialDelayMillis;
+    property public final long nextScheduleTimeMillis;
+    property public final androidx.work.Data outputData;
+    property public final androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo;
+    property public final androidx.work.Data progress;
+    property @IntRange(from=0L) public final int runAttemptCount;
+    property public final androidx.work.WorkInfo.State state;
+    property @RequiresApi(31) public final int stopReason;
+    property public final java.util.Set<java.lang.String> tags;
+    field public static final androidx.work.WorkInfo.Companion Companion;
+    field public static final int STOP_REASON_APP_STANDBY = 12; // 0xc
+    field public static final int STOP_REASON_BACKGROUND_RESTRICTION = 11; // 0xb
+    field public static final int STOP_REASON_CANCELLED_BY_APP = 1; // 0x1
+    field public static final int STOP_REASON_CONSTRAINT_BATTERY_NOT_LOW = 5; // 0x5
+    field public static final int STOP_REASON_CONSTRAINT_CHARGING = 6; // 0x6
+    field public static final int STOP_REASON_CONSTRAINT_CONNECTIVITY = 7; // 0x7
+    field public static final int STOP_REASON_CONSTRAINT_DEVICE_IDLE = 8; // 0x8
+    field public static final int STOP_REASON_CONSTRAINT_STORAGE_NOT_LOW = 9; // 0x9
+    field public static final int STOP_REASON_DEVICE_STATE = 4; // 0x4
+    field public static final int STOP_REASON_ESTIMATED_APP_LAUNCH_TIME_CHANGED = 15; // 0xf
+    field public static final int STOP_REASON_NOT_STOPPED = -256; // 0xffffff00
+    field public static final int STOP_REASON_PREEMPT = 2; // 0x2
+    field public static final int STOP_REASON_QUOTA = 10; // 0xa
+    field public static final int STOP_REASON_SYSTEM_PROCESSING = 14; // 0xe
+    field public static final int STOP_REASON_TIMEOUT = 3; // 0x3
+    field public static final int STOP_REASON_UNKNOWN = -512; // 0xfffffe00
+    field public static final int STOP_REASON_USER = 13; // 0xd
+  }
+
+  public static final class WorkInfo.Companion {
+  }
+
+  public static final class WorkInfo.PeriodicityInfo {
+    ctor public WorkInfo.PeriodicityInfo(long repeatIntervalMillis, long flexIntervalMillis);
+    method public long getFlexIntervalMillis();
+    method public long getRepeatIntervalMillis();
+    property public final long flexIntervalMillis;
+    property public final long repeatIntervalMillis;
+  }
+
+  public enum WorkInfo.State {
+    method public final boolean isFinished();
+    method public static androidx.work.WorkInfo.State valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.work.WorkInfo.State[] values();
+    property public final 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 kotlinx.coroutines.flow.Flow<androidx.work.WorkInfo!> getWorkInfoByIdFlow(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 kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagFlow(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosFlow(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkFlow(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(androidx.work.WorkInfo.State!...);
+    method public static androidx.work.WorkQuery fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery fromTags(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromTags(java.util.List<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 @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration duration);
+    method public final B keepResultsForAtLeast(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, java.time.Duration duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, long backoffDelay, java.util.concurrent.TimeUnit timeUnit);
+    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 @RequiresApi(26) public B setInitialDelay(java.time.Duration duration);
+    method public B setInitialDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    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.9.0-beta01.txt b/work/work-runtime/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-runtime/api/res-2.9.0-beta01.txt
diff --git a/work/work-runtime/api/restricted_2.9.0-beta01.txt b/work/work-runtime/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..4c1e9d7
--- /dev/null
+++ b/work/work-runtime/api/restricted_2.9.0-beta01.txt
@@ -0,0 +1,606 @@
+// 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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 interface Clock {
+    method public long currentTimeMillis();
+  }
+
+  public final class Configuration {
+    method public androidx.work.Clock getClock();
+    method public int getContentUriTriggerWorkersLimit();
+    method public String? getDefaultProcessName();
+    method public java.util.concurrent.Executor getExecutor();
+    method public androidx.core.util.Consumer<java.lang.Throwable>? getInitializationExceptionHandler();
+    method public androidx.work.InputMergerFactory getInputMergerFactory();
+    method public int getMaxJobSchedulerId();
+    method public int getMinJobSchedulerId();
+    method public androidx.work.RunnableScheduler getRunnableScheduler();
+    method public androidx.core.util.Consumer<java.lang.Throwable>? getSchedulingExceptionHandler();
+    method public java.util.concurrent.Executor getTaskExecutor();
+    method public androidx.work.WorkerFactory getWorkerFactory();
+    property public final androidx.work.Clock clock;
+    property public final int contentUriTriggerWorkersLimit;
+    property public final String? defaultProcessName;
+    property public final java.util.concurrent.Executor executor;
+    property public final androidx.core.util.Consumer<java.lang.Throwable>? initializationExceptionHandler;
+    property public final androidx.work.InputMergerFactory inputMergerFactory;
+    property public final int maxJobSchedulerId;
+    property public final int minJobSchedulerId;
+    property public final androidx.work.RunnableScheduler runnableScheduler;
+    property public final androidx.core.util.Consumer<java.lang.Throwable>? schedulingExceptionHandler;
+    property public final java.util.concurrent.Executor taskExecutor;
+    property public final androidx.work.WorkerFactory workerFactory;
+    field public static final androidx.work.Configuration.Companion Companion;
+    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 setClock(androidx.work.Clock clock);
+    method public androidx.work.Configuration.Builder setContentUriTriggerWorkersLimit(int contentUriTriggerWorkersLimit);
+    method public androidx.work.Configuration.Builder setDefaultProcessName(String processName);
+    method public androidx.work.Configuration.Builder setExecutor(java.util.concurrent.Executor executor);
+    method public androidx.work.Configuration.Builder setInitializationExceptionHandler(androidx.core.util.Consumer<java.lang.Throwable> exceptionHandler);
+    method public androidx.work.Configuration.Builder setInputMergerFactory(androidx.work.InputMergerFactory inputMergerFactory);
+    method public androidx.work.Configuration.Builder setJobSchedulerJobIdRange(int minJobSchedulerId, int maxJobSchedulerId);
+    method public androidx.work.Configuration.Builder setMaxSchedulerLimit(int maxSchedulerLimit);
+    method public androidx.work.Configuration.Builder setMinimumLoggingLevel(int loggingLevel);
+    method public androidx.work.Configuration.Builder setRunnableScheduler(androidx.work.RunnableScheduler runnableScheduler);
+    method public androidx.work.Configuration.Builder setSchedulingExceptionHandler(androidx.core.util.Consumer<java.lang.Throwable> schedulingExceptionHandler);
+    method public androidx.work.Configuration.Builder setTaskExecutor(java.util.concurrent.Executor taskExecutor);
+    method public androidx.work.Configuration.Builder setWorkerFactory(androidx.work.WorkerFactory workerFactory);
+  }
+
+  public static final class Configuration.Companion {
+  }
+
+  public static interface Configuration.Provider {
+    method public androidx.work.Configuration getWorkManagerConfiguration();
+    property public abstract androidx.work.Configuration workManagerConfiguration;
+  }
+
+  public final class Constraints {
+    ctor public Constraints(androidx.work.Constraints other);
+    ctor @androidx.room.Ignore public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow);
+    ctor @RequiresApi(23) @androidx.room.Ignore public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresDeviceIdle, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow);
+    ctor @RequiresApi(24) public Constraints(optional androidx.work.NetworkType requiredNetworkType, optional boolean requiresCharging, optional boolean requiresDeviceIdle, optional boolean requiresBatteryNotLow, optional boolean requiresStorageNotLow, optional long contentTriggerUpdateDelayMillis, optional long contentTriggerMaxDelayMillis, optional java.util.Set<androidx.work.Constraints.ContentUriTrigger> contentUriTriggers);
+    method @RequiresApi(24) public long getContentTriggerMaxDelayMillis();
+    method @RequiresApi(24) public long getContentTriggerUpdateDelayMillis();
+    method @RequiresApi(24) 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 @RequiresApi(24) public final long contentTriggerMaxDelayMillis;
+    property @RequiresApi(24) public final long contentTriggerUpdateDelayMillis;
+    property @RequiresApi(24) 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(26) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentMaxDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(java.time.Duration duration);
+    method @RequiresApi(24) public androidx.work.Constraints.Builder setTriggerContentUpdateDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+  }
+
+  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 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 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 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 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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 abstract class InputMerger {
+    ctor public InputMerger();
+    method public abstract androidx.work.Data merge(java.util.List<androidx.work.Data> inputs);
+  }
+
+  public abstract class InputMergerFactory {
+    ctor public InputMergerFactory();
+    method public abstract androidx.work.InputMerger? createInputMerger(String className);
+  }
+
+  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 @RequiresApi(31) public final int getStopReason();
+    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 value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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 final class OperationKt {
+    method public static suspend inline Object? await(androidx.work.Operation, kotlin.coroutines.Continuation<? super androidx.work.Operation.State.SUCCESS>);
+  }
+
+  public enum OutOfQuotaPolicy {
+    method public static androidx.work.OutOfQuotaPolicy valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    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> inputs);
+  }
+
+  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 @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval);
+    ctor @RequiresApi(26) public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, java.time.Duration repeatInterval, java.time.Duration flexInterval);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    ctor public PeriodicWorkRequest.Builder(Class<? extends androidx.work.ListenableWorker> workerClass, long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit, long flexInterval, java.util.concurrent.TimeUnit flexIntervalTimeUnit);
+    method public androidx.work.PeriodicWorkRequest.Builder clearNextScheduleTimeOverride();
+    method public androidx.work.PeriodicWorkRequest.Builder setNextScheduleTimeOverride(long nextScheduleTimeOverrideMillis);
+  }
+
+  public static final class PeriodicWorkRequest.Companion {
+  }
+
+  public final class PeriodicWorkRequestKt {
+    method @RequiresApi(26) public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder PeriodicWorkRequestBuilder(java.time.Duration repeatInterval);
+    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);
+    method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.PeriodicWorkRequest.Builder PeriodicWorkRequestBuilder(long repeatInterval, java.util.concurrent.TimeUnit repeatIntervalTimeUnit);
+    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);
+  }
+
+  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 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 {
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo, optional long nextScheduleTimeMillis);
+    ctor public WorkInfo(java.util.UUID id, androidx.work.WorkInfo.State state, java.util.Set<java.lang.String> tags, optional androidx.work.Data outputData, optional androidx.work.Data progress, optional int runAttemptCount, optional int generation, optional androidx.work.Constraints constraints, optional long initialDelayMillis, optional androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo, optional long nextScheduleTimeMillis, optional int stopReason);
+    method public androidx.work.Constraints getConstraints();
+    method public int getGeneration();
+    method public java.util.UUID getId();
+    method public long getInitialDelayMillis();
+    method public long getNextScheduleTimeMillis();
+    method public androidx.work.Data getOutputData();
+    method public androidx.work.WorkInfo.PeriodicityInfo? getPeriodicityInfo();
+    method public androidx.work.Data getProgress();
+    method @IntRange(from=0L) public int getRunAttemptCount();
+    method public androidx.work.WorkInfo.State getState();
+    method @RequiresApi(31) public int getStopReason();
+    method public java.util.Set<java.lang.String> getTags();
+    property public final androidx.work.Constraints constraints;
+    property public final int generation;
+    property public final java.util.UUID id;
+    property public final long initialDelayMillis;
+    property public final long nextScheduleTimeMillis;
+    property public final androidx.work.Data outputData;
+    property public final androidx.work.WorkInfo.PeriodicityInfo? periodicityInfo;
+    property public final androidx.work.Data progress;
+    property @IntRange(from=0L) public final int runAttemptCount;
+    property public final androidx.work.WorkInfo.State state;
+    property @RequiresApi(31) public final int stopReason;
+    property public final java.util.Set<java.lang.String> tags;
+    field public static final androidx.work.WorkInfo.Companion Companion;
+    field public static final int STOP_REASON_APP_STANDBY = 12; // 0xc
+    field public static final int STOP_REASON_BACKGROUND_RESTRICTION = 11; // 0xb
+    field public static final int STOP_REASON_CANCELLED_BY_APP = 1; // 0x1
+    field public static final int STOP_REASON_CONSTRAINT_BATTERY_NOT_LOW = 5; // 0x5
+    field public static final int STOP_REASON_CONSTRAINT_CHARGING = 6; // 0x6
+    field public static final int STOP_REASON_CONSTRAINT_CONNECTIVITY = 7; // 0x7
+    field public static final int STOP_REASON_CONSTRAINT_DEVICE_IDLE = 8; // 0x8
+    field public static final int STOP_REASON_CONSTRAINT_STORAGE_NOT_LOW = 9; // 0x9
+    field public static final int STOP_REASON_DEVICE_STATE = 4; // 0x4
+    field public static final int STOP_REASON_ESTIMATED_APP_LAUNCH_TIME_CHANGED = 15; // 0xf
+    field public static final int STOP_REASON_NOT_STOPPED = -256; // 0xffffff00
+    field public static final int STOP_REASON_PREEMPT = 2; // 0x2
+    field public static final int STOP_REASON_QUOTA = 10; // 0xa
+    field public static final int STOP_REASON_SYSTEM_PROCESSING = 14; // 0xe
+    field public static final int STOP_REASON_TIMEOUT = 3; // 0x3
+    field public static final int STOP_REASON_UNKNOWN = -512; // 0xfffffe00
+    field public static final int STOP_REASON_USER = 13; // 0xd
+  }
+
+  public static final class WorkInfo.Companion {
+  }
+
+  public static final class WorkInfo.PeriodicityInfo {
+    ctor public WorkInfo.PeriodicityInfo(long repeatIntervalMillis, long flexIntervalMillis);
+    method public long getFlexIntervalMillis();
+    method public long getRepeatIntervalMillis();
+    property public final long flexIntervalMillis;
+    property public final long repeatIntervalMillis;
+  }
+
+  public enum WorkInfo.State {
+    method public final boolean isFinished();
+    method public static androidx.work.WorkInfo.State valueOf(String value) throws java.lang.IllegalArgumentException, java.lang.NullPointerException;
+    method public static androidx.work.WorkInfo.State[] values();
+    property public final 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 kotlinx.coroutines.flow.Flow<androidx.work.WorkInfo!> getWorkInfoByIdFlow(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 kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagFlow(String);
+    method public abstract androidx.lifecycle.LiveData<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosByTagLiveData(String);
+    method public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosFlow(androidx.work.WorkQuery);
+    method public abstract com.google.common.util.concurrent.ListenableFuture<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWork(String);
+    method public abstract kotlinx.coroutines.flow.Flow<java.util.List<androidx.work.WorkInfo!>!> getWorkInfosForUniqueWorkFlow(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(androidx.work.WorkInfo.State!...);
+    method public static androidx.work.WorkQuery fromStates(java.util.List<androidx.work.WorkInfo.State!>);
+    method public static androidx.work.WorkQuery fromTags(java.lang.String!...);
+    method public static androidx.work.WorkQuery fromTags(java.util.List<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 @RequiresApi(26) public final B keepResultsForAtLeast(java.time.Duration duration);
+    method public final B keepResultsForAtLeast(long duration, java.util.concurrent.TimeUnit timeUnit);
+    method @RequiresApi(26) public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, java.time.Duration duration);
+    method public final B setBackoffCriteria(androidx.work.BackoffPolicy backoffPolicy, long backoffDelay, java.util.concurrent.TimeUnit timeUnit);
+    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 @RequiresApi(26) public B setInitialDelay(java.time.Duration duration);
+    method public B setInitialDelay(long duration, java.util.concurrent.TimeUnit timeUnit);
+    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-rxjava2/api/2.9.0-beta01.txt b/work/work-rxjava2/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..1cca40e
--- /dev/null
+++ b/work/work-rxjava2/api/2.9.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.9.0-beta01.txt b/work/work-rxjava2/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-rxjava2/api/res-2.9.0-beta01.txt
diff --git a/work/work-rxjava2/api/restricted_2.9.0-beta01.txt b/work/work-rxjava2/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..1cca40e
--- /dev/null
+++ b/work/work-rxjava2/api/restricted_2.9.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.9.0-beta01.txt b/work/work-rxjava3/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..0983052
--- /dev/null
+++ b/work/work-rxjava3/api/2.9.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.9.0-beta01.txt b/work/work-rxjava3/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-rxjava3/api/res-2.9.0-beta01.txt
diff --git a/work/work-rxjava3/api/restricted_2.9.0-beta01.txt b/work/work-rxjava3/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..0983052
--- /dev/null
+++ b/work/work-rxjava3/api/restricted_2.9.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.9.0-beta01.txt b/work/work-testing/api/2.9.0-beta01.txt
new file mode 100644
index 0000000..2812b61
--- /dev/null
+++ b/work/work-testing/api/2.9.0-beta01.txt
@@ -0,0 +1,61 @@
+// 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<java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<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<java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method public static void closeWorkDatabase();
+    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);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration, androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode);
+  }
+
+  public enum WorkManagerTestInitHelper.ExecutorsMode {
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode LEGACY_OVERRIDE_WITH_SYNCHRONOUS_EXECUTORS;
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode PRESERVE_EXECUTORS;
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode USE_TIME_BASED_SCHEDULING;
+  }
+
+}
+
diff --git a/work/work-testing/api/res-2.9.0-beta01.txt b/work/work-testing/api/res-2.9.0-beta01.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/work/work-testing/api/res-2.9.0-beta01.txt
diff --git a/work/work-testing/api/restricted_2.9.0-beta01.txt b/work/work-testing/api/restricted_2.9.0-beta01.txt
new file mode 100644
index 0000000..2812b61
--- /dev/null
+++ b/work/work-testing/api/restricted_2.9.0-beta01.txt
@@ -0,0 +1,61 @@
+// 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<java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<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<java.lang.String> tags, optional int runAttemptCount, optional java.util.List<? extends android.net.Uri> triggeredContentUris, optional java.util.List<java.lang.String> triggeredContentAuthorities);
+  }
+
+  public final class WorkManagerTestInitHelper {
+    method public static void closeWorkDatabase();
+    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);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.Configuration, androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode);
+    method public static void initializeTestWorkManager(android.content.Context, androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode);
+  }
+
+  public enum WorkManagerTestInitHelper.ExecutorsMode {
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode LEGACY_OVERRIDE_WITH_SYNCHRONOUS_EXECUTORS;
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode PRESERVE_EXECUTORS;
+    enum_constant public static final androidx.work.testing.WorkManagerTestInitHelper.ExecutorsMode USE_TIME_BASED_SCHEDULING;
+  }
+
+}
+