1 /* 2 * Copyright (C) 2017 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.view.autofill; 18 19 import static android.view.View.AUTOFILL_TYPE_DATE; 20 import static android.view.View.AUTOFILL_TYPE_LIST; 21 import static android.view.View.AUTOFILL_TYPE_TEXT; 22 import static android.view.View.AUTOFILL_TYPE_TOGGLE; 23 import static android.view.autofill.Helper.sDebug; 24 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.text.TextUtils; 30 import android.view.View; 31 32 import com.android.internal.util.Preconditions; 33 34 import java.util.Objects; 35 36 /** 37 * Abstracts how a {@link View} can be autofilled by an 38 * {@link android.service.autofill.AutofillService}. 39 * 40 * <p>Each {@link AutofillValue} is associated with a {@code type}, as defined by 41 * {@link View#getAutofillType()}. 42 */ 43 public final class AutofillValue implements Parcelable { 44 private final @View.AutofillType int mType; 45 private final @NonNull Object mValue; 46 AutofillValue(@iew.AutofillType int type, @NonNull Object value)47 private AutofillValue(@View.AutofillType int type, @NonNull Object value) { 48 mType = type; 49 mValue = value; 50 } 51 52 /** 53 * Gets the value to autofill a text field. 54 * 55 * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.</p> 56 * 57 * @throws IllegalStateException if the value is not a text value 58 */ getTextValue()59 @NonNull public CharSequence getTextValue() { 60 Preconditions.checkState(isText(), "value must be a text value, not type=" + mType); 61 return (CharSequence) mValue; 62 } 63 64 /** 65 * Checks is this is a text value. 66 * 67 * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info.</p> 68 */ isText()69 public boolean isText() { 70 return mType == AUTOFILL_TYPE_TEXT; 71 } 72 73 /** 74 * Gets the value to autofill a toggable field. 75 * 76 * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.</p> 77 * 78 * @throws IllegalStateException if the value is not a toggle value 79 */ getToggleValue()80 public boolean getToggleValue() { 81 Preconditions.checkState(isToggle(), "value must be a toggle value, not type=" + mType); 82 return (Boolean) mValue; 83 } 84 85 /** 86 * Checks is this is a toggle value. 87 * 88 * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info.</p> 89 */ isToggle()90 public boolean isToggle() { 91 return mType == AUTOFILL_TYPE_TOGGLE; 92 } 93 94 /** 95 * Gets the value to autofill a selection list field. 96 * 97 * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.</p> 98 * 99 * @throws IllegalStateException if the value is not a list value 100 */ getListValue()101 public int getListValue() { 102 Preconditions.checkState(isList(), "value must be a list value, not type=" + mType); 103 return (Integer) mValue; 104 } 105 106 /** 107 * Checks is this is a list value. 108 * 109 * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info.</p> 110 */ isList()111 public boolean isList() { 112 return mType == AUTOFILL_TYPE_LIST; 113 } 114 115 /** 116 * Gets the value to autofill a date field. 117 * 118 * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.</p> 119 * 120 * @throws IllegalStateException if the value is not a date value 121 */ getDateValue()122 public long getDateValue() { 123 Preconditions.checkState(isDate(), "value must be a date value, not type=" + mType); 124 return (Long) mValue; 125 } 126 127 /** 128 * Checks is this is a date value. 129 * 130 * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info.</p> 131 */ isDate()132 public boolean isDate() { 133 return mType == AUTOFILL_TYPE_DATE; 134 } 135 136 /** 137 * Used to define whether a field is empty so it's not sent to service on save. 138 * 139 * <p>Only applies to some types, like text. 140 * 141 * @hide 142 */ isEmpty()143 public boolean isEmpty() { 144 return isText() && ((CharSequence) mValue).length() == 0; 145 } 146 147 ///////////////////////////////////// 148 // Object "contract" methods. // 149 ///////////////////////////////////// 150 151 @Override hashCode()152 public int hashCode() { 153 return mType + mValue.hashCode(); 154 } 155 156 @Override equals(Object obj)157 public boolean equals(Object obj) { 158 if (this == obj) return true; 159 if (obj == null) return false; 160 if (getClass() != obj.getClass()) return false; 161 final AutofillValue other = (AutofillValue) obj; 162 163 if (mType != other.mType) return false; 164 165 if (isText()) { 166 return mValue.toString().equals(other.mValue.toString()); 167 } else { 168 return Objects.equals(mValue, other.mValue); 169 } 170 } 171 172 @Override toString()173 public String toString() { 174 if (!sDebug) return super.toString(); 175 176 final StringBuilder string = new StringBuilder() 177 .append("[type=").append(mType) 178 .append(", value="); 179 if (isText()) { 180 Helper.appendRedacted(string, (CharSequence) mValue); 181 } else { 182 string.append(mValue); 183 } 184 return string.append(']').toString(); 185 } 186 187 ///////////////////////////////////// 188 // Parcelable "contract" methods. // 189 ///////////////////////////////////// 190 191 @Override describeContents()192 public int describeContents() { 193 return 0; 194 } 195 196 @Override writeToParcel(Parcel parcel, int flags)197 public void writeToParcel(Parcel parcel, int flags) { 198 parcel.writeInt(mType); 199 200 switch (mType) { 201 case AUTOFILL_TYPE_TEXT: 202 parcel.writeCharSequence((CharSequence) mValue); 203 break; 204 case AUTOFILL_TYPE_TOGGLE: 205 parcel.writeInt((Boolean) mValue ? 1 : 0); 206 break; 207 case AUTOFILL_TYPE_LIST: 208 parcel.writeInt((Integer) mValue); 209 break; 210 case AUTOFILL_TYPE_DATE: 211 parcel.writeLong((Long) mValue); 212 break; 213 } 214 } 215 AutofillValue(@onNull Parcel parcel)216 private AutofillValue(@NonNull Parcel parcel) { 217 mType = parcel.readInt(); 218 219 switch (mType) { 220 case AUTOFILL_TYPE_TEXT: 221 mValue = parcel.readCharSequence(); 222 break; 223 case AUTOFILL_TYPE_TOGGLE: 224 int rawValue = parcel.readInt(); 225 mValue = rawValue != 0; 226 break; 227 case AUTOFILL_TYPE_LIST: 228 mValue = parcel.readInt(); 229 break; 230 case AUTOFILL_TYPE_DATE: 231 mValue = parcel.readLong(); 232 break; 233 default: 234 throw new IllegalArgumentException("type=" + mType + " not valid"); 235 } 236 } 237 238 public static final Parcelable.Creator<AutofillValue> CREATOR = 239 new Parcelable.Creator<AutofillValue>() { 240 @Override 241 public AutofillValue createFromParcel(Parcel source) { 242 return new AutofillValue(source); 243 } 244 245 @Override 246 public AutofillValue[] newArray(int size) { 247 return new AutofillValue[size]; 248 } 249 }; 250 251 //////////////////// 252 // Factory methods // 253 //////////////////// 254 255 /** 256 * Creates a new {@link AutofillValue} to autofill a {@link View} representing a text field. 257 * 258 * <p>See {@link View#AUTOFILL_TYPE_TEXT} for more info. 259 */ forText(@ullable CharSequence value)260 public static AutofillValue forText(@Nullable CharSequence value) { 261 return value == null ? null : new AutofillValue(AUTOFILL_TYPE_TEXT, 262 TextUtils.trimNoCopySpans(value)); 263 } 264 265 /** 266 * Creates a new {@link AutofillValue} to autofill a {@link View} representing a toggable 267 * field. 268 * 269 * <p>See {@link View#AUTOFILL_TYPE_TOGGLE} for more info. 270 */ forToggle(boolean value)271 public static AutofillValue forToggle(boolean value) { 272 return new AutofillValue(AUTOFILL_TYPE_TOGGLE, value); 273 } 274 275 /** 276 * Creates a new {@link AutofillValue} to autofill a {@link View} representing a selection 277 * list. 278 * 279 * <p>See {@link View#AUTOFILL_TYPE_LIST} for more info. 280 */ forList(int value)281 public static AutofillValue forList(int value) { 282 return new AutofillValue(AUTOFILL_TYPE_LIST, value); 283 } 284 285 /** 286 * Creates a new {@link AutofillValue} to autofill a {@link View} representing a date. 287 * 288 * <p>See {@link View#AUTOFILL_TYPE_DATE} for more info. 289 */ forDate(long value)290 public static AutofillValue forDate(long value) { 291 return new AutofillValue(AUTOFILL_TYPE_DATE, value); 292 } 293 } 294