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