diff options
author | 2024-10-23 04:00:09 +0000 | |
---|---|---|
committer | 2024-11-07 04:36:34 +0000 | |
commit | 63345612313ac55761906c8dfde533fd6f05b955 (patch) | |
tree | 1b790421dde8e4040847a03340251eb84247e4a6 | |
parent | ea0378dc388aec0ccde233ba17a83b032190a251 (diff) |
Define Settings Preference Service API data models
Bug: 375075504
Test: atest CtsSettingsPreferenceServiceTest
Flag: com.android.settingslib.flags.settings_catalyst
Change-Id: Ic491393b7617a2104b19aa1d64a83d6fe39529b8
22 files changed, 1845 insertions, 15 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 26fbd270eb46..39fcf76ed7a3 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -21,6 +21,7 @@ aconfig_declarations_group { 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 @@ cc_aconfig_library { ], 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 7f74a62d5956..03287ce7de26 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -263,6 +263,7 @@ package android { 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 @@ package android { 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.restrictions { } +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 000000000000..2a0eb09aa2a4 --- /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 000000000000..4f82800d1855 --- /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 000000000000..b5ebd35a3a37 --- /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 000000000000..369dea77cc85 --- /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 000000000000..bbc7423f453e --- /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 000000000000..3bd5ebe93660 --- /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 000000000000..0765660c83c3 --- /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 000000000000..dc3cbc42661e --- /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 000000000000..ffecc6bec5b2 --- /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 000000000000..af9e8a86e3ab --- /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 000000000000..6a65dcc9c757 --- /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 000000000000..198e333d5cb6 --- /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 000000000000..f7600aecdfaf --- /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 000000000000..f54813484d68 --- /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 000000000000..cb1776abd3bc --- /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 000000000000..1d08c5217129 --- /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 000000000000..f056e34a0dd2 --- /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 66c2e12f7cdf..c66d2b57fcef 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -172,6 +172,7 @@ android_app { "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 5913992004b8..46604d4c4efe 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 e1418678a9f8..b2dcb7fa4f53 100644 --- a/packages/SettingsLib/Android.bp +++ b/packages/SettingsLib/Android.bp @@ -61,7 +61,7 @@ android_library { "SettingsLibUtils", "SettingsLibZeroStatePreference", "settingslib_media_flags_lib", - "settingslib_flags_lib", + "aconfig_settingslib_flags_java_lib", ], plugins: ["androidx.room_room-compiler-plugin"], @@ -107,20 +107,6 @@ java_aconfig_library { 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", |