Merge changes from topic "messaging_people"
* changes:
Clipping to the top roundness when scrolling
Made the notification side paddings consistent
Changing messaging style and overall visual adoption
Improved the MessagingStyle API with Person
Added People to the Notification API
diff --git a/api/current.txt b/api/current.txt
index be52a83..01ed075 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5206,15 +5206,17 @@
field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
field public static final java.lang.String EXTRA_MESSAGES = "android.messages";
+ field public static final java.lang.String EXTRA_MESSAGING_PERSON = "android.messagingUser";
field public static final java.lang.String EXTRA_NOTIFICATION_ID = "android.intent.extra.NOTIFICATION_ID";
field public static final java.lang.String EXTRA_NOTIFICATION_TAG = "android.intent.extra.NOTIFICATION_TAG";
- field public static final java.lang.String EXTRA_PEOPLE = "android.people";
+ field public static final deprecated java.lang.String EXTRA_PEOPLE = "android.people";
+ field public static final java.lang.String EXTRA_PEOPLE_LIST = "android.people.list";
field public static final java.lang.String EXTRA_PICTURE = "android.picture";
field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
field public static final java.lang.String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final java.lang.String EXTRA_PROGRESS_MAX = "android.progressMax";
field public static final java.lang.String EXTRA_REMOTE_INPUT_HISTORY = "android.remoteInputHistory";
- field public static final java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
+ field public static final deprecated java.lang.String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
field public static final java.lang.String EXTRA_SHOW_CHRONOMETER = "android.showChronometer";
field public static final java.lang.String EXTRA_SHOW_WHEN = "android.showWhen";
field public static final deprecated java.lang.String EXTRA_SMALL_ICON = "android.icon";
@@ -5354,7 +5356,8 @@
method public deprecated android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
method public android.app.Notification.Builder addAction(android.app.Notification.Action);
method public android.app.Notification.Builder addExtras(android.os.Bundle);
- method public android.app.Notification.Builder addPerson(java.lang.String);
+ method public deprecated android.app.Notification.Builder addPerson(java.lang.String);
+ method public android.app.Notification.Builder addPerson(android.app.Notification.Person);
method public android.app.Notification build();
method public android.widget.RemoteViews createBigContentView();
method public android.widget.RemoteViews createContentView();
@@ -5477,14 +5480,17 @@
}
public static class Notification.MessagingStyle extends android.app.Notification.Style {
- ctor public Notification.MessagingStyle(java.lang.CharSequence);
+ ctor public deprecated Notification.MessagingStyle(java.lang.CharSequence);
+ ctor public Notification.MessagingStyle(android.app.Notification.Person);
method public android.app.Notification.MessagingStyle addHistoricMessage(android.app.Notification.MessagingStyle.Message);
- method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public deprecated android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, java.lang.CharSequence);
+ method public android.app.Notification.MessagingStyle addMessage(java.lang.CharSequence, long, android.app.Notification.Person);
method public android.app.Notification.MessagingStyle addMessage(android.app.Notification.MessagingStyle.Message);
method public java.lang.CharSequence getConversationTitle();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getHistoricMessages();
method public java.util.List<android.app.Notification.MessagingStyle.Message> getMessages();
- method public java.lang.CharSequence getUserDisplayName();
+ method public android.app.Notification.Person getUser();
+ method public deprecated java.lang.CharSequence getUserDisplayName();
method public boolean isGroupConversation();
method public android.app.Notification.MessagingStyle setConversationTitle(java.lang.CharSequence);
method public android.app.Notification.MessagingStyle setGroupConversation(boolean);
@@ -5492,16 +5498,34 @@
}
public static final class Notification.MessagingStyle.Message {
- ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ ctor public deprecated Notification.MessagingStyle.Message(java.lang.CharSequence, long, java.lang.CharSequence);
+ ctor public Notification.MessagingStyle.Message(java.lang.CharSequence, long, android.app.Notification.Person);
method public java.lang.String getDataMimeType();
method public android.net.Uri getDataUri();
method public android.os.Bundle getExtras();
- method public java.lang.CharSequence getSender();
+ method public deprecated java.lang.CharSequence getSender();
+ method public android.app.Notification.Person getSenderPerson();
method public java.lang.CharSequence getText();
method public long getTimestamp();
method public android.app.Notification.MessagingStyle.Message setData(java.lang.String, android.net.Uri);
}
+ public static final class Notification.Person implements android.os.Parcelable {
+ ctor protected Notification.Person(android.os.Parcel);
+ ctor public Notification.Person();
+ method public int describeContents();
+ method public android.graphics.drawable.Icon getIcon();
+ method public java.lang.String getKey();
+ method public java.lang.CharSequence getName();
+ method public java.lang.String getUri();
+ method public android.app.Notification.Person setIcon(android.graphics.drawable.Icon);
+ method public android.app.Notification.Person setKey(java.lang.String);
+ method public android.app.Notification.Person setName(java.lang.CharSequence);
+ method public android.app.Notification.Person setUri(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.app.Notification.Person> CREATOR;
+ }
+
public static abstract class Notification.Style {
ctor public Notification.Style();
method public android.app.Notification build();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 046a128..a383604 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1022,10 +1022,18 @@
/**
* {@link #extras} key: A String array containing the people that this notification relates to,
* each of which was supplied to {@link Builder#addPerson(String)}.
+ *
+ * @deprecated the actual objects are now in {@link #EXTRA_PEOPLE_LIST}
*/
public static final String EXTRA_PEOPLE = "android.people";
/**
+ * {@link #extras} key: An arrayList of {@link Person} objects containing the people that
+ * this notification relates to.
+ */
+ public static final String EXTRA_PEOPLE_LIST = "android.people.list";
+
+ /**
* Allow certain system-generated notifications to appear before the device is provisioned.
* Only available to notifications coming from the android package.
* @hide
@@ -1063,10 +1071,20 @@
* direct replies
* {@link android.app.Notification.MessagingStyle} notification. This extra is a
* {@link CharSequence}
+ *
+ * @deprecated use {@link #EXTRA_MESSAGING_PERSON}
*/
public static final String EXTRA_SELF_DISPLAY_NAME = "android.selfDisplayName";
/**
+ * {@link #extras} key: the person to be displayed for all messages sent by the user including
+ * direct replies
+ * {@link android.app.Notification.MessagingStyle} notification. This extra is a
+ * {@link Person}
+ */
+ public static final String EXTRA_MESSAGING_PERSON = "android.messagingUser";
+
+ /**
* {@link #extras} key: a {@link CharSequence} to be displayed as the title to a conversation
* represented by a {@link android.app.Notification.MessagingStyle}
*/
@@ -2819,7 +2837,7 @@
private Bundle mUserExtras = new Bundle();
private Style mStyle;
private ArrayList<Action> mActions = new ArrayList<Action>(MAX_ACTION_BUTTONS);
- private ArrayList<String> mPersonList = new ArrayList<String>();
+ private ArrayList<Person> mPersonList = new ArrayList<>();
private NotificationColorUtil mColorUtil;
private boolean mIsLegacy;
private boolean mIsLegacyInitialized;
@@ -2910,8 +2928,9 @@
Collections.addAll(mActions, mN.actions);
}
- if (mN.extras.containsKey(EXTRA_PEOPLE)) {
- Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
+ if (mN.extras.containsKey(EXTRA_PEOPLE_LIST)) {
+ ArrayList<Person> people = mN.extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
+ mPersonList.addAll(people);
}
if (mN.getSmallIcon() == null && mN.icon != 0) {
@@ -3621,13 +3640,41 @@
* 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}.
+ * It is also possible to provide a URI with the schema {@code name:} in order to uniquely
+ * identify a person without an entry in the contacts database.
* </P>
*
* @param uri A URI for the person.
* @see Notification#EXTRA_PEOPLE
+ * @deprecated use {@link #addPerson(Person)}
*/
public Builder addPerson(String uri) {
- mPersonList.add(uri);
+ addPerson(new Person().setUri(uri));
+ return this;
+ }
+
+ /**
+ * Add a person that is relevant to this notification.
+ *
+ * <P>
+ * Depending on user preferences, this annotation may allow the notification to pass
+ * through interruption filters, if this notification is of category {@link #CATEGORY_CALL}
+ * or {@link #CATEGORY_MESSAGE}. The addition of people may also cause this notification to
+ * appear more prominently in the user interface.
+ * </P>
+ *
+ * <P>
+ * A person should usually contain a uri in order to benefit from the ranking boost.
+ * However, even if no uri is provided, it's beneficial to provide other people in the
+ * notification, such that listeners and voice only devices can announce and handle them
+ * properly.
+ * </P>
+ *
+ * @param person the person to add.
+ * @see Notification#EXTRA_PEOPLE_LIST
+ */
+ public Builder addPerson(Person person) {
+ mPersonList.add(person);
return this;
}
@@ -3934,7 +3981,10 @@
contentView.setViewVisibility(R.id.chronometer, View.GONE);
contentView.setViewVisibility(R.id.header_text, View.GONE);
contentView.setTextViewText(R.id.header_text, null);
+ contentView.setViewVisibility(R.id.header_text_secondary, View.GONE);
+ contentView.setTextViewText(R.id.header_text_secondary, null);
contentView.setViewVisibility(R.id.header_text_divider, View.GONE);
+ contentView.setViewVisibility(R.id.header_text_secondary_divider, View.GONE);
contentView.setViewVisibility(R.id.time_divider, View.GONE);
contentView.setViewVisibility(R.id.time, View.GONE);
contentView.setImageViewIcon(R.id.profile_badge, null);
@@ -3965,7 +4015,7 @@
final Bundle ex = mN.extras;
updateBackgroundColor(contentView);
- bindNotificationHeader(contentView, p.ambient);
+ bindNotificationHeader(contentView, p.ambient, p.headerTextSecondary);
bindLargeIcon(contentView, p.hideLargeIcon, p.alwaysShowReply);
boolean showProgress = handleProgressBar(p.hasProgress, contentView, ex);
if (p.title != null) {
@@ -4248,12 +4298,14 @@
return null;
}
- private void bindNotificationHeader(RemoteViews contentView, boolean ambient) {
+ private void bindNotificationHeader(RemoteViews contentView, boolean ambient,
+ CharSequence secondaryHeaderText) {
bindSmallIcon(contentView, ambient);
bindHeaderAppName(contentView, ambient);
if (!ambient) {
// Ambient view does not have these
bindHeaderText(contentView);
+ bindHeaderTextSecondary(contentView, secondaryHeaderText);
bindHeaderChronometerAndTime(contentView);
bindProfileBadge(contentView);
}
@@ -4322,6 +4374,17 @@
}
}
+ private void bindHeaderTextSecondary(RemoteViews contentView, CharSequence secondaryText) {
+ if (!TextUtils.isEmpty(secondaryText)) {
+ contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
+ processLegacyText(secondaryText)));
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary);
+ contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
+ contentView.setViewVisibility(R.id.header_text_secondary_divider, View.VISIBLE);
+ setTextViewColorSecondary(contentView, R.id.header_text_secondary_divider);
+ }
+ }
+
/**
* @hide
*/
@@ -4555,7 +4618,7 @@
ambient ? R.layout.notification_template_ambient_header
: R.layout.notification_template_header);
resetNotificationHeader(header);
- bindNotificationHeader(header, ambient);
+ bindNotificationHeader(header, ambient, null);
if (colorized != null) {
mN.extras.putBoolean(EXTRA_COLORIZED, colorized);
} else {
@@ -4968,8 +5031,7 @@
mActions.toArray(mN.actions);
}
if (!mPersonList.isEmpty()) {
- mN.extras.putStringArray(EXTRA_PEOPLE,
- mPersonList.toArray(new String[mPersonList.size()]));
+ mN.extras.putParcelableArrayList(EXTRA_PEOPLE_LIST, mPersonList);
}
if (mN.bigContentView != null || mN.contentView != null
|| mN.headsUpContentView != null) {
@@ -5965,7 +6027,7 @@
*/
public static final int MAXIMUM_RETAINED_MESSAGES = 25;
- CharSequence mUserDisplayName;
+ @NonNull Person mUser;
@Nullable CharSequence mConversationTitle;
List<Message> mMessages = new ArrayList<>();
List<Message> mHistoricMessages = new ArrayList<>();
@@ -5979,16 +6041,40 @@
* user before the posting app reposts the notification with those messages after they've
* been actually sent and in previous messages sent by the user added in
* {@link #addMessage(Notification.MessagingStyle.Message)}
+ *
+ * @deprecated use {@code MessagingStyle(Person)}
*/
public MessagingStyle(@NonNull CharSequence userDisplayName) {
- mUserDisplayName = userDisplayName;
+ this(new Person().setName(userDisplayName));
+ }
+
+ /**
+ * @param user Required - The person displayed for any messages that are sent by the
+ * user. Any messages added with {@link #addMessage(Notification.MessagingStyle.Message)}
+ * who don't have a Person associated with it will be displayed as if they were sent
+ * by this user. The user also needs to have a valid name associated with it.
+ */
+ public MessagingStyle(@NonNull Person user) {
+ mUser = user;
+ if (user == null || user.getName() == null) {
+ throw new RuntimeException("user must be valid and have a name");
+ }
+ }
+
+ /**
+ * @return the user to be displayed for any replies sent by the user
+ */
+ public Person getUser() {
+ return mUser;
}
/**
* Returns the name to be displayed for any replies sent by the user
+ *
+ * @deprecated use {@link #getUser()} instead
*/
public CharSequence getUserDisplayName() {
- return mUserDisplayName;
+ return mUser.getName();
}
/**
@@ -6031,8 +6117,28 @@
* @see Message#Message(CharSequence, long, CharSequence)
*
* @return this object for method chaining
+ *
+ * @deprecated use {@link #addMessage(CharSequence, long, Person)}
*/
public MessagingStyle addMessage(CharSequence text, long timestamp, CharSequence sender) {
+ return addMessage(text, timestamp,
+ sender == null ? null : new Person().setName(sender));
+ }
+
+ /**
+ * Adds a message for display by this notification. Convenience call for a simple
+ * {@link Message} in {@link #addMessage(Notification.MessagingStyle.Message)}.
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender The {@link Person} who sent the message.
+ * Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert the user set in {@code MessagingStyle(Person)}.
+ *
+ * @see Message#Message(CharSequence, long, CharSequence)
+ *
+ * @return this object for method chaining
+ */
+ public MessagingStyle addMessage(CharSequence text, long timestamp, Person sender) {
return addMessage(new Message(text, timestamp, sender));
}
@@ -6131,8 +6237,10 @@
@Override
public void addExtras(Bundle extras) {
super.addExtras(extras);
- if (mUserDisplayName != null) {
- extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUserDisplayName);
+ if (mUser != null) {
+ // For legacy usages
+ extras.putCharSequence(EXTRA_SELF_DISPLAY_NAME, mUser.getName());
+ extras.putParcelable(EXTRA_MESSAGING_PERSON, mUser);
}
if (mConversationTitle != null) {
extras.putCharSequence(EXTRA_CONVERSATION_TITLE, mConversationTitle);
@@ -6152,14 +6260,15 @@
Message m = findLatestIncomingMessage();
CharSequence text = (m == null) ? null : m.mText;
CharSequence sender = m == null ? null
- : TextUtils.isEmpty(m.mSender) ? mUserDisplayName : m.mSender;
+ : m.mSender == null || TextUtils.isEmpty(m.mSender.getName())
+ ? mUser.getName() : m.mSender.getName();
CharSequence title;
if (!TextUtils.isEmpty(mConversationTitle)) {
if (!TextUtils.isEmpty(sender)) {
BidiFormatter bidi = BidiFormatter.getInstance();
title = mBuilder.mContext.getString(
com.android.internal.R.string.notification_messaging_title_template,
- bidi.unicodeWrap(mConversationTitle), bidi.unicodeWrap(m.mSender));
+ bidi.unicodeWrap(mConversationTitle), bidi.unicodeWrap(sender));
} else {
title = mConversationTitle;
}
@@ -6182,7 +6291,11 @@
protected void restoreFromExtras(Bundle extras) {
super.restoreFromExtras(extras);
- mUserDisplayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME);
+ mUser = extras.getParcelable(EXTRA_MESSAGING_PERSON);
+ if (mUser == null) {
+ CharSequence displayName = extras.getCharSequence(EXTRA_SELF_DISPLAY_NAME);
+ mUser = new Person().setName(displayName);
+ }
mConversationTitle = extras.getCharSequence(EXTRA_CONVERSATION_TITLE);
Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES);
mMessages = Message.getMessagesFromBundleArray(messages);
@@ -6198,7 +6311,7 @@
public RemoteViews makeContentView(boolean increasedHeight) {
mBuilder.mOriginalActions = mBuilder.mActions;
mBuilder.mActions = new ArrayList<>();
- RemoteViews remoteViews = makeBigContentView();
+ RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
mBuilder.mActions = mBuilder.mOriginalActions;
mBuilder.mOriginalActions = null;
return remoteViews;
@@ -6217,7 +6330,7 @@
for (int i = messages.size() - 1; i >= 0; i--) {
Message m = messages.get(i);
// Incoming messages have a non-empty sender.
- if (!TextUtils.isEmpty(m.mSender)) {
+ if (m.mSender != null && !TextUtils.isEmpty(m.mSender.getName())) {
return m;
}
}
@@ -6233,23 +6346,31 @@
*/
@Override
public RemoteViews makeBigContentView() {
+ return makeBigContentView(false /* showRightIcon */);
+ }
+
+ @NonNull
+ private RemoteViews makeBigContentView(boolean showRightIcon) {
CharSequence conversationTitle = !TextUtils.isEmpty(super.mBigContentTitle)
? super.mBigContentTitle
: mConversationTitle;
boolean isOneToOne = TextUtils.isEmpty(conversationTitle);
- if (isOneToOne) {
- // Let's add the conversationTitle in case we didn't have one before and all
- // messages are from the same sender
- conversationTitle = createConversationTitleFromMessages();
- } else if (hasOnlyWhiteSpaceSenders()) {
+ if (hasOnlyWhiteSpaceSenders()) {
isOneToOne = true;
}
- boolean hasTitle = !TextUtils.isEmpty(conversationTitle);
RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
mBuilder.getMessagingLayoutResource(),
mBuilder.mParams.reset().hasProgress(false).title(conversationTitle).text(null)
- .hideLargeIcon(isOneToOne).alwaysShowReply(true));
+ .hideLargeIcon(!showRightIcon || isOneToOne)
+ .headerTextSecondary(conversationTitle)
+ .alwaysShowReply(showRightIcon));
addExtras(mBuilder.mN.extras);
+ // also update the end margin if there is an image
+ int endMargin = R.dimen.notification_content_margin_end;
+ if (mBuilder.mN.hasLargeIcon() && showRightIcon) {
+ endMargin = R.dimen.notification_content_plus_picture_margin_end;
+ }
+ contentView.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
contentView.setInt(R.id.status_bar_latest_event_content, "setLayoutColor",
mBuilder.resolveContrastColor());
contentView.setIcon(R.id.status_bar_latest_event_content, "setLargeIcon",
@@ -6264,8 +6385,8 @@
private boolean hasOnlyWhiteSpaceSenders() {
for (int i = 0; i < mMessages.size(); i++) {
Message m = mMessages.get(i);
- CharSequence sender = m.getSender();
- if (!isWhiteSpace(sender)) {
+ Person sender = m.getSenderPerson();
+ if (sender != null && !isWhiteSpace(sender.getName())) {
return false;
}
}
@@ -6294,9 +6415,9 @@
ArraySet<CharSequence> names = new ArraySet<>();
for (int i = 0; i < mMessages.size(); i++) {
Message m = mMessages.get(i);
- CharSequence sender = m.getSender();
+ Person sender = m.getSenderPerson();
if (sender != null) {
- names.add(sender);
+ names.add(sender.getName());
}
}
SpannableStringBuilder title = new SpannableStringBuilder();
@@ -6316,7 +6437,7 @@
*/
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
- RemoteViews remoteViews = makeBigContentView();
+ RemoteViews remoteViews = makeBigContentView(true /* showRightIcon */);
remoteViews.setInt(R.id.notification_messaging, "setMaxDisplayedLines", 1);
return remoteViews;
}
@@ -6331,13 +6452,15 @@
static final String KEY_TEXT = "text";
static final String KEY_TIMESTAMP = "time";
static final String KEY_SENDER = "sender";
+ static final String KEY_SENDER_PERSON = "sender_person";
static final String KEY_DATA_MIME_TYPE = "type";
static final String KEY_DATA_URI= "uri";
static final String KEY_EXTRAS_BUNDLE = "extras";
private final CharSequence mText;
private final long mTimestamp;
- private final CharSequence mSender;
+ @Nullable
+ private final Person mSender;
private Bundle mExtras = new Bundle();
private String mDataMimeType;
@@ -6352,8 +6475,28 @@
* the platform will insert {@link MessagingStyle#getUserDisplayName()}.
* Should be unique amongst all individuals in the conversation, and should be
* consistent during re-posts of the notification.
+ *
+ * @deprecated use {@code Message(CharSequence, long, Person)}
*/
public Message(CharSequence text, long timestamp, CharSequence sender){
+ this(text, timestamp, sender == null ? null : new Person().setName(sender));
+ }
+
+ /**
+ * Constructor
+ * @param text A {@link CharSequence} to be displayed as the message content
+ * @param timestamp Time at which the message arrived
+ * @param sender The {@link Person} who sent the message.
+ * Should be <code>null</code> for messages by the current user, in which case
+ * the platform will insert the user set in {@code MessagingStyle(Person)}.
+ * <p>
+ * The person provided should contain an Icon, set with {@link Person#setIcon(Icon)}
+ * and also have a name provided with {@link Person#setName(CharSequence)}. If multiple
+ * users have the same name, consider providing a key with {@link Person#setKey(String)}
+ * in order to differentiate between the different users.
+ * </p>
+ */
+ public Message(CharSequence text, long timestamp, @Nullable Person sender){
mText = text;
mTimestamp = timestamp;
mSender = sender;
@@ -6416,8 +6559,18 @@
/**
* Get the text used to display the contact's name in the messaging experience
+ *
+ * @deprecated use {@link #getSenderPerson()}
*/
public CharSequence getSender() {
+ return mSender == null ? null : mSender.getName();
+ }
+
+ /**
+ * Get the sender associated with this message.
+ */
+ @Nullable
+ public Person getSenderPerson() {
return mSender;
}
@@ -6443,7 +6596,9 @@
}
bundle.putLong(KEY_TIMESTAMP, mTimestamp);
if (mSender != null) {
- bundle.putCharSequence(KEY_SENDER, mSender);
+ // Legacy listeners need this
+ bundle.putCharSequence(KEY_SENDER, mSender.getName());
+ bundle.putParcelable(KEY_SENDER_PERSON, mSender);
}
if (mDataMimeType != null) {
bundle.putString(KEY_DATA_MIME_TYPE, mDataMimeType);
@@ -6492,8 +6647,20 @@
if (!bundle.containsKey(KEY_TEXT) || !bundle.containsKey(KEY_TIMESTAMP)) {
return null;
} else {
+
+ Person senderPerson = bundle.getParcelable(KEY_SENDER_PERSON);
+ if (senderPerson == null) {
+ // Legacy apps that use compat don't actually provide the sender objects
+ // We need to fix the compat version to provide people / use
+ // the native api instead
+ CharSequence senderName = bundle.getCharSequence(KEY_SENDER);
+ if (senderName != null) {
+ senderPerson = new Person().setName(senderName);
+ }
+ }
Message message = new Message(bundle.getCharSequence(KEY_TEXT),
- bundle.getLong(KEY_TIMESTAMP), bundle.getCharSequence(KEY_SENDER));
+ bundle.getLong(KEY_TIMESTAMP),
+ senderPerson);
if (bundle.containsKey(KEY_DATA_MIME_TYPE) &&
bundle.containsKey(KEY_DATA_URI)) {
message.setData(bundle.getString(KEY_DATA_MIME_TYPE),
@@ -7128,6 +7295,176 @@
}
}
+ /**
+ * A Person associated with this Notification.
+ */
+ public static final class Person implements Parcelable {
+ @Nullable private CharSequence mName;
+ @Nullable private Icon mIcon;
+ @Nullable private String mUri;
+ @Nullable private String mKey;
+
+ protected Person(Parcel in) {
+ mName = in.readCharSequence();
+ if (in.readInt() != 0) {
+ mIcon = Icon.CREATOR.createFromParcel(in);
+ }
+ mUri = in.readString();
+ mKey = in.readString();
+ }
+
+ /**
+ * Create a new person.
+ */
+ public Person() {
+ }
+
+ /**
+ * Give this person a name.
+ *
+ * @param name the name of this person
+ */
+ public Person setName(@Nullable CharSequence name) {
+ this.mName = name;
+ return this;
+ }
+
+ /**
+ * Add an icon for this person.
+ * <br />
+ * This is currently only used for {@link MessagingStyle} notifications and should not be
+ * provided otherwise, in order to save memory. The system will prefer this icon over any
+ * images that are resolved from the URI.
+ *
+ * @param icon the icon of the person
+ */
+ public Person setIcon(@Nullable Icon icon) {
+ this.mIcon = icon;
+ return this;
+ }
+
+ /**
+ * Set a URI associated with this person.
+ *
+ * <P>
+ * Depending on user preferences, adding a URI to a Person may allow the notification to
+ * pass through interruption filters, if this notification is of
+ * category {@link #CATEGORY_CALL} or {@link #CATEGORY_MESSAGE}.
+ * The addition of people may also cause this notification to appear more prominently in
+ * the user interface.
+ * </P>
+ *
+ * <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
+ */
+ public Person 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 as the key for the purpose of
+ * identification.</P>
+ *
+ * @param key the key that uniquely identifies this person
+ */
+ public Person setKey(@Nullable String key) {
+ mKey = key;
+ return 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 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 "";
+ }
+
+ @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);
+ }
+
+ public static final 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];
+ }
+ };
+ }
+
// When adding a new Style subclass here, don't forget to update
// Builder.getNotificationStyleClass.
@@ -8567,6 +8904,7 @@
boolean ambient = false;
CharSequence title;
CharSequence text;
+ CharSequence headerTextSecondary;
boolean hideLargeIcon;
public boolean alwaysShowReply;
@@ -8575,6 +8913,7 @@
ambient = false;
title = null;
text = null;
+ headerTextSecondary = null;
return this;
}
@@ -8593,6 +8932,11 @@
return this;
}
+ final StandardTemplateParams headerTextSecondary(CharSequence text) {
+ this.headerTextSecondary = text;
+ return this;
+ }
+
final StandardTemplateParams alwaysShowReply(boolean alwaysShowReply) {
this.alwaysShowReply = alwaysShowReply;
return this;
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 18d4a1e..20cd906 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -890,6 +890,8 @@
createLegacyIconExtras(notification);
// populate remote views for older clients.
maybePopulateRemoteViews(notification);
+ // populate people for older clients.
+ maybePopulatePeople(notification);
} catch (IllegalArgumentException e) {
if (corruptNotifications == null) {
corruptNotifications = new ArrayList<>(N);
@@ -1178,6 +1180,25 @@
}
}
+ /**
+ * Populates remote views for pre-P targeting apps.
+ */
+ private void maybePopulatePeople(Notification notification) {
+ if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P) {
+ ArrayList<Notification.Person> people = notification.extras.getParcelableArrayList(
+ Notification.EXTRA_PEOPLE_LIST);
+ if (people != null && people.isEmpty()) {
+ int size = people.size();
+ String[] peopleArray = new String[size];
+ for (int i = 0; i < size; i++) {
+ Notification.Person person = people.get(i);
+ peopleArray[i] = person.resolveToLegacyUri();
+ }
+ notification.extras.putStringArray(Notification.EXTRA_PEOPLE, peopleArray);
+ }
+ }
+ }
+
/** @hide */
protected class NotificationListenerWrapper extends INotificationListener.Stub {
@Override
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index ab0b3ee..fbba8ab 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -47,6 +47,7 @@
private final int mGravity;
private View mAppName;
private View mHeaderText;
+ private View mSecondaryHeaderText;
private OnClickListener mExpandClickListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private ImageView mExpandButton;
@@ -58,7 +59,6 @@
private boolean mShowExpandButtonAtEnd;
private boolean mShowWorkBadgeAtEnd;
private Drawable mBackground;
- private int mHeaderBackgroundHeight;
private boolean mEntireHeaderClickable;
private boolean mExpandOnlyOnButton;
private boolean mAcceptAllTouches;
@@ -68,7 +68,7 @@
@Override
public void getOutline(View view, Outline outline) {
if (mBackground != null) {
- outline.setRect(0, 0, getWidth(), mHeaderBackgroundHeight);
+ outline.setRect(0, 0, getWidth(), getHeight());
outline.setAlpha(1f);
}
}
@@ -91,8 +91,6 @@
Resources res = getResources();
mChildMinWidth = res.getDimensionPixelSize(R.dimen.notification_header_shrink_min_width);
mContentEndMargin = res.getDimensionPixelSize(R.dimen.notification_content_margin_end);
- mHeaderBackgroundHeight = res.getDimensionPixelSize(
- R.dimen.notification_header_background_height);
mEntireHeaderClickable = res.getBoolean(R.bool.config_notificationHeaderClickableForExpand);
int[] attrIds = { android.R.attr.gravity };
@@ -106,6 +104,7 @@
super.onFinishInflate();
mAppName = findViewById(com.android.internal.R.id.app_name_text);
mHeaderText = findViewById(com.android.internal.R.id.header_text);
+ mSecondaryHeaderText = findViewById(com.android.internal.R.id.header_text_secondary);
mExpandButton = findViewById(com.android.internal.R.id.expand_button);
mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
@@ -137,26 +136,33 @@
if (totalWidth > givenWidth) {
int overFlow = totalWidth - givenWidth;
// We are overflowing, lets shrink the app name first
- final int appWidth = mAppName.getMeasuredWidth();
- if (overFlow > 0 && mAppName.getVisibility() != GONE && appWidth > mChildMinWidth) {
- int newSize = appWidth - Math.min(appWidth - mChildMinWidth, overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mAppName.measure(childWidthSpec, wrapContentHeightSpec);
- overFlow -= appWidth - newSize;
- }
- // still overflowing, finaly we shrink the header text
- if (overFlow > 0 && mHeaderText.getVisibility() != GONE) {
- // we're still too big
- final int textWidth = mHeaderText.getMeasuredWidth();
- int newSize = Math.max(0, textWidth - overFlow);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
- mHeaderText.measure(childWidthSpec, wrapContentHeightSpec);
- }
+ overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mAppName,
+ mChildMinWidth);
+
+ // still overflowing, we shrink the header text
+ overFlow = shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mHeaderText, 0);
+
+ // still overflowing, finally we shrink the secondary header text
+ shrinkViewForOverflow(wrapContentHeightSpec, overFlow, mSecondaryHeaderText,
+ 0);
}
mTotalWidth = Math.min(totalWidth, givenWidth);
setMeasuredDimension(givenWidth, givenHeight);
}
+ private int shrinkViewForOverflow(int heightSpec, int overFlow, View targetView,
+ int minimumWidth) {
+ final int oldWidth = targetView.getMeasuredWidth();
+ if (overFlow > 0 && targetView.getVisibility() != GONE && oldWidth > minimumWidth) {
+ // we're still too big
+ int newSize = Math.max(minimumWidth, oldWidth - overFlow);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(newSize, MeasureSpec.AT_MOST);
+ targetView.measure(childWidthSpec, heightSpec);
+ overFlow -= oldWidth - newSize;
+ }
+ return overFlow;
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = getPaddingStart();
@@ -228,7 +234,7 @@
@Override
protected void onDraw(Canvas canvas) {
if (mBackground != null) {
- mBackground.setBounds(0, 0, getWidth(), mHeaderBackgroundHeight);
+ mBackground.setBounds(0, 0, getWidth(), getHeight());
mBackground.draw(canvas);
}
}
diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java
index 792f921..20f05e6 100644
--- a/core/java/com/android/internal/widget/MessagingGroup.java
+++ b/core/java/com/android/internal/widget/MessagingGroup.java
@@ -20,17 +20,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StyleRes;
+import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Pools;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -41,7 +36,6 @@
import android.widget.RemoteViews;
import com.android.internal.R;
-import com.android.internal.util.NotificationColorUtil;
import java.util.ArrayList;
import java.util.List;
@@ -60,12 +54,12 @@
private int mLayoutColor;
private CharSequence mAvatarName = "";
private Icon mAvatarIcon;
- private ColorFilter mMessageBackgroundFilter;
private int mTextColor;
private List<MessagingMessage> mMessages;
private ArrayList<MessagingMessage> mAddedMessages = new ArrayList<>();
private boolean mFirstLayout;
private boolean mIsHidingAnimated;
+ private boolean mNeedsGeneratedAvatar;
public MessagingGroup(@NonNull Context context) {
super(context);
@@ -94,27 +88,19 @@
mAvatarView = findViewById(R.id.message_icon);
}
- public void setSender(CharSequence sender) {
- if (sender == null) {
- mAvatarView.setVisibility(GONE);
- mSenderName.setVisibility(GONE);
- setGravity(Gravity.END);
- mMessageBackgroundFilter = new PorterDuffColorFilter(mLayoutColor,
- PorterDuff.Mode.SRC_ATOP);
- mTextColor = NotificationColorUtil.isColorLight(mLayoutColor) ? getNormalTextColor()
- : Color.WHITE;
- } else {
- mSenderName.setText(sender);
- mAvatarView.setVisibility(VISIBLE);
- mSenderName.setVisibility(VISIBLE);
- setGravity(Gravity.START);
- mMessageBackgroundFilter = null;
- mTextColor = getNormalTextColor();
+ public void setSender(Notification.Person sender) {
+ mSenderName.setText(sender.getName());
+ mNeedsGeneratedAvatar = sender.getIcon() == null;
+ if (!mNeedsGeneratedAvatar) {
+ setAvatar(sender.getIcon());
}
+ mAvatarView.setVisibility(VISIBLE);
+ mSenderName.setVisibility(VISIBLE);
+ mTextColor = getNormalTextColor();
}
private int getNormalTextColor() {
- return mContext.getColor(R.color.notification_primary_text_color_light);
+ return mContext.getColor(R.color.notification_secondary_text_color_light);
}
public void setAvatar(Icon icon) {
@@ -207,10 +193,6 @@
return mSenderName.getText();
}
- public void setSenderVisible(boolean visible) {
- mSenderName.setVisibility(visible ? VISIBLE : GONE);
- }
-
public static void dropCache() {
sInstancePool = new Pools.SynchronizedPool<>(10);
}
@@ -317,12 +299,6 @@
mMessageContainer.removeView(message);
mMessageContainer.addView(message, messageIndex);
}
- // Let's make sure the message color is correct
- Drawable targetDrawable = message.getBackground();
-
- if (targetDrawable != null) {
- targetDrawable.mutate().setColorFilter(mMessageBackgroundFilter);
- }
message.setTextColor(mTextColor);
}
mMessages = group;
@@ -390,4 +366,8 @@
public MessagingLinearLayout getMessageContainer() {
return mMessageContainer;
}
+
+ public boolean needsGeneratedAvatar() {
+ return mNeedsGeneratedAvatar;
+ }
}
diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java
index 2acdc01..834c93a 100644
--- a/core/java/com/android/internal/widget/MessagingLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLayout.java
@@ -69,7 +69,6 @@
private List<MessagingMessage> mMessages = new ArrayList<>();
private List<MessagingMessage> mHistoricMessages = new ArrayList<>();
private MessagingLinearLayout mMessagingLinearLayout;
- private View mContractedMessage;
private boolean mShowHistoricMessages;
private ArrayList<MessagingGroup> mGroups = new ArrayList<>();
private TextView mTitleView;
@@ -81,6 +80,7 @@
private Icon mLargeIcon;
private boolean mIsOneToOne;
private ArrayList<MessagingGroup> mAddedGroups = new ArrayList<>();
+ private Notification.Person mUser;
public MessagingLayout(@NonNull Context context) {
super(context);
@@ -129,6 +129,7 @@
Parcelable[] histMessages = extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES);
List<Notification.MessagingStyle.Message> newHistoricMessages
= Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages);
+ setUser(extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON));
mConversationTitle = null;
TextView headerText = findViewById(R.id.header_text);
if (headerText != null) {
@@ -152,7 +153,6 @@
mMessages = messages;
mHistoricMessages = historicMessages;
- updateContractedMessage();
updateHistoricMessageVisibility();
updateTitleAndNamesDisplay();
}
@@ -163,12 +163,10 @@
for (int i = 0; i < mGroups.size(); i++) {
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
continue;
}
- boolean visible = !mIsOneToOne;
- group.setSenderVisible(visible);
- if ((visible || mLargeIcon == null) && !uniqueNames.containsKey(senderName)) {
+ if (!uniqueNames.containsKey(senderName)) {
char c = senderName.charAt(0);
if (uniqueCharacters.containsKey(c)) {
// this character was already used, lets make it more unique. We first need to
@@ -192,7 +190,8 @@
// Let's now set the avatars
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName) || (mIsOneToOne && mLargeIcon != null)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)
+ || (mIsOneToOne && mLargeIcon != null)) {
continue;
}
String symbol = uniqueNames.get(senderName);
@@ -207,7 +206,7 @@
// Let's now set the avatars
MessagingGroup group = mGroups.get(i);
CharSequence senderName = group.getSenderName();
- if (TextUtils.isEmpty(senderName)) {
+ if (!group.needsGeneratedAvatar() || TextUtils.isEmpty(senderName)) {
continue;
}
if (mIsOneToOne && mLargeIcon != null) {
@@ -234,7 +233,7 @@
canvas.drawCircle(radius, radius, radius, mPaint);
boolean needDarkText = ColorUtils.calculateLuminance(color) > 0.5f;
mTextPaint.setColor(needDarkText ? Color.BLACK : Color.WHITE);
- mTextPaint.setTextSize(symbol.length() == 1 ? mAvatarSize * 0.75f : mAvatarSize * 0.4f);
+ mTextPaint.setTextSize(symbol.length() == 1 ? mAvatarSize * 0.5f : mAvatarSize * 0.3f);
int yPos = (int) (radius - ((mTextPaint.descent() + mTextPaint.ascent()) / 2)) ;
canvas.drawText(symbol, radius, yPos, mTextPaint);
return Icon.createWithBitmap(bitmap);
@@ -270,11 +269,15 @@
mIsOneToOne = oneToOne;
}
+ public void setUser(Notification.Person user) {
+ mUser = user;
+ }
+
private void addMessagesToGroups(List<MessagingMessage> historicMessages,
List<MessagingMessage> messages) {
// Let's first find our groups!
List<List<MessagingMessage>> groups = new ArrayList<>();
- List<CharSequence> senders = new ArrayList<>();
+ List<Notification.Person> senders = new ArrayList<>();
// Lets first find the groups
findGroups(historicMessages, messages, groups, senders);
@@ -283,7 +286,8 @@
createGroupViews(groups, senders);
}
- private void createGroupViews(List<List<MessagingMessage>> groups, List<CharSequence> senders) {
+ private void createGroupViews(List<List<MessagingMessage>> groups,
+ List<Notification.Person> senders) {
mGroups.clear();
for (int groupIndex = 0; groupIndex < groups.size(); groupIndex++) {
List<MessagingMessage> group = groups.get(groupIndex);
@@ -314,8 +318,8 @@
private void findGroups(List<MessagingMessage> historicMessages,
List<MessagingMessage> messages, List<List<MessagingMessage>> groups,
- List<CharSequence> senders) {
- CharSequence currentSender = null;
+ List<Notification.Person> senders) {
+ CharSequence currentSenderKey = null;
List<MessagingMessage> currentGroup = null;
int histSize = historicMessages.size();
for (int i = 0; i < histSize + messages.size(); i++) {
@@ -326,35 +330,23 @@
message = messages.get(i - histSize);
}
boolean isNewGroup = currentGroup == null;
- CharSequence sender = message.getMessage().getSender();
- isNewGroup |= !TextUtils.equals(sender, currentSender);
+ Notification.Person sender = message.getMessage().getSenderPerson();
+ CharSequence key = sender == null ? null
+ : sender.getKey() == null ? sender.getName() : sender.getKey();
+ isNewGroup |= !TextUtils.equals(key, currentSenderKey);
if (isNewGroup) {
currentGroup = new ArrayList<>();
groups.add(currentGroup);
+ if (sender == null) {
+ sender = mUser;
+ }
senders.add(sender);
- currentSender = sender;
+ currentSenderKey = key;
}
currentGroup.add(message);
}
}
- private void updateContractedMessage() {
- for (int i = mMessages.size() - 1; i >= 0; i--) {
- MessagingMessage m = mMessages.get(i);
- // Incoming messages have a non-empty sender.
- if (!TextUtils.isEmpty(m.getMessage().getSender())) {
- mContractedMessage = m;
- return;
- }
- }
- if (!mMessages.isEmpty()) {
- // No incoming messages, fall back to outgoing message
- mContractedMessage = mMessages.get(mMessages.size() - 1);
- return;
- }
- mContractedMessage = null;
- }
-
/**
* Creates new messages, reusing existing ones if they are available.
*
@@ -430,10 +422,6 @@
}
}
- public View getContractedMessage() {
- return mContractedMessage;
- }
-
public MessagingLinearLayout getMessagingLinearLayout() {
return mMessagingLinearLayout;
}
diff --git a/core/res/res/drawable/messaging_message_background.xml b/core/res/res/drawable/messaging_message_background.xml
deleted file mode 100644
index 8a2096a..0000000
--- a/core/res/res/drawable/messaging_message_background.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 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
- -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle"
- android:tint="#14000000">
- <corners android:radius="4dp" />
- <padding android:bottom="6dp"
- android:left="8dp"
- android:right="8dp"
- android:top="6dp" />
-</shape>
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 3a28f4d..20bdf3f 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -41,6 +41,24 @@
android:singleLine="true"
/>
<TextView
+ android:id="@+id/header_text_secondary_divider"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:text="@string/notification_header_divider_symbol"
+ android:visibility="gone"/>
+ <TextView
+ android:id="@+id/header_text_secondary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?attr/notificationHeaderTextAppearance"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:visibility="gone"
+ android:singleLine="true"/>
+ <TextView
android:id="@+id/header_text_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index f72230b..a72ad53 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -21,10 +21,7 @@
android:layout_height="wrap_content"
android:tag="messaging"
>
- <include layout="@layout/notification_template_header"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/notification_header_height"
- android:layout_marginEnd="56dp"/>
+ <include layout="@layout/notification_template_header"/>
<LinearLayout
android:id="@+id/notification_action_list_margin_target"
android:layout_width="match_parent"
@@ -39,28 +36,19 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:paddingStart="@dimen/notification_content_margin_start"
- android:paddingEnd="@dimen/notification_content_margin_end"
+ android:layout_marginStart="@dimen/notification_content_margin_start"
+ android:layout_marginEnd="@dimen/notification_content_margin_end"
android:minHeight="@dimen/notification_min_content_height"
android:layout_marginBottom="@dimen/notification_content_margin_bottom"
android:orientation="vertical"
>
- <include layout="@layout/notification_template_part_line1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
-
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/notification_messaging"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
android:spacing="@dimen/notification_messaging_spacing" />
</LinearLayout>
</LinearLayout>
<include layout="@layout/notification_material_action_list" />
- <include layout="@layout/notification_template_right_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="18dp"
- android:layout_gravity="top|end"/>
+ <include layout="@layout/notification_template_right_icon"/>
</com.android.internal.widget.MessagingLayout>
diff --git a/core/res/res/layout/notification_template_messaging_group.xml b/core/res/res/layout/notification_template_messaging_group.xml
index 8973ceb..4ac308a 100644
--- a/core/res/res/layout/notification_template_messaging_group.xml
+++ b/core/res/res/layout/notification_template_messaging_group.xml
@@ -24,7 +24,7 @@
android:id="@+id/message_icon"
android:layout_width="@dimen/messaging_avatar_size"
android:layout_height="@dimen/messaging_avatar_size"
- android:layout_marginEnd="8dp"
+ android:layout_marginEnd="12dp"
android:scaleType="centerCrop"
android:importantForAccessibility="no" />
<com.android.internal.widget.RemeasuringLinearLayout
@@ -32,19 +32,16 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
+ <com.android.internal.widget.ImageFloatingTextView
+ android:id="@+id/message_name"
+ style="@style/Widget.Material.Notification.MessagingName"
+ android:layout_width="wrap_content"
+ />
<com.android.internal.widget.MessagingLinearLayout
android:id="@+id/group_message_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:spacing="2dp"
android:layout_weight="1"/>
- <com.android.internal.widget.ImageFloatingTextView
- android:id="@+id/message_name"
- style="@style/Widget.Material.Notification.MessagingName"
- android:layout_width="wrap_content"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:paddingTop="2dp"
- />
</com.android.internal.widget.RemeasuringLinearLayout>
</com.android.internal.widget.MessagingGroup>
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index 8fb2887..0b97e45 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -19,7 +19,7 @@
android:id="@+id/right_icon_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="36dp"
+ android:layout_marginTop="@dimen/notification_content_margin_top"
android:layout_gravity="top|end">
<ImageView android:id="@+id/right_icon"
android:layout_width="@dimen/notification_right_icon_size"
@@ -32,8 +32,8 @@
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="top|end"
- android:layout_marginTop="28dp"
- android:layout_marginEnd="12dp"
+ android:layout_marginTop="27dp"
+ android:layout_marginEnd="16dp"
android:background="@drawable/notification_reply_background"
android:src="@drawable/ic_reply_notification"
android:scaleType="center"
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9929545..2c824ea0 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -152,11 +152,11 @@
<dimen name="dialog_padding">16dp</dimen>
<!-- The margin on the start of the content view -->
- <dimen name="notification_content_margin_start">24dp</dimen>
+ <dimen name="notification_content_margin_start">16dp</dimen>
<!-- The margin on the end of the content view
Keep in sync with notification_content_plus_picture_margin! -->
- <dimen name="notification_content_margin_end">24dp</dimen>
+ <dimen name="notification_content_margin_end">16dp</dimen>
<!-- The margin on the end of the content view with a picture.
Keep in sync with notification_content_plus_picture_margin! -->
@@ -166,7 +166,7 @@
content end margin.
Keep equal to (notification_content_picture_margin + notification_content_margin_end)!
-->
- <dimen name="notification_content_plus_picture_margin_end">80dp</dimen>
+ <dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
<!-- The additional margin on the sides of the ambient view. -->
<dimen name="notification_extra_margin_ambient">16dp</dimen>
@@ -175,10 +175,10 @@
<dimen name="notification_action_list_height">56dp</dimen>
<!-- height of the content margin to accomodate for the header -->
- <dimen name="notification_content_margin_top">41.5dp</dimen>
+ <dimen name="notification_content_margin_top">46dp</dimen>
<!-- height of the content margin on the bottom -->
- <dimen name="notification_content_margin_bottom">18dp</dimen>
+ <dimen name="notification_content_margin_bottom">20dp</dimen>
<!-- The height of the progress bar. -->
<dimen name="notification_progress_bar_height">15dp</dimen>
@@ -187,7 +187,7 @@
<dimen name="notification_progress_margin_top">8dp</dimen>
<!-- height of the notification header (for icon and package name) -->
- <dimen name="notification_header_height">54dp</dimen>
+ <dimen name="notification_header_height">50dp</dimen>
<!-- The height of the background for a notification header on a group -->
<dimen name="notification_header_background_height">49.5dp</dimen>
@@ -199,7 +199,7 @@
<dimen name="notification_header_padding_bottom">16dp</dimen>
<!-- The margin at the bottom of the notification header. -->
- <dimen name="notification_header_margin_bottom">5dp</dimen>
+ <dimen name="notification_header_margin_bottom">0dp</dimen>
<!-- The end margin after the application icon in the notification header -->
<dimen name="notification_header_icon_margin_end">3dp</dimen>
@@ -250,7 +250,7 @@
<dimen name="media_notification_expanded_image_margin_bottom">20dp</dimen>
<!-- The absolute height for the header in a media notification. -->
- <dimen name="media_notification_header_height">53dp</dimen>
+ <dimen name="media_notification_header_height">@dimen/notification_header_height</dimen>
<!-- The margin of the content to an image-->
<dimen name="notification_content_image_margin_end">8dp</dimen>
@@ -590,7 +590,7 @@
<!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
<dimen name="notification_media_image_max_width">280dp</dimen>
<!-- The size of the right icon -->
- <dimen name="notification_right_icon_size">40dp</dimen>
+ <dimen name="notification_right_icon_size">38dp</dimen>
<!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. -->
<dimen name="notification_custom_view_max_image_height_low_ram">208dp</dimen>
@@ -607,7 +607,7 @@
<!-- The size of the right icon image when on low ram -->
<dimen name="notification_right_icon_size_low_ram">40dp</dimen>
- <dimen name="messaging_avatar_size">24dp</dimen>
+ <dimen name="messaging_avatar_size">@dimen/notification_right_icon_size</dimen>
<!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
<dimen name="autofill_dataset_picker_max_size">90%</dimen>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index def650a..fa3cf2f 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -502,20 +502,17 @@
<style name="Widget.Material.Notification.ProgressBar" parent="Widget.Material.Light.ProgressBar.Horizontal" />
<style name="Widget.Material.Notification.MessagingText" parent="Widget.Material.Light.TextView">
- <item name="layout_width">match_parent</item>
+ <item name="layout_width">wrap_content</item>
<item name="layout_height">wrap_content</item>
<item name="ellipsize">end</item>
<item name="textAppearance">@style/TextAppearance.Material.Notification</item>
- <item name="background">@drawable/messaging_message_background</item>
</style>
<style name="Widget.Material.Notification.MessagingName" parent="Widget.Material.Light.TextView">
<item name="layout_width">wrap_content</item>
<item name="layout_height">wrap_content</item>
<item name="ellipsize">end</item>
- <item name="textAppearance">@style/TextAppearance.Material.Notification</item>
- <item name="textColor">@color/notification_primary_text_color_light</item>
- <item name="textSize">12sp</item>
+ <item name="textAppearance">@style/TextAppearance.Material.Notification.Title</item>
</style>
<!-- Widget Styles -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2f2566c..d2ad99b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2608,10 +2608,12 @@
<java-symbol type="string" name="notification_hidden_text" />
<java-symbol type="id" name="app_name_text" />
<java-symbol type="id" name="header_text" />
+ <java-symbol type="id" name="header_text_secondary" />
<java-symbol type="id" name="expand_button" />
<java-symbol type="id" name="notification_header" />
<java-symbol type="id" name="time_divider" />
<java-symbol type="id" name="header_text_divider" />
+ <java-symbol type="id" name="header_text_secondary_divider" />
<java-symbol type="id" name="text_line_1" />
<java-symbol type="drawable" name="ic_expand_notification" />
<java-symbol type="drawable" name="ic_collapse_notification" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8f20681..a510c4a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -78,10 +78,10 @@
<dimen name="status_bar_connected_device_bt_indicator_size">17dp</dimen>
<!-- Height of a small notification in the status bar-->
- <dimen name="notification_min_height">100dp</dimen>
+ <dimen name="notification_min_height">106dp</dimen>
<!-- Increased height of a small notification in the status bar -->
- <dimen name="notification_min_height_increased">140dp</dimen>
+ <dimen name="notification_min_height_increased">146dp</dimen>
<!-- Height of a small notification in the status bar which was used before android N -->
<dimen name="notification_min_height_legacy">64dp</dimen>
@@ -90,7 +90,7 @@
<dimen name="notification_min_height_before_p">92dp</dimen>
<!-- Height of a large notification in the status bar -->
- <dimen name="notification_max_height">292dp</dimen>
+ <dimen name="notification_max_height">294dp</dimen>
<!-- Height of an ambient notification on ambient display -->
<dimen name="notification_ambient_height">400dp</dimen>
@@ -102,16 +102,13 @@
<dimen name="notification_max_heads_up_height_before_p">148dp</dimen>
<!-- Height of a heads up notification in the status bar -->
- <dimen name="notification_max_heads_up_height">156dp</dimen>
+ <dimen name="notification_max_heads_up_height">162dp</dimen>
<!-- Height of a heads up notification in the status bar -->
<dimen name="notification_max_heads_up_height_increased">188dp</dimen>
<!-- Side padding on the lockscreen on the side of notifications -->
- <dimen name="notification_lockscreen_side_paddings">8dp</dimen>
-
- <!-- Additional side padding for custom content if the app doesn't target P yet -->
- <dimen name="notification_content_custom_view_side_padding">@dimen/notification_lockscreen_side_paddings</dimen>
+ <dimen name="notification_side_paddings">4dp</dimen>
<!-- Height of a messaging notifications with actions at least. Not that this is an upper bound
and the notification won't use this much, but is measured with wrap_content -->
@@ -127,7 +124,7 @@
<dimen name="notification_min_interaction_height">40dp</dimen>
<!-- the padding of the shelf icon container -->
- <dimen name="shelf_icon_container_padding">21dp</dimen>
+ <dimen name="shelf_icon_container_padding">13dp</dimen>
<!-- The padding of a notification icon on top to the start of the notification. Used for custom
views where the distance can't be measured -->
@@ -238,7 +235,7 @@
<dimen name="qs_footer_height">48dp</dimen>
<!-- The padding between the notifications and the quick settings container -->
- <dimen name="qs_notification_keyguard_padding">8dp</dimen>
+ <dimen name="qs_notification_padding">@dimen/notification_side_paddings</dimen>
<!-- Height of the status bar header bar when expanded -->
<dimen name="status_bar_header_height_expanded">124dp</dimen>
@@ -391,9 +388,6 @@
group. -->
<dimen name="notification_children_container_divider_height">@dimen/notification_divider_height</dimen>
- <!-- The height of the header for a container containing child notifications. -->
- <dimen name="notification_children_container_header_height">53dp</dimen>
-
<!-- The top margin for the notification children container in its non-expanded form. -->
<dimen name="notification_children_container_margin_top">@*android:dimen/notification_content_margin_top</dimen>
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index dd31365..fed97c5 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -86,10 +86,6 @@
<item type="id" name="top_roundess_animator_start_tag"/>
<item type="id" name="top_roundess_animator_end_tag"/>
- <item type="id" name="side_padding_animator_tag"/>
- <item type="id" name="side_padding_animator_start_tag"/>
- <item type="id" name="side_padding_animator_end_tag"/>
-
<!-- Accessibility actions for the notification menu -->
<item type="id" name="action_snooze_undo"/>
<item type="id" name="action_snooze_shorter"/>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index ff0357a..e59c703 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -931,13 +931,6 @@
}
@Override
- public void setCurrentSidePaddings(float currentSidePaddings) {
- super.setCurrentSidePaddings(currentSidePaddings);
- mBackgroundNormal.setCurrentSidePaddings(currentSidePaddings);
- mBackgroundDimmed.setCurrentSidePaddings(currentSidePaddings);
- }
-
- @Override
protected boolean childNeedsClipping(View child) {
if (child instanceof NotificationBackgroundView && isClippingNeeded()) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f53eb48..d1e6dcc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -2362,16 +2362,15 @@
NotificationContentView contentView = (NotificationContentView) child;
if (isClippingNeeded()) {
return true;
- } else if (!hasNoRoundingAndNoPadding() && contentView.shouldClipToSidePaddings()) {
+ } else if (!hasNoRounding() && contentView.shouldClipToRounding()) {
return true;
}
} else if (child == mChildrenContainer) {
- if (isClippingNeeded() || ((isGroupExpanded() || isGroupExpansionChanging())
- && getClipBottomAmount() != 0.0f && getCurrentBottomRoundness() != 0.0f)) {
+ if (isClippingNeeded() || !hasNoRounding()) {
return true;
}
} else if (child instanceof NotificationGuts) {
- return !hasNoRoundingAndNoPadding();
+ return !hasNoRounding();
}
return super.childNeedsClipping(child);
}
@@ -2401,9 +2400,8 @@
return super.getCustomClipPath(child);
}
- private boolean hasNoRoundingAndNoPadding() {
- return mCurrentSidePaddings == 0 && getCurrentBottomRoundness() == 0.0f
- && getCurrentTopRoundness() == 0.0f;
+ private boolean hasNoRounding() {
+ return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f;
}
public boolean isShowingAmbient() {
@@ -2418,20 +2416,6 @@
}
}
- @Override
- public void setCurrentSidePaddings(float currentSidePaddings) {
- if (mIsSummaryWithChildren) {
- List<ExpandableNotificationRow> notificationChildren =
- mChildrenContainer.getNotificationChildren();
- int size = notificationChildren.size();
- for (int i = 0; i < size; i++) {
- ExpandableNotificationRow row = notificationChildren.get(i);
- row.setCurrentSidePaddings(currentSidePaddings);
- }
- }
- super.setCurrentSidePaddings(currentSidePaddings);
- }
-
public static class NotificationViewState extends ExpandableViewState {
private final StackScrollState mOverallState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index db19d2f..66b3a75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -58,6 +58,7 @@
private static final Path EMPTY_PATH = new Path();
private final Rect mOutlineRect = new Rect();
+ private final Path mClipPath = new Path();
private boolean mCustomOutline;
private float mOutlineAlpha = -1f;
private float mOutlineRadius;
@@ -69,13 +70,14 @@
private float mBottomRoundness;
private float mTopRoundness;
private int mBackgroundTop;
- protected int mCurrentSidePaddings;
/**
* {@code true} if the children views of the {@link ExpandableOutlineView} are translated when
* it is moved. Otherwise, the translation is set on the {@code ExpandableOutlineView} itself.
*/
protected boolean mShouldTranslateContents;
+ private boolean mClipRoundedToClipTopAmount;
+ private float mDistanceToTopRoundness = -1;
private final ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@Override
@@ -83,9 +85,9 @@
if (!mCustomOutline && mCurrentTopRoundness == 0.0f
&& mCurrentBottomRoundness == 0.0f && !mAlwaysRoundBothCorners) {
int translation = mShouldTranslateContents ? (int) getTranslation() : 0;
- int left = Math.max(translation + mCurrentSidePaddings, mCurrentSidePaddings);
+ int left = Math.max(translation, 0);
int top = mClipTopAmount + mBackgroundTop;
- int right = getWidth() - mCurrentSidePaddings + Math.min(translation, 0);
+ int right = getWidth() + Math.min(translation, 0);
int bottom = Math.max(getActualHeight() - mClipBottomAmount, top);
outline.setRect(left, top, right, bottom);
} else {
@@ -115,9 +117,9 @@
if (!mCustomOutline) {
int translation = mShouldTranslateContents && !ignoreTranslation
? (int) getTranslation() : 0;
- left = Math.max(translation + mCurrentSidePaddings, mCurrentSidePaddings);
+ left = Math.max(translation, 0);
top = mClipTopAmount + mBackgroundTop;
- right = getWidth() - mCurrentSidePaddings + Math.min(translation, 0);
+ right = getWidth() + Math.min(translation, 0);
bottom = Math.max(getActualHeight(), top);
int intersectBottom = Math.max(getActualHeight() - mClipBottomAmount, top);
if (bottom != intersectBottom) {
@@ -135,8 +137,6 @@
top = mOutlineRect.top;
right = mOutlineRect.right;
bottom = mOutlineRect.bottom;
- left = Math.max(mCurrentSidePaddings, left);
- right = Math.min(getWidth() - mCurrentSidePaddings, right);
}
height = bottom - top;
if (height == 0) {
@@ -162,15 +162,8 @@
return roundedRectPath;
}
- protected Path getRoundedRectPath(int left, int top, int right, int bottom, float topRoundness,
- float bottomRoundness) {
- getRoundedRectPath(left, top, right, bottom, topRoundness, bottomRoundness,
- mTmpPath);
- return mTmpPath;
- }
-
- private void getRoundedRectPath(int left, int top, int right, int bottom, float topRoundness,
- float bottomRoundness, Path outPath) {
+ public static void getRoundedRectPath(int left, int top, int right, int bottom,
+ float topRoundness, float bottomRoundness, Path outPath) {
outPath.reset();
int width = right - left;
float topRoundnessX = topRoundness;
@@ -207,20 +200,50 @@
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
canvas.save();
+ Path intersectPath = null;
+ if (mClipRoundedToClipTopAmount) {
+ int left = 0;
+ int top = (int) (mClipTopAmount - mDistanceToTopRoundness);
+ int right = getWidth();
+ int bottom = (int) Math.max(getActualHeight() - mClipBottomAmount,
+ top + mOutlineRadius);
+ ExpandableOutlineView.getRoundedRectPath(left, top, right, bottom, mOutlineRadius,
+ 0.0f,
+ mClipPath);
+ intersectPath = mClipPath;
+ }
+ boolean clipped = false;
if (childNeedsClipping(child)) {
Path clipPath = getCustomClipPath(child);
if (clipPath == null) {
clipPath = getClipPath();
}
if (clipPath != null) {
+ if (intersectPath != null) {
+ clipPath.op(intersectPath, Path.Op.INTERSECT);
+ }
canvas.clipPath(clipPath);
+ clipped = true;
}
}
+ if (!clipped && intersectPath != null) {
+ canvas.clipPath(intersectPath);
+ }
boolean result = super.drawChild(canvas, child, drawingTime);
canvas.restore();
return result;
}
+ @Override
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ super.setDistanceToTopRoundness(distanceToTopRoundness);
+ if (distanceToTopRoundness != mDistanceToTopRoundness) {
+ mClipRoundedToClipTopAmount = distanceToTopRoundness >= 0;
+ mDistanceToTopRoundness = distanceToTopRoundness;
+ invalidate();
+ }
+ }
+
protected boolean childNeedsClipping(View child) {
return false;
}
@@ -395,10 +418,4 @@
public Path getCustomClipPath(View child) {
return null;
}
-
- public void setCurrentSidePaddings(float currentSidePaddings) {
- mCurrentSidePaddings = (int) currentSidePaddings;
- invalidateOutline();
- invalidate();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index f762513..eafa825 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -130,6 +130,14 @@
}
}
+ /**
+ * Set the distance to the top roundness, from where we should start clipping a value above
+ * or equal to 0 is the effective distance, and if a value below 0 is received, there should
+ * be no clipping.
+ */
+ public void setDistanceToTopRoundness(float distanceToTopRoundness) {
+ }
+
public void setActualHeight(int actualHeight) {
setActualHeight(actualHeight, true /* notifyListeners */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 68cf51c..45b35d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -41,7 +41,6 @@
private int mClipBottomAmount;
private int mTintColor;
private float[] mCornerRadii = new float[8];
- private int mCurrentSidePaddings;
private boolean mBottomIsRounded;
private int mBackgroundTop;
private boolean mBottomAmountClips = true;
@@ -68,8 +67,7 @@
if (mBottomIsRounded && mBottomAmountClips) {
bottom -= mClipBottomAmount;
}
- drawable.setBounds(mCurrentSidePaddings, mBackgroundTop,
- getWidth() - mCurrentSidePaddings, bottom);
+ drawable.setBounds(0, mBackgroundTop, getWidth(), bottom);
drawable.draw(canvas);
}
}
@@ -206,11 +204,6 @@
}
}
- public void setCurrentSidePaddings(float currentSidePaddings) {
- mCurrentSidePaddings = (int) currentSidePaddings;
- invalidate();
- }
-
public void setBackgroundTop(int backgroundTop) {
mBackgroundTop = backgroundTop;
invalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 39c2131..c73e548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -136,7 +136,6 @@
private int mClipBottomAmount;
private boolean mIsLowPriority;
private boolean mIsContentExpandable;
- private int mCustomViewSidePaddings;
public NotificationContentView(Context context, AttributeSet attrs) {
@@ -150,8 +149,6 @@
R.dimen.min_notification_layout_height);
mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
- mCustomViewSidePaddings = getResources().getDimensionPixelSize(
- R.dimen.notification_content_custom_view_side_padding);
}
public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight,
@@ -391,22 +388,6 @@
mContractedWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
mContractedWrapper.setDark(mDark, false /* animate */, 0 /* delay */);
- updateMargins(child);
- }
-
- private void updateMargins(View child) {
- if (child == null) {
- return;
- }
- NotificationViewWrapper wrapper = getWrapperForView(child);
- boolean isCustomView = wrapper instanceof NotificationCustomViewWrapper;
- boolean needsMargins = isCustomView &&
- child.getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.P;
- int padding = needsMargins ? mCustomViewSidePaddings : 0;
- MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
- layoutParams.setMarginStart(padding);
- layoutParams.setMarginEnd(padding);
- child.setLayoutParams(layoutParams);
}
private NotificationViewWrapper getWrapperForView(View child) {
@@ -456,7 +437,6 @@
mExpandedChild = child;
mExpandedWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
- updateMargins(child);
}
public void setHeadsUpChild(View child) {
@@ -490,7 +470,6 @@
mHeadsUpChild = child;
mHeadsUpWrapper = NotificationViewWrapper.wrap(getContext(), child,
mContainingNotification);
- updateMargins(child);
}
public void setAmbientChild(View child) {
@@ -1510,19 +1489,19 @@
return false;
}
- public boolean shouldClipToSidePaddings() {
- boolean needsPaddings = shouldClipToSidePaddings(getVisibleType());
+ public boolean shouldClipToRounding() {
+ boolean needsPaddings = shouldClipToRounding(getVisibleType());
if (mUserExpanding) {
- needsPaddings |= shouldClipToSidePaddings(mTransformationStartVisibleType);
+ needsPaddings |= shouldClipToRounding(mTransformationStartVisibleType);
}
return needsPaddings;
}
- private boolean shouldClipToSidePaddings(int visibleType) {
+ private boolean shouldClipToRounding(int visibleType) {
NotificationViewWrapper visibleWrapper = getVisibleWrapper(visibleType);
if (visibleWrapper == null) {
return false;
}
- return visibleWrapper.shouldClipToSidePaddings();
+ return visibleWrapper.shouldClipToRounding();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 4301817..1127075 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
@@ -128,6 +128,7 @@
mComparators.add(HeaderProcessor.forTextView(mRow,
com.android.internal.R.id.header_text));
mDividers.add(com.android.internal.R.id.header_text_divider);
+ mDividers.add(com.android.internal.R.id.header_text_secondary_divider);
mDividers.add(com.android.internal.R.id.time_divider);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index b2604fe..037eeb2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -176,8 +176,6 @@
final Resources res = mContext.getResources();
mHorizSpaceForIcon = res.getDimensionPixelSize(R.dimen.notification_menu_icon_size);
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
- mSidePadding = res.getDimensionPixelSize(R.dimen.notification_lockscreen_side_paddings);
- mIconPadding = res.getDimensionPixelSize(R.dimen.notification_menu_icon_padding);
mMenuItems.clear();
// Construct the menu items based on the notification
if (mParent != null && mParent.getStatusBarNotification() != null) {
@@ -498,8 +496,8 @@
final int count = mMenuContainer.getChildCount();
for (int i = 0; i < count; i++) {
final View v = mMenuContainer.getChildAt(i);
- final float left = mSidePadding + i * mHorizSpaceForIcon;
- final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1)) - mSidePadding;
+ final float left = i * mHorizSpaceForIcon;
+ final float right = mParent.getWidth() - (mHorizSpaceForIcon * (i + 1));
v.setX(showOnLeft ? left : right);
}
mOnLeft = showOnLeft;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
index 66682e4..0d22095 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationCustomViewWrapper.java
@@ -38,7 +38,6 @@
private final Paint mGreyPaint = new Paint();
private boolean mIsLegacy;
private int mLegacyColor;
- private boolean mBeforeP;
protected NotificationCustomViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
super(ctx, view, row);
@@ -119,15 +118,7 @@
}
@Override
- public boolean shouldClipToSidePaddings() {
- // Before P we ensure that they are now drawing inside out content bounds since we inset
- // the view. If they target P, then we don't have that guarantee and we need to be safe.
- return !mBeforeP;
- }
-
- @Override
- public void onContentUpdated(ExpandableNotificationRow row) {
- super.onContentUpdated(row);
- mBeforeP = row.getEntry().targetSdk < Build.VERSION_CODES.P;
+ public boolean shouldClipToRounding() {
+ return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
index 060e6d6..d7c08cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
@@ -62,7 +62,7 @@
}
@Override
- public boolean shouldClipToSidePaddings() {
+ public boolean shouldClipToRounding() {
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
index e07112f..fd085d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
@@ -265,11 +265,6 @@
updateActionOffset();
}
- @Override
- public boolean shouldClipToSidePaddings() {
- return mActionsContainer != null && mActionsContainer.getVisibility() != View.GONE;
- }
-
private void updateActionOffset() {
if (mActionsContainer != null) {
// We should never push the actions higher than they are in the headsup view.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 8a767bb..c71d604 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -195,7 +195,7 @@
return 0;
}
- public boolean shouldClipToSidePaddings() {
+ public boolean shouldClipToRounding() {
return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index f0bd1f9..32675d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -309,7 +309,7 @@
mIndicationBottomPadding = getResources().getDimensionPixelSize(
R.dimen.keyguard_indication_bottom_padding);
mQsNotificationTopPadding = getResources().getDimensionPixelSize(
- R.dimen.qs_notification_keyguard_padding);
+ R.dimen.qs_notification_padding);
}
public void updateResources() {
@@ -451,7 +451,8 @@
boolean animate = mNotificationStackScroller.isAddOrRemoveAnimationPending();
int stackScrollerPadding;
if (mStatusBarState != StatusBarState.KEYGUARD) {
- stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight;
+ stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight
+ + mQsNotificationTopPadding;
mTopPaddingAdjustment = 0;
} else {
mClockPositionAlgorithm.setup(
@@ -1381,7 +1382,7 @@
mNotificationStackScroller.getIntrinsicPadding(),
mQsMaxExpansionHeight + mQsNotificationTopPadding);
} else {
- return mQsExpansionHeight;
+ return mQsExpansionHeight + mQsNotificationTopPadding;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index c0241e3..5505099 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -128,12 +128,11 @@
mDividerHeight = res.getDimensionPixelSize(
R.dimen.notification_children_container_divider_height);
mDividerAlpha = res.getFloat(R.dimen.notification_divider_alpha);
- mHeaderHeight = res.getDimensionPixelSize(
- R.dimen.notification_children_container_header_height);
mNotificationHeaderMargin = res.getDimensionPixelSize(
R.dimen.notification_children_container_margin_top);
mNotificatonTopPadding = res.getDimensionPixelSize(
R.dimen.notification_children_container_top_padding);
+ mHeaderHeight = mNotificationHeaderMargin + mNotificatonTopPadding;
mCollapsedBottompadding = res.getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_bottom);
mEnableShadowOnChildNotifications =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 369e7ff..167508a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -76,7 +76,6 @@
import com.android.systemui.statusbar.DismissView;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.ExpandableNotificationRow;
-import com.android.systemui.statusbar.ExpandableOutlineView;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationGuts;
@@ -86,10 +85,8 @@
import com.android.systemui.statusbar.NotificationSnooze;
import com.android.systemui.statusbar.StackScrollerDecorView;
import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
-import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -126,16 +123,7 @@
/**
* Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
*/
- private static final int INVALID_POINTER = -1;
- private static final AnimatableProperty SIDE_PADDINGS = AnimatableProperty.from(
- "sidePaddings",
- NotificationStackScrollLayout::setCurrentSidePadding,
- NotificationStackScrollLayout::getCurrentSidePadding,
- R.id.side_padding_animator_tag,
- R.id.side_padding_animator_end_tag,
- R.id.side_padding_animator_start_tag);
- private static final AnimationProperties SIDE_PADDING_PROPERTIES =
- new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ private static final int INVALID_POINTER = -1;;
private ExpandHelper mExpandHelper;
private NotificationSwipeHelper mSwipeHelper;
@@ -143,7 +131,6 @@
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
private final Path mBackgroundPath = new Path();
- private final float[] mBackgroundRadii = new float[8];
private final boolean mShouldDrawNotificationBackground;
private float mExpandedHeight;
@@ -174,7 +161,6 @@
private int mTopPadding;
private int mBottomMargin;
private int mBottomInset = 0;
- private float mCurrentSidePadding;
/**
* The algorithm which calculates the properties for our children
@@ -402,7 +388,6 @@
private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
private Runnable mAnimateScroll = this::animateScroll;
private int mCornerRadius;
- private int mLockscreenSidePaddings;
private int mSidePaddings;
public NotificationStackScrollLayout(Context context) {
@@ -440,8 +425,7 @@
res.getBoolean(R.bool.config_fadeNotificationsOnDismiss);
updateWillNotDraw();
- mBackgroundPaint.setAntiAlias(true);
- mBackgroundPaint.setStyle(Paint.Style.FILL);
+ mBackgroundPaint.setAntiAlias(true);;
if (DEBUG) {
mDebugPaint = new Paint();
mDebugPaint.setColor(0xffff0000);
@@ -490,7 +474,8 @@
protected void onDraw(Canvas canvas) {
if (mShouldDrawNotificationBackground && !mAmbientState.isDark()
&& mCurrentBounds.top < mCurrentBounds.bottom) {
- canvas.drawPath(mBackgroundPath, mBackgroundPaint);
+ canvas.drawRoundRect(mSidePaddings, mCurrentBounds.top, getWidth() - mSidePaddings,
+ mCurrentBounds.bottom, mCornerRadius, mCornerRadius, mBackgroundPaint);
}
if (DEBUG) {
@@ -543,8 +528,7 @@
R.dimen.min_top_overscroll_to_qs);
mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
- mLockscreenSidePaddings = res.getDimensionPixelSize(
- R.dimen.notification_lockscreen_side_paddings);
+ mSidePaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
mMinInteractionHeight = res.getDimensionPixelSize(
R.dimen.notification_min_interaction_height);
mCornerRadius = res.getDimensionPixelSize(
@@ -575,11 +559,15 @@
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int childWidthSpec = MeasureSpec.makeMeasureSpec(width - mSidePaddings * 2,
+ MeasureSpec.getMode(widthMeasureSpec));
// We need to measure all children even the GONE ones, such that the heights are calculated
// correctly as they are used to calculate how many we can fit on the screen.
final int size = getChildCount();
for (int i = 0; i < size; i++) {
- measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
+ measureChild(getChildAt(i), childWidthSpec, heightMeasureSpec);
}
}
@@ -675,11 +663,32 @@
private void onPreDrawDuringAnimation() {
mShelf.updateAppearance();
+ updateClippingToTopRoundedCorner();
if (!mNeedsAnimation && !mChildrenUpdateRequested) {
updateBackground();
}
}
+ private void updateClippingToTopRoundedCorner() {
+ Float clipStart = (float) mTopPadding;
+ Float clipEnd = clipStart + mCornerRadius;
+ boolean first = true;
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+ float start = child.getTranslationY();
+ float end = start + Math.max(child.getActualHeight() - child.getClipBottomAmount(),
+ 0);
+ boolean clip = clipStart > start && clipStart < end
+ || clipEnd >= start && clipEnd <= end;
+ clip &= !(first && mOwnScrollY == 0);
+ child.setDistanceToTopRoundness(clip ? Math.max(start - clipStart, 0) : -1);
+ first = false;
+ }
+ }
+
private void updateScrollStateForAddedChildren() {
if (mChildrenToAddAnimated.isEmpty()) {
return;
@@ -2255,31 +2264,9 @@
mScrimController.setExcludedBackgroundArea(
mFadingOut || mParentNotFullyVisible || mAmbientState.isDark() || mIsClipped ? null
: mCurrentBounds);
- updateBackgroundPath();
invalidate();
}
- private void updateBackgroundPath() {
- mBackgroundPath.reset();
- float topRoundness = 0;
- if (mFirstVisibleBackgroundChild != null) {
- topRoundness = mFirstVisibleBackgroundChild.getCurrentBackgroundRadiusTop();
- }
- topRoundness = onKeyguard() ? mCornerRadius : topRoundness;
- float bottomRoundNess = mCornerRadius;
- mBackgroundRadii[0] = topRoundness;
- mBackgroundRadii[1] = topRoundness;
- mBackgroundRadii[2] = topRoundness;
- mBackgroundRadii[3] = topRoundness;
- mBackgroundRadii[4] = bottomRoundNess;
- mBackgroundRadii[5] = bottomRoundNess;
- mBackgroundRadii[6] = bottomRoundNess;
- mBackgroundRadii[7] = bottomRoundNess;
- mBackgroundPath.addRoundRect(mCurrentSidePadding, mCurrentBounds.top,
- getWidth() - mCurrentSidePadding, mCurrentBounds.bottom, mBackgroundRadii,
- Path.Direction.CCW);
- }
-
/**
* Update the background bounds to the new desired bounds
*/
@@ -2292,8 +2279,8 @@
mBackgroundBounds.left = mTempInt2[0];
mBackgroundBounds.right = mTempInt2[0] + getWidth();
}
- mBackgroundBounds.left += mCurrentSidePadding;
- mBackgroundBounds.right -= mCurrentSidePadding;
+ mBackgroundBounds.left += mSidePaddings;
+ mBackgroundBounds.right -= mSidePaddings;
if (!mIsExpanded) {
mBackgroundBounds.top = 0;
mBackgroundBounds.bottom = 0;
@@ -2902,8 +2889,7 @@
private void applyRoundedNess() {
if (mFirstVisibleBackgroundChild != null) {
- mFirstVisibleBackgroundChild.setTopRoundness(
- mStatusBarState == StatusBarState.KEYGUARD ? 1.0f : 0.0f,
+ mFirstVisibleBackgroundChild.setTopRoundness(1.0f,
mFirstVisibleBackgroundChild.isShown()
&& !mChildrenToAddAnimated.contains(mFirstVisibleBackgroundChild));
}
@@ -2912,7 +2898,6 @@
mLastVisibleBackgroundChild.isShown()
&& !mChildrenToAddAnimated.contains(mLastVisibleBackgroundChild));
}
- updateBackgroundPath();
invalidate();
}
@@ -2922,7 +2907,6 @@
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
updateChronometerForChild(child);
- updateCurrentSidePaddings(child);
}
private void updateHideSensitiveForChild(View child) {
@@ -3021,6 +3005,7 @@
mAnimationEvents.clear();
updateBackground();
updateViewShadows();
+ updateClippingToTopRoundedCorner();
} else {
applyCurrentState();
}
@@ -3714,6 +3699,7 @@
setAnimationRunning(false);
updateBackground();
updateViewShadows();
+ updateClippingToTopRoundedCorner();
}
private void updateViewShadows() {
@@ -4382,43 +4368,6 @@
public void setStatusBarState(int statusBarState) {
mStatusBarState = statusBarState;
mAmbientState.setStatusBarState(statusBarState);
- applyRoundedNess();
- updateSidePaddings();
- }
-
- private void updateSidePaddings() {
- int sidePaddings = mStatusBarState == StatusBarState.KEYGUARD ? mLockscreenSidePaddings : 0;
- if (sidePaddings != mSidePaddings) {
- boolean animate = isShown();
- mSidePaddings = sidePaddings;
- PropertyAnimator.setProperty(this, SIDE_PADDINGS, sidePaddings,
- SIDE_PADDING_PROPERTIES, animate);
- }
- }
-
- protected void setCurrentSidePadding(float sidePadding) {
- mCurrentSidePadding = sidePadding;
- updateBackground();
- applySidePaddingsToChildren();
- }
-
- private void applySidePaddingsToChildren() {
- for (int i = 0; i < getChildCount(); i++) {
- View view = getChildAt(i);
- updateCurrentSidePaddings(view);
- }
- }
-
- private void updateCurrentSidePaddings(View view) {
- if (!(view instanceof ExpandableOutlineView)) {
- return;
- }
- ExpandableOutlineView outlineView = (ExpandableOutlineView) view;
- outlineView.setCurrentSidePaddings(mCurrentSidePadding);
- }
-
- protected float getCurrentSidePadding() {
- return mCurrentSidePadding;
}
public void setExpandingVelocity(float expandingVelocity) {
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index a30e0639..fd9ffb2 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -278,7 +278,7 @@
// VisibleForTesting
public static String[] getExtraPeople(Bundle extras) {
- Object people = extras.get(Notification.EXTRA_PEOPLE);
+ Object people = extras.get(Notification.EXTRA_PEOPLE_LIST);
if (people instanceof String[]) {
return (String[]) people;
}
@@ -305,6 +305,16 @@
return array;
}
+ if (arrayList.get(0) instanceof Notification.Person) {
+ ArrayList<Notification.Person> list = (ArrayList<Notification.Person>) arrayList;
+ final int N = list.size();
+ String[] array = new String[N];
+ for (int i = 0; i < N; i++) {
+ array[i] = list.get(i).resolveToLegacyUri();
+ }
+ return array;
+ }
+
return null;
}
@@ -459,7 +469,9 @@
lookupResult = searchContacts(mContext, uri);
} else {
lookupResult = new LookupResult(); // invalid person for the cache
- Slog.w(TAG, "unsupported URI " + handle);
+ if (!"name".equals(uri.getScheme())) {
+ Slog.w(TAG, "unsupported URI " + handle);
+ }
}
if (lookupResult != null) {
synchronized (mPeopleCache) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
index 58f0ded..a60d715 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java
@@ -47,7 +47,7 @@
public void testSingleString() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putString(Notification.EXTRA_PEOPLE, expected[0]);
+ bundle.putString(Notification.EXTRA_PEOPLE_LIST, expected[0]);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("string should be in result[0]", expected, result);
}
@@ -56,7 +56,7 @@
public void testSingleCharArray() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putCharArray(Notification.EXTRA_PEOPLE, expected[0].toCharArray());
+ bundle.putCharArray(Notification.EXTRA_PEOPLE_LIST, expected[0].toCharArray());
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("char[] should be in result[0]", expected, result);
}
@@ -65,7 +65,7 @@
public void testSingleCharSequence() throws Exception {
String[] expected = { "foobar" };
Bundle bundle = new Bundle();
- bundle.putCharSequence(Notification.EXTRA_PEOPLE, new SpannableString(expected[0]));
+ bundle.putCharSequence(Notification.EXTRA_PEOPLE_LIST, new SpannableString(expected[0]));
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("charSequence should be in result[0]", expected, result);
}
@@ -74,7 +74,7 @@
public void testStringArraySingle() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foobar" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("wrapped string should be in result[0]", expected, result);
}
@@ -83,7 +83,7 @@
public void testStringArrayMultiple() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foo", "bar", "baz" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayMultiple", expected, result);
}
@@ -92,7 +92,7 @@
public void testStringArrayNulls() throws Exception {
Bundle bundle = new Bundle();
String[] expected = { "foo", null, "baz" };
- bundle.putStringArray(Notification.EXTRA_PEOPLE, expected);
+ bundle.putStringArray(Notification.EXTRA_PEOPLE_LIST, expected);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayNulls", expected, result);
}
@@ -105,7 +105,7 @@
for (int i = 0; i < expected.length; i++) {
charSeqArray[i] = new SpannableString(expected[i]);
}
- bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
+ bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testCharSequenceArrayMultiple", expected, result);
}
@@ -122,7 +122,7 @@
charSeqArray[i] = new SpannableString(expected[i]);
}
}
- bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE, charSeqArray);
+ bundle.putCharSequenceArray(Notification.EXTRA_PEOPLE_LIST, charSeqArray);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testMixedCharSequenceArrayList", expected, result);
}
@@ -135,7 +135,7 @@
for (int i = 0; i < expected.length; i++) {
stringArrayList.add(expected[i]);
}
- bundle.putStringArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
+ bundle.putStringArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testStringArrayList", expected, result);
}
@@ -149,11 +149,24 @@
for (int i = 0; i < expected.length; i++) {
stringArrayList.add(new SpannableString(expected[i]));
}
- bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE, stringArrayList);
+ bundle.putCharSequenceArrayList(Notification.EXTRA_PEOPLE_LIST, stringArrayList);
String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
assertStringArrayEquals("testCharSequenceArrayList", expected, result);
}
+ @Test
+ public void testPeopleArrayList() throws Exception {
+ Bundle bundle = new Bundle();
+ String[] expected = { "name:test" , "tel:1234" };
+ final ArrayList<Notification.Person> arrayList =
+ new ArrayList<>(expected.length);
+ arrayList.add(new Notification.Person().setName("test"));
+ arrayList.add(new Notification.Person().setUri(expected[1]));
+ bundle.putParcelableArrayList(Notification.EXTRA_PEOPLE_LIST, arrayList);
+ String[] result = ValidateNotificationPeople.getExtraPeople(bundle);
+ assertStringArrayEquals("testPeopleArrayList", expected, result);
+ }
+
private void assertStringArrayEquals(String message, String[] expected, String[] result) {
String expectedString = Arrays.toString(expected);
String resultString = Arrays.toString(result);