summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Xiaowen Lei <xilei@google.com> 2025-01-15 18:47:32 +0000
committer Xiaowen Lei <xilei@google.com> 2025-01-16 22:34:32 +0000
commit5bb5a9cca2c96b14cf6acf371e4990948f1e8b8e (patch)
tree0225cce13b55fa381f9dfc5f6da6af7b64d4b28b
parent21ea15303ae01f7a10a13cc1fba3d7e2c3dd9ae8 (diff)
Implement fallbacks for when the drawable doesn't have enough width.
Also: - For better clarity, renamed `processAndConvertToViewParts` to `processModelAndConvertToViewParts`, and `processAndConvertToDrawableParts` to `processPartsAndConvertToDrawableParts`. - Fixed pre-existing failures in NotificationProgressModelTest. And a few tests were failing the verifs on process or indeterminateColor. - Cleaned up / reassigned a couple of TODOs. Test notification config, on Felix: - 10 segments, each of length 10 - Case 1: segments of multiple colors - Case 2: segments of same color - 4 points, at 0, 1, 55, 100 Flag: android.app.api_rich_ongoing Fix: 372908709 Bug: 390196782 Test: Post ProgressStyle notifs via test app Test: atest NotificationProgressBarTest Test: atest NotificationProgressModelTest Change-Id: I57333e2c14058298b5caf707442176883162b345
-rw-r--r--core/java/android/app/Notification.java27
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressBar.java180
-rw-r--r--core/java/com/android/internal/widget/NotificationProgressModel.java40
-rw-r--r--core/res/res/values/attrs.xml2
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java380
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/NotificationProgressModelTest.java48
6 files changed, 556 insertions, 121 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 93d751cb9402..fbe5b9449b00 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -11854,7 +11854,7 @@ public class Notification implements Parcelable
// If segment limit is exceeded. All segments will be replaced
// with a single segment
boolean allSameColor = true;
- int firstSegmentColor = segments.get(0).getColor();
+ int firstSegmentColor = segments.getFirst().getColor();
for (int i = 1; i < segments.size(); i++) {
if (segments.get(i).getColor() != firstSegmentColor) {
@@ -11887,8 +11887,31 @@ public class Notification implements Parcelable
}
}
+ // If the segments and points can't all fit inside the progress drawable, the
+ // view will replace all segments with a single segment.
+ final int segmentsFallbackColor;
+ if (segments.size() <= 1) {
+ segmentsFallbackColor = NotificationProgressModel.INVALID_COLOR;
+ } else {
+
+ boolean allSameColor = true;
+ int firstSegmentColor = segments.getFirst().getColor();
+ for (int i = 1; i < segments.size(); i++) {
+ if (segments.get(i).getColor() != firstSegmentColor) {
+ allSameColor = false;
+ break;
+ }
+ }
+ // If the segments are of the same color, the view can just use that color.
+ // In that case there is no need to send the fallback color.
+ segmentsFallbackColor = allSameColor ? NotificationProgressModel.INVALID_COLOR
+ : sanitizeProgressColor(Notification.COLOR_DEFAULT, backgroundColor,
+ defaultProgressColor);
+ }
+
model = new NotificationProgressModel(segments, points,
- Math.clamp(mProgress, 0, totalLength), mIsStyledByProgress);
+ Math.clamp(mProgress, 0, totalLength), mIsStyledByProgress,
+ segmentsFallbackColor);
}
return model;
}
diff --git a/core/java/com/android/internal/widget/NotificationProgressBar.java b/core/java/com/android/internal/widget/NotificationProgressBar.java
index 0d3c470b0e8a..973fd7ecf38b 100644
--- a/core/java/com/android/internal/widget/NotificationProgressBar.java
+++ b/core/java/com/android/internal/widget/NotificationProgressBar.java
@@ -47,6 +47,7 @@ import com.android.internal.widget.NotificationProgressDrawable.DrawablePoint;
import com.android.internal.widget.NotificationProgressDrawable.DrawableSegment;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -161,7 +162,7 @@ public final class NotificationProgressBar extends ProgressBar implements
final int progress = mProgressModel.getProgress();
final int progressMax = mProgressModel.getProgressMax();
- mParts = processAndConvertToViewParts(mProgressModel.getSegments(),
+ mParts = processModelAndConvertToViewParts(mProgressModel.getSegments(),
mProgressModel.getPoints(),
progress,
progressMax);
@@ -439,23 +440,107 @@ public final class NotificationProgressBar extends ProgressBar implements
return;
}
- mProgressDrawableParts = processAndConvertToDrawableParts(
+ final float segSegGap = mNotificationProgressDrawable.getSegSegGap();
+ final float segPointGap = mNotificationProgressDrawable.getSegPointGap();
+ final float pointRadius = mNotificationProgressDrawable.getPointRadius();
+ mProgressDrawableParts = processPartsAndConvertToDrawableParts(
mParts,
width,
- mNotificationProgressDrawable.getSegSegGap(),
- mNotificationProgressDrawable.getSegPointGap(),
- mNotificationProgressDrawable.getPointRadius(),
+ segSegGap,
+ segPointGap,
+ pointRadius,
mHasTrackerIcon
);
- Pair<List<DrawablePart>, Float> p = maybeStretchAndRescaleSegments(
- mParts,
- mProgressDrawableParts,
- mNotificationProgressDrawable.getSegmentMinWidth(),
- mNotificationProgressDrawable.getPointRadius(),
- getProgressFraction(),
- width,
- mProgressModel.isStyledByProgress(),
- mHasTrackerIcon ? 0F : mNotificationProgressDrawable.getSegSegGap());
+
+ final float segmentMinWidth = mNotificationProgressDrawable.getSegmentMinWidth();
+ final float progressFraction = getProgressFraction();
+ final boolean isStyledByProgress = mProgressModel.isStyledByProgress();
+ final float progressGap =
+ mHasTrackerIcon ? 0F : mNotificationProgressDrawable.getSegSegGap();
+ Pair<List<DrawablePart>, Float> p = null;
+ try {
+ p = maybeStretchAndRescaleSegments(
+ mParts,
+ mProgressDrawableParts,
+ segmentMinWidth,
+ pointRadius,
+ progressFraction,
+ width,
+ isStyledByProgress,
+ progressGap
+ );
+ } catch (NotEnoughWidthToFitAllPartsException ex) {
+ Log.w(TAG, "Failed to stretch and rescale segments", ex);
+ }
+
+ List<ProgressStyle.Segment> fallbackSegments = null;
+ if (p == null && mProgressModel.getSegments().size() > 1) {
+ Log.w(TAG, "Falling back to single segment");
+ try {
+ fallbackSegments = List.of(new ProgressStyle.Segment(getMax()).setColor(
+ mProgressModel.getSegmentsFallbackColor()
+ == NotificationProgressModel.INVALID_COLOR
+ ? mProgressModel.getSegments().getFirst().getColor()
+ : mProgressModel.getSegmentsFallbackColor()));
+ p = processModelAndConvertToFinalDrawableParts(
+ fallbackSegments,
+ mProgressModel.getPoints(),
+ mProgressModel.getProgress(),
+ getMax(),
+ width,
+ segSegGap,
+ segPointGap,
+ pointRadius,
+ mHasTrackerIcon,
+ segmentMinWidth,
+ isStyledByProgress
+ );
+ } catch (NotEnoughWidthToFitAllPartsException ex) {
+ Log.w(TAG, "Failed to stretch and rescale segments with single segment fallback",
+ ex);
+ }
+ }
+
+ if (p == null && !mProgressModel.getPoints().isEmpty()) {
+ Log.w(TAG, "Falling back to single segment and no points");
+ if (fallbackSegments == null) {
+ fallbackSegments = List.of(new ProgressStyle.Segment(getMax()).setColor(
+ mProgressModel.getSegmentsFallbackColor()
+ == NotificationProgressModel.INVALID_COLOR
+ ? mProgressModel.getSegments().getFirst().getColor()
+ : mProgressModel.getSegmentsFallbackColor()));
+ }
+ try {
+ p = processModelAndConvertToFinalDrawableParts(
+ fallbackSegments,
+ Collections.emptyList(),
+ mProgressModel.getProgress(),
+ getMax(),
+ width,
+ segSegGap,
+ segPointGap,
+ pointRadius,
+ mHasTrackerIcon,
+ segmentMinWidth,
+ isStyledByProgress
+ );
+ } catch (NotEnoughWidthToFitAllPartsException ex) {
+ Log.w(TAG,
+ "Failed to stretch and rescale segments with single segments and no points",
+ ex);
+ }
+ }
+
+ if (p == null) {
+ Log.w(TAG, "Falling back to no stretching and rescaling");
+ p = maybeSplitDrawableSegmentsByProgress(
+ mParts,
+ mProgressDrawableParts,
+ progressFraction,
+ width,
+ isStyledByProgress,
+ progressGap);
+ }
if (DEBUG) {
Log.d(TAG, "Updating NotificationProgressDrawable parts");
@@ -502,7 +587,11 @@ public final class NotificationProgressBar extends ProgressBar implements
int min = getMin();
int max = getMax();
int range = max - min;
- return range > 0 ? (getProgress() - min) / (float) range : 0;
+ return getProgressFraction(range, (getProgress() - min));
+ }
+
+ private static float getProgressFraction(int progressMax, int progress) {
+ return progressMax > 0 ? progress / (float) progressMax : 0;
}
/**
@@ -636,7 +725,7 @@ public final class NotificationProgressBar extends ProgressBar implements
* Processes the ProgressStyle data and convert to a list of {@code Part}.
*/
@VisibleForTesting
- public static List<Part> processAndConvertToViewParts(
+ public static List<Part> processModelAndConvertToViewParts(
List<ProgressStyle.Segment> segments,
List<ProgressStyle.Point> points,
int progress,
@@ -796,7 +885,7 @@ public final class NotificationProgressBar extends ProgressBar implements
* Processes the list of {@code Part} and convert to a list of {@code DrawablePart}.
*/
@VisibleForTesting
- public static List<DrawablePart> processAndConvertToDrawableParts(
+ public static List<DrawablePart> processPartsAndConvertToDrawableParts(
List<Part> parts,
float totalWidth,
float segSegGap,
@@ -823,7 +912,7 @@ public final class NotificationProgressBar extends ProgressBar implements
// Retract the end position to account for the padding and a point immediately
// after.
final float endOffset = getSegEndOffset(segment, nextPart, pointRadius, segPointGap,
- segSegGap, iPart == nParts - 2, totalWidth, hasTrackerIcon);
+ segSegGap, iPart == nParts - 2, hasTrackerIcon);
final float end = x + segWidth - endOffset;
drawableParts.add(new DrawableSegment(start, end, segment.mColor, segment.mFaded));
@@ -864,7 +953,7 @@ public final class NotificationProgressBar extends ProgressBar implements
}
private static float getSegEndOffset(Segment seg, Part nextPart, float pointRadius,
- float segPointGap, float segSegGap, boolean isSecondToLastPart, float totalWidth,
+ float segPointGap, float segSegGap, boolean isSecondToLastPart,
boolean hasTrackerIcon) {
if (nextPart == null) return 0F;
if (nextPart instanceof Segment nextSeg) {
@@ -894,7 +983,7 @@ public final class NotificationProgressBar extends ProgressBar implements
float totalWidth,
boolean isStyledByProgress,
float progressGap
- ) {
+ ) throws NotEnoughWidthToFitAllPartsException {
final List<DrawableSegment> drawableSegments = drawableParts
.stream()
.filter(DrawableSegment.class::isInstance)
@@ -920,16 +1009,8 @@ public final class NotificationProgressBar extends ProgressBar implements
}
if (totalExcessWidth < 0) {
- // TODO: b/372908709 - throw an error so that the caller can catch and go to fallback
- // option. (instead of return.)
- Log.w(TAG, "Not enough width to satisfy the minimum width for segments.");
- return maybeSplitDrawableSegmentsByProgress(
- parts,
- drawableParts,
- progressFraction,
- totalWidth,
- isStyledByProgress,
- progressGap);
+ throw new NotEnoughWidthToFitAllPartsException(
+ "Not enough width to satisfy the minimum width for segments.");
}
final int nParts = drawableParts.size();
@@ -1003,8 +1084,7 @@ public final class NotificationProgressBar extends ProgressBar implements
final int nParts = parts.size();
for (int iPart = 0; iPart < nParts; iPart++) {
final Part part = parts.get(iPart);
- if (!(part instanceof Segment)) continue;
- final Segment segment = (Segment) part;
+ if (!(part instanceof Segment segment)) continue;
if (startFraction == progressFraction) {
iPartFirstSegmentToStyle = iPart;
rescaledProgressX = segment.mStart;
@@ -1066,11 +1146,37 @@ public final class NotificationProgressBar extends ProgressBar implements
}
/**
+ * Processes the ProgressStyle data and convert to a pair of:
+ * - list of processed {@code DrawablePart}.
+ * - location of progress on the stretched and rescaled progress bar.
+ */
+ @VisibleForTesting
+ public static Pair<List<DrawablePart>, Float> processModelAndConvertToFinalDrawableParts(
+ List<ProgressStyle.Segment> segments,
+ List<ProgressStyle.Point> points,
+ int progress,
+ int progressMax,
+ float totalWidth,
+ float segSegGap,
+ float segPointGap,
+ float pointRadius,
+ boolean hasTrackerIcon,
+ float segmentMinWidth,
+ boolean isStyledByProgress
+ ) throws NotEnoughWidthToFitAllPartsException {
+ List<Part> parts = processModelAndConvertToViewParts(segments, points, progress,
+ progressMax);
+ List<DrawablePart> drawableParts = processPartsAndConvertToDrawableParts(parts, totalWidth,
+ segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ return maybeStretchAndRescaleSegments(parts, drawableParts, segmentMinWidth, pointRadius,
+ getProgressFraction(progressMax, progress), totalWidth, isStyledByProgress,
+ hasTrackerIcon ? 0F : segSegGap);
+ }
+
+ /**
* A part of the progress bar, which is either a {@link Segment} with non-zero length, or a
* {@link Point} with zero length.
*/
- // TODO: b/372908709 - maybe this should be made private? Only test the final
- // NotificationDrawable.Parts.
public interface Part {
}
@@ -1176,4 +1282,10 @@ public final class NotificationProgressBar extends ProgressBar implements
return Objects.hash(mColor);
}
}
+
+ public static class NotEnoughWidthToFitAllPartsException extends Exception {
+ public NotEnoughWidthToFitAllPartsException(String message) {
+ super(message);
+ }
+ }
}
diff --git a/core/java/com/android/internal/widget/NotificationProgressModel.java b/core/java/com/android/internal/widget/NotificationProgressModel.java
index e8cb37e8f19b..7eaf861f2af4 100644
--- a/core/java/com/android/internal/widget/NotificationProgressModel.java
+++ b/core/java/com/android/internal/widget/NotificationProgressModel.java
@@ -16,7 +16,6 @@
package com.android.internal.widget;
-
import android.annotation.ColorInt;
import android.annotation.FlaggedApi;
import android.annotation.NonNull;
@@ -45,24 +44,29 @@ import java.util.Objects;
*/
@FlaggedApi(Flags.FLAG_API_RICH_ONGOING)
public final class NotificationProgressModel {
- private static final int INVALID_INDETERMINATE_COLOR = Color.TRANSPARENT;
+ public static final int INVALID_COLOR = Color.TRANSPARENT;
private static final String KEY_SEGMENTS = "segments";
private static final String KEY_POINTS = "points";
private static final String KEY_PROGRESS = "progress";
private static final String KEY_IS_STYLED_BY_PROGRESS = "isStyledByProgress";
+ private static final String KEY_SEGMENTS_FALLBACK_COLOR = "segmentsFallColor";
private static final String KEY_INDETERMINATE_COLOR = "indeterminateColor";
private final List<Segment> mSegments;
private final List<Point> mPoints;
private final int mProgress;
private final boolean mIsStyledByProgress;
@ColorInt
+ private final int mSegmentsFallbackColor;
+
+ @ColorInt
private final int mIndeterminateColor;
public NotificationProgressModel(
@NonNull List<Segment> segments,
@NonNull List<Point> points,
int progress,
- boolean isStyledByProgress
+ boolean isStyledByProgress,
+ @ColorInt int segmentsFallbackColor
) {
Preconditions.checkArgument(progress >= 0);
Preconditions.checkArgument(!segments.isEmpty());
@@ -70,17 +74,19 @@ public final class NotificationProgressModel {
mPoints = points;
mProgress = progress;
mIsStyledByProgress = isStyledByProgress;
- mIndeterminateColor = INVALID_INDETERMINATE_COLOR;
+ mSegmentsFallbackColor = segmentsFallbackColor;
+ mIndeterminateColor = INVALID_COLOR;
}
public NotificationProgressModel(
@ColorInt int indeterminateColor
) {
- Preconditions.checkArgument(indeterminateColor != INVALID_INDETERMINATE_COLOR);
+ Preconditions.checkArgument(indeterminateColor != INVALID_COLOR);
mSegments = Collections.emptyList();
mPoints = Collections.emptyList();
mProgress = 0;
mIsStyledByProgress = false;
+ mSegmentsFallbackColor = INVALID_COLOR;
mIndeterminateColor = indeterminateColor;
}
@@ -105,12 +111,17 @@ public final class NotificationProgressModel {
}
@ColorInt
+ public int getSegmentsFallbackColor() {
+ return mSegmentsFallbackColor;
+ }
+
+ @ColorInt
public int getIndeterminateColor() {
return mIndeterminateColor;
}
public boolean isIndeterminate() {
- return mIndeterminateColor != INVALID_INDETERMINATE_COLOR;
+ return mIndeterminateColor != INVALID_COLOR;
}
/**
@@ -119,7 +130,7 @@ public final class NotificationProgressModel {
@NonNull
public Bundle toBundle() {
final Bundle bundle = new Bundle();
- if (mIndeterminateColor != INVALID_INDETERMINATE_COLOR) {
+ if (mIndeterminateColor != INVALID_COLOR) {
bundle.putInt(KEY_INDETERMINATE_COLOR, mIndeterminateColor);
} else {
bundle.putParcelableList(KEY_SEGMENTS,
@@ -128,6 +139,9 @@ public final class NotificationProgressModel {
Notification.ProgressStyle.getProgressPointsAsBundleList(mPoints));
bundle.putInt(KEY_PROGRESS, mProgress);
bundle.putBoolean(KEY_IS_STYLED_BY_PROGRESS, mIsStyledByProgress);
+ if (mSegmentsFallbackColor != INVALID_COLOR) {
+ bundle.putInt(KEY_SEGMENTS_FALLBACK_COLOR, mSegmentsFallbackColor);
+ }
}
return bundle;
}
@@ -138,8 +152,8 @@ public final class NotificationProgressModel {
@NonNull
public static NotificationProgressModel fromBundle(@NonNull Bundle bundle) {
final int indeterminateColor = bundle.getInt(KEY_INDETERMINATE_COLOR,
- INVALID_INDETERMINATE_COLOR);
- if (indeterminateColor != INVALID_INDETERMINATE_COLOR) {
+ INVALID_COLOR);
+ if (indeterminateColor != INVALID_COLOR) {
return new NotificationProgressModel(indeterminateColor);
} else {
final List<Segment> segments =
@@ -150,7 +164,10 @@ public final class NotificationProgressModel {
bundle.getParcelableArrayList(KEY_POINTS, Bundle.class));
final int progress = bundle.getInt(KEY_PROGRESS);
final boolean isStyledByProgress = bundle.getBoolean(KEY_IS_STYLED_BY_PROGRESS);
- return new NotificationProgressModel(segments, points, progress, isStyledByProgress);
+ final int segmentsFallbackColor = bundle.getInt(KEY_SEGMENTS_FALLBACK_COLOR,
+ INVALID_COLOR);
+ return new NotificationProgressModel(segments, points, progress, isStyledByProgress,
+ segmentsFallbackColor);
}
}
@@ -161,6 +178,7 @@ public final class NotificationProgressModel {
+ ", mPoints=" + mPoints
+ ", mProgress=" + mProgress
+ ", mIsStyledByProgress=" + mIsStyledByProgress
+ + ", mSegmentsFallbackColor=" + mSegmentsFallbackColor
+ ", mIndeterminateColor=" + mIndeterminateColor + "}";
}
@@ -171,6 +189,7 @@ public final class NotificationProgressModel {
final NotificationProgressModel that = (NotificationProgressModel) o;
return mProgress == that.mProgress
&& mIsStyledByProgress == that.mIsStyledByProgress
+ && mSegmentsFallbackColor == that.mSegmentsFallbackColor
&& mIndeterminateColor == that.mIndeterminateColor
&& Objects.equals(mSegments, that.mSegments)
&& Objects.equals(mPoints, that.mPoints);
@@ -182,6 +201,7 @@ public final class NotificationProgressModel {
mPoints,
mProgress,
mIsStyledByProgress,
+ mSegmentsFallbackColor,
mIndeterminateColor);
}
}
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index bd1d3033165e..a1f85c380a95 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -7585,7 +7585,7 @@
<!-- Used to config the segments of a NotificationProgressDrawable. -->
<!-- @hide internal use only -->
<declare-styleable name="NotificationProgressDrawableSegments">
- <!-- TODO: b/372908709 - maybe move this to NotificationProgressBar, because that's the only
+ <!-- TODO: b/390196782 - maybe move this to NotificationProgressBar, because that's the only
place this is used actually. Same for NotificationProgressDrawable.segSegGap/segPointGap
above. -->
<!-- Minimum required drawing width. The drawing width refers to the width after
diff --git a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
index 9818e19cea02..ec19c0c52759 100644
--- a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressBarTest.java
@@ -16,6 +16,8 @@
package com.android.internal.widget;
+import static com.android.internal.widget.NotificationProgressBar.NotEnoughWidthToFitAllPartsException;
+
import static com.google.common.truth.Truth.assertThat;
import android.app.Notification.ProgressStyle;
@@ -35,6 +37,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
@RunWith(AndroidJUnit4.class)
@@ -47,7 +50,7 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -60,7 +63,7 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -73,7 +76,7 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -86,7 +89,7 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -98,20 +101,21 @@ public class NotificationProgressBarTest {
int progress = -50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@Test
- public void processAndConvertToParts_progressIsZero() {
+ public void processAndConvertToParts_progressIsZero()
+ throws NotificationProgressBar.NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(100).setColor(Color.RED));
List<ProgressStyle.Point> points = new ArrayList<>();
int progress = 0;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(List.of(new Segment(1f, Color.RED)));
@@ -123,8 +127,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 300, Color.RED)));
@@ -148,15 +153,16 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_progressAtMax() {
+ public void processAndConvertToParts_progressAtMax()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(100).setColor(Color.RED));
List<ProgressStyle.Point> points = new ArrayList<>();
int progress = 100;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(List.of(new Segment(1f, Color.RED)));
@@ -168,8 +174,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 300, Color.RED)));
@@ -195,7 +202,7 @@ public class NotificationProgressBarTest {
int progress = 150;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -208,7 +215,7 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@@ -221,12 +228,62 @@ public class NotificationProgressBarTest {
int progress = 50;
int progressMax = 100;
- NotificationProgressBar.processAndConvertToViewParts(segments, points, progress,
+ NotificationProgressBar.processModelAndConvertToViewParts(segments, points, progress,
progressMax);
}
@Test
- public void processAndConvertToParts_multipleSegmentsWithoutPoints() {
+ public void processAndConvertToParts_singleSegmentWithoutPoints()
+ throws NotEnoughWidthToFitAllPartsException {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ int progress = 60;
+ int progressMax = 100;
+
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
+
+ List<Part> expectedParts = new ArrayList<>(
+ List.of(new Segment(1, Color.BLUE)));
+
+ assertThat(parts).isEqualTo(expectedParts);
+
+ float drawableWidth = 300;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ List<DrawablePart> expectedDrawableParts = new ArrayList<>(
+ List.of(new DrawableSegment(0, 300, Color.BLUE)));
+
+ assertThat(drawableParts).isEqualTo(expectedDrawableParts);
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<DrawablePart>, Float> p = NotificationProgressBar.maybeStretchAndRescaleSegments(
+ parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
+ 300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+
+ // Colors with 40% opacity
+ int fadedBlue = 0x660000FF;
+ expectedDrawableParts = new ArrayList<>(
+ List.of(new DrawableSegment(0, 180, Color.BLUE),
+ new DrawableSegment(180, 300, fadedBlue, true)));
+
+ assertThat(p.second).isEqualTo(180);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
+
+ @Test
+ public void processAndConvertToParts_multipleSegmentsWithoutPoints()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
@@ -234,8 +291,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.50f, Color.RED), new Segment(0.50f, Color.GREEN)));
@@ -248,8 +305,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 146, Color.RED),
@@ -274,15 +332,16 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_multipleSegmentsWithoutPoints_noTracker() {
+ public void processAndConvertToParts_multipleSegmentsWithoutPoints_noTracker()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
List<ProgressStyle.Point> points = new ArrayList<>();
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.50f, Color.RED), new Segment(0.50f, Color.GREEN)));
@@ -295,8 +354,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = false;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 146, Color.RED),
@@ -321,7 +381,8 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_singleSegmentWithPoints() {
+ public void processAndConvertToParts_singleSegmentWithPoints()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
List<ProgressStyle.Point> points = new ArrayList<>();
@@ -332,8 +393,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.15f, Color.BLUE),
@@ -354,8 +415,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 35, Color.BLUE),
@@ -396,7 +458,8 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_multipleSegmentsWithPoints() {
+ public void processAndConvertToParts_multipleSegmentsWithPoints()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
@@ -408,8 +471,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.15f, Color.RED),
@@ -430,8 +493,9 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 35, Color.RED), new DrawablePoint(39, 51, Color.RED),
@@ -473,7 +537,8 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_multipleSegmentsWithPointsAtStartAndEnd() {
+ public void processAndConvertToParts_multipleSegmentsWithPointsAtStartAndEnd()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
@@ -485,8 +550,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Point(Color.RED),
@@ -505,8 +570,10 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawablePoint(0, 12, Color.RED),
@@ -547,7 +614,8 @@ public class NotificationProgressBarTest {
// The points are so close to start/end that they would go out of bounds without the minimum
// segment width requirement.
@Test
- public void processAndConvertToParts_multipleSegmentsWithPointsNearStartAndEnd() {
+ public void processAndConvertToParts_multipleSegmentsWithPointsNearStartAndEnd()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
@@ -559,8 +627,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.01f, Color.RED),
@@ -581,8 +649,10 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, -7, Color.RED),
@@ -625,7 +695,8 @@ public class NotificationProgressBarTest {
}
@Test
- public void processAndConvertToParts_multipleSegmentsWithPoints_notStyledByProgress() {
+ public void processAndConvertToParts_multipleSegmentsWithPoints_notStyledByProgress()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
@@ -636,8 +707,8 @@ public class NotificationProgressBarTest {
int progress = 60;
int progressMax = 100;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Segment(0.15f, Color.RED), new Point(Color.RED),
@@ -653,8 +724,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawableSegment(0, 35, Color.RED), new DrawablePoint(39, 51, Color.RED),
@@ -691,7 +763,8 @@ public class NotificationProgressBarTest {
// The only difference from the `zeroWidthDrawableSegment` test below is the longer
// segmentMinWidth (= 16dp).
@Test
- public void maybeStretchAndRescaleSegments_negativeWidthDrawableSegment() {
+ public void maybeStretchAndRescaleSegments_negativeWidthDrawableSegment()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
@@ -702,8 +775,8 @@ public class NotificationProgressBarTest {
int progress = 1000;
int progressMax = 1000;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Point(Color.BLUE), new Segment(0.1f, Color.BLUE),
@@ -717,8 +790,10 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawablePoint(0, 12, Color.BLUE),
@@ -749,7 +824,8 @@ public class NotificationProgressBarTest {
// The only difference from the `negativeWidthDrawableSegment` test above is the shorter
// segmentMinWidth (= 10dp).
@Test
- public void maybeStretchAndRescaleSegments_zeroWidthDrawableSegment() {
+ public void maybeStretchAndRescaleSegments_zeroWidthDrawableSegment()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
@@ -760,8 +836,8 @@ public class NotificationProgressBarTest {
int progress = 1000;
int progressMax = 1000;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Point(Color.BLUE), new Segment(0.1f, Color.BLUE),
@@ -775,8 +851,10 @@ public class NotificationProgressBarTest {
float segPointGap = 4;
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawablePoint(0, 12, Color.BLUE),
@@ -805,7 +883,8 @@ public class NotificationProgressBarTest {
}
@Test
- public void maybeStretchAndRescaleSegments_noStretchingNecessary() {
+ public void maybeStretchAndRescaleSegments_noStretchingNecessary()
+ throws NotEnoughWidthToFitAllPartsException {
List<ProgressStyle.Segment> segments = new ArrayList<>();
segments.add(new ProgressStyle.Segment(200).setColor(Color.BLUE));
segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
@@ -816,8 +895,8 @@ public class NotificationProgressBarTest {
int progress = 1000;
int progressMax = 1000;
- List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
- progress, progressMax);
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
List<Part> expectedParts = new ArrayList<>(
List.of(new Point(Color.BLUE), new Segment(0.2f, Color.BLUE),
@@ -832,8 +911,9 @@ public class NotificationProgressBarTest {
float pointRadius = 6;
boolean hasTrackerIcon = true;
- List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
- parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
List<DrawablePart> expectedDrawableParts = new ArrayList<>(
List.of(new DrawablePoint(0, 12, Color.BLUE),
@@ -854,4 +934,168 @@ public class NotificationProgressBarTest {
assertThat(p.second).isEqualTo(200);
assertThat(p.first).isEqualTo(expectedDrawableParts);
}
+
+ @Test(expected = NotEnoughWidthToFitAllPartsException.class)
+ public void maybeStretchAndRescaleSegments_notEnoughWidthToFitAllParts()
+ throws NotEnoughWidthToFitAllPartsException {
+ final int orange = 0xff7f50;
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(10).setColor(orange));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.YELLOW));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.GREEN));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.RED));
+ segments.add(new ProgressStyle.Segment(10).setColor(orange));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.YELLOW));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.BLUE));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.GREEN));
+ segments.add(new ProgressStyle.Segment(10).setColor(Color.RED));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ points.add(new ProgressStyle.Point(0).setColor(orange));
+ points.add(new ProgressStyle.Point(1).setColor(Color.BLUE));
+ points.add(new ProgressStyle.Point(55).setColor(Color.BLUE));
+ points.add(new ProgressStyle.Point(100).setColor(orange));
+ int progress = 50;
+ int progressMax = 100;
+
+ List<Part> parts = NotificationProgressBar.processModelAndConvertToViewParts(segments,
+ points, progress, progressMax);
+
+ List<Part> expectedParts = new ArrayList<>(
+ List.of(new Point(orange),
+ new Segment(0.01f, orange),
+ new Point(Color.BLUE),
+ new Segment(0.09f, orange),
+ new Segment(0.1f, Color.YELLOW),
+ new Segment(0.1f, Color.BLUE),
+ new Segment(0.1f, Color.GREEN),
+ new Segment(0.1f, Color.RED),
+ new Segment(0.05f, orange),
+ new Point(Color.BLUE),
+ new Segment(0.05f, orange),
+ new Segment(0.1f, Color.YELLOW),
+ new Segment(0.1f, Color.BLUE),
+ new Segment(0.1f, Color.GREEN),
+ new Segment(0.1f, Color.RED),
+ new Point(orange)));
+
+ assertThat(parts).isEqualTo(expectedParts);
+
+ // For the list of ProgressStyle.Part used in this test, 300 is the minimum width.
+ float drawableWidth = 299;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+
+ List<DrawablePart> drawableParts =
+ NotificationProgressBar.processPartsAndConvertToDrawableParts(
+ parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);
+
+ // Skips the validation of the intermediate list of DrawableParts.
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ NotificationProgressBar.maybeStretchAndRescaleSegments(
+ parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
+ 300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);
+ }
+
+ @Test
+ public void processModelAndConvertToFinalDrawableParts_singleSegmentWithPoints()
+ throws NotEnoughWidthToFitAllPartsException {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ List<ProgressStyle.Point> points = new ArrayList<>();
+ points.add(new ProgressStyle.Point(15).setColor(Color.RED));
+ points.add(new ProgressStyle.Point(25).setColor(Color.BLUE));
+ points.add(new ProgressStyle.Point(60).setColor(Color.BLUE));
+ points.add(new ProgressStyle.Point(75).setColor(Color.YELLOW));
+ int progress = 60;
+ int progressMax = 100;
+
+ float drawableWidth = 300;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<DrawablePart>, Float> p =
+ NotificationProgressBar.processModelAndConvertToFinalDrawableParts(
+ segments,
+ points,
+ progress,
+ progressMax,
+ drawableWidth,
+ segSegGap,
+ segPointGap,
+ pointRadius,
+ hasTrackerIcon,
+ segmentMinWidth,
+ isStyledByProgress
+ );
+
+ // Colors with 40% opacity
+ int fadedBlue = 0x660000FF;
+ int fadedYellow = 0x66FFFF00;
+ List<DrawablePart> expectedDrawableParts = new ArrayList<>(
+ List.of(new DrawableSegment(0, 34.219177F, Color.BLUE),
+ new DrawablePoint(38.219177F, 50.219177F, Color.RED),
+ new DrawableSegment(54.219177F, 70.21918F, Color.BLUE),
+ new DrawablePoint(74.21918F, 86.21918F, Color.BLUE),
+ new DrawableSegment(90.21918F, 172.38356F, Color.BLUE),
+ new DrawablePoint(176.38356F, 188.38356F, Color.BLUE),
+ new DrawableSegment(192.38356F, 217.0137F, fadedBlue, true),
+ new DrawablePoint(221.0137F, 233.0137F, fadedYellow),
+ new DrawableSegment(237.0137F, 300F, fadedBlue, true)));
+
+ assertThat(p.second).isEqualTo(182.38356F);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
+
+ @Test
+ public void processModelAndConvertToFinalDrawableParts_singleSegmentWithoutPoints()
+ throws NotEnoughWidthToFitAllPartsException {
+ List<ProgressStyle.Segment> segments = new ArrayList<>();
+ segments.add(new ProgressStyle.Segment(100).setColor(Color.BLUE));
+ int progress = 60;
+ int progressMax = 100;
+
+ float drawableWidth = 100;
+ float segSegGap = 4;
+ float segPointGap = 4;
+ float pointRadius = 6;
+ boolean hasTrackerIcon = true;
+
+ float segmentMinWidth = 16;
+ boolean isStyledByProgress = true;
+
+ Pair<List<DrawablePart>, Float> p =
+ NotificationProgressBar.processModelAndConvertToFinalDrawableParts(
+ segments,
+ Collections.emptyList(),
+ progress,
+ progressMax,
+ drawableWidth,
+ segSegGap,
+ segPointGap,
+ pointRadius,
+ hasTrackerIcon,
+ segmentMinWidth,
+ isStyledByProgress
+ );
+
+ // Colors with 40% opacity
+ int fadedBlue = 0x660000FF;
+ List<DrawablePart> expectedDrawableParts = new ArrayList<>(
+ List.of(new DrawableSegment(0, 60.000004F, Color.BLUE),
+ new DrawableSegment(60.000004F, 100, fadedBlue, true)));
+
+ assertThat(p.second).isWithin(1e-5f).of(60);
+ assertThat(p.first).isEqualTo(expectedDrawableParts);
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressModelTest.java b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressModelTest.java
index 962399e48fb8..e1f5b1c2e4a4 100644
--- a/core/tests/coretests/src/com/android/internal/widget/NotificationProgressModelTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/NotificationProgressModelTest.java
@@ -49,7 +49,8 @@ public class NotificationProgressModelTest {
new NotificationProgressModel(List.of(),
List.of(),
10,
- false);
+ false,
+ Color.TRANSPARENT);
}
@Test(expected = IllegalArgumentException.class)
@@ -58,7 +59,8 @@ public class NotificationProgressModelTest {
List.of(new Notification.ProgressStyle.Segment(50).setColor(Color.YELLOW)),
List.of(),
-1,
- false);
+ false,
+ Color.TRANSPARENT);
}
@Test
@@ -74,14 +76,15 @@ public class NotificationProgressModelTest {
// THEN
assertThat(restoredModel.getIndeterminateColor()).isEqualTo(Color.RED);
assertThat(restoredModel.isIndeterminate()).isTrue();
- assertThat(restoredModel.getProgress()).isEqualTo(-1);
+ assertThat(restoredModel.getProgress()).isEqualTo(0);
assertThat(restoredModel.getSegments()).isEmpty();
assertThat(restoredModel.getPoints()).isEmpty();
assertThat(restoredModel.isStyledByProgress()).isFalse();
+ assertThat(restoredModel.getSegmentsFallbackColor()).isEqualTo(Color.TRANSPARENT);
}
@Test
- public void save_and_restore_non_indeterminate_progress_model() {
+ public void save_and_restore_determinate_progress_model() {
// GIVEN
final List<Notification.ProgressStyle.Segment> segments = List.of(
new Notification.ProgressStyle.Segment(50).setColor(Color.YELLOW),
@@ -92,7 +95,8 @@ public class NotificationProgressModelTest {
final NotificationProgressModel savedModel = new NotificationProgressModel(segments,
points,
100,
- true);
+ true,
+ Color.RED);
final Bundle bundle = savedModel.toBundle();
@@ -106,6 +110,38 @@ public class NotificationProgressModelTest {
assertThat(restoredModel.getPoints()).isEqualTo(points);
assertThat(restoredModel.getProgress()).isEqualTo(100);
assertThat(restoredModel.isStyledByProgress()).isTrue();
- assertThat(restoredModel.getIndeterminateColor()).isEqualTo(-1);
+ assertThat(restoredModel.getSegmentsFallbackColor()).isEqualTo(Color.RED);
+ assertThat(restoredModel.getIndeterminateColor()).isEqualTo(Color.TRANSPARENT);
+ }
+
+ @Test
+ public void save_and_restore_non_determinate_progress_model_segments_fallback_color_invalid() {
+ // GIVEN
+ final List<Notification.ProgressStyle.Segment> segments = List.of(
+ new Notification.ProgressStyle.Segment(50).setColor(Color.YELLOW),
+ new Notification.ProgressStyle.Segment(50).setColor(Color.YELLOW));
+ final List<Notification.ProgressStyle.Point> points = List.of(
+ new Notification.ProgressStyle.Point(0).setColor(Color.RED),
+ new Notification.ProgressStyle.Point(20).setColor(Color.BLUE));
+ final NotificationProgressModel savedModel = new NotificationProgressModel(segments,
+ points,
+ 100,
+ true,
+ Color.TRANSPARENT);
+
+ final Bundle bundle = savedModel.toBundle();
+
+ // WHEN
+ final NotificationProgressModel restoredModel =
+ NotificationProgressModel.fromBundle(bundle);
+
+ // THEN
+ assertThat(restoredModel.isIndeterminate()).isFalse();
+ assertThat(restoredModel.getSegments()).isEqualTo(segments);
+ assertThat(restoredModel.getPoints()).isEqualTo(points);
+ assertThat(restoredModel.getProgress()).isEqualTo(100);
+ assertThat(restoredModel.isStyledByProgress()).isTrue();
+ assertThat(restoredModel.getSegmentsFallbackColor()).isEqualTo(Color.TRANSPARENT);
+ assertThat(restoredModel.getIndeterminateColor()).isEqualTo(Color.TRANSPARENT);
}
}