629 lines
21 KiB
Java
629 lines
21 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2019 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.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;
|
||
|
import java.util.Collections;
|
||
|
import java.util.HashSet;
|
||
|
import java.util.List;
|
||
|
import java.util.Objects;
|
||
|
import java.util.Set;
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public final class NotificationHistory implements Parcelable {
|
||
|
|
||
|
/**
|
||
|
* A historical notification. Any new fields added here should also be added to
|
||
|
* {@link #readNotificationFromParcel} and
|
||
|
* {@link #writeNotificationToParcel(HistoricalNotification, Parcel, int)}.
|
||
|
*/
|
||
|
public static final class HistoricalNotification {
|
||
|
private String mPackage;
|
||
|
private String mChannelName;
|
||
|
private String mChannelId;
|
||
|
private int mUid;
|
||
|
private @UserIdInt int mUserId;
|
||
|
private long mPostedTimeMs;
|
||
|
private String mTitle;
|
||
|
private String mText;
|
||
|
private Icon mIcon;
|
||
|
private String mConversationId;
|
||
|
|
||
|
private HistoricalNotification() {}
|
||
|
|
||
|
public String getPackage() {
|
||
|
return mPackage;
|
||
|
}
|
||
|
|
||
|
public String getChannelName() {
|
||
|
return mChannelName;
|
||
|
}
|
||
|
|
||
|
public String getChannelId() {
|
||
|
return mChannelId;
|
||
|
}
|
||
|
|
||
|
public int getUid() {
|
||
|
return mUid;
|
||
|
}
|
||
|
|
||
|
public int getUserId() {
|
||
|
return mUserId;
|
||
|
}
|
||
|
|
||
|
public long getPostedTimeMs() {
|
||
|
return mPostedTimeMs;
|
||
|
}
|
||
|
|
||
|
public String getTitle() {
|
||
|
return mTitle;
|
||
|
}
|
||
|
|
||
|
public String getText() {
|
||
|
return mText;
|
||
|
}
|
||
|
|
||
|
public Icon getIcon() {
|
||
|
return mIcon;
|
||
|
}
|
||
|
|
||
|
public String getKey() {
|
||
|
return mPackage + "|" + mUid + "|" + mPostedTimeMs;
|
||
|
}
|
||
|
|
||
|
public String getConversationId() {
|
||
|
return mConversationId;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
return "HistoricalNotification{" +
|
||
|
"key='" + getKey() + '\'' +
|
||
|
", mChannelName='" + mChannelName + '\'' +
|
||
|
", mChannelId='" + mChannelId + '\'' +
|
||
|
", mUserId=" + mUserId +
|
||
|
", mUid=" + mUid +
|
||
|
", mTitle='" + mTitle + '\'' +
|
||
|
", mText='" + mText + '\'' +
|
||
|
", mIcon=" + mIcon +
|
||
|
", mPostedTimeMs=" + mPostedTimeMs +
|
||
|
", mConversationId=" + mConversationId +
|
||
|
'}';
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
if (this == o) return true;
|
||
|
if (o == null || getClass() != o.getClass()) return false;
|
||
|
HistoricalNotification that = (HistoricalNotification) o;
|
||
|
boolean iconsAreSame = getIcon() == null && that.getIcon() == null
|
||
|
|| (getIcon() != null && that.getIcon() != null
|
||
|
&& getIcon().sameAs(that.getIcon()));
|
||
|
return getUid() == that.getUid() &&
|
||
|
getUserId() == that.getUserId() &&
|
||
|
getPostedTimeMs() == that.getPostedTimeMs() &&
|
||
|
Objects.equals(getPackage(), that.getPackage()) &&
|
||
|
Objects.equals(getChannelName(), that.getChannelName()) &&
|
||
|
Objects.equals(getChannelId(), that.getChannelId()) &&
|
||
|
Objects.equals(getTitle(), that.getTitle()) &&
|
||
|
Objects.equals(getText(), that.getText()) &&
|
||
|
Objects.equals(getConversationId(), that.getConversationId()) &&
|
||
|
iconsAreSame;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(getPackage(), getChannelName(), getChannelId(), getUid(),
|
||
|
getUserId(),
|
||
|
getPostedTimeMs(), getTitle(), getText(), getIcon(), getConversationId());
|
||
|
}
|
||
|
|
||
|
public static final class Builder {
|
||
|
private String mPackage;
|
||
|
private String mChannelName;
|
||
|
private String mChannelId;
|
||
|
private int mUid;
|
||
|
private @UserIdInt int mUserId;
|
||
|
private long mPostedTimeMs;
|
||
|
private String mTitle;
|
||
|
private String mText;
|
||
|
private Icon mIcon;
|
||
|
private String mConversationId;
|
||
|
|
||
|
public Builder() {}
|
||
|
|
||
|
public Builder setPackage(String aPackage) {
|
||
|
mPackage = aPackage;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setChannelName(String channelName) {
|
||
|
mChannelName = channelName;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setChannelId(String channelId) {
|
||
|
mChannelId = channelId;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setUid(int uid) {
|
||
|
mUid = uid;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setUserId(int userId) {
|
||
|
mUserId = userId;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setPostedTimeMs(long postedTimeMs) {
|
||
|
mPostedTimeMs = postedTimeMs;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setTitle(String title) {
|
||
|
mTitle = title;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setText(String text) {
|
||
|
mText = text;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setIcon(Icon icon) {
|
||
|
mIcon = icon;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Builder setConversationId(String conversationId) {
|
||
|
mConversationId = conversationId;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public HistoricalNotification build() {
|
||
|
HistoricalNotification n = new HistoricalNotification();
|
||
|
n.mPackage = mPackage;
|
||
|
n.mChannelName = mChannelName;
|
||
|
n.mChannelId = mChannelId;
|
||
|
n.mUid = mUid;
|
||
|
n.mUserId = mUserId;
|
||
|
n.mPostedTimeMs = mPostedTimeMs;
|
||
|
n.mTitle = mTitle;
|
||
|
n.mText = mText;
|
||
|
n.mIcon = mIcon;
|
||
|
n.mConversationId = mConversationId;
|
||
|
return n;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Only used when creating the resulting history. Not used for reading/unparceling.
|
||
|
private List<HistoricalNotification> mNotificationsToWrite = new ArrayList<>();
|
||
|
// ditto
|
||
|
private Set<String> mStringsToWrite = new HashSet<>();
|
||
|
|
||
|
// Mostly used for reading/unparceling events.
|
||
|
private Parcel mParcel = null;
|
||
|
private int mHistoryCount;
|
||
|
private int mIndex = 0;
|
||
|
|
||
|
// Sorted array of commonly used strings to shrink the size of the parcel. populated from
|
||
|
// mStringsToWrite on write and the parcel on read.
|
||
|
private String[] mStringPool;
|
||
|
|
||
|
/**
|
||
|
* Construct the iterator from a parcel.
|
||
|
*/
|
||
|
private NotificationHistory(Parcel in) {
|
||
|
byte[] bytes = in.readBlob();
|
||
|
Parcel data = Parcel.obtain();
|
||
|
data.unmarshall(bytes, 0, bytes.length);
|
||
|
data.setDataPosition(0);
|
||
|
mHistoryCount = data.readInt();
|
||
|
mIndex = data.readInt();
|
||
|
if (mHistoryCount > 0) {
|
||
|
mStringPool = data.createStringArray();
|
||
|
|
||
|
final int listByteLength = data.readInt();
|
||
|
final int positionInParcel = data.readInt();
|
||
|
mParcel = Parcel.obtain();
|
||
|
mParcel.setDataPosition(0);
|
||
|
mParcel.appendFrom(data, data.dataPosition(), listByteLength);
|
||
|
mParcel.setDataSize(mParcel.dataPosition());
|
||
|
mParcel.setDataPosition(positionInParcel);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Create an empty iterator.
|
||
|
*/
|
||
|
public NotificationHistory() {
|
||
|
mHistoryCount = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns whether or not there are more events to read using {@link #getNextNotification()}.
|
||
|
*
|
||
|
* @return true if there are more events, false otherwise.
|
||
|
*/
|
||
|
public boolean hasNextNotification() {
|
||
|
return mIndex < mHistoryCount;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve the next {@link HistoricalNotification} from the collection and put the
|
||
|
* resulting data into {@code notificationOut}.
|
||
|
*
|
||
|
* @return The next {@link HistoricalNotification} or null if there are no more notifications.
|
||
|
*/
|
||
|
public @Nullable HistoricalNotification getNextNotification() {
|
||
|
if (!hasNextNotification()) {
|
||
|
return null;
|
||
|
}
|
||
|
HistoricalNotification n = readNotificationFromParcel(mParcel);
|
||
|
mIndex++;
|
||
|
if (!hasNextNotification()) {
|
||
|
mParcel.recycle();
|
||
|
mParcel = null;
|
||
|
}
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adds all of the pooled strings that have been read from disk
|
||
|
*/
|
||
|
public void addPooledStrings(@NonNull List<String> strings) {
|
||
|
mStringsToWrite.addAll(strings);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Builds the pooled strings from pending notifications. Useful if the pooled strings on
|
||
|
* disk contains strings that aren't relevant to the notifications in our collection.
|
||
|
*/
|
||
|
public void poolStringsFromNotifications() {
|
||
|
mStringsToWrite.clear();
|
||
|
for (int i = 0; i < mNotificationsToWrite.size(); i++) {
|
||
|
final HistoricalNotification notification = mNotificationsToWrite.get(i);
|
||
|
mStringsToWrite.add(notification.getPackage());
|
||
|
mStringsToWrite.add(notification.getChannelName());
|
||
|
mStringsToWrite.add(notification.getChannelId());
|
||
|
if (!TextUtils.isEmpty(notification.getConversationId())) {
|
||
|
mStringsToWrite.add(notification.getConversationId());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used when populating a history from disk; adds an historical notification.
|
||
|
*/
|
||
|
public void addNotificationToWrite(@NonNull HistoricalNotification notification) {
|
||
|
if (notification == null) {
|
||
|
return;
|
||
|
}
|
||
|
mNotificationsToWrite.add(notification);
|
||
|
mHistoryCount++;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used when populating a history from disk; adds an historical notification.
|
||
|
*/
|
||
|
public void addNewNotificationToWrite(@NonNull HistoricalNotification notification) {
|
||
|
if (notification == null) {
|
||
|
return;
|
||
|
}
|
||
|
mNotificationsToWrite.add(0, notification);
|
||
|
mHistoryCount++;
|
||
|
}
|
||
|
|
||
|
public void addNotificationsToWrite(@NonNull NotificationHistory notificationHistory) {
|
||
|
for (HistoricalNotification hn : notificationHistory.getNotificationsToWrite()) {
|
||
|
addNotificationToWrite(hn);
|
||
|
}
|
||
|
Collections.sort(mNotificationsToWrite,
|
||
|
(o1, o2) -> -1 * Long.compare(o1.getPostedTimeMs(), o2.getPostedTimeMs()));
|
||
|
poolStringsFromNotifications();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes a package's historical notifications and regenerates the string pool
|
||
|
*/
|
||
|
public void removeNotificationsFromWrite(String packageName) {
|
||
|
for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
|
||
|
if (packageName.equals(mNotificationsToWrite.get(i).getPackage())) {
|
||
|
mNotificationsToWrite.remove(i);
|
||
|
}
|
||
|
}
|
||
|
poolStringsFromNotifications();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes an individual historical notification and regenerates the string pool
|
||
|
*/
|
||
|
public boolean removeNotificationFromWrite(String packageName, long postedTime) {
|
||
|
boolean removed = false;
|
||
|
for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
|
||
|
HistoricalNotification hn = mNotificationsToWrite.get(i);
|
||
|
if (packageName.equals(hn.getPackage())
|
||
|
&& postedTime == hn.getPostedTimeMs()) {
|
||
|
removed = true;
|
||
|
mNotificationsToWrite.remove(i);
|
||
|
}
|
||
|
}
|
||
|
if (removed) {
|
||
|
poolStringsFromNotifications();
|
||
|
}
|
||
|
|
||
|
return removed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes all notifications from a conversation and regenerates the string pool
|
||
|
*/
|
||
|
public boolean removeConversationsFromWrite(String packageName, Set<String> conversationIds) {
|
||
|
boolean removed = false;
|
||
|
for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
|
||
|
HistoricalNotification hn = mNotificationsToWrite.get(i);
|
||
|
if (packageName.equals(hn.getPackage())
|
||
|
&& hn.getConversationId() != null
|
||
|
&& conversationIds.contains(hn.getConversationId())) {
|
||
|
removed = true;
|
||
|
mNotificationsToWrite.remove(i);
|
||
|
}
|
||
|
}
|
||
|
if (removed) {
|
||
|
poolStringsFromNotifications();
|
||
|
}
|
||
|
|
||
|
return removed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Removes all notifications from a channel and regenerates the string pool
|
||
|
*/
|
||
|
public boolean removeChannelFromWrite(String packageName, String channelId) {
|
||
|
boolean removed = false;
|
||
|
for (int i = mNotificationsToWrite.size() - 1; i >= 0; i--) {
|
||
|
HistoricalNotification hn = mNotificationsToWrite.get(i);
|
||
|
if (packageName.equals(hn.getPackage())
|
||
|
&& Objects.equals(channelId, hn.getChannelId())) {
|
||
|
removed = true;
|
||
|
mNotificationsToWrite.remove(i);
|
||
|
}
|
||
|
}
|
||
|
if (removed) {
|
||
|
poolStringsFromNotifications();
|
||
|
}
|
||
|
|
||
|
return removed;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets pooled strings in order to write them to disk
|
||
|
*/
|
||
|
public @NonNull String[] getPooledStringsToWrite() {
|
||
|
String[] stringsToWrite = mStringsToWrite.toArray(new String[]{});
|
||
|
Arrays.sort(stringsToWrite);
|
||
|
return stringsToWrite;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the historical notifications in order to write them to disk
|
||
|
*/
|
||
|
public @NonNull List<HistoricalNotification> getNotificationsToWrite() {
|
||
|
return mNotificationsToWrite;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the number of notifications in the collection
|
||
|
*/
|
||
|
public int getHistoryCount() {
|
||
|
return mHistoryCount;
|
||
|
}
|
||
|
|
||
|
private int findStringIndex(String str) {
|
||
|
final int index = Arrays.binarySearch(mStringPool, str);
|
||
|
if (index < 0) {
|
||
|
throw new IllegalStateException("String '" + str + "' is not in the string pool");
|
||
|
}
|
||
|
return index;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Writes a single notification to the parcel. Modify this when updating member variables of
|
||
|
* {@link HistoricalNotification}.
|
||
|
*/
|
||
|
private void writeNotificationToParcel(HistoricalNotification notification, Parcel p,
|
||
|
int flags) {
|
||
|
final int packageIndex;
|
||
|
if (notification.mPackage != null) {
|
||
|
packageIndex = findStringIndex(notification.mPackage);
|
||
|
} else {
|
||
|
packageIndex = -1;
|
||
|
}
|
||
|
|
||
|
final int channelNameIndex;
|
||
|
if (notification.getChannelName() != null) {
|
||
|
channelNameIndex = findStringIndex(notification.getChannelName());
|
||
|
} else {
|
||
|
channelNameIndex = -1;
|
||
|
}
|
||
|
|
||
|
final int channelIdIndex;
|
||
|
if (notification.getChannelId() != null) {
|
||
|
channelIdIndex = findStringIndex(notification.getChannelId());
|
||
|
} else {
|
||
|
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());
|
||
|
p.writeString(notification.getTitle());
|
||
|
p.writeString(notification.getText());
|
||
|
p.writeBoolean(false);
|
||
|
// The current design does not display icons, so don't bother adding them to the parcel
|
||
|
//if (notification.getIcon() != null) {
|
||
|
// notification.getIcon().writeToParcel(p, flags);
|
||
|
//}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reads a single notification from the parcel. Modify this when updating member variables of
|
||
|
* {@link HistoricalNotification}.
|
||
|
*/
|
||
|
private HistoricalNotification readNotificationFromParcel(Parcel p) {
|
||
|
HistoricalNotification.Builder notificationOut = new HistoricalNotification.Builder();
|
||
|
final int packageIndex = p.readInt();
|
||
|
if (packageIndex >= 0) {
|
||
|
notificationOut.mPackage = mStringPool[packageIndex];
|
||
|
} else {
|
||
|
notificationOut.mPackage = null;
|
||
|
}
|
||
|
|
||
|
final int channelNameIndex = p.readInt();
|
||
|
if (channelNameIndex >= 0) {
|
||
|
notificationOut.setChannelName(mStringPool[channelNameIndex]);
|
||
|
} else {
|
||
|
notificationOut.setChannelName(null);
|
||
|
}
|
||
|
|
||
|
final int channelIdIndex = p.readInt();
|
||
|
if (channelIdIndex >= 0) {
|
||
|
notificationOut.setChannelId(mStringPool[channelIdIndex]);
|
||
|
} else {
|
||
|
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());
|
||
|
notificationOut.setTitle(p.readString());
|
||
|
notificationOut.setText(p.readString());
|
||
|
if (p.readBoolean()) {
|
||
|
notificationOut.setIcon(Icon.CREATOR.createFromParcel(p));
|
||
|
}
|
||
|
|
||
|
return notificationOut.build();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel dest, int flags) {
|
||
|
Parcel data = Parcel.obtain();
|
||
|
data.writeInt(mHistoryCount);
|
||
|
data.writeInt(mIndex);
|
||
|
if (mHistoryCount > 0) {
|
||
|
mStringPool = getPooledStringsToWrite();
|
||
|
data.writeStringArray(mStringPool);
|
||
|
|
||
|
if (!mNotificationsToWrite.isEmpty()) {
|
||
|
// typically system_server to a process
|
||
|
|
||
|
// Write out the events
|
||
|
Parcel p = Parcel.obtain();
|
||
|
try {
|
||
|
p.setDataPosition(0);
|
||
|
for (int i = 0; i < mHistoryCount; i++) {
|
||
|
final HistoricalNotification notification = mNotificationsToWrite.get(i);
|
||
|
writeNotificationToParcel(notification, p, flags);
|
||
|
}
|
||
|
|
||
|
final int listByteLength = p.dataPosition();
|
||
|
|
||
|
// Write the total length of the data.
|
||
|
data.writeInt(listByteLength);
|
||
|
|
||
|
// Write our current position into the data.
|
||
|
data.writeInt(0);
|
||
|
|
||
|
// Write the data.
|
||
|
data.appendFrom(p, 0, listByteLength);
|
||
|
} finally {
|
||
|
p.recycle();
|
||
|
}
|
||
|
|
||
|
} else if (mParcel != null) {
|
||
|
// typically process to process as mNotificationsToWrite is not populated on
|
||
|
// unparcel.
|
||
|
|
||
|
// Write the total length of the data.
|
||
|
data.writeInt(mParcel.dataSize());
|
||
|
|
||
|
// Write out current position into the data.
|
||
|
data.writeInt(mParcel.dataPosition());
|
||
|
|
||
|
// Write the data.
|
||
|
data.appendFrom(mParcel, 0, mParcel.dataSize());
|
||
|
} else {
|
||
|
throw new IllegalStateException(
|
||
|
"Either mParcel or mNotificationsToWrite must not be null");
|
||
|
}
|
||
|
}
|
||
|
// Data can be too large for a transact. Write the data as a Blob, which will be written to
|
||
|
// ashmem if too large.
|
||
|
dest.writeBlob(data.marshall());
|
||
|
data.recycle();
|
||
|
}
|
||
|
|
||
|
public static final @NonNull Creator<NotificationHistory> CREATOR
|
||
|
= new Creator<NotificationHistory>() {
|
||
|
@Override
|
||
|
public NotificationHistory createFromParcel(Parcel source) {
|
||
|
return new NotificationHistory(source);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public NotificationHistory[] newArray(int size) {
|
||
|
return new NotificationHistory[size];
|
||
|
}
|
||
|
};
|
||
|
}
|