1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.safetycenter; 18 19 import static android.os.Build.VERSION_CODES.TIRAMISU; 20 21 import static java.util.Collections.unmodifiableList; 22 import static java.util.Objects.requireNonNull; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.annotation.SystemApi; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.safetycenter.config.SafetySourcesGroup; 30 import android.text.TextUtils; 31 32 import androidx.annotation.RequiresApi; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.Objects; 37 38 /** 39 * A group of conceptually related Safety Center entries. 40 * 41 * @hide 42 */ 43 @SystemApi 44 @RequiresApi(TIRAMISU) 45 public final class SafetyCenterEntryGroup implements Parcelable { 46 47 @NonNull 48 public static final Creator<SafetyCenterEntryGroup> CREATOR = 49 new Creator<SafetyCenterEntryGroup>() { 50 @Override 51 public SafetyCenterEntryGroup createFromParcel(Parcel in) { 52 String id = in.readString(); 53 CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 54 return new Builder(id, title) 55 .setSummary(TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in)) 56 .setSeverityLevel(in.readInt()) 57 .setSeverityUnspecifiedIconType(in.readInt()) 58 .setEntries(in.createTypedArrayList(SafetyCenterEntry.CREATOR)) 59 .build(); 60 } 61 62 @Override 63 public SafetyCenterEntryGroup[] newArray(int size) { 64 return new SafetyCenterEntryGroup[size]; 65 } 66 }; 67 68 @NonNull private final String mId; 69 @NonNull private final CharSequence mTitle; 70 @Nullable private final CharSequence mSummary; 71 @SafetyCenterEntry.EntrySeverityLevel private final int mSeverityLevel; 72 @SafetyCenterEntry.SeverityUnspecifiedIconType private final int mSeverityUnspecifiedIconType; 73 @NonNull private final List<SafetyCenterEntry> mEntries; 74 SafetyCenterEntryGroup( @onNull String id, @NonNull CharSequence title, @Nullable CharSequence summary, @SafetyCenterEntry.EntrySeverityLevel int severityLevel, @SafetyCenterEntry.SeverityUnspecifiedIconType int severityUnspecifiedIconType, @NonNull List<SafetyCenterEntry> entries)75 private SafetyCenterEntryGroup( 76 @NonNull String id, 77 @NonNull CharSequence title, 78 @Nullable CharSequence summary, 79 @SafetyCenterEntry.EntrySeverityLevel int severityLevel, 80 @SafetyCenterEntry.SeverityUnspecifiedIconType int severityUnspecifiedIconType, 81 @NonNull List<SafetyCenterEntry> entries) { 82 mId = id; 83 mTitle = title; 84 mSummary = summary; 85 mSeverityLevel = severityLevel; 86 mSeverityUnspecifiedIconType = severityUnspecifiedIconType; 87 mEntries = entries; 88 } 89 90 /** Returns the ID of the {@link SafetySourcesGroup} that this group corresponds to. */ 91 @NonNull getId()92 public String getId() { 93 return mId; 94 } 95 96 /** Returns the title of this entry group. */ 97 @NonNull getTitle()98 public CharSequence getTitle() { 99 return mTitle; 100 } 101 102 /** 103 * Returns the summary string describing this entry group if present, or {@code null} otherwise. 104 */ 105 @Nullable getSummary()106 public CharSequence getSummary() { 107 return mSummary; 108 } 109 110 /** Returns the combined severity level of the entries in this entry group. */ 111 @SafetyCenterEntry.EntrySeverityLevel getSeverityLevel()112 public int getSeverityLevel() { 113 return mSeverityLevel; 114 } 115 116 /** Returns the {@link SafetyCenterEntry.SeverityUnspecifiedIconType} for this entry group. */ 117 @SafetyCenterEntry.SeverityUnspecifiedIconType getSeverityUnspecifiedIconType()118 public int getSeverityUnspecifiedIconType() { 119 return mSeverityUnspecifiedIconType; 120 } 121 122 /** Returns the entries that comprise this entry group. */ 123 @NonNull getEntries()124 public List<SafetyCenterEntry> getEntries() { 125 return mEntries; 126 } 127 128 @Override equals(Object o)129 public boolean equals(Object o) { 130 if (this == o) return true; 131 if (!(o instanceof SafetyCenterEntryGroup)) return false; 132 SafetyCenterEntryGroup that = (SafetyCenterEntryGroup) o; 133 return mSeverityLevel == that.mSeverityLevel 134 && mSeverityUnspecifiedIconType == that.mSeverityUnspecifiedIconType 135 && Objects.equals(mId, that.mId) 136 && TextUtils.equals(mTitle, that.mTitle) 137 && TextUtils.equals(mSummary, that.mSummary) 138 && Objects.equals(mEntries, that.mEntries); 139 } 140 141 @Override hashCode()142 public int hashCode() { 143 return Objects.hash( 144 mId, mTitle, mSummary, mSeverityLevel, mSeverityUnspecifiedIconType, mEntries); 145 } 146 147 @Override toString()148 public String toString() { 149 return "SafetyCenterEntryGroup{" 150 + "mId=" 151 + mId 152 + ", mTitle=" 153 + mTitle 154 + ", mSummary=" 155 + mSummary 156 + ", mSeverityLevel=" 157 + mSeverityLevel 158 + ", mSeverityUnspecifiedIconType=" 159 + mSeverityUnspecifiedIconType 160 + ", mEntries=" 161 + mEntries 162 + '}'; 163 } 164 165 @Override describeContents()166 public int describeContents() { 167 return 0; 168 } 169 170 @Override writeToParcel(@onNull Parcel dest, int flags)171 public void writeToParcel(@NonNull Parcel dest, int flags) { 172 dest.writeString(mId); 173 TextUtils.writeToParcel(mTitle, dest, flags); 174 TextUtils.writeToParcel(mSummary, dest, flags); 175 dest.writeInt(mSeverityLevel); 176 dest.writeInt(mSeverityUnspecifiedIconType); 177 dest.writeTypedList(mEntries); 178 } 179 180 /** Builder class for {@link SafetyCenterEntryGroup} */ 181 public static final class Builder { 182 183 @NonNull private String mId; 184 @NonNull private CharSequence mTitle; 185 @Nullable private CharSequence mSummary; 186 187 @SafetyCenterEntry.EntrySeverityLevel 188 private int mSeverityLevel = SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN; 189 190 @SafetyCenterEntry.SeverityUnspecifiedIconType 191 private int mSeverityUnspecifiedIconType = 192 SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON; 193 194 @NonNull private List<SafetyCenterEntry> mEntries = new ArrayList<>(); 195 196 /** 197 * Creates a {@link Builder} for a {@link SafetyCenterEntryGroup}. 198 * 199 * @param id a unique encoded string ID, see {@link #getId} for details 200 * @param title a title for this group of entries 201 */ Builder(@onNull String id, @NonNull CharSequence title)202 public Builder(@NonNull String id, @NonNull CharSequence title) { 203 mId = requireNonNull(id); 204 mTitle = requireNonNull(title); 205 } 206 207 /** 208 * Creates a {@link Builder} with the values from the given {@link SafetyCenterEntryGroup}. 209 */ Builder(@onNull SafetyCenterEntryGroup safetyCenterEntryGroup)210 public Builder(@NonNull SafetyCenterEntryGroup safetyCenterEntryGroup) { 211 mId = safetyCenterEntryGroup.mId; 212 mTitle = safetyCenterEntryGroup.mTitle; 213 mSummary = safetyCenterEntryGroup.mSummary; 214 mSeverityLevel = safetyCenterEntryGroup.mSeverityLevel; 215 mSeverityUnspecifiedIconType = safetyCenterEntryGroup.mSeverityUnspecifiedIconType; 216 mEntries = new ArrayList<>(safetyCenterEntryGroup.mEntries); 217 } 218 219 /** Sets the ID for this entry group. */ 220 @NonNull setId(@onNull String id)221 public Builder setId(@NonNull String id) { 222 mId = requireNonNull(id); 223 return this; 224 } 225 226 /** Sets the title for this entry group. */ 227 @NonNull setTitle(@onNull CharSequence title)228 public Builder setTitle(@NonNull CharSequence title) { 229 mTitle = requireNonNull(title); 230 return this; 231 } 232 233 /** Sets the optional summary text for this entry group. */ 234 @NonNull setSummary(@ullable CharSequence summary)235 public Builder setSummary(@Nullable CharSequence summary) { 236 mSummary = summary; 237 return this; 238 } 239 240 /** 241 * Sets the {@link SafetyCenterEntry.EntrySeverityLevel} of this entry group. Defaults to 242 * {@link SafetyCenterEntry#ENTRY_SEVERITY_LEVEL_UNKNOWN}. 243 */ 244 @NonNull setSeverityLevel(@afetyCenterEntry.EntrySeverityLevel int severityLevel)245 public Builder setSeverityLevel(@SafetyCenterEntry.EntrySeverityLevel int severityLevel) { 246 mSeverityLevel = validateEntrySeverityLevel(severityLevel); 247 return this; 248 } 249 250 /** 251 * Sets the {@link SafetyCenterEntry.SeverityUnspecifiedIconType} of this entry group. 252 * Defaults to {@link SafetyCenterEntry#SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON}. 253 */ 254 @NonNull setSeverityUnspecifiedIconType( @afetyCenterEntry.SeverityUnspecifiedIconType int severityUnspecifiedIconType)255 public Builder setSeverityUnspecifiedIconType( 256 @SafetyCenterEntry.SeverityUnspecifiedIconType int severityUnspecifiedIconType) { 257 mSeverityUnspecifiedIconType = 258 validateSeverityUnspecifiedIconType(severityUnspecifiedIconType); 259 return this; 260 } 261 262 /** 263 * Sets the list of {@link SafetyCenterEntry} contained by this entry group. Defaults to an 264 * empty list. 265 */ 266 @NonNull setEntries(@onNull List<SafetyCenterEntry> entries)267 public Builder setEntries(@NonNull List<SafetyCenterEntry> entries) { 268 mEntries = requireNonNull(entries); 269 return this; 270 } 271 272 /** Creates the {@link SafetyCenterEntryGroup} defined by this {@link Builder}. */ 273 @NonNull build()274 public SafetyCenterEntryGroup build() { 275 return new SafetyCenterEntryGroup( 276 mId, 277 mTitle, 278 mSummary, 279 mSeverityLevel, 280 mSeverityUnspecifiedIconType, 281 unmodifiableList(new ArrayList<>(mEntries))); 282 } 283 } 284 285 @SafetyCenterEntry.EntrySeverityLevel validateEntrySeverityLevel(int value)286 private static int validateEntrySeverityLevel(int value) { 287 switch (value) { 288 case SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNKNOWN: 289 case SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_UNSPECIFIED: 290 case SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_OK: 291 case SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_RECOMMENDATION: 292 case SafetyCenterEntry.ENTRY_SEVERITY_LEVEL_CRITICAL_WARNING: 293 return value; 294 default: 295 } 296 throw new IllegalArgumentException( 297 "Unexpected EntrySeverityLevel for SafetyCenterEntryGroup: " + value); 298 } 299 300 @SafetyCenterEntry.SeverityUnspecifiedIconType validateSeverityUnspecifiedIconType(int value)301 private static int validateSeverityUnspecifiedIconType(int value) { 302 switch (value) { 303 case SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_ICON: 304 case SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_PRIVACY: 305 case SafetyCenterEntry.SEVERITY_UNSPECIFIED_ICON_TYPE_NO_RECOMMENDATION: 306 return value; 307 default: 308 } 309 throw new IllegalArgumentException( 310 "Unexpected SeverityUnspecifiedIconType for SafetyCenterEntryGroup: " + value); 311 } 312 } 313