Fix heads up views freeing too early.
In the previous CL, heads up views were freed while they were still animating away. As a result, there could be a sudden shift in the view the notification uses (most easily reproducible if you tap on a HUN with actions as the actions disappear). This CL introduces an API to set a a listener for when the content view becomes inactive and remove it then. Bug: 111809944 Test: runtest systemui, manual (HUN with full screen intent, tap, see that it goes away without visual jank) Change-Id: Ib27bcf993f6be41aa4fde50b39817004610f5fd4
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_AMBIENT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
@@ -85,6 +87,7 @@ public final class AmbientPulseManager extends AlertingNotificationManager {
|
||||
for (OnAmbientChangedListener listener : mListeners) {
|
||||
listener.onAmbientStateChanged(entry, false);
|
||||
}
|
||||
entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,9 +19,9 @@ import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENAB
|
||||
import static com.android.systemui.statusbar.NotificationRemoteInputManager
|
||||
.FORCE_REMOTE_INPUT_HISTORY;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_AMBIENT_VIEW;
|
||||
.FLAG_CONTENT_VIEW_AMBIENT;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_HEADS_UP_VIEW;
|
||||
.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
@@ -458,7 +458,7 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
|
||||
*/
|
||||
private void showAlertingView(NotificationData.Entry entry,
|
||||
@InflationFlag int inflatedFlags) {
|
||||
if ((inflatedFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
|
||||
if ((inflatedFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
|
||||
// Possible for shouldHeadsUp to change between the inflation starting and ending.
|
||||
// If it does and we no longer need to heads up, we should free the view.
|
||||
if (shouldHeadsUp(entry)) {
|
||||
@@ -466,14 +466,14 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
|
||||
// Mark as seen immediately
|
||||
setNotificationShown(entry.notification);
|
||||
} else {
|
||||
entry.row.updateInflationFlag(FLAG_REINFLATE_HEADS_UP_VIEW, false);
|
||||
entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
|
||||
}
|
||||
}
|
||||
if ((inflatedFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
|
||||
if ((inflatedFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
|
||||
if (shouldPulse(entry)) {
|
||||
mAmbientPulseManager.showNotification(entry);
|
||||
} else {
|
||||
entry.row.updateInflationFlag(FLAG_REINFLATE_AMBIENT_VIEW, false);
|
||||
entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_AMBIENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -666,8 +666,8 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
|
||||
row.setSmartActions(entry.smartActions);
|
||||
row.setEntry(entry);
|
||||
|
||||
row.updateInflationFlag(FLAG_REINFLATE_HEADS_UP_VIEW, shouldHeadsUp(entry));
|
||||
row.updateInflationFlag(FLAG_REINFLATE_AMBIENT_VIEW, shouldPulse(entry));
|
||||
row.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP, shouldHeadsUp(entry));
|
||||
row.updateInflationFlag(FLAG_CONTENT_VIEW_AMBIENT, shouldPulse(entry));
|
||||
row.inflateViews();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_AMBIENT_VIEW;
|
||||
.FLAG_CONTENT_VIEW_AMBIENT;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_HEADS_UP_VIEW;
|
||||
.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.InflationCallback;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -453,6 +455,33 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
mNotificationInflater.inflateNotificationViews();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a content view as freeable, setting it so that future inflations do not reinflate
|
||||
* and ensuring that the view is freed when it is safe to remove.
|
||||
*
|
||||
* @param inflationFlag flag corresponding to the content view to be freed
|
||||
*/
|
||||
public void freeContentViewWhenSafe(@InflationFlag int inflationFlag) {
|
||||
// View should not be reinflated in the future
|
||||
updateInflationFlag(inflationFlag, false);
|
||||
Runnable freeViewRunnable = () ->
|
||||
mNotificationInflater.freeNotificationView(inflationFlag);
|
||||
switch (inflationFlag) {
|
||||
case FLAG_CONTENT_VIEW_HEADS_UP:
|
||||
getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_HEADSUP,
|
||||
freeViewRunnable);
|
||||
break;
|
||||
case FLAG_CONTENT_VIEW_AMBIENT:
|
||||
getPrivateLayout().performWhenContentInactive(VISIBLE_TYPE_AMBIENT,
|
||||
freeViewRunnable);
|
||||
getPublicLayout().performWhenContentInactive(VISIBLE_TYPE_AMBIENT,
|
||||
freeViewRunnable);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update whether or not a content view should be inflated.
|
||||
*
|
||||
@@ -607,7 +636,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
headsUpHeight = mMaxHeadsUpHeight;
|
||||
}
|
||||
NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper(
|
||||
NotificationContentView.VISIBLE_TYPE_HEADSUP);
|
||||
VISIBLE_TYPE_HEADSUP);
|
||||
if (headsUpWrapper != null) {
|
||||
headsUpHeight = Math.max(headsUpHeight, headsUpWrapper.getMinLayoutHeight());
|
||||
}
|
||||
@@ -642,12 +671,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
if (isHeadsUp) {
|
||||
mMustStayOnScreen = true;
|
||||
setAboveShelf(true);
|
||||
} else {
|
||||
if (isAboveShelf() != wasAboveShelf) {
|
||||
mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
|
||||
}
|
||||
updateInflationFlag(FLAG_REINFLATE_HEADS_UP_VIEW, false);
|
||||
mNotificationInflater.freeNotificationView(FLAG_REINFLATE_HEADS_UP_VIEW);
|
||||
} else if (isAboveShelf() != wasAboveShelf) {
|
||||
mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,10 +682,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
|
||||
|
||||
public void setAmbientPulsing(boolean isAmbientPulsing) {
|
||||
mIsAmbientPulsing = isAmbientPulsing;
|
||||
if (!isAmbientPulsing) {
|
||||
updateInflationFlag(FLAG_REINFLATE_AMBIENT_VIEW, false);
|
||||
mNotificationInflater.freeNotificationView(FLAG_REINFLATE_AMBIENT_VIEW);
|
||||
}
|
||||
}
|
||||
|
||||
public void setGroupManager(NotificationGroupManager groupManager) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
@@ -108,6 +109,10 @@ public class NotificationContentView extends FrameLayout {
|
||||
private NotificationGroupManager mGroupManager;
|
||||
private RemoteInputController mRemoteInputController;
|
||||
private Runnable mExpandedVisibleListener;
|
||||
/**
|
||||
* List of listeners for when content views become inactive (i.e. not the showing view).
|
||||
*/
|
||||
private final ArrayMap<View, Runnable> mOnContentViewInactiveListeners = new ArrayMap<>();
|
||||
|
||||
private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
|
||||
= new ViewTreeObserver.OnPreDrawListener() {
|
||||
@@ -1171,6 +1176,7 @@ public class NotificationContentView extends FrameLayout {
|
||||
|
||||
public void onNotificationUpdated(NotificationData.Entry entry) {
|
||||
mStatusBarNotification = entry.notification;
|
||||
mOnContentViewInactiveListeners.clear();
|
||||
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
|
||||
updateAllSingleLineViews();
|
||||
if (mContractedChild != null) {
|
||||
@@ -1628,6 +1634,58 @@ public class NotificationContentView extends FrameLayout {
|
||||
fireExpandedVisibleListenerIfVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a one-shot listener to run when a given content view becomes inactive.
|
||||
*
|
||||
* @param visibleType visible type corresponding to the content view to listen
|
||||
* @param listener runnable to run once when the content view becomes inactive
|
||||
*/
|
||||
public void performWhenContentInactive(int visibleType, Runnable listener) {
|
||||
View view = getViewForVisibleType(visibleType);
|
||||
// View is already inactive
|
||||
if (view == null || isContentViewInactive(visibleType)) {
|
||||
listener.run();
|
||||
return;
|
||||
}
|
||||
mOnContentViewInactiveListeners.put(view, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the content view is inactive. This means it should not be visible
|
||||
* or the showing content as removing it would cause visual jank.
|
||||
*
|
||||
* @param visibleType visible type corresponding to the content view to be removed
|
||||
* @return true if the content view is inactive, false otherwise
|
||||
*/
|
||||
public boolean isContentViewInactive(int visibleType) {
|
||||
View view = getViewForVisibleType(visibleType);
|
||||
return isContentViewInactive(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the content view is inactive.
|
||||
*
|
||||
* @param view view to see if its inactive
|
||||
* @return true if the view is inactive, false o/w
|
||||
*/
|
||||
private boolean isContentViewInactive(View view) {
|
||||
if (view == null) {
|
||||
return true;
|
||||
}
|
||||
return view.getVisibility() != VISIBLE && getViewForVisibleType(mVisibleType) != view;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onChildVisibilityChanged(View child, int oldVisibility, int newVisibility) {
|
||||
super.onChildVisibilityChanged(child, oldVisibility, newVisibility);
|
||||
if (isContentViewInactive(child)) {
|
||||
Runnable listener = mOnContentViewInactiveListeners.remove(child);
|
||||
if (listener != null) {
|
||||
listener.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setIsLowPriority(boolean isLowPriority) {
|
||||
mIsLowPriority = isLowPriority;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_AMBIENT;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
@@ -59,54 +62,54 @@ public class NotificationInflater {
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(flag = true,
|
||||
prefix = {"FLAG_REINFLATE_"},
|
||||
prefix = {"FLAG_CONTENT_VIEW_"},
|
||||
value = {
|
||||
FLAG_REINFLATE_CONTENT_VIEW,
|
||||
FLAG_REINFLATE_EXPANDED_VIEW,
|
||||
FLAG_REINFLATE_HEADS_UP_VIEW,
|
||||
FLAG_REINFLATE_AMBIENT_VIEW,
|
||||
FLAG_REINFLATE_PUBLIC_VIEW,
|
||||
FLAG_REINFLATE_ALL})
|
||||
FLAG_CONTENT_VIEW_CONTRACTED,
|
||||
FLAG_CONTENT_VIEW_EXPANDED,
|
||||
FLAG_CONTENT_VIEW_HEADS_UP,
|
||||
FLAG_CONTENT_VIEW_AMBIENT,
|
||||
FLAG_CONTENT_VIEW_PUBLIC,
|
||||
FLAG_CONTENT_VIEW_ALL})
|
||||
public @interface InflationFlag {}
|
||||
/**
|
||||
* The default, contracted view. Seen when the shade is pulled down and in the lock screen
|
||||
* if there is no worry about content sensitivity.
|
||||
*/
|
||||
public static final int FLAG_REINFLATE_CONTENT_VIEW = 1;
|
||||
public static final int FLAG_CONTENT_VIEW_CONTRACTED = 1;
|
||||
|
||||
/**
|
||||
* The expanded view. Seen when the user expands a notification.
|
||||
*/
|
||||
public static final int FLAG_REINFLATE_EXPANDED_VIEW = 1 << 1;
|
||||
public static final int FLAG_CONTENT_VIEW_EXPANDED = 1 << 1;
|
||||
|
||||
/**
|
||||
* The heads up view. Seen when a high priority notification peeks in from the top.
|
||||
*/
|
||||
public static final int FLAG_REINFLATE_HEADS_UP_VIEW = 1 << 2;
|
||||
public static final int FLAG_CONTENT_VIEW_HEADS_UP = 1 << 2;
|
||||
|
||||
/**
|
||||
* The ambient view. Seen when a high priority notification is received and the phone
|
||||
* is dozing.
|
||||
*/
|
||||
public static final int FLAG_REINFLATE_AMBIENT_VIEW = 1 << 3;
|
||||
public static final int FLAG_CONTENT_VIEW_AMBIENT = 1 << 3;
|
||||
|
||||
/**
|
||||
* The public view. This is a version of the contracted view that hides sensitive
|
||||
* information and is used on the lock screen if we determine that the notification's
|
||||
* content should be hidden.
|
||||
*/
|
||||
public static final int FLAG_REINFLATE_PUBLIC_VIEW = 1 << 4;
|
||||
public static final int FLAG_CONTENT_VIEW_PUBLIC = 1 << 4;
|
||||
|
||||
public static final int FLAG_REINFLATE_ALL = ~0;
|
||||
public static final int FLAG_CONTENT_VIEW_ALL = ~0;
|
||||
|
||||
/**
|
||||
* Content views that must be inflated at all times.
|
||||
*/
|
||||
@InflationFlag
|
||||
private static final int REQUIRED_INFLATION_FLAGS =
|
||||
FLAG_REINFLATE_CONTENT_VIEW
|
||||
| FLAG_REINFLATE_EXPANDED_VIEW
|
||||
| FLAG_REINFLATE_PUBLIC_VIEW;
|
||||
FLAG_CONTENT_VIEW_CONTRACTED
|
||||
| FLAG_CONTENT_VIEW_EXPANDED
|
||||
| FLAG_CONTENT_VIEW_PUBLIC;
|
||||
|
||||
/**
|
||||
* The set of content views to inflate.
|
||||
@@ -144,7 +147,7 @@ public class NotificationInflater {
|
||||
if (childInGroup != mIsChildInGroup) {
|
||||
mIsChildInGroup = childInGroup;
|
||||
if (mIsLowPriority) {
|
||||
int flags = FLAG_REINFLATE_CONTENT_VIEW | FLAG_REINFLATE_EXPANDED_VIEW;
|
||||
int flags = FLAG_CONTENT_VIEW_CONTRACTED | FLAG_CONTENT_VIEW_EXPANDED;
|
||||
inflateNotificationViews(flags);
|
||||
}
|
||||
}
|
||||
@@ -172,7 +175,7 @@ public class NotificationInflater {
|
||||
if (mRow.getEntry() == null) {
|
||||
return;
|
||||
}
|
||||
inflateNotificationViews(FLAG_REINFLATE_AMBIENT_VIEW);
|
||||
inflateNotificationViews(FLAG_CONTENT_VIEW_AMBIENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,23 +255,41 @@ public class NotificationInflater {
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the content view associated with the inflation flag.
|
||||
* Frees the content view associated with the inflation flag. Will only succeed if the
|
||||
* view is safe to remove.
|
||||
*
|
||||
* @param inflateFlag the flag corresponding to the content view which should be freed
|
||||
*/
|
||||
public void freeNotificationView(@InflationFlag int inflateFlag) {
|
||||
if ((mInflationFlags & inflateFlag) != 0) {
|
||||
// The view should still be inflated.
|
||||
return;
|
||||
}
|
||||
switch (inflateFlag) {
|
||||
case FLAG_REINFLATE_HEADS_UP_VIEW:
|
||||
mRow.getPrivateLayout().setHeadsUpChild(null);
|
||||
mCachedContentViews.remove(FLAG_REINFLATE_HEADS_UP_VIEW);
|
||||
case FLAG_CONTENT_VIEW_HEADS_UP:
|
||||
if (mRow.getPrivateLayout().isContentViewInactive(VISIBLE_TYPE_HEADSUP)) {
|
||||
mRow.getPrivateLayout().setHeadsUpChild(null);
|
||||
mCachedContentViews.remove(FLAG_CONTENT_VIEW_HEADS_UP);
|
||||
}
|
||||
break;
|
||||
case FLAG_REINFLATE_AMBIENT_VIEW:
|
||||
mRow.getShowingLayout().setAmbientChild(null);
|
||||
mCachedContentViews.remove(FLAG_REINFLATE_AMBIENT_VIEW);
|
||||
case FLAG_CONTENT_VIEW_AMBIENT:
|
||||
boolean privateSafeToRemove = mRow.getPrivateLayout().isContentViewInactive(
|
||||
VISIBLE_TYPE_AMBIENT);
|
||||
boolean publicSafeToRemove = mRow.getPublicLayout().isContentViewInactive(
|
||||
VISIBLE_TYPE_AMBIENT);
|
||||
if (privateSafeToRemove) {
|
||||
mRow.getPrivateLayout().setAmbientChild(null);
|
||||
}
|
||||
if (publicSafeToRemove) {
|
||||
mRow.getPublicLayout().setAmbientChild(null);
|
||||
}
|
||||
if (privateSafeToRemove && publicSafeToRemove) {
|
||||
mCachedContentViews.remove(FLAG_CONTENT_VIEW_AMBIENT);
|
||||
}
|
||||
break;
|
||||
case FLAG_REINFLATE_CONTENT_VIEW:
|
||||
case FLAG_REINFLATE_EXPANDED_VIEW:
|
||||
case FLAG_REINFLATE_PUBLIC_VIEW:
|
||||
case FLAG_CONTENT_VIEW_CONTRACTED:
|
||||
case FLAG_CONTENT_VIEW_EXPANDED:
|
||||
case FLAG_CONTENT_VIEW_PUBLIC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -280,23 +301,23 @@ public class NotificationInflater {
|
||||
Context packageContext) {
|
||||
InflationProgress result = new InflationProgress();
|
||||
isLowPriority = isLowPriority && !isChildInGroup;
|
||||
if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
|
||||
result.newContentView = createContentView(builder, isLowPriority, usesIncreasedHeight);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
|
||||
result.newExpandedView = createExpandedView(builder, isLowPriority);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
|
||||
result.newHeadsUpView = builder.createHeadsUpContentView(usesIncreasedHeadsUpHeight);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
|
||||
result.newPublicView = builder.makePublicContentView();
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
|
||||
result.newAmbientView = redactAmbient ? builder.makePublicAmbientNotification()
|
||||
: builder.makeAmbientNotification();
|
||||
}
|
||||
@@ -316,11 +337,11 @@ public class NotificationInflater {
|
||||
NotificationContentView publicLayout = row.getPublicLayout();
|
||||
final HashMap<Integer, CancellationSignal> runningInflations = new HashMap<>();
|
||||
|
||||
int flag = FLAG_REINFLATE_CONTENT_VIEW;
|
||||
int flag = FLAG_CONTENT_VIEW_CONTRACTED;
|
||||
if ((reInflateFlags & flag) != 0) {
|
||||
boolean isNewView =
|
||||
!canReapplyRemoteView(result.newContentView,
|
||||
cachedContentViews.get(FLAG_REINFLATE_CONTENT_VIEW));
|
||||
cachedContentViews.get(FLAG_CONTENT_VIEW_CONTRACTED));
|
||||
ApplyCallback applyCallback = new ApplyCallback() {
|
||||
@Override
|
||||
public void setResultView(View v) {
|
||||
@@ -339,12 +360,12 @@ public class NotificationInflater {
|
||||
runningInflations, applyCallback);
|
||||
}
|
||||
|
||||
flag = FLAG_REINFLATE_EXPANDED_VIEW;
|
||||
flag = FLAG_CONTENT_VIEW_EXPANDED;
|
||||
if ((reInflateFlags & flag) != 0) {
|
||||
if (result.newExpandedView != null) {
|
||||
boolean isNewView =
|
||||
!canReapplyRemoteView(result.newExpandedView,
|
||||
cachedContentViews.get(FLAG_REINFLATE_EXPANDED_VIEW));
|
||||
cachedContentViews.get(FLAG_CONTENT_VIEW_EXPANDED));
|
||||
ApplyCallback applyCallback = new ApplyCallback() {
|
||||
@Override
|
||||
public void setResultView(View v) {
|
||||
@@ -365,12 +386,12 @@ public class NotificationInflater {
|
||||
}
|
||||
}
|
||||
|
||||
flag = FLAG_REINFLATE_HEADS_UP_VIEW;
|
||||
flag = FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
if ((reInflateFlags & flag) != 0) {
|
||||
if (result.newHeadsUpView != null) {
|
||||
boolean isNewView =
|
||||
!canReapplyRemoteView(result.newHeadsUpView,
|
||||
cachedContentViews.get(FLAG_REINFLATE_HEADS_UP_VIEW));
|
||||
cachedContentViews.get(FLAG_CONTENT_VIEW_HEADS_UP));
|
||||
ApplyCallback applyCallback = new ApplyCallback() {
|
||||
@Override
|
||||
public void setResultView(View v) {
|
||||
@@ -386,16 +407,16 @@ public class NotificationInflater {
|
||||
redactAmbient, isNewView, remoteViewClickHandler, callback,
|
||||
privateLayout, privateLayout.getHeadsUpChild(),
|
||||
privateLayout.getVisibleWrapper(
|
||||
NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,
|
||||
VISIBLE_TYPE_HEADSUP), runningInflations,
|
||||
applyCallback);
|
||||
}
|
||||
}
|
||||
|
||||
flag = FLAG_REINFLATE_PUBLIC_VIEW;
|
||||
flag = FLAG_CONTENT_VIEW_PUBLIC;
|
||||
if ((reInflateFlags & flag) != 0) {
|
||||
boolean isNewView =
|
||||
!canReapplyRemoteView(result.newPublicView,
|
||||
cachedContentViews.get(FLAG_REINFLATE_PUBLIC_VIEW));
|
||||
cachedContentViews.get(FLAG_CONTENT_VIEW_PUBLIC));
|
||||
ApplyCallback applyCallback = new ApplyCallback() {
|
||||
@Override
|
||||
public void setResultView(View v) {
|
||||
@@ -414,12 +435,12 @@ public class NotificationInflater {
|
||||
runningInflations, applyCallback);
|
||||
}
|
||||
|
||||
flag = FLAG_REINFLATE_AMBIENT_VIEW;
|
||||
flag = FLAG_CONTENT_VIEW_AMBIENT;
|
||||
if ((reInflateFlags & flag) != 0) {
|
||||
NotificationContentView newParent = redactAmbient ? publicLayout : privateLayout;
|
||||
boolean isNewView = (!canReapplyAmbient(row, redactAmbient)
|
||||
|| !canReapplyRemoteView(result.newAmbientView,
|
||||
cachedContentViews.get(FLAG_REINFLATE_AMBIENT_VIEW)));
|
||||
cachedContentViews.get(FLAG_CONTENT_VIEW_AMBIENT)));
|
||||
ApplyCallback applyCallback = new ApplyCallback() {
|
||||
@Override
|
||||
public void setResultView(View v) {
|
||||
@@ -570,40 +591,40 @@ public class NotificationInflater {
|
||||
NotificationContentView privateLayout = row.getPrivateLayout();
|
||||
NotificationContentView publicLayout = row.getPublicLayout();
|
||||
if (runningInflations.isEmpty()) {
|
||||
if ((reInflateFlags & FLAG_REINFLATE_CONTENT_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
|
||||
if (result.inflatedContentView != null) {
|
||||
privateLayout.setContractedChild(result.inflatedContentView);
|
||||
}
|
||||
cachedContentViews.put(FLAG_REINFLATE_CONTENT_VIEW, result.newContentView);
|
||||
cachedContentViews.put(FLAG_CONTENT_VIEW_CONTRACTED, result.newContentView);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_EXPANDED_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_EXPANDED) != 0) {
|
||||
if (result.inflatedExpandedView != null) {
|
||||
privateLayout.setExpandedChild(result.inflatedExpandedView);
|
||||
} else if (result.newExpandedView == null) {
|
||||
privateLayout.setExpandedChild(null);
|
||||
}
|
||||
cachedContentViews.put(FLAG_REINFLATE_EXPANDED_VIEW, result.newExpandedView);
|
||||
cachedContentViews.put(FLAG_CONTENT_VIEW_EXPANDED, result.newExpandedView);
|
||||
row.setExpandable(result.newExpandedView != null);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_HEADS_UP_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_HEADS_UP) != 0) {
|
||||
if (result.inflatedHeadsUpView != null) {
|
||||
privateLayout.setHeadsUpChild(result.inflatedHeadsUpView);
|
||||
} else if (result.newHeadsUpView == null) {
|
||||
privateLayout.setHeadsUpChild(null);
|
||||
}
|
||||
cachedContentViews.put(FLAG_REINFLATE_HEADS_UP_VIEW, result.newHeadsUpView);
|
||||
cachedContentViews.put(FLAG_CONTENT_VIEW_HEADS_UP, result.newHeadsUpView);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_PUBLIC_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
|
||||
if (result.inflatedPublicView != null) {
|
||||
publicLayout.setContractedChild(result.inflatedPublicView);
|
||||
}
|
||||
cachedContentViews.put(FLAG_REINFLATE_PUBLIC_VIEW, result.newPublicView);
|
||||
cachedContentViews.put(FLAG_CONTENT_VIEW_PUBLIC, result.newPublicView);
|
||||
}
|
||||
|
||||
if ((reInflateFlags & FLAG_REINFLATE_AMBIENT_VIEW) != 0) {
|
||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_AMBIENT) != 0) {
|
||||
if (result.inflatedAmbientView != null) {
|
||||
NotificationContentView newParent = redactAmbient
|
||||
? publicLayout : privateLayout;
|
||||
@@ -612,7 +633,7 @@ public class NotificationInflater {
|
||||
newParent.setAmbientChild(result.inflatedAmbientView);
|
||||
otherParent.setAmbientChild(null);
|
||||
}
|
||||
cachedContentViews.put(FLAG_REINFLATE_AMBIENT_VIEW, result.newAmbientView);
|
||||
cachedContentViews.put(FLAG_CONTENT_VIEW_AMBIENT, result.newAmbientView);
|
||||
}
|
||||
entry.headsUpStatusBarText = result.headsUpStatusBarText;
|
||||
entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic;
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.statusbar.policy;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
@@ -151,6 +153,7 @@ public abstract class HeadsUpManager extends AlertingNotificationManager {
|
||||
for (OnHeadsUpChangedListener listener : mListeners) {
|
||||
listener.onHeadsUpStateChanged(entry, false);
|
||||
}
|
||||
entry.row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
|
||||
}
|
||||
|
||||
protected void updatePinnedMode() {
|
||||
|
||||
@@ -18,9 +18,6 @@ package com.android.systemui.statusbar;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_ALL;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Instrumentation;
|
||||
@@ -190,7 +187,8 @@ public class NotificationTestHelper {
|
||||
.setSmallIcon(R.drawable.ic_person)
|
||||
.setContentTitle("Title")
|
||||
.setContentText("Text")
|
||||
.setPublicVersion(publicVersion);
|
||||
.setPublicVersion(publicVersion)
|
||||
.setStyle(new Notification.BigTextStyle().bigText("Big Text"));
|
||||
if (isGroupSummary) {
|
||||
notificationBuilder.setGroupSummary(true);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,12 @@ package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_ALL;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_HEADS_UP_VIEW;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -41,6 +40,7 @@ import android.app.AppOpsManager;
|
||||
import android.app.NotificationChannel;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.util.ArraySet;
|
||||
import android.view.NotificationHeaderView;
|
||||
@@ -140,25 +140,14 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHeadsUpViewShouldBeFreedWhenNotHeadsUp() throws Exception {
|
||||
ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_REINFLATE_ALL);
|
||||
row.setHeadsUp(true);
|
||||
public void testFreeContentViewWhenSafe() throws Exception {
|
||||
ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_CONTENT_VIEW_ALL);
|
||||
|
||||
row.setHeadsUp(false);
|
||||
row.freeContentViewWhenSafe(FLAG_CONTENT_VIEW_HEADS_UP);
|
||||
|
||||
assertNull(row.getPrivateLayout().getHeadsUpChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmbientViewShouldBeFreedWhenNotPulsing() throws Exception {
|
||||
ExpandableNotificationRow row = mNotificationTestHelper.createRow(FLAG_REINFLATE_ALL);
|
||||
row.setAmbientPulsing(true);
|
||||
|
||||
row.setAmbientPulsing(false);
|
||||
|
||||
assertNull(row.getShowingLayout().getAmbientChild());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAboveShelfChangedListenerCalled() throws Exception {
|
||||
ExpandableNotificationRow row = mNotificationTestHelper.createRow();
|
||||
|
||||
@@ -16,12 +16,9 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.row;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_ALL;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_EXPANDED_VIEW;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater
|
||||
.FLAG_REINFLATE_HEADS_UP_VIEW;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_HEADS_UP;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_ALL;
|
||||
import static com.android.systemui.statusbar.notification.row.NotificationInflater.FLAG_CONTENT_VIEW_EXPANDED;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -99,7 +96,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
public void testIncreasedHeadsUpBeingUsed() {
|
||||
mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
|
||||
Notification.Builder builder = spy(mBuilder);
|
||||
mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
|
||||
mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext);
|
||||
verify(builder).createHeadsUpContentView(true);
|
||||
}
|
||||
|
||||
@@ -107,7 +104,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
public void testIncreasedHeightBeingUsed() {
|
||||
mNotificationInflater.setUsesIncreasedHeight(true);
|
||||
Notification.Builder builder = spy(mBuilder);
|
||||
mNotificationInflater.inflateNotificationViews(FLAG_REINFLATE_ALL, builder, mContext);
|
||||
mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext);
|
||||
verify(builder).createContentView(true);
|
||||
}
|
||||
|
||||
@@ -120,7 +117,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testInflationOnlyInflatesSetFlags() throws Exception {
|
||||
mNotificationInflater.updateInflationFlag(FLAG_REINFLATE_HEADS_UP_VIEW,
|
||||
mNotificationInflater.updateInflationFlag(FLAG_CONTENT_VIEW_HEADS_UP,
|
||||
true /* shouldInflate */);
|
||||
runThenWaitForInflation(() -> mNotificationInflater.inflateNotificationViews(),
|
||||
mNotificationInflater);
|
||||
@@ -163,7 +160,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
new NotificationInflater.InflationProgress();
|
||||
result.packageContext = mContext;
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
NotificationInflater.applyRemoteView(result, FLAG_REINFLATE_EXPANDED_VIEW, 0,
|
||||
NotificationInflater.applyRemoteView(result, FLAG_CONTENT_VIEW_EXPANDED, 0,
|
||||
new ArrayMap() /* cachedContentViews */, mRow, false /* redactAmbient */,
|
||||
true /* isNewView */, new RemoteViews.OnClickHandler(),
|
||||
new NotificationInflater.InflationCallback() {
|
||||
@@ -197,7 +194,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
/* Cancelling requires us to be on the UI thread otherwise we might have a race */
|
||||
@Test
|
||||
public void testSupersedesExistingTask() {
|
||||
mNotificationInflater.addInflationFlags(FLAG_REINFLATE_ALL);
|
||||
mNotificationInflater.addInflationFlags(FLAG_CONTENT_VIEW_ALL);
|
||||
mNotificationInflater.inflateNotificationViews();
|
||||
|
||||
// Trigger inflation of content and expanded only.
|
||||
@@ -208,7 +205,7 @@ public class NotificationInflaterTest extends SysuiTestCase {
|
||||
NotificationInflater.AsyncInflationTask asyncInflationTask =
|
||||
(NotificationInflater.AsyncInflationTask) runningTask;
|
||||
assertEquals("Successive inflations don't inherit the previous flags!",
|
||||
asyncInflationTask.getReInflateFlags(), FLAG_REINFLATE_ALL);
|
||||
asyncInflationTask.getReInflateFlags(), FLAG_CONTENT_VIEW_ALL);
|
||||
runningTask.abort();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user