blob: a169d4402d6d469003765d3474d2eb88d2e1133f [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.google.android.connecteddevice.notificationmsg.common;
import static com.google.android.connecteddevice.util.SafeLog.logw;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.connecteddevice.notificationmsg.proto.NotificationMsg;
import com.google.android.connecteddevice.notificationmsg.proto.NotificationMsg.ConversationNotification;
import com.google.android.connecteddevice.notificationmsg.proto.NotificationMsg.MessagingStyle;
import com.google.android.connecteddevice.notificationmsg.proto.NotificationMsg.PhoneToCarMessage;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a conversation notification's metadata that is shared between the conversation's
* messages. Note, each {@link ConversationKey} should map to exactly one
* ConversationNotificationInfo object.
*/
public class ConversationNotificationInfo {
private static final String TAG = "CMC.ConvoNotifInfo";
private static int nextNotificationId = 0;
final int notificationId = nextNotificationId++;
private final String deviceName;
private final String deviceId;
// This is always the sender name for SMS Messages from Bluetooth MAP.
private String convoTitle;
private final boolean isGroupConvo;
/** Only used for {@link NotificationMsg} conversations. */
@Nullable private final String notificationKey;
@Nullable private final String appDisplayName;
private final String appPackageName;
@Nullable private final String userDisplayName;
@Nullable private final Icon appIcon;
/** Uris of all members in a MMS Group Conversation. */
@Nullable private final List<String> ccRecipientsUris;
public final ArrayList<MessageKey> messageKeys = new ArrayList<>();
/**
* Creates a ConversationNotificationInfo for a {@link NotificationMsg}. Returns {@code null} if
* the {@link ConversationNotification} is missing required fields.
*/
@Nullable
public static ConversationNotificationInfo createConversationNotificationInfo(
@NonNull String deviceName,
@NonNull String deviceId,
@NonNull ConversationNotification conversation,
@NonNull String notificationKey) {
MessagingStyle messagingStyle = conversation.getMessagingStyle();
if (!Utils.isValidConversationNotification(conversation, /* isShallowCheck= */ true)) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
throw new IllegalArgumentException(
"ConversationNotificationInfo is missing required fields");
} else {
logw(TAG, "ConversationNotificationInfo is missing required fields");
return null;
}
}
byte[] iconBytes = conversation.getAppIcon().toByteArray();
Icon appIcon = Icon.createWithData(iconBytes, 0, iconBytes.length);
return new ConversationNotificationInfo(
deviceName,
deviceId,
messagingStyle.getConvoTitle(),
messagingStyle.getIsGroupConvo(),
notificationKey,
conversation.getMessagingAppDisplayName(),
conversation.getMessagingAppPackageName(),
messagingStyle.getUserDisplayName(),
appIcon,
/* ccUris= */ null);
}
/** Creates a ConversationNotificationInfo for a BluetoothMapClient intent. */
public static ConversationNotificationInfo createConversationNotificationInfo(
Intent intent, String conversationTitle, String appPackageName, @Nullable Icon appIcon) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
return new ConversationNotificationInfo(
device.getName(),
device.getAddress(),
conversationTitle,
Utils.isGroupConversation(intent), /* notificationKey */
null,
/* appDisplayName */ null,
appPackageName, /* userDisplayName */
null,
appIcon,
Utils.getInclusiveRecipientsUrisList(intent));
}
private ConversationNotificationInfo(
@Nullable String deviceName,
String deviceId,
String convoTitle,
boolean isGroupConvo,
@Nullable String notificationKey,
@Nullable String appDisplayName,
String appPackageName,
@Nullable String userDisplayName,
@Nullable Icon appIcon,
@Nullable List<String> ccUris) {
boolean missingDeviceId = (deviceId == null);
boolean missingTitle = (convoTitle == null);
if (missingDeviceId || missingTitle) {
StringBuilder builder = new StringBuilder("Missing required fields:");
if (missingDeviceId) {
builder.append(" deviceId");
}
if (missingTitle) {
builder.append(" convoTitle");
}
throw new IllegalArgumentException(builder.toString());
}
this.deviceName = deviceName;
this.deviceId = deviceId;
this.convoTitle = convoTitle;
this.isGroupConvo = isGroupConvo;
this.notificationKey = notificationKey;
this.appDisplayName = appDisplayName;
this.appPackageName = appPackageName;
this.userDisplayName = userDisplayName;
this.appIcon = appIcon;
this.ccRecipientsUris = ccUris;
}
/** Returns the id that should be used for this object's {@link android.app.Notification}. */
public int getNotificationId() {
return notificationId;
}
/** Returns the friendly name of the device that received the notification. */
public String getDeviceName() {
return deviceName;
}
/** Returns the address of the device that received the notification. */
public String getDeviceId() {
return deviceId;
}
/**
* Returns the conversation title of this notification. If this notification came from MAP
* profile, the title will be the Sender's name.
*/
public String getConvoTitle() {
return convoTitle;
}
/** Update the conversation title. */
public void setConvoTitle(String newTitle) {
convoTitle = newTitle;
}
/** Returns {@code true} if this message is in a group conversation. */
public boolean isGroupConvo() {
return isGroupConvo;
}
/**
* Returns the key if this conversation is based on a {@link ConversationNotification}. Refer to
* {@link PhoneToCarMessage#getNotificationKey()} for more info.
*/
@Nullable
public String getNotificationKey() {
return notificationKey;
}
/**
* Returns the display name of the application that posted this notification if this object is
* based on a {@link ConversationNotification}.
*/
@Nullable
public String getAppDisplayName() {
return appDisplayName;
}
/** Returns the package name of the application that posted this notification. */
public String getAppPackageName() {
return appPackageName;
}
/**
* Returns the User Display Name if this object is based on a @link ConversationNotification}.
* This is needed for {@link android.app.Notification.MessagingStyle}.
*/
@Nullable
public String getUserDisplayName() {
return userDisplayName;
}
/** Returns the app's icon of the application that posted this notification. */
@Nullable
public Icon getAppIcon() {
return appIcon;
}
public MessageKey getLastMessageKey() {
return Iterables.getLast(messageKeys);
}
/**
* Returns the sorted URIs of all the participants of a MMS/SMS/RCS conversation. Returns {@code
* null} if this is based on a {@link NotificationMsg} conversation.
*/
@Nullable
public List<String> getCcRecipientsUris() {
return ccRecipientsUris;
}
}