Log conversation id in notification history

So we can clean up the history when a conversation is deleted
and link to the correct notification settings screen

Test: atest
Bug: 149505730
Change-Id: I0784ae80b0fd0a1c00e9b63dfce1104b274df6ce
Exempt-From-Owner-Approval: impatience
This commit is contained in:
Julia Reynolds
2020-02-14 10:21:28 -05:00
parent 747d05fbf0
commit 30965c45ce
5 changed files with 111 additions and 9 deletions

View File

@@ -21,6 +21,7 @@ import android.annotation.UserIdInt;
import android.graphics.drawable.Icon;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -51,6 +52,7 @@ public final class NotificationHistory implements Parcelable {
private String mTitle;
private String mText;
private Icon mIcon;
private String mConversationId;
private HistoricalNotification() {}
@@ -94,6 +96,10 @@ public final class NotificationHistory implements Parcelable {
return mPackage + "|" + mUid + "|" + mPostedTimeMs;
}
public String getConversationId() {
return mConversationId;
}
@Override
public String toString() {
return "HistoricalNotification{" +
@@ -104,6 +110,7 @@ public final class NotificationHistory implements Parcelable {
", mTitle='" + mTitle + '\'' +
", mText='" + mText + '\'' +
", mIcon=" + mIcon +
", mConversationId=" + mConversationId +
'}';
}
@@ -123,6 +130,7 @@ public final class NotificationHistory implements Parcelable {
Objects.equals(getChannelId(), that.getChannelId()) &&
Objects.equals(getTitle(), that.getTitle()) &&
Objects.equals(getText(), that.getText()) &&
Objects.equals(getConversationId(), that.getConversationId()) &&
iconsAreSame;
}
@@ -130,7 +138,7 @@ public final class NotificationHistory implements Parcelable {
public int hashCode() {
return Objects.hash(getPackage(), getChannelName(), getChannelId(), getUid(),
getUserId(),
getPostedTimeMs(), getTitle(), getText(), getIcon());
getPostedTimeMs(), getTitle(), getText(), getIcon(), getConversationId());
}
public static final class Builder {
@@ -143,6 +151,7 @@ public final class NotificationHistory implements Parcelable {
private String mTitle;
private String mText;
private Icon mIcon;
private String mConversationId;
public Builder() {}
@@ -191,6 +200,11 @@ public final class NotificationHistory implements Parcelable {
return this;
}
public Builder setConversationId(String conversationId) {
mConversationId = conversationId;
return this;
}
public HistoricalNotification build() {
HistoricalNotification n = new HistoricalNotification();
n.mPackage = mPackage;
@@ -202,6 +216,7 @@ public final class NotificationHistory implements Parcelable {
n.mTitle = mTitle;
n.mText = mText;
n.mIcon = mIcon;
n.mConversationId = mConversationId;
return n;
}
}
@@ -299,6 +314,9 @@ public final class NotificationHistory implements Parcelable {
mStringsToWrite.add(notification.getPackage());
mStringsToWrite.add(notification.getChannelName());
mStringsToWrite.add(notification.getChannelId());
if (!TextUtils.isEmpty(notification.getConversationId())) {
mStringsToWrite.add(notification.getConversationId());
}
}
}
@@ -423,9 +441,17 @@ public final class NotificationHistory implements Parcelable {
channelIdIndex = -1;
}
final int conversationIdIndex;
if (!TextUtils.isEmpty(notification.getConversationId())) {
conversationIdIndex = findStringIndex(notification.getConversationId());
} else {
conversationIdIndex = -1;
}
p.writeInt(packageIndex);
p.writeInt(channelNameIndex);
p.writeInt(channelIdIndex);
p.writeInt(conversationIdIndex);
p.writeInt(notification.getUid());
p.writeInt(notification.getUserId());
p.writeLong(notification.getPostedTimeMs());
@@ -461,6 +487,13 @@ public final class NotificationHistory implements Parcelable {
notificationOut.setChannelId(null);
}
final int conversationIdIndex = p.readInt();
if (conversationIdIndex >= 0) {
notificationOut.setConversationId(mStringPool[conversationIdIndex]);
} else {
notificationOut.setConversationId(null);
}
notificationOut.setUid(p.readInt());
notificationOut.setUserId(p.readInt());
notificationOut.setPostedTimeMs(p.readLong());

View File

@@ -55,6 +55,11 @@ message NotificationHistoryProto {
// The small icon of the notification
optional Icon icon = 12;
// The conversation id, if any, that this notification belongs to
optional string conversation_id = 13;
// conversation_id_index contains the index + 1 of the conversation id in the string pool
optional int32 conversation_id_index = 14;
// Matches the constants of android.graphics.drawable.Icon
enum ImageTypeEnum {
TYPE_UNKNOWN = 0;

View File

@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.NotificationHistory.HistoricalNotification;
import android.graphics.drawable.Icon;
import android.os.Parcel;
import android.util.Slog;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -48,6 +49,10 @@ public class NotificationHistoryTest {
String expectedText = "text" + index;
Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(),
index);
String conversationId = null;
if (index % 2 == 0) {
conversationId = "convo" + index;
}
return new HistoricalNotification.Builder()
.setPackage(packageName)
@@ -59,6 +64,7 @@ public class NotificationHistoryTest {
.setTitle(expectedTitle)
.setText(expectedText)
.setIcon(expectedIcon)
.setConversationId(conversationId)
.build();
}
@@ -74,6 +80,7 @@ public class NotificationHistoryTest {
String expectedText = "text";
Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(),
android.R.drawable.btn_star);
String expectedConversationId = "convo";
HistoricalNotification n = new HistoricalNotification.Builder()
.setPackage(expectedPackage)
@@ -85,6 +92,7 @@ public class NotificationHistoryTest {
.setTitle(expectedTitle)
.setText(expectedText)
.setIcon(expectedIcon)
.setConversationId(expectedConversationId)
.build();
assertThat(n.getPackage()).isEqualTo(expectedPackage);
@@ -96,6 +104,7 @@ public class NotificationHistoryTest {
assertThat(n.getTitle()).isEqualTo(expectedTitle);
assertThat(n.getText()).isEqualTo(expectedText);
assertThat(expectedIcon.sameAs(n.getIcon())).isTrue();
assertThat(n.getConversationId()).isEqualTo(expectedConversationId);
}
@Test
@@ -153,6 +162,9 @@ public class NotificationHistoryTest {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
expectedStrings.add(n.getConversationId());
}
history.addNotificationToWrite(n);
}
@@ -180,6 +192,9 @@ public class NotificationHistoryTest {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
expectedStrings.add(n.getConversationId());
}
history.addNotificationToWrite(n);
}
@@ -212,6 +227,9 @@ public class NotificationHistoryTest {
postRemoveExpectedStrings.add(n.getPackage());
postRemoveExpectedStrings.add(n.getChannelName());
postRemoveExpectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
postRemoveExpectedStrings.add(n.getConversationId());
}
postRemoveExpectedEntries.add(n);
}
@@ -221,14 +239,14 @@ public class NotificationHistoryTest {
history.poolStringsFromNotifications();
assertThat(history.getNotificationsToWrite().size()).isEqualTo(10);
// 2 package names and 10 * 2 unique channel names and ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(22);
// 2 package names and 10 * 2 unique channel names and ids and 5 conversation ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(27);
history.removeNotificationsFromWrite("pkgOdd");
// 1 package names and 5 * 2 unique channel names and ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(11);
// 1 package names and 5 * 2 unique channel names and ids and 5 conversation ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(16);
assertThat(history.getNotificationsToWrite())
.containsExactlyElementsIn(postRemoveExpectedEntries);
}
@@ -246,6 +264,9 @@ public class NotificationHistoryTest {
postRemoveExpectedStrings.add(n.getPackage());
postRemoveExpectedStrings.add(n.getChannelName());
postRemoveExpectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
postRemoveExpectedStrings.add(n.getConversationId());
}
postRemoveExpectedEntries.add(n);
}
@@ -255,14 +276,14 @@ public class NotificationHistoryTest {
history.poolStringsFromNotifications();
assertThat(history.getNotificationsToWrite().size()).isEqualTo(10);
// 1 package name and 10 unique channel names and ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(21);
// 1 package name and 20 unique channel names and ids and 5 conversation ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(26);
history.removeNotificationFromWrite("pkg", 987654323);
// 1 package names and 9 * 2 unique channel names and ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(19);
// 1 package names and 9 * 2 unique channel names and ids and 4 conversation ids
assertThat(history.getPooledStringsToWrite().length).isEqualTo(23);
assertThat(history.getNotificationsToWrite())
.containsExactlyElementsIn(postRemoveExpectedEntries);
}

View File

@@ -19,6 +19,7 @@ import android.app.NotificationHistory;
import android.app.NotificationHistory.HistoricalNotification;
import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
@@ -141,6 +142,16 @@ final class NotificationHistoryProtoHelper {
loadIcon(parser, notification, pkg);
parser.end(iconToken);
break;
case (int) Notification.CONVERSATION_ID_INDEX:
String conversationId =
stringPool.get(parser.readInt(Notification.CONVERSATION_ID_INDEX) - 1);
notification.setConversationId(conversationId);
break;
case (int) Notification.CONVERSATION_ID:
conversationId = parser.readString(Notification.CONVERSATION_ID);
notification.setConversationId(conversationId);
stringPool.add(conversationId);
break;
case ProtoInputStream.NO_MORE_FIELDS:
return notification.build();
}
@@ -271,6 +282,17 @@ final class NotificationHistoryProtoHelper {
+ ") not found in string cache");
proto.write(Notification.CHANNEL_ID, notification.getChannelId());
}
if (!TextUtils.isEmpty(notification.getConversationId())) {
final int conversationIdIndex = Arrays.binarySearch(
stringPool, notification.getConversationId());
if (conversationIdIndex >= 0) {
proto.write(Notification.CONVERSATION_ID_INDEX, conversationIdIndex + 1);
} else {
Slog.w(TAG, "notification conversation id (" + notification.getConversationId()
+ ") not found in string cache");
proto.write(Notification.CONVERSATION_ID, notification.getConversationId());
}
}
proto.write(Notification.UID, notification.getUid());
proto.write(Notification.USER_ID, notification.getUserId());
proto.write(Notification.POSTED_TIME_MS, notification.getPostedTimeMs());

View File

@@ -21,6 +21,7 @@ import android.app.NotificationHistory;
import android.app.NotificationHistory.HistoricalNotification;
import android.graphics.drawable.Icon;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
@@ -57,6 +58,10 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
String expectedText = "text" + index;
Icon expectedIcon = Icon.createWithResource(InstrumentationRegistry.getContext(),
index);
String conversationId = null;
if (index % 2 == 0) {
conversationId = "convo" + index;
}
return new HistoricalNotification.Builder()
.setPackage(packageName)
@@ -68,6 +73,7 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
.setTitle(expectedTitle)
.setText(expectedText)
.setIcon(expectedIcon)
.setConversationId(conversationId)
.build();
}
@@ -139,6 +145,9 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (!TextUtils.isEmpty(n.getConversationId())) {
expectedStrings.add(n.getConversationId());
}
expectedEntries.add(n);
}
history.addNotificationToWrite(n);
@@ -178,6 +187,9 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (!TextUtils.isEmpty(n.getConversationId())) {
expectedStrings.add(n.getConversationId());
}
expectedEntries.add(n);
}
history.addNotificationToWrite(n);
@@ -227,6 +239,9 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
expectedStrings.add(n.getConversationId());
}
expectedEntries.add(n);
}
history.addNotificationToWrite(n);
@@ -264,6 +279,9 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
expectedStrings.add(n.getConversationId());
}
history.addNotificationToWrite(n);
}
history.poolStringsFromNotifications();
@@ -279,6 +297,9 @@ public class NotificationHistoryProtoHelperTest extends UiServiceTestCase {
expectedStrings.add(n.getPackage());
expectedStrings.add(n.getChannelName());
expectedStrings.add(n.getChannelId());
if (n.getConversationId() != null) {
expectedStrings.add(n.getConversationId());
}
actualHistory.addNotificationToWrite(n);
}
actualHistory.poolStringsFromNotifications();