Merge "Fixed a flicker of group notifications" into oc-dev

am: beba1bf936

Change-Id: I22d44dde99093cbcf10ca8cddb3beccfdc9bdafb
This commit is contained in:
Selim Cinek
2017-06-07 21:03:12 +00:00
committed by android-build-merger
5 changed files with 122 additions and 23 deletions

View File

@@ -146,12 +146,12 @@ public class NotificationData {
// Construct the icon. // Construct the icon.
icon = new StatusBarIconView(context, icon = new StatusBarIconView(context,
sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n); sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
// Construct the expanded icon. // Construct the expanded icon.
expandedIcon = new StatusBarIconView(context, expandedIcon = new StatusBarIconView(context,
sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n); sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
final StatusBarIcon ic = new StatusBarIcon( final StatusBarIcon ic = new StatusBarIcon(
sbn.getUser(), sbn.getUser(),
@@ -187,9 +187,11 @@ public class NotificationData {
* @param n the notification to read the icon from. * @param n the notification to read the icon from.
* @throws InflationException * @throws InflationException
*/ */
public void updateIcons(Context context, Notification n) throws InflationException { public void updateIcons(Context context, StatusBarNotification sbn)
throws InflationException {
if (icon != null) { if (icon != null) {
// Update the icon // Update the icon
Notification n = sbn.getNotification();
final StatusBarIcon ic = new StatusBarIcon( final StatusBarIcon ic = new StatusBarIcon(
notification.getUser(), notification.getUser(),
notification.getPackageName(), notification.getPackageName(),
@@ -197,8 +199,8 @@ public class NotificationData {
n.iconLevel, n.iconLevel,
n.number, n.number,
StatusBarIconView.contentDescForNotification(context, n)); StatusBarIconView.contentDescForNotification(context, n));
icon.setNotification(n); icon.setNotification(sbn);
expandedIcon.setNotification(n); expandedIcon.setNotification(sbn);
if (!icon.set(ic) || !expandedIcon.set(ic)) { if (!icon.set(ic) || !expandedIcon.set(ic)) {
throw new InflationException("Couldn't update icon: " + ic); throw new InflationException("Couldn't update icon: " + ic);
} }

View File

@@ -34,6 +34,7 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.os.Parcelable; import android.os.Parcelable;
import android.os.UserHandle; import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.FloatProperty; import android.util.FloatProperty;
@@ -99,7 +100,7 @@ public class StatusBarIconView extends AnimatedImageView {
private int mNumberX; private int mNumberX;
private int mNumberY; private int mNumberY;
private String mNumberText; private String mNumberText;
private Notification mNotification; private StatusBarNotification mNotification;
private final boolean mBlocked; private final boolean mBlocked;
private int mDensity; private int mDensity;
private float mIconScale = 1.0f; private float mIconScale = 1.0f;
@@ -127,11 +128,11 @@ public class StatusBarIconView extends AnimatedImageView {
}; };
private final NotificationIconDozeHelper mDozer; private final NotificationIconDozeHelper mDozer;
public StatusBarIconView(Context context, String slot, Notification notification) { public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
this(context, slot, notification, false); this(context, slot, sbn, false);
} }
public StatusBarIconView(Context context, String slot, Notification notification, public StatusBarIconView(Context context, String slot, StatusBarNotification sbn,
boolean blocked) { boolean blocked) {
super(context); super(context);
mDozer = new NotificationIconDozeHelper(context); mDozer = new NotificationIconDozeHelper(context);
@@ -141,7 +142,7 @@ public class StatusBarIconView extends AnimatedImageView {
mNumberPain.setTextAlign(Paint.Align.CENTER); mNumberPain.setTextAlign(Paint.Align.CENTER);
mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color)); mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
mNumberPain.setAntiAlias(true); mNumberPain.setAntiAlias(true);
setNotification(notification); setNotification(sbn);
maybeUpdateIconScaleDimens(); maybeUpdateIconScaleDimens();
setScaleType(ScaleType.CENTER); setScaleType(ScaleType.CENTER);
mDensity = context.getResources().getDisplayMetrics().densityDpi; mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -207,9 +208,11 @@ public class StatusBarIconView extends AnimatedImageView {
} }
} }
public void setNotification(Notification notification) { public void setNotification(StatusBarNotification notification) {
mNotification = notification; mNotification = notification;
setContentDescription(notification); if (notification != null) {
setContentDescription(notification.getNotification());
}
} }
public StatusBarIconView(Context context, AttributeSet attrs) { public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -315,6 +318,10 @@ public class StatusBarIconView extends AnimatedImageView {
return true; return true;
} }
public Icon getSourceIcon() {
return mIcon.icon;
}
private Drawable getIcon(StatusBarIcon icon) { private Drawable getIcon(StatusBarIcon icon) {
return getIcon(getContext(), icon); return getIcon(getContext(), icon);
} }
@@ -354,7 +361,7 @@ public class StatusBarIconView extends AnimatedImageView {
public void onInitializeAccessibilityEvent(AccessibilityEvent event) { public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event); super.onInitializeAccessibilityEvent(event);
if (mNotification != null) { if (mNotification != null) {
event.setParcelableData(mNotification); event.setParcelableData(mNotification.getNotification());
} }
} }
@@ -456,6 +463,10 @@ public class StatusBarIconView extends AnimatedImageView {
+ " notification=" + mNotification + ")"; + " notification=" + mNotification + ")";
} }
public StatusBarNotification getNotification() {
return mNotification;
}
public String getSlot() { public String getSlot() {
return mSlot; return mSlot;
} }

View File

@@ -4,11 +4,15 @@ import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Icon;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.ArraySet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.NotificationColorUtil; import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -180,14 +184,54 @@ public class NotificationIconAreaController implements DarkReceiver {
} }
} }
// In case we are changing the suppression of a group, the replacement shouldn't flicker
// and it should just be replaced instead. We therefore look for notifications that were
// just replaced by the child or vice-versa to suppress this.
ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
ArrayList<View> toRemove = new ArrayList<>(); ArrayList<View> toRemove = new ArrayList<>();
for (int i = 0; i < hostLayout.getChildCount(); i++) { for (int i = 0; i < hostLayout.getChildCount(); i++) {
View child = hostLayout.getChildAt(i); View child = hostLayout.getChildAt(i);
if (!(child instanceof StatusBarIconView)) {
continue;
}
if (!toShow.contains(child)) { if (!toShow.contains(child)) {
toRemove.add(child); boolean iconWasReplaced = false;
StatusBarIconView removedIcon = (StatusBarIconView) child;
String removedGroupKey = removedIcon.getNotification().getGroupKey();
for (int j = 0; j < toShow.size(); j++) {
StatusBarIconView candidate = toShow.get(j);
if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
&& candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
if (!iconWasReplaced) {
iconWasReplaced = true;
} else {
iconWasReplaced = false;
break;
}
}
}
if (iconWasReplaced) {
ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
if (statusBarIcons == null) {
statusBarIcons = new ArrayList<>();
replacingIcons.put(removedGroupKey, statusBarIcons);
}
statusBarIcons.add(removedIcon.getStatusBarIcon());
}
toRemove.add(removedIcon);
} }
} }
// removing all duplicates
ArrayList<String> duplicates = new ArrayList<>();
for (String key : replacingIcons.keySet()) {
ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
if (statusBarIcons.size() != 1) {
duplicates.add(key);
}
}
replacingIcons.removeAll(duplicates);
hostLayout.setReplacingIcons(replacingIcons);
final int toRemoveCount = toRemove.size(); final int toRemoveCount = toRemove.size();
for (int i = 0; i < toRemoveCount; i++) { for (int i = 0; i < toRemoveCount; i++) {
@@ -217,6 +261,7 @@ public class NotificationIconAreaController implements DarkReceiver {
hostLayout.addView(expected, i); hostLayout.addView(expected, i);
} }
hostLayout.setChangingViewPositions(false); hostLayout.setChangingViewPositions(false);
hostLayout.setReplacingIcons(null);
} }
/** /**

View File

@@ -21,9 +21,13 @@ import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.drawable.Icon;
import android.support.v4.util.ArrayMap;
import android.support.v4.util.ArraySet;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Interpolators; import com.android.systemui.Interpolators;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.statusbar.AlphaOptimizedFrameLayout; import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -33,6 +37,7 @@ import com.android.systemui.statusbar.stack.AnimationProperties;
import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.statusbar.stack.StackStateAnimator;
import com.android.systemui.statusbar.stack.ViewState; import com.android.systemui.statusbar.stack.ViewState;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
/** /**
@@ -117,6 +122,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
private float mVisualOverflowAdaption; private float mVisualOverflowAdaption;
private boolean mDisallowNextAnimation; private boolean mDisallowNextAnimation;
private boolean mAnimationsEnabled = true; private boolean mAnimationsEnabled = true;
private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
public NotificationIconContainer(Context context, AttributeSet attrs) { public NotificationIconContainer(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
@@ -183,11 +189,17 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
@Override @Override
public void onViewAdded(View child) { public void onViewAdded(View child) {
super.onViewAdded(child); super.onViewAdded(child);
boolean isReplacingIcon = isReplacingIcon(child);
if (!mChangingViewPositions) { if (!mChangingViewPositions) {
mIconStates.put(child, new IconState()); IconState v = new IconState();
if (isReplacingIcon) {
v.justAdded = false;
v.justReplaced = true;
}
mIconStates.put(child, v);
} }
int childIndex = indexOfChild(child); int childIndex = indexOfChild(child);
if (childIndex < getChildCount() - 1 if (childIndex < getChildCount() - 1 && !isReplacingIcon
&& mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) { && mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
if (mAddAnimationStartIndex < 0) { if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = childIndex; mAddAnimationStartIndex = childIndex;
@@ -200,13 +212,34 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
} }
} }
private boolean isReplacingIcon(View child) {
if (mReplacingIcons == null) {
return false;
}
if (!(child instanceof StatusBarIconView)) {
return false;
}
StatusBarIconView iconView = (StatusBarIconView) child;
Icon sourceIcon = iconView.getSourceIcon();
String groupKey = iconView.getNotification().getGroupKey();
ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
if (statusBarIcons != null) {
StatusBarIcon replacedIcon = statusBarIcons.get(0);
if (sourceIcon.sameAs(replacedIcon.icon)) {
return true;
}
}
return false;
}
@Override @Override
public void onViewRemoved(View child) { public void onViewRemoved(View child) {
super.onViewRemoved(child); super.onViewRemoved(child);
if (child instanceof StatusBarIconView) { if (child instanceof StatusBarIconView) {
boolean isReplacingIcon = isReplacingIcon(child);
final StatusBarIconView icon = (StatusBarIconView) child; final StatusBarIconView icon = (StatusBarIconView) child;
if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
&& child.getVisibility() == VISIBLE) { && child.getVisibility() == VISIBLE && isReplacingIcon) {
int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX()); int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
if (mAddAnimationStartIndex < 0) { if (mAddAnimationStartIndex < 0) {
mAddAnimationStartIndex = animationStartIndex; mAddAnimationStartIndex = animationStartIndex;
@@ -216,9 +249,11 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
} }
if (!mChangingViewPositions) { if (!mChangingViewPositions) {
mIconStates.remove(child); mIconStates.remove(child);
addTransientView(icon, 0); if (!isReplacingIcon) {
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */, addTransientView(icon, 0);
() -> removeTransientView(icon)); icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
() -> removeTransientView(icon));
}
} }
} }
} }
@@ -473,11 +508,16 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
mAnimationsEnabled = enabled; mAnimationsEnabled = enabled;
} }
public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
mReplacingIcons = replacingIcons;
}
public class IconState extends ViewState { public class IconState extends ViewState {
public float iconAppearAmount = 1.0f; public float iconAppearAmount = 1.0f;
public float clampedAppearAmount = 1.0f; public float clampedAppearAmount = 1.0f;
public int visibleState; public int visibleState;
public boolean justAdded = true; public boolean justAdded = true;
private boolean justReplaced;
public boolean needsCannedAnimation; public boolean needsCannedAnimation;
public boolean useFullTransitionAmount; public boolean useFullTransitionAmount;
public boolean useLinearTransitionAmount; public boolean useLinearTransitionAmount;
@@ -496,9 +536,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
&& !mDisallowNextAnimation && !mDisallowNextAnimation
&& !noAnimations; && !noAnimations;
if (animationsAllowed) { if (animationsAllowed) {
if (justAdded) { if (justAdded || justReplaced) {
super.applyToView(icon); super.applyToView(icon);
if (iconAppearAmount != 0.0f) { if (justAdded && iconAppearAmount != 0.0f) {
icon.setAlpha(0.0f); icon.setAlpha(0.0f);
icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
false /* animate */); false /* animate */);
@@ -557,6 +597,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
} }
} }
justAdded = false; justAdded = false;
justReplaced = false;
needsCannedAnimation = false; needsCannedAnimation = false;
justUndarkened = false; justUndarkened = false;
} }

View File

@@ -6976,7 +6976,7 @@ public class StatusBar extends SystemUI implements DemoMode,
entry.notification = notification; entry.notification = notification;
mGroupManager.onEntryUpdated(entry, oldNotification); mGroupManager.onEntryUpdated(entry, oldNotification);
entry.updateIcons(mContext, n); entry.updateIcons(mContext, notification);
inflateViews(entry, mStackScroller); inflateViews(entry, mStackScroller);
mForegroundServiceController.updateNotification(notification, mForegroundServiceController.updateNotification(notification,