Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61a75423 authored by Selim Cinek's avatar Selim Cinek Committed by Android (Google) Code Review
Browse files

Merge "Follow up CL for heads up notification refactoring" into mnc-dev

parents f7143ce6 684a442b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@
    <integer name="heads_up_notification_minimum_time">2000</integer>

    <!-- milliseconds before the heads up notification accepts touches. -->
    <integer name="heads_up_sensitivity_delay">700</integer>
    <integer name="touch_acceptance_delay">700</integer>

    <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
    <integer name="recents_task_bar_dismiss_delay_seconds">1</integer>
+35 −33
Original line number Diff line number Diff line
@@ -784,7 +784,8 @@ public abstract class BaseStatusBar extends SystemUI implements
    protected void applyColorsAndBackgrounds(StatusBarNotification sbn,
            NotificationData.Entry entry) {

        if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
        if (entry.getContentView().getId()
                != com.android.internal.R.id.status_bar_latest_event_content) {
            // Using custom RemoteViews
            if (entry.targetSdk >= Build.VERSION_CODES.GINGERBREAD
                    && entry.targetSdk < Build.VERSION_CODES.LOLLIPOP) {
@@ -809,8 +810,9 @@ public abstract class BaseStatusBar extends SystemUI implements

    public boolean isMediaNotification(NotificationData.Entry entry) {
        // TODO: confirm that there's a valid media key
        return entry.expandedBig != null &&
               entry.expandedBig.findViewById(com.android.internal.R.id.media_actions) != null;
        return entry.getExpandedContentView() != null &&
               entry.getExpandedContentView()
                       .findViewById(com.android.internal.R.id.media_actions) != null;
    }

    // The gear button in the guts that links to the app's own notification settings
@@ -1134,9 +1136,9 @@ public abstract class BaseStatusBar extends SystemUI implements
    }

    /**
     * if the interrupting notification had a fullscreen intent, fire it now.
     * If there is an active heads-up notification and it has a fullscreen intent, fire it now.
     */
    public abstract void escalateHeadsUp();
    public abstract void maybeEscalateHeadsUp();

    /**
     * Save the current "public" (locked and secure) state of the lockscreen.
@@ -1337,8 +1339,8 @@ public abstract class BaseStatusBar extends SystemUI implements
        View publicViewLocal = null;
        if (publicNotification != null) {
            try {
                publicViewLocal = publicNotification.contentView.apply(mContext, contentContainerPublic,
                        mOnClickHandler);
                publicViewLocal = publicNotification.contentView.apply(mContext,
                        contentContainerPublic, mOnClickHandler);

                if (publicViewLocal != null) {
                    publicViewLocal.setIsRootNamespace(true);
@@ -1445,9 +1447,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        entry.row = row;
        entry.row.setHeightRange(mRowMinHeight, maxHeight);
        entry.row.setOnActivatedListener(this);
        entry.expanded = contentViewLocal;
        entry.expandedPublic = publicViewLocal;
        entry.setBigContentView(bigContentViewLocal);
        entry.row.setExpandable(bigContentViewLocal != null);

        applyColorsAndBackgrounds(sbn, entry);

@@ -1536,12 +1536,13 @@ public abstract class BaseStatusBar extends SystemUI implements

        // See if we have somewhere to put that remote input
        if (remoteInput != null) {
            if (entry.expandedBig != null) {
                inflateRemoteInput(entry.expandedBig, remoteInput, actions);
            View bigContentView = entry.getExpandedContentView();
            if (bigContentView != null) {
                inflateRemoteInput(bigContentView, remoteInput, actions);
            }
            View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
            if (headsUpChild != null) {
                inflateRemoteInput(headsUpChild, remoteInput, actions);
            View headsUpContentView = entry.getHeadsUpContentView();
            if (headsUpContentView != null) {
                inflateRemoteInput(headsUpContentView, remoteInput, actions);
            }
        }

@@ -1883,15 +1884,14 @@ public abstract class BaseStatusBar extends SystemUI implements
            logUpdate(entry, n);
        }
        boolean applyInPlace = shouldApplyInPlace(entry, n);
        final boolean shouldInterrupt = shouldInterrupt(notification);
        final boolean alertAgain = alertAgain(entry, n);
        boolean shouldInterrupt = shouldInterrupt(notification);
        boolean alertAgain = alertAgain(entry, n);

        entry.notification = notification;
        mGroupManager.onEntryUpdated(entry, entry.notification);

        boolean updateSuccessful = false;
        if (applyInPlace) {
            // We can just reapply the notifications in place
            if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
            try {
                if (entry.icon != null) {
@@ -1912,7 +1912,7 @@ public abstract class BaseStatusBar extends SystemUI implements
                updateSuccessful = true;
            }
            catch (RuntimeException e) {
                // It failed to add cleanly.  Log, and remove the view from the panel.
                // It failed to apply cleanly.
                Log.w(TAG, "Couldn't reapply views for package " + n.contentView.getPackage(), e);
            }
        }
@@ -1936,11 +1936,12 @@ public abstract class BaseStatusBar extends SystemUI implements
        // swipe-dismissable)
        updateNotificationVetoButton(entry.row, notification);

        if (DEBUG) {
            // Is this for you?
            boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
        if (DEBUG) Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
            Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
        }

        // Recalculate the position of the sliding windows and the titles.
        setAreThereNotifications();
    }

@@ -1951,7 +1952,7 @@ public abstract class BaseStatusBar extends SystemUI implements
        StatusBarNotification oldNotification = oldEntry.notification;
        Log.d(TAG, "old notification: when=" + oldNotification.getNotification().when
                + " ongoing=" + oldNotification.isOngoing()
                + " expanded=" + oldEntry.expanded
                + " expanded=" + oldEntry.getContentView()
                + " contentView=" + oldNotification.getNotification().contentView
                + " bigContentView=" + oldNotification.getNotification().bigContentView
                + " publicView=" + oldNotification.getNotification().publicVersion
@@ -1964,7 +1965,8 @@ public abstract class BaseStatusBar extends SystemUI implements
    }

    /**
     * @return whether we can just reapply the RemoteViews in place when it is updated
     * @return whether we can just reapply the RemoteViews from a notification in-place when it is
     * updated
     */
    private boolean shouldApplyInPlace(Entry entry, Notification n) {
        StatusBarNotification oldNotification = entry.notification;
@@ -1982,15 +1984,15 @@ public abstract class BaseStatusBar extends SystemUI implements
        final Notification publicNotification = n.publicVersion;
        final RemoteViews publicContentView = publicNotification != null
                ? publicNotification.contentView : null;
        boolean contentsUnchanged = entry.expanded != null
        boolean contentsUnchanged = entry.getContentView() != null
                && contentView.getPackage() != null
                && oldContentView.getPackage() != null
                && oldContentView.getPackage().equals(contentView.getPackage())
                && oldContentView.getLayoutId() == contentView.getLayoutId();
        // large view may be null
        boolean bigContentsUnchanged =
                (entry.getBigContentView() == null && bigContentView == null)
                || ((entry.getBigContentView() != null && bigContentView != null)
                (entry.getExpandedContentView() == null && bigContentView == null)
                || ((entry.getExpandedContentView() != null && bigContentView != null)
                    && bigContentView.getPackage() != null
                    && oldBigContentView.getPackage() != null
                    && oldBigContentView.getPackage().equals(bigContentView.getPackage())
@@ -2022,12 +2024,12 @@ public abstract class BaseStatusBar extends SystemUI implements
                : null;

        // Reapply the RemoteViews
        contentView.reapply(mContext, entry.expanded, mOnClickHandler);
        if (bigContentView != null && entry.getBigContentView() != null) {
            bigContentView.reapply(mContext, entry.getBigContentView(),
        contentView.reapply(mContext, entry.getContentView(), mOnClickHandler);
        if (bigContentView != null && entry.getExpandedContentView() != null) {
            bigContentView.reapply(mContext, entry.getExpandedContentView(),
                    mOnClickHandler);
        }
        View headsUpChild = entry.row.getPrivateLayout().getHeadsUpChild();
        View headsUpChild = entry.getHeadsUpContentView();
        if (headsUpContentView != null && headsUpChild != null) {
            headsUpContentView.reapply(mContext, headsUpChild, mOnClickHandler);
        }
@@ -2050,7 +2052,7 @@ public abstract class BaseStatusBar extends SystemUI implements
    }

    protected void notifyHeadsUpScreenOff() {
        escalateHeadsUp();
        maybeEscalateHeadsUp();
    }

    private boolean alertAgain(Entry oldEntry, Notification newNotification) {
+11 −6
Original line number Diff line number Diff line
@@ -84,7 +84,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
    private ExpansionLogger mLogger;
    private String mLoggingKey;
    private boolean mWasReset;

    private NotificationGuts mGuts;
    private StatusBarNotification mStatusBarNotification;
    private boolean mIsHeadsUp;
@@ -102,6 +101,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
    private ViewStub mGutsStub;
    private boolean mHasExpandAction;
    private boolean mIsSystemChildExpanded;
    private boolean mIsPinned;
    private OnClickListener mExpandClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
@@ -109,7 +109,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
                    !mChildrenExpanded);
        }
    };
    private boolean mInShade;

    public NotificationContentView getPrivateLayout() {
        return mPrivateLayout;
@@ -284,12 +283,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
        return realActualHeight;
    }

    public void setInShade(boolean inShade) {
        mInShade = inShade;
    /**
     * Set this notification to be pinned to the top if {@link #isHeadsUp()} is true. By doing this
     * the notification will be rendered on top of the screen.
     *
     * @param pinned whether it is pinned
     */
    public void setPinned(boolean pinned) {
        mIsPinned = pinned;
    }

    public boolean isInShade() {
        return mInShade;
    public boolean isPinned() {
        return mIsPinned;
    }

    public int getHeadsUpHeight() {
+49 −43
Original line number Diff line number Diff line
@@ -32,37 +32,34 @@ import android.widget.FrameLayout;
import com.android.systemui.R;

/**
 * A frame layout containing the actual payload of the notification, including the contracted and
 * expanded layout. This class is responsible for clipping the content and and switching between the
 * expanded and contracted view depending on its clipped size.
 * A frame layout containing the actual payload of the notification, including the contracted,
 * expanded and heads up layout. This class is responsible for clipping the content and and
 * switching between the expanded, contracted and the heads up view depending on its clipped size.
 */
public class NotificationContentView extends FrameLayout {

    private static final long ANIMATION_DURATION_LENGTH = 170;
    private static final int CONTRACTED = 1;
    private static final int EXPANDED = 2;
    private static final int HEADSUP = 3;
    private static final int VISIBLE_TYPE_CONTRACTED = 0;
    private static final int VISIBLE_TYPE_EXPANDED = 1;
    private static final int VISIBLE_TYPE_HEADSUP = 2;

    private final Rect mClipBounds = new Rect();
    private final int mSmallHeight;
    private final int mHeadsUpHeight;
    private final Interpolator mLinearInterpolator = new LinearInterpolator();

    private View mContractedChild;
    private View mExpandedChild;
    private View mHeadsUpChild;

    private NotificationViewWrapper mContractedWrapper;

    private final int mSmallHeight;
    private final int mHeadsUpHeight;
    private int mClipTopAmount;

    private int mContentHeight;

    private final Interpolator mLinearInterpolator = new LinearInterpolator();
    private int mVisibleView = CONTRACTED;

    private int mVisibleType = VISIBLE_TYPE_CONTRACTED;
    private boolean mDark;
    private final Paint mFadePaint = new Paint();
    private boolean mAnimate;
    private boolean mIsHeadsUp;
    private ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
            = new ViewTreeObserver.OnPreDrawListener() {
        @Override
@@ -72,7 +69,6 @@ public class NotificationContentView extends FrameLayout {
            return true;
        }
    };
    private boolean mIsHeadsUp;

    public NotificationContentView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -105,9 +101,9 @@ public class NotificationContentView extends FrameLayout {
                // An actual height is set
                size = Math.min(maxSize, layoutParams.height);
            }
            int spec = size == Integer.MAX_VALUE ?
                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) :
                    MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
            int spec = size == Integer.MAX_VALUE
                    ? MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
                    : MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
            mExpandedChild.measure(widthMeasureSpec, spec);
            maxChildHeight = Math.max(maxChildHeight, mExpandedChild.getMeasuredHeight());
        }
@@ -153,7 +149,7 @@ public class NotificationContentView extends FrameLayout {
        mContractedChild = null;
        mExpandedChild = null;
        mHeadsUpChild = null;
        mVisibleView = CONTRACTED;
        mVisibleType = VISIBLE_TYPE_CONTRACTED;
        if (resetActualHeight) {
            mContentHeight = mSmallHeight;
        }
@@ -263,30 +259,32 @@ public class NotificationContentView extends FrameLayout {
        if (mContractedChild == null) {
            return;
        }
        int visibleView = calculateVisibleView();
        if (visibleView != mVisibleView || force) {
            if (animate && mExpandedChild != null) {
                runSwitchAnimation(visibleView);
        int visibleType = calculateVisibleType();
        if (visibleType != mVisibleType || force) {
            if (animate && (visibleType == VISIBLE_TYPE_EXPANDED && mExpandedChild != null)
                    || (visibleType == VISIBLE_TYPE_HEADSUP && mHeadsUpChild != null)
                    || visibleType == VISIBLE_TYPE_CONTRACTED) {
                runSwitchAnimation(visibleType);
            } else {
                updateViewVisibilities(visibleView);
                updateViewVisibilities(visibleType);
            }
            mVisibleView = visibleView;
            mVisibleType = visibleType;
        }
    }

    private void updateViewVisibilities(int visibleView) {
        boolean contractedVisible = visibleView == CONTRACTED;
    private void updateViewVisibilities(int visibleType) {
        boolean contractedVisible = visibleType == VISIBLE_TYPE_CONTRACTED;
        mContractedChild.setVisibility(contractedVisible ? View.VISIBLE : View.INVISIBLE);
        mContractedChild.setAlpha(contractedVisible ? 1f : 0f);
        mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
        if (mExpandedChild != null) {
            boolean expandedVisible = visibleView == EXPANDED;
            boolean expandedVisible = visibleType == VISIBLE_TYPE_EXPANDED;
            mExpandedChild.setVisibility(expandedVisible ? View.VISIBLE : View.INVISIBLE);
            mExpandedChild.setAlpha(expandedVisible ? 1f : 0f);
            mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
        }
        if (mHeadsUpChild != null) {
            boolean headsUpVisible = visibleView == HEADSUP;
            boolean headsUpVisible = visibleType == VISIBLE_TYPE_HEADSUP;
            mHeadsUpChild.setVisibility(headsUpVisible ? View.VISIBLE : View.INVISIBLE);
            mHeadsUpChild.setAlpha(headsUpVisible ? 1f : 0f);
            mHeadsUpChild.setLayerType(LAYER_TYPE_NONE, null);
@@ -294,9 +292,9 @@ public class NotificationContentView extends FrameLayout {
        setLayerType(LAYER_TYPE_NONE, null);
    }

    private void runSwitchAnimation(int visibleView) {
        View shownView = getViewFromFlag(visibleView);
        View hiddenView = getViewFromFlag(mVisibleView);
    private void runSwitchAnimation(int visibleType) {
        View shownView = getViewForVisibleType(visibleType);
        View hiddenView = getViewForVisibleType(mVisibleType);
        shownView.setVisibility(View.VISIBLE);
        hiddenView.setVisibility(View.VISIBLE);
        shownView.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
@@ -314,34 +312,42 @@ public class NotificationContentView extends FrameLayout {
                .withEndAction(new Runnable() {
                    @Override
                    public void run() {
                        updateViewVisibilities(mVisibleView);
                        updateViewVisibilities(mVisibleType);
                    }
                });
    }

    private View getViewFromFlag(int visibleView) {
        switch (visibleView) {
            case EXPANDED:
    /**
     * @param visibleType one of the static enum types in this view
     * @return the corresponding view according to the given visible type
     */
    private View getViewForVisibleType(int visibleType) {
        switch (visibleType) {
            case VISIBLE_TYPE_EXPANDED:
                return mExpandedChild;
            case HEADSUP:
            case VISIBLE_TYPE_HEADSUP:
                return mHeadsUpChild;
        }
            default:
                return mContractedChild;
        }
    }

    private int calculateVisibleView() {
    /**
     * @return one of the static enum types in this view, calculated form the current state
     */
    private int calculateVisibleType() {
        boolean noExpandedChild = mExpandedChild == null;
        if (mIsHeadsUp && mHeadsUpChild != null) {
            if (mContentHeight <= mHeadsUpChild.getHeight() || noExpandedChild) {
                return HEADSUP;
                return VISIBLE_TYPE_HEADSUP;
            } else {
                return EXPANDED;
                return VISIBLE_TYPE_EXPANDED;
            }
        } else {
            if (mContentHeight <= mSmallHeight || noExpandedChild) {
                return CONTRACTED;
                return VISIBLE_TYPE_CONTRACTED;
            } else {
                return EXPANDED;
                return VISIBLE_TYPE_EXPANDED;
            }
        }
    }
+17 −15
Original line number Diff line number Diff line
@@ -45,9 +45,6 @@ public class NotificationData {
        public StatusBarNotification notification;
        public StatusBarIconView icon;
        public ExpandableNotificationRow row; // the outer expanded view
        public View expanded; // the inflated RemoteViews
        public View expandedPublic; // for insecure lockscreens
        public View expandedBig;
        private boolean interruption;
        public boolean autoRedacted; // whether the redacted notification was generated by us
        public boolean legacy; // whether the notification has a legacy, dark background
@@ -58,14 +55,6 @@ public class NotificationData {
            this.notification = n;
            this.icon = ic;
        }
        public void setBigContentView(View bigContentView) {
            this.expandedBig = bigContentView;
            row.setExpandable(bigContentView != null);
        }
        public View getBigContentView() {
            return expandedBig;
        }
        public View getPublicContentView() { return expandedPublic; }

        public void setInterruption() {
            interruption = true;
@@ -81,15 +70,28 @@ public class NotificationData {
        public void reset() {
            // NOTE: Icon needs to be preserved for now.
            // We should fix this at some point.
            expanded = null;
            expandedPublic = null;
            expandedBig = null;
            autoRedacted = false;
            legacy = false;
            if (row != null) {
                row.reset();
            }
        }

        public View getContentView() {
            return row.getPrivateLayout().getContractedChild();
        }

        public View getExpandedContentView() {
            return row.getPrivateLayout().getExpandedChild();
        }

        public View getHeadsUpContentView() {
            return row.getPrivateLayout().getHeadsUpChild();
        }

        public View getPublicContentView() {
            return row.getPublicLayout().getContractedChild();
        }
    }

    private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
@@ -258,7 +260,7 @@ public class NotificationData {
     */
    public boolean hasActiveClearableNotifications() {
        for (Entry e : mSortedAndFiltered) {
            if (e.expanded != null) { // the view successfully inflated
            if (e.getContentView() != null) { // the view successfully inflated
                if (e.notification.isClearable()) {
                    return true;
                }
Loading