1 /* 2 * Copyright (C) 2018 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.app; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.graphics.drawable.Icon; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import java.util.Objects; 26 27 /** 28 * Provides an immutable reference to an entity that appears repeatedly on different surfaces of the 29 * platform. For example, this could represent the sender of a message. 30 */ 31 public final class Person implements Parcelable { 32 33 @Nullable private CharSequence mName; 34 @Nullable private Icon mIcon; 35 @Nullable private String mUri; 36 @Nullable private String mKey; 37 private boolean mIsBot; 38 private boolean mIsImportant; 39 Person(Parcel in)40 private Person(Parcel in) { 41 mName = in.readCharSequence(); 42 if (in.readInt() != 0) { 43 mIcon = Icon.CREATOR.createFromParcel(in); 44 } 45 mUri = in.readString(); 46 mKey = in.readString(); 47 mIsImportant = in.readBoolean(); 48 mIsBot = in.readBoolean(); 49 } 50 Person(Builder builder)51 private Person(Builder builder) { 52 mName = builder.mName; 53 mIcon = builder.mIcon; 54 mUri = builder.mUri; 55 mKey = builder.mKey; 56 mIsBot = builder.mIsBot; 57 mIsImportant = builder.mIsImportant; 58 } 59 60 /** Creates and returns a new {@link Builder} initialized with this Person's data. */ toBuilder()61 public Builder toBuilder() { 62 return new Builder(this); 63 } 64 65 /** 66 * @return the uri provided for this person or {@code null} if no Uri was provided. 67 */ 68 @Nullable getUri()69 public String getUri() { 70 return mUri; 71 } 72 73 /** 74 * @return the name provided for this person or {@code null} if no name was provided. 75 */ 76 @Nullable getName()77 public CharSequence getName() { 78 return mName; 79 } 80 81 /** 82 * @return the icon provided for this person or {@code null} if no icon was provided. 83 */ 84 @Nullable getIcon()85 public Icon getIcon() { 86 return mIcon; 87 } 88 89 /** 90 * @return the key provided for this person or {@code null} if no key was provided. 91 */ 92 @Nullable getKey()93 public String getKey() { 94 return mKey; 95 } 96 97 /** 98 * @return whether this Person is a machine. 99 */ isBot()100 public boolean isBot() { 101 return mIsBot; 102 } 103 104 /** 105 * @return whether this Person is important. 106 */ isImportant()107 public boolean isImportant() { 108 return mIsImportant; 109 } 110 111 /** 112 * @return the URI associated with this person, or "name:mName" otherwise 113 * @hide 114 */ resolveToLegacyUri()115 public String resolveToLegacyUri() { 116 if (mUri != null) { 117 return mUri; 118 } 119 if (mName != null) { 120 return "name:" + mName; 121 } 122 return ""; 123 } 124 125 @Override equals(Object obj)126 public boolean equals(Object obj) { 127 if (obj instanceof Person) { 128 final Person other = (Person) obj; 129 return Objects.equals(mName, other.mName) 130 && (mIcon == null ? other.mIcon == null : 131 (other.mIcon != null && mIcon.sameAs(other.mIcon))) 132 && Objects.equals(mUri, other.mUri) 133 && Objects.equals(mKey, other.mKey) 134 && mIsBot == other.mIsBot 135 && mIsImportant == other.mIsImportant; 136 } 137 return false; 138 } 139 140 @Override hashCode()141 public int hashCode() { 142 return Objects.hash(mName, mIcon, mUri, mKey, mIsBot, mIsImportant); 143 } 144 145 @Override describeContents()146 public int describeContents() { 147 return 0; 148 } 149 150 @Override writeToParcel(Parcel dest, @WriteFlags int flags)151 public void writeToParcel(Parcel dest, @WriteFlags int flags) { 152 dest.writeCharSequence(mName); 153 if (mIcon != null) { 154 dest.writeInt(1); 155 mIcon.writeToParcel(dest, 0); 156 } else { 157 dest.writeInt(0); 158 } 159 dest.writeString(mUri); 160 dest.writeString(mKey); 161 dest.writeBoolean(mIsImportant); 162 dest.writeBoolean(mIsBot); 163 } 164 165 /** Builder for the immutable {@link Person} class. */ 166 public static class Builder { 167 @Nullable private CharSequence mName; 168 @Nullable private Icon mIcon; 169 @Nullable private String mUri; 170 @Nullable private String mKey; 171 private boolean mIsBot; 172 private boolean mIsImportant; 173 174 /** Creates a new, empty {@link Builder}. */ Builder()175 public Builder() { 176 } 177 Builder(Person person)178 private Builder(Person person) { 179 mName = person.mName; 180 mIcon = person.mIcon; 181 mUri = person.mUri; 182 mKey = person.mKey; 183 mIsBot = person.mIsBot; 184 mIsImportant = person.mIsImportant; 185 } 186 187 /** 188 * Give this person a name. 189 * 190 * @param name the name of this person. 191 */ 192 @NonNull setName(@ullable CharSequence name)193 public Person.Builder setName(@Nullable CharSequence name) { 194 this.mName = name; 195 return this; 196 } 197 198 /** 199 * Add an icon for this person. 200 * <br /> 201 * The system will prefer this icon over any images that are resolved from the URI. 202 * 203 * @param icon the icon of the person. 204 */ 205 @NonNull setIcon(@ullable Icon icon)206 public Person.Builder setIcon(@Nullable Icon icon) { 207 this.mIcon = icon; 208 return this; 209 } 210 211 /** 212 * Set a URI associated with this person. 213 * 214 * <P> 215 * The person should be specified by the {@code String} representation of a 216 * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}. 217 * </P> 218 * 219 * <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema 220 * URIs. The path part of these URIs must exist in the contacts database, in the 221 * appropriate column, or the reference will be discarded as invalid. Telephone schema 222 * URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}. 223 * </P> 224 * 225 * @param uri a URI for the person. 226 */ 227 @NonNull setUri(@ullable String uri)228 public Person.Builder setUri(@Nullable String uri) { 229 mUri = uri; 230 return this; 231 } 232 233 /** 234 * Add a key to this person in order to uniquely identify it. 235 * This is especially useful if the name doesn't uniquely identify this person or if the 236 * display name is a short handle of the actual name. 237 * 238 * <P>If no key is provided, the name serves as the key for the purpose of 239 * identification.</P> 240 * 241 * @param key the key that uniquely identifies this person. 242 */ 243 @NonNull setKey(@ullable String key)244 public Person.Builder setKey(@Nullable String key) { 245 mKey = key; 246 return this; 247 } 248 249 /** 250 * Sets whether this is an important person. Use this method to denote users who frequently 251 * interact with the user of this device when {@link #setUri(String)} isn't provided with 252 * {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}, and instead with 253 * the {@code mailto:} or {@code tel:} schemas. 254 * 255 * @param isImportant {@code true} if this is an important person, {@code false} otherwise. 256 */ 257 @NonNull setImportant(boolean isImportant)258 public Person.Builder setImportant(boolean isImportant) { 259 mIsImportant = isImportant; 260 return this; 261 } 262 263 /** 264 * Sets whether this person is a machine rather than a human. 265 * 266 * @param isBot {@code true} if this person is a machine, {@code false} otherwise. 267 */ 268 @NonNull setBot(boolean isBot)269 public Person.Builder setBot(boolean isBot) { 270 mIsBot = isBot; 271 return this; 272 } 273 274 /** Creates and returns the {@link Person} this builder represents. */ 275 @NonNull build()276 public Person build() { 277 return new Person(this); 278 } 279 } 280 281 public static final @android.annotation.NonNull Creator<Person> CREATOR = new Creator<Person>() { 282 @Override 283 public Person createFromParcel(Parcel in) { 284 return new Person(in); 285 } 286 287 @Override 288 public Person[] newArray(int size) { 289 return new Person[size]; 290 } 291 }; 292 } 293