327 lines
9.7 KiB
Java
327 lines
9.7 KiB
Java
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.app;
|
|
|
|
import android.annotation.NonNull;
|
|
import android.annotation.Nullable;
|
|
import android.graphics.drawable.Icon;
|
|
import android.net.Uri;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
|
|
import java.util.Objects;
|
|
import java.util.function.Consumer;
|
|
|
|
/**
|
|
* Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
|
|
* platform. For example, this could represent the sender of a message.
|
|
*/
|
|
public final class Person implements Parcelable {
|
|
|
|
@Nullable private CharSequence mName;
|
|
@Nullable private Icon mIcon;
|
|
@Nullable private String mUri;
|
|
@Nullable private String mKey;
|
|
private boolean mIsBot;
|
|
private boolean mIsImportant;
|
|
|
|
private Person(Parcel in) {
|
|
mName = in.readCharSequence();
|
|
if (in.readInt() != 0) {
|
|
mIcon = Icon.CREATOR.createFromParcel(in);
|
|
}
|
|
mUri = in.readString();
|
|
mKey = in.readString();
|
|
mIsImportant = in.readBoolean();
|
|
mIsBot = in.readBoolean();
|
|
}
|
|
|
|
private Person(Builder builder) {
|
|
mName = builder.mName;
|
|
mIcon = builder.mIcon;
|
|
mUri = builder.mUri;
|
|
mKey = builder.mKey;
|
|
mIsBot = builder.mIsBot;
|
|
mIsImportant = builder.mIsImportant;
|
|
}
|
|
|
|
/** Creates and returns a new {@link Builder} initialized with this Person's data. */
|
|
public Builder toBuilder() {
|
|
return new Builder(this);
|
|
}
|
|
|
|
/**
|
|
* @return the uri provided for this person or {@code null} if no Uri was provided.
|
|
*/
|
|
@Nullable
|
|
public String getUri() {
|
|
return mUri;
|
|
}
|
|
|
|
/**
|
|
* @return the name provided for this person or {@code null} if no name was provided.
|
|
*/
|
|
@Nullable
|
|
public CharSequence getName() {
|
|
return mName;
|
|
}
|
|
|
|
/**
|
|
* @return the icon provided for this person or {@code null} if no icon was provided.
|
|
*/
|
|
@Nullable
|
|
public Icon getIcon() {
|
|
return mIcon;
|
|
}
|
|
|
|
/**
|
|
* @return the key provided for this person or {@code null} if no key was provided.
|
|
*/
|
|
@Nullable
|
|
public String getKey() {
|
|
return mKey;
|
|
}
|
|
|
|
/**
|
|
* @return whether this Person is a machine.
|
|
*/
|
|
public boolean isBot() {
|
|
return mIsBot;
|
|
}
|
|
|
|
/**
|
|
* @return whether this Person is important.
|
|
*/
|
|
public boolean isImportant() {
|
|
return mIsImportant;
|
|
}
|
|
|
|
/**
|
|
* @return the URI associated with this person, or "name:mName" otherwise
|
|
* @hide
|
|
*/
|
|
public String resolveToLegacyUri() {
|
|
if (mUri != null) {
|
|
return mUri;
|
|
}
|
|
if (mName != null) {
|
|
return "name:" + mName;
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* @return the URI associated with the {@link #getIcon()} for this person, iff the icon exists
|
|
* and is URI based.
|
|
* @hide
|
|
*/
|
|
@Nullable
|
|
public Uri getIconUri() {
|
|
if (mIcon != null && (mIcon.getType() == Icon.TYPE_URI
|
|
|| mIcon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
|
|
return mIcon.getUri();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(@Nullable Object obj) {
|
|
if (obj instanceof Person) {
|
|
final Person other = (Person) obj;
|
|
return Objects.equals(mName, other.mName)
|
|
&& (mIcon == null ? other.mIcon == null :
|
|
(other.mIcon != null && mIcon.sameAs(other.mIcon)))
|
|
&& Objects.equals(mUri, other.mUri)
|
|
&& Objects.equals(mKey, other.mKey)
|
|
&& mIsBot == other.mIsBot
|
|
&& mIsImportant == other.mIsImportant;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(mName, mIcon, mUri, mKey, mIsBot, mIsImportant);
|
|
}
|
|
|
|
@Override
|
|
public int describeContents() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public void writeToParcel(Parcel dest, @WriteFlags int flags) {
|
|
dest.writeCharSequence(mName);
|
|
if (mIcon != null) {
|
|
dest.writeInt(1);
|
|
mIcon.writeToParcel(dest, 0);
|
|
} else {
|
|
dest.writeInt(0);
|
|
}
|
|
dest.writeString(mUri);
|
|
dest.writeString(mKey);
|
|
dest.writeBoolean(mIsImportant);
|
|
dest.writeBoolean(mIsBot);
|
|
}
|
|
|
|
/**
|
|
* Note all {@link Uri} that are referenced internally, with the expectation that Uri permission
|
|
* grants will need to be issued to ensure the recipient of this object is able to render its
|
|
* contents.
|
|
* See b/281044385 for more context and examples about what happens when this isn't done
|
|
* correctly.
|
|
*
|
|
* @hide
|
|
*/
|
|
public void visitUris(@NonNull Consumer<Uri> visitor) {
|
|
visitor.accept(getIconUri());
|
|
if (Flags.visitRiskyUris()) {
|
|
if (mUri != null && !mUri.isEmpty()) {
|
|
visitor.accept(Uri.parse(mUri));
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Builder for the immutable {@link Person} class. */
|
|
public static class Builder {
|
|
@Nullable private CharSequence mName;
|
|
@Nullable private Icon mIcon;
|
|
@Nullable private String mUri;
|
|
@Nullable private String mKey;
|
|
private boolean mIsBot;
|
|
private boolean mIsImportant;
|
|
|
|
/** Creates a new, empty {@link Builder}. */
|
|
public Builder() {
|
|
}
|
|
|
|
private Builder(Person person) {
|
|
mName = person.mName;
|
|
mIcon = person.mIcon;
|
|
mUri = person.mUri;
|
|
mKey = person.mKey;
|
|
mIsBot = person.mIsBot;
|
|
mIsImportant = person.mIsImportant;
|
|
}
|
|
|
|
/**
|
|
* Give this person a name.
|
|
*
|
|
* @param name the name of this person.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setName(@Nullable CharSequence name) {
|
|
this.mName = name;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Add an icon for this person.
|
|
* <br />
|
|
* The system will prefer this icon over any images that are resolved from the URI.
|
|
*
|
|
* @param icon the icon of the person.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setIcon(@Nullable Icon icon) {
|
|
this.mIcon = icon;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set a URI associated with this person.
|
|
*
|
|
* <P>
|
|
* The person should be specified by the {@code String} representation of a
|
|
* {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}.
|
|
* </P>
|
|
*
|
|
* <P>The system will also attempt to resolve {@code mailto:} and {@code tel:} schema
|
|
* URIs. The path part of these URIs must exist in the contacts database, in the
|
|
* appropriate column, or the reference will be discarded as invalid. Telephone schema
|
|
* URIs will be resolved by {@link android.provider.ContactsContract.PhoneLookup}.
|
|
* </P>
|
|
*
|
|
* @param uri a URI for the person.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setUri(@Nullable String uri) {
|
|
mUri = uri;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Add a key to this person in order to uniquely identify it.
|
|
* This is especially useful if the name doesn't uniquely identify this person or if the
|
|
* display name is a short handle of the actual name.
|
|
*
|
|
* <P>If no key is provided, the name serves as the key for the purpose of
|
|
* identification.</P>
|
|
*
|
|
* @param key the key that uniquely identifies this person.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setKey(@Nullable String key) {
|
|
mKey = key;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether this is an important person. Use this method to denote users who frequently
|
|
* interact with the user of this device when {@link #setUri(String)} isn't provided with
|
|
* {@link android.provider.ContactsContract.Contacts#CONTENT_LOOKUP_URI}, and instead with
|
|
* the {@code mailto:} or {@code tel:} schemas.
|
|
*
|
|
* @param isImportant {@code true} if this is an important person, {@code false} otherwise.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setImportant(boolean isImportant) {
|
|
mIsImportant = isImportant;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Sets whether this person is a machine rather than a human.
|
|
*
|
|
* @param isBot {@code true} if this person is a machine, {@code false} otherwise.
|
|
*/
|
|
@NonNull
|
|
public Person.Builder setBot(boolean isBot) {
|
|
mIsBot = isBot;
|
|
return this;
|
|
}
|
|
|
|
/** Creates and returns the {@link Person} this builder represents. */
|
|
@NonNull
|
|
public Person build() {
|
|
return new Person(this);
|
|
}
|
|
}
|
|
|
|
public static final @android.annotation.NonNull Creator<Person> CREATOR = new Creator<Person>() {
|
|
@Override
|
|
public Person createFromParcel(Parcel in) {
|
|
return new Person(in);
|
|
}
|
|
|
|
@Override
|
|
public Person[] newArray(int size) {
|
|
return new Person[size];
|
|
}
|
|
};
|
|
}
|