Define Settings Preference Service API data models

Bug: 375075504
Test: atest CtsSettingsPreferenceServiceTest
Flag: com.android.settingslib.flags.settings_catalyst
Change-Id: Ic491393b7617a2104b19aa1d64a83d6fe39529b8
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 26fbd27..39fcf76 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -21,6 +21,7 @@
     java_aconfig_libraries: [
         // !!! KEEP THIS LIST ALPHABETICAL !!!
         "aconfig_mediacodec_flags_java_lib",
+        "aconfig_settingslib_flags_java_lib",
         "aconfig_trade_in_mode_flags_java_lib",
         "android-sdk-flags-java",
         "android.adaptiveauth.flags-aconfig-java",
@@ -1749,3 +1750,19 @@
     ],
     min_sdk_version: "apex_inherit",
 }
+
+// Settings Lib
+aconfig_declarations {
+    name: "aconfig_settingslib_flags",
+    package: "com.android.settingslib.flags",
+    container: "system",
+    srcs: [
+        "packages/SettingsLib/aconfig/settingslib.aconfig",
+    ],
+}
+
+java_aconfig_library {
+    name: "aconfig_settingslib_flags_java_lib",
+    aconfig_declarations: "aconfig_settingslib_flags",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index 7f74a62..03287ce 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -263,6 +263,7 @@
     field public static final String READ_SMS = "android.permission.READ_SMS";
     field public static final String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
     field public static final String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
+    field @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final String READ_SYSTEM_PREFERENCES = "android.permission.READ_SYSTEM_PREFERENCES";
     field public static final String READ_VOICEMAIL = "com.android.voicemail.permission.READ_VOICEMAIL";
     field public static final String REBOOT = "android.permission.REBOOT";
     field public static final String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
@@ -334,6 +335,7 @@
     field public static final String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
     field public static final String WRITE_SETTINGS = "android.permission.WRITE_SETTINGS";
     field public static final String WRITE_SYNC_SETTINGS = "android.permission.WRITE_SYNC_SETTINGS";
+    field @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public static final String WRITE_SYSTEM_PREFERENCES = "android.permission.WRITE_SYSTEM_PREFERENCES";
     field public static final String WRITE_VOICEMAIL = "com.android.voicemail.permission.WRITE_VOICEMAIL";
   }
 
@@ -41985,6 +41987,174 @@
 
 }
 
+package android.service.settings.preferences {
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class GetValueRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public String getPreferenceKey();
+    method @NonNull public String getScreenKey();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.GetValueRequest> CREATOR;
+  }
+
+  public static final class GetValueRequest.Builder {
+    ctor public GetValueRequest.Builder(@NonNull String, @NonNull String);
+    method @NonNull public android.service.settings.preferences.GetValueRequest build();
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class GetValueResult implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.service.settings.preferences.SettingsPreferenceMetadata getMetadata();
+    method public int getResultCode();
+    method @Nullable public android.service.settings.preferences.SettingsPreferenceValue getValue();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.GetValueResult> CREATOR;
+    field public static final int RESULT_DISALLOW = 4; // 0x4
+    field public static final int RESULT_INTERNAL_ERROR = 6; // 0x6
+    field public static final int RESULT_INVALID_REQUEST = 5; // 0x5
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_REQUIRE_APP_PERMISSION = 3; // 0x3
+    field public static final int RESULT_UNAVAILABLE = 2; // 0x2
+    field public static final int RESULT_UNSUPPORTED = 1; // 0x1
+  }
+
+  public static final class GetValueResult.Builder {
+    ctor public GetValueResult.Builder(int);
+    method @NonNull public android.service.settings.preferences.GetValueResult build();
+    method @NonNull public android.service.settings.preferences.GetValueResult.Builder setMetadata(@Nullable android.service.settings.preferences.SettingsPreferenceMetadata);
+    method @NonNull public android.service.settings.preferences.GetValueResult.Builder setValue(@Nullable android.service.settings.preferences.SettingsPreferenceValue);
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class MetadataRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.MetadataRequest> CREATOR;
+  }
+
+  public static final class MetadataRequest.Builder {
+    ctor public MetadataRequest.Builder();
+    method @NonNull public android.service.settings.preferences.MetadataRequest build();
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class MetadataResult implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<android.service.settings.preferences.SettingsPreferenceMetadata> getMetadataList();
+    method public int getResultCode();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.MetadataResult> CREATOR;
+    field public static final int RESULT_INTERNAL_ERROR = 2; // 0x2
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_UNSUPPORTED = 1; // 0x1
+  }
+
+  public static final class MetadataResult.Builder {
+    ctor public MetadataResult.Builder(int);
+    method @NonNull public android.service.settings.preferences.MetadataResult build();
+    method @NonNull public android.service.settings.preferences.MetadataResult.Builder setMetadataList(@NonNull java.util.List<android.service.settings.preferences.SettingsPreferenceMetadata>);
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class SetValueRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public String getPreferenceKey();
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue getPreferenceValue();
+    method @NonNull public String getScreenKey();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SetValueRequest> CREATOR;
+  }
+
+  public static final class SetValueRequest.Builder {
+    ctor public SetValueRequest.Builder(@NonNull String, @NonNull String, @NonNull android.service.settings.preferences.SettingsPreferenceValue);
+    method @NonNull public android.service.settings.preferences.SetValueRequest build();
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class SetValueResult implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getResultCode();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SetValueResult> CREATOR;
+    field public static final int RESULT_DISABLED = 2; // 0x2
+    field public static final int RESULT_DISALLOW = 7; // 0x7
+    field public static final int RESULT_INTERNAL_ERROR = 9; // 0x9
+    field public static final int RESULT_INVALID_REQUEST = 8; // 0x8
+    field public static final int RESULT_OK = 0; // 0x0
+    field public static final int RESULT_REQUIRE_APP_PERMISSION = 5; // 0x5
+    field public static final int RESULT_REQUIRE_USER_CONSENT = 6; // 0x6
+    field public static final int RESULT_RESTRICTED = 3; // 0x3
+    field public static final int RESULT_UNAVAILABLE = 4; // 0x4
+    field public static final int RESULT_UNSUPPORTED = 1; // 0x1
+  }
+
+  public static final class SetValueResult.Builder {
+    ctor public SetValueResult.Builder(int);
+    method @NonNull public android.service.settings.preferences.SetValueResult build();
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class SettingsPreferenceMetadata implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getBreadcrumbs();
+    method @NonNull public android.os.Bundle getExtras();
+    method @NonNull public String getKey();
+    method @Nullable public android.app.PendingIntent getLaunchIntent();
+    method @NonNull public java.util.List<java.lang.String> getReadPermissions();
+    method @NonNull public String getScreenKey();
+    method @Nullable public String getSummary();
+    method @Nullable public String getTitle();
+    method @NonNull public java.util.List<java.lang.String> getWritePermissions();
+    method public int getWriteSensitivity();
+    method public boolean isAvailable();
+    method public boolean isEnabled();
+    method public boolean isRestricted();
+    method public boolean isWritable();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SettingsPreferenceMetadata> CREATOR;
+    field public static final int INTENT_ONLY = 2; // 0x2
+    field public static final int NOT_SENSITIVE = 0; // 0x0
+    field public static final int SENSITIVE = 1; // 0x1
+  }
+
+  public static final class SettingsPreferenceMetadata.Builder {
+    ctor public SettingsPreferenceMetadata.Builder(@NonNull String, @NonNull String);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata build();
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setAvailable(boolean);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setBreadcrumbs(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setEnabled(boolean);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setLaunchIntent(@Nullable android.app.PendingIntent);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setReadPermissions(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setRestricted(boolean);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setSummary(@Nullable String);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setTitle(@Nullable String);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setWritable(boolean);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setWritePermissions(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceMetadata.Builder setWriteSensitivity(int);
+  }
+
+  @FlaggedApi("com.android.settingslib.flags.settings_catalyst") public final class SettingsPreferenceValue implements android.os.Parcelable {
+    method public int describeContents();
+    method public boolean getBooleanValue();
+    method public double getDoubleValue();
+    method public long getLongValue();
+    method @Nullable public String getStringValue();
+    method public int getType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.service.settings.preferences.SettingsPreferenceValue> CREATOR;
+    field public static final int TYPE_BOOLEAN = 0; // 0x0
+    field public static final int TYPE_DOUBLE = 2; // 0x2
+    field public static final int TYPE_LONG = 1; // 0x1
+    field public static final int TYPE_STRING = 3; // 0x3
+  }
+
+  public static final class SettingsPreferenceValue.Builder {
+    ctor public SettingsPreferenceValue.Builder(int);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue build();
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue.Builder setBooleanValue(boolean);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue.Builder setDoubleValue(double);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue.Builder setLongValue(long);
+    method @NonNull public android.service.settings.preferences.SettingsPreferenceValue.Builder setStringValue(@Nullable String);
+  }
+
+}
+
 package android.service.textservice {
 
   public abstract class SpellCheckerService extends android.app.Service {
diff --git a/core/java/android/service/settings/preferences/GetValueRequest.aidl b/core/java/android/service/settings/preferences/GetValueRequest.aidl
new file mode 100644
index 0000000..2a0eb09
--- /dev/null
+++ b/core/java/android/service/settings/preferences/GetValueRequest.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable GetValueRequest;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/GetValueRequest.java b/core/java/android/service/settings/preferences/GetValueRequest.java
new file mode 100644
index 0000000..4f82800
--- /dev/null
+++ b/core/java/android/service/settings/preferences/GetValueRequest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.flags.Flags;
+
+import java.util.Objects;
+
+/**
+ * Request parameters to retrieve the current value of a Settings Preference.
+ *
+ * <p>This object passed to {@link SettingsPreferenceService#onGetPreferenceValue} will result
+ * in a {@link GetValueResult}.
+ *
+ * <ul>
+ *   <li>{@link #getScreenKey} is a parameter to distinguish the container screen
+ *   of a preference as a preference key may not be unique within its application.
+ *   <li>{@link #getPreferenceKey} is a parameter to identify the preference for which the value is
+ *   being requested. These keys will be unique with their Preference Screen, but may not be unique
+ *   within their application, so it is required to pair this with {@link #getScreenKey} to
+ *   ensure this request matches the intended target.
+ * </ul>
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class GetValueRequest implements Parcelable {
+
+    @NonNull
+    private final String mScreenKey;
+    @NonNull
+    private final String mPreferenceKey;
+
+    /**
+     * Returns the screen key of requested Preference.
+     */
+    @NonNull
+    public String getScreenKey() {
+        return mScreenKey;
+    }
+
+    /**
+     * Returns the key of requested Preference.
+     */
+    @NonNull
+    public String getPreferenceKey() {
+        return mPreferenceKey;
+    }
+
+    private GetValueRequest(@NonNull Builder builder) {
+        mScreenKey = builder.mScreenKey;
+        mPreferenceKey = builder.mPreferenceKey;
+    }
+
+    private GetValueRequest(@NonNull Parcel in) {
+        mScreenKey = Objects.requireNonNull(in.readString8());
+        mPreferenceKey = Objects.requireNonNull(in.readString8());
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mScreenKey);
+        dest.writeString8(mPreferenceKey);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link GetValueRequest}.
+     */
+    @NonNull
+    public static final Creator<GetValueRequest> CREATOR = new Creator<GetValueRequest>() {
+        @Override
+        public GetValueRequest createFromParcel(@NonNull Parcel in) {
+            return new GetValueRequest(in);
+        }
+
+        @Override
+        public GetValueRequest[] newArray(int size) {
+            return new GetValueRequest[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link GetValueRequest}.
+     */
+    public static final class Builder {
+        private final String mScreenKey;
+        private final String mPreferenceKey;
+
+        /**
+         * Create Builder instance.
+         * @param screenKey required to be not empty
+         * @param preferenceKey required to be not empty
+         */
+        public Builder(@NonNull String screenKey, @NonNull String preferenceKey) {
+            if (TextUtils.isEmpty(screenKey)) {
+                throw new IllegalArgumentException("screenKey cannot be empty");
+            }
+            if (TextUtils.isEmpty(preferenceKey)) {
+                throw new IllegalArgumentException("preferenceKey cannot be empty");
+            }
+            mScreenKey = screenKey;
+            mPreferenceKey = preferenceKey;
+        }
+
+        /**
+         * Constructs an immutable {@link GetValueRequest} object.
+         */
+        @NonNull
+        public GetValueRequest build() {
+            return new GetValueRequest(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/GetValueResult.aidl b/core/java/android/service/settings/preferences/GetValueResult.aidl
new file mode 100644
index 0000000..b5ebd35
--- /dev/null
+++ b/core/java/android/service/settings/preferences/GetValueResult.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable GetValueResult;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/GetValueResult.java b/core/java/android/service/settings/preferences/GetValueResult.java
new file mode 100644
index 0000000..369dea7
--- /dev/null
+++ b/core/java/android/service/settings/preferences/GetValueResult.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Result object given a corresponding {@link GetValueRequest}.
+ * <ul>
+ *   <li>If the request was successful, {@link #getResultCode} will be {@link #RESULT_OK},
+ *   {@link #getValue} will be populated with the settings preference value and
+ *   {@link #getMetadata} will be populated with its metadata.
+ *   <li>If the request is unsuccessful, {@link #getResultCode} be a value other than
+ *   {@link #RESULT_OK} - see documentation for those possibilities to understand the cause
+ *   of the failure.
+ * </ul>
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class GetValueResult implements Parcelable {
+
+    @ResultCode
+    private final int mResultCode;
+    @Nullable
+    private final SettingsPreferenceValue mValue;
+    @Nullable
+    private final SettingsPreferenceMetadata mMetadata;
+
+    /**
+     * Returns the result code indicating status of the request.
+     */
+    @ResultCode
+    public int getResultCode() {
+        return mResultCode;
+    }
+
+    /**
+     * Returns the value of requested Preference if request successful.
+     */
+    @Nullable
+    public SettingsPreferenceValue getValue() {
+        return mValue;
+    }
+
+    /**
+     * Returns the metadata of requested Preference if request successful.
+     */
+    @Nullable
+    public SettingsPreferenceMetadata getMetadata() {
+        return mMetadata;
+    }
+
+    /** @hide */
+    @IntDef(prefix = { "RESULT_" }, value = {
+            RESULT_OK,
+            RESULT_UNSUPPORTED,
+            RESULT_UNAVAILABLE,
+            RESULT_REQUIRE_APP_PERMISSION,
+            RESULT_DISALLOW,
+            RESULT_INVALID_REQUEST,
+            RESULT_INTERNAL_ERROR,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ResultCode {
+    }
+
+    /** Request is successful. */
+    public static final int RESULT_OK = 0;
+    /**
+     * Requested preference is not supported by this API.
+     * <p>Retry not advised.
+     */
+    public static final int RESULT_UNSUPPORTED = 1;
+    /**
+     * Preference is currently not available, likely due to device state or the state of
+     * a dependency.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_UNAVAILABLE = 2;
+    /**
+     * Requested preference requires permissions not held by the calling application.
+     * <p>Retry may succeed if necessary permissions are obtained.
+     */
+    public static final int RESULT_REQUIRE_APP_PERMISSION = 3;
+    /**
+     * Requested preference is not allowed for access in this API under the current device policy.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_DISALLOW = 4;
+    /**
+     * Request object is not valid.
+     * <p>Retry not advised with current parameters.
+     */
+    public static final int RESULT_INVALID_REQUEST = 5;
+    /**
+     * API call failed due to an issue with the service binding.
+     * <p>Retry may succeed.
+     */
+    public static final int RESULT_INTERNAL_ERROR = 6;
+
+
+    private GetValueResult(@NonNull Builder builder) {
+        mResultCode = builder.mResultCode;
+        mValue = builder.mValue;
+        mMetadata = builder.mMetadata;
+    }
+
+    private GetValueResult(@NonNull Parcel in) {
+        mResultCode = in.readInt();
+        mValue = in.readParcelable(SettingsPreferenceValue.class.getClassLoader(),
+                SettingsPreferenceValue.class);
+        mMetadata = in.readParcelable(SettingsPreferenceMetadata.class.getClassLoader(),
+                SettingsPreferenceMetadata.class);
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mResultCode);
+        dest.writeParcelable(mValue, flags);
+        dest.writeParcelable(mMetadata, flags);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link GetValueResult}.
+     */
+    @NonNull
+    public static final Creator<GetValueResult> CREATOR = new Creator<>() {
+        @Override
+        public GetValueResult createFromParcel(@NonNull Parcel in) {
+            return new GetValueResult(in);
+        }
+
+        @Override
+        public GetValueResult[] newArray(int size) {
+            return new GetValueResult[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link GetValueResult}.
+     */
+    public static final class Builder {
+        @ResultCode
+        private final int mResultCode;
+        private SettingsPreferenceValue mValue;
+        private SettingsPreferenceMetadata mMetadata;
+
+        /**
+         * Create Builder instance.
+         * @param resultCode indicates status of the request
+         */
+        public Builder(@ResultCode int resultCode) {
+            mResultCode = resultCode;
+        }
+
+        /**
+         * Sets the preference value on the result.
+         */
+        @NonNull
+        public Builder setValue(@Nullable SettingsPreferenceValue value) {
+            mValue = value;
+            return this;
+        }
+
+        /**
+         * Sets the metadata on the result.
+         */
+        @NonNull
+        public Builder setMetadata(@Nullable SettingsPreferenceMetadata metadata) {
+            mMetadata = metadata;
+            return this;
+        }
+
+        /**
+         * Constructs an immutable {@link GetValueResult} object.
+         */
+        @NonNull
+        public GetValueResult build() {
+            return new GetValueResult(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/IGetValueCallback.aidl b/core/java/android/service/settings/preferences/IGetValueCallback.aidl
new file mode 100644
index 0000000..bbc7423
--- /dev/null
+++ b/core/java/android/service/settings/preferences/IGetValueCallback.aidl
@@ -0,0 +1,9 @@
+package android.service.settings.preferences;
+
+import android.service.settings.preferences.GetValueResult;
+
+/** @hide */
+oneway interface IGetValueCallback {
+    void onSuccess(in GetValueResult result) = 1;
+    void onFailure() = 2;
+}
diff --git a/core/java/android/service/settings/preferences/IMetadataCallback.aidl b/core/java/android/service/settings/preferences/IMetadataCallback.aidl
new file mode 100644
index 0000000..3bd5ebe
--- /dev/null
+++ b/core/java/android/service/settings/preferences/IMetadataCallback.aidl
@@ -0,0 +1,9 @@
+package android.service.settings.preferences;
+
+import android.service.settings.preferences.MetadataResult;
+
+/** @hide */
+oneway interface IMetadataCallback {
+    void onSuccess(in MetadataResult result);
+    void onFailure();
+}
diff --git a/core/java/android/service/settings/preferences/ISetValueCallback.aidl b/core/java/android/service/settings/preferences/ISetValueCallback.aidl
new file mode 100644
index 0000000..0765660
--- /dev/null
+++ b/core/java/android/service/settings/preferences/ISetValueCallback.aidl
@@ -0,0 +1,9 @@
+package android.service.settings.preferences;
+
+import android.service.settings.preferences.SetValueResult;
+
+/** @hide */
+oneway interface ISetValueCallback {
+    void onSuccess(in SetValueResult result);
+    void onFailure();
+}
diff --git a/core/java/android/service/settings/preferences/MetadataRequest.aidl b/core/java/android/service/settings/preferences/MetadataRequest.aidl
new file mode 100644
index 0000000..dc3cbc42
--- /dev/null
+++ b/core/java/android/service/settings/preferences/MetadataRequest.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable MetadataRequest;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/MetadataRequest.java b/core/java/android/service/settings/preferences/MetadataRequest.java
new file mode 100644
index 0000000..ffecc6b
--- /dev/null
+++ b/core/java/android/service/settings/preferences/MetadataRequest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.flags.Flags;
+
+/**
+ * Request parameters to retrieve all metadata for all available settings preferences within this
+ * application.
+ *
+ * <p>This object passed to {@link SettingsPreferenceService#onGetAllPreferenceMetadata} will result
+ * in a {@link MetadataResult}.
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class MetadataRequest implements Parcelable {
+    private MetadataRequest() {}
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link MetadataRequest}.
+     */
+    @NonNull
+    public static final Creator<MetadataRequest> CREATOR = new Creator<>() {
+        @Override
+        public MetadataRequest createFromParcel(@NonNull Parcel in) {
+            return new MetadataRequest();
+        }
+
+        @Override
+        public MetadataRequest[] newArray(int size) {
+            return new MetadataRequest[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link MetadataRequest}.
+     */
+    public static final class Builder {
+        /** Constructs an immutable {@link MetadataRequest} object. */
+        @NonNull
+        public MetadataRequest build() {
+            return new MetadataRequest();
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/MetadataResult.aidl b/core/java/android/service/settings/preferences/MetadataResult.aidl
new file mode 100644
index 0000000..af9e8a8
--- /dev/null
+++ b/core/java/android/service/settings/preferences/MetadataResult.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable MetadataResult;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/MetadataResult.java b/core/java/android/service/settings/preferences/MetadataResult.java
new file mode 100644
index 0000000..6a65dcc
--- /dev/null
+++ b/core/java/android/service/settings/preferences/MetadataResult.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Result object given a corresponding {@link MetadataRequest}.
+ * <ul>
+ *   <li>If the request was successful, {@link #getResultCode} will be {@link #RESULT_OK} and
+ *   {@link #getMetadataList} will be populated with metadata for all available preferences within
+ *   this application.
+ *   <li>If the request is unsuccessful, {@link #getResultCode} be a value other than
+ *   {@link #RESULT_OK} - see documentation for those possibilities to understand the cause
+ *   of the failure.
+ * </ul>
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class MetadataResult implements Parcelable {
+
+    @ResultCode
+    private final int mResultCode;
+    @NonNull
+    private final List<SettingsPreferenceMetadata> mMetadataList;
+
+    /**
+     * Returns the result code indicating status of the request.
+     */
+    @ResultCode
+    public int getResultCode() {
+        return mResultCode;
+    }
+
+    /**
+     * Returns the list of available Preference Metadata.
+     * <p>This instance is shared so this list should not be modified.
+     */
+    @NonNull
+    public List<SettingsPreferenceMetadata> getMetadataList() {
+        return mMetadataList;
+    }
+
+    /** @hide */
+    @IntDef(prefix = { "RESULT_" }, value = {
+            RESULT_OK,
+            RESULT_UNSUPPORTED,
+            RESULT_INTERNAL_ERROR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ResultCode {
+    }
+
+    /** Request is successful. */
+    public static final int RESULT_OK = 0;
+    /**
+     * No preferences in this application support this API.
+     * <p>Retry not advised.
+     */
+    public static final int RESULT_UNSUPPORTED = 1;
+    /**
+     * API call failed due to an issue with the service binding.
+     * <p>Retry may succeed.
+     */
+    public static final int RESULT_INTERNAL_ERROR = 2;
+
+    private MetadataResult(@NonNull Builder builder) {
+        mResultCode = builder.mResultCode;
+        mMetadataList = builder.mMetadataList;
+    }
+    private MetadataResult(@NonNull Parcel in) {
+        mResultCode = in.readInt();
+        mMetadataList = new ArrayList<>();
+        in.readTypedList(mMetadataList, SettingsPreferenceMetadata.CREATOR);
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mResultCode);
+        dest.writeTypedList(mMetadataList, flags);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link MetadataResult}.
+     */
+    @NonNull
+    public static final Creator<MetadataResult> CREATOR = new Creator<>() {
+        @Override
+        public MetadataResult createFromParcel(@NonNull Parcel in) {
+            return new MetadataResult(in);
+        }
+
+        @Override
+        public MetadataResult[] newArray(int size) {
+            return new MetadataResult[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link MetadataResult}.
+     */
+    public static final class Builder {
+        @ResultCode
+        private final int mResultCode;
+        private List<SettingsPreferenceMetadata> mMetadataList = Collections.emptyList();
+
+        /**
+         * Create Builder instance.
+         * @param resultCode indicates status of the request
+         */
+        public Builder(@ResultCode int resultCode) {
+            mResultCode = resultCode;
+        }
+
+        /**
+         * Sets the metadata list on the result.
+         */
+        @NonNull
+        public Builder setMetadataList(@NonNull List<SettingsPreferenceMetadata> metadataList) {
+            mMetadataList = metadataList;
+            return this;
+        }
+
+        /**
+         * Constructs an immutable {@link MetadataResult} object.
+         */
+        @NonNull
+        public MetadataResult build() {
+            return new MetadataResult(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/SetValueRequest.aidl b/core/java/android/service/settings/preferences/SetValueRequest.aidl
new file mode 100644
index 0000000..198e333
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SetValueRequest.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable SetValueRequest;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/SetValueRequest.java b/core/java/android/service/settings/preferences/SetValueRequest.java
new file mode 100644
index 0000000..f7600ae
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SetValueRequest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.flags.Flags;
+
+import java.util.Objects;
+
+/**
+ * Request parameters to set the current value to a Settings Preference.
+ * <p>This object passed to {@link SettingsPreferenceService#onSetPreferenceValue} will result in a
+ * {@link SetValueResult}.
+ * <ul>
+ *   <li>{@link #getScreenKey} is a parameter to distinguish the container screen
+ *   of a preference as a preference key may not be unique within its application.
+ *   <li>{@link #getPreferenceKey} is a parameter to identify the preference for which the value is
+ *   being requested. These keys will be unique with their Preference Screen, but may not be unique
+ *   within their application, so it is required to pair this with {@link #getScreenKey} to
+ *   ensure this request matches the intended target.
+ *   <li>{@link #getPreferenceValue} is a parameter to specify the value that this request aims to
+ *   set. If this value is invalid (malformed or does not match the type of the preference) then
+ *   this request will fail.
+ * </ul>
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class SetValueRequest implements Parcelable {
+
+    @NonNull
+    private final String mScreenKey;
+    @NonNull
+    private final String mPreferenceKey;
+    @NonNull
+    private final SettingsPreferenceValue mPreferenceValue;
+
+    /**
+     * Returns the screen key of requested Preference.
+     */
+    @NonNull
+    public String getScreenKey() {
+        return mScreenKey;
+    }
+
+    /**
+     * Returns the key of requested Preference.
+     */
+    @NonNull
+    public String getPreferenceKey() {
+        return mPreferenceKey;
+    }
+
+    /**
+     * Returns the value of requested Preference.
+     */
+    @NonNull
+    public SettingsPreferenceValue getPreferenceValue() {
+        return mPreferenceValue;
+    }
+
+    private SetValueRequest(@NonNull Builder builder) {
+        mScreenKey = builder.mScreenKey;
+        mPreferenceKey = builder.mPreferenceKey;
+        mPreferenceValue = builder.mPreferenceValue;
+    }
+
+    private SetValueRequest(@NonNull Parcel in) {
+        mScreenKey = Objects.requireNonNull(in.readString8());
+        mPreferenceKey = Objects.requireNonNull(in.readString8());
+        mPreferenceValue = Objects.requireNonNull(in.readParcelable(
+                SettingsPreferenceValue.class.getClassLoader(), SettingsPreferenceValue.class));
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mScreenKey);
+        dest.writeString8(mPreferenceKey);
+        dest.writeParcelable(mPreferenceValue, flags);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link SetValueRequest}.
+     */
+    @NonNull
+    public static final Creator<SetValueRequest> CREATOR = new Creator<SetValueRequest>() {
+        @Override
+        public SetValueRequest createFromParcel(@NonNull Parcel in) {
+            return new SetValueRequest(in);
+        }
+
+        @Override
+        public SetValueRequest[] newArray(int size) {
+            return new SetValueRequest[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link SetValueRequest}.
+     */
+    public static final class Builder {
+        private final String mScreenKey;
+        private final String mPreferenceKey;
+        private final SettingsPreferenceValue mPreferenceValue;
+
+        /**
+         * Create Builder instance.
+         * @param screenKey required to be not empty
+         * @param preferenceKey required to be not empty
+         * @param value value to set to requested Preference
+         */
+        public Builder(@NonNull String screenKey, @NonNull String preferenceKey,
+                       @NonNull SettingsPreferenceValue value) {
+            if (TextUtils.isEmpty(screenKey)) {
+                throw new IllegalArgumentException("screenKey cannot be empty");
+            }
+            if (TextUtils.isEmpty(preferenceKey)) {
+                throw new IllegalArgumentException("preferenceKey cannot be empty");
+            }
+            mScreenKey = screenKey;
+            mPreferenceKey = preferenceKey;
+            mPreferenceValue = value;
+        }
+
+        /**
+         * Constructs an immutable {@link SetValueRequest} object.
+         */
+        @NonNull
+        public SetValueRequest build() {
+            return new SetValueRequest(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/SetValueResult.aidl b/core/java/android/service/settings/preferences/SetValueResult.aidl
new file mode 100644
index 0000000..f548134
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SetValueResult.aidl
@@ -0,0 +1,4 @@
+package android.service.settings.preferences;
+
+/** @hide */
+parcelable SetValueResult;
\ No newline at end of file
diff --git a/core/java/android/service/settings/preferences/SetValueResult.java b/core/java/android/service/settings/preferences/SetValueResult.java
new file mode 100644
index 0000000..cb1776a
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SetValueResult.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+
+import com.android.settingslib.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Result object given a corresponding {@link SetValueRequest}.
+ * <ul>
+ *   <li>If the request was successful, {@link #getResultCode} will be {@link #RESULT_OK}.
+ *   <li>If the request is unsuccessful, {@link #getResultCode} be a value other than
+ *   {@link #RESULT_OK} - see documentation for those possibilities to understand the cause
+ *   of the failure.
+ * </ul>
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class SetValueResult implements Parcelable {
+
+    @ResultCode
+    private final int mResultCode;
+
+    /**
+     * Returns the result code indicating status of the request.
+     */
+    @ResultCode
+    public int getResultCode() {
+        return mResultCode;
+    }
+
+    /** @hide */
+    @IntDef(prefix = { "RESULT_" }, value = {
+            RESULT_OK,
+            RESULT_UNSUPPORTED,
+            RESULT_DISABLED,
+            RESULT_RESTRICTED,
+            RESULT_UNAVAILABLE,
+            RESULT_REQUIRE_APP_PERMISSION,
+            RESULT_REQUIRE_USER_CONSENT,
+            RESULT_DISALLOW,
+            RESULT_INVALID_REQUEST,
+            RESULT_INTERNAL_ERROR
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ResultCode {
+    }
+
+    /** Request is successful and the value was set. */
+    public static final int RESULT_OK = 0;
+    /**
+     * Requested preference is not supported by this API.
+     * <p>Retry not advised.
+     */
+    public static final int RESULT_UNSUPPORTED = 1;
+    /**
+     * Requested preference is disabled, thus unable to be set in this state.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_DISABLED = 2;
+    /**
+     * Requested preference is restricted, thus unable to be set under this policy.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_RESTRICTED = 3;
+    /**
+     * Preference is currently not available, likely due to device state or the state of
+     * a dependency.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_UNAVAILABLE = 4;
+    /**
+     * Requested preference requires permissions not held by the calling application.
+     * <p>Retry may succeed if necessary permissions are obtained.
+     */
+    public static final int RESULT_REQUIRE_APP_PERMISSION = 5;
+    /**
+     * User consent was not approved for this operation.
+     * <p>Retry may succeed if user provides consent.
+     */
+    public static final int RESULT_REQUIRE_USER_CONSENT = 6;
+    /**
+     * Requested preference is not allowed for access in this API under the current device policy.
+     * <p>Retry may succeed if underlying conditions change.
+     */
+    public static final int RESULT_DISALLOW = 7;
+    /**
+     * Request object is not valid.
+     * <p>Retry not advised with current parameters.
+     */
+    public static final int RESULT_INVALID_REQUEST = 8;
+    /**
+     * API call failed due to an issue with the service binding.
+     * <p>Retry may succeed.
+     */
+    public static final int RESULT_INTERNAL_ERROR = 9;
+
+    private SetValueResult(@NonNull Builder builder) {
+        mResultCode = builder.mResultCode;
+    }
+
+    private SetValueResult(@NonNull Parcel in) {
+        mResultCode = in.readInt();
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mResultCode);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link SetValueResult}.
+     */
+    @NonNull
+    public static final Creator<SetValueResult> CREATOR = new Creator<>() {
+        @Override
+        public SetValueResult createFromParcel(@NonNull Parcel in) {
+            return new SetValueResult(in);
+        }
+
+        @Override
+        public SetValueResult[] newArray(int size) {
+            return new SetValueResult[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link SetValueResult}.
+     */
+    public static final class Builder {
+        @ResultCode
+        private final int mResultCode;
+
+        /**
+         * Create Builder instance.
+         * @param resultCode indicates status of the request
+         */
+        public Builder(@ResultCode int resultCode) {
+            mResultCode = resultCode;
+        }
+
+        /**
+         * Constructs an immutable {@link SetValueResult} object.
+         */
+        @NonNull
+        public SetValueResult build() {
+            return new SetValueResult(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java b/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java
new file mode 100644
index 0000000..1d08c52
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SettingsPreferenceMetadata.java
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.SuppressLint;
+import android.app.PendingIntent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Data object representation of a Settings Preference definition and state.
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class SettingsPreferenceMetadata implements Parcelable {
+
+    @NonNull
+    private final String mKey;
+    @NonNull
+    private final String mScreenKey;
+    @Nullable
+    private final String mTitle;
+    @Nullable
+    private final String mSummary;
+    @NonNull
+    private final List<String> mBreadcrumbs;
+    @NonNull
+    private final List<String> mReadPermissions;
+    @NonNull
+    private final List<String> mWritePermissions;
+    private final boolean mEnabled;
+    private final boolean mAvailable;
+    private final boolean mWritable;
+    private final boolean mRestricted;
+    private final int mSensitivity;
+    @Nullable
+    private final PendingIntent mLaunchIntent;
+    @NonNull
+    private final Bundle mExtras;
+
+    /**
+     * Returns the key of Preference.
+     */
+    @NonNull
+    public String getKey() {
+        return mKey;
+    }
+
+    /**
+     * Returns the screen key of Preference.
+     */
+    @NonNull
+    public String getScreenKey() {
+        return mScreenKey;
+    }
+
+    /**
+     * Returns the title of Preference.
+     */
+    @Nullable
+    public String getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns the summary of Preference.
+     */
+    @Nullable
+    public String getSummary() {
+        return mSummary;
+    }
+
+    /**
+     * Returns the breadcrumbs (navigation context) of Preference.
+     * <p>May be empty.
+     */
+    @NonNull
+    public List<String> getBreadcrumbs() {
+        return mBreadcrumbs;
+    }
+
+    /**
+     * Returns the permissions required to read this Preference's value.
+     * <p>May be empty.
+     */
+    @NonNull
+    public List<String> getReadPermissions() {
+        return mReadPermissions;
+    }
+
+    /**
+     * Returns the permissions required to write this Preference's value.
+     * <p>May be empty.
+     */
+    @NonNull
+    public List<String> getWritePermissions() {
+        return mWritePermissions;
+    }
+
+    /**
+     * Returns whether Preference is enabled.
+     */
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Returns whether Preference is available.
+     */
+    public boolean isAvailable() {
+        return mAvailable;
+    }
+
+    /**
+     * Returns whether Preference is writable.
+     */
+    public boolean isWritable() {
+        return mWritable;
+    }
+
+    /**
+     * Returns whether Preference is restricted.
+     */
+    public boolean isRestricted() {
+        return mRestricted;
+    }
+
+    /**
+     * Returns the write-level sensitivity of Preference.
+     */
+    @WriteSensitivity
+    public int getWriteSensitivity() {
+        return mSensitivity;
+    }
+
+    /**
+     * Returns the intent to launch the host app page for this Preference.
+     */
+    @Nullable
+    public PendingIntent getLaunchIntent() {
+        return mLaunchIntent;
+    }
+
+    /**
+     * Returns any additional fields specific to this preference.
+     * <p>Treat all data as optional.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    /** @hide */
+    @IntDef(value = {
+            NOT_SENSITIVE,
+            SENSITIVE,
+            INTENT_ONLY
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface WriteSensitivity {}
+
+    /**
+     * Preference is not sensitive, thus its value is writable without explicit consent, assuming
+     * all necessary permissions are granted.
+     */
+    public static final int NOT_SENSITIVE = 0;
+    /**
+     * Preference is sensitive, meaning that in addition to necessary permissions, writing its value
+     * will also request explicit user consent.
+     */
+    public static final int SENSITIVE = 1;
+    /**
+     * Preference is not permitted for write-access via API and must be changed via Settings page.
+     */
+    public static final int INTENT_ONLY = 2;
+
+    private SettingsPreferenceMetadata(@NonNull Builder builder) {
+        mKey = builder.mKey;
+        mScreenKey = builder.mScreenKey;
+        mTitle = builder.mTitle;
+        mSummary = builder.mSummary;
+        mBreadcrumbs = builder.mBreadcrumbs;
+        mReadPermissions = builder.mReadPermissions;
+        mWritePermissions = builder.mWritePermissions;
+        mEnabled = builder.mEnabled;
+        mAvailable = builder.mAvailable;
+        mWritable = builder.mWritable;
+        mRestricted = builder.mRestricted;
+        mSensitivity = builder.mSensitivity;
+        mLaunchIntent = builder.mLaunchIntent;
+        mExtras = Objects.requireNonNullElseGet(builder.mExtras, Bundle::new);
+    }
+    @SuppressLint("ParcelClassLoader")
+    private SettingsPreferenceMetadata(@NonNull Parcel in) {
+        mKey = Objects.requireNonNull(in.readString8());
+        mScreenKey = Objects.requireNonNull(in.readString8());
+        mTitle = in.readString8();
+        mSummary = in.readString8();
+        mBreadcrumbs = new ArrayList<>();
+        in.readStringList(mBreadcrumbs);
+        mReadPermissions = new ArrayList<>();
+        in.readStringList(mReadPermissions);
+        mWritePermissions = new ArrayList<>();
+        in.readStringList(mWritePermissions);
+        mEnabled = in.readBoolean();
+        mAvailable = in.readBoolean();
+        mWritable = in.readBoolean();
+        mRestricted = in.readBoolean();
+        mSensitivity = in.readInt();
+        mLaunchIntent = in.readParcelable(PendingIntent.class.getClassLoader(),
+                PendingIntent.class);
+        mExtras = Objects.requireNonNullElseGet(in.readBundle(), Bundle::new);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString8(mKey);
+        dest.writeString8(mScreenKey);
+        dest.writeString8(mTitle);
+        dest.writeString8(mSummary);
+        dest.writeStringList(mBreadcrumbs);
+        dest.writeStringList(mReadPermissions);
+        dest.writeStringList(mWritePermissions);
+        dest.writeBoolean(mEnabled);
+        dest.writeBoolean(mAvailable);
+        dest.writeBoolean(mWritable);
+        dest.writeBoolean(mRestricted);
+        dest.writeInt(mSensitivity);
+        dest.writeParcelable(mLaunchIntent, flags);
+        dest.writeBundle(mExtras);
+    }
+
+    /**
+     * Parcelable Creator for {@link SettingsPreferenceMetadata}.
+     */
+    @NonNull
+    public static final Creator<SettingsPreferenceMetadata> CREATOR = new Creator<>() {
+        @Override
+        public SettingsPreferenceMetadata createFromParcel(@NonNull Parcel in) {
+            return new SettingsPreferenceMetadata(in);
+        }
+
+        @Override
+        public SettingsPreferenceMetadata[] newArray(int size) {
+            return new SettingsPreferenceMetadata[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link SettingsPreferenceMetadata}.
+     */
+    public static final class Builder {
+        private final String mScreenKey;
+        private final String mKey;
+        private String mTitle;
+        private String mSummary;
+        private List<String> mBreadcrumbs = Collections.emptyList();
+        private List<String> mReadPermissions = Collections.emptyList();
+        private List<String> mWritePermissions = Collections.emptyList();
+        private boolean mEnabled = false;
+        private boolean mAvailable = false;
+        private boolean mWritable = false;
+        private boolean mRestricted = false;
+        @WriteSensitivity private int mSensitivity = INTENT_ONLY;
+        private PendingIntent mLaunchIntent;
+        private Bundle mExtras;
+
+        /**
+         * Create Builder instance.
+         * @param screenKey required to be not empty
+         * @param key required to be not empty
+         */
+        public Builder(@NonNull String screenKey, @NonNull String key) {
+            if (TextUtils.isEmpty(screenKey)) {
+                throw new IllegalArgumentException("screenKey cannot be empty");
+            }
+            if (TextUtils.isEmpty(key)) {
+                throw new IllegalArgumentException("key cannot be empty");
+            }
+            mScreenKey = screenKey;
+            mKey = key;
+        }
+
+        /**
+         * Sets the preference title.
+         */
+        @NonNull
+        public Builder setTitle(@Nullable String title) {
+            mTitle = title;
+            return this;
+        }
+
+        /**
+         * Sets the preference summary.
+         */
+        @NonNull
+        public Builder setSummary(@Nullable String summary) {
+            mSummary = summary;
+            return this;
+        }
+
+        /**
+         * Sets the preference breadcrumbs (navigation context).
+         */
+        @NonNull
+        public Builder setBreadcrumbs(@NonNull List<String> breadcrumbs) {
+            mBreadcrumbs = breadcrumbs;
+            return this;
+        }
+
+        /**
+         * Sets the permissions required for reading this preference.
+         */
+        @NonNull
+        public Builder setReadPermissions(@NonNull List<String> readPermissions) {
+            mReadPermissions = readPermissions;
+            return this;
+        }
+
+        /**
+         * Sets the permissions required for writing this preference.
+         */
+        @NonNull
+        public Builder setWritePermissions(@NonNull List<String> writePermissions) {
+            mWritePermissions = writePermissions;
+            return this;
+        }
+
+        /**
+         * Set whether the preference is enabled.
+         */
+        @NonNull
+        public Builder setEnabled(boolean enabled) {
+            mEnabled = enabled;
+            return this;
+        }
+
+        /**
+         * Sets whether the preference is available.
+         */
+        @NonNull
+        public Builder setAvailable(boolean available) {
+            mAvailable = available;
+            return this;
+        }
+
+        /**
+         * Sets whether the preference is writable.
+         */
+        @NonNull
+        public Builder setWritable(boolean writable) {
+            mWritable = writable;
+            return this;
+        }
+
+        /**
+         * Sets whether the preference is restricted.
+         */
+        @NonNull
+        public Builder setRestricted(boolean restricted) {
+            mRestricted = restricted;
+            return this;
+        }
+
+        /**
+         * Sets the preference write-level sensitivity.
+         */
+        @NonNull
+        public Builder setWriteSensitivity(@WriteSensitivity int sensitivity) {
+            mSensitivity = sensitivity;
+            return this;
+        }
+
+        /**
+         * Sets the intent to launch the host app page for this preference.
+         */
+        @NonNull
+        public Builder setLaunchIntent(@Nullable PendingIntent launchIntent) {
+            mLaunchIntent = launchIntent;
+            return this;
+        }
+
+        /**
+         * Sets additional fields specific to this preference. Treat all data as optional.
+         */
+        @NonNull
+        public Builder setExtras(@NonNull Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
+         * Constructs an immutable {@link SettingsPreferenceMetadata} object.
+         */
+        @NonNull
+        public SettingsPreferenceMetadata build() {
+            return new SettingsPreferenceMetadata(this);
+        }
+    }
+}
diff --git a/core/java/android/service/settings/preferences/SettingsPreferenceValue.java b/core/java/android/service/settings/preferences/SettingsPreferenceValue.java
new file mode 100644
index 0000000..f056e34
--- /dev/null
+++ b/core/java/android/service/settings/preferences/SettingsPreferenceValue.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 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 android.service.settings.preferences;
+
+import android.annotation.FlaggedApi;
+import android.annotation.IntDef;
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settingslib.flags.Flags;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This objects represents a value that can be used for a particular settings preference.
+ * <p>The data type for the value will correspond to {@link #getType}. For possible types, see
+ * constants below, such as {@link #TYPE_BOOLEAN} and {@link #TYPE_STRING}.
+ * Depending on the type, the corresponding getter will contain its value. All other getters will
+ * return default values (boolean returns false, String returns null) so they should not be used.
+ * <p>See documentation on the constants for which getter method should be used.
+ */
+@FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
+public final class SettingsPreferenceValue implements Parcelable {
+
+    @Type
+    private final int mType;
+    private final boolean mBooleanValue;
+    private final long mLongValue;
+    private final double mDoubleValue;
+    @Nullable
+    private final String mStringValue;
+
+    /**
+     * Returns the type indicator for Preference value.
+     */
+    @Type
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Returns the boolean value for Preference if type is {@link #TYPE_BOOLEAN}.
+     */
+    public boolean getBooleanValue() {
+        return mBooleanValue;
+    }
+
+    /**
+     * Returns the long value for Preference if type is {@link #TYPE_LONG}.
+     */
+    public long getLongValue() {
+        return mLongValue;
+    }
+
+    /**
+     * Returns the double value for Preference if type is {@link #TYPE_DOUBLE}.
+     */
+    public double getDoubleValue() {
+        return mDoubleValue;
+    }
+
+    /**
+     * Returns the string value for Preference if type is {@link #TYPE_STRING}.
+     */
+    @Nullable
+    public String getStringValue() {
+        return mStringValue;
+    }
+
+    /** @hide */
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_BOOLEAN,
+            TYPE_LONG,
+            TYPE_DOUBLE,
+            TYPE_STRING,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Type {}
+
+    /** Value is of type boolean. Access via {@link #getBooleanValue}. */
+    public static final int TYPE_BOOLEAN = 0;
+    /** Value is of type long. Access via {@link #getLongValue()}. */
+    public static final int TYPE_LONG = 1;
+    /** Value is of type double. Access via {@link #getDoubleValue()}. */
+    public static final int TYPE_DOUBLE = 2;
+    /** Value is of type string. Access via {@link #getStringValue}. */
+    public static final int TYPE_STRING = 3;
+
+    private SettingsPreferenceValue(@NonNull Builder builder) {
+        mType = builder.mType;
+        mBooleanValue = builder.mBooleanValue;
+        mLongValue = builder.mLongValue;
+        mDoubleValue = builder.mDoubleValue;
+        mStringValue = builder.mStringValue;
+    }
+
+    private SettingsPreferenceValue(@NonNull Parcel in) {
+        mType = in.readInt();
+        mBooleanValue = in.readBoolean();
+        mLongValue = in.readLong();
+        mDoubleValue = in.readDouble();
+        mStringValue = in.readString8();
+    }
+
+    /** @hide */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mType);
+        dest.writeBoolean(mBooleanValue);
+        dest.writeLong(mLongValue);
+        dest.writeDouble(mDoubleValue);
+        dest.writeString8(mStringValue);
+    }
+
+    /** @hide */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Parcelable Creator for {@link SettingsPreferenceValue}.
+     */
+    @NonNull
+    public static final Creator<SettingsPreferenceValue> CREATOR = new Creator<>() {
+        @Override
+        public SettingsPreferenceValue createFromParcel(@NonNull Parcel in) {
+            return new SettingsPreferenceValue(in);
+        }
+
+        @Override
+        public SettingsPreferenceValue[] newArray(int size) {
+            return new SettingsPreferenceValue[size];
+        }
+    };
+
+    /**
+     * Builder to construct {@link SettingsPreferenceValue}.
+     */
+    public static final class Builder {
+        @Type
+        private final int mType;
+        private boolean mBooleanValue;
+        private long mLongValue;
+        private double mDoubleValue;
+        private String mStringValue;
+
+        /**
+         * Create Builder instance.
+         * @param type type indicator for preference value
+         */
+        public Builder(@Type int type) {
+            mType = type;
+        }
+
+        /**
+         * Sets boolean value for Preference.
+         */
+        @SuppressLint("MissingGetterMatchingBuilder")
+        @NonNull
+        public Builder setBooleanValue(boolean booleanValue) {
+            mBooleanValue = booleanValue;
+            return this;
+        }
+
+        /**
+         * Sets long value for Preference.
+         */
+        @NonNull
+        public Builder setLongValue(long longValue) {
+            mLongValue = longValue;
+            return this;
+        }
+
+        /**
+         * Sets floating point value for Preference.
+         */
+        @NonNull
+        public Builder setDoubleValue(double doubleValue) {
+            mDoubleValue = doubleValue;
+            return this;
+        }
+
+        /**
+         * Sets string value for Preference.
+         */
+        @NonNull
+        public Builder setStringValue(@Nullable String stringValue) {
+            mStringValue = stringValue;
+            return this;
+        }
+
+        /**
+         * Constructs an immutable {@link SettingsPreferenceValue} object.
+         */
+        @NonNull
+        public SettingsPreferenceValue build() {
+            return new SettingsPreferenceValue(this);
+        }
+    }
+}
diff --git a/core/res/Android.bp b/core/res/Android.bp
index 66c2e12..c66d2b5 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -172,6 +172,7 @@
         "com.android.hardware.input.input-aconfig",
         "aconfig_trade_in_mode_flags",
         "ranging_aconfig_flags",
+        "aconfig_settingslib_flags",
     ],
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5913992..46604d4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4960,6 +4960,27 @@
     <permission android:name="android.permission.PROVIDE_REMOTE_CREDENTIALS"
                 android:protectionLevel="signature|privileged|role" />
 
+    <!-- @FlaggedApi(com.android.settingslib.flags.Flags.FLAG_SETTINGS_CATALYST)
+         Allows an application to access the Settings Preference services to read settings exposed
+         by the system Settings app and system apps that contribute settings surfaced by the
+         Settings app.
+         <p>This allows the calling application to read settings values through the host
+         application, agnostic of underlying storage. -->
+    <permission android:name="android.permission.READ_SYSTEM_PREFERENCES"
+        android:protectionLevel="signature|privileged|role"
+        android:featureFlag="com.android.settingslib.flags.settings_catalyst" />
+
+    <!-- @FlaggedApi(com.android.settingslib.flags.Flags.FLAG_SETTINGS_CATALYST)
+         Allows an application to access the Settings Preference services to write settings
+         values exposed by the system Settings app and system apps that contribute settings surfaced
+         in the Settings app.
+         <p>This allows the calling application to write settings values
+         through the host application, agnostic of underlying storage.
+         <p>Protection Level: signature|privileged|appop - appop to be added in followup -->
+    <permission android:name="android.permission.WRITE_SYSTEM_PREFERENCES"
+        android:protectionLevel="signature|privileged"
+        android:featureFlag="com.android.settingslib.flags.settings_catalyst" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index e141867..b2dcb7f 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -61,7 +61,7 @@
         "SettingsLibUtils",
         "SettingsLibZeroStatePreference",
         "settingslib_media_flags_lib",
-        "settingslib_flags_lib",
+        "aconfig_settingslib_flags_java_lib",
     ],
 
     plugins: ["androidx.room_room-compiler-plugin"],
@@ -107,20 +107,6 @@
     aconfig_declarations: "settingslib_media_flags",
 }
 
-aconfig_declarations {
-    name: "settingslib_flags",
-    package: "com.android.settingslib.flags",
-    container: "system",
-    srcs: [
-        "aconfig/settingslib.aconfig",
-    ],
-}
-
-java_aconfig_library {
-    name: "settingslib_flags_lib",
-    aconfig_declarations: "settingslib_flags",
-}
-
 soong_config_module_type {
     name: "avatar_picker_java_defaults",
     module_type: "java_defaults",