Merge "Create a Factory class for DefaultSurfaceProcessor" into androidx-main
diff --git a/appactions/interaction/interaction-service/api/current.txt b/appactions/interaction/interaction-service/api/current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/appactions/interaction/interaction-service/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service/api/public_plus_experimental_current.txt b/appactions/interaction/interaction-service/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/appactions/interaction/interaction-service/api/public_plus_experimental_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service/api/res-current.txt b/appactions/interaction/interaction-service/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/appactions/interaction/interaction-service/api/res-current.txt
diff --git a/appactions/interaction/interaction-service/api/restricted_current.txt b/appactions/interaction/interaction-service/api/restricted_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/appactions/interaction/interaction-service/api/restricted_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/appactions/interaction/interaction-service/build.gradle b/appactions/interaction/interaction-service/build.gradle
new file mode 100644
index 0000000..fa19659
--- /dev/null
+++ b/appactions/interaction/interaction-service/build.gradle
@@ -0,0 +1,36 @@
+/*
+ * 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")
+}
+
+dependencies {
+}
+
+android {
+    namespace "androidx.appactions.interaction.service"
+}
+
+androidx {
+    name = "androidx.appactions.interaction:interaction-service"
+    type = LibraryType.PUBLISHED_LIBRARY
+    inceptionYear = "2023"
+    description = "Library for integrating with Google Assistant via GRPC binder channel."
+}
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/build.gradle b/benchmark/integration-tests/baselineprofiles-consumer/build.gradle
new file mode 100644
index 0000000..d3e1e45
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/build.gradle
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.application")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.consumer")
+    id("androidx.baselineprofiles.buildprovider")
+}
+
+android {
+    buildTypes {
+        release {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt")
+        }
+    }
+    namespace "androidx.benchmark.integration.baselineprofiles.consumer"
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+    implementation(libs.constraintLayout)
+    baselineprofiles(project(":benchmark:integration-tests:baselineprofiles-producer"))
+}
+
+apply(from: "../baselineprofiles-test-utils/utils.gradle")
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-consumer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..ca9827a
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <application
+        android:allowBackup="false"
+        android:label="Jetpack Baselineprofiles Target"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppCompat"
+        tools:ignore="MissingApplicationIcon">
+
+        <activity
+            android:name=".EmptyActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="androidx.benchmark.integration.baselineprofiles.consumer.EMPTY_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/src/main/expected-baseline-prof.txt b/benchmark/integration-tests/baselineprofiles-consumer/src/main/expected-baseline-prof.txt
new file mode 100644
index 0000000..205f8c9
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/src/main/expected-baseline-prof.txt
@@ -0,0 +1,172 @@
+HSPLandroidx/appcompat/widget/TintTypedArray;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/appcompat/widget/TintTypedArray;->measure(Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Z)Z
+HSPLandroidx/appcompat/widget/TintTypedArray;->solveLinearSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;II)V
+HSPLandroidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity;-><init>()V
+HSPLandroidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity;->onCreate(Landroid/os/Bundle;)V
+HSPLandroidx/collection/ArrayMap$1;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->addError(Landroidx/constraintlayout/solver/LinearSystem;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->pivot(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->reset()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromFinalVariable(Landroidx/constraintlayout/solver/SolverVariable;Z)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/LinearSystem$ValuesRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;-><init>()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->acquireSolverVariable$enumunboxing$(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addCentering(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IFLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addConstraint(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createErrorVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createObjectVariable(Ljava/lang/Object;)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createRow()Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createSlackVariable()Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getObjectVariableValue(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;)I
+HSPLandroidx/constraintlayout/solver/LinearSystem;->increaseTableSize()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->optimize(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->releaseRows()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->reset()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;-><init>()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->acquire()Ljava/lang/Object;
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->release(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;-><init>(Landroidx/constraintlayout/solver/PriorityGoalRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->addToGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->getPivotCandidate([Z)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->removeGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;->ordinal(I)I
+HSPLandroidx/constraintlayout/solver/SolverVariable;-><init>(I)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->addToRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->removeFromRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->reset()V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->updateReferencesWithNewDefinition(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->add(Landroidx/constraintlayout/solver/SolverVariable;FZ)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addToHashMap(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addVariable(ILandroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->clear()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->divideByAmount(F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->get(Landroidx/constraintlayout/solver/SolverVariable;)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getCurrentSize()I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariableValue(I)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->indexOf(Landroidx/constraintlayout/solver/SolverVariable;)I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->invert()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->put(Landroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->remove(Landroidx/constraintlayout/solver/SolverVariable;Z)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->use(Landroidx/constraintlayout/solver/ArrayRow;Z)F
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><init>(ILjava/lang/String;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->connect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getMargin()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->isConnected()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->resetSolverVariable()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->applyConstraints$enumunboxing$(Landroidx/constraintlayout/solver/LinearSystem;ZZZZLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IZLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIIIFZZZZIIIIFZ)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->createObjectVariables(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getAnchor(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getDimensionBehaviour$enumunboxing$(I)I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getHeight()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getWidth()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getX()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getY()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->immediateConnect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isChainHead(I)Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInHorizontalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInVerticalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHeight(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->updateFromSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->addChildrenToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->layout()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;-><clinit>()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->resolveLayoutDirection(I)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->validate()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;-><init>(Landroidx/constraintlayout/widget/ConstraintLayout;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->measure(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->applyConstraintsFromLayoutParams(ZLandroid/view/View;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;Landroid/util/SparseArray;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->checkLayoutParams(Landroid/view/ViewGroup$LayoutParams;)Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->dispatchDraw(Landroid/graphics/Canvas;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->generateLayoutParams(Landroid/util/AttributeSet;)Landroid/view/ViewGroup$LayoutParams;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getPaddingWidth()I
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getViewWidget(Landroid/view/View;)Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->isRtl()Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onLayout(ZIIII)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onMeasure(II)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onViewAdded(Landroid/view/View;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->requestLayout()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->updateHierarchy()Z
+HSPLandroidx/constraintlayout/widget/R$styleable;-><clinit>()V
+HSPLandroidx/core/app/CoreComponentFactory;-><init>()V
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;
+HSPLandroidx/core/util/ObjectsCompat;-><clinit>()V
+Landroidx/appcompat/widget/TintTypedArray;
+Landroidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity;
+Landroidx/collection/ArrayMap$1;
+Landroidx/constraintlayout/solver/ArrayLinkedVariables;
+Landroidx/constraintlayout/solver/ArrayRow$ArrayRowVariables;
+Landroidx/constraintlayout/solver/ArrayRow;
+Landroidx/constraintlayout/solver/LinearSystem$ValuesRow;
+Landroidx/constraintlayout/solver/LinearSystem;
+Landroidx/constraintlayout/solver/Pools$SimplePool;
+Landroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;
+Landroidx/constraintlayout/solver/PriorityGoalRow;
+Landroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;
+Landroidx/constraintlayout/solver/SolverVariable;
+Landroidx/constraintlayout/solver/SolverVariableValues;
+Landroidx/constraintlayout/solver/widgets/Barrier;
+Landroidx/constraintlayout/solver/widgets/ChainHead;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;
+Landroidx/constraintlayout/solver/widgets/Guideline;
+Landroidx/constraintlayout/solver/widgets/Helper;
+Landroidx/constraintlayout/solver/widgets/HelperWidget;
+Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;
+Landroidx/constraintlayout/solver/widgets/analyzer/Dependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;
+Landroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;
+Landroidx/constraintlayout/widget/ConstraintHelper;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;
+Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;
+Landroidx/constraintlayout/widget/ConstraintLayout;
+Landroidx/constraintlayout/widget/Guideline;
+Landroidx/constraintlayout/widget/R$styleable;
+Landroidx/core/app/CoreComponentFactory;
+Landroidx/core/util/ObjectsCompat;
\ No newline at end of file
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity.kt b/benchmark/integration-tests/baselineprofiles-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity.kt
new file mode 100644
index 0000000..9a1b40b
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/consumer/EmptyActivity.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.consumer
+
+import android.app.Activity
+import android.os.Bundle
+import android.widget.TextView
+
+class EmptyActivity : Activity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main)
+        findViewById<TextView>(R.id.txtNotice).setText(R.string.app_notice)
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/layout/activity_main.xml b/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..7739482
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/layout/activity_main.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/txtNotice"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Preview Some Text" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/values/donottranslate-strings.xml b/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/values/donottranslate-strings.xml
new file mode 100644
index 0000000..c880dc5
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-consumer/src/main/res/values/donottranslate-strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="app_notice">Baseline Profiles Integration Test App.</string>
+</resources>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/build.gradle b/benchmark/integration-tests/baselineprofiles-flavors-consumer/build.gradle
new file mode 100644
index 0000000..8ae2e3f
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/build.gradle
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.application")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.buildprovider")
+    id("androidx.baselineprofiles.consumer")
+}
+
+android {
+    buildTypes {
+        release {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt")
+        }
+    }
+    productFlavors {
+        flavorDimensions = ["version"]
+        free {
+            dimension "version"
+            applicationIdSuffix ".free"
+            versionNameSuffix "-free"
+        }
+        paid {
+            dimension "version"
+            applicationIdSuffix ".paid"
+            versionNameSuffix "-paid"
+        }
+    }
+    namespace "androidx.benchmark.integration.baselineprofiles.flavors.consumer"
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+    implementation(libs.constraintLayout)
+
+    baselineprofiles(project(":benchmark:integration-tests:baselineprofiles-flavors-producer"))
+}
+
+baselineProfilesProfileConsumer {
+    buildTypeName = "release"
+}
+
+apply(from: "../baselineprofiles-test-utils/utils.gradle")
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/free/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/free/AndroidManifest.xml
new file mode 100644
index 0000000..fb4bcd8
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/free/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:node="merge">
+
+    <application
+        android:allowBackup="false"
+        android:label="Jetpack Baselineprofiles Target"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppCompat"
+        tools:ignore="MissingApplicationIcon">
+
+        <activity
+            android:name=".EmptyActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="androidx.benchmark.integration.baselineprofiles.flavors.consumer.free.EMPTY_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..118910a
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:node="merge">
+
+    <application />
+</manifest>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/expected-baseline-prof.txt b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/expected-baseline-prof.txt
new file mode 100644
index 0000000..49756602
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/expected-baseline-prof.txt
@@ -0,0 +1,172 @@
+HSPLandroidx/appcompat/widget/TintTypedArray;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/appcompat/widget/TintTypedArray;->measure(Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Z)Z
+HSPLandroidx/appcompat/widget/TintTypedArray;->solveLinearSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;II)V
+HSPLandroidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity;-><init>()V
+HSPLandroidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity;->onCreate(Landroid/os/Bundle;)V
+HSPLandroidx/collection/ArrayMap$1;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->addError(Landroidx/constraintlayout/solver/LinearSystem;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->pivot(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->reset()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromFinalVariable(Landroidx/constraintlayout/solver/SolverVariable;Z)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/LinearSystem$ValuesRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;-><init>()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->acquireSolverVariable$enumunboxing$(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addCentering(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IFLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addConstraint(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createErrorVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createObjectVariable(Ljava/lang/Object;)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createRow()Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createSlackVariable()Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getObjectVariableValue(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;)I
+HSPLandroidx/constraintlayout/solver/LinearSystem;->increaseTableSize()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->optimize(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->releaseRows()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->reset()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;-><init>()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->acquire()Ljava/lang/Object;
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->release(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;-><init>(Landroidx/constraintlayout/solver/PriorityGoalRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->addToGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->getPivotCandidate([Z)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->removeGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;->ordinal(I)I
+HSPLandroidx/constraintlayout/solver/SolverVariable;-><init>(I)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->addToRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->removeFromRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->reset()V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->updateReferencesWithNewDefinition(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->add(Landroidx/constraintlayout/solver/SolverVariable;FZ)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addToHashMap(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addVariable(ILandroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->clear()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->divideByAmount(F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->get(Landroidx/constraintlayout/solver/SolverVariable;)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getCurrentSize()I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariableValue(I)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->indexOf(Landroidx/constraintlayout/solver/SolverVariable;)I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->invert()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->put(Landroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->remove(Landroidx/constraintlayout/solver/SolverVariable;Z)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->use(Landroidx/constraintlayout/solver/ArrayRow;Z)F
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><init>(ILjava/lang/String;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->connect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getMargin()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->isConnected()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->resetSolverVariable()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->applyConstraints$enumunboxing$(Landroidx/constraintlayout/solver/LinearSystem;ZZZZLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IZLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIIIFZZZZIIIIFZ)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->createObjectVariables(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getAnchor(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getDimensionBehaviour$enumunboxing$(I)I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getHeight()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getWidth()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getX()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getY()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->immediateConnect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isChainHead(I)Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInHorizontalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInVerticalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHeight(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->updateFromSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->addChildrenToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->layout()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;-><clinit>()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->resolveLayoutDirection(I)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->validate()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;-><init>(Landroidx/constraintlayout/widget/ConstraintLayout;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->measure(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->applyConstraintsFromLayoutParams(ZLandroid/view/View;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;Landroid/util/SparseArray;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->checkLayoutParams(Landroid/view/ViewGroup$LayoutParams;)Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->dispatchDraw(Landroid/graphics/Canvas;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->generateLayoutParams(Landroid/util/AttributeSet;)Landroid/view/ViewGroup$LayoutParams;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getPaddingWidth()I
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getViewWidget(Landroid/view/View;)Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->isRtl()Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onLayout(ZIIII)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onMeasure(II)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onViewAdded(Landroid/view/View;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->requestLayout()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->updateHierarchy()Z
+HSPLandroidx/constraintlayout/widget/R$styleable;-><clinit>()V
+HSPLandroidx/core/app/CoreComponentFactory;-><init>()V
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;
+HSPLandroidx/core/util/ObjectsCompat;-><clinit>()V
+Landroidx/appcompat/widget/TintTypedArray;
+Landroidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity;
+Landroidx/collection/ArrayMap$1;
+Landroidx/constraintlayout/solver/ArrayLinkedVariables;
+Landroidx/constraintlayout/solver/ArrayRow$ArrayRowVariables;
+Landroidx/constraintlayout/solver/ArrayRow;
+Landroidx/constraintlayout/solver/LinearSystem$ValuesRow;
+Landroidx/constraintlayout/solver/LinearSystem;
+Landroidx/constraintlayout/solver/Pools$SimplePool;
+Landroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;
+Landroidx/constraintlayout/solver/PriorityGoalRow;
+Landroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;
+Landroidx/constraintlayout/solver/SolverVariable;
+Landroidx/constraintlayout/solver/SolverVariableValues;
+Landroidx/constraintlayout/solver/widgets/Barrier;
+Landroidx/constraintlayout/solver/widgets/ChainHead;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;
+Landroidx/constraintlayout/solver/widgets/Guideline;
+Landroidx/constraintlayout/solver/widgets/Helper;
+Landroidx/constraintlayout/solver/widgets/HelperWidget;
+Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;
+Landroidx/constraintlayout/solver/widgets/analyzer/Dependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;
+Landroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;
+Landroidx/constraintlayout/widget/ConstraintHelper;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;
+Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;
+Landroidx/constraintlayout/widget/ConstraintLayout;
+Landroidx/constraintlayout/widget/Guideline;
+Landroidx/constraintlayout/widget/R$styleable;
+Landroidx/core/app/CoreComponentFactory;
+Landroidx/core/util/ObjectsCompat;
\ No newline at end of file
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity.kt b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity.kt
new file mode 100644
index 0000000..5119859
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/flavors/consumer/EmptyActivity.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.flavors.consumer
+
+import android.app.Activity
+import android.os.Bundle
+import android.widget.TextView
+
+class EmptyActivity : Activity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main)
+        findViewById<TextView>(R.id.txtNotice).setText(R.string.app_notice)
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/layout/activity_main.xml b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..7739482
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/layout/activity_main.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/txtNotice"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Preview Some Text" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/values/donottranslate-strings.xml b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/values/donottranslate-strings.xml
new file mode 100644
index 0000000..c880dc5
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/main/res/values/donottranslate-strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="app_notice">Baseline Profiles Integration Test App.</string>
+</resources>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/paid/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/paid/AndroidManifest.xml
new file mode 100644
index 0000000..514b52c
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-consumer/src/paid/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:node="merge">
+
+    <application
+        android:allowBackup="false"
+        android:label="Jetpack Baselineprofiles Target"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppCompat"
+        tools:ignore="MissingApplicationIcon">
+
+        <activity
+            android:name=".EmptyActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="androidx.benchmark.integration.baselineprofiles.flavors.consumer.paid.EMPTY_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/build.gradle b/benchmark/integration-tests/baselineprofiles-flavors-producer/build.gradle
new file mode 100644
index 0000000..d3e6cdb
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/build.gradle
@@ -0,0 +1,68 @@
+import com.android.build.api.dsl.ManagedVirtualDevice
+
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.test")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.producer")
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    testOptions.managedDevices.devices {
+        pixel6Api31(ManagedVirtualDevice) {
+            device = "Pixel 6"
+            apiLevel = 31
+            systemImageSource = "aosp"
+        }
+    }
+    buildTypes {
+        release { }
+    }
+    productFlavors {
+        flavorDimensions = ["version"]
+        free { dimension "version" }
+        paid { dimension "version" }
+    }
+    targetProjectPath = ":benchmark:integration-tests:baselineprofiles-flavors-consumer"
+    namespace "androidx.benchmark.integration.baselineprofiles.flavors.producer"
+}
+
+dependencies {
+    implementation(project(":benchmark:benchmark-junit4"))
+    implementation(project(":benchmark:benchmark-macro-junit4"))
+    implementation(libs.testRules)
+    implementation(libs.testExtJunit)
+    implementation(libs.testCore)
+    implementation(libs.testRunner)
+    implementation(libs.testUiautomator)
+    implementation(libs.testExtTruth)
+}
+
+baselineProfilesProfileProducer {
+    managedDevices += "pixel6Api31"
+    useConnectedDevices = false
+}
+
+androidx {
+    disableDeviceTests = true
+}
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/AndroidManifest.xml
new file mode 100644
index 0000000..bae036b
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt
new file mode 100644
index 0000000..1fd878f
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/free/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.flavors.producer
+
+import android.content.Intent
+import android.os.Build
+import androidx.benchmark.DeviceInfo
+import androidx.benchmark.macro.junit4.BaselineProfileRule
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+@SdkSuppress(minSdkVersion = 29)
+class BaselineProfileTest {
+
+    @get:Rule
+    val baselineRule = BaselineProfileRule()
+
+    @Test
+    fun startupBaselineProfile() {
+        assumeTrue(DeviceInfo.isRooted || Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+
+        // Collects the baseline profile
+        baselineRule.collectBaselineProfile(
+            packageName = PACKAGE_NAME,
+            profileBlock = {
+                startActivityAndWait(Intent(ACTION))
+                device.waitForIdle()
+            }
+        )
+    }
+
+    companion object {
+        private const val PACKAGE_NAME =
+            "androidx.benchmark.integration.baselineprofiles.flavors.consumer.free"
+        private const val ACTION =
+            "androidx.benchmark.integration.baselineprofiles.flavors.consumer.free.EMPTY_ACTIVITY"
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..d4c1970
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/main/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/AndroidManifest.xml
new file mode 100644
index 0000000..bae036b
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt
new file mode 100644
index 0000000..6a96947
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-flavors-producer/src/paid/java/androidx/benchmark/integration/baselineprofiles/flavors/producer/BaselineProfileTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.flavors.producer
+
+import android.content.Intent
+import android.os.Build
+import androidx.benchmark.DeviceInfo
+import androidx.benchmark.macro.junit4.BaselineProfileRule
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+@SdkSuppress(minSdkVersion = 29)
+class BaselineProfileTest {
+
+    @get:Rule
+    val baselineRule = BaselineProfileRule()
+
+    @Test
+    fun startupBaselineProfile() {
+        assumeTrue(DeviceInfo.isRooted || Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+
+        // Collects the baseline profile
+        baselineRule.collectBaselineProfile(
+            packageName = PACKAGE_NAME,
+            profileBlock = {
+                startActivityAndWait(Intent(ACTION))
+                device.waitForIdle()
+            }
+        )
+    }
+
+    companion object {
+        private const val PACKAGE_NAME =
+            "androidx.benchmark.integration.baselineprofiles.flavors.consumer.paid"
+        private const val ACTION =
+            "androidx.benchmark.integration.baselineprofiles.flavors.consumer.paid.EMPTY_ACTIVITY"
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-library-build-provider/build.gradle b/benchmark/integration-tests/baselineprofiles-library-build-provider/build.gradle
new file mode 100644
index 0000000..9c8061f
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-build-provider/build.gradle
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.application")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.buildprovider")
+}
+
+android {
+    buildTypes {
+        release {
+            minifyEnabled true
+            shrinkResources true
+            proguardFiles getDefaultProguardFile("proguard-android-optimize.txt")
+        }
+    }
+    namespace "androidx.benchmark.integration.baselineprofiles.library.buildprovider"
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+    implementation(libs.constraintLayout)
+}
diff --git a/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..fbb0bc7
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <application
+        android:allowBackup="false"
+        android:label="Jetpack Baselineprofiles Target"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AppCompat"
+        tools:ignore="MissingApplicationIcon">
+
+        <activity
+            android:name=".EmptyActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="androidx.benchmark.integration.baselineprofiles.EMPTY_ACTIVITY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <profileable android:shell="true" />
+    </application>
+</manifest>
diff --git a/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/java/androidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity.kt b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/java/androidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity.kt
new file mode 100644
index 0000000..64b8ed7
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/java/androidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity.kt
@@ -0,0 +1,29 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.library.buildprovider
+
+import android.app.Activity
+import android.os.Bundle
+import android.widget.TextView
+
+class EmptyActivity : Activity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main)
+        findViewById<TextView>(R.id.txtNotice).setText(R.string.app_notice)
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/layout/activity_main.xml b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..7739482
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/layout/activity_main.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/txtNotice"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Preview Some Text" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/values/donottranslate-strings.xml b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/values/donottranslate-strings.xml
new file mode 100644
index 0000000..c880dc5
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-build-provider/src/main/res/values/donottranslate-strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<resources>
+    <string name="app_notice">Baseline Profiles Integration Test App.</string>
+</resources>
diff --git a/benchmark/integration-tests/baselineprofiles-library-consumer/build.gradle b/benchmark/integration-tests/baselineprofiles-library-consumer/build.gradle
new file mode 100644
index 0000000..e314c41
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-consumer/build.gradle
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.consumer")
+}
+
+android {
+    namespace "androidx.benchmark.integration.baselineprofiles.library.consumer"
+}
+
+dependencies {
+    baselineprofiles(project(":benchmark:integration-tests:baselineprofiles-library-producer"))
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+}
+
+apply(from: "../baselineprofiles-test-utils/utils.gradle")
diff --git a/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7c52910
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<!--
+  ~ Copyright 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/expected-baseline-prof.txt b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/expected-baseline-prof.txt
new file mode 100644
index 0000000..29e1de4
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/expected-baseline-prof.txt
@@ -0,0 +1,172 @@
+HSPLandroidx/appcompat/widget/TintTypedArray;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/appcompat/widget/TintTypedArray;->measure(Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Z)Z
+HSPLandroidx/appcompat/widget/TintTypedArray;->solveLinearSystem(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;II)V
+HSPLandroidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity;-><init>()V
+HSPLandroidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity;->onCreate(Landroid/os/Bundle;)V
+HSPLandroidx/collection/ArrayMap$1;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayLinkedVariables;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->addError(Landroidx/constraintlayout/solver/LinearSystem;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->createRowLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->pivot(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->reset()V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromFinalVariable(Landroidx/constraintlayout/solver/SolverVariable;Z)V
+HSPLandroidx/constraintlayout/solver/ArrayRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/LinearSystem$ValuesRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;-><init>()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->acquireSolverVariable$enumunboxing$(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addCentering(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IFLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addConstraint(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addEquality(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addGreaterThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addLowerThan(Landroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;II)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->addRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createErrorVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createObjectVariable(Ljava/lang/Object;)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createRow()Landroidx/constraintlayout/solver/ArrayRow;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->createSlackVariable()Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/LinearSystem;->getObjectVariableValue(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;)I
+HSPLandroidx/constraintlayout/solver/LinearSystem;->increaseTableSize()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->optimize(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->releaseRows()V
+HSPLandroidx/constraintlayout/solver/LinearSystem;->reset()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;-><init>()V
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->acquire()Ljava/lang/Object;
+HSPLandroidx/constraintlayout/solver/Pools$SimplePool;->release(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;-><init>(Landroidx/constraintlayout/solver/PriorityGoalRow;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;-><init>(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->addToGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->getPivotCandidate([Z)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->removeGoal(Landroidx/constraintlayout/solver/SolverVariable;)V
+HSPLandroidx/constraintlayout/solver/PriorityGoalRow;->updateFromRow(Landroidx/constraintlayout/solver/ArrayRow;Z)V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;->ordinal(I)I
+HSPLandroidx/constraintlayout/solver/SolverVariable;-><init>(I)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->addToRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->removeFromRow(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->reset()V
+HSPLandroidx/constraintlayout/solver/SolverVariable;->updateReferencesWithNewDefinition(Landroidx/constraintlayout/solver/ArrayRow;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;-><init>(Landroidx/constraintlayout/solver/ArrayRow;Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->add(Landroidx/constraintlayout/solver/SolverVariable;FZ)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addToHashMap(Landroidx/constraintlayout/solver/SolverVariable;I)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->addVariable(ILandroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->clear()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->divideByAmount(F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->get(Landroidx/constraintlayout/solver/SolverVariable;)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getCurrentSize()I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariable(I)Landroidx/constraintlayout/solver/SolverVariable;
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->getVariableValue(I)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->indexOf(Landroidx/constraintlayout/solver/SolverVariable;)I
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->invert()V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->put(Landroidx/constraintlayout/solver/SolverVariable;F)V
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->remove(Landroidx/constraintlayout/solver/SolverVariable;Z)F
+HSPLandroidx/constraintlayout/solver/SolverVariableValues;->use(Landroidx/constraintlayout/solver/ArrayRow;Z)F
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;-><init>(ILjava/lang/String;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->connect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->getMargin()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->isConnected()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;->resetSolverVariable()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->addToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->applyConstraints$enumunboxing$(Landroidx/constraintlayout/solver/LinearSystem;ZZZZLandroidx/constraintlayout/solver/SolverVariable;Landroidx/constraintlayout/solver/SolverVariable;IZLandroidx/constraintlayout/solver/widgets/ConstraintAnchor;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;IIIIFZZZZIIIIFZ)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->createObjectVariables(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getAnchor(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;)Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getDimensionBehaviour$enumunboxing$(I)I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getHeight()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getWidth()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getX()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->getY()I
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->immediateConnect(Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;II)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isChainHead(I)Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInHorizontalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->isInVerticalChain()Z
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->reset()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHeight(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setHorizontalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setVerticalDimensionBehaviour$enumunboxing$(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->setWidth(I)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidget;->updateFromSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->addChildrenToSolver(Landroidx/constraintlayout/solver/LinearSystem;)V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->layout()V
+HSPLandroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;->resetSolverVariables(Landroidx/collection/ArrayMap$1;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;-><init>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;-><init>(Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><clinit>()V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;-><init>(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;-><clinit>()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->resolveLayoutDirection(I)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;->validate()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;-><init>(Landroidx/constraintlayout/widget/ConstraintLayout;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout$Measurer;->measure(Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;-><init>(Landroid/content/Context;Landroid/util/AttributeSet;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->addView(Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->applyConstraintsFromLayoutParams(ZLandroid/view/View;Landroidx/constraintlayout/solver/widgets/ConstraintWidget;Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;Landroid/util/SparseArray;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->checkLayoutParams(Landroid/view/ViewGroup$LayoutParams;)Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->dispatchDraw(Landroid/graphics/Canvas;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->generateLayoutParams(Landroid/util/AttributeSet;)Landroid/view/ViewGroup$LayoutParams;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getPaddingWidth()I
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->getViewWidget(Landroid/view/View;)Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->isRtl()Z
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onLayout(ZIIII)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onMeasure(II)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->onViewAdded(Landroid/view/View;)V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->requestLayout()V
+HSPLandroidx/constraintlayout/widget/ConstraintLayout;->updateHierarchy()Z
+HSPLandroidx/constraintlayout/widget/R$styleable;-><clinit>()V
+HSPLandroidx/core/app/CoreComponentFactory;-><init>()V
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateActivity(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Intent;)Landroid/app/Activity;
+HSPLandroidx/core/app/CoreComponentFactory;->instantiateApplication(Ljava/lang/ClassLoader;Ljava/lang/String;)Landroid/app/Application;
+HSPLandroidx/core/util/ObjectsCompat;-><clinit>()V
+Landroidx/appcompat/widget/TintTypedArray;
+Landroidx/benchmark/integration/baselineprofiles/library/buildprovider/EmptyActivity;
+Landroidx/collection/ArrayMap$1;
+Landroidx/constraintlayout/solver/ArrayLinkedVariables;
+Landroidx/constraintlayout/solver/ArrayRow$ArrayRowVariables;
+Landroidx/constraintlayout/solver/ArrayRow;
+Landroidx/constraintlayout/solver/LinearSystem$ValuesRow;
+Landroidx/constraintlayout/solver/LinearSystem;
+Landroidx/constraintlayout/solver/Pools$SimplePool;
+Landroidx/constraintlayout/solver/PriorityGoalRow$GoalVariableAccessor;
+Landroidx/constraintlayout/solver/PriorityGoalRow;
+Landroidx/constraintlayout/solver/SolverVariable$Type$EnumUnboxingSharedUtility;
+Landroidx/constraintlayout/solver/SolverVariable;
+Landroidx/constraintlayout/solver/SolverVariableValues;
+Landroidx/constraintlayout/solver/widgets/Barrier;
+Landroidx/constraintlayout/solver/widgets/ChainHead;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor$Type;
+Landroidx/constraintlayout/solver/widgets/ConstraintAnchor;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidget;
+Landroidx/constraintlayout/solver/widgets/ConstraintWidgetContainer;
+Landroidx/constraintlayout/solver/widgets/Guideline;
+Landroidx/constraintlayout/solver/widgets/Helper;
+Landroidx/constraintlayout/solver/widgets/HelperWidget;
+Landroidx/constraintlayout/solver/widgets/analyzer/BasicMeasure$Measure;
+Landroidx/constraintlayout/solver/widgets/analyzer/Dependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyGraph;
+Landroidx/constraintlayout/solver/widgets/analyzer/DependencyNode;
+Landroidx/constraintlayout/solver/widgets/analyzer/DimensionDependency;
+Landroidx/constraintlayout/solver/widgets/analyzer/HorizontalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/VerticalWidgetRun;
+Landroidx/constraintlayout/solver/widgets/analyzer/WidgetRun;
+Landroidx/constraintlayout/widget/ConstraintHelper;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams$Table;
+Landroidx/constraintlayout/widget/ConstraintLayout$LayoutParams;
+Landroidx/constraintlayout/widget/ConstraintLayout$Measurer;
+Landroidx/constraintlayout/widget/ConstraintLayout;
+Landroidx/constraintlayout/widget/Guideline;
+Landroidx/constraintlayout/widget/R$styleable;
+Landroidx/core/app/CoreComponentFactory;
+Landroidx/core/util/ObjectsCompat;
\ No newline at end of file
diff --git a/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/consumer/EmptyClass.kt b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/consumer/EmptyClass.kt
new file mode 100644
index 0000000..47a198a
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-consumer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/consumer/EmptyClass.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.benchmark.integration.baselineprofiles.library.consumer
+
+import android.util.Log
+
+object EmptyClass {
+
+    fun doSomething() {
+        Log.d("EmptyClass", "Done.")
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-library-producer/build.gradle b/benchmark/integration-tests/baselineprofiles-library-producer/build.gradle
new file mode 100644
index 0000000..c797473
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-producer/build.gradle
@@ -0,0 +1,60 @@
+import com.android.build.api.dsl.ManagedVirtualDevice
+
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.test")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.producer")
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    testOptions.managedDevices.devices {
+        pixel6Api31(ManagedVirtualDevice) {
+            device = "Pixel 6"
+            apiLevel = 31
+            systemImageSource = "aosp"
+        }
+    }
+    targetProjectPath = ":benchmark:integration-tests:baselineprofiles-library-build-provider"
+    namespace "androidx.benchmark.integration.baselineprofiles.library.producer"
+}
+
+dependencies {
+    implementation(project(":benchmark:benchmark-junit4"))
+    implementation(project(":benchmark:benchmark-macro-junit4"))
+    implementation(libs.testRules)
+    implementation(libs.testExtJunit)
+    implementation(libs.testCore)
+    implementation(libs.testRunner)
+    implementation(libs.testUiautomator)
+    implementation(libs.testExtTruth)
+}
+
+baselineProfilesProfileProducer {
+    managedDevices += "pixel6Api31"
+    useConnectedDevices = false
+}
+
+androidx {
+    disableDeviceTests = true
+}
diff --git a/benchmark/integration-tests/baselineprofiles-library-producer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-library-producer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bae036b
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-producer/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-library-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/producer/BaselineProfileTest.kt b/benchmark/integration-tests/baselineprofiles-library-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/producer/BaselineProfileTest.kt
new file mode 100644
index 0000000..1d5cdec
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-library-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/library/producer/BaselineProfileTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.library.producer
+
+import android.content.Intent
+import android.os.Build
+import androidx.benchmark.DeviceInfo
+import androidx.benchmark.macro.junit4.BaselineProfileRule
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+@SdkSuppress(minSdkVersion = 29)
+class BaselineProfileTest {
+
+    @get:Rule
+    val baselineRule = BaselineProfileRule()
+
+    @Test
+    fun startupBaselineProfile() {
+        assumeTrue(DeviceInfo.isRooted || Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+
+        // Collects the baseline profile
+        baselineRule.collectBaselineProfile(
+            packageName = PACKAGE_NAME,
+            profileBlock = {
+                startActivityAndWait(Intent(ACTION))
+                device.waitForIdle()
+            }
+        )
+    }
+
+    companion object {
+        private const val PACKAGE_NAME =
+            "androidx.benchmark.integration.baselineprofiles.library.buildprovider"
+        private const val ACTION =
+            "androidx.benchmark.integration.baselineprofiles.EMPTY_ACTIVITY"
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-producer/build.gradle b/benchmark/integration-tests/baselineprofiles-producer/build.gradle
new file mode 100644
index 0000000..c49546c
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-producer/build.gradle
@@ -0,0 +1,60 @@
+import com.android.build.api.dsl.ManagedVirtualDevice
+
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.test")
+    id("kotlin-android")
+    id("androidx.baselineprofiles.producer")
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 23
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    testOptions.managedDevices.devices {
+        pixel6Api31(ManagedVirtualDevice) {
+            device = "Pixel 6"
+            apiLevel = 31
+            systemImageSource = "aosp"
+        }
+    }
+    targetProjectPath = ":benchmark:integration-tests:baselineprofiles-consumer"
+    namespace "androidx.benchmark.integration.baselineprofiles.producer"
+}
+
+dependencies {
+    implementation(project(":benchmark:benchmark-junit4"))
+    implementation(project(":benchmark:benchmark-macro-junit4"))
+    implementation(libs.testRules)
+    implementation(libs.testExtJunit)
+    implementation(libs.testCore)
+    implementation(libs.testRunner)
+    implementation(libs.testUiautomator)
+    implementation(libs.testExtTruth)
+}
+
+baselineProfilesProfileProducer {
+    managedDevices += "pixel6Api31"
+    useConnectedDevices = false
+}
+
+androidx {
+    disableDeviceTests = true
+}
diff --git a/benchmark/integration-tests/baselineprofiles-producer/src/main/AndroidManifest.xml b/benchmark/integration-tests/baselineprofiles-producer/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..bae036b
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-producer/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest />
diff --git a/benchmark/integration-tests/baselineprofiles-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/producer/BaselineProfileTest.kt b/benchmark/integration-tests/baselineprofiles-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/producer/BaselineProfileTest.kt
new file mode 100644
index 0000000..3fbcfea
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-producer/src/main/java/androidx/benchmark/integration/baselineprofiles/producer/BaselineProfileTest.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.benchmark.integration.baselineprofiles.producer
+
+import android.content.Intent
+import android.os.Build
+import androidx.benchmark.DeviceInfo
+import androidx.benchmark.macro.junit4.BaselineProfileRule
+import androidx.test.filters.LargeTest
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeTrue
+import org.junit.Rule
+import org.junit.Test
+
+@LargeTest
+@SdkSuppress(minSdkVersion = 29)
+class BaselineProfileTest {
+
+    @get:Rule
+    val baselineRule = BaselineProfileRule()
+
+    @Test
+    fun startupBaselineProfile() {
+        assumeTrue(DeviceInfo.isRooted || Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
+
+        // Collects the baseline profile
+        baselineRule.collectBaselineProfile(
+            packageName = PACKAGE_NAME,
+            profileBlock = {
+                startActivityAndWait(Intent(ACTION))
+                device.waitForIdle()
+            }
+        )
+    }
+
+    companion object {
+        private const val PACKAGE_NAME =
+            "androidx.benchmark.integration.baselineprofiles.consumer"
+        private const val ACTION =
+            "androidx.benchmark.integration.baselineprofiles.consumer.EMPTY_ACTIVITY"
+    }
+}
diff --git a/benchmark/integration-tests/baselineprofiles-test-utils/utils.gradle b/benchmark/integration-tests/baselineprofiles-test-utils/utils.gradle
new file mode 100644
index 0000000..4a0a8dd
--- /dev/null
+++ b/benchmark/integration-tests/baselineprofiles-test-utils/utils.gradle
@@ -0,0 +1,26 @@
+// To trigger the baseline profile generation using the different modules the test will call
+// the base generation task `generateBaselineProfiles`. The `AssertEqualsAndCleanUpTask` asserts
+// that the final output is the expected one and if there are no failures cleans up the
+// generated baseline-prof.txt.
+@CacheableTask
+abstract class AssertEqualsAndCleanUpTask extends DefaultTask {
+    @InputFile
+    @PathSensitive(PathSensitivity.NONE)
+    abstract RegularFileProperty getExpectedFile()
+
+    @InputFile
+    @PathSensitive(PathSensitivity.NONE)
+    abstract RegularFileProperty getActualFile()
+
+    @TaskAction
+    void exec() {
+        assert getExpectedFile().get().asFile.text == getActualFile().get().asFile.text
+
+        // This deletes the actual file since it's a test artifact
+        getActualFile().get().asFile.delete()
+    }
+}
+tasks.register("testBaselineProfilesGeneration", AssertEqualsAndCleanUpTask).configure {
+    it.expectedFile.set(project.layout.projectDirectory.file("src/main/expected-baseline-prof.txt"))
+    it.actualFile.set(tasks.named("generateBaselineProfiles").flatMap { it.baselineProfileFile })
+}
diff --git a/camera/camera-camera2-pipe-integration/OWNERS b/camera/camera-camera2-pipe-integration/OWNERS
index 871060e..c445688 100644
--- a/camera/camera-camera2-pipe-integration/OWNERS
+++ b/camera/camera-camera2-pipe-integration/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 575599
 codelogic@google.com
 sushilnath@google.com
 lnishan@google.com
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
index edf21f9..40b5167 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/ApiCompat.kt
@@ -35,6 +35,7 @@
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresApi
 import androidx.annotation.RequiresPermission
+import androidx.camera.camera2.pipe.CameraMetadata
 import java.util.concurrent.Executor
 
 @RequiresApi(Build.VERSION_CODES.M)
@@ -322,6 +323,12 @@
 
     @JvmStatic
     @DoNotInline
+    fun getAvailableStreamUseCases(cameraMetadata: CameraMetadata): LongArray? {
+        return cameraMetadata[CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES]
+    }
+
+    @JvmStatic
+    @DoNotInline
     fun getStreamUseCase(outputConfig: OutputConfiguration): Long {
         return outputConfig.streamUseCase
     }
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
index 56c25a7..f9767ba 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactory.kt
@@ -24,6 +24,7 @@
 import android.view.Surface
 import androidx.annotation.RequiresApi
 import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
 import androidx.camera.camera2.pipe.StreamId
 import androidx.camera.camera2.pipe.compat.OutputConfigurationWrapper.Companion.SURFACE_GROUP_ID_NONE
 import androidx.camera.camera2.pipe.config.Camera2ControllerScope
@@ -180,14 +181,21 @@
 constructor(
     private val threads: Threads,
     private val streamGraph: StreamGraphImpl,
-    private val graphConfig: CameraGraph.Config
+    private val graphConfig: CameraGraph.Config,
+    private val camera2MetadataProvider: Camera2MetadataProvider
 ) : CaptureSessionFactory {
     override fun create(
         cameraDevice: CameraDeviceWrapper,
         surfaces: Map<StreamId, Surface>,
         captureSessionState: CaptureSessionState
     ): Map<StreamId, OutputConfigurationWrapper> {
-        val outputs = buildOutputConfigurations(graphConfig, streamGraph, surfaces)
+        val outputs = buildOutputConfigurations(
+            graphConfig,
+            streamGraph,
+            surfaces,
+            camera2MetadataProvider,
+            cameraDevice.cameraId
+        )
         if (outputs.all.isEmpty()) {
             Log.warn { "Failed to create OutputConfigurations for $graphConfig" }
             return emptyMap()
@@ -224,7 +232,8 @@
 constructor(
     private val threads: Threads,
     private val graphConfig: CameraGraph.Config,
-    private val streamGraph: StreamGraphImpl
+    private val streamGraph: StreamGraphImpl,
+    private val camera2MetadataProvider: Camera2MetadataProvider
 ) : CaptureSessionFactory {
     override fun create(
         cameraDevice: CameraDeviceWrapper,
@@ -238,7 +247,13 @@
                 CameraGraph.OperatingMode.HIGH_SPEED -> SessionConfigData.SESSION_TYPE_HIGH_SPEED
             }
 
-        val outputs = buildOutputConfigurations(graphConfig, streamGraph, surfaces)
+        val outputs = buildOutputConfigurations(
+            graphConfig,
+            streamGraph,
+            surfaces,
+            camera2MetadataProvider,
+            cameraDevice.cameraId
+        )
         if (outputs.all.isEmpty()) {
             Log.warn { "Failed to create OutputConfigurations for $graphConfig" }
             return emptyMap()
@@ -277,7 +292,9 @@
 internal fun buildOutputConfigurations(
     graphConfig: CameraGraph.Config,
     streamGraph: StreamGraphImpl,
-    surfaces: Map<StreamId, Surface>
+    surfaces: Map<StreamId, Surface>,
+    camera2MetadataProvider: Camera2MetadataProvider,
+    cameraId: CameraId
 ): OutputConfigurations {
     val allOutputs = arrayListOf<OutputConfigurationWrapper>()
     val deferredOutputs = mutableMapOf<StreamId, OutputConfigurationWrapper>()
@@ -303,23 +320,24 @@
         }
 
         if (outputConfig.deferrable && outputSurfaces.size != outputConfig.streams.size) {
-            val output =
-                AndroidOutputConfiguration.create(
-                    null,
-                    size = outputConfig.size,
-                    outputType = outputConfig.deferredOutputType!!,
-                    mirrorMode = outputConfig.mirrorMode,
-                    timestampBase = outputConfig.timestampBase,
-                    dynamicRangeProfile = outputConfig.dynamicRangeProfile,
-                    streamUseCase = outputConfig.streamUseCase,
-                    surfaceSharing = outputConfig.surfaceSharing,
-                    surfaceGroupId = outputConfig.groupNumber ?: SURFACE_GROUP_ID_NONE,
-                    physicalCameraId =
-                        if (outputConfig.camera != graphConfig.camera) {
-                            outputConfig.camera
-                        } else {
-                            null
-                        })
+            val output = AndroidOutputConfiguration.create(
+                null,
+                size = outputConfig.size,
+                outputType = outputConfig.deferredOutputType!!,
+                mirrorMode = outputConfig.mirrorMode,
+                timestampBase = outputConfig.timestampBase,
+                dynamicRangeProfile = outputConfig.dynamicRangeProfile,
+                streamUseCase = outputConfig.streamUseCase,
+                surfaceSharing = outputConfig.surfaceSharing,
+                surfaceGroupId = outputConfig.groupNumber ?: SURFACE_GROUP_ID_NONE,
+                physicalCameraId = if (outputConfig.camera != graphConfig.camera) {
+                    outputConfig.camera
+                } else {
+                    null
+                },
+                cameraId = cameraId,
+                camera2MetadataProvider = camera2MetadataProvider
+            )
             if (output == null) {
                 Log.warn { "Failed to create AndroidOutputConfiguration for $outputConfig" }
                 continue
@@ -337,22 +355,23 @@
             "Surfaces are not yet available for $outputConfig!" +
                 " Missing surfaces for $missingStreams!"
         }
-        val output =
-            AndroidOutputConfiguration.create(
-                outputSurfaces.first(),
-                mirrorMode = outputConfig.mirrorMode,
-                timestampBase = outputConfig.timestampBase,
-                dynamicRangeProfile = outputConfig.dynamicRangeProfile,
-                streamUseCase = outputConfig.streamUseCase,
-                size = outputConfig.size,
-                surfaceSharing = outputConfig.surfaceSharing,
-                surfaceGroupId = outputConfig.groupNumber ?: SURFACE_GROUP_ID_NONE,
-                physicalCameraId =
-                    if (outputConfig.camera != graphConfig.camera) {
-                        outputConfig.camera
-                    } else {
-                        null
-                    })
+        val output = AndroidOutputConfiguration.create(
+            outputSurfaces.first(),
+            mirrorMode = outputConfig.mirrorMode,
+            timestampBase = outputConfig.timestampBase,
+            dynamicRangeProfile = outputConfig.dynamicRangeProfile,
+            streamUseCase = outputConfig.streamUseCase,
+            size = outputConfig.size,
+            surfaceSharing = outputConfig.surfaceSharing,
+            surfaceGroupId = outputConfig.groupNumber ?: SURFACE_GROUP_ID_NONE,
+            physicalCameraId = if (outputConfig.camera != graphConfig.camera) {
+                outputConfig.camera
+            } else {
+                null
+            },
+            cameraId = cameraId,
+            camera2MetadataProvider = camera2MetadataProvider
+        )
         if (output == null) {
             Log.warn { "Failed to create AndroidOutputConfiguration for $outputConfig" }
             continue
diff --git a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
index 550563a..d5b60d1 100644
--- a/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
+++ b/camera/camera-camera2-pipe/src/main/java/androidx/camera/camera2/pipe/compat/Configuration.kt
@@ -142,7 +142,9 @@
             size: Size? = null,
             surfaceSharing: Boolean = false,
             surfaceGroupId: Int = SURFACE_GROUP_ID_NONE,
-            physicalCameraId: CameraId? = null
+            physicalCameraId: CameraId? = null,
+            cameraId: CameraId? = null,
+            camera2MetadataProvider: Camera2MetadataProvider? = null,
         ): OutputConfigurationWrapper? {
             check(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
 
@@ -172,7 +174,8 @@
                 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
                     throw IllegalStateException(
                         "Deferred OutputConfigurations are not supported on API " +
-                            "${Build.VERSION.SDK_INT} (requires API ${Build.VERSION_CODES.O})")
+                            "${Build.VERSION.SDK_INT} (requires API ${Build.VERSION_CODES.O})"
+                    )
                 }
 
                 check(size != null) {
@@ -241,9 +244,14 @@
                 }
             }
 
-            if (streamUseCase != null) {
+            if (streamUseCase != null && cameraId != null && camera2MetadataProvider != null) {
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
-                    Api33Compat.setStreamUseCase(configuration, streamUseCase.value)
+                    val cameraMetadata = camera2MetadataProvider.awaitCameraMetadata(cameraId)
+                    val availableStreamUseCases =
+                        Api33Compat.getAvailableStreamUseCases(cameraMetadata)
+                    if (availableStreamUseCases?.contains(streamUseCase.value) == true) {
+                        Api33Compat.setStreamUseCase(configuration, streamUseCase.value)
+                    }
                 }
             }
 
@@ -256,7 +264,8 @@
                 } else {
                     1
                 },
-                physicalCameraId)
+                physicalCameraId
+            )
         }
 
         private fun OutputConfiguration.enableSurfaceSharingCompat() {
diff --git a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
index c418fe9..c2bcc17 100644
--- a/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
+++ b/camera/camera-camera2-pipe/src/test/java/androidx/camera/camera2/pipe/compat/CaptureSessionFactoryTest.kt
@@ -23,6 +23,8 @@
 import android.util.Size
 import android.view.Surface
 import androidx.camera.camera2.pipe.CameraGraph
+import androidx.camera.camera2.pipe.CameraId
+import androidx.camera.camera2.pipe.CameraMetadata
 import androidx.camera.camera2.pipe.CameraPipe
 import androidx.camera.camera2.pipe.CameraStream
 import androidx.camera.camera2.pipe.CameraSurfaceManager
@@ -104,22 +106,25 @@
         val pendingOutputs =
             sessionFactory.create(
                 AndroidCameraDevice(
-                    testCamera.metadata, testCamera.cameraDevice, testCamera.cameraId),
+                    testCamera.metadata, testCamera.cameraDevice, testCamera.cameraId
+                ),
                 mapOf(stream1.id to surface),
                 captureSessionState =
-                    CaptureSessionState(
-                        FakeGraphProcessor(),
-                        sessionFactory,
-                        object : Camera2CaptureSequenceProcessorFactory {
-                            override fun create(
-                                session: CameraCaptureSessionWrapper,
-                                surfaceMap: Map<StreamId, Surface>
-                            ): CaptureSequenceProcessor<Request, FakeCaptureSequence> =
-                                FakeCaptureSequenceProcessor()
-                        },
-                        CameraSurfaceManager(),
-                        SystemTimeSource(),
-                        this))
+                CaptureSessionState(
+                    FakeGraphProcessor(),
+                    sessionFactory,
+                    object : Camera2CaptureSequenceProcessorFactory {
+                        override fun create(
+                            session: CameraCaptureSessionWrapper,
+                            surfaceMap: Map<StreamId, Surface>
+                        ): CaptureSequenceProcessor<Request, FakeCaptureSequence> =
+                            FakeCaptureSequenceProcessor()
+                    },
+                    CameraSurfaceManager(),
+                    SystemTimeSource(),
+                    this
+                )
+            )
 
         assertThat(pendingOutputs).isNotNull()
         assertThat(pendingOutputs).isEmpty()
@@ -132,10 +137,12 @@
 @Camera2ControllerScope
 @Component(
     modules =
-        [
-            FakeCameraGraphModule::class,
-            FakeCameraPipeModule::class,
-            Camera2CaptureSessionsModule::class])
+    [
+        FakeCameraGraphModule::class,
+        FakeCameraPipeModule::class,
+        Camera2CaptureSessionsModule::class,
+        FakeCamera2Module::class]
+)
 internal interface Camera2CaptureSessionTestComponent {
     fun graphConfig(): CameraGraph.Config
     fun sessionFactory(): CaptureSessionFactory
@@ -148,9 +155,12 @@
     private val context: Context,
     private val fakeCamera: RobolectricCameras.FakeCamera
 ) {
-    @Provides fun provideFakeCamera() = fakeCamera
+    @Provides
+    fun provideFakeCamera() = fakeCamera
 
-    @Provides @Singleton fun provideFakeCameraPipeConfig() = CameraPipe.Config(context)
+    @Provides
+    @Singleton
+    fun provideFakeCameraPipeConfig() = CameraPipe.Config(context)
 }
 
 @Module(includes = [SharedCameraGraphModules::class])
@@ -169,3 +179,20 @@
         )
     }
 }
+
+@Module
+class FakeCamera2Module {
+    @Provides
+    @Singleton
+    internal fun provideFakeCamera2MetadataProvider(
+        fakeCamera: RobolectricCameras.FakeCamera
+    ): Camera2MetadataProvider = object : Camera2MetadataProvider {
+        override suspend fun getCameraMetadata(cameraId: CameraId): CameraMetadata {
+            return fakeCamera.metadata
+        }
+
+        override fun awaitCameraMetadata(cameraId: CameraId): CameraMetadata {
+            return fakeCamera.metadata
+        }
+    }
+}
\ No newline at end of file
diff --git a/camera/integration-tests/avsynctestapp/build.gradle b/camera/integration-tests/avsynctestapp/build.gradle
index 8612bb7..0f4683f 100644
--- a/camera/integration-tests/avsynctestapp/build.gradle
+++ b/camera/integration-tests/avsynctestapp/build.gradle
@@ -53,6 +53,7 @@
     implementation("androidx.compose.ui:ui:$compose_version")
     implementation("androidx.compose.ui:ui-tooling-preview:$compose_version")
     implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.4.1")
+    implementation(project(":lifecycle:lifecycle-viewmodel"))
 
     compileOnly(libs.kotlinCompiler)
 
@@ -61,6 +62,7 @@
     testImplementation(libs.junit)
     testImplementation(libs.truth)
     androidTestImplementation(project(":camera:camera-testing"))
+    androidTestImplementation(project(":lifecycle:lifecycle-viewmodel"))
     androidTestImplementation(libs.kotlinCoroutinesTest)
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testRules)
diff --git a/camera/integration-tests/avsynctestapp/src/androidTest/java/androidx/camera/integration/avsync/SignalGeneratorViewModelTest.kt b/camera/integration-tests/avsynctestapp/src/androidTest/java/androidx/camera/integration/avsync/SignalGeneratorViewModelTest.kt
index 36b13db..88c8b26 100644
--- a/camera/integration-tests/avsynctestapp/src/androidTest/java/androidx/camera/integration/avsync/SignalGeneratorViewModelTest.kt
+++ b/camera/integration-tests/avsynctestapp/src/androidTest/java/androidx/camera/integration/avsync/SignalGeneratorViewModelTest.kt
@@ -66,12 +66,12 @@
     private lateinit var viewModel: SignalGeneratorViewModel
     private lateinit var lifecycleOwner: FakeLifecycleOwner
     private val fakeViewModelStoreOwner = object : ViewModelStoreOwner {
-        private val viewModelStore = ViewModelStore()
+        private val vmStore = ViewModelStore()
 
-        override fun getViewModelStore() = viewModelStore
+        override val viewModelStore = vmStore
 
         fun clear() {
-            viewModelStore.clear()
+            vmStore.clear()
         }
     }
 
diff --git a/compose/OWNERS b/compose/OWNERS
index 578f153..d441e85 100644
--- a/compose/OWNERS
+++ b/compose/OWNERS
@@ -2,3 +2,6 @@
 chuckj@google.com
 jsproch@google.com
 lelandr@google.com
+aelias@google.com
+malkov@google.com
+clarabayarri@google.com
diff --git a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
index df702a8..a62fdb5 100644
--- a/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
+++ b/compose/foundation/foundation/src/androidMain/kotlin/androidx/compose/foundation/SystemGestureExclusion.kt
@@ -26,7 +26,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.graphics.toAndroidRect
 import androidx.compose.ui.layout.LayoutCoordinates
 import androidx.compose.ui.layout.OnGloballyPositionedModifier
 import androidx.compose.ui.layout.boundsInRoot
@@ -97,7 +96,13 @@
 
     override fun onGloballyPositioned(coordinates: LayoutCoordinates) {
         val newRect = if (exclusion == null) {
-            coordinates.boundsInRoot().toAndroidRect()
+            val boundsInRoot = coordinates.boundsInRoot()
+            android.graphics.Rect(
+                boundsInRoot.left.roundToInt(),
+                boundsInRoot.top.roundToInt(),
+                boundsInRoot.right.roundToInt(),
+                boundsInRoot.bottom.roundToInt()
+            )
         } else {
             calcBounds(coordinates, exclusion.invoke(coordinates))
         }
diff --git a/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/RippleHostView.android.kt b/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/RippleHostView.android.kt
index ae926e8..c969613 100644
--- a/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/RippleHostView.android.kt
+++ b/compose/material/material-ripple/src/androidMain/kotlin/androidx/compose/material/ripple/RippleHostView.android.kt
@@ -29,9 +29,7 @@
 import androidx.annotation.RequiresApi
 import androidx.compose.foundation.interaction.PressInteraction
 import androidx.compose.ui.geometry.Size
-import androidx.compose.ui.geometry.toRect
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toAndroidRect
 import androidx.compose.ui.graphics.toArgb
 import java.lang.reflect.Method
 
@@ -179,7 +177,12 @@
         // another invalidation, etc.
         ripple.trySetRadius(radius)
         ripple.setColor(color, alpha)
-        val newBounds = size.toRect().toAndroidRect()
+        val newBounds = Rect(
+            0,
+            0,
+            size.width.toInt(),
+            size.height.toInt()
+        )
         // Drawing the background causes the view to update the bounds of the drawable
         // based on the view's bounds, so we need to adjust the view itself to match the
         // canvas' bounds.
diff --git a/compose/ui/ui-graphics/api/current.txt b/compose/ui/ui-graphics/api/current.txt
index fd2b2c0..358b6e6 100644
--- a/compose/ui/ui-graphics/api/current.txt
+++ b/compose/ui/ui-graphics/api/current.txt
@@ -734,7 +734,7 @@
   }
 
   public final class RectHelper_androidKt {
-    method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
+    method @Deprecated public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
     method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.unit.IntRect);
     method public static android.graphics.RectF toAndroidRectF(androidx.compose.ui.geometry.Rect);
     method public static androidx.compose.ui.unit.IntRect toComposeIntRect(android.graphics.Rect);
diff --git a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
index b9e2ae2..39ec0533 100644
--- a/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-graphics/api/public_plus_experimental_current.txt
@@ -737,7 +737,7 @@
   }
 
   public final class RectHelper_androidKt {
-    method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
+    method @Deprecated public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
     method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.unit.IntRect);
     method public static android.graphics.RectF toAndroidRectF(androidx.compose.ui.geometry.Rect);
     method public static androidx.compose.ui.unit.IntRect toComposeIntRect(android.graphics.Rect);
diff --git a/compose/ui/ui-graphics/api/restricted_current.txt b/compose/ui/ui-graphics/api/restricted_current.txt
index c59dbea..5dbda20 100644
--- a/compose/ui/ui-graphics/api/restricted_current.txt
+++ b/compose/ui/ui-graphics/api/restricted_current.txt
@@ -766,7 +766,7 @@
   }
 
   public final class RectHelper_androidKt {
-    method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
+    method @Deprecated public static android.graphics.Rect toAndroidRect(androidx.compose.ui.geometry.Rect);
     method public static android.graphics.Rect toAndroidRect(androidx.compose.ui.unit.IntRect);
     method public static android.graphics.RectF toAndroidRectF(androidx.compose.ui.geometry.Rect);
     method public static androidx.compose.ui.unit.IntRect toComposeIntRect(android.graphics.Rect);
diff --git a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/RectHelperTest.kt b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/RectHelperTest.kt
index 248e171..8c20469 100644
--- a/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/RectHelperTest.kt
+++ b/compose/ui/ui-graphics/src/androidAndroidTest/kotlin/androidx/compose/ui/graphics/RectHelperTest.kt
@@ -28,6 +28,7 @@
 @RunWith(AndroidJUnit4::class)
 class RectHelperTest {
 
+    @Suppress("DEPRECATION")
     @Test
     fun rectToAndroidRectTruncates() {
         assertEquals(
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
index 5e79774..0907e2c 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/AndroidPath.android.kt
@@ -133,12 +133,12 @@
 
     override fun addRect(rect: Rect) {
         check(_rectIsValid(rect))
-        rectF.set(rect.toAndroidRectF())
+        rectF.set(rect.left, rect.top, rect.right, rect.bottom)
         internalPath.addRect(rectF, android.graphics.Path.Direction.CCW)
     }
 
     override fun addOval(oval: Rect) {
-        rectF.set(oval.toAndroidRect())
+        rectF.set(oval.left, oval.top, oval.right, oval.bottom)
         internalPath.addOval(rectF, android.graphics.Path.Direction.CCW)
     }
 
@@ -148,7 +148,7 @@
 
     override fun addArc(oval: Rect, startAngleDegrees: Float, sweepAngleDegrees: Float) {
         check(_rectIsValid(oval))
-        rectF.set(oval.toAndroidRect())
+        rectF.set(oval.left, oval.top, oval.right, oval.bottom)
         internalPath.addArc(rectF, startAngleDegrees, sweepAngleDegrees)
     }
 
diff --git a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/RectHelper.android.kt b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/RectHelper.android.kt
index c926c3c..9537090 100644
--- a/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/RectHelper.android.kt
+++ b/compose/ui/ui-graphics/src/androidMain/kotlin/androidx/compose/ui/graphics/RectHelper.android.kt
@@ -22,6 +22,14 @@
  * Creates a new instance of [android.graphics.Rect] with the same bounds
  * specified in the given [Rect]
  */
+@Deprecated(
+    "Converting Rect to android.graphics.Rect is lossy, and requires rounding. The " +
+        "behavior of toAndroidRect() truncates to an integral Rect, but you should choose the " +
+        "method of rounding most suitable for your use case.",
+    replaceWith = ReplaceWith(
+        "android.graphics.Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())"
+    )
+)
 fun Rect.toAndroidRect(): android.graphics.Rect {
     return android.graphics.Rect(
         left.toInt(),
diff --git a/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt b/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
index 4d3f223..850087e 100644
--- a/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-test-junit4/api/public_plus_experimental_current.txt
@@ -32,6 +32,10 @@
 
   public final class ComposeUiTestKt {
     method @androidx.compose.ui.test.ExperimentalTestApi public static void runComposeUiTest(optional kotlin.coroutines.CoroutineContext effectContext, kotlin.jvm.functions.Function1<? super androidx.compose.ui.test.ComposeUiTest,? extends kotlin.Unit> block);
+    method @androidx.compose.ui.test.ExperimentalTestApi public static void waitUntilAtLeastOneExists(androidx.compose.ui.test.ComposeUiTest, androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public static void waitUntilDoesNotExist(androidx.compose.ui.test.ComposeUiTest, androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public static void waitUntilExactlyOneExists(androidx.compose.ui.test.ComposeUiTest, androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public static void waitUntilNodeCount(androidx.compose.ui.test.ComposeUiTest, androidx.compose.ui.test.SemanticsMatcher matcher, int count, optional long timeoutMillis);
   }
 
   public final class ComposeUiTest_androidKt {
@@ -70,6 +74,10 @@
     method public void unregisterIdlingResource(androidx.compose.ui.test.IdlingResource idlingResource);
     method public void waitForIdle();
     method public void waitUntil(long timeoutMillis, kotlin.jvm.functions.Function0<java.lang.Boolean> condition);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher matcher, long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher matcher, long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher matcher, long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher matcher, int count, long timeoutMillis);
     property public final A activity;
     property public final R activityRule;
     property public androidx.compose.ui.unit.Density density;
@@ -115,6 +123,10 @@
     method public void unregisterIdlingResource(androidx.compose.ui.test.IdlingResource idlingResource);
     method public void waitForIdle();
     method public void waitUntil(optional long timeoutMillis, kotlin.jvm.functions.Function0<java.lang.Boolean> condition);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher matcher, optional long timeoutMillis);
+    method @androidx.compose.ui.test.ExperimentalTestApi public void waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher matcher, int count, optional long timeoutMillis);
     property public abstract androidx.compose.ui.unit.Density density;
     property public abstract androidx.compose.ui.test.MainTestClock mainClock;
   }
diff --git a/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/ComposeTestRuleWaitUntilTest.kt b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/ComposeTestRuleWaitUntilTest.kt
new file mode 100644
index 0000000..3652cf4
--- /dev/null
+++ b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/ComposeTestRuleWaitUntilTest.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.test.junit4
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.expectError
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ComposeTimeoutException
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.hasTestTag
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalTestApi::class)
+class ComposeTestRuleWaitUntilTest {
+
+    @get:Rule
+    val rule = createComposeRule()
+
+    companion object {
+        private const val TestTag = "TestTag"
+        private const val Timeout = 500L
+    }
+
+    @Composable
+    private fun TaggedBox() = Box(
+        Modifier
+            .size(10.dp, 10.dp)
+            .testTag(TestTag)
+    )
+
+    @Test
+    fun waitUntilNodeCount_succeedsWhen_nodeCountCorrect() {
+        rule.setContent {
+            TaggedBox()
+            TaggedBox()
+            TaggedBox()
+        }
+
+        rule.waitUntilNodeCount(hasTestTag(TestTag), 3, Timeout)
+    }
+
+    @Test
+    fun waitUntilNodeCount_throwsWhen_nodeCountIncorrect() {
+        rule.setContent {
+            TaggedBox()
+            TaggedBox()
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            rule.waitUntilNodeCount(hasTestTag(TestTag), 2, Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilAtLeastOneExists_succeedsWhen_nodesExist() {
+        rule.setContent {
+            TaggedBox()
+            TaggedBox()
+        }
+
+        rule.waitUntilAtLeastOneExists(hasTestTag(TestTag))
+    }
+
+    @Test
+    fun waitUntilAtLeastOneExists_throwsWhen_nodesDoNotExist() {
+        rule.setContent {
+            Box(Modifier.size(10.dp))
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            rule.waitUntilAtLeastOneExists(hasTestTag(TestTag), Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilExactlyOneExists_succeedsWhen_oneNodeExists() {
+        rule.setContent {
+            TaggedBox()
+        }
+
+        rule.waitUntilExactlyOneExists(hasTestTag(TestTag))
+    }
+
+    @Test
+    fun waitUntilExactlyOneExists_throwsWhen_twoNodesExist() {
+        rule.setContent {
+            TaggedBox()
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            rule.waitUntilExactlyOneExists(hasTestTag(TestTag), Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilDoesNotExists_succeedsWhen_nodeDoesNotExist() {
+        rule.setContent {
+            Box(Modifier.size(10.dp))
+        }
+
+        rule.waitUntilDoesNotExist(hasTestTag(TestTag), timeoutMillis = Timeout)
+    }
+
+    @Test
+    fun waitUntilDoesNotExists_throwsWhen_nodeExistsUntilTimeout() {
+        rule.setContent {
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            rule.waitUntilDoesNotExist(hasTestTag(TestTag), timeoutMillis = Timeout)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/WaitUntilNodeCountTest.kt b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/WaitUntilNodeCountTest.kt
new file mode 100644
index 0000000..9fc70a6
--- /dev/null
+++ b/compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/WaitUntilNodeCountTest.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.test.junit4
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.testutils.expectError
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.testTag
+import androidx.compose.ui.test.ComposeTimeoutException
+import androidx.compose.ui.test.ExperimentalTestApi
+import androidx.compose.ui.test.hasTestTag
+import androidx.compose.ui.test.runComposeUiTest
+import androidx.compose.ui.test.waitUntilAtLeastOneExists
+import androidx.compose.ui.test.waitUntilDoesNotExist
+import androidx.compose.ui.test.waitUntilExactlyOneExists
+import androidx.compose.ui.test.waitUntilNodeCount
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalTestApi::class)
+class WaitUntilNodeCountTest {
+    companion object {
+        private const val TestTag = "TestTag"
+        private const val Timeout = 500L
+    }
+
+    @Composable
+    private fun TaggedBox() = Box(
+        Modifier
+            .size(10.dp, 10.dp)
+            .testTag(TestTag)
+    )
+
+    @Test
+    fun waitUntilNodeCount_succeedsWhen_nodeCountCorrect() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+            TaggedBox()
+            TaggedBox()
+        }
+
+        waitUntilNodeCount(hasTestTag(TestTag), 3, Timeout)
+    }
+
+    @Test
+    fun waitUntilNodeCount_throwsWhen_nodeCountIncorrect() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+            TaggedBox()
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            waitUntilNodeCount(hasTestTag(TestTag), 2, Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilAtLeastOneExists_succeedsWhen_nodesExist() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+            TaggedBox()
+        }
+
+        waitUntilAtLeastOneExists(hasTestTag(TestTag))
+    }
+
+    @Test
+    fun waitUntilAtLeastOneExists_throwsWhen_nodesDoNotExist() = runComposeUiTest {
+        setContent {
+            Box(Modifier.size(10.dp))
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            waitUntilAtLeastOneExists(hasTestTag(TestTag), Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilExactlyOneExists_succeedsWhen_oneNodeExists() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+        }
+
+        waitUntilExactlyOneExists(hasTestTag(TestTag))
+    }
+
+    @Test
+    fun waitUntilExactlyOneExists_throwsWhen_twoNodesExist() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            waitUntilExactlyOneExists(hasTestTag(TestTag), Timeout)
+        }
+    }
+
+    @Test
+    fun waitUntilDoesNotExists_succeedsWhen_nodeDoesNotExist() = runComposeUiTest {
+        setContent {
+            Box(Modifier.size(10.dp))
+        }
+
+        waitUntilDoesNotExist(hasTestTag(TestTag), timeoutMillis = Timeout)
+    }
+
+    @Test
+    fun waitUntilDoesNotExists_throwsWhen_nodeExistsUntilTimeout() = runComposeUiTest {
+        setContent {
+            TaggedBox()
+        }
+
+        expectError<ComposeTimeoutException>(
+            expectedMessage = "Condition still not satisfied after $Timeout ms"
+        ) {
+            waitUntilDoesNotExist(hasTestTag(TestTag), timeoutMillis = Timeout)
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
index ec2ea21..626ca1e3 100644
--- a/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
+++ b/compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule.android.kt
@@ -25,6 +25,10 @@
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.SemanticsNodeInteraction
 import androidx.compose.ui.test.SemanticsNodeInteractionCollection
+import androidx.compose.ui.test.waitUntilAtLeastOneExists
+import androidx.compose.ui.test.waitUntilDoesNotExist
+import androidx.compose.ui.test.waitUntilExactlyOneExists
+import androidx.compose.ui.test.waitUntilNodeCount
 import androidx.compose.ui.unit.Density
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import kotlin.coroutines.CoroutineContext
@@ -301,6 +305,22 @@
     override fun waitUntil(timeoutMillis: Long, condition: () -> Boolean) =
         composeTest.waitUntil(timeoutMillis, condition)
 
+    @ExperimentalTestApi
+    override fun waitUntilNodeCount(matcher: SemanticsMatcher, count: Int, timeoutMillis: Long) =
+        composeTest.waitUntilNodeCount(matcher, count, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilAtLeastOneExists(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilAtLeastOneExists(matcher, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilExactlyOneExists(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilExactlyOneExists(matcher, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilDoesNotExist(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilDoesNotExist(matcher, timeoutMillis)
+
     override fun registerIdlingResource(idlingResource: IdlingResource) =
         composeTest.registerIdlingResource(idlingResource)
 
diff --git a/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/ComposeUiTest.kt b/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/ComposeUiTest.kt
index e7900ea..3414dab 100644
--- a/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/ComposeUiTest.kt
+++ b/compose/ui/ui-test-junit4/src/commonMain/kotlin/androidx/compose/ui/test/ComposeUiTest.kt
@@ -161,8 +161,8 @@
      * @param condition Condition that must be satisfied in order for this method to successfully
      * finish.
      *
-     * @throws ComposeTimeoutException If the condition is not satisfied after [timeoutMillis]
-     * (in wall clock time).
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If the condition is not satisfied
+     * after [timeoutMillis] (in wall clock time).
      */
     fun waitUntil(timeoutMillis: Long = 1_000, condition: () -> Boolean)
 
@@ -186,4 +186,86 @@
     fun setContent(composable: @Composable () -> Unit)
 }
 
+/**
+ * Blocks until the number of nodes matching the given [matcher] is equal to the given [count].
+ *
+ * @see ComposeUiTest.waitUntil
+ *
+ * @param matcher The matcher that will be used to filter nodes.
+ * @param count The number of nodes that are expected to
+ * @param timeoutMillis The time after which this method throws an exception if the number of nodes
+ * that match the [matcher] is not [count]. This observes wall clock time, not frame time.
+ *
+ * @throws androidx.compose.ui.test.ComposeTimeoutException If the number of nodes that match the
+ * [matcher] is not [count] after [timeoutMillis] (in wall clock time).
+ */
+@ExperimentalTestApi
+fun ComposeUiTest.waitUntilNodeCount(
+    matcher: SemanticsMatcher,
+    count: Int,
+    timeoutMillis: Long = 1_000L
+) {
+    waitUntil(timeoutMillis) {
+        onAllNodes(matcher).fetchSemanticsNodes().size == count
+    }
+}
+
+/**
+ * Blocks until at least one node matches the given [matcher].
+ *
+ * @see ComposeUiTest.waitUntil
+ *
+ * @param matcher The matcher that will be used to filter nodes.
+ * @param timeoutMillis The time after which this method throws an exception if no nodes match the
+ * given [matcher]. This observes wall clock time, not frame time.
+ *
+ * @throws androidx.compose.ui.test.ComposeTimeoutException If no nodes match the given [matcher]
+ * after [timeoutMillis] (in wall clock time).
+ */
+@ExperimentalTestApi
+fun ComposeUiTest.waitUntilAtLeastOneExists(
+    matcher: SemanticsMatcher,
+    timeoutMillis: Long = 1_000L
+) {
+    waitUntil(timeoutMillis) {
+        onAllNodes(matcher).fetchSemanticsNodes().isNotEmpty()
+    }
+}
+
+/**
+ * Blocks until exactly one node matches the given [matcher].
+ *
+ * @see ComposeUiTest.waitUntil
+ *
+ * @param matcher The matcher that will be used to filter nodes.
+ * @param timeoutMillis The time after which this method throws an exception if exactly one node
+ * does not match the given [matcher]. This observes wall clock time, not frame time.
+ *
+ * @throws androidx.compose.ui.test.ComposeTimeoutException If exactly one node does not match the
+ * given [matcher] after [timeoutMillis] (in wall clock time).
+ */
+@ExperimentalTestApi
+fun ComposeUiTest.waitUntilExactlyOneExists(
+    matcher: SemanticsMatcher,
+    timeoutMillis: Long = 1_000L
+) = waitUntilNodeCount(matcher, 1, timeoutMillis)
+
+/**
+ * Blocks until no nodes match the given [matcher].
+ *
+ * @see ComposeUiTest.waitUntil
+ *
+ * @param matcher The matcher that will be used to filter nodes.
+ * @param timeoutMillis The time after which this method throws an exception if any nodes match
+ * the given [matcher]. This observes wall clock time, not frame time.
+ *
+ * @throws androidx.compose.ui.test.ComposeTimeoutException If any nodes match the given [matcher]
+ * after [timeoutMillis] (in wall clock time).
+ */
+@ExperimentalTestApi
+fun ComposeUiTest.waitUntilDoesNotExist(
+    matcher: SemanticsMatcher,
+    timeoutMillis: Long = 1_000L
+) = waitUntilNodeCount(matcher, 0, timeoutMillis)
+
 internal const val NanoSecondsPerMilliSecond = 1_000_000L
diff --git a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
index f9ca8ad..9fd4197 100644
--- a/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
+++ b/compose/ui/ui-test-junit4/src/desktopMain/kotlin/androidx/compose/ui/test/junit4/DesktopComposeTestRule.desktop.kt
@@ -26,6 +26,10 @@
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.SemanticsNodeInteraction
 import androidx.compose.ui.test.SemanticsNodeInteractionCollection
+import androidx.compose.ui.test.waitUntilAtLeastOneExists
+import androidx.compose.ui.test.waitUntilDoesNotExist
+import androidx.compose.ui.test.waitUntilExactlyOneExists
+import androidx.compose.ui.test.waitUntilNodeCount
 import androidx.compose.ui.unit.Density
 import kotlin.coroutines.CoroutineContext
 import kotlin.coroutines.EmptyCoroutineContext
@@ -89,6 +93,22 @@
     override fun waitUntil(timeoutMillis: Long, condition: () -> Boolean) =
         composeTest.waitUntil(timeoutMillis, condition)
 
+    @ExperimentalTestApi
+    override fun waitUntilNodeCount(matcher: SemanticsMatcher, count: Int, timeoutMillis: Long) =
+        composeTest.waitUntilNodeCount(matcher, count, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilAtLeastOneExists(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilAtLeastOneExists(matcher, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilExactlyOneExists(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilExactlyOneExists(matcher, timeoutMillis)
+
+    @ExperimentalTestApi
+    override fun waitUntilDoesNotExist(matcher: SemanticsMatcher, timeoutMillis: Long) =
+        composeTest.waitUntilDoesNotExist(matcher, timeoutMillis)
+
     override fun registerIdlingResource(idlingResource: IdlingResource) =
         composeTest.registerIdlingResource(idlingResource)
 
diff --git a/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.jvm.kt b/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.jvm.kt
index b0d353a..08dadac 100644
--- a/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.jvm.kt
+++ b/compose/ui/ui-test-junit4/src/jvmMain/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.jvm.kt
@@ -21,6 +21,7 @@
 import androidx.compose.ui.test.ExperimentalTestApi
 import androidx.compose.ui.test.IdlingResource
 import androidx.compose.ui.test.MainTestClock
+import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.SemanticsNodeInteractionsProvider
 import androidx.compose.ui.unit.Density
 import kotlin.coroutines.CoroutineContext
@@ -127,11 +128,73 @@
      * @param condition Condition that must be satisfied in order for this method to successfully
      * finish.
      *
-     * @throws ComposeTimeoutException If the condition is not satisfied after [timeoutMillis].
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If the condition is not satisfied
+     * after [timeoutMillis].
      */
     fun waitUntil(timeoutMillis: Long = 1_000, condition: () -> Boolean)
 
     /**
+     * Blocks until the number of nodes matching the given [matcher] is equal to the given [count].
+     *
+     * @see ComposeTestRule.waitUntil
+     *
+     * @param matcher The matcher that will be used to filter nodes.
+     * @param count The number of nodes that are expected to
+     * @param timeoutMillis The time after which this method throws an exception if the number of
+     * nodes that match the [matcher] is not [count]. This observes wall clock time, not frame time.
+     *
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If the number of nodes that match
+     * the [matcher] is not [count] after [timeoutMillis] (in wall clock time).
+     */
+    @ExperimentalTestApi
+    fun waitUntilNodeCount(matcher: SemanticsMatcher, count: Int, timeoutMillis: Long = 1_000L)
+
+    /**
+     * Blocks until at least one node matches the given [matcher].
+     *
+     * @see ComposeTestRule.waitUntil
+     *
+     * @param matcher The matcher that will be used to filter nodes.
+     * @param timeoutMillis The time after which this method throws an exception if no nodes match
+     * the given [matcher]. This observes wall clock time, not frame time.
+     *
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If no nodes match the given
+     * [matcher] after [timeoutMillis] (in wall clock time).
+     */
+    @ExperimentalTestApi
+    fun waitUntilAtLeastOneExists(matcher: SemanticsMatcher, timeoutMillis: Long = 1_000L)
+
+    /**
+     * Blocks until exactly one node matches the given [matcher].
+     *
+     * @see ComposeTestRule.waitUntil
+     *
+     * @param matcher The matcher that will be used to filter nodes.
+     * @param timeoutMillis The time after which this method throws an exception if exactly one node
+     * does not match the given [matcher]. This observes wall clock time, not frame time.
+     *
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If exactly one node does not match
+     * the given [matcher] after [timeoutMillis] (in wall clock time).
+     */
+    @ExperimentalTestApi
+    fun waitUntilExactlyOneExists(matcher: SemanticsMatcher, timeoutMillis: Long = 1_000L)
+
+    /**
+     * Blocks until no nodes match the given [matcher].
+     *
+     * @see ComposeTestRule.waitUntil
+     *
+     * @param matcher The matcher that will be used to filter nodes.
+     * @param timeoutMillis The time after which this method throws an exception if any nodes match
+     * the given [matcher]. This observes wall clock time, not frame time.
+     *
+     * @throws androidx.compose.ui.test.ComposeTimeoutException If any nodes match the given
+     * [matcher] after [timeoutMillis] (in wall clock time).
+     */
+    @ExperimentalTestApi
+    fun waitUntilDoesNotExist(matcher: SemanticsMatcher, timeoutMillis: Long = 1_000L)
+
+    /**
      * Registers an [IdlingResource] in this test.
      */
     fun registerIdlingResource(idlingResource: IdlingResource)
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 62ec3a6..541262b 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
@@ -646,9 +646,9 @@
     }
 
     private val FakeViewModelStoreOwner = object : ViewModelStoreOwner {
-        private val viewModelStore = ViewModelStore()
+        private val vmStore = ViewModelStore()
 
-        override fun getViewModelStore() = viewModelStore
+        override val viewModelStore = vmStore
     }
 
     private val FakeOnBackPressedDispatcherOwner = object : OnBackPressedDispatcherOwner {
diff --git a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/AnimationSearch.kt b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/AnimationSearch.kt
index 85fa93c..74f9023 100644
--- a/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/AnimationSearch.kt
+++ b/compose/ui/ui-tooling/src/androidMain/kotlin/androidx/compose/ui/tooling/animation/AnimationSearch.kt
@@ -38,6 +38,7 @@
 private const val ANIMATED_VISIBILITY = "AnimatedVisibility"
 private const val ANIMATE_VALUE_AS_STATE = "animateValueAsState"
 private const val REMEMBER = "remember"
+private const val REMEMBER_INFINITE_TRANSITION = "rememberInfiniteTransition"
 private const val REMEMBER_UPDATED_STATE = "rememberUpdatedState"
 private const val SIZE_ANIMATION_MODIFIER = "androidx.compose.animation.SizeAnimationModifier"
 
@@ -58,9 +59,12 @@
 }
 
 @OptIn(UiToolingDataApi::class)
-private inline fun <reified T> Group.findData(): T? {
+private inline fun <reified T> Group.findData(includeGrandchildren: Boolean = false): T? {
     // Search in self data and children data
-    return (data + children.flatMap { it.data }).firstOrNull { data ->
+    val dataToSearch = data + children.let {
+        if (includeGrandchildren) (it + it.flatMap { child -> child.children }) else it
+    }.flatMap { it.data }
+    return dataToSearch.firstOrNull { data ->
         data is T
     } as? T
 }
@@ -201,11 +205,13 @@
 
         private fun findAnimations(groupsWithLocation: Collection<Group>):
             List<InfiniteTransitionSearchInfo> {
-            val groups = groupsWithLocation.filter { group -> group.name == "run" }
-                .filterIsInstance<CallGroup>()
+            val groups =
+                groupsWithLocation.filter { group -> group.name == REMEMBER_INFINITE_TRANSITION }
+                    .filterIsInstance<CallGroup>()
+
             return groups.mapNotNull {
                 val infiniteTransition = it.findData<InfiniteTransition>()
-                val toolingOverride = it.findData<MutableState<State<Long>?>>()
+                val toolingOverride = it.findData<MutableState<State<Long>?>>(true)
                 if (infiniteTransition != null && toolingOverride != null) {
                     if (toolingOverride.value == null) {
                         toolingOverride.value = ToolingState(0L)
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 9af6a59..1e844e4 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
@@ -86,8 +86,8 @@
 import androidx.compose.ui.focus.focusRequester
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.graphics.ImageBitmap
-import androidx.compose.ui.graphics.toAndroidRect
 import androidx.compose.ui.graphics.graphicsLayer
+import androidx.compose.ui.graphics.toComposeRect
 import androidx.compose.ui.layout.Layout
 import androidx.compose.ui.platform.AndroidComposeView
 import androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat
@@ -1150,7 +1150,7 @@
             textFieldNode.positionInWindow
         )
         val expectedTopLeftInScreenCoords = androidComposeView.localToScreen(
-            expectedRectInLocalCoords.toAndroidRect().topLeftToOffset()
+            expectedRectInLocalCoords.topLeft
         )
         assertEquals(expectedTopLeftInScreenCoords.x, rectF.left)
         assertEquals(expectedTopLeftInScreenCoords.y, rectF.top)
@@ -2932,7 +2932,7 @@
         accessibilityNodeInfo.getBoundsInScreen(rect)
         val resultWidth = rect.right - rect.left
         val resultHeight = rect.bottom - rect.top
-        val resultInLocalCoords = androidComposeView.screenToLocal(rect.topLeftToOffset())
+        val resultInLocalCoords = androidComposeView.screenToLocal(rect.toComposeRect().topLeft)
 
         assertEquals(size, resultWidth)
         assertEquals(size, resultHeight)
@@ -3466,5 +3466,3 @@
             )
     }
 }
-
-private fun Rect.topLeftToOffset() = Offset(this.left.toFloat(), this.top.toFloat())
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofill.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofill.android.kt
index a1b44c7..436c8be 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofill.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofill.android.kt
@@ -27,7 +27,6 @@
 import androidx.annotation.DoNotInline
 import androidx.annotation.RequiresApi
 import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.graphics.toAndroidRect
 import androidx.compose.ui.util.fastMap
 
 /**
@@ -46,13 +45,20 @@
     init { view.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES }
 
     override fun requestAutofillForNode(autofillNode: AutofillNode) {
+        val boundingBox = autofillNode.boundingBox
+            ?: error("requestAutofill called before onChildPositioned()")
+
         // TODO(b/138731416): Find out what happens when notifyViewEntered() is called multiple times
         // before calling notifyViewExited().
         autofillManager.notifyViewEntered(
             view,
             autofillNode.id,
-            autofillNode.boundingBox?.toAndroidRect()
-                ?: error("requestAutofill called before onChildPositioned()")
+            android.graphics.Rect(
+                boundingBox.left.toInt(),
+                boundingBox.top.toInt(),
+                boundingBox.right.toInt(),
+                boundingBox.bottom.toInt()
+            )
         )
     }
 
@@ -89,7 +95,8 @@
                 autofillNode.autofillTypes.fastMap { it.androidType }.toTypedArray()
             )
 
-            if (autofillNode.boundingBox == null) {
+            val boundingBox = autofillNode.boundingBox
+            if (boundingBox == null) {
                 // Do we need an exception here? warning? silently ignore? If the boundingbox is
                 // null, the autofill overlay will not be shown.
                 Log.w(
@@ -97,9 +104,14 @@
                     """Bounding box not set.
                         Did you call perform autofillTree before the component was positioned? """
                 )
-            }
-            autofillNode.boundingBox?.toAndroidRect()?.run {
-                AutofillApi23Helper.setDimens(child, left, top, 0, 0, width(), height())
+            } else {
+                val left = boundingBox.left.toInt()
+                val top = boundingBox.top.toInt()
+                val right = boundingBox.right.toInt()
+                val bottom = boundingBox.bottom.toInt()
+                val width = right - left
+                val height = bottom - top
+                AutofillApi23Helper.setDimens(child, left, top, 0, 0, width, height)
             }
         }
         index++
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 f2876ab..64e9bbe 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
@@ -49,7 +49,6 @@
 import androidx.compose.ui.fastJoinToString
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Rect
-import androidx.compose.ui.graphics.toAndroidRect
 import androidx.compose.ui.graphics.toComposeRect
 import androidx.compose.ui.layout.boundsInParent
 import androidx.compose.ui.layout.boundsInWindow
@@ -2797,7 +2796,18 @@
     if (!root.layoutNode.isPlaced || !root.layoutNode.isAttached) {
         return nodes
     }
-    val unaccountedSpace = Region().also { it.set(root.boundsInRoot.toAndroidRect()) }
+    val unaccountedSpace = Region().also {
+        it.set(
+            root.boundsInRoot.run {
+                android.graphics.Rect(
+                    left.toInt(),
+                    top.toInt(),
+                    right.toInt(),
+                    bottom.toInt()
+                )
+            }
+        )
+    }
 
     fun findAllSemanticNodesRecursive(currentNode: SemanticsNode) {
         val notAttachedOrPlaced =
@@ -2807,7 +2817,12 @@
         ) {
             return
         }
-        val boundsInRoot = currentNode.touchBoundsInRoot.toAndroidRect()
+        val boundsInRoot = android.graphics.Rect(
+            currentNode.touchBoundsInRoot.left.toInt(),
+            currentNode.touchBoundsInRoot.top.toInt(),
+            currentNode.touchBoundsInRoot.right.toInt(),
+            currentNode.touchBoundsInRoot.bottom.toInt(),
+        )
         val region = Region().also { it.set(boundsInRoot) }
         val virtualViewId = if (currentNode.id == root.id) {
             AccessibilityNodeProviderCompat.HOST_VIEW_ID
@@ -2836,7 +2851,12 @@
                 }
                 nodes[virtualViewId] = SemanticsNodeWithAdjustedBounds(
                     currentNode,
-                    boundsForFakeNode.toAndroidRect()
+                    android.graphics.Rect(
+                        boundsForFakeNode.left.toInt(),
+                        boundsForFakeNode.top.toInt(),
+                        boundsForFakeNode.right.toInt(),
+                        boundsForFakeNode.bottom.toInt(),
+                    )
                 )
             } else if (virtualViewId == AccessibilityNodeProviderCompat.HOST_VIEW_ID) {
                 // Root view might have WRAP_CONTENT layout params in which case it will have zero
diff --git a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java
index 1c94351..c675c67 100644
--- a/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java
+++ b/constraintlayout/constraintlayout/src/main/java/androidx/constraintlayout/widget/ConstraintLayout.java
@@ -105,7 +105,6 @@
  * ConstraintLayout.LayoutParams} for layout attributes
  * </p>
  *
- * <div class="special reference">
  * <h3>Developer Guide</h3>
  *
  * <h4 id="RelativePositioning"> Relative positioning </h4>
@@ -556,7 +555,6 @@
  * <p>This attribute is a mask, so you can decide to turn on or off
  * specific optimizations by listing the ones you want.
  * For example: <i>app:layout_optimizationLevel="direct|barrier|chain"</i> </p>
- * </div>
  */
 public class ConstraintLayout extends ViewGroup {
     /**
diff --git a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ImportVersionCatalog.kt b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ImportVersionCatalog.kt
index 93a8175..7c554df 100644
--- a/development/importMaven/src/main/kotlin/androidx/build/importMaven/ImportVersionCatalog.kt
+++ b/development/importMaven/src/main/kotlin/androidx/build/importMaven/ImportVersionCatalog.kt
@@ -46,7 +46,6 @@
             Interners.newStrongInterner(),
             Interners.newStrongInterner(),
             project.objects,
-            project.providers,
             { error("Not supported") },
             configurations
         )
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index d61d7f9..498ff9f 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -18,8 +18,9 @@
     docs(project(":ads:ads-identifier-testing"))
     kmpDocs(project(":annotation:annotation"))
     docs(project(":annotation:annotation-experimental"))
-    docs(project(":appactions:interaction:interaction-proto"))
     docs(project(":appactions:interaction:interaction-capabilities-core"))
+    docs(project(":appactions:interaction:interaction-proto"))
+    docs(project(":appactions:interaction:interaction-service"))
     docs(project(":appcompat:appcompat"))
     docs(project(":appcompat:appcompat-resources"))
     docs(project(":appsearch:appsearch"))
diff --git a/fragment/OWNERS b/fragment/OWNERS
index 94b111e..b867087 100644
--- a/fragment/OWNERS
+++ b/fragment/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 460964
+# Bug component: 461227
 ilake@google.com
 jbwoods@google.com
 mount@google.com
diff --git a/fragment/fragment/api/current.txt b/fragment/fragment/api/current.txt
index 76aeea3..8417281 100644
--- a/fragment/fragment/api/current.txt
+++ b/fragment/fragment/api/current.txt
@@ -145,11 +145,11 @@
     method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
     method @Deprecated public void setUserVisibleHint(boolean);
     method public boolean shouldShowRequestPermissionRationale(String);
-    method public void startActivity(android.content.Intent!);
-    method public void startActivity(android.content.Intent!, android.os.Bundle?);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void startPostponedEnterTransition();
     method public void unregisterForContextMenu(android.view.View);
   }
@@ -174,9 +174,9 @@
     method public void onStateNotSaved();
     method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
     method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void supportFinishAfterTransition();
     method @Deprecated public void supportInvalidateOptionsMenu();
     method public void supportPostponeEnterTransition();
@@ -261,9 +261,9 @@
     method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
     method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
     method public boolean onShouldShowRequestPermissionRationale(String);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void onSupportInvalidateOptionsMenu();
   }
 
diff --git a/fragment/fragment/api/public_plus_experimental_current.txt b/fragment/fragment/api/public_plus_experimental_current.txt
index 76aeea3..8417281 100644
--- a/fragment/fragment/api/public_plus_experimental_current.txt
+++ b/fragment/fragment/api/public_plus_experimental_current.txt
@@ -145,11 +145,11 @@
     method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
     method @Deprecated public void setUserVisibleHint(boolean);
     method public boolean shouldShowRequestPermissionRationale(String);
-    method public void startActivity(android.content.Intent!);
-    method public void startActivity(android.content.Intent!, android.os.Bundle?);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void startPostponedEnterTransition();
     method public void unregisterForContextMenu(android.view.View);
   }
@@ -174,9 +174,9 @@
     method public void onStateNotSaved();
     method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
     method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void supportFinishAfterTransition();
     method @Deprecated public void supportInvalidateOptionsMenu();
     method public void supportPostponeEnterTransition();
@@ -261,9 +261,9 @@
     method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
     method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
     method public boolean onShouldShowRequestPermissionRationale(String);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void onSupportInvalidateOptionsMenu();
   }
 
diff --git a/fragment/fragment/api/restricted_current.txt b/fragment/fragment/api/restricted_current.txt
index bdcefeb..3671696 100644
--- a/fragment/fragment/api/restricted_current.txt
+++ b/fragment/fragment/api/restricted_current.txt
@@ -149,11 +149,11 @@
     method @Deprecated public void setTargetFragment(androidx.fragment.app.Fragment?, int);
     method @Deprecated public void setUserVisibleHint(boolean);
     method public boolean shouldShowRequestPermissionRationale(String);
-    method public void startActivity(android.content.Intent!);
-    method public void startActivity(android.content.Intent!, android.os.Bundle?);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int);
-    method @Deprecated public void startActivityForResult(android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivity(android.content.Intent);
+    method public void startActivity(android.content.Intent, android.os.Bundle?);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int);
+    method @Deprecated public void startActivityForResult(android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderForResult(android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void startPostponedEnterTransition();
     method public void unregisterForContextMenu(android.view.View);
   }
@@ -178,9 +178,9 @@
     method public void onStateNotSaved();
     method public void setEnterSharedElementCallback(androidx.core.app.SharedElementCallback?);
     method public void setExitSharedElementCallback(androidx.core.app.SharedElementCallback?);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void startActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void startIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void supportFinishAfterTransition();
     method @Deprecated public void supportInvalidateOptionsMenu();
     method public void supportPostponeEnterTransition();
@@ -265,9 +265,9 @@
     method @Deprecated public void onRequestPermissionsFromFragment(androidx.fragment.app.Fragment, String![], int);
     method public boolean onShouldSaveFragmentState(androidx.fragment.app.Fragment);
     method public boolean onShouldShowRequestPermissionRationale(String);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int);
-    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent!, int, android.os.Bundle?);
-    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender!, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int);
+    method public void onStartActivityFromFragment(androidx.fragment.app.Fragment, android.content.Intent, int, android.os.Bundle?);
+    method @Deprecated public void onStartIntentSenderFromFragment(androidx.fragment.app.Fragment, android.content.IntentSender, int, android.content.Intent?, int, int, int, android.os.Bundle?) throws android.content.IntentSender.SendIntentException;
     method public void onSupportInvalidateOptionsMenu();
   }
 
diff --git a/fragment/fragment/build.gradle b/fragment/fragment/build.gradle
index 658a821..b751358 100644
--- a/fragment/fragment/build.gradle
+++ b/fragment/fragment/build.gradle
@@ -32,7 +32,7 @@
     api("androidx.activity:activity:1.5.1")
     api(projectOrArtifact(":lifecycle:lifecycle-runtime"))
     api("androidx.lifecycle:lifecycle-livedata-core:2.5.1")
-    api("androidx.lifecycle:lifecycle-viewmodel:2.5.1")
+    api(projectOrArtifact(":lifecycle:lifecycle-viewmodel"))
     api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.1")
     api("androidx.savedstate:savedstate:1.2.0")
     api("androidx.annotation:annotation-experimental:1.0.0")
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
index 095f013..f4ba719b 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/ControllerHostCallbacks.kt
@@ -81,12 +81,10 @@
 
 class ControllerHostCallbacks(
     private val activity: FragmentActivity,
-    private val viewModelStore: ViewModelStore
+    private val vmStore: ViewModelStore
 ) : FragmentHostCallback<FragmentActivity>(activity), ViewModelStoreOwner {
 
-    override fun getViewModelStore(): ViewModelStore {
-        return viewModelStore
-    }
+    override val viewModelStore: ViewModelStore = vmStore
 
     override fun onDump(
         prefix: String,
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
index cbd53a2..31a1632 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
@@ -1431,7 +1431,7 @@
      * Call {@link Activity#startActivity(Intent)} from the fragment's
      * containing Activity.
      */
-    public void startActivity(@SuppressLint("UnknownNullness") Intent intent) {
+    public void startActivity(@NonNull Intent intent) {
         startActivity(intent, null);
     }
 
@@ -1439,7 +1439,7 @@
      * Call {@link Activity#startActivity(Intent, Bundle)} from the fragment's
      * containing Activity.
      */
-    public void startActivity(@SuppressLint("UnknownNullness") Intent intent,
+    public void startActivity(@NonNull Intent intent,
             @Nullable Bundle options) {
         if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
@@ -1468,7 +1468,7 @@
      */
     @SuppressWarnings("deprecation")
     @Deprecated
-    public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
+    public void startActivityForResult(@NonNull Intent intent,
             int requestCode) {
         startActivityForResult(intent, requestCode, null);
     }
@@ -1496,7 +1496,7 @@
      */
     @SuppressWarnings("DeprecatedIsStillUsed")
     @Deprecated
-    public void startActivityForResult(@SuppressLint("UnknownNullness") Intent intent,
+    public void startActivityForResult(@NonNull Intent intent,
             int requestCode, @Nullable Bundle options) {
         if (mHost == null) {
             throw new IllegalStateException("Fragment " + this + " not attached to Activity");
@@ -1534,7 +1534,7 @@
      * {@link ActivityResultContract}.
      */
     @Deprecated
-    public void startIntentSenderForResult(@SuppressLint("UnknownNullness") IntentSender intent,
+    public void startIntentSenderForResult(@NonNull IntentSender intent,
             int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
             int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
         if (mHost == null) {
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
index b48c19c..c373049 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentActivity.java
@@ -18,7 +18,6 @@
 
 import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult;
 
-import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -501,7 +500,7 @@
      *                    greater than 65535, an IllegalArgumentException would be thrown.
      */
     public void startActivityFromFragment(@NonNull Fragment fragment,
-            @SuppressLint("UnknownNullness") Intent intent, int requestCode) {
+            @NonNull Intent intent, int requestCode) {
         startActivityFromFragment(fragment, intent, requestCode, null);
     }
 
@@ -519,7 +518,7 @@
      */
     @SuppressWarnings("deprecation")
     public void startActivityFromFragment(@NonNull Fragment fragment,
-            @SuppressLint("UnknownNullness") Intent intent, int requestCode,
+            @NonNull Intent intent, int requestCode,
             @Nullable Bundle options) {
         // request code will be -1 if called from fragment.startActivity
         if (requestCode == -1) {
@@ -558,7 +557,7 @@
     @SuppressWarnings({"deprecation"})
     @Deprecated
     public void startIntentSenderFromFragment(@NonNull Fragment fragment,
-            @SuppressLint("UnknownNullness") IntentSender intent, int requestCode,
+            @NonNull IntentSender intent, int requestCode,
             @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
             @Nullable Bundle options) throws IntentSender.SendIntentException {
         if (requestCode == -1) {
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
index 21079f0..b9ebe38 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentHostCallback.java
@@ -19,7 +19,6 @@
 import static androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions;
 import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult;
 
-import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -149,7 +148,7 @@
      * See {@link FragmentActivity#startActivityForResult(Intent, int)}.
      */
     public void onStartActivityFromFragment(@NonNull Fragment fragment,
-            @SuppressLint("UnknownNullness") Intent intent, int requestCode) {
+            @NonNull Intent intent, int requestCode) {
         onStartActivityFromFragment(fragment, intent, requestCode, null);
     }
 
@@ -158,7 +157,7 @@
      * See {@link FragmentActivity#startActivityForResult(Intent, int, Bundle)}.
      */
     public void onStartActivityFromFragment(
-            @NonNull Fragment fragment, @SuppressLint("UnknownNullness") Intent intent,
+            @NonNull Fragment fragment, @NonNull Intent intent,
             int requestCode, @Nullable Bundle options) {
         if (requestCode != -1) {
             throw new IllegalStateException(
@@ -179,7 +178,7 @@
      */
     @Deprecated
     public void onStartIntentSenderFromFragment(@NonNull Fragment fragment,
-            @SuppressLint("UnknownNullness") IntentSender intent, int requestCode,
+            @NonNull IntentSender intent, int requestCode,
             @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
             @Nullable Bundle options) throws IntentSender.SendIntentException {
         if (requestCode != -1) {
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 1e0f070..af6591c 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/FragmentManager.java
@@ -2815,12 +2815,12 @@
     }
 
     void launchStartActivityForResult(@NonNull Fragment f,
-            @SuppressLint("UnknownNullness") Intent intent,
+            @NonNull Intent intent,
             int requestCode, @Nullable Bundle options) {
         if (mStartActivityForResult != null) {
             LaunchedFragmentInfo info = new LaunchedFragmentInfo(f.mWho, requestCode);
             mLaunchedFragments.addLast(info);
-            if (intent != null && options != null) {
+            if (options != null) {
                 intent.putExtra(EXTRA_ACTIVITY_OPTIONS_BUNDLE, options);
             }
             mStartActivityForResult.launch(intent);
@@ -2831,7 +2831,7 @@
 
     @SuppressWarnings("deprecation")
     void launchStartIntentSenderForResult(@NonNull Fragment f,
-            @SuppressLint("UnknownNullness") IntentSender intent,
+            @NonNull IntentSender intent,
             int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues,
             int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
         if (mStartIntentSenderForResult != null) {
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
index 809209f..ac37082 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
+++ b/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
@@ -228,6 +228,7 @@
         }
     }
 
+    @Ignore("b/266588723")
     @Test
     fun createTextWithFillMaxDimensions() {
         TestGlanceAppWidget.uiDefinition = {
@@ -346,6 +347,7 @@
         }
     }
 
+    @Ignore("b/265078768")
     @Test
     fun createRowWithTwoTexts() {
         TestGlanceAppWidget.uiDefinition = {
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
index 379f501..69601cf 100644
--- a/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
+++ b/graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/PolygonTest.kt
@@ -21,7 +21,10 @@
 import androidx.core.graphics.plus
 import androidx.core.graphics.times
 import androidx.test.filters.SmallTest
-import org.junit.Assert
+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
@@ -73,7 +76,7 @@
     fun pathTest() {
         val shape = square.toCubicShape()
         val path = shape.toPath()
-        Assert.assertFalse(path.isEmpty)
+        assertFalse(path.isEmpty)
     }
 
     @Test
@@ -95,7 +98,7 @@
         val squareCopy = Polygon(square)
         val identity = Matrix()
         square.transform(identity)
-        Assert.assertEquals(square, squareCopy)
+        assertEquals(square, squareCopy)
 
         // Now create a matrix which translates points by (1, 2) and make sure
         // the shape is translated similarly by it
@@ -112,4 +115,48 @@
             assertPointsEqualish(squareCopyCubics[i].p3 + offset, squareCubics[i].p3)
         }
     }
+
+    @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 = Polygon(square)
+        val squareCopyFeatures = squareCopy.features
+        assertTrue(squareCopy.toCubicShape().cubics == squareCopyFeatures.flatMap { it.cubics })
+
+        // Test other elements of Features
+        val copy = Polygon(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 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 Corner) {
+                postTransformVertices.add(feature.vertex)
+                postTransformCenters.add(feature.roundedCenter)
+            }
+        }
+        assertNotEquals(preTransformVertices, postTransformVertices)
+        assertNotEquals(preTransformCenters, postTransformCenters)
+    }
 }
\ No newline at end of file
diff --git a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Polygon.kt b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Polygon.kt
index 24194e4..5129044 100644
--- a/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Polygon.kt
+++ b/graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/Polygon.kt
@@ -181,11 +181,12 @@
         val tempFeatures = mutableListOf<Feature>()
         for (feature in source.features) {
             if (feature is Edge) {
-                tempFeatures.add(Edge(feature))
+                tempFeatures.add(Edge(this, feature))
             } else {
-                tempFeatures.add(Corner(feature as Corner))
+                tempFeatures.add(Corner(this, feature as Corner))
             }
         }
+        features = tempFeatures
         center = PointF(source.center.x, source.center.y)
         cubicShape.updateCubics(newCubics)
     }
@@ -257,11 +258,15 @@
         // from above, along with new cubics representing the edges between those corners.
         val tempFeatures = mutableListOf<Feature>()
         for (i in 0 until n) {
-            cubics.addAll(corners[i])
+            val cornerIndices = mutableListOf<Int>()
+            for (cubic in corners[i]) {
+                cornerIndices.add(cubics.size)
+                cubics.add(cubic)
+            }
             // TODO: determine and pass convexity flag
-            tempFeatures.add(Corner(corners[i], roundedCorners[i].center, vertices[i]))
+            tempFeatures.add(Corner(this, cornerIndices, roundedCorners[i].center, vertices[i]))
+            tempFeatures.add(Edge(this, listOf(cubics.size)))
             cubics.add(Cubic.straightLine(corners[i].last().p3, corners[(i + 1) % n].first().p0))
-            tempFeatures.add(Edge(listOf(cubics[cubics.size - 1])))
         }
         features = tempFeatures
         cubicShape.updateCubics(cubics)
@@ -276,6 +281,9 @@
         matrix.mapPoints(point)
         center.x = point[0]
         center.y = point[1]
+        for (feature in features) {
+            feature.transform(matrix)
+        }
     }
 
     /**
@@ -415,15 +423,27 @@
  * of what the shape actually is, rather than simply manipulating the raw curves and lines
  * which describe it.
  */
-internal sealed class Feature(val cubics: List<Cubic>)
+internal sealed class Feature(private val polygon: Polygon, protected val cubicIndices: List<Int>) {
+    val cubics: MutableList<Cubic>
+        get() {
+            val featureCubics = mutableListOf<Cubic>()
+            val cubics = polygon.toCubicShape().cubics
+            for (index in cubicIndices) {
+                featureCubics.add(cubics[index])
+            }
+            return featureCubics
+        }
+
+    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 class Edge(cubics: List<Cubic>) : Feature(cubics) {
-    constructor(source: Edge) : this(source.cubics)
+internal class Edge(polygon: Polygon, indices: List<Int>) : Feature(polygon, indices) {
+    constructor(polygon: Polygon, source: Edge) : this(polygon, source.cubicIndices)
 }
 
 /**
@@ -434,18 +454,27 @@
  * convex (outer) and concave (inner) corners.
  */
 internal class Corner(
-    cubics: List<Cubic>,
+    polygon: Polygon,
+    cubicIndices: List<Int>,
     // TODO: parameters here should be immutable
     val vertex: PointF,
     val roundedCenter: PointF,
     val convex: Boolean = true
-) : Feature(cubics) {
-    constructor(source: Corner) : this(
-        source.cubics,
+) : Feature(polygon, cubicIndices) {
+    constructor(polygon: Polygon, source: Corner) : this(
+        polygon,
+        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])
+    }
 }
 
 /**
diff --git a/health/connect/connect-client/src/main/java/androidx/health/platform/client/SdkConfig.java b/health/connect/connect-client/src/main/java/androidx/health/platform/client/SdkConfig.java
index 3e2ec2d..7629a30 100644
--- a/health/connect/connect-client/src/main/java/androidx/health/platform/client/SdkConfig.java
+++ b/health/connect/connect-client/src/main/java/androidx/health/platform/client/SdkConfig.java
@@ -25,7 +25,7 @@
 @RestrictTo(RestrictTo.Scope.LIBRARY)
 public final class SdkConfig {
     // should be increased everytime a new SDK is released
-    public static final int SDK_VERSION = 10;
+    public static final int SDK_VERSION = 11;
 
     private SdkConfig() {}
 }
diff --git a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
index c067c51..3b02e84 100644
--- a/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
+++ b/lifecycle/lifecycle-viewmodel-compose/src/androidTest/java/androidx/lifecycle/viewmodel/compose/ViewModelTest.kt
@@ -270,6 +270,6 @@
     val store = ViewModelStore()
     val factory = FakeViewModelProviderFactory()
 
-    override fun getViewModelStore(): ViewModelStore = store
+    override val viewModelStore: ViewModelStore = store
     override val defaultViewModelProviderFactory = factory
 }
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/build.gradle b/lifecycle/lifecycle-viewmodel-savedstate/build.gradle
index 3ceb0b3..a88aecc 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/build.gradle
+++ b/lifecycle/lifecycle-viewmodel-savedstate/build.gradle
@@ -52,10 +52,6 @@
     constraints {
         implementation(project(":lifecycle:lifecycle-livedata-core"))
         implementation(project(":lifecycle:lifecycle-viewmodel"))
-        // this syntax is a temporary workout to allow project dependency on cross-project-set
-        // i.e. COMPOSE + MAIN project sets
-        // update syntax when b/239979823 is fixed
-        implementation("androidx.lifecycle:lifecycle-viewmodel-compose:${androidx.LibraryVersions.LIFECYCLE}")
     }
 }
 
diff --git a/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/TestComponent.kt b/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/TestComponent.kt
index 1f7b190..efdb532 100644
--- a/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/TestComponent.kt
+++ b/lifecycle/lifecycle-viewmodel-savedstate/src/androidTest/java/androidx/lifecycle/viewmodel/savedstate/TestComponent.kt
@@ -49,7 +49,7 @@
     override val savedStateRegistry: SavedStateRegistry
         get() = savedStateController.savedStateRegistry
 
-    override fun getViewModelStore(): ViewModelStore = vmStore
+    override val viewModelStore: ViewModelStore = vmStore
 
     fun resume() {
         lifecycleRegistry.currentState = Lifecycle.State.RESUMED
diff --git a/lifecycle/lifecycle-viewmodel/api/current.txt b/lifecycle/lifecycle-viewmodel/api/current.txt
index 75944f4..f8457f6 100644
--- a/lifecycle/lifecycle-viewmodel/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/current.txt
@@ -80,6 +80,7 @@
 
   public interface ViewModelStoreOwner {
     method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public abstract androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class ViewTreeViewModelKt {
diff --git a/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
index 75944f4..f8457f6 100644
--- a/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
@@ -80,6 +80,7 @@
 
   public interface ViewModelStoreOwner {
     method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public abstract androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class ViewTreeViewModelKt {
diff --git a/lifecycle/lifecycle-viewmodel/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
index 75944f4..f8457f6 100644
--- a/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
@@ -80,6 +80,7 @@
 
   public interface ViewModelStoreOwner {
     method public androidx.lifecycle.ViewModelStore getViewModelStore();
+    property public abstract androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class ViewTreeViewModelKt {
diff --git a/lifecycle/lifecycle-viewmodel/src/androidTest/java/androidx/lifecycle/ViewTreeViewModelStoreOwnerTest.kt b/lifecycle/lifecycle-viewmodel/src/androidTest/java/androidx/lifecycle/ViewTreeViewModelStoreOwnerTest.kt
index 2fd80c7..6424d49 100644
--- a/lifecycle/lifecycle-viewmodel/src/androidTest/java/androidx/lifecycle/ViewTreeViewModelStoreOwnerTest.kt
+++ b/lifecycle/lifecycle-viewmodel/src/androidTest/java/androidx/lifecycle/ViewTreeViewModelStoreOwnerTest.kt
@@ -133,8 +133,9 @@
     }
 
     internal class FakeViewModelStoreOwner : ViewModelStoreOwner {
-        override fun getViewModelStore(): ViewModelStore {
-            throw UnsupportedOperationException("not a real ViewModelStoreOwner")
-        }
+        override val viewModelStore: ViewModelStore
+            get() {
+                throw UnsupportedOperationException("not a real ViewModelStoreOwner")
+            }
     }
 }
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.kt
similarity index 64%
rename from lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java
rename to lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.kt
index 19152be..5296800 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.kt
@@ -13,27 +13,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package androidx.lifecycle;
-
-import androidx.annotation.NonNull;
+package androidx.lifecycle
 
 /**
- * A scope that owns {@link ViewModelStore}.
- * <p>
+ * A scope that owns [ViewModelStore].
+ *
  * A responsibility of an implementation of this interface is to retain owned ViewModelStore
- * during the configuration changes and call {@link ViewModelStore#clear()}, when this scope is
+ * during the configuration changes and call [ViewModelStore.clear], when this scope is
  * going to be destroyed.
  *
  * @see ViewTreeViewModelStoreOwner
  */
-@SuppressWarnings("WeakerAccess")
-public interface ViewModelStoreOwner {
+interface ViewModelStoreOwner {
+
     /**
-     * Returns owned {@link ViewModelStore}
-     *
-     * @return a {@code ViewModelStore}
+     * The owned [ViewModelStore]
      */
-    @NonNull
-    ViewModelStore getViewModelStore();
-}
+    val viewModelStore: ViewModelStore
+}
\ No newline at end of file
diff --git a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt
index 2536918..934878d 100644
--- a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt
+++ b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.kt
@@ -62,8 +62,7 @@
 
     @Test
     fun testOwnedBy() {
-        val store = ViewModelStore()
-        val owner = ViewModelStoreOwner { store }
+        val owner = FakeViewModelStoreOwner()
         val provider = ViewModelProvider(owner, ViewModelProvider.NewInstanceFactory())
         val viewModel = provider[ViewModel1::class.java]
         assertThat(viewModel).isSameInstanceAs(provider[ViewModel1::class.java])
@@ -82,8 +81,7 @@
 
     @Test
     fun testKeyedFactory() {
-        val store = ViewModelStore()
-        val owner = ViewModelStoreOwner { store }
+        val owner = FakeViewModelStoreOwner()
         val explicitlyKeyed: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
             override fun <T : ViewModel> create(
                 modelClass: Class<T>,
@@ -172,13 +170,16 @@
         private val mStore: ViewModelStore,
         private val mFactory: ViewModelProvider.Factory
     ) : ViewModelStoreOwner, HasDefaultViewModelProviderFactory {
-        override fun getViewModelStore(): ViewModelStore {
-            return mStore
-        }
-
+        override val viewModelStore: ViewModelStore = mStore
         override val defaultViewModelProviderFactory = mFactory
     }
 
+    class FakeViewModelStoreOwner internal constructor(
+        store: ViewModelStore = ViewModelStore()
+    ) : ViewModelStoreOwner {
+        override val viewModelStore: ViewModelStore = store
+    }
+
     open class ViewModel1 : ViewModel() {
         var cleared = false
         override fun onCleared() {
@@ -197,7 +198,7 @@
 
     internal open class ViewModelStoreOwnerWithCreationExtras : ViewModelStoreOwner,
         HasDefaultViewModelProviderFactory {
-        private val viewModelStore = ViewModelStore()
+        private val _viewModelStore = ViewModelStore()
         override val defaultViewModelProviderFactory: ViewModelProvider.Factory
             get() = throw UnsupportedOperationException()
 
@@ -208,9 +209,7 @@
                 return extras
             }
 
-        override fun getViewModelStore(): ViewModelStore {
-            return viewModelStore
-        }
+        override val viewModelStore: ViewModelStore = _viewModelStore
     }
 }
 
diff --git a/navigation/navigation-common/api/current.txt b/navigation/navigation-common/api/current.txt
index 34e00ed..a0905df 100644
--- a/navigation/navigation-common/api/current.txt
+++ b/navigation/navigation-common/api/current.txt
@@ -129,6 +129,7 @@
     property public final String id;
     property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class NavDeepLink {
diff --git a/navigation/navigation-common/api/public_plus_experimental_current.txt b/navigation/navigation-common/api/public_plus_experimental_current.txt
index 34e00ed..a0905df 100644
--- a/navigation/navigation-common/api/public_plus_experimental_current.txt
+++ b/navigation/navigation-common/api/public_plus_experimental_current.txt
@@ -129,6 +129,7 @@
     property public final String id;
     property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class NavDeepLink {
diff --git a/navigation/navigation-common/api/restricted_current.txt b/navigation/navigation-common/api/restricted_current.txt
index 34e00ed..a0905df 100644
--- a/navigation/navigation-common/api/restricted_current.txt
+++ b/navigation/navigation-common/api/restricted_current.txt
@@ -129,6 +129,7 @@
     property public final String id;
     property public final androidx.lifecycle.SavedStateHandle savedStateHandle;
     property public androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    property public androidx.lifecycle.ViewModelStore viewModelStore;
   }
 
   public final class NavDeepLink {
diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
index 3f0656e..953aae9 100644
--- a/navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
+++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavBackStackEntry.kt
@@ -197,29 +197,30 @@
         }
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @throws IllegalStateException if called before the [lifecycle] has moved to
-     * [Lifecycle.State.CREATED] or before the [androidx.navigation.NavHost] has called
-     * [androidx.navigation.NavHostController.setViewModelStore].
-     */
-    public override fun getViewModelStore(): ViewModelStore {
-        check(savedStateRegistryAttached) {
-            "You cannot access the NavBackStackEntry's ViewModels until it is added to " +
-                "the NavController's back stack (i.e., the Lifecycle of the NavBackStackEntry " +
-                "reaches the CREATED state)."
+    public override val viewModelStore: ViewModelStore
+        /**
+         * {@inheritDoc}
+         *
+         * @throws IllegalStateException if called before the [lifecycle] has moved to
+         * [Lifecycle.State.CREATED] or before the [androidx.navigation.NavHost] has called
+         * [androidx.navigation.NavHostController.setViewModelStore].
+         */
+        get() {
+            check(savedStateRegistryAttached) {
+                "You cannot access the NavBackStackEntry's ViewModels until it is added to " +
+                    "the NavController's back stack (i.e., the Lifecycle of the " +
+                    "NavBackStackEntry reaches the CREATED state)."
+            }
+            check(lifecycle.currentState != Lifecycle.State.DESTROYED) {
+                "You cannot access the NavBackStackEntry's ViewModels after the " +
+                    "NavBackStackEntry is destroyed."
+            }
+            checkNotNull(viewModelStoreProvider) {
+                "You must call setViewModelStore() on your NavHostController before " +
+                    "accessing the ViewModelStore of a navigation graph."
+            }
+            return viewModelStoreProvider.getViewModelStore(id)
         }
-        check(lifecycle.currentState != Lifecycle.State.DESTROYED) {
-            "You cannot access the NavBackStackEntry's ViewModels after the " +
-                "NavBackStackEntry is destroyed."
-        }
-        checkNotNull(viewModelStoreProvider) {
-            "You must call setViewModelStore() on your NavHostController before accessing the " +
-                "ViewModelStore of a navigation graph."
-        }
-        return viewModelStoreProvider.getViewModelStore(id)
-    }
 
     override val defaultViewModelProviderFactory: ViewModelProvider.Factory = defaultFactory
 
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/TestUtils.kt b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/TestUtils.kt
index 57fd35f..94f7888 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/TestUtils.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/TestUtils.kt
@@ -16,7 +16,7 @@
 
 package androidx.privacysandbox.tools.apicompiler
 
-import androidx.privacysandbox.tools.apicompiler.util.allTestLibraryStubs
+import androidx.privacysandbox.tools.testing.allTestLibraryStubs
 import androidx.privacysandbox.tools.testing.CompilationTestHelper
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.compiler.TestCompilationResult
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/KspTestRunner.kt b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/KspTestRunner.kt
index 57468ca..31aee1f2 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/KspTestRunner.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/KspTestRunner.kt
@@ -16,10 +16,11 @@
 
 package androidx.privacysandbox.tools.apicompiler.util
 
-import androidx.privacysandbox.tools.core.model.ParsedApi
 import androidx.privacysandbox.tools.apicompiler.parser.ApiParser
-import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertThat
+import androidx.privacysandbox.tools.core.model.ParsedApi
 import androidx.privacysandbox.tools.testing.CompilationResultSubject
+import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertThat
+import androidx.privacysandbox.tools.testing.allTestLibraryStubs
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.compiler.TestCompilationArguments
 import androidx.room.compiler.processing.util.compiler.compile
diff --git a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/InterfaceFileGenerator.kt b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/InterfaceFileGenerator.kt
index 02ecc7d..e7e87a0 100644
--- a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/InterfaceFileGenerator.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/InterfaceFileGenerator.kt
@@ -33,12 +33,13 @@
     fun generate(annotatedInterface: AnnotatedInterface): FileSpec {
         val annotatedInterfaceType =
             TypeSpec.interfaceBuilder(annotatedInterface.type.poetClassName()).build {
+                addSuperinterfaces(annotatedInterface.superTypes.map { it.poetClassName() })
                 addFunctions(annotatedInterface.methods.map(::generateInterfaceMethod))
             }
 
         return FileSpec.get(annotatedInterface.type.packageName, annotatedInterfaceType)
             .toBuilder().build {
-            addCommonSettings()
+                addCommonSettings()
         }
     }
 
diff --git a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParser.kt b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParser.kt
index fd952ab..f0bb98a 100644
--- a/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParser.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/main/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParser.kt
@@ -22,6 +22,7 @@
 import androidx.privacysandbox.tools.core.model.Parameter
 import androidx.privacysandbox.tools.core.model.ParsedApi
 import androidx.privacysandbox.tools.core.model.Type
+import androidx.privacysandbox.tools.core.model.Types
 import androidx.privacysandbox.tools.core.model.ValueProperty
 import androidx.privacysandbox.tools.core.validator.ModelValidator
 import java.nio.file.Path
@@ -55,6 +56,7 @@
 
     private fun parseInterface(service: KmClass, annotationName: String): AnnotatedInterface {
         val type = parseClassName(service.name)
+        val superTypes = service.supertypes.map(this::parseType).filterNot { it == Types.any }
 
         if (!Flag.Class.IS_INTERFACE(service.flags)) {
             throw PrivacySandboxParsingException(
@@ -65,6 +67,7 @@
 
         return AnnotatedInterface(
             type = type,
+            superTypes = superTypes,
             methods = service.functions.map(this::parseMethod),
         )
     }
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/BaseApiGeneratorTest.kt b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/BaseApiGeneratorTest.kt
index 860b155..73ce728 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/BaseApiGeneratorTest.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/BaseApiGeneratorTest.kt
@@ -18,6 +18,7 @@
 
 import androidx.privacysandbox.tools.core.Metadata
 import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertCompiles
+import androidx.privacysandbox.tools.testing.allTestLibraryStubs
 import androidx.privacysandbox.tools.testing.hasAllExpectedGeneratedSourceFilesAndContent
 import androidx.privacysandbox.tools.testing.loadSourcesFromDirectory
 import androidx.room.compiler.processing.util.Source
@@ -49,7 +50,7 @@
 
     @Test
     fun generatedApi_compiles() {
-        assertCompiles(generatedSources)
+        assertCompiles(generatedSources + allTestLibraryStubs)
     }
 
     @Test
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/TestUtils.kt b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/TestUtils.kt
index fade128..ea01aa8 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/TestUtils.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/TestUtils.kt
@@ -18,6 +18,7 @@
 
 import androidx.privacysandbox.tools.apipackager.PrivacySandboxApiPackager
 import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertCompiles
+import androidx.privacysandbox.tools.testing.allTestLibraryStubs
 import androidx.room.compiler.processing.util.Source
 import androidx.room.compiler.processing.util.compiler.TestCompilationResult
 import java.nio.file.Files.createTempDirectory
@@ -31,13 +32,17 @@
  *
  * @param descriptorResources map of extra resources that will be added to descriptors jar keyed by
  *      their relative path.
+ * @param addLibraryStubs whether to include latest Android platform API stubs that support the
+ * Privacy Sandbox.
  */
 fun compileIntoInterfaceDescriptorsJar(
     sources: List<Source>,
     descriptorResources: Map<Path, ByteArray> = mapOf(),
+    addLibraryStubs: Boolean = true,
 ): Path {
+    val testSources = if (addLibraryStubs) sources + allTestLibraryStubs else sources
     val tempDir = createTempDirectory("compile").also { it.toFile().deleteOnExit() }
-    val result = assertCompiles(sources.toList())
+    val result = assertCompiles(testSources.toList())
     val sdkInterfaceDescriptors = tempDir.resolve("sdk-interface-descriptors.jar")
     val outputClasspath = mergedClasspath(result)
     descriptorResources.forEach { (relativePath, contents) ->
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
index efc6bf0..1909e41 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
@@ -27,6 +27,7 @@
 import androidx.privacysandbox.tools.core.model.Types.asNullable
 import androidx.privacysandbox.tools.core.model.ValueProperty
 import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertCompiles
+import androidx.privacysandbox.tools.testing.allTestLibraryStubs
 import androidx.room.compiler.processing.util.Source
 import androidx.testutils.assertThrows
 import com.google.common.truth.Truth.assertThat
@@ -39,34 +40,47 @@
     @Test
     fun annotatedInterface_isParsed() {
         val source = Source.kotlin(
-            "com/mysdk/TestSandboxSdk.kt", """
-                    package com.mysdk
-                    import androidx.privacysandbox.tools.PrivacySandboxCallback
-                    import androidx.privacysandbox.tools.PrivacySandboxInterface
-                    import androidx.privacysandbox.tools.PrivacySandboxService
-                    import androidx.privacysandbox.tools.PrivacySandboxValue
-                    @PrivacySandboxService
-                    interface MySdk {
-                      fun doSomething(magicNumber: Int, awesomeString: String?)
-                      suspend fun getPayload(request: PayloadRequest): PayloadResponse
-                      suspend fun getInterface(): MyInterface
-                      suspend fun processList(list: List<Long>): List<Long>
-                    }
-                    @PrivacySandboxInterface
-                    interface MyInterface {
-                      suspend fun getMorePayload(request: PayloadRequest): PayloadResponse
-                    }
-                    @PrivacySandboxValue
-                    data class PayloadType(val size: Long, val appId: String)
-                    @PrivacySandboxValue
-                    data class PayloadResponse(val url: String)
-                    @PrivacySandboxValue
-                    data class PayloadRequest(val type: PayloadType)
-                    @PrivacySandboxCallback
-                    interface CustomCallback {
-                      fun onComplete(status: Int)
-                    }
-                """,
+            "com/mysdk/TestSandboxSdk.kt",
+            """
+                    |package com.mysdk
+                    |
+                    |import androidx.privacysandbox.tools.PrivacySandboxCallback
+                    |import androidx.privacysandbox.tools.PrivacySandboxInterface
+                    |import androidx.privacysandbox.tools.PrivacySandboxService
+                    |import androidx.privacysandbox.tools.PrivacySandboxValue
+                    |import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+                    |
+                    |@PrivacySandboxService
+                    |interface MySdk {
+                    |  fun doSomething(magicNumber: Int, awesomeString: String?)
+                    |  suspend fun getPayload(request: PayloadRequest): PayloadResponse
+                    |  suspend fun getInterface(): MyInterface
+                    |  suspend fun getUiInterface(): MyUiInterface
+                    |  suspend fun processList(list: List<Long>): List<Long>
+                    |}
+                    |
+                    |@PrivacySandboxInterface
+                    |interface MyInterface {
+                    |  suspend fun getMorePayload(request: PayloadRequest): PayloadResponse
+                    |}
+                    |
+                    |@PrivacySandboxInterface
+                    |interface MyUiInterface : SandboxedUiAdapter {}
+                    |
+                    |@PrivacySandboxValue
+                    |data class PayloadType(val size: Long, val appId: String)
+                    |
+                    |@PrivacySandboxValue
+                    |data class PayloadResponse(val url: String)
+                    |
+                    |@PrivacySandboxValue
+                    |data class PayloadRequest(val type: PayloadType)
+                    |
+                    |@PrivacySandboxCallback
+                    |interface CustomCallback {
+                    |  fun onComplete(status: Int)
+                    |}
+                """.trimMargin(),
         )
 
         val expectedPayloadType = AnnotatedValue(
@@ -122,6 +136,12 @@
                         isSuspend = true,
                     ),
                     Method(
+                        name = "getUiInterface",
+                        parameters = listOf(),
+                        returnType = Type("com.mysdk", "MyUiInterface"),
+                        isSuspend = true,
+                    ),
+                    Method(
                         name = "processList",
                         parameters = listOf(
                             Parameter(
@@ -134,7 +154,7 @@
                     ),
                 )
             )
-        val expectedInterface =
+        val expectedInterfaces = listOf(
             AnnotatedInterface(
                 type = Type(packageName = "com.mysdk", simpleName = "MyInterface"),
                 methods = listOf(
@@ -150,7 +170,13 @@
                         isSuspend = true,
                     )
                 )
-            )
+            ),
+            AnnotatedInterface(
+                type = Type(packageName = "com.mysdk", simpleName = "MyUiInterface"),
+                superTypes = listOf(Types.sandboxedUiAdapter),
+                methods = listOf(),
+            ),
+        )
         val expectedCallback = AnnotatedInterface(
             type = Type(packageName = "com.mysdk", simpleName = "CustomCallback"),
                 methods = listOf(
@@ -176,7 +202,7 @@
             expectedPayloadResponse,
         )
         assertThat(actualApi.callbacks).containsExactly(expectedCallback)
-        assertThat(actualApi.interfaces).containsExactly(expectedInterface)
+        assertThat(actualApi.interfaces).containsExactlyElementsIn(expectedInterfaces)
     }
 
     @Test
@@ -378,7 +404,7 @@
     }
 
     private fun compileAndParseApi(vararg sources: Source): ParsedApi {
-        val classpath = mergedClasspath(assertCompiles(sources.toList()))
+        val classpath = mergedClasspath(assertCompiles(sources.toList() + allTestLibraryStubs))
         return ApiStubParser.parse(classpath)
     }
 }
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
index 8ace244..b64faf5 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
@@ -2,6 +2,7 @@
 
 import androidx.privacysandbox.tools.PrivacySandboxInterface
 import androidx.privacysandbox.tools.PrivacySandboxService
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
 
 @PrivacySandboxService
 interface MySdk {
@@ -20,6 +21,6 @@
 }
 
 @PrivacySandboxInterface
-interface MySecondInterface {
+interface MySecondInterface : SandboxedUiAdapter {
    fun doStuff()
 }
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterface.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterface.kt
index b858ed5..0505e08 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterface.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterface.kt
@@ -1,5 +1,7 @@
 package com.sdk
 
-public interface MySecondInterface {
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+
+public interface MySecondInterface : SandboxedUiAdapter {
     public fun doStuff(): Unit
 }
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterfaceClientProxy.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterfaceClientProxy.kt
index 67e7d28a..9880002 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterfaceClientProxy.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MySecondInterfaceClientProxy.kt
@@ -1,9 +1,27 @@
 package com.sdk
 
+import android.content.Context
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter.SessionClient
+import java.util.concurrent.Executor
+
 public class MySecondInterfaceClientProxy(
     public val remote: IMySecondInterface,
+    public val sandboxedUiAdapter: SandboxedUiAdapter,
 ) : MySecondInterface {
     public override fun doStuff(): Unit {
         remote.doStuff()
     }
+
+    public override fun openSession(
+        context: Context,
+        initialWidth: Int,
+        initialHeight: Int,
+        isZOrderOnTop: Boolean,
+        clientExecutor: Executor,
+        client: SandboxedUiAdapter.SessionClient,
+    ): Unit {
+        sandboxedUiAdapter.openSession(context, initialWidth, initialHeight, isZOrderOnTop,
+                clientExecutor, client)
+    }
 }
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/ClientProxyTypeGenerator.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/ClientProxyTypeGenerator.kt
index 43b9abe..49d0853 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/ClientProxyTypeGenerator.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/ClientProxyTypeGenerator.kt
@@ -21,11 +21,13 @@
 import androidx.privacysandbox.tools.core.generator.SpecNames.suspendCancellableCoroutineMethod
 import androidx.privacysandbox.tools.core.model.AnnotatedInterface
 import androidx.privacysandbox.tools.core.model.Method
+import androidx.privacysandbox.tools.core.model.Types
 import com.squareup.kotlinpoet.ClassName
 import com.squareup.kotlinpoet.CodeBlock
 import com.squareup.kotlinpoet.FileSpec
 import com.squareup.kotlinpoet.FunSpec
 import com.squareup.kotlinpoet.KModifier
+import com.squareup.kotlinpoet.ParameterSpec
 import com.squareup.kotlinpoet.PropertySpec
 import com.squareup.kotlinpoet.TypeSpec
 import com.squareup.kotlinpoet.joinToCode
@@ -34,24 +36,34 @@
     private val basePackageName: String,
     private val binderCodeConverter: BinderCodeConverter
 ) {
-    private val cancellationSignalClassName =
-        ClassName(basePackageName, "ICancellationSignal")
+    private val cancellationSignalClassName = ClassName(basePackageName, "ICancellationSignal")
+    private val sandboxedUiAdapterPropertyName = "sandboxedUiAdapter"
 
     fun generate(annotatedInterface: AnnotatedInterface): FileSpec {
         val className = annotatedInterface.clientProxyNameSpec().simpleName
         val remoteBinderClassName = annotatedInterface.aidlType().innerType.poetTypeName()
+        val inheritsUiAdapter = annotatedInterface.superTypes.contains(Types.sandboxedUiAdapter)
 
         val classSpec = TypeSpec.classBuilder(className).build {
             addSuperinterface(annotatedInterface.type.poetTypeName())
 
-            primaryConstructor(
-                listOf(
+            primaryConstructor(buildList {
+                add(
                     PropertySpec.builder("remote", remoteBinderClassName)
                         .addModifiers(KModifier.PUBLIC).build()
                 )
-            )
+                if (inheritsUiAdapter) add(
+                    PropertySpec.builder(
+                        sandboxedUiAdapterPropertyName, Types.sandboxedUiAdapter.poetTypeName()
+                    ).addModifiers(KModifier.PUBLIC).build()
+                )
+            })
 
             addFunctions(annotatedInterface.methods.map(::toFunSpec))
+
+            if (inheritsUiAdapter) {
+                addFunction(generateOpenSession())
+            }
         }
 
         return FileSpec.builder(annotatedInterface.type.packageName, className).build {
@@ -94,6 +106,28 @@
             addCode(generateRemoteCall(method))
         }
 
+    private fun generateOpenSession() = FunSpec.builder("openSession").build {
+        addModifiers(KModifier.OVERRIDE)
+        addParameters(
+            listOf(
+                ParameterSpec("context", ClassName("android.content", "Context")),
+                ParameterSpec("initialWidth", Types.int.poetClassName()),
+                ParameterSpec("initialHeight", Types.int.poetClassName()),
+                ParameterSpec("isZOrderOnTop", Types.boolean.poetClassName()),
+                ParameterSpec("clientExecutor", ClassName("java.util.concurrent", "Executor")),
+                ParameterSpec(
+                    "client", ClassName(
+                        "androidx.privacysandbox.ui.core", "SandboxedUiAdapter.SessionClient"
+                    )
+                ),
+            )
+        )
+        addStatement(
+            "$sandboxedUiAdapterPropertyName.openSession(context, initialWidth, initialHeight, " +
+                "isZOrderOnTop, clientExecutor, client)"
+        )
+    }
+
     private fun generateTransactionCallbackObject(method: Method) = CodeBlock.builder().build {
         val transactionCallbackClassName = ClassName(
             basePackageName,
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/LibraryStubs.kt b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt
similarity index 98%
rename from privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/LibraryStubs.kt
rename to privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt
index b9e9314..b51203a 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/util/LibraryStubs.kt
+++ b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package androidx.privacysandbox.tools.apicompiler.util
+package androidx.privacysandbox.tools.testing
 
 import androidx.room.compiler.processing.util.Source
 
diff --git a/privacysandbox/ui/ui-client/api/current.txt b/privacysandbox/ui/ui-client/api/current.txt
index e6f50d0..e6beb91 100644
--- a/privacysandbox/ui/ui-client/api/current.txt
+++ b/privacysandbox/ui/ui-client/api/current.txt
@@ -1 +1,10 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.client {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class SandboxedUiAdapterFactory {
+    method public androidx.privacysandbox.ui.core.SandboxedUiAdapter createFromCoreLibInfo(android.os.Bundle coreLibInfo);
+    field public static final androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory INSTANCE;
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-client/api/public_plus_experimental_current.txt b/privacysandbox/ui/ui-client/api/public_plus_experimental_current.txt
index e6f50d0..e6beb91 100644
--- a/privacysandbox/ui/ui-client/api/public_plus_experimental_current.txt
+++ b/privacysandbox/ui/ui-client/api/public_plus_experimental_current.txt
@@ -1 +1,10 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.client {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class SandboxedUiAdapterFactory {
+    method public androidx.privacysandbox.ui.core.SandboxedUiAdapter createFromCoreLibInfo(android.os.Bundle coreLibInfo);
+    field public static final androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory INSTANCE;
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-client/api/restricted_current.txt b/privacysandbox/ui/ui-client/api/restricted_current.txt
index e6f50d0..e6beb91 100644
--- a/privacysandbox/ui/ui-client/api/restricted_current.txt
+++ b/privacysandbox/ui/ui-client/api/restricted_current.txt
@@ -1 +1,10 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.client {
+
+  @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public final class SandboxedUiAdapterFactory {
+    method public androidx.privacysandbox.ui.core.SandboxedUiAdapter createFromCoreLibInfo(android.os.Bundle coreLibInfo);
+    field public static final androidx.privacysandbox.ui.client.SandboxedUiAdapterFactory INSTANCE;
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-client/build.gradle b/privacysandbox/ui/ui-client/build.gradle
index 82beabb..918c043 100644
--- a/privacysandbox/ui/ui-client/build.gradle
+++ b/privacysandbox/ui/ui-client/build.gradle
@@ -24,7 +24,8 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+    implementation project(path: ':privacysandbox:ui:ui-core')
+    implementation project(path: ':annotation:annotation')
 }
 
 android {
diff --git a/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/SandboxedUiAdapterFactory.kt b/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/SandboxedUiAdapterFactory.kt
new file mode 100644
index 0000000..f87ab3d
--- /dev/null
+++ b/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/SandboxedUiAdapterFactory.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.privacysandbox.ui.client
+
+import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Binder
+import android.os.Build
+import android.os.Bundle
+import android.view.Display
+import android.view.SurfaceControlViewHost
+import android.view.SurfaceView
+import android.view.View
+import androidx.annotation.RequiresApi
+import androidx.privacysandbox.ui.core.IRemoteSessionClient
+import androidx.privacysandbox.ui.core.IRemoteSessionController
+import androidx.privacysandbox.ui.core.ISandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import java.util.concurrent.Executor
+
+/**
+ * Provides an adapter created from the supplied Bundle which acts as a proxy between the host app
+ * and Binder provided by the provider of content.
+ * @throws IllegalArgumentException if CoreLibInfo does not contain a Binder with the key
+ * uiAdapterBinder
+ */
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+object SandboxedUiAdapterFactory {
+    // Bundle key is a binary compatibility requirement
+    private const val UI_ADAPTER_BINDER = "uiAdapterBinder"
+    fun createFromCoreLibInfo(coreLibInfo: Bundle): SandboxedUiAdapter {
+        val uiAdapterBinder = requireNotNull(coreLibInfo.getBinder(UI_ADAPTER_BINDER)) {
+            "Invalid CoreLibInfo bundle, missing $UI_ADAPTER_BINDER."
+        }
+        val adapterInterface = ISandboxedUiAdapter.Stub.asInterface(
+            uiAdapterBinder
+        )
+        return RemoteAdapter(adapterInterface)
+    }
+
+    private class RemoteAdapter(private val adapterInterface: ISandboxedUiAdapter) :
+        SandboxedUiAdapter {
+
+        override fun openSession(
+            context: Context,
+            initialWidth: Int,
+            initialHeight: Int,
+            isZOrderOnTop: Boolean,
+            clientExecutor: Executor,
+            client: SandboxedUiAdapter.SessionClient
+        ) {
+            val mDisplayManager =
+                context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+            val displayId = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).displayId
+
+            adapterInterface.openRemoteSession(
+                Binder(), // Host Token
+                displayId,
+                initialWidth,
+                initialHeight,
+                isZOrderOnTop,
+                RemoteSessionClient(context, client, clientExecutor)
+            )
+        }
+
+        class RemoteSessionClient(
+            val context: Context,
+            val client: SandboxedUiAdapter.SessionClient,
+            val clientExecutor: Executor
+        ) : IRemoteSessionClient.Stub() {
+
+            override fun onRemoteSessionOpened(
+                surfacePackage: SurfaceControlViewHost.SurfacePackage,
+                remoteSessionController: IRemoteSessionController,
+                isZOrderOnTop: Boolean
+            ) {
+                val surfaceView = SurfaceView(context)
+                surfaceView.setChildSurfacePackage(surfacePackage)
+                surfaceView.setZOrderOnTop(isZOrderOnTop)
+
+                clientExecutor.execute {
+                    client.onSessionOpened(SessionImpl(surfaceView, remoteSessionController))
+                }
+            }
+
+            override fun onRemoteSessionError(errorString: String) {
+                clientExecutor.execute {
+                    client.onSessionError(Throwable(errorString))
+                }
+            }
+        }
+
+        private class SessionImpl(
+            val surfaceView: SurfaceView,
+            val remoteSessionController: IRemoteSessionController
+        ) : SandboxedUiAdapter.Session {
+
+            override val view: View = surfaceView
+
+            override fun close() {
+                remoteSessionController.close()
+            }
+        }
+    }
+}
diff --git a/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-client-documentation.md b/privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/androidx-privacysandbox-ui-ui-client-documentation.md
similarity index 100%
rename from privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-client-documentation.md
rename to privacysandbox/ui/ui-client/src/main/java/androidx/privacysandbox/ui/client/androidx-privacysandbox-ui-ui-client-documentation.md
diff --git a/privacysandbox/ui/ui-core/api/current.txt b/privacysandbox/ui/ui-core/api/current.txt
index e6f50d0..3ab33d6 100644
--- a/privacysandbox/ui/ui-core/api/current.txt
+++ b/privacysandbox/ui/ui-core/api/current.txt
@@ -1 +1,27 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.core {
+
+  public interface SandboxedUiAdapter {
+    method public void openSession(android.content.Context context, int initialWidth, int initialHeight, boolean isZOrderOnTop, java.util.concurrent.Executor clientExecutor, androidx.privacysandbox.ui.core.SandboxedUiAdapter.SessionClient client);
+  }
+
+  public static interface SandboxedUiAdapter.Session {
+    method public void close();
+    method public android.view.View getView();
+    property public abstract android.view.View view;
+  }
+
+  public static interface SandboxedUiAdapter.SessionClient {
+    method public void onSessionError(Throwable throwable);
+    method public void onSessionOpened(androidx.privacysandbox.ui.core.SandboxedUiAdapter.Session session);
+  }
+
+  public final class SdkRuntimeUiLibVersions {
+    method public int getClientVersion();
+    property public final int clientVersion;
+    field public static final androidx.privacysandbox.ui.core.SdkRuntimeUiLibVersions INSTANCE;
+    field public static final int apiVersion = 1; // 0x1
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-core/api/public_plus_experimental_current.txt b/privacysandbox/ui/ui-core/api/public_plus_experimental_current.txt
index e6f50d0..3ab33d6 100644
--- a/privacysandbox/ui/ui-core/api/public_plus_experimental_current.txt
+++ b/privacysandbox/ui/ui-core/api/public_plus_experimental_current.txt
@@ -1 +1,27 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.core {
+
+  public interface SandboxedUiAdapter {
+    method public void openSession(android.content.Context context, int initialWidth, int initialHeight, boolean isZOrderOnTop, java.util.concurrent.Executor clientExecutor, androidx.privacysandbox.ui.core.SandboxedUiAdapter.SessionClient client);
+  }
+
+  public static interface SandboxedUiAdapter.Session {
+    method public void close();
+    method public android.view.View getView();
+    property public abstract android.view.View view;
+  }
+
+  public static interface SandboxedUiAdapter.SessionClient {
+    method public void onSessionError(Throwable throwable);
+    method public void onSessionOpened(androidx.privacysandbox.ui.core.SandboxedUiAdapter.Session session);
+  }
+
+  public final class SdkRuntimeUiLibVersions {
+    method public int getClientVersion();
+    property public final int clientVersion;
+    field public static final androidx.privacysandbox.ui.core.SdkRuntimeUiLibVersions INSTANCE;
+    field public static final int apiVersion = 1; // 0x1
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-core/api/restricted_current.txt b/privacysandbox/ui/ui-core/api/restricted_current.txt
index e6f50d0..3ab33d6 100644
--- a/privacysandbox/ui/ui-core/api/restricted_current.txt
+++ b/privacysandbox/ui/ui-core/api/restricted_current.txt
@@ -1 +1,27 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.core {
+
+  public interface SandboxedUiAdapter {
+    method public void openSession(android.content.Context context, int initialWidth, int initialHeight, boolean isZOrderOnTop, java.util.concurrent.Executor clientExecutor, androidx.privacysandbox.ui.core.SandboxedUiAdapter.SessionClient client);
+  }
+
+  public static interface SandboxedUiAdapter.Session {
+    method public void close();
+    method public android.view.View getView();
+    property public abstract android.view.View view;
+  }
+
+  public static interface SandboxedUiAdapter.SessionClient {
+    method public void onSessionError(Throwable throwable);
+    method public void onSessionOpened(androidx.privacysandbox.ui.core.SandboxedUiAdapter.Session session);
+  }
+
+  public final class SdkRuntimeUiLibVersions {
+    method public int getClientVersion();
+    property public final int clientVersion;
+    field public static final androidx.privacysandbox.ui.core.SdkRuntimeUiLibVersions INSTANCE;
+    field public static final int apiVersion = 1; // 0x1
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-core/build.gradle b/privacysandbox/ui/ui-core/build.gradle
index 4e0e9bd..f0b88cd 100644
--- a/privacysandbox/ui/ui-core/build.gradle
+++ b/privacysandbox/ui/ui-core/build.gradle
@@ -24,11 +24,21 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+    implementation 'androidx.annotation:annotation:1.5.0'
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.kotlinStdlib)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.truth)
 }
 
 android {
     namespace "androidx.privacysandbox.ui.core"
+    buildFeatures {
+        aidl = true
+    }
 }
 
 androidx {
diff --git a/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionClient.aidl b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionClient.aidl
new file mode 100644
index 0000000..63a66c1
--- /dev/null
+++ b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionClient.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.privacysandbox.ui.core;
+
+import androidx.privacysandbox.ui.core.IRemoteSessionController;
+import android.view.SurfaceControlViewHost.SurfacePackage;
+
+/** @hide */
+oneway interface IRemoteSessionClient {
+    void onRemoteSessionOpened(in SurfacePackage surfacePackage,
+        IRemoteSessionController remoteSessionController, boolean isZOrderOnTop);
+    void onRemoteSessionError(String exception);
+}
\ No newline at end of file
diff --git a/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionController.aidl b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionController.aidl
new file mode 100644
index 0000000..b64a992
--- /dev/null
+++ b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/IRemoteSessionController.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.privacysandbox.ui.core;
+
+/** @hide */
+oneway interface IRemoteSessionController {
+    void close();
+}
\ No newline at end of file
diff --git a/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/ISandboxedUiAdapter.aidl b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/ISandboxedUiAdapter.aidl
new file mode 100644
index 0000000..a452da6
--- /dev/null
+++ b/privacysandbox/ui/ui-core/src/main/aidl/androidx/privacysandbox/ui/core/ISandboxedUiAdapter.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.privacysandbox.ui.core;
+
+import androidx.privacysandbox.ui.core.IRemoteSessionClient;
+import android.content.Context;
+
+/** @hide */
+oneway interface ISandboxedUiAdapter {
+    void openRemoteSession(
+        IBinder hostToken, int displayId, int initialWidth, int initialHeight, boolean isZOrderOnTop,
+        IRemoteSessionClient remoteSessionClient);
+}
\ No newline at end of file
diff --git a/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SandboxedUiAdapter.kt b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SandboxedUiAdapter.kt
new file mode 100644
index 0000000..c6751e3
--- /dev/null
+++ b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SandboxedUiAdapter.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.privacysandbox.ui.core
+
+import android.content.Context
+import android.view.View
+import java.util.concurrent.Executor
+
+/**
+ * An Adapter that provides content from a SandboxedSdk to be displayed as part of a host app's UI.
+ */
+
+interface SandboxedUiAdapter {
+
+    /**
+     * Open a new session for displaying content with an initial size of
+     * [initialWidth]x[initialHeight] pixels. [client] will receive all incoming communication from
+     * the provider of content. All incoming calls to [client] will be made through the provided
+     * [clientExecutor]. [isZOrderOnTop] tracks if the content surface will be placed on top of its
+     * window
+     */
+    fun openSession(
+        context: Context,
+        initialWidth: Int,
+        initialHeight: Int,
+        isZOrderOnTop: Boolean,
+        clientExecutor: Executor,
+        client: SessionClient
+    )
+
+    /**
+     * A single session with the provider of remote content.
+     */
+    interface Session {
+
+        /**
+         * Return the [View] that presents content for this session. The same view will be returned
+         * for the life of the session object. Accessing [view] after [close] may throw an
+         * [IllegalStateException].
+         */
+        val view: View
+
+        /**
+         * Close this session, indicating that the remote provider of content should
+         * dispose of associated resources and that the [SessionClient] should not
+         * receive further callback events.
+         */
+        fun close()
+    }
+
+    /**
+     * The client of a single session that will receive callback events from an active session.
+     */
+    interface SessionClient {
+        /**
+         * Called to report that the session was opened successfully, delivering the [Session]
+         * handle that should be used to notify the session of UI events.
+         */
+        fun onSessionOpened(session: Session)
+
+        /**
+         * Called to report a terminal error in the session. No further events will be reported
+         * to this [SessionClient] and any further or currently pending calls to the [Session]
+         * that may have been in flight may be ignored.
+         */
+        fun onSessionError(throwable: Throwable)
+    }
+}
diff --git a/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SdkRuntimeUiLibVersions.kt b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SdkRuntimeUiLibVersions.kt
new file mode 100644
index 0000000..ce0f622
--- /dev/null
+++ b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/SdkRuntimeUiLibVersions.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.privacysandbox.ui.core
+
+import androidx.annotation.RestrictTo
+
+object SdkRuntimeUiLibVersions {
+    var clientVersion: Int = -1
+        /**
+         * @hide
+         */
+        @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+        set
+
+    const val apiVersion: Int = 1
+}
\ No newline at end of file
diff --git a/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-core-documentation.md b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/androidx-privacysandbox-ui-ui-core-documentation.md
similarity index 99%
rename from privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-core-documentation.md
rename to privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/androidx-privacysandbox-ui-ui-core-documentation.md
index aa56a66..df34ca3 100644
--- a/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-core-documentation.md
+++ b/privacysandbox/ui/ui-core/src/main/java/androidx/privacysandbox/ui/core/androidx-privacysandbox-ui-ui-core-documentation.md
@@ -3,5 +3,6 @@
 Privacy Sandbox Ui Core
 
 # Package androidx.privacysandbox.ui.core
+
 This package contains interface and class definitions shared between Privacy
 Sandbox Ui Client and Privacy Sandbox Ui Provider.
diff --git a/privacysandbox/ui/ui-provider/api/current.txt b/privacysandbox/ui/ui-provider/api/current.txt
index e6f50d0..20170b4 100644
--- a/privacysandbox/ui/ui-provider/api/current.txt
+++ b/privacysandbox/ui/ui-provider/api/current.txt
@@ -1 +1,9 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.provider {
+
+  @RequiresApi(33) public final class SandboxedUiAdapterProxy {
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static android.os.Bundle toCoreLibInfo(androidx.privacysandbox.ui.core.SandboxedUiAdapter, android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-provider/api/public_plus_experimental_current.txt b/privacysandbox/ui/ui-provider/api/public_plus_experimental_current.txt
index e6f50d0..20170b4 100644
--- a/privacysandbox/ui/ui-provider/api/public_plus_experimental_current.txt
+++ b/privacysandbox/ui/ui-provider/api/public_plus_experimental_current.txt
@@ -1 +1,9 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.provider {
+
+  @RequiresApi(33) public final class SandboxedUiAdapterProxy {
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static android.os.Bundle toCoreLibInfo(androidx.privacysandbox.ui.core.SandboxedUiAdapter, android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-provider/api/restricted_current.txt b/privacysandbox/ui/ui-provider/api/restricted_current.txt
index e6f50d0..20170b4 100644
--- a/privacysandbox/ui/ui-provider/api/restricted_current.txt
+++ b/privacysandbox/ui/ui-provider/api/restricted_current.txt
@@ -1 +1,9 @@
 // Signature format: 4.0
+package androidx.privacysandbox.ui.provider {
+
+  @RequiresApi(33) public final class SandboxedUiAdapterProxy {
+    method @RequiresApi(android.os.Build.VERSION_CODES.TIRAMISU) public static android.os.Bundle toCoreLibInfo(androidx.privacysandbox.ui.core.SandboxedUiAdapter, android.content.Context context);
+  }
+
+}
+
diff --git a/privacysandbox/ui/ui-provider/build.gradle b/privacysandbox/ui/ui-provider/build.gradle
index 6b2b1324..bcbd719 100644
--- a/privacysandbox/ui/ui-provider/build.gradle
+++ b/privacysandbox/ui/ui-provider/build.gradle
@@ -24,7 +24,15 @@
 
 dependencies {
     api(libs.kotlinStdlib)
-    // Add dependencies here
+    implementation project(path: ':privacysandbox:ui:ui-core')
+    implementation project(path: ':annotation:annotation')
+    androidTestImplementation(libs.junit)
+    androidTestImplementation(libs.kotlinStdlib)
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testCore)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.testRules)
+    androidTestImplementation(libs.truth)
 }
 
 android {
diff --git a/privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/provider/BinderAdapterDelegate.kt b/privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/provider/BinderAdapterDelegate.kt
new file mode 100644
index 0000000..84149c0
--- /dev/null
+++ b/privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/provider/BinderAdapterDelegate.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@file:RequiresApi(Build.VERSION_CODES.TIRAMISU)
+@file:JvmName("SandboxedUiAdapterProxy")
+
+package androidx.privacysandbox.ui.provider
+
+import android.content.Context
+import android.hardware.display.DisplayManager
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.IBinder
+import android.os.Looper
+import android.view.SurfaceControlViewHost
+import androidx.annotation.RequiresApi
+import androidx.annotation.VisibleForTesting
+import androidx.privacysandbox.ui.core.IRemoteSessionClient
+import androidx.privacysandbox.ui.core.IRemoteSessionController
+import androidx.privacysandbox.ui.core.ISandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import java.util.concurrent.Executor
+
+/**
+ * Provides a [Bundle] containing a Binder which represents a [SandboxedUiAdapter]. The Bundle
+ * is shuttled to the host app in order for the [SandboxedUiAdapter] to be used to retrieve
+ * content.
+ */
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+fun SandboxedUiAdapter.toCoreLibInfo(@Suppress("ContextFirst") context: Context): Bundle {
+    val binderAdapter = BinderAdapterDelegate(context, this)
+    // TODO: Add version info
+    val bundle = Bundle()
+    // Bundle key is a binary compatibility requirement
+    bundle.putBinder("uiAdapterBinder", binderAdapter)
+    return bundle
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+private class BinderAdapterDelegate(
+    private val sandboxContext: Context,
+    private val adapter: SandboxedUiAdapter
+) : ISandboxedUiAdapter.Stub() {
+
+    fun openSession(
+        context: Context,
+        initialWidth: Int,
+        initialHeight: Int,
+        isZOrderOnTop: Boolean,
+        clientExecutor: Executor,
+        client: SandboxedUiAdapter.SessionClient
+    ) {
+        adapter.openSession(
+            context, initialWidth, initialHeight, isZOrderOnTop, clientExecutor,
+            client
+        )
+    }
+
+    override fun openRemoteSession(
+        hostToken: IBinder,
+        displayId: Int,
+        initialWidth: Int,
+        initialHeight: Int,
+        isZOrderOnTop: Boolean,
+        remoteSessionClient: IRemoteSessionClient
+    ) {
+        val mHandler = Handler(Looper.getMainLooper())
+        mHandler.post {
+            try {
+                val mDisplayManager: DisplayManager =
+                    sandboxContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+                val windowContext =
+                    sandboxContext.createDisplayContext(mDisplayManager.getDisplay(displayId))
+                val surfaceControlViewHost = SurfaceControlViewHost(
+                    windowContext,
+                    mDisplayManager.getDisplay(displayId), hostToken
+                )
+                val sessionClient = SessionClientProxy(
+                    surfaceControlViewHost, initialWidth, initialHeight, remoteSessionClient
+                )
+                openSession(
+                    windowContext, initialWidth, initialHeight, isZOrderOnTop,
+                    Runnable::run, sessionClient
+                )
+            } catch (exception: Throwable) {
+                remoteSessionClient.onRemoteSessionError(exception.message)
+            }
+        }
+    }
+
+    private inner class SessionClientProxy(
+        private val surfaceControlViewHost: SurfaceControlViewHost,
+        private val initialWidth: Int,
+        private val initialHeight: Int,
+        private val remoteSessionClient: IRemoteSessionClient
+    ) : SandboxedUiAdapter.SessionClient {
+
+        override fun onSessionOpened(session: SandboxedUiAdapter.Session) {
+            val view = session.view
+            surfaceControlViewHost.setView(view, initialWidth, initialHeight)
+            val surfacePackage = surfaceControlViewHost.surfacePackage
+            val remoteSessionController =
+                RemoteSessionController(surfaceControlViewHost, session)
+            remoteSessionClient.onRemoteSessionOpened(
+                surfacePackage, remoteSessionController,
+                /* isZOrderOnTop= */ true
+            )
+        }
+
+        override fun onSessionError(throwable: Throwable) {
+            remoteSessionClient.onRemoteSessionError(throwable.message)
+        }
+
+        @VisibleForTesting
+        private inner class RemoteSessionController(
+            val surfaceControlViewHost: SurfaceControlViewHost,
+            val session: SandboxedUiAdapter.Session
+        ) : IRemoteSessionController.Stub() {
+            override fun close() {
+                session.close()
+                surfaceControlViewHost.release()
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-provider-documentation.md b/privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/provider/androidx-privacysandbox-ui-ui-provider-documentation.md
similarity index 100%
rename from privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/androidx-privacysandbox-ui-ui-provider-documentation.md
rename to privacysandbox/ui/ui-provider/src/main/java/androidx/privacysandbox/ui/provider/androidx-privacysandbox-ui-ui-provider-documentation.md
diff --git a/settings.gradle b/settings.gradle
index c8a5999..2471fc2d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -365,8 +365,9 @@
 includeProject(":annotation:annotation-experimental-lint")
 includeProject(":annotation:annotation-experimental-lint-integration-tests", "annotation/annotation-experimental-lint/integration-tests")
 includeProject(":annotation:annotation-sampled")
-includeProject(":appactions:interaction:interaction-proto", [BuildType.MAIN])
 includeProject(":appactions:interaction:interaction-capabilities-core", [BuildType.MAIN])
+includeProject(":appactions:interaction:interaction-proto", [BuildType.MAIN])
+includeProject(":appactions:interaction:interaction-service", [BuildType.MAIN])
 includeProject(":appcompat:appcompat", [BuildType.MAIN])
 includeProject(":appcompat:appcompat-benchmark", [BuildType.MAIN])
 includeProject(":appcompat:appcompat-lint", [BuildType.MAIN])
@@ -382,8 +383,8 @@
 includeProject(":appsearch:appsearch-local-storage", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-platform-storage", [BuildType.MAIN])
 includeProject(":appsearch:appsearch-test-util", [BuildType.MAIN])
-includeProject(":arch:core:core-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":arch:core:core-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":arch:core:core-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":arch:core:core-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":arch:core:core-testing", [BuildType.MAIN])
 includeProject(":asynclayoutinflater:asynclayoutinflater", [BuildType.MAIN])
 includeProject(":asynclayoutinflater:asynclayoutinflater-appcompat", [BuildType.MAIN])
@@ -399,6 +400,13 @@
 includeProject(":benchmark:benchmark-junit4")
 includeProject(":benchmark:benchmark-macro", [BuildType.MAIN, BuildType.COMPOSE])
 includeProject(":benchmark:benchmark-macro-junit4", [BuildType.MAIN, BuildType.COMPOSE])
+includeProject(":benchmark:integration-tests:baselineprofiles-producer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-consumer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-flavors-producer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-flavors-consumer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-library-consumer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-library-producer", [BuildType.MAIN])
+includeProject(":benchmark:integration-tests:baselineprofiles-library-build-provider", [BuildType.MAIN])
 includeProject(":benchmark:integration-tests:dry-run-benchmark", [BuildType.MAIN])
 includeProject(":benchmark:integration-tests:macrobenchmark", [BuildType.MAIN])
 includeProject(":benchmark:integration-tests:macrobenchmark-target", [BuildType.MAIN])
@@ -715,33 +723,33 @@
 includeProject(":lifecycle:integration-tests:incrementality", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:integration-tests:lifecycle-testapp", "lifecycle/integration-tests/testapp", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:integration-tests:lifecycle-testapp-kotlin", "lifecycle/integration-tests/kotlintestapp", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-common-java8", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-common", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-common-java8", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-compiler", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-extensions", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-livedata", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-livedata-core", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-livedata-core-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-livedata-core-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-livedata", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-livedata-core", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-livedata-core-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-livedata-core-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-livedata-core-truth", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-livedata-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-livedata-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-process", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-reactivestreams", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":lifecycle:lifecycle-reactivestreams-ktx", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-runtime", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-runtime-compose", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-runtime-compose:lifecycle-runtime-compose-samples", "lifecycle/lifecycle-runtime-compose/samples", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-runtime-compose:integration-tests:lifecycle-runtime-compose-demos", [BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-runtime-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-runtime-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-runtime-testing", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-runtime-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-runtime-ktx-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-runtime-testing", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-service", [BuildType.MAIN, BuildType.FLAN])
-includeProject(":lifecycle:lifecycle-viewmodel", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-viewmodel", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lifecycle:lifecycle-viewmodel-compose", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-viewmodel-compose:lifecycle-viewmodel-compose-samples", "lifecycle/lifecycle-viewmodel-compose/samples", [BuildType.COMPOSE])
 includeProject(":lifecycle:lifecycle-viewmodel-compose:integration-tests:lifecycle-viewmodel-demos", [BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-viewmodel-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
-includeProject(":lifecycle:lifecycle-viewmodel-savedstate", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE])
+includeProject(":lifecycle:lifecycle-viewmodel-ktx", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
+includeProject(":lifecycle:lifecycle-viewmodel-savedstate", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR, BuildType.COMPOSE, BuildType.CAMERA])
 includeProject(":lint-checks")
 includeProject(":lint-checks:integration-tests")
 includeProject(":loader:loader", [BuildType.MAIN])
diff --git a/tracing/OWNERS b/tracing/OWNERS
index 5db1872..9b3f90f 100644
--- a/tracing/OWNERS
+++ b/tracing/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 873508
 ccraik@google.com
 jgielzak@google.com
 rahulrav@google.com
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index f826f7d..2d08931 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -27,7 +27,7 @@
         minSdk 25
         targetSdk 30
         versionCode 12
-        versionName "1.11"
+        versionName "1.12"
         // Change the APK name to match the *testapp regex we use to pick up APKs for testing as
         // part of CI.
         archivesBaseName = "wear-compose-demos-testapp"
diff --git a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
index 4ece658..88edba6 100644
--- a/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
+++ b/wear/watchface/watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
@@ -16,6 +16,7 @@
 
 package androidx.wear.watchface.editor
 
+import androidx.wear.watchface.data.DeviceConfig as WireDeviceConfig
 import android.annotation.SuppressLint
 import android.app.Activity
 import android.content.ComponentName
@@ -47,8 +48,6 @@
 internal const val USER_STYLE_KEY: String = "USER_STYLE_KEY"
 internal const val USER_STYLE_VALUES: String = "USER_STYLE_VALUES"
 
-typealias WireDeviceConfig = androidx.wear.watchface.data.DeviceConfig
-
 /**
  * Parameters for an optional final screenshot taken by [EditorSession] upon exit and reported via
  * [EditorState].
diff --git a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index d160094..84970d4 100644
--- a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -5488,6 +5488,49 @@
     }
 
     @Test
+    public fun updateComplicationTimelineOnly_updatesComplication() {
+        // Arrange
+        initWallpaperInteractiveWatchFaceInstance(complicationSlots = listOf(leftComplication))
+        val defaultBase = WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+            .setLongText(WireComplicationText("default"))
+            .build()
+        val timelineEntryBase = WireComplicationData.Builder(WireComplicationData.TYPE_LONG_TEXT)
+            .setLongText(WireComplicationText("timeline"))
+            .build()
+        val oldTimelineEntry = WireComplicationData.Builder(defaultBase).build().apply {
+            setTimelineEntryCollection(
+                listOf(
+                    WireComplicationData.Builder(timelineEntryBase).build().apply {
+                        timelineStartEpochSecond = 100
+                        timelineEndEpochSecond = 200
+                    }
+                )
+            )
+        }
+        val newTimelineEntry = WireComplicationData.Builder(defaultBase).build().apply {
+            setTimelineEntryCollection(
+                listOf(
+                    WireComplicationData.Builder(timelineEntryBase).build().apply {
+                        timelineStartEpochSecond = 200
+                        timelineEndEpochSecond = 300
+                    }
+                )
+            )
+        }
+        engineWrapper.setComplicationDataList(
+            listOf(IdAndComplicationDataWireFormat(LEFT_COMPLICATION_ID, oldTimelineEntry))
+        )
+        complicationSlotsManager.selectComplicationDataForInstant(Instant.ofEpochSecond(150))
+        // Act
+        engineWrapper.setComplicationDataList(
+            listOf(IdAndComplicationDataWireFormat(LEFT_COMPLICATION_ID, newTimelineEntry))
+        )
+        complicationSlotsManager.selectComplicationDataForInstant(Instant.ofEpochSecond(250))
+        // Assert
+        assertThat(getLeftLongTextComplicationDataText()).isEqualTo("timeline")
+    }
+
+    @Test
     @Config(sdk = [Build.VERSION_CODES.R])
     public fun renderParameters_isScreenshot() {
         initWallpaperInteractiveWatchFaceInstance(
diff --git a/work/OWNERS b/work/OWNERS
index e994ca6..d390fd5 100644
--- a/work/OWNERS
+++ b/work/OWNERS
@@ -1,6 +1,7 @@
-# Bug component: 409906
+# Bug component: 324783
+sergeyv@google.com
 sumir@google.com
 rahulrav@google.com
 ilake@google.com
 
-per-file settings.gradle = dustinlam@google.com, rahulrav@google.com
+per-file settings.gradle = dustinlam@google.com, rahulrav@google.com, sergeyv@google.com
diff --git a/work/work-runtime/src/androidTest/AndroidManifest.xml b/work/work-runtime/src/androidTest/AndroidManifest.xml
index 3f54449..e636ee9 100644
--- a/work/work-runtime/src/androidTest/AndroidManifest.xml
+++ b/work/work-runtime/src/androidTest/AndroidManifest.xml
@@ -17,10 +17,12 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
 
     <!--
-      ~ Adding this permission to the test-app's AndroidManifest.xml. This is because
+      ~ Adding these permissions to the test-app's AndroidManifest.xml. This is because
       ~ we don't want applications to implicitly add this permission on API 31 and above. We only
       ~ need this permission for tests.
     -->
-    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
+    <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
+        android:maxSdkVersion="32"/>
+    <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
     <application android:name="androidx.multidex.MultiDexApplication"/>
 </manifest>
diff --git a/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemalarm/AlarmsTest.java b/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemalarm/AlarmsTest.java
index 2c2aced..164a3ef 100644
--- a/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemalarm/AlarmsTest.java
+++ b/work/work-runtime/src/androidTest/java/androidx/work/impl/background/systemalarm/AlarmsTest.java
@@ -25,11 +25,9 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 
 import android.content.Context;
-import android.os.Build;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SdkSuppress;
 import androidx.test.filters.SmallTest;
 import androidx.work.DatabaseTest;
 import androidx.work.OneTimeWorkRequest;
@@ -51,12 +49,7 @@
     private final long mTriggerAt = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1);
 
     @Test
-    @SdkSuppress(maxSdkVersion = 33) // b/262909049: Failing on SDK 34
     public void testSetAlarm_noPreExistingAlarms() {
-        if (Build.VERSION.SDK_INT == 33 && !"REL".equals(Build.VERSION.CODENAME)) {
-            return; // b/262909049: Do not run this test on pre-release Android U.
-        }
-
         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
         insertWork(work);
         WorkGenerationalId workSpecId = generationalId(work.getWorkSpec());
@@ -67,12 +60,7 @@
     }
 
     @Test
-    @SdkSuppress(maxSdkVersion = 33) // b/262909049: Failing on SDK 34
     public void testSetAlarm_withPreExistingAlarms() {
-        if (Build.VERSION.SDK_INT == 33 && !"REL".equals(Build.VERSION.CODENAME)) {
-            return; // b/262909049: Do not run this test on pre-release Android U.
-        }
-
         OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(TestWorker.class).build();
         insertWork(work);
         WorkGenerationalId workSpecId = generationalId(work.getWorkSpec());