1 /* 2 * Copyright (C) 2013 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.content; 18 19 import android.annotation.ArrayRes; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.util.Arrays; 24 import java.util.Objects; 25 26 /** 27 * Applications can expose restrictions for a restricted user on a 28 * multiuser device. The administrator can configure these restrictions that will then be 29 * applied to the restricted user. Each RestrictionsEntry is one configurable restriction. 30 * <p/> 31 * Any application that chooses to expose such restrictions does so by implementing a 32 * receiver that handles the {@link Intent#ACTION_GET_RESTRICTION_ENTRIES} action. 33 * The receiver then returns a result bundle that contains an entry called "restrictions", whose 34 * value is an ArrayList<RestrictionsEntry>. 35 */ 36 public class RestrictionEntry implements Parcelable { 37 38 /** 39 * Hidden restriction type. Use this type for information that needs to be transferred 40 * across but shouldn't be presented to the user in the UI. Stores a single String value. 41 */ 42 public static final int TYPE_NULL = 0; 43 44 /** 45 * Restriction of type "bool". Use this for storing a boolean value, typically presented as 46 * a checkbox in the UI. 47 */ 48 public static final int TYPE_BOOLEAN = 1; 49 50 /** 51 * Restriction of type "choice". Use this for storing a string value, typically presented as 52 * a single-select list. Call {@link #setChoiceEntries(String[])} and 53 * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user 54 * and the corresponding values, respectively. 55 */ 56 public static final int TYPE_CHOICE = 2; 57 58 /** 59 * Internal restriction type. Use this for storing a string value, typically presented as 60 * a single-select list. Call {@link #setChoiceEntries(String[])} and 61 * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user 62 * and the corresponding values, respectively. 63 * The presentation could imply that values in lower array indices are included when a 64 * particular value is chosen. 65 * @hide 66 */ 67 public static final int TYPE_CHOICE_LEVEL = 3; 68 69 /** 70 * Restriction of type "multi-select". Use this for presenting a multi-select list where more 71 * than one entry can be selected, such as for choosing specific titles to white-list. 72 * Call {@link #setChoiceEntries(String[])} and 73 * {@link #setChoiceValues(String[])} to set the localized list entries to present to the user 74 * and the corresponding values, respectively. 75 * Use {@link #getAllSelectedStrings()} and {@link #setAllSelectedStrings(String[])} to 76 * manipulate the selections. 77 */ 78 public static final int TYPE_MULTI_SELECT = 4; 79 80 /** 81 * Restriction of type "integer". Use this for storing an integer value. The range of values 82 * is from {@link Integer#MIN_VALUE} to {@link Integer#MAX_VALUE}. 83 */ 84 public static final int TYPE_INTEGER = 5; 85 86 /** 87 * Restriction of type "string". Use this for storing a string value. 88 * @see #setSelectedString 89 * @see #getSelectedString 90 */ 91 public static final int TYPE_STRING = 6; 92 93 /** 94 * Restriction of type "bundle". Use this for storing {@link android.os.Bundle bundles} of 95 * restrictions 96 */ 97 public static final int TYPE_BUNDLE = 7; 98 99 /** 100 * Restriction of type "bundle_array". Use this for storing arrays of 101 * {@link android.os.Bundle bundles} of restrictions 102 */ 103 public static final int TYPE_BUNDLE_ARRAY = 8; 104 105 /** The type of restriction. */ 106 private int mType; 107 108 /** The unique key that identifies the restriction. */ 109 private String mKey; 110 111 /** The user-visible title of the restriction. */ 112 private String mTitle; 113 114 /** The user-visible secondary description of the restriction. */ 115 private String mDescription; 116 117 /** The user-visible set of choices used for single-select and multi-select lists. */ 118 private String[] mChoiceEntries; 119 120 /** The values corresponding to the user-visible choices. The value(s) of this entry will 121 * one or more of these, returned by {@link #getAllSelectedStrings()} and 122 * {@link #getSelectedString()}. 123 */ 124 private String[] mChoiceValues; 125 126 /* The chosen value, whose content depends on the type of the restriction. */ 127 private String mCurrentValue; 128 129 /* List of selected choices in the multi-select case. */ 130 private String[] mCurrentValues; 131 132 /** 133 * List of nested restrictions. Used by {@link #TYPE_BUNDLE bundle} and 134 * {@link #TYPE_BUNDLE_ARRAY bundle_array} restrictions. 135 */ 136 private RestrictionEntry[] mRestrictions; 137 138 /** 139 * Constructor for specifying the type and key, with no initial value; 140 * 141 * @param type the restriction type. 142 * @param key the unique key for this restriction 143 */ RestrictionEntry(int type, String key)144 public RestrictionEntry(int type, String key) { 145 mType = type; 146 mKey = key; 147 } 148 149 /** 150 * Constructor for {@link #TYPE_CHOICE} type. 151 * @param key the unique key for this restriction 152 * @param selectedString the current value 153 */ RestrictionEntry(String key, String selectedString)154 public RestrictionEntry(String key, String selectedString) { 155 this.mKey = key; 156 this.mType = TYPE_CHOICE; 157 this.mCurrentValue = selectedString; 158 } 159 160 /** 161 * Constructor for {@link #TYPE_BOOLEAN} type. 162 * @param key the unique key for this restriction 163 * @param selectedState whether this restriction is selected or not 164 */ RestrictionEntry(String key, boolean selectedState)165 public RestrictionEntry(String key, boolean selectedState) { 166 this.mKey = key; 167 this.mType = TYPE_BOOLEAN; 168 setSelectedState(selectedState); 169 } 170 171 /** 172 * Constructor for {@link #TYPE_MULTI_SELECT} type. 173 * @param key the unique key for this restriction 174 * @param selectedStrings the list of values that are currently selected 175 */ RestrictionEntry(String key, String[] selectedStrings)176 public RestrictionEntry(String key, String[] selectedStrings) { 177 this.mKey = key; 178 this.mType = TYPE_MULTI_SELECT; 179 this.mCurrentValues = selectedStrings; 180 } 181 182 /** 183 * Constructor for {@link #TYPE_INTEGER} type. 184 * @param key the unique key for this restriction 185 * @param selectedInt the integer value of the restriction 186 */ RestrictionEntry(String key, int selectedInt)187 public RestrictionEntry(String key, int selectedInt) { 188 mKey = key; 189 mType = TYPE_INTEGER; 190 setIntValue(selectedInt); 191 } 192 193 /** 194 * Constructor for {@link #TYPE_BUNDLE}/{@link #TYPE_BUNDLE_ARRAY} type. 195 * @param key the unique key for this restriction 196 * @param restrictionEntries array of nested restriction entries. If the entry, being created 197 * represents a {@link #TYPE_BUNDLE_ARRAY bundle-array}, {@code restrictionEntries} array may 198 * only contain elements of type {@link #TYPE_BUNDLE bundle}. 199 * @param isBundleArray true if this restriction represents 200 * {@link #TYPE_BUNDLE_ARRAY bundle-array} type, otherwise the type will be set to 201 * {@link #TYPE_BUNDLE bundle}. 202 */ RestrictionEntry(String key, RestrictionEntry[] restrictionEntries, boolean isBundleArray)203 private RestrictionEntry(String key, RestrictionEntry[] restrictionEntries, 204 boolean isBundleArray) { 205 mKey = key; 206 if (isBundleArray) { 207 mType = TYPE_BUNDLE_ARRAY; 208 if (restrictionEntries != null) { 209 for (RestrictionEntry restriction : restrictionEntries) { 210 if (restriction.getType() != TYPE_BUNDLE) { 211 throw new IllegalArgumentException("bundle_array restriction can only have " 212 + "nested restriction entries of type bundle"); 213 } 214 } 215 } 216 } else { 217 mType = TYPE_BUNDLE; 218 } 219 setRestrictions(restrictionEntries); 220 } 221 222 /** 223 * Creates an entry of type {@link #TYPE_BUNDLE}. 224 * @param key the unique key for this restriction 225 * @param restrictionEntries array of nested restriction entries. 226 * @return the newly created restriction 227 */ createBundleEntry(String key, RestrictionEntry[] restrictionEntries)228 public static RestrictionEntry createBundleEntry(String key, 229 RestrictionEntry[] restrictionEntries) { 230 return new RestrictionEntry(key, restrictionEntries, false); 231 } 232 233 /** 234 * Creates an entry of type {@link #TYPE_BUNDLE_ARRAY}. 235 * @param key the unique key for this restriction 236 * @param restrictionEntries array of nested restriction entries. The array may only contain 237 * elements of type {@link #TYPE_BUNDLE bundle}. 238 * @return the newly created restriction 239 */ createBundleArrayEntry(String key, RestrictionEntry[] restrictionEntries)240 public static RestrictionEntry createBundleArrayEntry(String key, 241 RestrictionEntry[] restrictionEntries) { 242 return new RestrictionEntry(key, restrictionEntries, true); 243 } 244 245 /** 246 * Sets the type for this restriction. 247 * @param type the type for this restriction. 248 */ setType(int type)249 public void setType(int type) { 250 this.mType = type; 251 } 252 253 /** 254 * Returns the type for this restriction. 255 * @return the type for this restriction 256 */ getType()257 public int getType() { 258 return mType; 259 } 260 261 /** 262 * Returns the currently selected string value. 263 * @return the currently selected value, which can be null for types that aren't for holding 264 * single string values. 265 */ getSelectedString()266 public String getSelectedString() { 267 return mCurrentValue; 268 } 269 270 /** 271 * Returns the list of currently selected values. 272 * @return the list of current selections, if type is {@link #TYPE_MULTI_SELECT}, 273 * null otherwise. 274 */ getAllSelectedStrings()275 public String[] getAllSelectedStrings() { 276 return mCurrentValues; 277 } 278 279 /** 280 * Returns the current selected state for an entry of type {@link #TYPE_BOOLEAN}. 281 * @return the current selected state of the entry. 282 */ getSelectedState()283 public boolean getSelectedState() { 284 return Boolean.parseBoolean(mCurrentValue); 285 } 286 287 /** 288 * Returns the value of the entry as an integer when the type is {@link #TYPE_INTEGER}. 289 * @return the integer value of the entry. 290 */ getIntValue()291 public int getIntValue() { 292 return Integer.parseInt(mCurrentValue); 293 } 294 295 /** 296 * Sets the integer value of the entry when the type is {@link #TYPE_INTEGER}. 297 * @param value the integer value to set. 298 */ setIntValue(int value)299 public void setIntValue(int value) { 300 mCurrentValue = Integer.toString(value); 301 } 302 303 /** 304 * Sets the string value to use as the selected value for this restriction. This value will 305 * be persisted by the system for later use by the application. 306 * @param selectedString the string value to select. 307 */ setSelectedString(String selectedString)308 public void setSelectedString(String selectedString) { 309 mCurrentValue = selectedString; 310 } 311 312 /** 313 * Sets the current selected state for an entry of type {@link #TYPE_BOOLEAN}. This value will 314 * be persisted by the system for later use by the application. 315 * @param state the current selected state 316 */ setSelectedState(boolean state)317 public void setSelectedState(boolean state) { 318 mCurrentValue = Boolean.toString(state); 319 } 320 321 /** 322 * Sets the current list of selected values for an entry of type {@link #TYPE_MULTI_SELECT}. 323 * These values will be persisted by the system for later use by the application. 324 * @param allSelectedStrings the current list of selected values. 325 */ setAllSelectedStrings(String[] allSelectedStrings)326 public void setAllSelectedStrings(String[] allSelectedStrings) { 327 mCurrentValues = allSelectedStrings; 328 } 329 330 /** 331 * Sets a list of string values that can be selected by the user. If no user-visible entries 332 * are set by a call to {@link #setChoiceEntries(String[])}, these values will be the ones 333 * shown to the user. Values will be chosen from this list as the user's selection and the 334 * selected values can be retrieved by a call to {@link #getAllSelectedStrings()}, or 335 * {@link #getSelectedString()}, depending on whether it is a multi-select type or choice type. 336 * This method is not relevant for types other than 337 * {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}. 338 * @param choiceValues an array of Strings which will be the selected values for the user's 339 * selections. 340 * @see #getChoiceValues() 341 * @see #getAllSelectedStrings() 342 */ setChoiceValues(String[] choiceValues)343 public void setChoiceValues(String[] choiceValues) { 344 mChoiceValues = choiceValues; 345 } 346 347 /** 348 * Sets a list of string values that can be selected by the user, similar to 349 * {@link #setChoiceValues(String[])}. 350 * @param context the application context for retrieving the resources. 351 * @param stringArrayResId the resource id for a string array containing the possible values. 352 * @see #setChoiceValues(String[]) 353 */ setChoiceValues(Context context, @ArrayRes int stringArrayResId)354 public void setChoiceValues(Context context, @ArrayRes int stringArrayResId) { 355 mChoiceValues = context.getResources().getStringArray(stringArrayResId); 356 } 357 358 /** 359 * Returns array of possible restriction entries that this entry may contain. 360 */ getRestrictions()361 public RestrictionEntry[] getRestrictions() { 362 return mRestrictions; 363 } 364 365 /** 366 * Sets an array of possible restriction entries, that this entry may contain. 367 * <p>This method is only relevant for types {@link #TYPE_BUNDLE} and 368 * {@link #TYPE_BUNDLE_ARRAY} 369 */ setRestrictions(RestrictionEntry[] restrictions)370 public void setRestrictions(RestrictionEntry[] restrictions) { 371 mRestrictions = restrictions; 372 } 373 374 /** 375 * Returns the list of possible string values set earlier. 376 * @return the list of possible values. 377 */ getChoiceValues()378 public String[] getChoiceValues() { 379 return mChoiceValues; 380 } 381 382 /** 383 * Sets a list of strings that will be presented as choices to the user. When the 384 * user selects one or more of these choices, the corresponding value from the possible values 385 * are stored as the selected strings. The size of this array must match the size of the array 386 * set in {@link #setChoiceValues(String[])}. This method is not relevant for types other 387 * than {@link #TYPE_CHOICE}, and {@link #TYPE_MULTI_SELECT}. 388 * @param choiceEntries the list of user-visible choices. 389 * @see #setChoiceValues(String[]) 390 */ setChoiceEntries(String[] choiceEntries)391 public void setChoiceEntries(String[] choiceEntries) { 392 mChoiceEntries = choiceEntries; 393 } 394 395 /** Sets a list of strings that will be presented as choices to the user. This is similar to 396 * {@link #setChoiceEntries(String[])}. 397 * @param context the application context, used for retrieving the resources. 398 * @param stringArrayResId the resource id of a string array containing the possible entries. 399 */ setChoiceEntries(Context context, @ArrayRes int stringArrayResId)400 public void setChoiceEntries(Context context, @ArrayRes int stringArrayResId) { 401 mChoiceEntries = context.getResources().getStringArray(stringArrayResId); 402 } 403 404 /** 405 * Returns the list of strings, set earlier, that will be presented as choices to the user. 406 * @return the list of choices presented to the user. 407 */ getChoiceEntries()408 public String[] getChoiceEntries() { 409 return mChoiceEntries; 410 } 411 412 /** 413 * Returns the provided user-visible description of the entry, if any. 414 * @return the user-visible description, null if none was set earlier. 415 */ getDescription()416 public String getDescription() { 417 return mDescription; 418 } 419 420 /** 421 * Sets the user-visible description of the entry, as a possible sub-text for the title. 422 * You can use this to describe the entry in more detail or to display the current state of 423 * the restriction. 424 * @param description the user-visible description string. 425 */ setDescription(String description)426 public void setDescription(String description) { 427 this.mDescription = description; 428 } 429 430 /** 431 * This is the unique key for the restriction entry. 432 * @return the key for the restriction. 433 */ getKey()434 public String getKey() { 435 return mKey; 436 } 437 438 /** 439 * Returns the user-visible title for the entry, if any. 440 * @return the user-visible title for the entry, null if none was set earlier. 441 */ getTitle()442 public String getTitle() { 443 return mTitle; 444 } 445 446 /** 447 * Sets the user-visible title for the entry. 448 * @param title the user-visible title for the entry. 449 */ setTitle(String title)450 public void setTitle(String title) { 451 this.mTitle = title; 452 } 453 454 @Override equals(Object o)455 public boolean equals(Object o) { 456 if (o == this) return true; 457 if (!(o instanceof RestrictionEntry)) return false; 458 final RestrictionEntry other = (RestrictionEntry) o; 459 if (mType != other.mType || !mKey.equals(other.mKey)) { 460 return false; 461 } 462 if (mCurrentValues == null && other.mCurrentValues == null 463 && mRestrictions == null && other.mRestrictions == null 464 && Objects.equals(mCurrentValue, other.mCurrentValue)) { 465 return true; 466 } 467 if (mCurrentValue == null && other.mCurrentValue == null 468 && mRestrictions == null && other.mRestrictions == null 469 && Arrays.equals(mCurrentValues, other.mCurrentValues)) { 470 return true; 471 } 472 if (mCurrentValue == null && other.mCurrentValue == null 473 && mCurrentValue == null && other.mCurrentValue == null 474 && Arrays.equals(mRestrictions, other.mRestrictions)) { 475 return true; 476 } 477 return false; 478 } 479 480 @Override hashCode()481 public int hashCode() { 482 int result = 17; 483 result = 31 * result + mKey.hashCode(); 484 if (mCurrentValue != null) { 485 result = 31 * result + mCurrentValue.hashCode(); 486 } else if (mCurrentValues != null) { 487 for (String value : mCurrentValues) { 488 if (value != null) { 489 result = 31 * result + value.hashCode(); 490 } 491 } 492 } else if (mRestrictions != null) { 493 result = 31 * result + Arrays.hashCode(mRestrictions); 494 } 495 return result; 496 } 497 RestrictionEntry(Parcel in)498 public RestrictionEntry(Parcel in) { 499 mType = in.readInt(); 500 mKey = in.readString(); 501 mTitle = in.readString(); 502 mDescription = in.readString(); 503 mChoiceEntries = in.readStringArray(); 504 mChoiceValues = in.readStringArray(); 505 mCurrentValue = in.readString(); 506 mCurrentValues = in.readStringArray(); 507 Parcelable[] parcelables = in.readParcelableArray(null); 508 if (parcelables != null) { 509 mRestrictions = new RestrictionEntry[parcelables.length]; 510 for (int i = 0; i < parcelables.length; i++) { 511 mRestrictions[i] = (RestrictionEntry) parcelables[i]; 512 } 513 } 514 } 515 516 @Override describeContents()517 public int describeContents() { 518 return 0; 519 } 520 521 @Override writeToParcel(Parcel dest, int flags)522 public void writeToParcel(Parcel dest, int flags) { 523 dest.writeInt(mType); 524 dest.writeString(mKey); 525 dest.writeString(mTitle); 526 dest.writeString(mDescription); 527 dest.writeStringArray(mChoiceEntries); 528 dest.writeStringArray(mChoiceValues); 529 dest.writeString(mCurrentValue); 530 dest.writeStringArray(mCurrentValues); 531 dest.writeParcelableArray(mRestrictions, 0); 532 } 533 534 public static final @android.annotation.NonNull Creator<RestrictionEntry> CREATOR = new Creator<RestrictionEntry>() { 535 public RestrictionEntry createFromParcel(Parcel source) { 536 return new RestrictionEntry(source); 537 } 538 539 public RestrictionEntry[] newArray(int size) { 540 return new RestrictionEntry[size]; 541 } 542 }; 543 544 @Override toString()545 public String toString() { 546 return "RestrictionEntry{" + 547 "mType=" + mType + 548 ", mKey='" + mKey + '\'' + 549 ", mTitle='" + mTitle + '\'' + 550 ", mDescription='" + mDescription + '\'' + 551 ", mChoiceEntries=" + Arrays.toString(mChoiceEntries) + 552 ", mChoiceValues=" + Arrays.toString(mChoiceValues) + 553 ", mCurrentValue='" + mCurrentValue + '\'' + 554 ", mCurrentValues=" + Arrays.toString(mCurrentValues) + 555 ", mRestrictions=" + Arrays.toString(mRestrictions) + 556 '}'; 557 } 558 } 559