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

Commit c71f559d authored by Ibrahim Yilmaz's avatar Ibrahim Yilmaz Committed by Android (Google) Code Review
Browse files

Merge "[RONs] Enforce segment and point limits" into main

parents 7277dbb2 075fbee7
Loading
Loading
Loading
Loading
+60 −9
Original line number Diff line number Diff line
@@ -11208,8 +11208,8 @@ public class Notification implements Parcelable
        private static final String KEY_SEGMENT_LENGTH = "length";
        private static final String KEY_POINT_POSITION = "position";
        private static final int MAX_PROGRESS_SEGMENT_LIMIT = 15;
        private static final int MAX_PROGRESS_STOP_LIMIT = 5;
        private static final int MAX_PROGRESS_SEGMENT_LIMIT = 10;
        private static final int MAX_PROGRESS_POINT_LIMIT = 4;
        private static final int DEFAULT_PROGRESS_MAX = 100;
        private List<Segment> mProgressSegments = new ArrayList<>();
@@ -11286,7 +11286,9 @@ public class Notification implements Parcelable
                mProgressSegments = new ArrayList<>();
            }
            mProgressSegments.clear();
            mProgressSegments.addAll(progressSegments);
            for (Segment segment : progressSegments) {
                addProgressSegment(segment);
            }
            return this;
        }
@@ -11302,7 +11304,11 @@ public class Notification implements Parcelable
            if (mProgressSegments == null) {
                mProgressSegments = new ArrayList<>();
            }
            if (segment.getLength() > 0) {
                mProgressSegments.add(segment);
            } else {
                Log.w(TAG, "Dropped the segment. The length is not a positive integer.");
            }
            return this;
        }
@@ -11327,7 +11333,14 @@ public class Notification implements Parcelable
         * @see Point
         */
        public @NonNull ProgressStyle setProgressPoints(@NonNull List<Point> points) {
            mProgressPoints = new ArrayList<>(points);
            if (mProgressPoints == null) {
                mProgressPoints = new ArrayList<>();
            }
            mProgressPoints.clear();
            for (Point point: points) {
                addProgressPoint(point);
            }
            return this;
        }
@@ -11348,8 +11361,18 @@ public class Notification implements Parcelable
            if (mProgressPoints == null) {
                mProgressPoints = new ArrayList<>();
            }
            if (point.getPosition() >= 0) {
                mProgressPoints.add(point);
                if (mProgressPoints.size() > MAX_PROGRESS_POINT_LIMIT) {
                    Log.w(TAG, "Progress points limit is reached. First"
                            + MAX_PROGRESS_POINT_LIMIT + " points will be rendered.");
                }
            } else {
                Log.w(TAG, "Dropped the point. The position is a negative integer.");
            }
            return this;
        }
@@ -11384,8 +11407,7 @@ public class Notification implements Parcelable
            } else {
                int progressMax = 0;
                int validSegmentCount = 0;
                for (int i = 0; i < progressSegment.size()
                        && validSegmentCount < MAX_PROGRESS_SEGMENT_LIMIT; i++) {
                for (int i = 0; i < progressSegment.size(); i++) {
                    int segmentLength = progressSegment.get(i).getLength();
                    if (segmentLength > 0) {
                        try {
@@ -11832,6 +11854,30 @@ public class Notification implements Parcelable
                    totalLength = DEFAULT_PROGRESS_MAX;
                    segments.add(sanitizeSegment(new Segment(totalLength), backgroundColor,
                            defaultProgressColor));
                } else if (segments.size() > MAX_PROGRESS_SEGMENT_LIMIT) {
                    // If segment limit is exceeded. All segments will be replaced
                    // with a single segment
                    boolean allSameColor = true;
                    int firstSegmentColor = segments.get(0).getColor();
                    for (int i = 1; i < segments.size(); i++) {
                        if (segments.get(i).getColor() != firstSegmentColor) {
                            allSameColor = false;
                            break;
                        }
                    }
                    // This single segment length has same max as total.
                    final Segment singleSegment = new Segment(totalLength);
                    // Single segment color: if all segments have the same color,
                    // use that color. Otherwise, use 0 / default.
                    singleSegment.setColor(allSameColor ? firstSegmentColor
                            : Notification.COLOR_DEFAULT);
                    segments.clear();
                    segments.add(sanitizeSegment(singleSegment,
                            backgroundColor,
                            defaultProgressColor));
                }
                // Ensure point color contrasts.
@@ -11840,6 +11886,9 @@ public class Notification implements Parcelable
                    final int position = point.getPosition();
                    if (position < 0 || position > totalLength) continue;
                    points.add(sanitizePoint(point, backgroundColor, defaultProgressColor));
                    if (points.size() == MAX_PROGRESS_POINT_LIMIT) {
                        break;
                    }
                }
                model = new NotificationProgressModel(segments, points,
@@ -11868,8 +11917,10 @@ public class Notification implements Parcelable
         * has the same hue as the original color, but is lightened or darkened depending on
         * whether the background is dark or light.
         *
         * @hide
         */
        private int sanitizeProgressColor(@ColorInt int color,
        @VisibleForTesting
        public static int sanitizeProgressColor(@ColorInt int color,
                @ColorInt int bg,
                @ColorInt int defaultColor) {
            return Builder.ensureColorContrast(
+207 −1
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ import androidx.test.filters.SmallTest;

import com.android.internal.R;
import com.android.internal.util.ContrastColorUtil;
import com.android.internal.widget.NotificationProgressModel;

import junit.framework.Assert;

@@ -2414,7 +2415,7 @@ public class NotificationTest {

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_getProgressMax_nooSegments_returnsDefault() {
    public void progressStyle_getProgressMax_noSegments_returnsDefault() {
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        progressStyle.setProgressSegments(Collections.emptyList());
        assertThat(progressStyle.getProgressMax()).isEqualTo(100);
@@ -2457,6 +2458,211 @@ public class NotificationTest {
        assertThat(progressStyle.getProgressMax()).isEqualTo(100);
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_getProgressMax_onSegmentLimitExceeded_returnsSumOfSegmentLength() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        // limit is 10 for ProgressStyle
        for (int i = 0; i < 30; i++) {
            progressStyle
                    .addProgressSegment(new Notification.ProgressStyle.Segment(10));
        }

        // THEN
        assertThat(progressStyle.getProgressMax()).isEqualTo(300);
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_addProgressSegment_dropsInvalidSegments() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        // Segments should be a positive integer.
        progressStyle
                .addProgressSegment(new Notification.ProgressStyle.Segment(0));
        progressStyle
                .addProgressSegment(new Notification.ProgressStyle.Segment(-1));

        // THEN
        assertThat(progressStyle.getProgressSegments()).isEmpty();
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_setProgressSegment_dropsInvalidSegments() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        // Segments should be a positive integer.
        progressStyle
                .setProgressSegments(List.of(new Notification.ProgressStyle.Segment(0),
                        new Notification.ProgressStyle.Segment(-1)));

        // THEN
        assertThat(progressStyle.getProgressSegments()).isEmpty();
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_addProgressPoint_dropsNegativePoints() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        // Points should not be a negative integer.
        progressStyle
                .addProgressPoint(new Notification.ProgressStyle.Point(-1))
                .addProgressPoint(new Notification.ProgressStyle.Point(-100));

        // THEN
        assertThat(progressStyle.getProgressPoints()).isEmpty();
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_setProgressPoint_dropsNegativePoints() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        // Points should not be a negative integer.
        progressStyle
                .setProgressPoints(List.of(new Notification.ProgressStyle.Point(-1),
                        new Notification.ProgressStyle.Point(-100)));

        // THEN
        assertThat(progressStyle.getProgressPoints()).isEmpty();
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_createProgressModel_ignoresPointsExceedingMax() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100));
        // Points should not larger than progress maximum.
        progressStyle
                .addProgressPoint(new Notification.ProgressStyle.Point(101))
                .addProgressPoint(new Notification.ProgressStyle.Point(500));

        // THEN
        assertThat(progressStyle.createProgressModel(Color.BLUE, Color.RED).getPoints()).isEmpty();
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_createProgressModel_ignoresOverLimitPoints() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        progressStyle.addProgressSegment(new Notification.ProgressStyle.Segment(100));

        // maximum 4 points are going to be rendered.
        progressStyle
                .addProgressPoint(new Notification.ProgressStyle.Point(0))
                .addProgressPoint(new Notification.ProgressStyle.Point(20))
                .addProgressPoint(new Notification.ProgressStyle.Point(150))
                .addProgressPoint(new Notification.ProgressStyle.Point(50))
                .addProgressPoint(new Notification.ProgressStyle.Point(70))
                .addProgressPoint(new Notification.ProgressStyle.Point(80))
                .addProgressPoint(new Notification.ProgressStyle.Point(90))
                .addProgressPoint(new Notification.ProgressStyle.Point(95))
                .addProgressPoint(new Notification.ProgressStyle.Point(100));
        final int backgroundColor = Color.RED;
        final int defaultProgressColor = Color.BLUE;
        final int expectedProgressColor = Notification.ProgressStyle.sanitizeProgressColor(
                /* color = */Notification.COLOR_DEFAULT,
                /* bg = */backgroundColor,
                /* defaultColor = */defaultProgressColor);

        // THEN
        assertThat(progressStyle.createProgressModel(defaultProgressColor, backgroundColor)
                .getPoints()).isEqualTo(
                        List.of(new Notification.ProgressStyle.Point(0)
                                .setColor(expectedProgressColor),
                                new Notification.ProgressStyle.Point(20)
                                .setColor(expectedProgressColor),
                                new Notification.ProgressStyle.Point(50)
                                .setColor(expectedProgressColor),
                                new Notification.ProgressStyle.Point(70)
                                .setColor(expectedProgressColor)
                        )
        );
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_createProgressModel_mergeSegmentsOnOverflow() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();

        for (int i = 0; i < 15; i++) {
            progressStyle
                    .addProgressSegment(new Notification.ProgressStyle.Segment(10));
        }

        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
                Color.BLUE, Color.RED);

        // THEN
        assertThat(progressModel.getSegments().size()).isEqualTo(1);
        assertThat(progressModel.getProgressMax()).isEqualTo(150);
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_createProgressModel_useSegmentColorWhenAllMatch() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        final int segmentColor = Color.YELLOW;
        final int defaultProgressColor = Color.BLUE;
        final int backgroundColor = Color.RED;
        // contrast ensured color for segmentColor.
        final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor(
                /* color = */   segmentColor,
                /* bg = */  backgroundColor,
                /* defaultColor = */ defaultProgressColor);

        for (int i = 0; i < 15; i++) {
            progressStyle
                    .addProgressSegment(new Notification.ProgressStyle.Segment(10)
                            .setColor(segmentColor));
        }

        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
                defaultProgressColor, backgroundColor);

        // THEN
        assertThat(progressModel.getSegments())
                .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150)
                        .setColor(expectedSegmentColor)));
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_createProgressModel_useDefaultColorWhenAllNotMatch() {
        // GIVEN
        final Notification.ProgressStyle progressStyle = new Notification.ProgressStyle();
        final int defaultProgressColor = Color.BLUE;
        final int backgroundColor = Color.RED;
        // contrast ensured color for default progress color.
        final int expectedSegmentColor = Notification.ProgressStyle.sanitizeProgressColor(
                /* color = */  defaultProgressColor,
                /* bg = */ backgroundColor,
                /* defaultColor = */ defaultProgressColor);

        for (int i = 0; i < 15; i++) {
            progressStyle
                    .addProgressSegment(new Notification.ProgressStyle.Segment(5)
                            .setColor(Color.BLUE))
                    .addProgressSegment(new Notification.ProgressStyle.Segment(5)
                            .setColor(Color.CYAN));
        }

        final NotificationProgressModel progressModel = progressStyle.createProgressModel(
                defaultProgressColor, backgroundColor);

        // THEN
        assertThat(progressModel.getSegments())
                .isEqualTo(List.of(new Notification.ProgressStyle.Segment(150)
                        .setColor(expectedSegmentColor)));
    }

    @Test
    @EnableFlags(Flags.FLAG_API_RICH_ONGOING)
    public void progressStyle_indeterminate_defaultValueFalse() {