Add `Long` support to Saved State KMP

RelNote: "SavedState KMP now supports Long."
Test: SavedStateTest
Bug: 334076622
Change-Id: I4c180e12c8259436628e5b6b62a0dfa38f003be6
diff --git a/savedstate/savedstate/api/current.txt b/savedstate/savedstate/api/current.txt
index 7378076..fe1c8f0 100644
--- a/savedstate/savedstate/api/current.txt
+++ b/savedstate/savedstate/api/current.txt
@@ -23,6 +23,8 @@
     method public inline java.util.List<java.lang.Integer> getIntList(String key);
     method public inline java.util.List<java.lang.Integer> getIntListOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<java.lang.Integer>> defaultValue);
     method public inline int getIntOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Integer> defaultValue);
+    method public inline long getLong(String key);
+    method public inline long getLongOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Long> defaultValue);
     method public inline <reified T extends android.os.Parcelable> T getParcelable(String key);
     method public inline <reified T extends android.os.Parcelable> java.util.List<T> getParcelableList(String key);
     method public inline <reified T extends android.os.Parcelable> java.util.List<T> getParcelableListOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> defaultValue);
@@ -86,6 +88,7 @@
     method public inline void putFloat(String key, float value);
     method public inline void putInt(String key, int value);
     method public inline void putIntList(String key, java.util.List<java.lang.Integer> values);
+    method public inline void putLong(String key, long value);
     method public inline <reified T extends android.os.Parcelable> void putParcelable(String key, T value);
     method public inline <reified T extends android.os.Parcelable> void putParcelableList(String key, java.util.List<? extends T> values);
     method public inline void putSavedState(String key, android.os.Bundle value);
diff --git a/savedstate/savedstate/api/restricted_current.txt b/savedstate/savedstate/api/restricted_current.txt
index 27b0b57..47dcf78 100644
--- a/savedstate/savedstate/api/restricted_current.txt
+++ b/savedstate/savedstate/api/restricted_current.txt
@@ -25,6 +25,8 @@
     method public inline int getIntOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Integer> defaultValue);
     method @kotlin.PublishedApi internal inline <reified T> java.util.List<T> getListResultOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> defaultValue, kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>?> currentValue);
     method @kotlin.PublishedApi internal inline <reified T> java.util.List<T> getListResultOrThrow(String key, kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>?> currentValue);
+    method public inline long getLong(String key);
+    method public inline long getLongOrElse(String key, kotlin.jvm.functions.Function0<java.lang.Long> defaultValue);
     method public inline <reified T extends android.os.Parcelable> T getParcelable(String key);
     method public inline <reified T extends android.os.Parcelable> java.util.List<T> getParcelableList(String key);
     method public inline <reified T extends android.os.Parcelable> java.util.List<T> getParcelableListOrElse(String key, kotlin.jvm.functions.Function0<? extends java.util.List<? extends T>> defaultValue);
@@ -90,6 +92,7 @@
     method public inline void putFloat(String key, float value);
     method public inline void putInt(String key, int value);
     method public inline void putIntList(String key, java.util.List<java.lang.Integer> values);
+    method public inline void putLong(String key, long value);
     method public inline <reified T extends android.os.Parcelable> void putParcelable(String key, T value);
     method public inline <reified T extends android.os.Parcelable> void putParcelableList(String key, java.util.List<? extends T> values);
     method public inline void putSavedState(String key, android.os.Bundle value);
@@ -124,6 +127,7 @@
     field public static final double DEFAULT_DOUBLE = 0.0;
     field public static final float DEFAULT_FLOAT = 0.0f;
     field public static final int DEFAULT_INT = 0; // 0x0
+    field public static final long DEFAULT_LONG = 0L; // 0x0L
   }
 
 }
diff --git a/savedstate/savedstate/bcv/native/current.txt b/savedstate/savedstate/bcv/native/current.txt
index 0406089..1a70510 100644
--- a/savedstate/savedstate/bcv/native/current.txt
+++ b/savedstate/savedstate/bcv/native/current.txt
@@ -69,6 +69,8 @@
     final inline fun getIntList(kotlin/String): kotlin.collections/List<kotlin/Int> // androidx.savedstate/SavedStateReader.getIntList|getIntList(kotlin.String){}[0]
     final inline fun getIntListOrElse(kotlin/String, kotlin/Function0<kotlin.collections/List<kotlin/Int>>): kotlin.collections/List<kotlin/Int> // androidx.savedstate/SavedStateReader.getIntListOrElse|getIntListOrElse(kotlin.String;kotlin.Function0<kotlin.collections.List<kotlin.Int>>){}[0]
     final inline fun getIntOrElse(kotlin/String, kotlin/Function0<kotlin/Int>): kotlin/Int // androidx.savedstate/SavedStateReader.getIntOrElse|getIntOrElse(kotlin.String;kotlin.Function0<kotlin.Int>){}[0]
+    final inline fun getLong(kotlin/String): kotlin/Long // androidx.savedstate/SavedStateReader.getLong|getLong(kotlin.String){}[0]
+    final inline fun getLongOrElse(kotlin/String, kotlin/Function0<kotlin/Long>): kotlin/Long // androidx.savedstate/SavedStateReader.getLongOrElse|getLongOrElse(kotlin.String;kotlin.Function0<kotlin.Long>){}[0]
     final inline fun getSavedState(kotlin/String): androidx.savedstate/SavedState // androidx.savedstate/SavedStateReader.getSavedState|getSavedState(kotlin.String){}[0]
     final inline fun getSavedStateOrElse(kotlin/String, kotlin/Function0<androidx.savedstate/SavedState>): androidx.savedstate/SavedState // androidx.savedstate/SavedStateReader.getSavedStateOrElse|getSavedStateOrElse(kotlin.String;kotlin.Function0<androidx.savedstate.SavedState>){}[0]
     final inline fun getString(kotlin/String): kotlin/String // androidx.savedstate/SavedStateReader.getString|getString(kotlin.String){}[0]
@@ -95,6 +97,7 @@
     final inline fun putFloat(kotlin/String, kotlin/Float) // androidx.savedstate/SavedStateWriter.putFloat|putFloat(kotlin.String;kotlin.Float){}[0]
     final inline fun putInt(kotlin/String, kotlin/Int) // androidx.savedstate/SavedStateWriter.putInt|putInt(kotlin.String;kotlin.Int){}[0]
     final inline fun putIntList(kotlin/String, kotlin.collections/List<kotlin/Int>) // androidx.savedstate/SavedStateWriter.putIntList|putIntList(kotlin.String;kotlin.collections.List<kotlin.Int>){}[0]
+    final inline fun putLong(kotlin/String, kotlin/Long) // androidx.savedstate/SavedStateWriter.putLong|putLong(kotlin.String;kotlin.Long){}[0]
     final inline fun putSavedState(kotlin/String, androidx.savedstate/SavedState) // androidx.savedstate/SavedStateWriter.putSavedState|putSavedState(kotlin.String;androidx.savedstate.SavedState){}[0]
     final inline fun putString(kotlin/String, kotlin/String) // androidx.savedstate/SavedStateWriter.putString|putString(kotlin.String;kotlin.String){}[0]
     final inline fun putStringList(kotlin/String, kotlin.collections/List<kotlin/String>) // androidx.savedstate/SavedStateWriter.putStringList|putStringList(kotlin.String;kotlin.collections.List<kotlin.String>){}[0]
@@ -110,6 +113,8 @@
         final fun <get-DEFAULT_FLOAT>(): kotlin/Float // androidx.savedstate.internal/SavedStateUtils.DEFAULT_FLOAT.<get-DEFAULT_FLOAT>|<get-DEFAULT_FLOAT>(){}[0]
     final const val DEFAULT_INT // androidx.savedstate.internal/SavedStateUtils.DEFAULT_INT|{}DEFAULT_INT[0]
         final fun <get-DEFAULT_INT>(): kotlin/Int // androidx.savedstate.internal/SavedStateUtils.DEFAULT_INT.<get-DEFAULT_INT>|<get-DEFAULT_INT>(){}[0]
+    final const val DEFAULT_LONG // androidx.savedstate.internal/SavedStateUtils.DEFAULT_LONG|{}DEFAULT_LONG[0]
+        final fun <get-DEFAULT_LONG>(): kotlin/Long // androidx.savedstate.internal/SavedStateUtils.DEFAULT_LONG.<get-DEFAULT_LONG>|<get-DEFAULT_LONG>(){}[0]
 
     final inline fun <#A1: reified kotlin/Any?> getValueFromSavedState(kotlin/String, kotlin/Function0<#A1?>, kotlin/Function1<kotlin/String, kotlin/Boolean>, kotlin/Function0<#A1>): #A1 // androidx.savedstate.internal/SavedStateUtils.getValueFromSavedState|getValueFromSavedState(kotlin.String;kotlin.Function0<0:0?>;kotlin.Function1<kotlin.String,kotlin.Boolean>;kotlin.Function0<0:0>){0§<kotlin.Any?>}[0]
     final inline fun keyNotFoundError(kotlin/String): kotlin/Nothing // androidx.savedstate.internal/SavedStateUtils.keyNotFoundError|keyNotFoundError(kotlin.String){}[0]
diff --git a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
index 73eea19..c17f0fa 100644
--- a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
+++ b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateReader.android.kt
@@ -60,6 +60,14 @@
         return getSingleResultOrElse(key, defaultValue) { source.getInt(key) }
     }
 
+    actual inline fun getLong(key: String): Long {
+        return getSingleResultOrThrow(key) { source.getLong(key) }
+    }
+
+    actual inline fun getLongOrElse(key: String, defaultValue: () -> Long): Long {
+        return getSingleResultOrElse(key, defaultValue) { source.getLong(key) }
+    }
+
     /**
      * Retrieves a [Parcelable] object associated with the specified key. Throws an
      * [IllegalStateException] if the key doesn't exist.
diff --git a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
index 2d1c86e..68df552 100644
--- a/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
+++ b/savedstate/savedstate/src/androidMain/kotlin/androidx/savedstate/SavedStateWriter.android.kt
@@ -38,6 +38,10 @@
         source.putInt(key, value)
     }
 
+    actual inline fun putLong(key: String, value: Long) {
+        source.putLong(key, value)
+    }
+
     /**
      * Stores an [Parcelable] value associated with the specified key in the [SavedState].
      *
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
index 4f4d741..e3f37ac 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateReader.kt
@@ -115,6 +115,27 @@
     public inline fun getIntOrElse(key: String, defaultValue: () -> Int): Int
 
     /**
+     * Retrieves an [Long] value associated with the specified [key]. Throws an
+     * [IllegalStateException] if the [key] doesn't exist.
+     *
+     * @param key The [key] to retrieve the value for.
+     * @return The [Long] value associated with the [key].
+     * @throws IllegalStateException If the [key] is not found.
+     */
+    public inline fun getLong(key: String): Long
+
+    /**
+     * Retrieves an [Int] value associated with the specified [key], or a default value if the [key]
+     * doesn't exist.
+     *
+     * @param key The [key] to retrieve the value for.
+     * @param defaultValue A function providing the default value if the [key] is not found.
+     * @return The [Int] value associated with the [key], or the default value if the [key] is not
+     *   found.
+     */
+    public inline fun getLongOrElse(key: String, defaultValue: () -> Long): Long
+
+    /**
      * Retrieves a [String] value associated with the specified [key]. Throws an
      * [IllegalStateException] if the [key] doesn't exist.
      *
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
index c290244..bf7aff6 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/SavedStateWriter.kt
@@ -63,6 +63,14 @@
     public inline fun putInt(key: String, value: Int)
 
     /**
+     * Stores an int value associated with the specified key in the [SavedState].
+     *
+     * @param key The key to associate the value with.
+     * @param value The [Long] value to store.
+     */
+    public inline fun putLong(key: String, value: Long)
+
+    /**
      * Stores a string value associated with the specified key in the [SavedState].
      *
      * @param key The key to associate the value with.
diff --git a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
index 8cebe5e9..bf602bd 100644
--- a/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
+++ b/savedstate/savedstate/src/commonMain/kotlin/androidx/savedstate/internal/SavedStateUtils.kt
@@ -20,9 +20,10 @@
 internal object SavedStateUtils {
 
     const val DEFAULT_BOOLEAN = false
-    const val DEFAULT_FLOAT = 0f
+    const val DEFAULT_FLOAT = 0F
     const val DEFAULT_DOUBLE = 0.0
     const val DEFAULT_INT = 0
+    const val DEFAULT_LONG = 0L
 
     @Suppress("NOTHING_TO_INLINE")
     inline fun keyNotFoundError(key: String): Nothing =
diff --git a/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt b/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
index 1034b38..b40f557 100644
--- a/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
+++ b/savedstate/savedstate/src/commonTest/kotlin/androidx/savedstate/SavedStateTest.kt
@@ -245,6 +245,42 @@
     }
 
     @Test
+    fun getLong_whenSet_returns() {
+        val underTest = savedState { putLong(KEY_1, Long.MAX_VALUE) }
+        val actual = underTest.read { getLong(KEY_1) }
+
+        assertThat(actual).isEqualTo(Long.MAX_VALUE)
+    }
+
+    @Test
+    fun getLong_whenNotSet_throws() {
+        assertThrows<IllegalStateException> { savedState().read { getLong(KEY_1) } }
+    }
+
+    @Test
+    fun getLong_whenSet_differentType_returnsDefault() {
+        val underTest = savedState { putBoolean(KEY_1, false) }
+        val actual = underTest.read { getLong(KEY_1) }
+
+        assertThat(actual).isEqualTo(SavedStateUtils.DEFAULT_LONG)
+    }
+
+    @Test
+    fun getLongOrElse_whenSet_returns() {
+        val underTest = savedState { putLong(KEY_1, Long.MAX_VALUE) }
+        val actual = underTest.read { getLongOrElse(KEY_1) { Long.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Long.MAX_VALUE)
+    }
+
+    @Test
+    fun getLongOrElse_whenNotSet_returnsElse() {
+        val actual = savedState().read { getLongOrElse(KEY_1) { Long.MIN_VALUE } }
+
+        assertThat(actual).isEqualTo(Long.MIN_VALUE)
+    }
+
+    @Test
     fun getString_whenSet_returns() {
         val underTest = savedState { putString(KEY_1, STRING_VALUE) }
         val actual = underTest.read { getString(KEY_1) }
diff --git a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
index 5df4565..01e3cd9 100644
--- a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
+++ b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateReader.nonAndroid.kt
@@ -59,6 +59,14 @@
             source.map[key] as? Int ?: SavedStateUtils.DEFAULT_INT
         }
 
+    actual inline fun getLong(key: String): Long =
+        getSingleResultOrThrow(key) { source.map[key] as? Long ?: SavedStateUtils.DEFAULT_LONG }
+
+    actual inline fun getLongOrElse(key: String, defaultValue: () -> Long): Long =
+        getSingleResultOrElse(key, defaultValue) {
+            source.map[key] as? Long ?: SavedStateUtils.DEFAULT_LONG
+        }
+
     actual inline fun getString(key: String): String =
         getSingleResultOrThrow(key) { source.map[key] as? String }
 
diff --git a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
index 8bb79dd..4b614d6 100644
--- a/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
+++ b/savedstate/savedstate/src/nonAndroidMain/kotlin/androidx/savedstate/SavedStateWriter.nonAndroid.kt
@@ -38,6 +38,10 @@
         source.map[key] = value
     }
 
+    actual inline fun putLong(key: String, value: Long) {
+        source.map[key] = value
+    }
+
     actual inline fun putString(key: String, value: String) {
         source.map[key] = value
     }