• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.service.settings.preferences;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.SuppressLint;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.text.TextUtils;
27 
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 
31 import com.android.settingslib.flags.Flags;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Objects;
39 
40 /**
41  * Data object representation of a Settings Preference definition and state.
42  */
43 @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
44 public final class SettingsPreferenceMetadata implements Parcelable {
45 
46     @NonNull
47     private final String mKey;
48     @NonNull
49     private final String mScreenKey;
50     @Nullable
51     private final String mTitle;
52     @Nullable
53     private final String mSummary;
54     @NonNull
55     private final List<String> mBreadcrumbs;
56     @NonNull
57     private final List<String> mReadPermissions;
58     @NonNull
59     private final List<String> mWritePermissions;
60     private final boolean mEnabled;
61     private final boolean mAvailable;
62     private final boolean mWritable;
63     private final boolean mRestricted;
64     private final int mSensitivity;
65     @Nullable
66     private final Intent mLaunchIntent;
67     @NonNull
68     private final Bundle mExtras;
69 
70     /**
71      * Returns the key of Preference.
72      */
73     @NonNull
getKey()74     public String getKey() {
75         return mKey;
76     }
77 
78     /**
79      * Returns the screen key of Preference.
80      */
81     @NonNull
getScreenKey()82     public String getScreenKey() {
83         return mScreenKey;
84     }
85 
86     /**
87      * Returns the title of Preference.
88      */
89     @Nullable
getTitle()90     public String getTitle() {
91         return mTitle;
92     }
93 
94     /**
95      * Returns the summary of Preference.
96      */
97     @Nullable
getSummary()98     public String getSummary() {
99         return mSummary;
100     }
101 
102     /**
103      * Returns the breadcrumbs (navigation context) of Preference.
104      * <p>May be empty.
105      * @hide restrict to platform; may be opened wider in the future
106      */
107     @NonNull
getBreadcrumbs()108     public List<String> getBreadcrumbs() {
109         return mBreadcrumbs;
110     }
111 
112     /**
113      * Returns the permissions required to read this Preference's value.
114      * <p>May be empty.
115      */
116     @NonNull
getReadPermissions()117     public List<String> getReadPermissions() {
118         return mReadPermissions;
119     }
120 
121     /**
122      * Returns the permissions required to write this Preference's value.
123      * <p>May be empty.
124      */
125     @NonNull
getWritePermissions()126     public List<String> getWritePermissions() {
127         return mWritePermissions;
128     }
129 
130     /**
131      * Returns whether Preference is enabled.
132      */
isEnabled()133     public boolean isEnabled() {
134         return mEnabled;
135     }
136 
137     /**
138      * Returns whether Preference is available.
139      */
isAvailable()140     public boolean isAvailable() {
141         return mAvailable;
142     }
143 
144     /**
145      * Returns whether Preference is writable.
146      */
isWritable()147     public boolean isWritable() {
148         return mWritable;
149     }
150 
151     /**
152      * Returns whether Preference is restricted.
153      * <p>If true, this means the Preference is treated as a Restricted Preference which indicates
154      * that it could be conditionally disabled/unavailable due to admin settings.
155      */
isRestricted()156     public boolean isRestricted() {
157         return mRestricted;
158     }
159 
160     /**
161      * Returns the write-level sensitivity of Preference.
162      */
163     @WriteSensitivity
getWriteSensitivity()164     public int getWriteSensitivity() {
165         return mSensitivity;
166     }
167 
168     /**
169      * Returns the intent to launch the host app page for this Preference.
170      */
171     @SuppressLint("IntentBuilderName")
172     @Nullable
getLaunchIntent()173     public Intent getLaunchIntent() {
174         return mLaunchIntent;
175     }
176 
177     /**
178      * Returns any additional fields specific to this preference.
179      * <p>Treat all data as optional. This may contain unstructured data for a given preference,
180      * where the type and format of this data may only known by inspecting the source code of that
181      * preference. As such, any access of this data must handle failures gracefully to account for
182      * changing or missing data.
183      */
184     @NonNull
getExtras()185     public Bundle getExtras() {
186         return mExtras;
187     }
188 
189     /** @hide */
190     @IntDef(value = {
191             NO_SENSITIVITY,
192             EXPECT_POST_CONFIRMATION,
193             DEEPLINK_ONLY,
194             NO_DIRECT_ACCESS,
195     })
196     @Retention(RetentionPolicy.SOURCE)
197     public @interface WriteSensitivity {}
198 
199     /**
200      * Indicates preference is not write-sensitive.
201      * <p>Its value is writable without explicit consent, assuming all necessary permissions are
202      * granted.
203      */
204     public static final int NO_SENSITIVITY = 0;
205     /**
206      * Indicates preference is mildly write-sensitive.
207      * <p>In addition to necessary permissions, after writing its value the user should be
208      * given the option to revert back.
209      */
210     public static final int EXPECT_POST_CONFIRMATION = 1;
211     /**
212      * Indicates preference is write-sensitive.
213      * <p>This preference cannot be changed through this API; instead a deeplink to the Preference's
214      * page should be used instead, accessible via {@link #getLaunchIntent}.
215      */
216     public static final int DEEPLINK_ONLY = 2;
217     /**
218      * Indicates preference is highly write-sensitivity and carries significant user-risk.
219      * <p>This Preference cannot be changed through this API and no direct deeplink is available.
220      * Other Metadata is still available.
221      */
222     public static final int NO_DIRECT_ACCESS = 3;
223 
SettingsPreferenceMetadata(@onNull Builder builder)224     private SettingsPreferenceMetadata(@NonNull Builder builder) {
225         mKey = builder.mKey;
226         mScreenKey = builder.mScreenKey;
227         mTitle = builder.mTitle;
228         mSummary = builder.mSummary;
229         mBreadcrumbs = builder.mBreadcrumbs;
230         mReadPermissions = builder.mReadPermissions;
231         mWritePermissions = builder.mWritePermissions;
232         mEnabled = builder.mEnabled;
233         mAvailable = builder.mAvailable;
234         mWritable = builder.mWritable;
235         mRestricted = builder.mRestricted;
236         mSensitivity = builder.mSensitivity;
237         mLaunchIntent = builder.mLaunchIntent;
238         mExtras = Objects.requireNonNullElseGet(builder.mExtras, Bundle::new);
239     }
240     @SuppressLint("ParcelClassLoader")
SettingsPreferenceMetadata(@onNull Parcel in)241     private SettingsPreferenceMetadata(@NonNull Parcel in) {
242         mKey = Objects.requireNonNull(in.readString8());
243         mScreenKey = Objects.requireNonNull(in.readString8());
244         mTitle = in.readString8();
245         mSummary = in.readString8();
246         mBreadcrumbs = new ArrayList<>();
247         in.readStringList(mBreadcrumbs);
248         mReadPermissions = new ArrayList<>();
249         in.readStringList(mReadPermissions);
250         mWritePermissions = new ArrayList<>();
251         in.readStringList(mWritePermissions);
252         mEnabled = in.readBoolean();
253         mAvailable = in.readBoolean();
254         mWritable = in.readBoolean();
255         mRestricted = in.readBoolean();
256         mSensitivity = in.readInt();
257         mLaunchIntent = in.readParcelable(Intent.class.getClassLoader(),
258                 Intent.class);
259         mExtras = Objects.requireNonNullElseGet(in.readBundle(), Bundle::new);
260     }
261 
262     /** @hide */
263     @Override
describeContents()264     public int describeContents() {
265         return 0;
266     }
267 
268     /** @hide */
269     @Override
writeToParcel(@onNull Parcel dest, int flags)270     public void writeToParcel(@NonNull Parcel dest, int flags) {
271         dest.writeString8(mKey);
272         dest.writeString8(mScreenKey);
273         dest.writeString8(mTitle);
274         dest.writeString8(mSummary);
275         dest.writeStringList(mBreadcrumbs);
276         dest.writeStringList(mReadPermissions);
277         dest.writeStringList(mWritePermissions);
278         dest.writeBoolean(mEnabled);
279         dest.writeBoolean(mAvailable);
280         dest.writeBoolean(mWritable);
281         dest.writeBoolean(mRestricted);
282         dest.writeInt(mSensitivity);
283         dest.writeParcelable(mLaunchIntent, flags);
284         dest.writeBundle(mExtras);
285     }
286 
287     /**
288      * Parcelable Creator for {@link SettingsPreferenceMetadata}.
289      */
290     @NonNull
291     public static final Creator<SettingsPreferenceMetadata> CREATOR = new Creator<>() {
292         @Override
293         public SettingsPreferenceMetadata createFromParcel(@NonNull Parcel in) {
294             return new SettingsPreferenceMetadata(in);
295         }
296 
297         @Override
298         public SettingsPreferenceMetadata[] newArray(int size) {
299             return new SettingsPreferenceMetadata[size];
300         }
301     };
302 
303     /**
304      * Builder to construct {@link SettingsPreferenceMetadata}.
305      */
306     @FlaggedApi(Flags.FLAG_SETTINGS_CATALYST)
307     public static final class Builder {
308         private final String mScreenKey;
309         private final String mKey;
310         private String mTitle;
311         private String mSummary;
312         private List<String> mBreadcrumbs = Collections.emptyList();
313         private List<String> mReadPermissions = Collections.emptyList();
314         private List<String> mWritePermissions = Collections.emptyList();
315         private boolean mEnabled = false;
316         private boolean mAvailable = false;
317         private boolean mWritable = false;
318         private boolean mRestricted = false;
319         @WriteSensitivity private int mSensitivity = NO_DIRECT_ACCESS;
320         private Intent mLaunchIntent;
321         private Bundle mExtras;
322 
323         /**
324          * Create Builder instance.
325          * @param screenKey required to be not empty
326          * @param key required to be not empty
327          */
Builder(@onNull String screenKey, @NonNull String key)328         public Builder(@NonNull String screenKey, @NonNull String key) {
329             if (TextUtils.isEmpty(screenKey)) {
330                 throw new IllegalArgumentException("screenKey cannot be empty");
331             }
332             if (TextUtils.isEmpty(key)) {
333                 throw new IllegalArgumentException("key cannot be empty");
334             }
335             mScreenKey = screenKey;
336             mKey = key;
337         }
338 
339         /**
340          * Sets the preference title.
341          */
342         @NonNull
setTitle(@ullable String title)343         public Builder setTitle(@Nullable String title) {
344             mTitle = title;
345             return this;
346         }
347 
348         /**
349          * Sets the preference summary.
350          */
351         @NonNull
setSummary(@ullable String summary)352         public Builder setSummary(@Nullable String summary) {
353             mSummary = summary;
354             return this;
355         }
356 
357         /**
358          * Sets the preference breadcrumbs (navigation context).
359          * @hide
360          */
361         @NonNull
setBreadcrumbs(@onNull List<String> breadcrumbs)362         public Builder setBreadcrumbs(@NonNull List<String> breadcrumbs) {
363             mBreadcrumbs = breadcrumbs;
364             return this;
365         }
366 
367         /**
368          * Sets the permissions required for reading this preference.
369          */
370         @NonNull
setReadPermissions(@onNull List<String> readPermissions)371         public Builder setReadPermissions(@NonNull List<String> readPermissions) {
372             mReadPermissions = readPermissions;
373             return this;
374         }
375 
376         /**
377          * Sets the permissions required for writing this preference.
378          */
379         @NonNull
setWritePermissions(@onNull List<String> writePermissions)380         public Builder setWritePermissions(@NonNull List<String> writePermissions) {
381             mWritePermissions = writePermissions;
382             return this;
383         }
384 
385         /**
386          * Set whether the preference is enabled.
387          */
388         @NonNull
setEnabled(boolean enabled)389         public Builder setEnabled(boolean enabled) {
390             mEnabled = enabled;
391             return this;
392         }
393 
394         /**
395          * Sets whether the preference is available.
396          */
397         @NonNull
setAvailable(boolean available)398         public Builder setAvailable(boolean available) {
399             mAvailable = available;
400             return this;
401         }
402 
403         /**
404          * Sets whether the preference is writable.
405          */
406         @NonNull
setWritable(boolean writable)407         public Builder setWritable(boolean writable) {
408             mWritable = writable;
409             return this;
410         }
411 
412         /**
413          * Sets whether the preference is restricted.
414          */
415         @NonNull
setRestricted(boolean restricted)416         public Builder setRestricted(boolean restricted) {
417             mRestricted = restricted;
418             return this;
419         }
420 
421         /**
422          * Sets the preference write-level sensitivity.
423          */
424         @NonNull
setWriteSensitivity(@riteSensitivity int sensitivity)425         public Builder setWriteSensitivity(@WriteSensitivity int sensitivity) {
426             mSensitivity = sensitivity;
427             return this;
428         }
429 
430         /**
431          * Sets the intent to launch the host app page for this preference.
432          */
433         @NonNull
setLaunchIntent(@ullable Intent launchIntent)434         public Builder setLaunchIntent(@Nullable Intent launchIntent) {
435             mLaunchIntent = launchIntent;
436             return this;
437         }
438 
439         /**
440          * Sets additional fields specific to this preference. Treat all data as optional.
441          */
442         @NonNull
setExtras(@onNull Bundle extras)443         public Builder setExtras(@NonNull Bundle extras) {
444             mExtras = extras;
445             return this;
446         }
447 
448         /**
449          * Constructs an immutable {@link SettingsPreferenceMetadata} object.
450          */
451         @NonNull
build()452         public SettingsPreferenceMetadata build() {
453             if (mSensitivity == NO_DIRECT_ACCESS) {
454                 mLaunchIntent = null;
455             }
456             return new SettingsPreferenceMetadata(this);
457         }
458     }
459 }
460