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