• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Objects.requireNonNull;
22 
23 import android.annotation.IntDef;
24 import android.annotation.NonNull;
25 import android.annotation.SystemApi;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.text.TextUtils;
29 
30 import androidx.annotation.RequiresApi;
31 
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.util.Objects;
35 
36 /**
37  * The overall status of the Safety Center.
38  *
39  * @hide
40  */
41 @SystemApi
42 @RequiresApi(TIRAMISU)
43 public final class SafetyCenterStatus implements Parcelable {
44 
45     /** Indicates the overall severity level of the Safety Center is not currently known. */
46     public static final int OVERALL_SEVERITY_LEVEL_UNKNOWN = 1000;
47 
48     /**
49      * Indicates the overall safety status of the device is OK and there are no actionable issues.
50      */
51     public static final int OVERALL_SEVERITY_LEVEL_OK = 1100;
52 
53     /** Indicates the presence of safety recommendations which the user is encouraged to act on. */
54     public static final int OVERALL_SEVERITY_LEVEL_RECOMMENDATION = 1200;
55 
56     /** Indicates the presence of critical safety warnings on the device. */
57     public static final int OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING = 1300;
58 
59     /**
60      * All possible overall severity levels for the Safety Center.
61      *
62      * <p>The overall severity level is calculated from the severity level and statuses of all
63      * issues and entries in the Safety Center.
64      *
65      * @hide
66      * @see #getSeverityLevel()
67      * @see Builder#setSeverityLevel(int)
68      */
69     @Retention(RetentionPolicy.SOURCE)
70     @IntDef(
71             prefix = "OVERALL_SEVERITY_LEVEL_",
72             value = {
73                 OVERALL_SEVERITY_LEVEL_UNKNOWN,
74                 OVERALL_SEVERITY_LEVEL_OK,
75                 OVERALL_SEVERITY_LEVEL_RECOMMENDATION,
76                 OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING,
77             })
78     public @interface OverallSeverityLevel {}
79 
80     /** Indicates that no refresh is ongoing. */
81     public static final int REFRESH_STATUS_NONE = 0;
82 
83     /**
84      * Indicates that a data fetch is ongoing, and Safety Sources are being asked for their current
85      * safety state.
86      *
87      * <p>If sources already have their safety data cached, they may provide it without triggering a
88      * process to fetch or recompute state which may be expensive and/or slow.
89      */
90     public static final int REFRESH_STATUS_DATA_FETCH_IN_PROGRESS = 10100;
91 
92     /**
93      * Indicates that a full rescan is ongoing, and Safety Sources are being asked to fetch fresh
94      * data for their safety state.
95      *
96      * <p>The term "fresh" here means that the sources should ensure that the safety data is
97      * accurate as possible at the time of providing it to Safety Center, even if it involves
98      * performing an expensive and/or slow process.
99      */
100     public static final int REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS = 10200;
101 
102     /**
103      * All possible refresh states for the Safety Center.
104      *
105      * @hide
106      * @see #getRefreshStatus()
107      * @see Builder#setRefreshStatus(int)
108      */
109     @Retention(RetentionPolicy.SOURCE)
110     @IntDef(
111             prefix = "REFRESH_STATUS_",
112             value = {
113                 REFRESH_STATUS_NONE,
114                 REFRESH_STATUS_DATA_FETCH_IN_PROGRESS,
115                 REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS,
116             })
117     public @interface RefreshStatus {}
118 
119     @NonNull
120     public static final Creator<SafetyCenterStatus> CREATOR =
121             new Creator<SafetyCenterStatus>() {
122                 @Override
123                 public SafetyCenterStatus createFromParcel(Parcel in) {
124                     CharSequence title = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
125                     CharSequence summary = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
126                     return new Builder(title, summary)
127                             .setSeverityLevel(in.readInt())
128                             .setRefreshStatus(in.readInt())
129                             .build();
130                 }
131 
132                 @Override
133                 public SafetyCenterStatus[] newArray(int size) {
134                     return new SafetyCenterStatus[size];
135                 }
136             };
137 
138     @NonNull private final CharSequence mTitle;
139     @NonNull private final CharSequence mSummary;
140     @OverallSeverityLevel private final int mSeverityLevel;
141     @RefreshStatus private final int mRefreshStatus;
142 
SafetyCenterStatus( @onNull CharSequence title, @NonNull CharSequence summary, @OverallSeverityLevel int severityLevel, @RefreshStatus int refreshStatus)143     private SafetyCenterStatus(
144             @NonNull CharSequence title,
145             @NonNull CharSequence summary,
146             @OverallSeverityLevel int severityLevel,
147             @RefreshStatus int refreshStatus) {
148         mTitle = title;
149         mSummary = summary;
150         mSeverityLevel = severityLevel;
151         mRefreshStatus = refreshStatus;
152     }
153 
154     /** Returns the title which describes the overall safety state of the device. */
155     @NonNull
getTitle()156     public CharSequence getTitle() {
157         return mTitle;
158     }
159 
160     /** Returns the summary text which adds detail to the overall safety state of the device. */
161     @NonNull
getSummary()162     public CharSequence getSummary() {
163         return mSummary;
164     }
165 
166     /** Returns the current {@link OverallSeverityLevel} of the Safety Center. */
167     @OverallSeverityLevel
getSeverityLevel()168     public int getSeverityLevel() {
169         return mSeverityLevel;
170     }
171 
172     /** Returns the current {@link RefreshStatus} of the Safety Center */
173     @RefreshStatus
getRefreshStatus()174     public int getRefreshStatus() {
175         return mRefreshStatus;
176     }
177 
178     @Override
equals(Object o)179     public boolean equals(Object o) {
180         if (this == o) return true;
181         if (!(o instanceof SafetyCenterStatus)) return false;
182         SafetyCenterStatus that = (SafetyCenterStatus) o;
183         return mSeverityLevel == that.mSeverityLevel
184                 && mRefreshStatus == that.mRefreshStatus
185                 && TextUtils.equals(mTitle, that.mTitle)
186                 && TextUtils.equals(mSummary, that.mSummary);
187     }
188 
189     @Override
hashCode()190     public int hashCode() {
191         return Objects.hash(mTitle, mSummary, mSeverityLevel, mRefreshStatus);
192     }
193 
194     @Override
toString()195     public String toString() {
196         return "SafetyCenterStatus{"
197                 + "mTitle="
198                 + mTitle
199                 + ", mSummary="
200                 + mSummary
201                 + ", mSeverityLevel="
202                 + mSeverityLevel
203                 + ", mRefreshStatus="
204                 + mRefreshStatus
205                 + '}';
206     }
207 
208     @Override
describeContents()209     public int describeContents() {
210         return 0;
211     }
212 
213     @Override
writeToParcel(@onNull Parcel dest, int flags)214     public void writeToParcel(@NonNull Parcel dest, int flags) {
215         TextUtils.writeToParcel(mTitle, dest, flags);
216         TextUtils.writeToParcel(mSummary, dest, flags);
217         dest.writeInt(mSeverityLevel);
218         dest.writeInt(mRefreshStatus);
219     }
220 
221     /** Builder class for {@link SafetyCenterStatus}. */
222     public static final class Builder {
223 
224         @NonNull private CharSequence mTitle;
225         @NonNull private CharSequence mSummary;
226         @OverallSeverityLevel private int mSeverityLevel = OVERALL_SEVERITY_LEVEL_UNKNOWN;
227         @RefreshStatus private int mRefreshStatus = REFRESH_STATUS_NONE;
228 
229         /**
230          * Creates a new {@link Builder} for a {@link SafetyCenterStatus}.
231          *
232          * @param title an overall title for the status
233          * @param summary a summary for the status
234          */
Builder(@onNull CharSequence title, @NonNull CharSequence summary)235         public Builder(@NonNull CharSequence title, @NonNull CharSequence summary) {
236             mTitle = requireNonNull(title);
237             mSummary = requireNonNull(summary);
238         }
239 
240         /** Creates a {@link Builder} with the values from the given {@link SafetyCenterStatus}. */
Builder(@onNull SafetyCenterStatus safetyCenterStatus)241         public Builder(@NonNull SafetyCenterStatus safetyCenterStatus) {
242             mTitle = safetyCenterStatus.mTitle;
243             mSummary = safetyCenterStatus.mSummary;
244             mSeverityLevel = safetyCenterStatus.mSeverityLevel;
245             mRefreshStatus = safetyCenterStatus.mRefreshStatus;
246         }
247 
248         /** Sets the title for this status. */
249         @NonNull
setTitle(@onNull CharSequence title)250         public Builder setTitle(@NonNull CharSequence title) {
251             mTitle = requireNonNull(title);
252             return this;
253         }
254 
255         /** Sets the summary text for this status. */
256         @NonNull
setSummary(@onNull CharSequence summary)257         public Builder setSummary(@NonNull CharSequence summary) {
258             mSummary = requireNonNull(summary);
259             return this;
260         }
261 
262         /**
263          * Sets the {@link OverallSeverityLevel} of this status. Defaults to {@link
264          * #OVERALL_SEVERITY_LEVEL_UNKNOWN}.
265          */
266         @NonNull
setSeverityLevel(@verallSeverityLevel int severityLevel)267         public Builder setSeverityLevel(@OverallSeverityLevel int severityLevel) {
268             mSeverityLevel = validateOverallSeverityLevel(severityLevel);
269             return this;
270         }
271 
272         /**
273          * Sets the {@link RefreshStatus} of this status. Defaults to {@link #REFRESH_STATUS_NONE}.
274          */
275         @NonNull
setRefreshStatus(@efreshStatus int refreshStatus)276         public Builder setRefreshStatus(@RefreshStatus int refreshStatus) {
277             mRefreshStatus = validateRefreshStatus(refreshStatus);
278             return this;
279         }
280 
281         /** Creates the {@link SafetyCenterStatus} defined by this {@link Builder}. */
282         @NonNull
build()283         public SafetyCenterStatus build() {
284             return new SafetyCenterStatus(mTitle, mSummary, mSeverityLevel, mRefreshStatus);
285         }
286     }
287 
288     @OverallSeverityLevel
validateOverallSeverityLevel(int value)289     private static int validateOverallSeverityLevel(int value) {
290         switch (value) {
291             case OVERALL_SEVERITY_LEVEL_UNKNOWN:
292             case OVERALL_SEVERITY_LEVEL_OK:
293             case OVERALL_SEVERITY_LEVEL_RECOMMENDATION:
294             case OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING:
295                 return value;
296             default:
297         }
298         throw new IllegalArgumentException(
299                 "Unexpected OverallSeverityLevel for SafetyCenterStatus: " + value);
300     }
301 
302     @RefreshStatus
validateRefreshStatus(int value)303     private static int validateRefreshStatus(int value) {
304         switch (value) {
305             case REFRESH_STATUS_NONE:
306             case REFRESH_STATUS_DATA_FETCH_IN_PROGRESS:
307             case REFRESH_STATUS_FULL_RESCAN_IN_PROGRESS:
308                 return value;
309             default:
310         }
311         throw new IllegalArgumentException(
312                 "Unexpected RefreshStatus for SafetyCenterStatus: " + value);
313     }
314 }
315