Merge "Bump versions for Beta 1-synced releases" into androidx-platform-dev
diff --git a/appcompat/appcompat/src/androidTest/AndroidManifest.xml b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
index 602c351..cede9fd 100644
--- a/appcompat/appcompat/src/androidTest/AndroidManifest.xml
+++ b/appcompat/appcompat/src/androidTest/AndroidManifest.xml
@@ -317,6 +317,10 @@
             android:theme="@style/Theme.CustomInflater"/>
 
         <activity
+            android:name="androidx.appcompat.app.NoThemeAppCompatActivity"
+            android:theme="@android:style/Theme.Holo.NoActionBar"/>
+
+        <activity
             android:name="androidx.appcompat.widget.ToolbarTestActivity"
             android:theme="@style/Theme.AppCompat.NoActionBar"/>
 
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatActivity.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatActivity.kt
new file mode 100644
index 0000000..e0a6fb8
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatActivity.kt
@@ -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.
+ */
+
+package androidx.appcompat.app
+
+import android.os.Bundle
+
+import androidx.appcompat.test.R
+
+class NoThemeAppCompatActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        // We don't have an AppCompat theme by default, but this
+        // shouldn't create the subDecor - it should just no-op
+        invalidateOptionsMenu()
+
+        super.onCreate(savedInstanceState)
+
+        // Now set the theme to whatever AppCompat theme we have in tests
+        setTheme(R.style.Theme_TextColors)
+
+        // And call setContentView(), which will internally create the subDecor
+        setContentView(R.layout.layout_actv)
+    }
+}
diff --git a/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatTest.kt b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatTest.kt
new file mode 100644
index 0000000..5614e37
--- /dev/null
+++ b/appcompat/appcompat/src/androidTest/java/androidx/appcompat/app/NoThemeAppCompatTest.kt
@@ -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.
+ */
+
+package androidx.appcompat.app
+
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import org.junit.Assert.fail
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class NoThemeAppCompatTest {
+
+    @Test
+    fun initializeNoThemeAppCompatActivity() {
+        try {
+            ActivityScenario.launch(NoThemeAppCompatActivity::class.java)
+        } catch (e: IllegalStateException) {
+            fail("launching AppCompatActivity with no theme should not throw error")
+        }
+    }
+}
\ No newline at end of file
diff --git a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
index 4e85bcb..bcdc36b 100644
--- a/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -1237,8 +1237,7 @@
 
     @Override
     public void invalidateOptionsMenu() {
-        final ActionBar ab = getSupportActionBar();
-        if (ab != null && ab.invalidateOptionsMenu()) return;
+        if (peekSupportActionBar() == null || getSupportActionBar().invalidateOptionsMenu()) return;
 
         invalidatePanelMenu(FEATURE_OPTIONS_PANEL);
     }
diff --git a/appsearch/appsearch-local-storage/build.gradle b/appsearch/appsearch-local-storage/build.gradle
index 35f841a..d723e00 100644
--- a/appsearch/appsearch-local-storage/build.gradle
+++ b/appsearch/appsearch-local-storage/build.gradle
@@ -44,12 +44,11 @@
     defaultConfig {
         externalNativeBuild {
             cmake {
-                cppFlags "-std=c++17"
                 arguments "-DCMAKE_VERBOSE_MAKEFILE=ON"
                 targets "icing"
             }
         }
-	multiDexEnabled true
+        multiDexEnabled true
     }
     externalNativeBuild {
         cmake {
diff --git a/car/app/app-automotive/src/main/java/androidx/car/app/hardware/common/PropertyUtils.java b/car/app/app-automotive/src/main/java/androidx/car/app/hardware/common/PropertyUtils.java
index de551e6..8dc560a 100644
--- a/car/app/app-automotive/src/main/java/androidx/car/app/hardware/common/PropertyUtils.java
+++ b/car/app/app-automotive/src/main/java/androidx/car/app/hardware/common/PropertyUtils.java
@@ -160,7 +160,7 @@
     /**
      * Maps speed units in car service to speed units in {@link CarUnit}.
      */
-    public static @CarUnit.CarSpeedUnit int covertSpeedUnit(int vehicleUnit) {
+    public static @CarUnit.CarSpeedUnit int convertSpeedUnit(int vehicleUnit) {
         switch (vehicleUnit) {
             case VEHICLE_UNIT_METER_PER_SEC:
                 return CarUnit.METERS_PER_SEC;
@@ -176,7 +176,7 @@
     /**
      * Maps distance units in car service to distance units in {@link CarUnit}.
      */
-    public static @CarUnit.CarDistanceUnit int covertDistanceUnit(int vehicleUnit) {
+    public static @CarUnit.CarDistanceUnit int convertDistanceUnit(int vehicleUnit) {
         switch (vehicleUnit) {
             case VEHICLE_UNIT_METER:
                 return CarUnit.METER;
@@ -196,7 +196,7 @@
      */
     // TODO(b/202303614): Remove this annotation once FuelVolumeDisplayUnit is ready.
     @OptIn(markerClass = ExperimentalCarApi.class)
-    public static @CarUnit.CarVolumeUnit int covertVolumeUnit(int vehicleUnit) {
+    public static @CarUnit.CarVolumeUnit int convertVolumeUnit(int vehicleUnit) {
         switch (vehicleUnit) {
             case VEHICLE_UNIT_MILLILITER:
                 return MILLILITER;
@@ -214,7 +214,7 @@
     /**
      * Maps EV connector types in car service to types in {@link EnergyProfile}.
      */
-    public static @EnergyProfile.EvConnectorType int covertEvConnectorType(
+    public static @EnergyProfile.EvConnectorType int convertEvConnectorType(
             int vehicleEvConnectorType) {
         switch (vehicleEvConnectorType) {
             case 1: // IEC_TYPE_1_AC
diff --git a/car/app/app-automotive/src/main/java/androidx/car/app/hardware/info/AutomotiveCarInfo.java b/car/app/app-automotive/src/main/java/androidx/car/app/hardware/info/AutomotiveCarInfo.java
index 9340089..9485209 100644
--- a/car/app/app-automotive/src/main/java/androidx/car/app/hardware/info/AutomotiveCarInfo.java
+++ b/car/app/app-automotive/src/main/java/androidx/car/app/hardware/info/AutomotiveCarInfo.java
@@ -349,7 +349,7 @@
                         List<Integer> evConnectorsInCarValue = new ArrayList<>();
                         for (Integer connectorType : evConnectorsInVehicle) {
                             evConnectorsInCarValue.add(
-                                    PropertyUtils.covertEvConnectorType(connectorType));
+                                    PropertyUtils.convertEvConnectorType(connectorType));
                         }
                         evConnector = getCarValue(value, evConnectorsInCarValue);
                     }
@@ -465,7 +465,7 @@
                         case SPEED_DISPLAY_UNIT_ID:
                             Integer speedUnit = null;
                             if (response.getValue() != null) {
-                                speedUnit = PropertyUtils.covertSpeedUnit(
+                                speedUnit = PropertyUtils.convertSpeedUnit(
                                         (Integer) response.getValue());
                             }
                             displayUnitValue = getCarValue(response, speedUnit);
@@ -588,7 +588,7 @@
                         case DISTANCE_DISPLAY_UNITS:
                             Integer displayUnit = null;
                             if (response.getValue() != null) {
-                                displayUnit = PropertyUtils.covertDistanceUnit(
+                                displayUnit = PropertyUtils.convertDistanceUnit(
                                         (Integer) response.getValue());
                             }
                             distanceDisplayUnitValue = new CarValue<>(displayUnit,
@@ -689,7 +689,7 @@
                         case DISTANCE_DISPLAY_UNITS:
                             Integer displayUnit = null;
                             if (response.getValue() != null) {
-                                displayUnit = PropertyUtils.covertDistanceUnit(
+                                displayUnit = PropertyUtils.convertDistanceUnit(
                                         (Integer) response.getValue());
                             }
                             distanceDisplayUnitValue = new CarValue<>(displayUnit,
@@ -698,7 +698,7 @@
                         case FUEL_VOLUME_DISPLAY_UNITS:
                             Integer volumeUnit = null;
                             if (response.getValue() != null) {
-                                volumeUnit = PropertyUtils.covertVolumeUnit(
+                                volumeUnit = PropertyUtils.convertVolumeUnit(
                                         (Integer) response.getValue());
                             }
                             fuelVolumeDisplayUnitValue =
diff --git a/car/app/app-samples/helloworld/automotive/github_build.gradle b/car/app/app-samples/helloworld/automotive/github_build.gradle
index 06afd50..2e30e16 100644
--- a/car/app/app-samples/helloworld/automotive/github_build.gradle
+++ b/car/app/app-samples/helloworld/automotive/github_build.gradle
@@ -44,6 +44,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.2.0-alpha02"
+    implementation "androidx.car.app:app-automotive:1.2.0-rc01"
     implementation project(":helloworld:common")
 }
diff --git a/car/app/app-samples/helloworld/common/github_build.gradle b/car/app/app-samples/helloworld/common/github_build.gradle
index c897e85..8eb82ea 100644
--- a/car/app/app-samples/helloworld/common/github_build.gradle
+++ b/car/app/app-samples/helloworld/common/github_build.gradle
@@ -43,7 +43,7 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app:1.2.0-alpha02"
+    implementation "androidx.car.app:app:1.2.0-rc01"
 }
 
 
diff --git a/car/app/app-samples/helloworld/mobile/github_build.gradle b/car/app/app-samples/helloworld/mobile/github_build.gradle
index 4997f292..ea2d696 100644
--- a/car/app/app-samples/helloworld/mobile/github_build.gradle
+++ b/car/app/app-samples/helloworld/mobile/github_build.gradle
@@ -44,7 +44,7 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.2.0-alpha02"
+    implementation "androidx.car.app:app-projected:1.2.0-rc01"
     implementation project(":helloworld:common")
 }
 
diff --git a/car/app/app-samples/navigation/automotive/github_build.gradle b/car/app/app-samples/navigation/automotive/github_build.gradle
index 253704b..8583f42 100644
--- a/car/app/app-samples/navigation/automotive/github_build.gradle
+++ b/car/app/app-samples/navigation/automotive/github_build.gradle
@@ -23,8 +23,10 @@
         applicationId "androidx.car.app.sample.navigation"
         minSdkVersion 29
         targetSdkVersion 31
-        versionCode 101     // Increment this to generate signed builds for uploading to Playstore
-        versionName "101"
+        // Increment this to generate signed builds for uploading to Playstore
+        // Make sure this is different from the navigation-mobile version
+        versionCode 109
+        versionName "109"
     }
 
     buildTypes {
@@ -44,6 +46,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.2.0-alpha02"
+    implementation "androidx.car.app:app-automotive:1.2.0-rc01"
     implementation project(":navigation:common")
 }
diff --git a/car/app/app-samples/navigation/common/github_build.gradle b/car/app/app-samples/navigation/common/github_build.gradle
index e05f3bc..0b13b40 100644
--- a/car/app/app-samples/navigation/common/github_build.gradle
+++ b/car/app/app-samples/navigation/common/github_build.gradle
@@ -35,6 +35,6 @@
     implementation "androidx.constraintlayout:constraintlayout:1.1.3"
     implementation "androidx.core:core:1.5.0-alpha01"
 
-    implementation "androidx.car.app:app:1.2.0-alpha02"
+    implementation "androidx.car.app:app:1.2.0-rc01"
     implementation "androidx.annotation:annotation-experimental:1.0.0"
 }
diff --git a/car/app/app-samples/navigation/mobile/github_build.gradle b/car/app/app-samples/navigation/mobile/github_build.gradle
index 3fb6ea8..78ea1f8 100644
--- a/car/app/app-samples/navigation/mobile/github_build.gradle
+++ b/car/app/app-samples/navigation/mobile/github_build.gradle
@@ -23,8 +23,10 @@
         applicationId "androidx.car.app.sample.navigation"
         minSdkVersion 23
         targetSdkVersion 31
-        versionCode 101     // Increment this to generate signed builds for uploading to Playstore
-        versionName "101"
+        // Increment this to generate signed builds for uploading to Playstore
+        // Make sure this is different from the navigation-automotive version
+        versionCode 108
+        versionName "108"
     }
 
     buildTypes {
@@ -44,6 +46,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.2.0-alpha02"
+    implementation "androidx.car.app:app-projected:1.2.0-rc01"
     implementation project(":navigation:common")
 }
diff --git a/car/app/app-samples/places/automotive/github_build.gradle b/car/app/app-samples/places/automotive/github_build.gradle
index 319064a..f9b2078 100644
--- a/car/app/app-samples/places/automotive/github_build.gradle
+++ b/car/app/app-samples/places/automotive/github_build.gradle
@@ -43,6 +43,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.2.0-alpha02"
+    implementation "androidx.car.app:app-automotive:1.2.0-rc01"
     implementation project(":places:common")
 }
\ No newline at end of file
diff --git a/car/app/app-samples/places/common/github_build.gradle b/car/app/app-samples/places/common/github_build.gradle
index 45c1d1a..e51f92f 100644
--- a/car/app/app-samples/places/common/github_build.gradle
+++ b/car/app/app-samples/places/common/github_build.gradle
@@ -31,7 +31,7 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app:1.2.0-alpha02"
+    implementation "androidx.car.app:app:1.2.0-rc01"
     implementation "androidx.core:core:1.5.0-alpha01"
     implementation 'com.google.guava:guava:28.1-jre'
 }
\ No newline at end of file
diff --git a/car/app/app-samples/places/mobile/github_build.gradle b/car/app/app-samples/places/mobile/github_build.gradle
index c737ee1..cf37c23 100644
--- a/car/app/app-samples/places/mobile/github_build.gradle
+++ b/car/app/app-samples/places/mobile/github_build.gradle
@@ -43,6 +43,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.2.0-alpha02"
+    implementation "androidx.car.app:app-projected:1.2.0-rc01"
     implementation project(":places:common")
 }
\ No newline at end of file
diff --git a/car/app/app-samples/showcase/automotive/github_build.gradle b/car/app/app-samples/showcase/automotive/github_build.gradle
index d41d257..046c9ae 100644
--- a/car/app/app-samples/showcase/automotive/github_build.gradle
+++ b/car/app/app-samples/showcase/automotive/github_build.gradle
@@ -25,8 +25,8 @@
         targetSdkVersion 31
         // Increment this to generate signed builds for uploading to Playstore
         // Make sure this is different from the showcase-mobile version
-        versionCode 107
-        versionName "107"
+        versionCode 109
+        versionName "109"
     }
 
     buildTypes {
@@ -48,6 +48,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-automotive:1.2.0-alpha02"
+    implementation "androidx.car.app:app-automotive:1.2.0-rc01"
     implementation project(":showcase:common")
 }
diff --git a/car/app/app-samples/showcase/common/github_build.gradle b/car/app/app-samples/showcase/common/github_build.gradle
index 04be794..33a90bb 100644
--- a/car/app/app-samples/showcase/common/github_build.gradle
+++ b/car/app/app-samples/showcase/common/github_build.gradle
@@ -34,6 +34,6 @@
 
 dependencies {
     implementation "androidx.core:core:1.6.0-alpha01"
-    implementation "androidx.car.app:app:1.2.0-alpha02"
+    implementation "androidx.car.app:app:1.2.0-rc01"
     implementation "androidx.annotation:annotation-experimental:1.0.0"
 }
diff --git a/car/app/app-samples/showcase/mobile/github_build.gradle b/car/app/app-samples/showcase/mobile/github_build.gradle
index 83498fb..a95c043 100644
--- a/car/app/app-samples/showcase/mobile/github_build.gradle
+++ b/car/app/app-samples/showcase/mobile/github_build.gradle
@@ -25,8 +25,8 @@
         targetSdkVersion 31
         // Increment this to generate signed builds for uploading to Playstore
         // Make sure this is different from the showcase-automotive version
-        versionCode 106
-        versionName "106"
+        versionCode 108
+        versionName "108"
     }
 
     buildTypes {
@@ -48,6 +48,6 @@
 }
 
 dependencies {
-    implementation "androidx.car.app:app-projected:1.2.0-alpha02"
+    implementation "androidx.car.app:app-projected:1.2.0-rc01"
     implementation project(":showcase:common")
 }
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 7af4b5c..83fef5e 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1010,10 +1010,15 @@
     method public static <T> T? getSystemService(android.content.Context, Class<T!>);
     method public static String? getSystemServiceName(android.content.Context, Class<?>);
     method public static boolean isDeviceProtectedStorage(android.content.Context);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
     method public static boolean startActivities(android.content.Context, android.content.Intent![]);
     method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
     method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
     method public static void startForegroundService(android.content.Context, android.content.Intent);
+    field public static final int RECEIVER_EXPORTED = 2; // 0x2
+    field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+    field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
   }
 
   public class FileProvider extends android.content.ContentProvider {
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index f0fc4cf..70ec372 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -1010,10 +1010,15 @@
     method public static <T> T? getSystemService(android.content.Context, Class<T!>);
     method public static String? getSystemServiceName(android.content.Context, Class<?>);
     method public static boolean isDeviceProtectedStorage(android.content.Context);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
     method public static boolean startActivities(android.content.Context, android.content.Intent![]);
     method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
     method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
     method public static void startForegroundService(android.content.Context, android.content.Intent);
+    field public static final int RECEIVER_EXPORTED = 2; // 0x2
+    field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+    field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
   }
 
   public class FileProvider extends android.content.ContentProvider {
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index 6cc603e..12ad90c 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -1118,10 +1118,15 @@
     method public static <T> T? getSystemService(android.content.Context, Class<T!>);
     method public static String? getSystemServiceName(android.content.Context, Class<?>);
     method public static boolean isDeviceProtectedStorage(android.content.Context);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, int);
+    method public static android.content.Intent? registerReceiver(android.content.Context, android.content.BroadcastReceiver?, android.content.IntentFilter, String?, android.os.Handler?, int);
     method public static boolean startActivities(android.content.Context, android.content.Intent![]);
     method public static boolean startActivities(android.content.Context, android.content.Intent![], android.os.Bundle?);
     method public static void startActivity(android.content.Context, android.content.Intent, android.os.Bundle?);
     method public static void startForegroundService(android.content.Context, android.content.Intent);
+    field public static final int RECEIVER_EXPORTED = 2; // 0x2
+    field public static final int RECEIVER_NOT_EXPORTED = 4; // 0x4
+    field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
   }
 
   public class FileProvider extends android.content.ContentProvider {
diff --git a/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java b/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
index 3c082f1..afb8249 100644
--- a/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
+++ b/core/core/src/androidTest/java/androidx/core/content/ContextCompatTest.java
@@ -70,7 +70,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 import android.Manifest;
 import android.accounts.AccountManager;
@@ -88,9 +93,12 @@
 import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
+import android.content.BroadcastReceiver;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.RestrictionsManager;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
@@ -150,7 +158,14 @@
 @LargeTest
 public class ContextCompatTest extends BaseInstrumentationTestCase<ThemedYellowActivity> {
     private Context mContext;
+    private IntentFilter mTestFilter = new IntentFilter();
+    private String mPermission;
+    private BroadcastReceiver mTestReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
 
+        }
+    };
     public ContextCompatTest() {
         super(ThemedYellowActivity.class);
     }
@@ -158,6 +173,7 @@
     @Before
     public void setup() {
         mContext = mActivityTestRule.getActivity();
+        mPermission = mContext.getPackageName() + ".DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION";
     }
 
     @Test
@@ -449,6 +465,71 @@
         return ((size * tdensity) + (sdensity >> 1)) / sdensity;
     }
 
+    @Test
+    public void testRegisterReceiver_noExportStateFlagThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> ContextCompat.registerReceiver(mContext,
+                mTestReceiver, mTestFilter, 0));
+
+        assertThrows(IllegalArgumentException.class, () -> ContextCompat.registerReceiver(mContext,
+                mTestReceiver, mTestFilter, Context.RECEIVER_VISIBLE_TO_INSTANT_APPS));
+    }
+
+    @Test
+    public void testRegisterReceiver_specifyBothExportStateFlagsThrowsException() {
+        assertThrows(IllegalArgumentException.class,
+                () -> ContextCompat.registerReceiver(mContext,
+                mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_EXPORTED | ContextCompat.RECEIVER_NOT_EXPORTED));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 33)
+    public void testRegisterReceiverApi33() {
+        Context spyContext = spy(mContext);
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_NOT_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter), eq(null),
+                any(), eq(ContextCompat.RECEIVER_NOT_EXPORTED));
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter), eq(null), any(),
+                eq(ContextCompat.RECEIVER_EXPORTED));
+    }
+
+    @Test
+    @SdkSuppress(minSdkVersion = 26, maxSdkVersion = 32)
+    public void testRegisterReceiverApi26() {
+        Context spyContext = spy(mContext);
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_NOT_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter),
+                eq(mPermission), any());
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter), eq(null), any(),
+                eq(0));
+
+    }
+
+    @Test
+    @SdkSuppress(maxSdkVersion = 25)
+    public void testRegisterReceiver() {
+        Context spyContext = spy(mContext);
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_NOT_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter), eq(mPermission),
+                any());
+
+        ContextCompat.registerReceiver(spyContext, mTestReceiver, mTestFilter,
+                ContextCompat.RECEIVER_EXPORTED);
+        verify(spyContext).registerReceiver(eq(mTestReceiver), eq(mTestFilter), eq(null), any());
+    }
+
     @Test(expected = NullPointerException.class)
     public void testCheckSelfPermissionNull() {
         ContextCompat.checkSelfPermission(mContext, null);
diff --git a/core/core/src/main/AndroidManifest.xml b/core/core/src/main/AndroidManifest.xml
index 8481017..b050c7e 100644
--- a/core/core/src/main/AndroidManifest.xml
+++ b/core/core/src/main/AndroidManifest.xml
@@ -16,4 +16,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     <application
         android:appComponentFactory="androidx.core.app.CoreComponentFactory" />
+    <permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>
+    <uses-permission android:name="${applicationId}.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>
 </manifest>
diff --git a/core/core/src/main/java/androidx/core/content/ContextCompat.java b/core/core/src/main/java/androidx/core/content/ContextCompat.java
index bcf29ab..2ac62dc 100644
--- a/core/core/src/main/java/androidx/core/content/ContextCompat.java
+++ b/core/core/src/main/java/androidx/core/content/ContextCompat.java
@@ -84,10 +84,12 @@
 import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.bluetooth.BluetoothManager;
+import android.content.BroadcastReceiver;
 import android.content.ClipboardManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.RestrictionsManager;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherApps;
@@ -140,10 +142,12 @@
 import androidx.annotation.ColorRes;
 import androidx.annotation.DoNotInline;
 import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.OptIn;
 import androidx.annotation.RequiresApi;
+import androidx.annotation.RestrictTo;
 import androidx.core.app.ActivityOptionsCompat;
 import androidx.core.app.NotificationManagerCompat;
 import androidx.core.content.res.ResourcesCompat;
@@ -153,6 +157,8 @@
 import androidx.core.util.ObjectsCompat;
 
 import java.io.File;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.HashMap;
 import java.util.concurrent.Executor;
 
@@ -194,6 +200,35 @@
         return null;
     }
 
+
+    private static final String DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX =
+            ".DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION";
+
+
+    /** @hide */
+    @RestrictTo(RestrictTo.Scope.LIBRARY)
+    @IntDef(flag = true, value = {
+            RECEIVER_VISIBLE_TO_INSTANT_APPS, RECEIVER_EXPORTED, RECEIVER_NOT_EXPORTED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RegisterReceiverFlags {}
+    /**
+     * Flag for {@link #registerReceiver}: The receiver can receive broadcasts from Instant Apps.
+     */
+    public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 0x1;
+
+    /**
+     * Flag for {@link #registerReceiver}: The receiver can receive broadcasts from other Apps.
+     * Has the same behavior as marking a statically registered receiver with "exported=true"
+     */
+    public static final int RECEIVER_EXPORTED = 0x2;
+
+    /**
+     * Flag for {@link #registerReceiver}: The receiver cannot receive broadcasts from other Apps.
+     * Has the same behavior as marking a statically registered receiver with "exported=false"
+     */
+    public static final int RECEIVER_NOT_EXPORTED = 0x4;
+
     /**
      * Start a set of activities as a synthesized task stack, if able.
      *
@@ -738,6 +773,80 @@
     }
 
     /**
+     * Register a broadcast receiver.
+     *
+     * @param context  Context to retrieve service from.
+     * @param receiver The BroadcastReceiver to handle the broadcast.
+     * @param filter   Selects the Intent broadcasts to be received.
+     * @param flags    Specify one of {@link #RECEIVER_EXPORTED}, if you wish for your receiver
+     *                 to be able to receiver broadcasts from other applications, or
+     *                 {@link #RECEIVER_NOT_EXPORTED} if you only want your receiver to be able
+     *                 to receive broadcasts from the system or your own app.
+     * @return The first sticky intent found that matches <var>filter</var>,
+     * or null if there are none.
+     * @see Context#registerReceiver(BroadcastReceiver, IntentFilter, int)
+     */
+    @Nullable
+    public static Intent registerReceiver(@NonNull Context context,
+            @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter,
+            @RegisterReceiverFlags int flags) {
+        return registerReceiver(context, receiver, filter, null, null, flags);
+    }
+
+    /**
+     * Register a broadcast receiver.
+     *
+     * @param context             Context to retrieve service from.
+     * @param receiver            The BroadcastReceiver to handle the broadcast.
+     * @param filter              Selects the Intent broadcasts to be received.
+     * @param broadcastPermission String naming a permission that a broadcaster must hold in
+     *                            order to send and Intent to you. If null, no permission is
+     *                            required.
+     * @param scheduler           Handler identifying the thread will receive the Intent. If
+     *                            null, the main thread of the process will be used.
+     * @param flags               Specify one of {@link #RECEIVER_EXPORTED}, if you wish for your
+     *                            receiver to be able to receiver broadcasts from other
+     *                            applications, or {@link #RECEIVER_NOT_EXPORTED} if you only want
+     *                            your receiver to be able to receive broadcasts from the system
+     *                            or your own app.
+     * @return The first sticky intent found that matches <var>filter</var>,
+     * or null if there are none.
+     * @see Context#registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)
+     */
+    @Nullable
+    @OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
+    public static Intent registerReceiver(@NonNull Context context,
+            @Nullable BroadcastReceiver receiver, @NonNull IntentFilter filter,
+            @Nullable String broadcastPermission,
+            @Nullable Handler scheduler, @RegisterReceiverFlags int flags) {
+        if (((flags & RECEIVER_EXPORTED) == 0) && ((flags & RECEIVER_NOT_EXPORTED) == 0)) {
+            throw new IllegalArgumentException("One of either RECEIVER_EXPORTED or "
+                    + "RECEIVER_NOT_EXPORTED is required");
+        }
+
+        if (((flags & RECEIVER_EXPORTED) != 0) && ((flags & RECEIVER_NOT_EXPORTED) != 0)) {
+            throw new IllegalArgumentException("Cannot specify both RECEIVER_EXPORTED and "
+                    + "RECEIVER_NOT_EXPORTED");
+        }
+
+        if (BuildCompat.isAtLeastT()) {
+            return Api33Impl.registerReceiver(context, receiver, filter, broadcastPermission,
+                    scheduler, flags);
+        }
+        if (Build.VERSION.SDK_INT >= 26) {
+            return Api26Impl.registerReceiver(context, receiver, filter, broadcastPermission,
+                    scheduler, flags);
+        }
+        if (((flags & RECEIVER_NOT_EXPORTED) != 0) && (broadcastPermission == null)) {
+            String permission =
+                    context.getPackageName() + DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX;
+            return context.registerReceiver(receiver, filter, permission, scheduler /* handler */);
+        }
+        return context.registerReceiver(receiver, filter, broadcastPermission,
+                scheduler);
+    }
+
+    /**
      * Gets the name of the system-level service that is represented by the specified class.
      *
      * @param context      Context to retrieve service name from.
@@ -936,6 +1045,19 @@
             // This class is not instantiable.
         }
 
+        @DoNotInline
+        static Intent registerReceiver(Context obj, @Nullable BroadcastReceiver receiver,
+                IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+            if ((flags & RECEIVER_NOT_EXPORTED) != 0 && broadcastPermission == null) {
+                String permission =
+                        obj.getPackageName() + DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION_SUFFIX;
+                // receivers that are not exported should also not be visible to instant apps
+                return obj.registerReceiver(receiver, filter, permission, scheduler);
+            }
+            flags &= Context.RECEIVER_VISIBLE_TO_INSTANT_APPS;
+            return obj.registerReceiver(receiver, filter, broadcastPermission, scheduler, flags);
+        }
+
         @SuppressWarnings("UnusedReturnValue")
         @DoNotInline
         static ComponentName startForegroundService(Context obj, Intent service) {
@@ -966,4 +1088,17 @@
             return obj.getAttributionTag();
         }
     }
+
+    @RequiresApi(33)
+    static class Api33Impl {
+        private Api33Impl() {
+            // This class is not instantiable
+        }
+
+        @DoNotInline
+        static Intent registerReceiver(Context obj, @Nullable BroadcastReceiver receiver,
+                IntentFilter filter, String broadcastPermission, Handler scheduler, int flags) {
+            return obj.registerReceiver(receiver, filter, broadcastPermission, scheduler, flags);
+        }
+    }
 }
diff --git a/datastore/datastore-compose-samples/build.gradle b/datastore/datastore-compose-samples/build.gradle
index d7c2c16..15480ae 100644
--- a/datastore/datastore-compose-samples/build.gradle
+++ b/datastore/datastore-compose-samples/build.gradle
@@ -53,9 +53,6 @@
     buildFeatures {
         compose true
     }
-    composeOptions {
-        kotlinCompilerExtensionVersion '1.1.0-rc02'
-    }
 }
 
 protobuf {
diff --git a/savedstate/savedstate/api/current.txt b/savedstate/savedstate/api/current.txt
index 2d04ca6..7c561cb 100644
--- a/savedstate/savedstate/api/current.txt
+++ b/savedstate/savedstate/api/current.txt
@@ -19,11 +19,17 @@
   }
 
   public final class SavedStateRegistryController {
-    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner);
+    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
     method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
     method @MainThread public void performAttach();
-    method @MainThread public void performRestore(android.os.Bundle?);
-    method @MainThread public void performSave(android.os.Bundle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void performSave(android.os.Bundle outBundle);
+    property public final androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    field public static final androidx.savedstate.SavedStateRegistryController.Companion Companion;
+  }
+
+  public static final class SavedStateRegistryController.Companion {
+    method public androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
   public interface SavedStateRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/savedstate/savedstate/api/public_plus_experimental_current.txt b/savedstate/savedstate/api/public_plus_experimental_current.txt
index 2d04ca6..7c561cb 100644
--- a/savedstate/savedstate/api/public_plus_experimental_current.txt
+++ b/savedstate/savedstate/api/public_plus_experimental_current.txt
@@ -19,11 +19,17 @@
   }
 
   public final class SavedStateRegistryController {
-    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner);
+    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
     method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
     method @MainThread public void performAttach();
-    method @MainThread public void performRestore(android.os.Bundle?);
-    method @MainThread public void performSave(android.os.Bundle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void performSave(android.os.Bundle outBundle);
+    property public final androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    field public static final androidx.savedstate.SavedStateRegistryController.Companion Companion;
+  }
+
+  public static final class SavedStateRegistryController.Companion {
+    method public androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
   public interface SavedStateRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/savedstate/savedstate/api/restricted_current.txt b/savedstate/savedstate/api/restricted_current.txt
index 2d04ca6..7c561cb 100644
--- a/savedstate/savedstate/api/restricted_current.txt
+++ b/savedstate/savedstate/api/restricted_current.txt
@@ -19,11 +19,17 @@
   }
 
   public final class SavedStateRegistryController {
-    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner);
+    method public static androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
     method public androidx.savedstate.SavedStateRegistry getSavedStateRegistry();
     method @MainThread public void performAttach();
-    method @MainThread public void performRestore(android.os.Bundle?);
-    method @MainThread public void performSave(android.os.Bundle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void performSave(android.os.Bundle outBundle);
+    property public final androidx.savedstate.SavedStateRegistry savedStateRegistry;
+    field public static final androidx.savedstate.SavedStateRegistryController.Companion Companion;
+  }
+
+  public static final class SavedStateRegistryController.Companion {
+    method public androidx.savedstate.SavedStateRegistryController create(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
   public interface SavedStateRegistryOwner extends androidx.lifecycle.LifecycleOwner {
diff --git a/savedstate/savedstate/build.gradle b/savedstate/savedstate/build.gradle
index f5735d0..ae8b16d 100644
--- a/savedstate/savedstate/build.gradle
+++ b/savedstate/savedstate/build.gradle
@@ -15,6 +15,7 @@
 
 dependencies {
     api("androidx.annotation:annotation:1.1.0")
+    api("androidx.core:core-ktx:1.2.0")
     implementation("androidx.arch.core:core-common:2.1.0")
     implementation("androidx.lifecycle:lifecycle-common:2.4.0")
 
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.java b/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.java
deleted file mode 100644
index 33647d3..0000000
--- a/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.savedstate;
-
-
-import android.os.Bundle;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.savedstate.SavedStateRegistry.AutoRecreated;
-
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
-final class Recreator implements LifecycleEventObserver {
-
-    static final String CLASSES_KEY = "classes_to_restore";
-    static final String COMPONENT_KEY = "androidx.savedstate.Restarter";
-
-    private final SavedStateRegistryOwner mOwner;
-
-    Recreator(SavedStateRegistryOwner owner) {
-        mOwner = owner;
-    }
-
-    @Override
-    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
-        if (event != Lifecycle.Event.ON_CREATE) {
-            throw new AssertionError("Next event must be ON_CREATE");
-        }
-        source.getLifecycle().removeObserver(this);
-        Bundle bundle = mOwner.getSavedStateRegistry()
-                .consumeRestoredStateForKey(COMPONENT_KEY);
-        if (bundle == null) {
-            return;
-        }
-        ArrayList<String> classes = bundle.getStringArrayList(CLASSES_KEY);
-        if (classes == null) {
-            throw new IllegalStateException("Bundle with restored state for the component \""
-                    + COMPONENT_KEY + "\" must contain list of strings by the key \""
-                    + CLASSES_KEY + "\"");
-        }
-        for (String className : classes) {
-            reflectiveNew(className);
-        }
-    }
-
-    private void reflectiveNew(String className) {
-        Class<? extends AutoRecreated> clazz;
-        try {
-            clazz = Class.forName(className, false,
-                    Recreator.class.getClassLoader()).asSubclass(AutoRecreated.class);
-        } catch (ClassNotFoundException e) {
-            throw new RuntimeException("Class " + className + " wasn't found", e);
-        }
-
-        Constructor<? extends AutoRecreated> constructor;
-        try {
-            constructor = clazz.getDeclaredConstructor();
-        } catch (NoSuchMethodException e) {
-            throw new IllegalStateException("Class" + clazz.getSimpleName() + " must have "
-                    + "default constructor in order to be automatically recreated", e);
-        }
-        constructor.setAccessible(true);
-
-        AutoRecreated newInstance;
-        try {
-            newInstance = constructor.newInstance();
-        } catch (Exception e) {
-            throw new RuntimeException("Failed to instantiate " + className, e);
-        }
-        newInstance.onRecreated(mOwner);
-    }
-
-    static final class SavedStateProvider implements SavedStateRegistry.SavedStateProvider {
-        @SuppressWarnings("WeakerAccess") // synthetic access
-        final Set<String> mClasses = new HashSet<>();
-
-        SavedStateProvider(final SavedStateRegistry registry) {
-            registry.registerSavedStateProvider(COMPONENT_KEY, this);
-        }
-
-        @NonNull
-        @Override
-        public Bundle saveState() {
-            Bundle bundle = new Bundle();
-            bundle.putStringArrayList(CLASSES_KEY, new ArrayList<>(mClasses));
-            return bundle;
-        }
-
-        void add(String className) {
-            mClasses.add(className);
-        }
-    }
-}
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.kt b/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.kt
new file mode 100644
index 0000000..315ab92
--- /dev/null
+++ b/savedstate/savedstate/src/main/java/androidx/savedstate/Recreator.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package androidx.savedstate
+
+import android.os.Bundle
+import androidx.core.os.bundleOf
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
+import androidx.lifecycle.LifecycleOwner
+import androidx.savedstate.SavedStateRegistry.AutoRecreated
+
+internal class Recreator(
+    private val owner: SavedStateRegistryOwner
+) : LifecycleEventObserver {
+
+    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
+        if (event != Lifecycle.Event.ON_CREATE) {
+            throw AssertionError("Next event must be ON_CREATE")
+        }
+        source.lifecycle.removeObserver(this)
+        val bundle: Bundle = owner.savedStateRegistry
+            .consumeRestoredStateForKey(COMPONENT_KEY) ?: return
+        val classes: MutableList<String> = bundle.getStringArrayList(CLASSES_KEY)
+            ?: throw IllegalStateException(
+                "Bundle with restored state for the component " +
+                    "\"$COMPONENT_KEY\" must contain list of strings by the key " +
+                    "\"$CLASSES_KEY\""
+            )
+        for (className: String in classes) {
+            reflectiveNew(className)
+        }
+    }
+
+    private fun reflectiveNew(className: String) {
+        val clazz: Class<out AutoRecreated> =
+            try {
+                Class.forName(className, false, Recreator::class.java.classLoader)
+                    .asSubclass(AutoRecreated::class.java)
+            } catch (e: ClassNotFoundException) {
+                throw RuntimeException("Class $className wasn't found", e)
+            }
+        val constructor =
+            try {
+                clazz.getDeclaredConstructor()
+            } catch (e: NoSuchMethodException) {
+                throw IllegalStateException(
+                    "Class ${clazz.simpleName} must have " +
+                        "default constructor in order to be automatically recreated", e
+                )
+            }
+        constructor.isAccessible = true
+        val newInstance: AutoRecreated =
+            try {
+                constructor.newInstance()
+            } catch (e: Exception) {
+                throw RuntimeException("Failed to instantiate $className", e)
+            }
+        newInstance.onRecreated(owner)
+    }
+
+    internal class SavedStateProvider(registry: SavedStateRegistry) :
+        SavedStateRegistry.SavedStateProvider {
+
+        private val classes: MutableSet<String> = mutableSetOf()
+
+        init {
+            registry.registerSavedStateProvider(COMPONENT_KEY, this)
+        }
+
+        override fun saveState(): Bundle {
+            return bundleOf(CLASSES_KEY to ArrayList(classes))
+        }
+
+        fun add(className: String) {
+            classes.add(className)
+        }
+    }
+
+    companion object {
+        const val CLASSES_KEY = "classes_to_restore"
+        const val COMPONENT_KEY = "androidx.savedstate.Restarter"
+    }
+}
\ No newline at end of file
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.java b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.java
deleted file mode 100644
index 98fe68f..0000000
--- a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2018 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.savedstate;
-
-import android.os.Bundle;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.lifecycle.Lifecycle;
-
-/**
- * An API for {@link SavedStateRegistryOwner} implementations to control {@link SavedStateRegistry}.
- * <p>
- * {@code SavedStateRegistryOwner} should call {@link #performRestore(Bundle)} to restore state of
- * {@link SavedStateRegistry} and {@link #performSave(Bundle)} to gather SavedState from it.
- */
-public final class SavedStateRegistryController {
-    private final SavedStateRegistryOwner mOwner;
-    private final SavedStateRegistry mRegistry;
-
-    private boolean mAttached = false;
-
-    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
-        mOwner = owner;
-        mRegistry = new SavedStateRegistry();
-    }
-
-    /**
-     * Returns controlled {@link SavedStateRegistry}
-     */
-    @NonNull
-    public SavedStateRegistry getSavedStateRegistry() {
-        return mRegistry;
-    }
-
-    /**
-     * Perform the initial, one time attachment necessary to configure this
-     * {@link SavedStateRegistry}. This must be called when the owner's {@link Lifecycle} is
-     * {@link Lifecycle.State#INITIALIZED} and before you call
-     * {@link #performRestore(Bundle)}.
-     */
-    @MainThread
-    public void performAttach() {
-        Lifecycle lifecycle = mOwner.getLifecycle();
-        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
-            throw new IllegalStateException("Restarter must be created only during "
-                    + "owner's initialization stage");
-        }
-        lifecycle.addObserver(new Recreator(mOwner));
-        mRegistry.performAttach(lifecycle);
-
-        mAttached = true;
-    }
-
-    /**
-     * An interface for an owner of this {@link SavedStateRegistry} to restore saved state.
-     *
-     * @param savedState restored state
-     */
-    @MainThread
-    public void performRestore(@Nullable Bundle savedState) {
-        // To support backward compatibility with libraries that do not explicitly
-        // call performAttach(), we make sure that work is done here
-        if (!mAttached) {
-            performAttach();
-        }
-        Lifecycle lifecycle = mOwner.getLifecycle();
-        if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
-            throw new IllegalStateException("performRestore cannot be called when owner "
-                    + " is " + lifecycle.getCurrentState());
-        }
-        mRegistry.performRestore(savedState);
-    }
-
-    /**
-     * An interface for an owner of this  {@link SavedStateRegistry}
-     * to perform state saving, it will call all registered providers and
-     * merge with unconsumed state.
-     *
-     * @param outBundle Bundle in which to place a saved state
-     */
-    @MainThread
-    public void performSave(@NonNull Bundle outBundle) {
-        mRegistry.performSave(outBundle);
-    }
-
-    /**
-     * Creates a {@link SavedStateRegistryController}.
-     * <p>
-     * It should be called during construction time of {@link SavedStateRegistryOwner}
-     */
-    @NonNull
-    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
-        return new SavedStateRegistryController(owner);
-    }
-}
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.kt b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.kt
new file mode 100644
index 0000000..8a477ed
--- /dev/null
+++ b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistryController.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 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.savedstate
+
+import android.os.Bundle
+import androidx.annotation.MainThread
+import androidx.lifecycle.Lifecycle
+
+/**
+ * An API for [SavedStateRegistryOwner] implementations to control [SavedStateRegistry].
+ *
+ * `SavedStateRegistryOwner` should call [performRestore] to restore state of
+ * [SavedStateRegistry] and [performSave] to gather SavedState from it.
+ */
+class SavedStateRegistryController private constructor(private val owner: SavedStateRegistryOwner) {
+
+    val savedStateRegistry: SavedStateRegistry = SavedStateRegistry()
+
+    private var attached = false
+
+    /**
+     * Perform the initial, one time attachment necessary to configure this
+     * [SavedStateRegistry]. This must be called when the owner's [Lifecycle] is
+     * [Lifecycle.State.INITIALIZED] and before you call [performRestore].
+     */
+    @MainThread
+    fun performAttach() {
+        val lifecycle = owner.lifecycle
+        check(lifecycle.currentState == Lifecycle.State.INITIALIZED) {
+            ("Restarter must be created only during owner's initialization stage")
+        }
+        lifecycle.addObserver(Recreator(owner))
+        savedStateRegistry.performAttach(lifecycle)
+        attached = true
+    }
+
+    /**
+     * An interface for an owner of this [SavedStateRegistry] to restore saved state.
+     *
+     * @param savedState restored state
+     */
+    @MainThread
+    fun performRestore(savedState: Bundle?) {
+        // To support backward compatibility with libraries that do not explicitly
+        // call performAttach(), we make sure that work is done here
+        if (!attached) {
+            performAttach()
+        }
+        val lifecycle = owner.lifecycle
+        check(!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
+            ("performRestore cannot be called when owner is ${lifecycle.currentState}")
+        }
+        savedStateRegistry.performRestore(savedState)
+    }
+
+    /**
+     * An interface for an owner of this  [SavedStateRegistry]
+     * to perform state saving, it will call all registered providers and
+     * merge with unconsumed state.
+     *
+     * @param outBundle Bundle in which to place a saved state
+     */
+    @MainThread
+    fun performSave(outBundle: Bundle) {
+        savedStateRegistry.performSave(outBundle)
+    }
+
+    companion object {
+        /**
+         * Creates a [SavedStateRegistryController].
+         *
+         * It should be called during construction time of [SavedStateRegistryOwner]
+         */
+        @JvmStatic
+        fun create(owner: SavedStateRegistryOwner): SavedStateRegistryController {
+            return SavedStateRegistryController(owner)
+        }
+    }
+}
diff --git a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
index dc4347d..b4508e3 100644
--- a/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
+++ b/wear/watchface/watchface-client/src/androidTest/java/androidx/wear/watchface/client/test/WatchFaceControlClientTest.kt
@@ -102,6 +102,7 @@
 import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -1437,6 +1438,7 @@
         assertTrue(service.hasComplicationDataCache())
     }
 
+    @Ignore // b/225230182
     @RequiresApi(Build.VERSION_CODES.O_MR1)
     @Test
     fun interactiveAndHeadlessOpenGlWatchFaceInstances() {