blob: bb97533b3222a97f3e44f32a56379d35fd4f19ad [file] [log] [blame]
/*
* Copyright (C) 2020 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 com.android.server.people.data;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.LocusId;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutInfo.ShortcutFlags;
import android.net.Uri;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* Represents a conversation that is provided by the app based on {@link ShortcutInfo}.
*/
public class ConversationInfo {
private static final int FLAG_VIP = 1;
private static final int FLAG_NOTIFICATION_SILENCED = 1 << 1;
private static final int FLAG_BUBBLED = 1 << 2;
private static final int FLAG_PERSON_IMPORTANT = 1 << 3;
private static final int FLAG_PERSON_BOT = 1 << 4;
private static final int FLAG_CONTACT_STARRED = 1 << 5;
private static final int FLAG_DEMOTED = 1 << 6;
@IntDef(flag = true, prefix = {"FLAG_"}, value = {
FLAG_VIP,
FLAG_NOTIFICATION_SILENCED,
FLAG_BUBBLED,
FLAG_PERSON_IMPORTANT,
FLAG_PERSON_BOT,
FLAG_CONTACT_STARRED,
FLAG_DEMOTED,
})
@Retention(RetentionPolicy.SOURCE)
private @interface ConversationFlags {
}
@NonNull
private String mShortcutId;
@Nullable
private LocusId mLocusId;
@Nullable
private Uri mContactUri;
@Nullable
private String mContactPhoneNumber;
@Nullable
private String mNotificationChannelId;
@ShortcutFlags
private int mShortcutFlags;
@ConversationFlags
private int mConversationFlags;
private ConversationInfo(Builder builder) {
mShortcutId = builder.mShortcutId;
mLocusId = builder.mLocusId;
mContactUri = builder.mContactUri;
mContactPhoneNumber = builder.mContactPhoneNumber;
mNotificationChannelId = builder.mNotificationChannelId;
mShortcutFlags = builder.mShortcutFlags;
mConversationFlags = builder.mConversationFlags;
}
@NonNull
public String getShortcutId() {
return mShortcutId;
}
@Nullable
LocusId getLocusId() {
return mLocusId;
}
/** The URI to look up the entry in the contacts data provider. */
@Nullable
Uri getContactUri() {
return mContactUri;
}
/** The phone number of the associated contact. */
@Nullable
String getContactPhoneNumber() {
return mContactPhoneNumber;
}
/**
* ID of the {@link android.app.NotificationChannel} where the notifications for this
* conversation are posted.
*/
@Nullable
String getNotificationChannelId() {
return mNotificationChannelId;
}
/** Whether the shortcut for this conversation is set long-lived by the app. */
public boolean isShortcutLongLived() {
return hasShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED);
}
/** Whether this conversation is marked as VIP by the user. */
public boolean isVip() {
return hasConversationFlags(FLAG_VIP);
}
/** Whether the notifications for this conversation should be silenced. */
public boolean isNotificationSilenced() {
return hasConversationFlags(FLAG_NOTIFICATION_SILENCED);
}
/** Whether the notifications for this conversation should show in bubbles. */
public boolean isBubbled() {
return hasConversationFlags(FLAG_BUBBLED);
}
/**
* Whether this conversation is demoted by the user. New notifications for the demoted
* conversation will not show in the conversation space.
*/
public boolean isDemoted() {
return hasConversationFlags(FLAG_DEMOTED);
}
/** Whether the associated person is marked as important by the app. */
public boolean isPersonImportant() {
return hasConversationFlags(FLAG_PERSON_IMPORTANT);
}
/** Whether the associated person is marked as a bot by the app. */
public boolean isPersonBot() {
return hasConversationFlags(FLAG_PERSON_BOT);
}
/** Whether the associated contact is marked as starred by the user. */
public boolean isContactStarred() {
return hasConversationFlags(FLAG_CONTACT_STARRED);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof ConversationInfo)) {
return false;
}
ConversationInfo other = (ConversationInfo) obj;
return Objects.equals(mShortcutId, other.mShortcutId)
&& Objects.equals(mLocusId, other.mLocusId)
&& Objects.equals(mContactUri, other.mContactUri)
&& Objects.equals(mContactPhoneNumber, other.mContactPhoneNumber)
&& Objects.equals(mNotificationChannelId, other.mNotificationChannelId)
&& mShortcutFlags == other.mShortcutFlags
&& mConversationFlags == other.mConversationFlags;
}
@Override
public int hashCode() {
return Objects.hash(mShortcutId, mLocusId, mContactUri, mContactPhoneNumber,
mNotificationChannelId, mShortcutFlags, mConversationFlags);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("ConversationInfo {");
sb.append("shortcutId=").append(mShortcutId);
sb.append(", locusId=").append(mLocusId);
sb.append(", contactUri=").append(mContactUri);
sb.append(", phoneNumber=").append(mContactPhoneNumber);
sb.append(", notificationChannelId=").append(mNotificationChannelId);
sb.append(", shortcutFlags=0x").append(Integer.toHexString(mShortcutFlags));
sb.append(" [");
if (isShortcutLongLived()) {
sb.append("Liv");
}
sb.append("]");
sb.append(", conversationFlags=0x").append(Integer.toHexString(mConversationFlags));
sb.append(" [");
if (isVip()) {
sb.append("Vip");
}
if (isNotificationSilenced()) {
sb.append("Sil");
}
if (isBubbled()) {
sb.append("Bub");
}
if (isDemoted()) {
sb.append("Dem");
}
if (isPersonImportant()) {
sb.append("Imp");
}
if (isPersonBot()) {
sb.append("Bot");
}
if (isContactStarred()) {
sb.append("Sta");
}
sb.append("]}");
return sb.toString();
}
private boolean hasShortcutFlags(@ShortcutFlags int flags) {
return (mShortcutFlags & flags) == flags;
}
private boolean hasConversationFlags(@ConversationFlags int flags) {
return (mConversationFlags & flags) == flags;
}
/**
* Builder class for {@link ConversationInfo} objects.
*/
static class Builder {
private String mShortcutId;
@Nullable
private LocusId mLocusId;
@Nullable
private Uri mContactUri;
@Nullable
private String mContactPhoneNumber;
@Nullable
private String mNotificationChannelId;
@ShortcutFlags
private int mShortcutFlags;
@ConversationFlags
private int mConversationFlags;
Builder() {
}
Builder(@NonNull ConversationInfo conversationInfo) {
if (mShortcutId == null) {
mShortcutId = conversationInfo.mShortcutId;
} else {
Preconditions.checkArgument(mShortcutId.equals(conversationInfo.mShortcutId));
}
mLocusId = conversationInfo.mLocusId;
mContactUri = conversationInfo.mContactUri;
mContactPhoneNumber = conversationInfo.mContactPhoneNumber;
mNotificationChannelId = conversationInfo.mNotificationChannelId;
mShortcutFlags = conversationInfo.mShortcutFlags;
mConversationFlags = conversationInfo.mConversationFlags;
}
Builder setShortcutId(@NonNull String shortcutId) {
mShortcutId = shortcutId;
return this;
}
Builder setLocusId(LocusId locusId) {
mLocusId = locusId;
return this;
}
Builder setContactUri(Uri contactUri) {
mContactUri = contactUri;
return this;
}
Builder setContactPhoneNumber(String phoneNumber) {
mContactPhoneNumber = phoneNumber;
return this;
}
Builder setNotificationChannelId(String notificationChannelId) {
mNotificationChannelId = notificationChannelId;
return this;
}
Builder setShortcutFlags(@ShortcutFlags int shortcutFlags) {
mShortcutFlags = shortcutFlags;
return this;
}
Builder setConversationFlags(@ConversationFlags int conversationFlags) {
mConversationFlags = conversationFlags;
return this;
}
Builder setVip(boolean value) {
return setConversationFlag(FLAG_VIP, value);
}
Builder setNotificationSilenced(boolean value) {
return setConversationFlag(FLAG_NOTIFICATION_SILENCED, value);
}
Builder setBubbled(boolean value) {
return setConversationFlag(FLAG_BUBBLED, value);
}
Builder setDemoted(boolean value) {
return setConversationFlag(FLAG_DEMOTED, value);
}
Builder setPersonImportant(boolean value) {
return setConversationFlag(FLAG_PERSON_IMPORTANT, value);
}
Builder setPersonBot(boolean value) {
return setConversationFlag(FLAG_PERSON_BOT, value);
}
Builder setContactStarred(boolean value) {
return setConversationFlag(FLAG_CONTACT_STARRED, value);
}
private Builder setConversationFlag(@ConversationFlags int flags, boolean value) {
if (value) {
return addConversationFlags(flags);
} else {
return removeConversationFlags(flags);
}
}
private Builder addConversationFlags(@ConversationFlags int flags) {
mConversationFlags |= flags;
return this;
}
private Builder removeConversationFlags(@ConversationFlags int flags) {
mConversationFlags &= ~flags;
return this;
}
ConversationInfo build() {
Objects.requireNonNull(mShortcutId);
return new ConversationInfo(this);
}
}
}