blob: d86e51316c2d49318add350649be49c13923535c [file] [log] [blame]
Ram Parameswaran619cc5f2020-11-03 21:07:41 -08001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package androidx.car.app.navigation.model;
18
19import static androidx.annotation.RestrictTo.Scope.LIBRARY;
20
Jorge Pereira07502ba2021-01-21 09:38:30 -080021import static java.util.Objects.requireNonNull;
22
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080023import androidx.annotation.IntDef;
Ram Parameswaran25c966e2021-01-15 11:42:53 -080024import androidx.annotation.IntRange;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080025import androidx.annotation.Keep;
26import androidx.annotation.NonNull;
27import androidx.annotation.Nullable;
28import androidx.annotation.RestrictTo;
Ram Parameswaranf5db48f2021-03-10 10:42:58 -080029import androidx.car.app.annotations.CarProtocol;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080030import androidx.car.app.model.CarIcon;
31import androidx.car.app.model.constraints.CarIconConstraints;
32
33import java.lang.annotation.Retention;
34import java.lang.annotation.RetentionPolicy;
35import java.util.Objects;
36
37/** Information about a maneuver that the driver will be required to perform. */
Jorge Pereira1d7c7022021-01-26 13:30:15 -080038// TODO(b/154671667): Update when host(s) updates or a scheme for auto sync is established.
Ram Parameswaranf5db48f2021-03-10 10:42:58 -080039@CarProtocol
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080040public final class Maneuver {
41 /**
42 * Possible maneuver types.
43 *
44 * @hide
45 */
46 @IntDef({
47 TYPE_UNKNOWN,
48 TYPE_DEPART,
49 TYPE_NAME_CHANGE,
50 TYPE_KEEP_LEFT,
51 TYPE_KEEP_RIGHT,
52 TYPE_TURN_SLIGHT_LEFT,
53 TYPE_TURN_SLIGHT_RIGHT,
54 TYPE_TURN_NORMAL_LEFT,
55 TYPE_TURN_NORMAL_RIGHT,
56 TYPE_TURN_SHARP_LEFT,
57 TYPE_TURN_SHARP_RIGHT,
58 TYPE_U_TURN_LEFT,
59 TYPE_U_TURN_RIGHT,
60 TYPE_ON_RAMP_SLIGHT_LEFT,
61 TYPE_ON_RAMP_SLIGHT_RIGHT,
62 TYPE_ON_RAMP_NORMAL_LEFT,
63 TYPE_ON_RAMP_NORMAL_RIGHT,
64 TYPE_ON_RAMP_SHARP_LEFT,
65 TYPE_ON_RAMP_SHARP_RIGHT,
66 TYPE_ON_RAMP_U_TURN_LEFT,
67 TYPE_ON_RAMP_U_TURN_RIGHT,
68 TYPE_OFF_RAMP_SLIGHT_LEFT,
69 TYPE_OFF_RAMP_SLIGHT_RIGHT,
70 TYPE_OFF_RAMP_NORMAL_LEFT,
71 TYPE_OFF_RAMP_NORMAL_RIGHT,
72 TYPE_FORK_LEFT,
73 TYPE_FORK_RIGHT,
74 TYPE_MERGE_LEFT,
75 TYPE_MERGE_RIGHT,
76 TYPE_MERGE_SIDE_UNSPECIFIED,
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080077 TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW,
78 TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE,
79 TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW,
80 TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE,
81 TYPE_STRAIGHT,
82 TYPE_FERRY_BOAT,
83 TYPE_FERRY_TRAIN,
84 TYPE_DESTINATION,
85 TYPE_DESTINATION_STRAIGHT,
86 TYPE_DESTINATION_LEFT,
Billy Lamd5488f42020-11-23 22:54:47 -080087 TYPE_DESTINATION_RIGHT,
88 TYPE_ROUNDABOUT_ENTER_CW,
89 TYPE_ROUNDABOUT_EXIT_CW,
90 TYPE_ROUNDABOUT_ENTER_CCW,
91 TYPE_ROUNDABOUT_EXIT_CCW,
92 TYPE_FERRY_BOAT_LEFT,
93 TYPE_FERRY_BOAT_RIGHT,
94 TYPE_FERRY_TRAIN_LEFT,
95 TYPE_FERRY_TRAIN_RIGHT,
Ram Parameswaran619cc5f2020-11-03 21:07:41 -080096 })
97 @Retention(RetentionPolicy.SOURCE)
98 @RestrictTo(LIBRARY)
99 public @interface Type {
100 }
101
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800102 /**
103 * Maneuver type is unknown, no maneuver information should be displayed.
104 *
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800105 * <p>This type may be interpreted differently depending on the consumer. In some
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800106 * cases the previous maneuver will continue to be shown while in others no maneuver will be
107 * shown at all.
108 */
109 @Type
110 public static final int TYPE_UNKNOWN = 0;
111
112 /**
113 * Starting point of the navigation.
114 *
115 * <p>For example, "Start driving on Main St."
116 */
117 @Type
118 public static final int TYPE_DEPART = 1;
119
120 /**
121 * No turn, but the street name changes.
122 *
123 * <p>For example, "Continue on Main St."
124 */
125 @Type
126 public static final int TYPE_NAME_CHANGE = 2;
127
128 /**
129 * No turn, from 0 (included) to 10 (excluded) degrees.
130 *
131 * <p>This is used in contrast to {@link #TYPE_STRAIGHT} for disambiguating cases where there is
132 * more than one option to go into the same general direction.
133 */
134 @Type
135 public static final int TYPE_KEEP_LEFT = 3;
136
137 /**
138 * No turn, from 0 (included) to 10 (excluded) degrees.
139 *
140 * <p>This is used in contrast to {@link #TYPE_STRAIGHT} for disambiguating cases where there is
141 * more than one option to go into the same general direction.
142 */
143 @Type
144 public static final int TYPE_KEEP_RIGHT = 4;
145
146 /** Slight left turn at an intersection, from 10 (included) to 45 (excluded) degrees. */
147 @Type
148 public static final int TYPE_TURN_SLIGHT_LEFT = 5;
149
150 /** Slight right turn at an intersection, from 10 (included) to 45 (excluded) degrees. */
151 @Type
152 public static final int TYPE_TURN_SLIGHT_RIGHT = 6;
153
154 /** Regular left turn at an intersection, from 45 (included) to 135 (excluded) degrees. */
155 @Type
156 public static final int TYPE_TURN_NORMAL_LEFT = 7;
157
158 /** Regular right turn at an intersection, from 45 (included) to 135 (excluded) degrees. */
159 @Type
160 public static final int TYPE_TURN_NORMAL_RIGHT = 8;
161
162 /** Sharp left turn at an intersection, from 135 (included) to 175 (excluded) degrees. */
163 @Type
164 public static final int TYPE_TURN_SHARP_LEFT = 9;
165
166 /** Sharp right turn at an intersection, from 135 (included) to 175 (excluded) degrees. */
167 @Type
168 public static final int TYPE_TURN_SHARP_RIGHT = 10;
169
170 /**
171 * Left turn onto the opposite side of the same street, from 175 (included) to 180 (included)
172 * degrees.
173 */
174 @Type
175 public static final int TYPE_U_TURN_LEFT = 11;
176
177 /**
178 * A right turn onto the opposite side of the same street, from 175 (included) to 180 (included)
179 * degrees.
180 */
181 @Type
182 public static final int TYPE_U_TURN_RIGHT = 12;
183
184 /**
185 * Slight left turn to enter a turnpike or freeway, from 10 (included) to 45 (excluded) degrees.
186 */
187 @Type
188 public static final int TYPE_ON_RAMP_SLIGHT_LEFT = 13;
189
190 /**
191 * Slight right turn to enter a turnpike or freeway, from 10 (included) to 45 (excluded)
192 * degrees.
193 */
194 @Type
195 public static final int TYPE_ON_RAMP_SLIGHT_RIGHT = 14;
196
197 /**
198 * Regular left turn to enter a turnpike or freeway, from 45 (included) to 135 (excluded)
199 * degrees.
200 */
201 @Type
202 public static final int TYPE_ON_RAMP_NORMAL_LEFT = 15;
203
204 /**
205 * Regular right turn to enter a turnpike or freeway, from 45 (included) to 135 (excluded)
206 * degrees.
207 */
208 @Type
209 public static final int TYPE_ON_RAMP_NORMAL_RIGHT = 16;
210
211 /**
212 * Sharp left turn to enter a turnpike or freeway, from 135 (included) to 175 (excluded)
213 * degrees.
214 */
215 @Type
216 public static final int TYPE_ON_RAMP_SHARP_LEFT = 17;
217
218 /**
219 * Sharp right turn to enter a turnpike or freeway, from 135 (included) to 175 (excluded)
220 * degrees.
221 */
222 @Type
223 public static final int TYPE_ON_RAMP_SHARP_RIGHT = 18;
224
225 /**
226 * Left turn onto the opposite side of the same street to enter a turnpike or freeway, from 175
227 * (included) to 180 (included).
228 */
229 @Type
230 public static final int TYPE_ON_RAMP_U_TURN_LEFT = 19;
231
232 /**
233 * Right turn onto the opposite side of the same street to enter a turnpike or freeway, from 175
234 * (included) to 180 (included).
235 */
236 @Type
237 public static final int TYPE_ON_RAMP_U_TURN_RIGHT = 20;
238
239 /** A left turn to exit a turnpike or freeway, from 10 (included) to 45 (excluded) degrees. */
240 @Type
241 public static final int TYPE_OFF_RAMP_SLIGHT_LEFT = 21;
242
243 /** A right turn to exit a turnpike or freeway, from 10 (included) to 45 (excluded) degrees. */
244 @Type
245 public static final int TYPE_OFF_RAMP_SLIGHT_RIGHT = 22;
246
247 /** A left turn to exit a turnpike or freeway, from 45 (included) to 135 (excluded) degrees. */
248 @Type
249 public static final int TYPE_OFF_RAMP_NORMAL_LEFT = 23;
250
251 /** A left right to exit a turnpike or freeway, from 45 (included) to 135 (excluded) degrees. */
252 @Type
253 public static final int TYPE_OFF_RAMP_NORMAL_RIGHT = 24;
254
255 /**
256 * Keep to the left as the road diverges.
257 *
258 * <p>For example, this is used to indicate "Keep left at the fork".
259 */
260 @Type
261 public static final int TYPE_FORK_LEFT = 25;
262
263 /**
264 * Keep to the right as the road diverges.
265 *
266 * <p>For example, this is used to indicate "Keep right at the fork".
267 */
268 @Type
269 public static final int TYPE_FORK_RIGHT = 26;
270
271 /**
272 * Current road joins another on the left.
273 *
274 * <p>For example, this is used to indicate "Merge left onto Main St.".
275 */
276 @Type
277 public static final int TYPE_MERGE_LEFT = 27;
278
279 /**
280 * Current road joins another on the right.
281 *
282 * <p>For example, this is used to indicate "Merge left onto Main St.".
283 */
284 @Type
285 public static final int TYPE_MERGE_RIGHT = 28;
286
287 /**
288 * Current road joins another without direction specified.
289 *
290 * <p>For example, this is used to indicate "Merge onto Main St.".
291 */
292 @Type
293 public static final int TYPE_MERGE_SIDE_UNSPECIFIED = 29;
294
295 /**
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800296 * Enter a clockwise roundabout and take the Nth exit.
297 *
298 * <p>The exit number must be passed when created the maneuver.
299 *
300 * <p>For example, this is used to indicate "At the roundabout, take the Nth exit".
301 */
302 @Type
303 public static final int TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW = 32;
304
305 /**
306 * Enter a clockwise roundabout and take the Nth exit after angle A degrees.
307 *
308 * <p>The exit number and angle must be passed when creating the maneuver.
309 *
310 * <p>For example, this is used to indicate "At the roundabout, take the Nth exit".
311 */
312 @Type
313 public static final int TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE = 33;
314
315 /**
316 * Enter a counter-clockwise roundabout and take the Nth exit.
317 *
318 * <p>The exit number must be passed when created the maneuver.
319 *
320 * <p>For example, this is used to indicate "At the roundabout, take the Nth exit".
321 */
322 @Type
323 public static final int TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW = 34;
324
325 /**
326 * Enter a counter-clockwise roundabout and take the Nth exit after angle A degrees.
327 *
328 * <p>The exit number and angle must be passed when creating the maneuver.
329 *
330 * <p>For example, this is used to indicate "At the roundabout, take a sharp right at the Nth
331 * exit".
332 */
333 @Type
334 public static final int TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE = 35;
335
336 /** Driver should steer straight. */
337 @Type
338 public static final int TYPE_STRAIGHT = 36;
339
340 /**
Billy Lamd5488f42020-11-23 22:54:47 -0800341 * Drive towards a boat ferry for vehicles, where the entrance is straight ahead or in an
342 * unknown direction.
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800343 *
344 * <p>For example, this is used to indicate "Take the ferry".
345 */
346 @Type
347 public static final int TYPE_FERRY_BOAT = 37;
348
Billy Lamd5488f42020-11-23 22:54:47 -0800349 /**
350 * Drive towards a train ferry for vehicles (e.g. "Take the train"), where the entrance is
351 * straight ahead or in an unknown direction.
352 */
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800353 @Type
354 public static final int TYPE_FERRY_TRAIN = 38;
355
356 /** Arrival at a destination. */
357 @Type
358 public static final int TYPE_DESTINATION = 39;
359
360 /** Arrival to a destination located straight ahead. */
361 @Type
362 public static final int TYPE_DESTINATION_STRAIGHT = 40;
363
364 /** Arrival to a destination located to the left side of the road. */
365 @Type
366 public static final int TYPE_DESTINATION_LEFT = 41;
367
368 /** Arrival to a destination located to the right side of the road. */
369 @Type
370 public static final int TYPE_DESTINATION_RIGHT = 42;
Billy Lamd5488f42020-11-23 22:54:47 -0800371
372 /**
373 * Entrance to a clockwise roundabout on which the current road ends.
374 *
375 * <p>For example, this is used to indicate "Enter the roundabout".
376 */
377 @Type
378 public static final int TYPE_ROUNDABOUT_ENTER_CW = 43;
379
380 /**
381 * Used when leaving a clockwise roundabout when the step starts in it.
382 *
383 * <p>For example, this is used to indicate "Exit the roundabout".
384 */
385 @Type
386 public static final int TYPE_ROUNDABOUT_EXIT_CW = 44;
387
388 /**
389 * Entrance to a counter-clockwise roundabout on which the current road ends.
390 *
391 * <p>For example, this is used to indicate "Enter the roundabout".
392 */
393 @Type
394 public static final int TYPE_ROUNDABOUT_ENTER_CCW = 45;
395
396 /**
397 * Used when leaving a counter-clockwise roundabout when the step starts in it.
398 *
399 * <p>For example, this is used to indicate "Exit the roundabout".
400 */
401 @Type
402 public static final int TYPE_ROUNDABOUT_EXIT_CCW = 46;
403
404 /**
405 * Drive towards a boat ferry for vehicles, where the entrance is to the left.
406 *
407 * <p>For example, this is used to indicate "Take the ferry".
408 */
409 @Type
410 public static final int TYPE_FERRY_BOAT_LEFT = 47;
411
412 /**
413 * Drive towards a boat ferry for vehicles, where the entrance is to the right.
414 *
415 * <p>For example, this is used to indicate "Take the ferry".
416 */
417 @Type
418 public static final int TYPE_FERRY_BOAT_RIGHT = 48;
419
420 /**
421 * Drive towards a train ferry for vehicles (e.g. "Take the train"), where the entrance is to
422 * the
423 * left.
424 */
425 @Type
426 public static final int TYPE_FERRY_TRAIN_LEFT = 49;
427
428 /**
429 * Drive towards a train ferry for vehicles (e.g. "Take the train"), where the entrance is to
430 * the
431 * right.
432 */
433 @Type
434 public static final int TYPE_FERRY_TRAIN_RIGHT = 50;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800435
436 @Keep
437 @Type
438 private final int mType;
439 @Keep
440 private final int mRoundaboutExitNumber;
441 @Keep
442 private final int mRoundaboutExitAngle;
443 @Keep
444 @Nullable
445 private final CarIcon mIcon;
446
447 /**
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800448 * Returns the maneuver type.
449 *
450 * <p>Required to be set at all times.
451 */
452 @Type
453 public int getType() {
454 return mType;
455 }
456
457 /**
458 * Returns the roundabout exit number, starting from 1 to designate the first exit after joining
459 * the roundabout, and increasing in circulation order. Only relevant if the type is any
460 * variation of {@code TYPE_ROUNDABOUT_ENTER_AND_EXIT_*}.
461 *
462 * <p>For example, if the driver is joining a counter-clockwise roundabout with 4 exits, then
463 * the exit to the right would be exit #1, the one straight ahead would be exit #2, the one
464 * to the left would be exit #3 and the one used by the driver to join the roundabout would
465 * be exit #4.
466 *
467 * <p>Required when the type is a roundabout.
468 */
469 public int getRoundaboutExitNumber() {
470 return mRoundaboutExitNumber;
471 }
472
473 /**
474 * Returns the roundabout exit angle in degrees to designate the amount of distance to travel
475 * around the roundabout. Only relevant if the type is {@link
476 * #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE} or {@link
477 * #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE}.
478 *
479 * <p>For example, if the drive is joining a counter-clockwise roundabout with equally spaced
Stav Raviv94148102021-07-27 00:03:31 +0000480 * exits then the exit to the right would be at 90 degrees, the one straight ahead would be
481 * at 180 degrees, the one to the left would at 270 degrees and the one used by the driver to
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800482 * join the roundabout would be at 360 degrees.
483 *
484 * <p>The angle can also be set for irregular roundabouts. For example a roundabout with three
485 * exits at 90, 270 and 360 degrees could also have the desired exit angle specified.
486 *
487 * <p>Required with the type is a roundabout with an angle.
488 */
489 public int getRoundaboutExitAngle() {
490 return mRoundaboutExitAngle;
491 }
492
493 /**
494 * Returns the icon for the maneuver.
495 *
496 * <p>Optional field that when not set may be shown in the target display by a generic image
497 * representing the specific maneuver.
498 */
499 @Nullable
500 public CarIcon getIcon() {
501 return mIcon;
502 }
503
504 @Override
505 @NonNull
506 public String toString() {
507 return "[type: "
508 + mType
509 + ", exit #: "
510 + mRoundaboutExitNumber
511 + ", exit angle: "
512 + mRoundaboutExitAngle
513 + ", icon: "
514 + mIcon
515 + "]";
516 }
517
518 @Override
519 public int hashCode() {
520 return Objects.hash(mType, mRoundaboutExitNumber, mRoundaboutExitAngle, mIcon);
521 }
522
523 @Override
524 public boolean equals(@Nullable Object other) {
525 if (this == other) {
526 return true;
527 }
528 if (!(other instanceof Maneuver)) {
529 return false;
530 }
531
532 Maneuver otherManeuver = (Maneuver) other;
533 return mType == otherManeuver.mType
534 && mRoundaboutExitNumber == otherManeuver.mRoundaboutExitNumber
535 && mRoundaboutExitAngle == otherManeuver.mRoundaboutExitAngle
536 && Objects.equals(mIcon, otherManeuver.mIcon);
537 }
538
Ram Parameswaran686008f2020-12-10 19:20:02 -0800539 Maneuver(@Type int type, int roundaboutExitNumber, int roundaboutExitAngle,
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800540 @Nullable CarIcon icon) {
Jorge Pereira0515c672021-01-28 13:41:54 -0800541 mType = type;
542 mRoundaboutExitNumber = roundaboutExitNumber;
543 mRoundaboutExitAngle = roundaboutExitAngle;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800544 CarIconConstraints.DEFAULT.validateOrThrow(icon);
Jorge Pereira0515c672021-01-28 13:41:54 -0800545 mIcon = icon;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800546 }
547
548 /** Constructs an empty instance, used by serialization code. */
549 private Maneuver() {
550 mType = TYPE_UNKNOWN;
551 mRoundaboutExitNumber = 0;
552 mRoundaboutExitAngle = 0;
553 mIcon = null;
554 }
555
Jorge Pereira5dd252d2021-01-07 20:30:13 -0800556 static boolean isValidType(@Type int type) {
Billy Lamd5488f42020-11-23 22:54:47 -0800557 return (type >= TYPE_UNKNOWN && type <= TYPE_FERRY_TRAIN_RIGHT);
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800558 }
559
Ram Parameswaran686008f2020-12-10 19:20:02 -0800560 static boolean isValidTypeWithExitNumber(@Type int type) {
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800561 return (type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW
562 || type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW
563 || type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE
564 || type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE);
565 }
566
Ram Parameswaran686008f2020-12-10 19:20:02 -0800567 static boolean isValidTypeWithExitAngle(@Type int type) {
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800568 return (type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE
569 || type == TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE);
570 }
571
572 /** A builder of {@link Maneuver}. */
573 public static final class Builder {
574 @Type
575 private final int mType;
576 private boolean mIsRoundaboutExitNumberSet;
577 private int mRoundaboutExitNumber;
578 private boolean mIsRoundaboutExitAngleSet;
579 private int mRoundaboutExitAngle;
580 @Nullable
581 private CarIcon mIcon;
582
Jorge Pereira5dd252d2021-01-07 20:30:13 -0800583 /**
584 * Constructs a new instance of a {@link Builder}.
585 *
586 * <p>The type should be chosen to reflect the closest semantic meaning of the maneuver.
Jorge Pereira07502ba2021-01-21 09:38:30 -0800587 * In some cases, an exact type match is not possible, but choosing a similar or slightly
588 * more general type is preferred. Using {@link #TYPE_UNKNOWN} is allowed, but some head
589 * units will not display any information in that case.
Jorge Pereira5dd252d2021-01-07 20:30:13 -0800590 *
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800591 * @param type one of the {@code TYPE_*} static constants defined in this class
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800592 * @throws IllegalArgumentException if {@code type} is not a valid maneuver type
Jorge Pereira5dd252d2021-01-07 20:30:13 -0800593 */
594 public Builder(@Type int type) {
595 if (!isValidType(type)) {
596 throw new IllegalArgumentException("Maneuver must have a valid type");
597 }
Jorge Pereira0515c672021-01-28 13:41:54 -0800598 mType = type;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800599 }
600
601 /**
Jorge Pereira07502ba2021-01-21 09:38:30 -0800602 * Sets an image representing the maneuver.
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800603 *
Billy Lam09c4af22021-05-20 22:49:29 -0700604 * <h4>Icon Sizing Guidance</h4>
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800605 *
Billy Lam09c4af22021-05-20 22:49:29 -0700606 * To minimize scaling artifacts across a wide range of car screens, apps should provide
607 * icons targeting a 128 x 128 dp bounding box. If the icon exceeds this maximum size in
608 * either one of the dimensions, it will be scaled down to be centered inside the
609 * bounding box while preserving its aspect ratio.
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800610 *
611 * <p>See {@link CarIcon} for more details related to providing icon and image resources
612 * that work with different car screen pixel densities.
Jorge Pereira07502ba2021-01-21 09:38:30 -0800613 *
614 * @throws NullPointerException if {@code icon} is {@code null}
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800615 */
616 @NonNull
Jorge Pereira07502ba2021-01-21 09:38:30 -0800617 public Builder setIcon(@NonNull CarIcon icon) {
Jorge Pereira0515c672021-01-28 13:41:54 -0800618 mIcon = requireNonNull(icon);
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800619 return this;
620 }
621
622 /**
623 * Sets an exit number for roundabout maneuvers.
624 *
625 * <p>Use for when {@code type} is {@link #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW}, {@link
626 * #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW},
627 * {@link #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE} or
628 * {@link #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE}. The {@code
629 * roundaboutExitNumber} starts from 1 to designate the first exit after joining the
630 * roundabout, and increases in circulation order.
631 *
632 * <p>For example, if the driver is joining a counter-clockwise roundabout with 4 exits,
633 * then the exit to the right would be exit #1, the one straight ahead would be exit #2,
634 * the one to the left would be exit #3 and the one used by the driver to join the
635 * roundabout would be exit #4.
636 *
Jorge Pereira3c4013f2021-01-20 17:24:19 -0800637 * @throws IllegalArgumentException if {@code type} does not include a exit number, or
638 * if {@code roundaboutExitNumber} is not greater than
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800639 * zero
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800640 */
641 @NonNull
Ram Parameswaran25c966e2021-01-15 11:42:53 -0800642 public Builder setRoundaboutExitNumber(@IntRange(from = 1) int roundaboutExitNumber) {
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800643 if (!isValidTypeWithExitNumber(mType)) {
644 throw new IllegalArgumentException(
645 "Maneuver does not include roundaboutExitNumber");
646 }
647 if (roundaboutExitNumber < 1) {
648 throw new IllegalArgumentException("Maneuver must include a valid exit number");
649 }
Jorge Pereira0515c672021-01-28 13:41:54 -0800650 mIsRoundaboutExitNumberSet = true;
651 mRoundaboutExitNumber = roundaboutExitNumber;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800652 return this;
653 }
654
655 /**
656 * Sets an exit angle for roundabout maneuvers.
657 *
658 * <p>Use for when {@code type} is {@link #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE} or
659 * {@link #TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE}. The {@code roundaboutExitAngle}
660 * represents the degrees traveled in circulation from the entrance to the exit.
661 *
662 * <p>For example, in a 4 exit example, if all the exits are equally spaced then exit 1
663 * would be at 90 degrees, exit 2 at 180, exit 3 at 270 and exit 4 at 360. However if the
664 * exits are irregular then a different angle could be provided.
665 *
Jorge Pereira3c4013f2021-01-20 17:24:19 -0800666 * @throws IllegalArgumentException if {@code type} does not include a exit angle or if
667 * {@code roundaboutExitAngle} is not greater than zero
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800668 * and less than or equal to 360 degrees
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800669 */
670 @NonNull
Ram Parameswaran25c966e2021-01-15 11:42:53 -0800671 public Builder setRoundaboutExitAngle(
672 @IntRange(from = 1, to = 360) int roundaboutExitAngle) {
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800673 if (!isValidTypeWithExitAngle(mType)) {
674 throw new IllegalArgumentException("Maneuver does not include roundaboutExitAngle");
675 }
676 if (roundaboutExitAngle < 1 || roundaboutExitAngle > 360) {
677 throw new IllegalArgumentException("Maneuver must include a valid exit angle");
678 }
Jorge Pereira0515c672021-01-28 13:41:54 -0800679 mIsRoundaboutExitAngleSet = true;
680 mRoundaboutExitAngle = roundaboutExitAngle;
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800681 return this;
682 }
683
684 /**
685 * Constructs the {@link Maneuver} defined by this builder.
686 *
687 * @throws IllegalArgumentException if {@code type} includes an exit number and one has
Jorge Pereira3c4013f2021-01-20 17:24:19 -0800688 * not been set, or if it includes an exit angle and one
Jorge Pereiradf8ed582021-01-28 07:32:11 -0800689 * has not been set
Ram Parameswaran619cc5f2020-11-03 21:07:41 -0800690 */
691 @NonNull
692 public Maneuver build() {
693 if (isValidTypeWithExitNumber(mType) && !mIsRoundaboutExitNumberSet) {
694 throw new IllegalArgumentException("Maneuver missing roundaboutExitNumber");
695 }
696 if (isValidTypeWithExitAngle(mType) && !mIsRoundaboutExitAngleSet) {
697 throw new IllegalArgumentException("Maneuver missing roundaboutExitAngle");
698 }
699 return new Maneuver(mType, mRoundaboutExitNumber, mRoundaboutExitAngle, mIcon);
700 }
701 }
702}