diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index fa6995ad44e42..39f8e190aeab0 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -184,6 +184,11 @@ public class Notification implements Parcelable */ public long when; + /** + * The creation time of the notification + */ + private long creationTime; + /** * The resource id of a drawable to use as the icon in the status bar. * @@ -1479,6 +1484,7 @@ public class Notification implements Parcelable public Notification() { this.when = System.currentTimeMillis(); + this.creationTime = System.currentTimeMillis(); this.priority = PRIORITY_DEFAULT; } @@ -1516,6 +1522,7 @@ public class Notification implements Parcelable this.icon = icon; this.tickerText = tickerText; this.when = when; + this.creationTime = System.currentTimeMillis(); } /** @@ -1526,6 +1533,7 @@ public class Notification implements Parcelable int version = parcel.readInt(); when = parcel.readLong(); + creationTime = parcel.readLong(); if (parcel.readInt() != 0) { mSmallIcon = Icon.CREATOR.createFromParcel(parcel); if (mSmallIcon.getType() == Icon.TYPE_RESOURCE) { @@ -1614,6 +1622,7 @@ public class Notification implements Parcelable */ public void cloneInto(Notification that, boolean heavy) { that.when = this.when; + that.creationTime = this.creationTime; that.mSmallIcon = this.mSmallIcon; that.number = this.number; @@ -1794,6 +1803,7 @@ public class Notification implements Parcelable parcel.writeInt(1); parcel.writeLong(when); + parcel.writeLong(creationTime); if (mSmallIcon == null && icon != 0) { // you snuck an icon in here without using the builder; let's try to keep it mSmallIcon = Icon.createWithResource("", icon); @@ -3129,6 +3139,7 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.header_text, View.GONE); contentView.setViewVisibility(R.id.header_text_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); contentView.setViewVisibility(R.id.profile_badge, View.GONE); } @@ -3264,6 +3275,10 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.time, View.VISIBLE); contentView.setLong(R.id.time, "setTime", mN.when); } + } else { + // We still want a time to be set but gone, such that we can show and hide it + // on demand in case it's a child notification without anything in the header + contentView.setLong(R.id.time, "setTime", mN.when != 0 ? mN.when : mN.creationTime); } } @@ -3331,7 +3346,7 @@ public class Notification implements Parcelable * otherwise */ private boolean showsTimeOrChronometer() { - return mN.when != 0 && mN.extras.getBoolean(EXTRA_SHOW_WHEN); + return mN.showsTimeOrChronometer(); } private void resetStandardTemplateWithActions(RemoteViews big) { @@ -3693,6 +3708,8 @@ public class Notification implements Parcelable mN.extras = getAllExtras(); } + mN.creationTime = System.currentTimeMillis(); + // lazy stuff from mContext; see comment in Builder(Context, Notification) Notification.addFieldsFromContext(mContext, mN); @@ -3825,6 +3842,15 @@ public class Notification implements Parcelable } } + /** + * @return true if the notification will show the time or the chronometer; false + * otherwise + * @hide + */ + public boolean showsTimeOrChronometer() { + return when != 0 && extras.getBoolean(EXTRA_SHOW_WHEN); + } + /** * An object that can apply a rich notification style to a {@link Notification.Builder} * object. diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java index 39eba7d3d7063..d2ee86622e082 100644 --- a/core/java/android/widget/DateTimeView.java +++ b/core/java/android/widget/DateTimeView.java @@ -131,8 +131,18 @@ public class DateTimeView extends TextView { update(); } + @Override + @android.view.RemotableViewMethod + public void setVisibility(@Visibility int visibility) { + boolean gotVisible = visibility != GONE && getVisibility() == GONE; + super.setVisibility(visibility); + if (gotVisible) { + update(); + } + } + void update() { - if (mTime == null) { + if (mTime == null || getVisibility() == GONE) { return; } if (mShowRelativeTime) { diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml index 992e88e22ad9f..d16dcc6b906ce 100644 --- a/core/res/res/layout/notification_template_header.xml +++ b/core/res/res/layout/notification_template_header.xml @@ -69,15 +69,17 @@ android:text="@string/notification_header_divider_symbol" android:singleLine="true" android:visibility="gone"/> - + android:showRelative="true" + android:singleLine="true" + android:visibility="gone" /> - - - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java index 06d79a7f91248..3363993dd2894 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java @@ -65,12 +65,7 @@ public class NotificationHeaderUtil { ImageView expand = (ImageView) view.findViewById( com.android.internal.R.id.expand_button); applyToChild(icon, apply, header.getOriginalIconColor()); - int color = header.getOriginalNotificationColor(); - if (color == Notification.COLOR_DEFAULT) { - color = view.getContext().getColor( - com.android.internal.R.color.notification_icon_default_color); - } - applyToChild(expand, apply, color); + applyToChild(expand, apply, header.getOriginalNotificationColor()); } private void applyToChild(View view, boolean shouldApply, int originalColor) { @@ -116,7 +111,7 @@ public class NotificationHeaderUtil { @Override public boolean compare(View parent, View child, Object parentData, Object childData) { - return parent.getVisibility() == View.VISIBLE; + return parent.getVisibility() != View.GONE; } @Override @@ -161,11 +156,11 @@ public class NotificationHeaderUtil { mComparators.get(compI).apply(row); } // We need to sanitize the dividers since they might be off-balance now - sanitizeDividers(row); + sanitizeHeaderViews(row); } } - private void sanitizeDividers(ExpandableNotificationRow row) { + private void sanitizeHeaderViews(ExpandableNotificationRow row) { if (row.isSummaryWithChildren()) { sanitizeHeader(row.getNotificationHeader()); return; @@ -188,9 +183,26 @@ public class NotificationHeaderUtil { if (rowHeader == null) { return; } + final int childCount = rowHeader.getChildCount(); + View time = rowHeader.findViewById(com.android.internal.R.id.time); + boolean hasVisibleText = false; + for (int i = 1; i < childCount - 1 ; i++) { + View child = rowHeader.getChildAt(i); + if (child instanceof TextView + && child.getVisibility() != View.GONE + && !mDividers.contains(Integer.valueOf(child.getId())) + && child != time) { + hasVisibleText = true; + break; + } + } + // in case no view is visible we make sure the time is visible + int timeVisibility = !hasVisibleText + || mRow.getStatusBarNotification().getNotification().showsTimeOrChronometer() + ? View.VISIBLE : View.GONE; + time.setVisibility(timeVisibility); View left = null; View right; - final int childCount = rowHeader.getChildCount(); for (int i = 1; i < childCount - 1 ; i++) { View child = rowHeader.getChildAt(i); if (mDividers.contains(Integer.valueOf(child.getId()))) { @@ -202,14 +214,14 @@ public class NotificationHeaderUtil { // A divider was found, this needs to be hidden i--; break; - } else if (right.getVisibility() == View.VISIBLE) { + } else if (right.getVisibility() != View.GONE && right instanceof TextView) { visible = left != null; left = right; break; } } child.setVisibility(visible ? View.VISIBLE : View.GONE); - } else if (child.getVisibility() == View.VISIBLE) { + } else if (child.getVisibility() != View.GONE && child instanceof TextView) { left = child; } } @@ -219,7 +231,7 @@ public class NotificationHeaderUtil { for (int compI = 0; compI < mComparators.size(); compI++) { mComparators.get(compI).apply(row, true /* reset */); } - sanitizeDividers(row); + sanitizeHeaderViews(row); } private static class HeaderProcessor {