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

Commit 65b2e7c6 authored by Selim Cinek's avatar Selim Cinek
Browse files

Update the notification templates

Most of the notification templates have been updated.
Some cases like media notifications don't yet work well
but will be fixed in a later CL.

Bug: 25376106
Change-Id: I26c366e58ebba3852cea20de6fca311bd302bb24
parent ef695936
Loading
Loading
Loading
Loading
+125 −180
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
@@ -44,8 +45,8 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.LayoutDirection;
import android.util.Log;
import android.util.MathUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
@@ -2999,25 +3000,35 @@ public class Notification implements Parcelable
        }

        private void resetStandardTemplate(RemoteViews contentView) {
            removeLargeIconBackground(contentView);
            contentView.setViewPadding(R.id.icon, 0, 0, 0, 0);
            contentView.setImageViewResource(R.id.icon, 0);
            contentView.setInt(R.id.icon, "setBackgroundResource", 0);
            resetHeader(contentView);
            resetContentMargins(contentView);
            contentView.setViewVisibility(R.id.right_icon, View.GONE);
            contentView.setInt(R.id.right_icon, "setBackgroundResource", 0);
            contentView.setImageViewResource(R.id.right_icon, 0);
            contentView.setImageViewResource(R.id.icon, 0);
            contentView.setTextViewText(R.id.title, null);
            contentView.setTextViewText(R.id.text, null);
            unshrinkLine3Text(contentView);
            contentView.setTextViewText(R.id.text2, null);
            contentView.setViewVisibility(R.id.text2, View.GONE);
            contentView.setViewVisibility(R.id.info, View.GONE);
            contentView.setViewVisibility(R.id.time, View.GONE);
            contentView.setViewVisibility(R.id.line3, View.GONE);
            contentView.setViewVisibility(R.id.overflow_divider, View.GONE);
            contentView.setViewVisibility(R.id.progress, View.GONE);
        }

        private void resetHeader(RemoteViews contentView) {
            contentView.setImageViewResource(R.id.icon, 0);
            contentView.setTextViewText(R.id.app_name_text, null);
            contentView.setViewVisibility(R.id.chronometer, View.GONE);
            contentView.setViewVisibility(R.id.expand_button, View.GONE);
            contentView.setViewVisibility(R.id.sub_text_time_divider, View.GONE);
            contentView.setViewVisibility(R.id.header_sub_text, View.GONE);
            contentView.setViewVisibility(R.id.app_title_sub_text_divider, View.GONE);
            contentView.setViewVisibility(R.id.number_of_children, View.GONE);
        }

        private void resetContentMargins(RemoteViews contentView) {
            contentView.setViewLayoutMarginEnd(R.id.line1, 0);
            contentView.setViewLayoutMarginEnd(R.id.line2, 0);
            contentView.setViewLayoutMarginEnd(R.id.line3, 0);
        }

        private RemoteViews applyStandardTemplate(int resId) {
@@ -3033,21 +3044,13 @@ public class Notification implements Parcelable
            resetStandardTemplate(contentView);

            boolean showLine3 = false;
            // TODO: look into line3 shrinking
            boolean showLine2 = false;
            boolean contentTextInLine2 = false;
            final Bundle ex = mN.extras;

            if (mN.mLargeIcon != null) {
                contentView.setImageViewIcon(R.id.icon, mN.mLargeIcon);
                processLargeLegacyIcon(mN.mLargeIcon, contentView);
                contentView.setImageViewIcon(R.id.right_icon, mN.mSmallIcon);
                contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
                processSmallRightIcon(mN.mSmallIcon, contentView);
            } else { // small icon at left
                contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
                contentView.setViewVisibility(R.id.icon, View.VISIBLE);
                processSmallIconAsLarge(mN.mSmallIcon, contentView);
            }
            bindNotificationHeader(contentView);
            bindLargeIcon(contentView);
            if (ex.getCharSequence(EXTRA_TITLE) != null) {
                contentView.setTextViewText(R.id.title,
                        processLegacyText(ex.getCharSequence(EXTRA_TITLE)));
@@ -3079,20 +3082,6 @@ public class Notification implements Parcelable
                contentView.setViewVisibility(R.id.info, View.GONE);
            }

            // Need to show three lines?
            if (ex.getCharSequence(EXTRA_SUB_TEXT) != null) {
                contentView.setTextViewText(R.id.text,
                        processLegacyText(ex.getCharSequence(EXTRA_SUB_TEXT)));
                if (ex.getCharSequence(EXTRA_TEXT) != null) {
                    contentView.setTextViewText(R.id.text2,
                            processLegacyText(ex.getCharSequence(EXTRA_TEXT)));
                    contentView.setViewVisibility(R.id.text2, View.VISIBLE);
                    showLine2 = true;
                    contentTextInLine2 = true;
                } else {
                    contentView.setViewVisibility(R.id.text2, View.GONE);
                }
            } else {
            contentView.setViewVisibility(R.id.text2, View.GONE);
            final int max = ex.getInt(EXTRA_PROGRESS_MAX, 0);
            final int progress = ex.getInt(EXTRA_PROGRESS, 0);
@@ -3113,15 +3102,56 @@ public class Notification implements Parcelable
            } else {
                contentView.setViewVisibility(R.id.progress, View.GONE);
            }
            }
            if (showLine2) {

                // need to shrink all the type to make sure everything fits
                shrinkLine3Text(contentView);
            }

            // We want to add badge to first line of text.
            boolean addedBadge = addProfileBadge(contentView,
                    contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3);
            // If we added the badge to line 3 then we should show line 3.
            if (addedBadge && !contentTextInLine2) {
                showLine3 = true;
            }

            // Note getStandardView may hide line 3 again.
            contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
            contentView.setViewVisibility(R.id.overflow_divider, showLine3 ? View.VISIBLE : View.GONE);
            return contentView;
        }

        private void bindLargeIcon(RemoteViews contentView) {
            if (mN.mLargeIcon != null) {
                contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
                contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
                processLargeLegacyIcon(mN.mLargeIcon, contentView);
                int endMargin = mContext.getResources().getDimensionPixelSize(
                        R.dimen.notification_content_picture_margin);
                contentView.setViewLayoutMarginEnd(R.id.line1, endMargin);
                contentView.setViewLayoutMarginEnd(R.id.line2, endMargin);
                contentView.setViewLayoutMarginEnd(R.id.line3, endMargin);
            }
        }

        private void bindNotificationHeader(RemoteViews contentView) {
            bindSmallIcon(contentView);
            bindHeaderAppName(contentView);
            bindHeaderSubText(contentView, mN.extras.getCharSequence(EXTRA_SUB_TEXT));
            bindHeaderChronometerAndTime(contentView);
            bindExpandButton(contentView);
        }

        private void bindExpandButton(RemoteViews contentView) {
            contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveColor(),
                    PorterDuff.Mode.SRC_ATOP, -1);
        }

        private void bindHeaderChronometerAndTime(RemoteViews contentView) {
            if (showsTimeOrChronometer()) {
                if (ex.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                contentView.setViewVisibility(R.id.sub_text_time_divider, View.VISIBLE);
                if (mN.extras.getBoolean(EXTRA_SHOW_CHRONOMETER)) {
                    contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
                    contentView.setLong(R.id.chronometer, "setBase",
                            mN.when + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
@@ -3131,26 +3161,37 @@ public class Notification implements Parcelable
                    contentView.setLong(R.id.time, "setTime", mN.when);
                }
            }
        }

            // Adjust padding depending on line count and font size.
            contentView.setViewPadding(R.id.line1, 0,
                    calculateTopPadding(mContext, hasThreeLines(),
                            mContext.getResources().getConfiguration().fontScale),
                    0, 0);
        private void bindHeaderSubText(RemoteViews contentView, CharSequence subText) {
            if (subText != null) {
                // TODO: Remove the span entirely to only have the string with propper formating.
                contentView.setTextViewText(R.id.header_sub_text, processLegacyText(subText));
                contentView.setViewVisibility(R.id.header_sub_text, View.VISIBLE);
                contentView.setViewVisibility(R.id.app_title_sub_text_divider, View.VISIBLE);
            }
        }

            // We want to add badge to first line of text.
            boolean addedBadge = addProfileBadge(contentView,
                    contentTextInLine2 ? R.id.profile_badge_line2 : R.id.profile_badge_line3);
            // If we added the badge to line 3 then we should show line 3.
            if (addedBadge && !contentTextInLine2) {
                showLine3 = true;
        private void bindHeaderAppName(RemoteViews contentView) {
            PackageManager packageManager = mContext.getPackageManager();
            ApplicationInfo info = null;
            try {
                info = packageManager.getApplicationInfo(mContext.getApplicationInfo().packageName,
                        0);
            } catch (final NameNotFoundException e) {
                return;
            }
            CharSequence appName = info != null ? packageManager.getApplicationLabel(info)
                    : null;
            if (TextUtils.isEmpty(appName)) {
                return;
            }
            contentView.setTextViewText(R.id.app_name_text, appName);
        }

            // Note getStandardView may hide line 3 again.
            contentView.setViewVisibility(R.id.line3, showLine3 ? View.VISIBLE : View.GONE);
            contentView.setViewVisibility(R.id.overflow_divider,
                    showLine3 ? View.VISIBLE : View.GONE);
            return contentView;
        private void bindSmallIcon(RemoteViews contentView) {
            contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
            processSmallIconColor(mN.mSmallIcon, contentView);
        }

        /**
@@ -3185,25 +3226,6 @@ public class Notification implements Parcelable
            return hasLine2 && hasLine3;
        }

        /**
         * @hide
         */
        public static int calculateTopPadding(Context ctx, boolean hasThreeLines,
                float fontScale) {
            int padding = ctx.getResources().getDimensionPixelSize(hasThreeLines
                    ? R.dimen.notification_top_pad_narrow
                    : R.dimen.notification_top_pad);
            int largePadding = ctx.getResources().getDimensionPixelSize(hasThreeLines
                    ? R.dimen.notification_top_pad_large_text_narrow
                    : R.dimen.notification_top_pad_large_text);
            float largeFactor = (MathUtils.constrain(fontScale, 1.0f, LARGE_TEXT_SCALE) - 1f)
                    / (LARGE_TEXT_SCALE - 1f);

            // Linearly interpolate the padding between large and normal with the font scale ranging
            // from 1f to LARGE_TEXT_SCALE
            return Math.round((1 - largeFactor) * padding + largeFactor * largePadding);
        }

        private void resetStandardTemplateWithActions(RemoteViews big) {
            big.setViewVisibility(R.id.actions, View.GONE);
            big.setViewVisibility(R.id.action_divider, View.GONE);
@@ -3330,84 +3352,27 @@ public class Notification implements Parcelable
        }

        /**
         * Apply any necessary background to smallIcons being used in the largeIcon spot.
         * Apply any necessariy colors to the small icon
         */
        private void processSmallIconAsLarge(Icon largeIcon, RemoteViews contentView) {
            if (!isLegacy()) {
                contentView.setDrawableParameters(R.id.icon, false, -1,
                        0xFFFFFFFF,
        private void processSmallIconColor(Icon smallIcon, RemoteViews contentView) {
            if (!isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon)) {
                contentView.setDrawableParameters(R.id.icon, false, -1, resolveColor(),
                        PorterDuff.Mode.SRC_ATOP, -1);
                applyLargeIconBackground(contentView);
            } else {
                if (getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
                    applyLargeIconBackground(contentView);
                }
            }
        }

        /**
         * Apply any necessary background to a largeIcon if it's a fake smallIcon (that is,
         * Make the largeIcon dark if it's a fake smallIcon (that is,
         * if it's grayscale).
         */
        // TODO: also check bounds, transparency, that sort of thing.
        private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) {
            if (largeIcon != null && isLegacy()
                    && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
                applyLargeIconBackground(contentView);
            } else {
                removeLargeIconBackground(contentView);
            }
        }

        /**
         * Add a colored circle behind the largeIcon slot.
         */
        private void applyLargeIconBackground(RemoteViews contentView) {
            contentView.setInt(R.id.icon, "setBackgroundResource",
                    R.drawable.notification_icon_legacy_bg);

            contentView.setDrawableParameters(
                    R.id.icon,
                    true,
                    -1,
                    resolveColor(),
                    PorterDuff.Mode.SRC_ATOP,
                    -1);

            int padding = mContext.getResources().getDimensionPixelSize(
                    R.dimen.notification_large_icon_circle_padding);
            contentView.setViewPadding(R.id.icon, padding, padding, padding, padding);
        }

        private void removeLargeIconBackground(RemoteViews contentView) {
            contentView.setInt(R.id.icon, "setBackgroundResource", 0);
        }

        /**
         * Recolor small icons when used in the R.id.right_icon slot.
         */
        private void processSmallRightIcon(Icon smallIcon, RemoteViews contentView) {
            if (!isLegacy()) {
                contentView.setDrawableParameters(R.id.right_icon, false, -1,
                        0xFFFFFFFF,
                // resolve color will fall back to the default when legacy
                contentView.setDrawableParameters(R.id.icon, false, -1, resolveColor(),
                        PorterDuff.Mode.SRC_ATOP, -1);
            }
            final boolean gray = isLegacy()
                    && smallIcon.getType() == Icon.TYPE_RESOURCE
                    && getColorUtil().isGrayscaleIcon(mContext, smallIcon.getResId());
            if (!isLegacy() || gray) {
                contentView.setInt(R.id.right_icon,
                        "setBackgroundResource",
                        R.drawable.notification_icon_legacy_bg);

                contentView.setDrawableParameters(
                        R.id.right_icon,
                        true,
                        -1,
                        resolveColor(),
                        PorterDuff.Mode.SRC_ATOP,
                        -1);
            }
        }

        private void sanitizeColor() {
@@ -3418,7 +3383,7 @@ public class Notification implements Parcelable

        private int resolveColor() {
            if (mN.color == COLOR_DEFAULT) {
                return mContext.getColor(R.color.notification_icon_bg_color);
                return mContext.getColor(R.color.notification_icon_default_color);
            }
            return mN.color;
        }
@@ -3622,19 +3587,19 @@ public class Notification implements Parcelable
                contentView.setViewVisibility(R.id.line1, View.VISIBLE);
            }

            // The last line defaults to the subtext, but can be replaced by mSummaryText
            final CharSequence overflowText =
                    mSummaryTextSet ? mSummaryText
                                    : mBuilder.getAllExtras().getCharSequence(EXTRA_SUB_TEXT);
            if (overflowText != null) {
                contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText));
            final CharSequence overflowText = mSummaryTextSet ? mSummaryText : null;
            final CharSequence subText = mBuilder.mN.extras.getCharSequence(EXTRA_SUB_TEXT);
            boolean showSummaryOnBottom = overflowText != null && !overflowText.equals(subText);
            if (showSummaryOnBottom) {
                contentView
                        .setTextViewText(R.id.text, mBuilder.processLegacyText(overflowText));
                contentView.setViewVisibility(R.id.overflow_divider, View.VISIBLE);
                contentView.setViewVisibility(R.id.line3, View.VISIBLE);
            } else {
                // Clear text in case we use the line to show the profile badge.
                contentView.setTextViewText(R.id.text, "");
                contentView.setViewVisibility(R.id.overflow_divider, View.GONE);
                contentView.setViewVisibility(R.id.line3, View.GONE);
                contentView.setTextViewText(com.android.internal.R.id.text, "");
                contentView.setViewVisibility(com.android.internal.R.id.overflow_divider, View.GONE);
                contentView.setViewVisibility(com.android.internal.R.id.line3, View.GONE);
            }

            return contentView;
@@ -3665,19 +3630,6 @@ public class Notification implements Parcelable
            return null;
        }

        /**
         * Changes the padding of the first line such that the big and small content view have the
         * same top padding.
         *
         * @hide
         */
        protected void applyTopPadding(RemoteViews contentView) {
            int topPadding = Builder.calculateTopPadding(mBuilder.mContext,
                    mBuilder.hasThreeLines(),
                    mBuilder.mContext.getResources().getConfiguration().fontScale);
            contentView.setViewPadding(R.id.line1, 0, topPadding, 0, 0);
        }

        /**
         * Apply any style-specific extras to this notification before shipping it out.
         * @hide
@@ -3853,8 +3805,6 @@ public class Notification implements Parcelable

            contentView.setImageViewBitmap(R.id.big_picture, mPicture);

            applyTopPadding(contentView);

            boolean twoTextLines = mBuilder.getAllExtras().getCharSequence(EXTRA_SUB_TEXT) != null
                    && mBuilder.getAllExtras().getCharSequence(EXTRA_TEXT) != null;
            mBuilder.addProfileBadge(contentView,
@@ -3985,8 +3935,6 @@ public class Notification implements Parcelable
            contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines());
            contentView.setViewVisibility(R.id.text2, View.GONE);

            applyTopPadding(contentView);

            mBuilder.shrinkLine3Text(contentView);

            mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
@@ -4139,8 +4087,6 @@ public class Notification implements Parcelable
            contentView.setViewVisibility(R.id.inbox_more,
                    mTexts.size() > rowIds.length ? View.VISIBLE : View.GONE);

            applyTopPadding(contentView);

            mBuilder.shrinkLine3Text(contentView);

            mBuilder.addProfileBadge(contentView, R.id.profile_badge_large_template);
@@ -4334,7 +4280,6 @@ public class Notification implements Parcelable
            }
            styleText(big);
            hideRightIcon(big);
            applyTopPadding(big);
            big.setViewVisibility(android.R.id.progress, View.GONE);
            return big;
        }
+57 −0
Original line number Diff line number Diff line
@@ -1637,6 +1637,47 @@ public class RemoteViews implements Parcelable, Filter {
        public final static int TAG = 14;
    }

    /**
     * Helper action to set layout margin on a View.
     */
    private class ViewMarginEndAction extends Action {
        public ViewMarginEndAction(int viewId, int end) {
            this.viewId = viewId;
            this.end = end;
        }

        public ViewMarginEndAction(Parcel parcel) {
            viewId = parcel.readInt();
            end = parcel.readInt();
        }

        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(TAG);
            dest.writeInt(viewId);
            dest.writeInt(end);
        }

        @Override
        public void apply(View root, ViewGroup rootParent, OnClickHandler handler) {
            final View target = root.findViewById(viewId);
            if (target == null) {
                return;
            }
            ViewGroup.LayoutParams layoutParams = target.getLayoutParams();
            if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
                ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(end);
            }
        }

        public String getActionName() {
            return "ViewMarginEndAction";
        }

        int end;

        public final static int TAG = 19;
    }

    /**
     * Helper action to set a color filter on a compound drawable on a TextView. Supports relative
     * (s/t/e/b) or cardinal (l/t/r/b) arrangement.
@@ -1942,6 +1983,9 @@ public class RemoteViews implements Parcelable, Filter {
                        case SetRemoteInputsAction.TAG:
                            mActions.add(new SetRemoteInputsAction(parcel));
                            break;
                        case ViewMarginEndAction.TAG:
                            mActions.add(new ViewMarginEndAction(parcel));
                            break;
                        default:
                            throw new ActionException("Tag " + tag + " not found");
                    }
@@ -2548,6 +2592,19 @@ public class RemoteViews implements Parcelable, Filter {
        addAction(new ViewPaddingAction(viewId, left, top, right, bottom));
    }

    /**
     * @hide
     * Equivalent to calling {@link android.view.ViewGroup.MarginLayoutParams#setMarginEnd(int)}.
     * Only works if the {@link View#getLayoutParams()} supports margins.
     * Hidden for now since we don't want to support this for all different layout margins yet.
     *
     * @param viewId The id of the view to change
     * @param endMargin the left padding in pixels
     */
    public void setViewLayoutMarginEnd(int viewId, int endMargin) {
        addAction(new ViewMarginEndAction(viewId, endMargin));
    }

    /**
     * Call a method taking one boolean on a view in the layout for this RemoteViews.
     *
+25 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The Android Open Source Project

   Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="14.0dp"
    android:height="14.0dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    <path
        android:pathData="M16.600000,8.600000l-4.600000,4.599999 -4.600000,-4.599999 -1.400000,1.400000 6.000000,6.000000 6.000000,-6.000000z"
        android:fillColor="#FF000000"/>
</vector>
+104 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −45
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2014 The Android Open Source Project
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~      http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License
  -->

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
    android:layout_width="@dimen/notification_large_icon_width"
    android:layout_height="@dimen/notification_large_icon_height"
    android:id="@+id/icon_group"
    >
    <ImageView android:id="@+id/icon"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="12dp"
        android:layout_marginBottom="12dp"
        android:layout_marginStart="12dp"
        android:layout_marginEnd="12dp"
        android:scaleType="centerInside"
        />
    <ImageView android:id="@+id/right_icon"
        android:layout_width="16dp"
        android:layout_height="16dp"
        android:padding="3dp"
        android:layout_gravity="end|bottom"
        android:scaleType="centerInside"
        android:visibility="gone"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        />
</FrameLayout>
Loading