Fixed a bug where notification header could become empty
Also fixed a few more issues with the header util that could
lead to wrong states.
Change-Id: I95c3479f5d9e5221ee9e91120271e7957b887607
Fixes: 28295743
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index fa6995a..39f8e19 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -185,6 +185,11 @@
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.
*
* @deprecated Use {@link Builder#setSmallIcon(Icon)} instead.
@@ -1479,6 +1484,7 @@
public Notification()
{
this.when = System.currentTimeMillis();
+ this.creationTime = System.currentTimeMillis();
this.priority = PRIORITY_DEFAULT;
}
@@ -1516,6 +1522,7 @@
this.icon = icon;
this.tickerText = tickerText;
this.when = when;
+ this.creationTime = System.currentTimeMillis();
}
/**
@@ -1526,6 +1533,7 @@
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 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 @@
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 @@
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 @@
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 @@
* 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 @@
mN.extras = getAllExtras();
}
+ mN.creationTime = System.currentTimeMillis();
+
// lazy stuff from mContext; see comment in Builder(Context, Notification)
Notification.addFieldsFromContext(mContext, mN);
@@ -3826,6 +3843,15 @@
}
/**
+ * @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 39eba7d..d2ee866 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -131,8 +131,18 @@
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 992e88e..d16dcc6 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"/>
- <ViewStub
+ <DateTimeView
android:id="@+id/time"
+ android:textAppearance="@style/TextAppearance.Material.Notification.Time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
- android:layout="@layout/notification_template_part_time"
- android:visibility="gone"
- />
+ android:showRelative="true"
+ android:singleLine="true"
+ android:visibility="gone" />
<ViewStub
android:id="@+id/chronometer"
android:layout_width="wrap_content"
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
deleted file mode 100644
index e53f378..0000000
--- a/core/res/res/layout/notification_template_part_time.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<DateTimeView android:id="@+id/time" xmlns:android="http://schemas.android.com/apk/res/android"
- android:textAppearance="@style/TextAppearance.Material.Notification.Time"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginEnd="4dp"
- android:layout_weight="0"
- android:showRelative="true"
- android:singleLine="true"
- />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java
index 06d79a7..3363993 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 @@
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 @@
@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 @@
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 @@
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 @@
// 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 @@
for (int compI = 0; compI < mComparators.size(); compI++) {
mComparators.get(compI).apply(row, true /* reset */);
}
- sanitizeDividers(row);
+ sanitizeHeaderViews(row);
}
private static class HeaderProcessor {