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

Commit 684a442b authored by Selim Cinek's avatar Selim Cinek
Browse files

Follow up CL for heads up notification refactoring

Change-Id: Iaf286dfd30a86d3d7d6dd947d3c10ac9eb8c2b1e
parent b7018ba6
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
@@ -783,7 +783,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) {
@@ -808,8 +809,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
@@ -1133,9 +1135,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.
@@ -1336,8 +1338,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);
@@ -1444,9 +1446,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);

@@ -1535,12 +1535,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);
            }
        }

@@ -1882,15 +1883,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) {
@@ -1911,7 +1911,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);
            }
        }
@@ -1935,11 +1935,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();
    }

@@ -1950,7 +1951,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
@@ -1963,7 +1964,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;
@@ -1981,15 +1983,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())
@@ -2021,12 +2023,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);
        }
@@ -2049,7 +2051,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