Convert SavedStateRegistry to Kotlin

Part of the kotlinification of SavedState module.

Test: ./gradlew checkApi all existing test pass
Bug: 220191285

Relnote: "SavedStateRegistry is now in Kotlin"

Change-Id: I2539228cdbb20892cb71dcc8f4fecc31cede9486
diff --git a/savedstate/savedstate/api/current.txt b/savedstate/savedstate/api/current.txt
index 6ef8e87..e1371e1 100644
--- a/savedstate/savedstate/api/current.txt
+++ b/savedstate/savedstate/api/current.txt
@@ -2,19 +2,22 @@
 package androidx.savedstate {
 
   public final class SavedStateRegistry {
-    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String);
-    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String);
+    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String key);
+    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String key);
     method @MainThread public boolean isRestored();
-    method @MainThread public void registerSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
-    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated>);
-    method @MainThread public void unregisterSavedStateProvider(String);
+    method @MainThread public void performAttach(androidx.lifecycle.Lifecycle lifecycle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void registerSavedStateProvider(String key, androidx.savedstate.SavedStateRegistry.SavedStateProvider provider);
+    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated> clazz);
+    method @MainThread public void unregisterSavedStateProvider(String key);
+    property @MainThread public final boolean isRestored;
   }
 
   public static interface SavedStateRegistry.AutoRecreated {
-    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner);
+    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
-  public static interface SavedStateRegistry.SavedStateProvider {
+  public static fun interface SavedStateRegistry.SavedStateProvider {
     method public android.os.Bundle saveState();
   }
 
diff --git a/savedstate/savedstate/api/public_plus_experimental_current.txt b/savedstate/savedstate/api/public_plus_experimental_current.txt
index 6ef8e87..e1371e1 100644
--- a/savedstate/savedstate/api/public_plus_experimental_current.txt
+++ b/savedstate/savedstate/api/public_plus_experimental_current.txt
@@ -2,19 +2,22 @@
 package androidx.savedstate {
 
   public final class SavedStateRegistry {
-    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String);
-    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String);
+    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String key);
+    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String key);
     method @MainThread public boolean isRestored();
-    method @MainThread public void registerSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
-    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated>);
-    method @MainThread public void unregisterSavedStateProvider(String);
+    method @MainThread public void performAttach(androidx.lifecycle.Lifecycle lifecycle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void registerSavedStateProvider(String key, androidx.savedstate.SavedStateRegistry.SavedStateProvider provider);
+    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated> clazz);
+    method @MainThread public void unregisterSavedStateProvider(String key);
+    property @MainThread public final boolean isRestored;
   }
 
   public static interface SavedStateRegistry.AutoRecreated {
-    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner);
+    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
-  public static interface SavedStateRegistry.SavedStateProvider {
+  public static fun interface SavedStateRegistry.SavedStateProvider {
     method public android.os.Bundle saveState();
   }
 
diff --git a/savedstate/savedstate/api/restricted_current.txt b/savedstate/savedstate/api/restricted_current.txt
index 6ef8e87..e1371e1 100644
--- a/savedstate/savedstate/api/restricted_current.txt
+++ b/savedstate/savedstate/api/restricted_current.txt
@@ -2,19 +2,22 @@
 package androidx.savedstate {
 
   public final class SavedStateRegistry {
-    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String);
-    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String);
+    method @MainThread public android.os.Bundle? consumeRestoredStateForKey(String key);
+    method public androidx.savedstate.SavedStateRegistry.SavedStateProvider? getSavedStateProvider(String key);
     method @MainThread public boolean isRestored();
-    method @MainThread public void registerSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
-    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated>);
-    method @MainThread public void unregisterSavedStateProvider(String);
+    method @MainThread public void performAttach(androidx.lifecycle.Lifecycle lifecycle);
+    method @MainThread public void performRestore(android.os.Bundle? savedState);
+    method @MainThread public void registerSavedStateProvider(String key, androidx.savedstate.SavedStateRegistry.SavedStateProvider provider);
+    method @MainThread public void runOnNextRecreation(Class<? extends androidx.savedstate.SavedStateRegistry.AutoRecreated> clazz);
+    method @MainThread public void unregisterSavedStateProvider(String key);
+    property @MainThread public final boolean isRestored;
   }
 
   public static interface SavedStateRegistry.AutoRecreated {
-    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner);
+    method public void onRecreated(androidx.savedstate.SavedStateRegistryOwner owner);
   }
 
-  public static interface SavedStateRegistry.SavedStateProvider {
+  public static fun interface SavedStateRegistry.SavedStateProvider {
     method public android.os.Bundle saveState();
   }
 
diff --git a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.kt b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.kt
index 3bca4f1..a8bd28d 100644
--- a/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.kt
+++ b/savedstate/savedstate/src/main/java/androidx/savedstate/SavedStateRegistry.kt
@@ -13,270 +13,259 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package androidx.savedstate
 
-package androidx.savedstate;
-
-import android.annotation.SuppressLint;
-import android.os.Bundle;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.arch.core.internal.SafeIterableMap;
-import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleEventObserver;
-
-import java.util.Iterator;
-import java.util.Map;
+import android.annotation.SuppressLint
+import android.os.Bundle
+import androidx.annotation.MainThread
+import androidx.arch.core.internal.SafeIterableMap
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleEventObserver
 
 /**
  * An interface for plugging components that consumes and contributes to the saved state.
  *
- * <p>This objects lifetime is bound to the lifecycle of owning component: when activity or
+ *
+ * This objects lifetime is bound to the lifecycle of owning component: when activity or
  * fragment is recreated, new instance of the object is created as well.
  */
 @SuppressLint("RestrictedApi")
-public final class SavedStateRegistry {
-    private static final String SAVED_COMPONENTS_KEY =
-            "androidx.lifecycle.BundlableSavedStateRegistry.key";
-
-    private final SafeIterableMap<String, SavedStateProvider> mComponents =
-            new SafeIterableMap<>();
-    private boolean mAttached;
-    @Nullable
-    private Bundle mRestoredState;
-    private boolean mRestored;
-    private Recreator.SavedStateProvider mRecreatorProvider;
-    boolean mAllowingSavingState = true;
-
-    SavedStateRegistry() {
-    }
+class SavedStateRegistry internal constructor() {
+    private val components = SafeIterableMap<String, SavedStateProvider>()
+    private var attached = false
+    private var restoredState: Bundle? = null
 
     /**
-     * Consumes saved state previously supplied by {@link SavedStateProvider} registered
-     * via {@link #registerSavedStateProvider(String, SavedStateProvider)}
-     * with the given {@code key}.
-     * <p>
+     * Whether the state was restored after creation and can be safely consumed
+     * with [consumeRestoredStateForKey].
+     *
+     * [isRestored] == true if state was restored
+     */
+    @get: MainThread
+    var isRestored = false
+        private set
+    private var recreatorProvider: Recreator.SavedStateProvider? = null
+    internal var isAllowingSavingState = true
+
+    /**
+     * Consumes saved state previously supplied by [SavedStateProvider] registered
+     * via [registerSavedStateProvider] with the given `key`.
+     *
+     *
      * This call clears an internal reference to returned saved state, so if you call it second time
-     * in the row it will return {@code null}.
-     * <p>
-     * All unconsumed values will be saved during {@code onSaveInstanceState(Bundle savedState)}
-     * <p>
-     * This method can be called after {@code super.onCreate(savedStateBundle)} of the corresponding
-     * component. Calling it before that will result in {@code IllegalArgumentException}.
-     * {@link Lifecycle.Event#ON_CREATE} can be used as a signal
+     * in the row it will return `null`.
+     *
+     *
+     * All unconsumed values will be saved during `onSaveInstanceState(Bundle savedState)`
+     *
+     *
+     * This method can be called after `super.onCreate(savedStateBundle)` of the corresponding
+     * component. Calling it before that will result in `IllegalArgumentException`.
+     * [Lifecycle.Event.ON_CREATE] can be used as a signal
      * that a saved state can be safely consumed.
      *
-     * @param key a key with which {@link SavedStateProvider} was previously registered.
-     * @return {@code S} with the previously saved state or {@code null}
+     * @param key a key with which [SavedStateProvider] was previously registered.
+     * @return `S` with the previously saved state or {@code null}
      */
     @MainThread
-    @Nullable
-    public Bundle consumeRestoredStateForKey(@NonNull String key) {
-        if (!mRestored) {
-            throw new IllegalStateException("You can consumeRestoredStateForKey "
-                    + "only after super.onCreate of corresponding component");
+    fun consumeRestoredStateForKey(key: String): Bundle? {
+        check(isRestored) {
+            ("You can consumeRestoredStateForKey " +
+                "only after super.onCreate of corresponding component")
         }
-        if (mRestoredState != null) {
-            Bundle result = mRestoredState.getBundle(key);
-            mRestoredState.remove(key);
-            if (mRestoredState.isEmpty()) {
-                mRestoredState = null;
+        if (restoredState != null) {
+            val result = restoredState?.getBundle(key)
+            restoredState?.remove(key)
+            if (restoredState?.isEmpty != false) {
+                restoredState = null
             }
-            return result;
+            return result
         }
-        return null;
+        return null
     }
 
     /**
-     * Registers a {@link SavedStateProvider} by the given {@code key}. This
-     * {@code savedStateProvider} will be called
-     * during state saving phase, returned object will be associated with the given {@code key}
-     * and can be used after the restoration via {@link #consumeRestoredStateForKey(String)}.
-     * <p>
-     * If there is unconsumed value with the same {@code key},
-     * the value supplied by {@code savedStateProvider} will be override and
+     * Registers a [SavedStateProvider] by the given `key`. This
+     * `savedStateProvider` will be called
+     * during state saving phase, returned object will be associated with the given `key`
+     * and can be used after the restoration via [.consumeRestoredStateForKey].
+     *
+     *
+     * If there is unconsumed value with the same `key`,
+     * the value supplied by `savedStateProvider` will be overridden and
      * will be written to resulting saved state.
-     * <p> if a provider was already registered with the given {@code key}, an implementation should
-     * throw an {@link IllegalArgumentException}
+     *
+     * If a provider was already registered with the given `key`, an implementation should
+     * throw an [IllegalArgumentException]
      *
      * @param key      a key with which returned saved state will be associated
      * @param provider savedStateProvider to get saved state.
      */
     @MainThread
-    public void registerSavedStateProvider(@NonNull String key,
-            @NonNull SavedStateProvider provider) {
-        SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
-        if (previous != null) {
-            throw new IllegalArgumentException("SavedStateProvider with the given key is"
-                    + " already registered");
+    fun registerSavedStateProvider(
+        key: String,
+        provider: SavedStateProvider
+    ) {
+        val previous = components.putIfAbsent(key, provider)
+        require(previous == null) {
+            ("SavedStateProvider with the given key is" +
+                " already registered")
         }
     }
 
     /**
-     * Get a previously registered {@link SavedStateProvider}.
+     * Get a previously registered [SavedStateProvider].
      *
-     * @param key The key used to register the {@link SavedStateProvider} when it was registered
-     *            with {@link #registerSavedStateProvider(String, SavedStateProvider)}.
-     * @return The {@link SavedStateProvider} previously registered with
-     * {@link #registerSavedStateProvider(String, SavedStateProvider)} or null if no provider
+     * @param key The key used to register the [SavedStateProvider] when it was registered
+     *            with registerSavedStateProvider(String, SavedStateProvider).
+     *
+     * Returns the [SavedStateProvider] previously registered with
+     * [registerSavedStateProvider] or null if no provider
      * has been registered with the given key.
-     * @see #registerSavedStateProvider(String, SavedStateProvider)
      */
-    @Nullable
-    public SavedStateProvider getSavedStateProvider(@NonNull String key) {
-        SavedStateProvider provider = null;
-        for (Map.Entry<String, SavedStateProvider> entry : mComponents) {
-            if (entry.getKey().equals(key)) {
-                provider = entry.getValue();
-                break;
+    fun getSavedStateProvider(key: String): SavedStateProvider? {
+        var provider: SavedStateProvider? = null
+        for ((k, value) in components) {
+            if (k == key) {
+                provider = value
+                break
             }
         }
-        return provider;
+        return provider
     }
 
     /**
-     * Unregisters a component previously registered by the given {@code key}
+     * Unregisters a component previously registered by the given `key`
      *
      * @param key a key with which a component was previously registered.
      */
     @MainThread
-    public void unregisterSavedStateProvider(@NonNull String key) {
-        mComponents.remove(key);
-    }
-
-    /**
-     * Returns if state was restored after creation and can be safely consumed
-     * with {@link #consumeRestoredStateForKey(String)}
-     *
-     * @return true if state was restored.
-     */
-    @MainThread
-    public boolean isRestored() {
-        return mRestored;
+    fun unregisterSavedStateProvider(key: String) {
+        components.remove(key)
     }
 
     /**
      * Subclasses of this interface will be automatically recreated if they were previously
-     * registered via {@link #runOnNextRecreation(Class)}.
-     * <p>
+     * registered via [runOnNextRecreation].
+     *
+     *
      * Subclasses must have a default constructor
      */
-    public interface AutoRecreated {
+    interface AutoRecreated {
         /**
          * This method will be called during
-         * dispatching of {@link androidx.lifecycle.Lifecycle.Event#ON_CREATE} of owning component.
+         * dispatching of [androidx.lifecycle.Lifecycle.Event.ON_CREATE] of owning component
+         * which was restarted
          *
          * @param owner a component that was restarted
          */
-        void onRecreated(@NonNull SavedStateRegistryOwner owner);
+        fun onRecreated(owner: SavedStateRegistryOwner)
     }
 
     /**
      * Executes the given class when the owning component restarted.
-     * <p>
+     *
+     *
      * The given class will be automatically instantiated via default constructor and method
-     * {@link AutoRecreated#onRecreated(SavedStateRegistryOwner)} will be called.
-     * It is called as part of dispatching of {@link androidx.lifecycle.Lifecycle.Event#ON_CREATE}
+     * [AutoRecreated.onRecreated] will be called.
+     * It is called as part of dispatching of [androidx.lifecycle.Lifecycle.Event.ON_CREATE]
      * event.
      *
      * @param clazz that will need to be instantiated on the next component recreation
-     * @throws IllegalStateException if you try to call if after {@link Lifecycle.Event#ON_STOP}
+     * @throws IllegalArgumentException if you try to call if after [Lifecycle.Event.ON_STOP]
      *                               was dispatched
      */
     @MainThread
-    public void runOnNextRecreation(@NonNull Class<? extends AutoRecreated> clazz) {
-        if (!mAllowingSavingState) {
-            throw new IllegalStateException(
-                    "Can not perform this action after onSaveInstanceState");
-        }
-        if (mRecreatorProvider == null) {
-            mRecreatorProvider = new Recreator.SavedStateProvider(this);
-        }
+    fun runOnNextRecreation(clazz: Class<out AutoRecreated>) {
+        check(isAllowingSavingState) { "Can not perform this action after onSaveInstanceState" }
+        recreatorProvider = recreatorProvider ?: Recreator.SavedStateProvider(this)
         try {
-            clazz.getDeclaredConstructor();
-        } catch (NoSuchMethodException e) {
-            throw new IllegalArgumentException("Class" + clazz.getSimpleName() + " must have "
-                    + "default constructor in order to be automatically recreated", e);
+            clazz.getDeclaredConstructor()
+        } catch (e: NoSuchMethodException) {
+            throw IllegalArgumentException(
+                "Class ${clazz.simpleName} must have " +
+                    "default constructor in order to be automatically recreated", e
+            )
         }
-        mRecreatorProvider.add(clazz.getName());
+        recreatorProvider?.add(clazz.name)
     }
 
     /**
-     * An interface for an owner of this @{code {@link SavedStateRegistry} to attach this
-     * to a {@link Lifecycle}.
+     * An interface for an owner of this [SavedStateRegistry] to attach this
+     * to a [Lifecycle].
      */
     @MainThread
-    void performAttach(@NonNull Lifecycle lifecycle) {
-        if (mAttached) {
-            throw new IllegalStateException("SavedStateRegistry was already attached.");
-        }
+    fun performAttach(lifecycle: Lifecycle) {
+        check(!attached) { "SavedStateRegistry was already attached." }
 
-        lifecycle.addObserver((LifecycleEventObserver) (source, event) -> {
+        lifecycle.addObserver(LifecycleEventObserver { _, event ->
             if (event == Lifecycle.Event.ON_START) {
-                mAllowingSavingState = true;
+                isAllowingSavingState = true
             } else if (event == Lifecycle.Event.ON_STOP) {
-                mAllowingSavingState = false;
+                isAllowingSavingState = false
             }
-        });
-
-        mAttached = true;
+        })
+        attached = true
     }
 
     /**
-     * An interface for an owner of this @{code {@link SavedStateRegistry} to restore saved state.
+     * An interface for an owner of this [SavedStateRegistry] to restore saved state.
      *
      */
     @MainThread
-    void performRestore(@Nullable Bundle savedState) {
-        if (!mAttached) {
-            throw new IllegalStateException("You must call performAttach() before calling "
-                    + "performRestore(Bundle).");
+    fun performRestore(savedState: Bundle?) {
+        check(attached) {
+            ("You must call performAttach() before calling " +
+                "performRestore(Bundle).")
         }
-        if (mRestored) {
-            throw new IllegalStateException("SavedStateRegistry was already restored.");
-        }
-        if (savedState != null) {
-            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
-        }
+        check(!isRestored) { "SavedStateRegistry was already restored." }
+        restoredState = savedState?.getBundle(SAVED_COMPONENTS_KEY)
 
-        mRestored = true;
+        isRestored = true
     }
 
     /**
-     * An interface for an owner of this @{code {@link SavedStateRegistry}
+     * 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
+     * @suppress INACCESSIBLE_TYPE iterator is used strictly as Iterator, does not access
+     * inaccessible type IteratorWithAdditions
      */
     @MainThread
-    void performSave(@NonNull Bundle outBundle) {
-        Bundle components = new Bundle();
-        if (mRestoredState != null) {
-            components.putAll(mRestoredState);
+    @Suppress("INACCESSIBLE_TYPE")
+    fun performSave(outBundle: Bundle) {
+        val components = Bundle()
+        if (restoredState != null) {
+            components.putAll(restoredState)
         }
-        for (Iterator<Map.Entry<String, SavedStateProvider>> it =
-                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
-            Map.Entry<String, SavedStateProvider> entry1 = it.next();
-            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
+        val it: Iterator<Map.Entry<String, SavedStateProvider>> =
+            this.components.iteratorWithAdditions()
+        while (it.hasNext()) {
+            val (key, value) = it.next()
+            components.putBundle(key, value.saveState())
         }
-        if (!components.isEmpty()) {
-            outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
+        if (!components.isEmpty) {
+            outBundle.putBundle(SAVED_COMPONENTS_KEY, components)
         }
     }
 
     /**
      * This interface marks a component that contributes to saved state.
      */
-    public interface SavedStateProvider {
+    fun interface SavedStateProvider {
         /**
          * Called to retrieve a state from a component before being killed
-         * so later the state can be received from {@link #consumeRestoredStateForKey(String)}
+         * so later the state can be received from [consumeRestoredStateForKey]
          *
-         * @return S with your saved state.
+         * Returns `S` with your saved state.
          */
-        @NonNull
-        Bundle saveState();
+        fun saveState(): Bundle
+    }
+
+    private companion object {
+        private const val SAVED_COMPONENTS_KEY =
+            "androidx.lifecycle.BundlableSavedStateRegistry.key"
     }
 }