|  | /* | 
|  | * Copyright (C) 2013 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.content; | 
|  |  | 
|  | import android.annotation.ArrayRes; | 
|  | import android.annotation.Nullable; | 
|  | import android.os.Parcel; | 
|  | import android.os.Parcelable; | 
|  |  | 
|  | import java.util.Arrays; | 
|  | import java.util.Objects; | 
|  |  | 
|  | /** | 
|  | * Applications can expose restrictions for a restricted user on a | 
|  | * multiuser device. The administrator can configure these restrictions that will then be | 
|  | * applied to the restricted user. Each RestrictionsEntry is one configurable restriction. | 
|  | * <p/> | 
|  | * Any application that chooses to expose such restrictions does so by implementing a | 
|  | * receiver that handles the {@link Intent#ACTION_GET_RESTRICTION_ENTRIES} action. | 
|  | * The receiver then returns a result bundle that contains an entry called "restrictions", whose | 
|  | * value is an ArrayList<RestrictionsEntry>. | 
|  | */ | 
|  | public class RestrictionEntry implements Parcelable { | 
|  |  | 
|  | /** | 
|  | * Hidden restriction type. Use this type for information that needs to be transferred | 
|  | * across but shouldn't be presented to the user in the UI. Stores a single String value. | 
|  | */ | 
|  | public static final int TYPE_NULL         = 0; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "bool". Use this for storing a boolean value, typically presented as | 
|  | * a checkbox in the UI. | 
|  | */ | 
|  | public static final int TYPE_BOOLEAN      = 1; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "choice". Use this for storing a string value, typically presented as | 
|  | * a single-select list. Call {@link #setChoiceEntries(String[])} and | 
|  | * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user | 
|  | * and the corresponding values, respectively. | 
|  | */ | 
|  | public static final int TYPE_CHOICE       = 2; | 
|  |  | 
|  | /** | 
|  | * Internal restriction type. Use this for storing a string value, typically presented as | 
|  | * a single-select list. Call {@link #setChoiceEntries(String[])} and | 
|  | * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user | 
|  | * and the corresponding values, respectively. | 
|  | * The presentation could imply that values in lower array indices are included when a | 
|  | * particular value is chosen. | 
|  | * @hide | 
|  | */ | 
|  | public static final int TYPE_CHOICE_LEVEL = 3; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "multi-select". Use this for presenting a multi-select list where more | 
|  | * than one entry can be selected, such as for choosing specific titles to allowlist. | 
|  | * Call {@link #setChoiceEntries(String[])} and | 
|  | * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user | 
|  | * and the corresponding values, respectively. | 
|  | * Use {@link #getAllSelectedStrings()} and {@link #setAllSelectedStrings(String[])} to | 
|  | * manipulate the selections. | 
|  | */ | 
|  | public static final int TYPE_MULTI_SELECT = 4; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "integer". Use this for storing an integer value. The range of values | 
|  | * is from {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}. | 
|  | */ | 
|  | public static final int TYPE_INTEGER = 5; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "string". Use this for storing a string value. | 
|  | * @see #setSelectedString | 
|  | * @see #getSelectedString | 
|  | */ | 
|  | public static final int TYPE_STRING = 6; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "bundle". Use this for storing {@link android.os.Bundle bundles} of | 
|  | * restrictions | 
|  | */ | 
|  | public static final int TYPE_BUNDLE = 7; | 
|  |  | 
|  | /** | 
|  | * Restriction of type "bundle_array". Use this for storing arrays of | 
|  | * {@link android.os.Bundle bundles} of restrictions | 
|  | */ | 
|  | public static final int TYPE_BUNDLE_ARRAY = 8; | 
|  |  | 
|  | /** The type of restriction. */ | 
|  | private int mType; | 
|  |  | 
|  | /** The unique key that identifies the restriction. */ | 
|  | private String mKey; | 
|  |  | 
|  | /** The user-visible title of the restriction. */ | 
|  | private String mTitle; | 
|  |  | 
|  | /** The user-visible secondary description of the restriction. */ | 
|  | private String mDescription; | 
|  |  | 
|  | /** The user-visible set of choices used for single-select and multi-select lists. */ | 
|  | private String[] mChoiceEntries; | 
|  |  | 
|  | /** The values corresponding to the user-visible choices. The value(s) of this entry will | 
|  | * one or more of these, returned by {@link #getAllSelectedStrings()} and | 
|  | * {@link #getSelectedString()}. | 
|  | */ | 
|  | private String[] mChoiceValues; | 
|  |  | 
|  | /* The chosen value, whose content depends on the type of the restriction. */ | 
|  | private String mCurrentValue; | 
|  |  | 
|  | /* List of selected choices in the multi-select case. */ | 
|  | private String[] mCurrentValues; | 
|  |  | 
|  | /** | 
|  | * List of nested restrictions. Used by {@link #TYPE_BUNDLE bundle} and | 
|  | * {@link #TYPE_BUNDLE_ARRAY bundle_array} restrictions. | 
|  | */ | 
|  | private RestrictionEntry[] mRestrictions; | 
|  |  | 
|  | /** | 
|  | * Constructor for specifying the type and key, with no initial value; | 
|  | * | 
|  | * @param type the restriction type. | 
|  | * @param key the unique key for this restriction | 
|  | */ | 
|  | public RestrictionEntry(int type, String key) { | 
|  | mType = type; | 
|  | mKey = key; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructor for {@link #TYPE_CHOICE} type. | 
|  | * @param key the unique key for this restriction | 
|  | * @param selectedString the current value | 
|  | */ | 
|  | public RestrictionEntry(String key, String selectedString) { | 
|  | this.mKey = key; | 
|  | this.mType = TYPE_CHOICE; | 
|  | this.mCurrentValue = selectedString; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructor for {@link #TYPE_BOOLEAN} type. | 
|  | * @param key the unique key for this restriction | 
|  | * @param selectedState whether this restriction is selected or not | 
|  | */ | 
|  | public RestrictionEntry(String key, boolean selectedState) { | 
|  | this.mKey = key; | 
|  | this.mType = TYPE_BOOLEAN; | 
|  | setSelectedState(selectedState); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructor for {@link #TYPE_MULTI_SELECT} type. | 
|  | * @param key the unique key for this restriction | 
|  | * @param selectedStrings the list of values that are currently selected | 
|  | */ | 
|  | public RestrictionEntry(String key, String[] selectedStrings) { | 
|  | this.mKey = key; | 
|  | this.mType = TYPE_MULTI_SELECT; | 
|  | this.mCurrentValues = selectedStrings; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructor for {@link #TYPE_INTEGER} type. | 
|  | * @param key the unique key for this restriction | 
|  | * @param selectedInt the integer value of the restriction | 
|  | */ | 
|  | public RestrictionEntry(String key, int selectedInt) { | 
|  | mKey = key; | 
|  | mType = TYPE_INTEGER; | 
|  | setIntValue(selectedInt); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Constructor for {@link #TYPE_BUNDLE}/{@link #TYPE_BUNDLE_ARRAY} type. | 
|  | * @param key the unique key for this restriction | 
|  | * @param restrictionEntries array of nested restriction entries. If the entry, being created | 
|  | * represents a {@link #TYPE_BUNDLE_ARRAY bundle-array}, {@code restrictionEntries} array may | 
|  | * only contain elements of type {@link #TYPE_BUNDLE bundle}. | 
|  | * @param isBundleArray true if this restriction represents | 
|  | * {@link #TYPE_BUNDLE_ARRAY bundle-array} type, otherwise the type will be set to | 
|  | * {@link #TYPE_BUNDLE bundle}. | 
|  | */ | 
|  | private RestrictionEntry(String key, RestrictionEntry[] restrictionEntries, | 
|  | boolean isBundleArray) { | 
|  | mKey = key; | 
|  | if (isBundleArray) { | 
|  | mType = TYPE_BUNDLE_ARRAY; | 
|  | if (restrictionEntries != null) { | 
|  | for (RestrictionEntry restriction : restrictionEntries) { | 
|  | if (restriction.getType() != TYPE_BUNDLE) { | 
|  | throw new IllegalArgumentException("bundle_array restriction can only have " | 
|  | + "nested restriction entries of type bundle"); | 
|  | } | 
|  | } | 
|  | } | 
|  | } else { | 
|  | mType = TYPE_BUNDLE; | 
|  | } | 
|  | setRestrictions(restrictionEntries); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates an entry of type {@link #TYPE_BUNDLE}. | 
|  | * @param key the unique key for this restriction | 
|  | * @param restrictionEntries array of nested restriction entries. | 
|  | * @return the newly created restriction | 
|  | */ | 
|  | public static RestrictionEntry createBundleEntry(String key, | 
|  | RestrictionEntry[] restrictionEntries) { | 
|  | return new RestrictionEntry(key, restrictionEntries, false); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Creates an entry of type {@link #TYPE_BUNDLE_ARRAY}. | 
|  | * @param key the unique key for this restriction | 
|  | * @param restrictionEntries array of nested restriction entries. The array may only contain | 
|  | * elements of type {@link #TYPE_BUNDLE bundle}. | 
|  | * @return the newly created restriction | 
|  | */ | 
|  | public static RestrictionEntry createBundleArrayEntry(String key, | 
|  | RestrictionEntry[] restrictionEntries) { | 
|  | return new RestrictionEntry(key, restrictionEntries, true); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the type for this restriction. | 
|  | * @param type the type for this restriction. | 
|  | */ | 
|  | public void setType(int type) { | 
|  | this.mType = type; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the type for this restriction. | 
|  | * @return the type for this restriction | 
|  | */ | 
|  | public int getType() { | 
|  | return mType; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the currently selected string value. | 
|  | * @return the currently selected value, which can be null for types that aren't for holding | 
|  | * single string values. | 
|  | */ | 
|  | public String getSelectedString() { | 
|  | return mCurrentValue; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the list of currently selected values. | 
|  | * @return the list of current selections, if type is {@link #TYPE_MULTI_SELECT}, | 
|  | *  null otherwise. | 
|  | */ | 
|  | public String[] getAllSelectedStrings() { | 
|  | return mCurrentValues; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the current selected state for an entry of type {@link #TYPE_BOOLEAN}. | 
|  | * @return the current selected state of the entry. | 
|  | */ | 
|  | public boolean getSelectedState() { | 
|  | return Boolean.parseBoolean(mCurrentValue); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the value of the entry as an integer when the type is {@link #TYPE_INTEGER}. | 
|  | * @return the integer value of the entry. | 
|  | */ | 
|  | public int getIntValue() { | 
|  | return Integer.parseInt(mCurrentValue); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the integer value of the entry when the type is {@link #TYPE_INTEGER}. | 
|  | * @param value the integer value to set. | 
|  | */ | 
|  | public void setIntValue(int value) { | 
|  | mCurrentValue = Integer.toString(value); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the string value to use as the selected value for this restriction. This value will | 
|  | * be persisted by the system for later use by the application. | 
|  | * @param selectedString the string value to select. | 
|  | */ | 
|  | public void setSelectedString(String selectedString) { | 
|  | mCurrentValue = selectedString; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the current selected state for an entry of type {@link #TYPE_BOOLEAN}. This value will | 
|  | * be persisted by the system for later use by the application. | 
|  | * @param state the current selected state | 
|  | */ | 
|  | public void setSelectedState(boolean state) { | 
|  | mCurrentValue = Boolean.toString(state); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the current list of selected values for an entry of type {@link #TYPE_MULTI_SELECT}. | 
|  | * These values will be persisted by the system for later use by the application. | 
|  | * @param allSelectedStrings the current list of selected values. | 
|  | */ | 
|  | public void setAllSelectedStrings(String[] allSelectedStrings) { | 
|  | mCurrentValues = allSelectedStrings; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets a list of string values that can be selected by the user. If no user-visible entries | 
|  | * are set by a call to {@link #setChoiceEntries(String[])}, these values will be the ones | 
|  | * shown to the user. Values will be chosen from this list as the user's selection and the | 
|  | * selected values can be retrieved by a call to {@link #getAllSelectedStrings()}, or | 
|  | * {@link #getSelectedString()}, depending on whether it is a multi-select type or choice type. | 
|  | * This method is not relevant for types other than | 
|  | * {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}. | 
|  | * @param choiceValues an array of Strings which will be the selected values for the user's | 
|  | * selections. | 
|  | * @see #getChoiceValues() | 
|  | * @see #getAllSelectedStrings() | 
|  | */ | 
|  | public void setChoiceValues(String[] choiceValues) { | 
|  | mChoiceValues = choiceValues; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets a list of string values that can be selected by the user, similar to | 
|  | * {@link #setChoiceValues(String[])}. | 
|  | * @param context the application context for retrieving the resources. | 
|  | * @param stringArrayResId the resource id for a string array containing the possible values. | 
|  | * @see #setChoiceValues(String[]) | 
|  | */ | 
|  | public void setChoiceValues(Context context, @ArrayRes int stringArrayResId) { | 
|  | mChoiceValues = context.getResources().getStringArray(stringArrayResId); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns array of possible restriction entries that this entry may contain. | 
|  | */ | 
|  | public RestrictionEntry[] getRestrictions() { | 
|  | return mRestrictions; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets an array of possible restriction entries, that this entry may contain. | 
|  | * <p>This method is only relevant for types {@link #TYPE_BUNDLE} and | 
|  | * {@link #TYPE_BUNDLE_ARRAY} | 
|  | */ | 
|  | public void setRestrictions(RestrictionEntry[] restrictions) { | 
|  | mRestrictions = restrictions; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the list of possible string values set earlier. | 
|  | * @return the list of possible values. | 
|  | */ | 
|  | public String[] getChoiceValues() { | 
|  | return mChoiceValues; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets a list of strings that will be presented as choices to the user. When the | 
|  | * user selects one or more of these choices, the corresponding value from the possible values | 
|  | * are stored as the selected strings. The size of this array must match the size of the array | 
|  | * set in {@link #setChoiceValues(String[])}. This method is not relevant for types other | 
|  | * than {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}. | 
|  | * @param choiceEntries the list of user-visible choices. | 
|  | * @see #setChoiceValues(String[]) | 
|  | */ | 
|  | public void setChoiceEntries(String[] choiceEntries) { | 
|  | mChoiceEntries = choiceEntries; | 
|  | } | 
|  |  | 
|  | /** Sets a list of strings that will be presented as choices to the user. This is similar to | 
|  | * {@link #setChoiceEntries(String[])}. | 
|  | * @param context the application context, used for retrieving the resources. | 
|  | * @param stringArrayResId the resource id of a string array containing the possible entries. | 
|  | */ | 
|  | public void setChoiceEntries(Context context, @ArrayRes int stringArrayResId) { | 
|  | mChoiceEntries = context.getResources().getStringArray(stringArrayResId); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the list of strings, set earlier, that will be presented as choices to the user. | 
|  | * @return the list of choices presented to the user. | 
|  | */ | 
|  | public String[] getChoiceEntries() { | 
|  | return mChoiceEntries; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the provided user-visible description of the entry, if any. | 
|  | * @return the user-visible description, null if none was set earlier. | 
|  | */ | 
|  | public String getDescription() { | 
|  | return mDescription; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the user-visible description of the entry, as a possible sub-text for the title. | 
|  | * You can use this to describe the entry in more detail or to display the current state of | 
|  | * the restriction. | 
|  | * @param description the user-visible description string. | 
|  | */ | 
|  | public void setDescription(String description) { | 
|  | this.mDescription = description; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * This is the unique key for the restriction entry. | 
|  | * @return the key for the restriction. | 
|  | */ | 
|  | public String getKey() { | 
|  | return mKey; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns the user-visible title for the entry, if any. | 
|  | * @return the user-visible title for the entry, null if none was set earlier. | 
|  | */ | 
|  | public String getTitle() { | 
|  | return mTitle; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Sets the user-visible title for the entry. | 
|  | * @param title the user-visible title for the entry. | 
|  | */ | 
|  | public void setTitle(String title) { | 
|  | this.mTitle = title; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean equals(@Nullable Object o) { | 
|  | if (o == this) return true; | 
|  | if (!(o instanceof RestrictionEntry)) return false; | 
|  | final RestrictionEntry other = (RestrictionEntry) o; | 
|  | if (mType != other.mType || !mKey.equals(other.mKey)) { | 
|  | return false; | 
|  | } | 
|  | if (mCurrentValues == null && other.mCurrentValues == null | 
|  | && mRestrictions == null && other.mRestrictions == null | 
|  | && Objects.equals(mCurrentValue, other.mCurrentValue)) { | 
|  | return true; | 
|  | } | 
|  | if (mCurrentValue == null && other.mCurrentValue == null | 
|  | && mRestrictions == null && other.mRestrictions == null | 
|  | && Arrays.equals(mCurrentValues, other.mCurrentValues)) { | 
|  | return true; | 
|  | } | 
|  | if (mCurrentValue == null && other.mCurrentValue == null | 
|  | && mCurrentValue == null && other.mCurrentValue == null | 
|  | && Arrays.equals(mRestrictions, other.mRestrictions)) { | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int hashCode() { | 
|  | int result = 17; | 
|  | result = 31 * result + mKey.hashCode(); | 
|  | if (mCurrentValue != null) { | 
|  | result = 31 * result + mCurrentValue.hashCode(); | 
|  | } else if (mCurrentValues != null) { | 
|  | for (String value : mCurrentValues) { | 
|  | if (value != null) { | 
|  | result = 31 * result + value.hashCode(); | 
|  | } | 
|  | } | 
|  | } else if (mRestrictions != null) { | 
|  | result = 31 * result + Arrays.hashCode(mRestrictions); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | public RestrictionEntry(Parcel in) { | 
|  | mType = in.readInt(); | 
|  | mKey = in.readString(); | 
|  | mTitle = in.readString(); | 
|  | mDescription = in.readString(); | 
|  | mChoiceEntries = in.readStringArray(); | 
|  | mChoiceValues = in.readStringArray(); | 
|  | mCurrentValue = in.readString(); | 
|  | mCurrentValues = in.readStringArray(); | 
|  | Parcelable[] parcelables = in.readParcelableArray(null); | 
|  | if (parcelables != null) { | 
|  | mRestrictions = new RestrictionEntry[parcelables.length]; | 
|  | for (int i = 0; i < parcelables.length; i++) { | 
|  | mRestrictions[i] = (RestrictionEntry) parcelables[i]; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public int describeContents() { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void writeToParcel(Parcel dest, int flags) { | 
|  | dest.writeInt(mType); | 
|  | dest.writeString(mKey); | 
|  | dest.writeString(mTitle); | 
|  | dest.writeString(mDescription); | 
|  | dest.writeStringArray(mChoiceEntries); | 
|  | dest.writeStringArray(mChoiceValues); | 
|  | dest.writeString(mCurrentValue); | 
|  | dest.writeStringArray(mCurrentValues); | 
|  | dest.writeParcelableArray(mRestrictions, 0); | 
|  | } | 
|  |  | 
|  | public static final @android.annotation.NonNull Creator<RestrictionEntry> CREATOR = new Creator<RestrictionEntry>() { | 
|  | public RestrictionEntry createFromParcel(Parcel source) { | 
|  | return new RestrictionEntry(source); | 
|  | } | 
|  |  | 
|  | public RestrictionEntry[] newArray(int size) { | 
|  | return new RestrictionEntry[size]; | 
|  | } | 
|  | }; | 
|  |  | 
|  | @Override | 
|  | public String toString() { | 
|  | return "RestrictionEntry{" + | 
|  | "mType=" + mType + | 
|  | ", mKey='" + mKey + '\'' + | 
|  | ", mTitle='" + mTitle + '\'' + | 
|  | ", mDescription='" + mDescription + '\'' + | 
|  | ", mChoiceEntries=" + Arrays.toString(mChoiceEntries) + | 
|  | ", mChoiceValues=" + Arrays.toString(mChoiceValues) + | 
|  | ", mCurrentValue='" + mCurrentValue + '\'' + | 
|  | ", mCurrentValues=" + Arrays.toString(mCurrentValues) + | 
|  | ", mRestrictions=" + Arrays.toString(mRestrictions) + | 
|  | '}'; | 
|  | } | 
|  | } |