[Catalyst] Support SET api for int value

Bug: 351941813
Flag: EXEMPT library
Test: Manual
Change-Id: I62d1bc9c3ca07d9c815a1b0aca0f0c7cd275dba9
diff --git a/packages/SettingsLib/Graph/graph.proto b/packages/SettingsLib/Graph/graph.proto
index cbe602e..6b93cd7 100644
--- a/packages/SettingsLib/Graph/graph.proto
+++ b/packages/SettingsLib/Graph/graph.proto
@@ -77,6 +77,8 @@
   // Intent to show and locate the preference (might have highlight animation on
   // the preference).
   optional IntentProto launch_intent = 14;
+  // Descriptor of the preference value.
+  optional PreferenceValueDescriptorProto value_descriptor = 15;
 
   // Target of an Intent
   message ActionTarget {
@@ -103,9 +105,28 @@
 message PreferenceValueProto {
   oneof value {
     bool boolean_value = 1;
+    int32 int_value = 2;
   }
 }
 
+// Proto of preference value descriptor.
+message PreferenceValueDescriptorProto {
+  oneof type {
+    bool boolean_type = 1;
+    RangeValueProto range_value = 2;
+  }
+}
+
+// Proto of preference value that is between a range.
+message RangeValueProto {
+  // The lower bound (inclusive) of the range.
+  optional int32 min = 1;
+  // The upper bound (inclusive) of the range.
+  optional int32 max = 2;
+  // The increment step within the range. 0 means unset, which implies step size is 1.
+  optional int32 step = 3;
+}
+
 // Proto of android.content.Intent
 message IntentProto {
   // The action of the Intent.
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
index fdffe5d..5ceee6d 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/GetPreferenceGraphApiHandler.kt
@@ -65,6 +65,7 @@
     val visitedScreens: Set<String> = setOf(),
     val locale: Locale? = null,
     val includeValue: Boolean = true,
+    val includeValueDescriptor: Boolean = true,
 )
 
 object GetPreferenceGraphRequestCodec : MessageCodec<GetPreferenceGraphRequest> {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
index cf6bf70..2256bb3 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceGraphBuilder.kt
@@ -49,6 +49,7 @@
 import com.android.settingslib.metadata.PreferenceScreenRegistry
 import com.android.settingslib.metadata.PreferenceSummaryProvider
 import com.android.settingslib.metadata.PreferenceTitleProvider
+import com.android.settingslib.metadata.RangeValue
 import com.android.settingslib.preference.PreferenceScreenFactory
 import com.android.settingslib.preference.PreferenceScreenProvider
 import java.util.Locale
@@ -66,6 +67,7 @@
     private val builder by lazy { PreferenceGraphProto.newBuilder() }
     private val visitedScreens = mutableSetOf<String>().apply { addAll(request.visitedScreens) }
     private val includeValue = request.includeValue
+    private val includeValueDescriptor = request.includeValueDescriptor
 
     private suspend fun init() {
         for (key in request.screenKeys) {
@@ -284,14 +286,37 @@
             restricted = metadata.isRestricted(context)
         }
         persistent = metadata.isPersistent(context)
-        if (
-            includeValue &&
-                persistent &&
-                metadata is BooleanValue &&
-                metadata is PersistentPreference<*>
-        ) {
-            metadata.storage(context).getValue(metadata.key, Boolean::class.javaObjectType)?.let {
-                value = preferenceValueProto { booleanValue = it }
+        if (persistent) {
+            if (includeValue && metadata is PersistentPreference<*>) {
+                value = preferenceValueProto {
+                    when (metadata) {
+                        is BooleanValue ->
+                            metadata
+                                .storage(context)
+                                .getValue(metadata.key, Boolean::class.javaObjectType)
+                                ?.let { booleanValue = it }
+                        is RangeValue -> {
+                            metadata
+                                .storage(context)
+                                .getValue(metadata.key, Int::class.javaObjectType)
+                                ?.let { intValue = it }
+                        }
+                        else -> {}
+                    }
+                }
+            }
+            if (includeValueDescriptor) {
+                valueDescriptor = preferenceValueDescriptorProto {
+                    when (metadata) {
+                        is BooleanValue -> booleanType = true
+                        is RangeValue -> rangeValue = rangeValueProto {
+                                min = metadata.getMinValue(context)
+                                max = metadata.getMaxValue(context)
+                                step = metadata.getIncrementStep(context)
+                            }
+                        else -> {}
+                    }
+                }
             }
         }
         if (metadata is PreferenceScreenMetadata) {
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
index d8db1bb..6e4db1d 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/PreferenceSetterApi.kt
@@ -27,8 +27,10 @@
 import com.android.settingslib.metadata.BooleanValue
 import com.android.settingslib.metadata.PersistentPreference
 import com.android.settingslib.metadata.PreferenceAvailabilityProvider
+import com.android.settingslib.metadata.PreferenceMetadata
 import com.android.settingslib.metadata.PreferenceRestrictionProvider
 import com.android.settingslib.metadata.PreferenceScreenRegistry
+import com.android.settingslib.metadata.RangeValue
 import com.android.settingslib.metadata.ReadWritePermit
 
 /** Request to set preference value. */
@@ -114,27 +116,39 @@
         if (metadata is PreferenceAvailabilityProvider && !metadata.isAvailable(application)) {
             return PreferenceSetterResult.UNAVAILABLE
         }
+
+        fun <T> PreferenceMetadata.checkWritePermit(value: T): Int {
+            @Suppress("UNCHECKED_CAST") val preference = (this as PersistentPreference<T>)
+            return when (preference.getWritePermit(application, value, myUid, callingUid)) {
+                ReadWritePermit.ALLOW -> PreferenceSetterResult.OK
+                ReadWritePermit.DISALLOW -> PreferenceSetterResult.DISALLOW
+                ReadWritePermit.REQUIRE_APP_PERMISSION ->
+                    PreferenceSetterResult.REQUIRE_APP_PERMISSION
+                ReadWritePermit.REQUIRE_USER_AGREEMENT ->
+                    PreferenceSetterResult.REQUIRE_USER_AGREEMENT
+                else -> PreferenceSetterResult.INTERNAL_ERROR
+            }
+        }
+
         val storage = metadata.storage(application)
         val value = request.value
         try {
             if (value.hasBooleanValue()) {
                 if (metadata !is BooleanValue) return PreferenceSetterResult.INVALID_REQUEST
                 val booleanValue = value.booleanValue
-                @Suppress("UNCHECKED_CAST")
-                val booleanPreference = metadata as PersistentPreference<Boolean>
-                when (
-                    booleanPreference.getWritePermit(application, booleanValue, myUid, callingUid)
-                ) {
-                    ReadWritePermit.ALLOW -> {}
-                    ReadWritePermit.DISALLOW -> return PreferenceSetterResult.DISALLOW
-                    ReadWritePermit.REQUIRE_APP_PERMISSION ->
-                        return PreferenceSetterResult.REQUIRE_APP_PERMISSION
-                    ReadWritePermit.REQUIRE_USER_AGREEMENT ->
-                        return PreferenceSetterResult.REQUIRE_USER_AGREEMENT
-                    else -> return PreferenceSetterResult.INTERNAL_ERROR
-                }
+                val resultCode = metadata.checkWritePermit(booleanValue)
+                if (resultCode != PreferenceSetterResult.OK) return resultCode
                 storage.setValue(key, Boolean::class.javaObjectType, booleanValue)
                 return PreferenceSetterResult.OK
+            } else if (value.hasIntValue()) {
+                val intValue = value.intValue
+                val resultCode = metadata.checkWritePermit(intValue)
+                if (resultCode != PreferenceSetterResult.OK) return resultCode
+                if (metadata is RangeValue && !metadata.isValidValue(application, intValue)) {
+                    return PreferenceSetterResult.INVALID_REQUEST
+                }
+                storage.setValue(key, Int::class.javaObjectType, intValue)
+                return PreferenceSetterResult.OK
             }
         } catch (e: Exception) {
             return PreferenceSetterResult.INTERNAL_ERROR
diff --git a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
index d7dae77..dee32d9 100644
--- a/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
+++ b/packages/SettingsLib/Graph/src/com/android/settingslib/graph/ProtoDsl.kt
@@ -24,7 +24,9 @@
 import com.android.settingslib.graph.proto.PreferenceProto
 import com.android.settingslib.graph.proto.PreferenceProto.ActionTarget
 import com.android.settingslib.graph.proto.PreferenceScreenProto
+import com.android.settingslib.graph.proto.PreferenceValueDescriptorProto
 import com.android.settingslib.graph.proto.PreferenceValueProto
+import com.android.settingslib.graph.proto.RangeValueProto
 import com.android.settingslib.graph.proto.TextProto
 
 /** Returns root or null. */
@@ -89,6 +91,16 @@
 inline fun preferenceValueProto(init: PreferenceValueProto.Builder.() -> Unit) =
     PreferenceValueProto.newBuilder().also(init).build()
 
+/** Kotlin DSL-style builder for [PreferenceValueDescriptorProto]. */
+@JvmSynthetic
+inline fun preferenceValueDescriptorProto(init: PreferenceValueDescriptorProto.Builder.() -> Unit) =
+    PreferenceValueDescriptorProto.newBuilder().also(init).build()
+
+/** Kotlin DSL-style builder for [RangeValueProto]. */
+@JvmSynthetic
+inline fun rangeValueProto(init: RangeValueProto.Builder.() -> Unit) =
+    RangeValueProto.newBuilder().also(init).build()
+
 /** Kotlin DSL-style builder for [TextProto]. */
 @JvmSynthetic
 inline fun textProto(init: TextProto.Builder.() -> Unit) = TextProto.newBuilder().also(init).build()