diff options
7 files changed, 111 insertions, 85 deletions
diff --git a/framework-s/java/android/safetycenter/SafetySourceData.java b/framework-s/java/android/safetycenter/SafetySourceData.java index 954b2794f..70c0a8186 100644 --- a/framework-s/java/android/safetycenter/SafetySourceData.java +++ b/framework-s/java/android/safetycenter/SafetySourceData.java @@ -29,6 +29,7 @@ import android.os.Parcelable; import androidx.annotation.RequiresApi; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -50,7 +51,12 @@ public final class SafetySourceData implements Parcelable { SafetySourceStatus status = in.readTypedObject(SafetySourceStatus.CREATOR); List<SafetySourceIssue> issues = in.createTypedArrayList(SafetySourceIssue.CREATOR); - return new SafetySourceData(status, issues); + Builder builder = new Builder().setStatus(status); + // TODO(b/224513050): Consider simplifying by adding a new API to the builder. + for (int i = 0; i < issues.size(); i++) { + builder.addIssue(issues.get(i)); + } + return builder.build(); } @Override @@ -70,13 +76,13 @@ public final class SafetySourceData implements Parcelable { this.mIssues = new ArrayList<>(issues); } - /** Returns the data for the safety source status to be shown in UI. */ + /** Returns the data for the {@link SafetySourceStatus} to be shown in UI. */ @Nullable public SafetySourceStatus getStatus() { return mStatus; } - /** Returns the data for the list of safety source issues to be shown in UI. */ + /** Returns the data for the list of {@link SafetySourceIssue}s to be shown in UI. */ @NonNull public List<SafetySourceIssue> getIssues() { return new ArrayList<>(mIssues); @@ -124,14 +130,14 @@ public final class SafetySourceData implements Parcelable { @Nullable private SafetySourceStatus mStatus; - /** Sets data for the safety source status to be shown in UI. */ + /** Sets data for the {@link SafetySourceStatus} to be shown in UI. */ @NonNull public Builder setStatus(@Nullable SafetySourceStatus status) { mStatus = status; return this; } - /** Adds data for a safety source issue to be shown in UI. */ + /** Adds data for a {@link SafetySourceIssue} to be shown in UI. */ @NonNull public Builder addIssue(@NonNull SafetySourceIssue safetySourceIssue) { mIssues.add(requireNonNull(safetySourceIssue)); @@ -139,7 +145,8 @@ public final class SafetySourceData implements Parcelable { } /** - * Clears data for all the safety source issues that were added to this {@link Builder}. + * Clears data for all the {@link SafetySourceIssue}s that were added to this + * {@link Builder}. */ @NonNull public Builder clearIssues() { @@ -152,7 +159,7 @@ public final class SafetySourceData implements Parcelable { public SafetySourceData build() { // TODO(b/207329841): Validate data matches validation in S, for eg that the status // and severity levels of the settings and issues are compatible. - return new SafetySourceData(mStatus, mIssues); + return new SafetySourceData(mStatus, Collections.unmodifiableList(mIssues)); } } } diff --git a/framework-s/java/android/safetycenter/SafetySourceIssue.java b/framework-s/java/android/safetycenter/SafetySourceIssue.java index 950fc359f..dc7d91236 100644 --- a/framework-s/java/android/safetycenter/SafetySourceIssue.java +++ b/framework-s/java/android/safetycenter/SafetySourceIssue.java @@ -37,6 +37,7 @@ import androidx.annotation.RequiresApi; 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; @@ -112,8 +113,15 @@ public final class SafetySourceIssue implements Parcelable { PendingIntent onDismissPendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(in); String issueTypeId = requireNonNull(in.readString()); - return new SafetySourceIssue(id, title, subtitle, summary, severityLevel, - issueCategory, actions, onDismissPendingIntent, issueTypeId); + Builder builder = new Builder(id, title, summary, severityLevel, issueTypeId) + .setSubtitle(subtitle) + .setIssueCategory(issueCategory) + .setOnDismissPendingIntent(onDismissPendingIntent); + // TODO(b/224513050): Consider simplifying by adding a new API to the builder. + for (int i = 0; i < actions.size(); i++) { + builder.addAction(actions.get(i)); + } + return builder.build(); } @Override @@ -209,8 +217,7 @@ public final class SafetySourceIssue implements Parcelable { } /** - * Returns a list of {@link Action} instances representing actions supported in the UI for this - * issue. + * Returns a list of {@link Action}s representing actions supported in the UI for this issue. * * <p>Each issue must contain at least one action, in order to help the user resolve the issue. * @@ -383,16 +390,14 @@ public final class SafetySourceIssue implements Parcelable { new Parcelable.Creator<Action>() { @Override public Action createFromParcel(Parcel in) { - String id = requireNonNull(in.readString()); - CharSequence label = - requireNonNull( - TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)); - PendingIntent pendingIntent = - requireNonNull(PendingIntent.readPendingIntentOrNullFromParcel(in)); - boolean willResolve = in.readBoolean(); - CharSequence successMessage = - TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - return new Action(id, label, pendingIntent, willResolve, successMessage); + return new Builder( + in.readString(), + TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in), + PendingIntent.readPendingIntentOrNullFromParcel(in)) + .setWillResolve(in.readBoolean()) + .setSuccessMessage( + TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)) + .build(); } @Override @@ -618,14 +623,14 @@ public final class SafetySourceIssue implements Parcelable { return this; } - /** Adds data for an action to be shown in UI. */ + /** Adds data for an {@link Action} to be shown in UI. */ @NonNull public Builder addAction(@NonNull Action actionData) { mActions.add(requireNonNull(actionData)); return this; } - /** Clears data for all the actions that were added to this {@link Builder}. */ + /** Clears data for all the {@link Action}s that were added to this {@link Builder}. */ @NonNull public Builder clearActions() { mActions.clear(); @@ -656,7 +661,8 @@ public final class SafetySourceIssue implements Parcelable { checkArgument(mActions.size() <= 2, "Safety source issue must not contain more than 2 actions"); return new SafetySourceIssue(mId, mTitle, mSubtitle, mSummary, mSeverityLevel, - mIssueCategory, mActions, mOnDismissPendingIntent, mIssueTypeId); + mIssueCategory, Collections.unmodifiableList(mActions), mOnDismissPendingIntent, + mIssueTypeId); } } } diff --git a/framework-s/java/android/safetycenter/SafetySourceStatus.java b/framework-s/java/android/safetycenter/SafetySourceStatus.java index 83a54106d..9868064ff 100644 --- a/framework-s/java/android/safetycenter/SafetySourceStatus.java +++ b/framework-s/java/android/safetycenter/SafetySourceStatus.java @@ -80,17 +80,14 @@ public final class SafetySourceStatus implements Parcelable { new Parcelable.Creator<SafetySourceStatus>() { @Override public SafetySourceStatus createFromParcel(Parcel in) { - CharSequence title = - requireNonNull(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)); - CharSequence summary = - requireNonNull(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)); - int statusLevel = in.readInt(); - PendingIntent pendingIntent = - requireNonNull(PendingIntent.readPendingIntentOrNullFromParcel(in)); - IconAction iconAction = in.readTypedObject(IconAction.CREATOR); - boolean enabled = in.readBoolean(); - return new SafetySourceStatus(title, summary, statusLevel, pendingIntent, - iconAction, enabled); + return new Builder( + TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in), + TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in), + in.readInt(), + PendingIntent.readPendingIntentOrNullFromParcel(in)) + .setIconAction(in.readTypedObject(IconAction.CREATOR)) + .setEnabled(in.readBoolean()) + .build(); } @Override @@ -150,7 +147,7 @@ public final class SafetySourceStatus implements Parcelable { } /** - * Returns an optional icon action to be displayed in the safety source status UI. + * Returns an optional {@link IconAction} to be displayed in the safety source status UI. * * <p>The icon action will be a clickable icon which performs an action as indicated by the * icon. @@ -387,7 +384,7 @@ public final class SafetySourceStatus implements Parcelable { } /** - * Sets an optional icon action for the safety source status. + * Sets an optional {@link IconAction} for the safety source status. * * @see #getIconAction() */ diff --git a/framework-s/java/android/safetycenter/config/BuilderUtils.java b/framework-s/java/android/safetycenter/config/BuilderUtils.java index b94f9fe54..a01eb65c5 100644 --- a/framework-s/java/android/safetycenter/config/BuilderUtils.java +++ b/framework-s/java/android/safetycenter/config/BuilderUtils.java @@ -16,38 +16,50 @@ package android.safetycenter.config; -import android.annotation.IdRes; +import android.annotation.AnyRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Resources; +import java.util.Objects; + final class BuilderUtils { private BuilderUtils() { } - static void validateAttribute(@Nullable Object attribute, @NonNull String name, - boolean required, boolean prohibited) { + private static void validateAttribute(@Nullable Object attribute, @NonNull String name, + boolean required, boolean prohibited, @Nullable Object defaultValue) { if (attribute == null && required) { throw new IllegalStateException(String.format("Required attribute %s missing", name)); } - if (attribute != null && prohibited) { + boolean nonDefaultValueProvided = !Objects.equals(attribute, defaultValue); + boolean checkProhibited = prohibited && nonDefaultValueProvided; + if (attribute != null && checkProhibited) { throw new IllegalStateException(String.format("Prohibited attribute %s present", name)); } } - @IdRes - static int validateResId(@Nullable @IdRes Integer value, @NonNull String name, boolean required, - boolean prohibited) { - validateAttribute(value, name, required, prohibited); + static void validateAttribute(@Nullable Object attribute, @NonNull String name, + boolean required, boolean prohibited) { + validateAttribute(attribute, name, required, prohibited, null); + } + + @AnyRes + static int validateResId(@Nullable @AnyRes Integer value, @NonNull String name, + boolean required, boolean prohibited) { + validateAttribute(value, name, required, prohibited, Integer.valueOf(Resources.ID_NULL)); if (value == null) { return Resources.ID_NULL; } + if (required && value == Resources.ID_NULL) { + throw new IllegalStateException(String.format("Required attribute %s invalid", name)); + } return value; } static int validateIntDef(@Nullable Integer value, @NonNull String name, boolean required, boolean prohibited, int defaultValue, int... validValues) { - validateAttribute(value, name, required, prohibited); + validateAttribute(value, name, required, prohibited, Integer.valueOf(defaultValue)); if (value == null) { return defaultValue; } @@ -64,7 +76,7 @@ final class BuilderUtils { static int validateInteger(@Nullable Integer value, @NonNull String name, boolean required, boolean prohibited, int defaultValue) { - validateAttribute(value, name, required, prohibited); + validateAttribute(value, name, required, prohibited, Integer.valueOf(defaultValue)); if (value == null) { return defaultValue; } @@ -73,7 +85,7 @@ final class BuilderUtils { static boolean validateBoolean(@Nullable Boolean value, @NonNull String name, boolean required, boolean prohibited, boolean defaultValue) { - validateAttribute(value, name, required, prohibited); + validateAttribute(value, name, required, prohibited, Boolean.valueOf(defaultValue)); if (value == null) { return defaultValue; } diff --git a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java index 9f74be082..6f2bb8d54 100644 --- a/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java +++ b/framework-s/java/android/safetycenter/config/SafetyCenterConfig.java @@ -50,7 +50,7 @@ public final class SafetyCenterConfig implements Parcelable { mSafetySourcesGroups = safetySourcesGroups; } - /** Returns the list of safety sources groups in the configuration. */ + /** Returns the list of {@link SafetySourcesGroup}s in the configuration. */ @NonNull public List<SafetySourcesGroup> getSafetySourcesGroups() { return mSafetySourcesGroups; @@ -83,7 +83,7 @@ public final class SafetyCenterConfig implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeParcelableList(mSafetySourcesGroups, flags); + dest.writeTypedList(mSafetySourcesGroups); } @NonNull @@ -91,11 +91,14 @@ public final class SafetyCenterConfig implements Parcelable { new Parcelable.Creator<SafetyCenterConfig>() { @Override public SafetyCenterConfig createFromParcel(Parcel in) { - List<SafetySourcesGroup> safetySourcesGroups = new ArrayList<>(); - in.readParcelableList(safetySourcesGroups, - SafetySourcesGroup.class.getClassLoader()); - return new SafetyCenterConfig( - Collections.unmodifiableList(safetySourcesGroups)); + List<SafetySourcesGroup> safetySourcesGroups = + in.createTypedArrayList(SafetySourcesGroup.CREATOR); + Builder builder = new Builder(); + // TODO(b/224513050): Consider simplifying by adding a new API to the builder. + for (int i = 0; i < safetySourcesGroups.size(); i++) { + builder.addSafetySourcesGroup(safetySourcesGroups.get(i)); + } + return builder.build(); } @Override @@ -113,7 +116,7 @@ public final class SafetyCenterConfig implements Parcelable { public Builder() { } - /** Adds a safety source group to the configuration. */ + /** Adds a {@link SafetySourcesGroup} to the configuration. */ @NonNull public Builder addSafetySourcesGroup(@NonNull SafetySourcesGroup safetySourcesGroup) { mSafetySourcesGroups.add(requireNonNull(safetySourcesGroup)); diff --git a/framework-s/java/android/safetycenter/config/SafetySource.java b/framework-s/java/android/safetycenter/config/SafetySource.java index 2ec6cfdba..2ed746374 100644 --- a/framework-s/java/android/safetycenter/config/SafetySource.java +++ b/framework-s/java/android/safetycenter/config/SafetySource.java @@ -387,24 +387,21 @@ public final class SafetySource implements Parcelable { new Parcelable.Creator<SafetySource>() { @Override public SafetySource createFromParcel(Parcel in) { - int type = in.readInt(); - String id = in.readString(); - String packageName = in.readString(); - int titleResId = in.readInt(); - int titleForWorkResId = in.readInt(); - int summaryResId = in.readInt(); - String intentAction = in.readString(); - int profile = in.readInt(); - int initialDisplayState = in.readInt(); - int maxSeverityLevel = in.readInt(); - int searchTermsResId = in.readInt(); - String broadcastReceiverClassName = in.readString(); - boolean loggingAllowed = in.readBoolean(); - boolean refreshOnPageOpenAllowed = in.readBoolean(); - return new SafetySource(type, id, packageName, titleResId, titleForWorkResId, - summaryResId, intentAction, profile, initialDisplayState, - maxSeverityLevel, searchTermsResId, broadcastReceiverClassName, - loggingAllowed, refreshOnPageOpenAllowed); + return new Builder(in.readInt()) + .setId(in.readString()) + .setPackageName(in.readString()) + .setTitleResId(in.readInt()) + .setTitleForWorkResId(in.readInt()) + .setSummaryResId(in.readInt()) + .setIntentAction(in.readString()) + .setProfile(in.readInt()) + .setInitialDisplayState(in.readInt()) + .setMaxSeverityLevel(in.readInt()) + .setSearchTermsResId(in.readInt()) + .setBroadcastReceiverClassName(in.readString()) + .setLoggingAllowed(in.readBoolean()) + .setRefreshOnPageOpenAllowed(in.readBoolean()) + .build(); } @Override diff --git a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java index 84ce67748..e76d9a634 100644 --- a/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java +++ b/framework-s/java/android/safetycenter/config/SafetySourcesGroup.java @@ -163,7 +163,7 @@ public final class SafetySourcesGroup implements Parcelable { return mStatelessIconType; } - /** Returns the list of safety sources in this safety sources group. */ + /** Returns the list of {@link SafetySource}s in this safety sources group. */ @NonNull public List<SafetySource> getSafetySources() { return mSafetySources; @@ -208,7 +208,7 @@ public final class SafetySourcesGroup implements Parcelable { dest.writeInt(mTitleResId); dest.writeInt(mSummaryResId); dest.writeInt(mStatelessIconType); - dest.writeParcelableList(mSafetySources, flags); + dest.writeTypedList(mSafetySources); } @NonNull @@ -216,14 +216,18 @@ public final class SafetySourcesGroup implements Parcelable { new Parcelable.Creator<SafetySourcesGroup>() { @Override public SafetySourcesGroup createFromParcel(Parcel in) { - String id = in.readString(); - int titleResId = in.readInt(); - int summaryResId = in.readInt(); - int statelessIconType = in.readInt(); - List<SafetySource> safetySources = new ArrayList<>(); - in.readParcelableList(safetySources, SafetySource.class.getClassLoader()); - return new SafetySourcesGroup(id, titleResId, summaryResId, statelessIconType, - Collections.unmodifiableList(safetySources)); + Builder builder = new Builder() + .setId(in.readString()) + .setTitleResId(in.readInt()) + .setSummaryResId(in.readInt()) + .setStatelessIconType(in.readInt()); + List<SafetySource> safetySources = + in.createTypedArrayList(SafetySource.CREATOR); + // TODO(b/224513050): Consider simplifying by adding a new API to the builder. + for (int i = 0; i < safetySources.size(); i++) { + builder.addSafetySource(safetySources.get(i)); + } + return builder.build(); } @Override @@ -280,7 +284,7 @@ public final class SafetySourcesGroup implements Parcelable { return this; } - /** Adds a safety source to this safety sources group. */ + /** Adds a {@link SafetySource} to this safety sources group. */ @NonNull public Builder addSafetySource(@NonNull SafetySource safetySource) { mSafetySources.add(requireNonNull(safetySource)); |