Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package androidx.car.app.navigation.model; |
| 18 | |
| 19 | import static androidx.annotation.RestrictTo.Scope.LIBRARY; |
| 20 | |
Jorge Pereira | 07502ba | 2021-01-21 09:38:30 -0800 | [diff] [blame] | 21 | import static java.util.Objects.requireNonNull; |
| 22 | |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 23 | import androidx.annotation.IntDef; |
Ram Parameswaran | 25c966e | 2021-01-15 11:42:53 -0800 | [diff] [blame] | 24 | import androidx.annotation.IntRange; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 25 | import androidx.annotation.Keep; |
| 26 | import androidx.annotation.NonNull; |
| 27 | import androidx.annotation.Nullable; |
| 28 | import androidx.annotation.RestrictTo; |
Ram Parameswaran | f5db48f | 2021-03-10 10:42:58 -0800 | [diff] [blame] | 29 | import androidx.car.app.annotations.CarProtocol; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 30 | import androidx.car.app.model.CarIcon; |
| 31 | import androidx.car.app.model.constraints.CarIconConstraints; |
| 32 | |
| 33 | import java.lang.annotation.Retention; |
| 34 | import java.lang.annotation.RetentionPolicy; |
| 35 | import java.util.Objects; |
| 36 | |
| 37 | /** Information about a maneuver that the driver will be required to perform. */ |
Jorge Pereira | 1d7c702 | 2021-01-26 13:30:15 -0800 | [diff] [blame] | 38 | // TODO(b/154671667): Update when host(s) updates or a scheme for auto sync is established. |
Ram Parameswaran | f5db48f | 2021-03-10 10:42:58 -0800 | [diff] [blame] | 39 | @CarProtocol |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 40 | public 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 77 | 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 Lam | d5488f4 | 2020-11-23 22:54:47 -0800 | [diff] [blame] | 87 | 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 96 | }) |
| 97 | @Retention(RetentionPolicy.SOURCE) |
| 98 | @RestrictTo(LIBRARY) |
| 99 | public @interface Type { |
| 100 | } |
| 101 | |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 102 | /** |
| 103 | * Maneuver type is unknown, no maneuver information should be displayed. |
| 104 | * |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 105 | * <p>This type may be interpreted differently depending on the consumer. In some |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 106 | * 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 296 | * 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 Lam | d5488f4 | 2020-11-23 22:54:47 -0800 | [diff] [blame] | 341 | * Drive towards a boat ferry for vehicles, where the entrance is straight ahead or in an |
| 342 | * unknown direction. |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 343 | * |
| 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 Lam | d5488f4 | 2020-11-23 22:54:47 -0800 | [diff] [blame] | 349 | /** |
| 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 353 | @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 Lam | d5488f4 | 2020-11-23 22:54:47 -0800 | [diff] [blame] | 371 | |
| 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 435 | |
| 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 448 | * 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 Raviv | 9414810 | 2021-07-27 00:03:31 +0000 | [diff] [blame] | 480 | * 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 482 | * 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 Parameswaran | 686008f | 2020-12-10 19:20:02 -0800 | [diff] [blame] | 539 | Maneuver(@Type int type, int roundaboutExitNumber, int roundaboutExitAngle, |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 540 | @Nullable CarIcon icon) { |
Jorge Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 541 | mType = type; |
| 542 | mRoundaboutExitNumber = roundaboutExitNumber; |
| 543 | mRoundaboutExitAngle = roundaboutExitAngle; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 544 | CarIconConstraints.DEFAULT.validateOrThrow(icon); |
Jorge Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 545 | mIcon = icon; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 546 | } |
| 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 Pereira | 5dd252d | 2021-01-07 20:30:13 -0800 | [diff] [blame] | 556 | static boolean isValidType(@Type int type) { |
Billy Lam | d5488f4 | 2020-11-23 22:54:47 -0800 | [diff] [blame] | 557 | return (type >= TYPE_UNKNOWN && type <= TYPE_FERRY_TRAIN_RIGHT); |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 558 | } |
| 559 | |
Ram Parameswaran | 686008f | 2020-12-10 19:20:02 -0800 | [diff] [blame] | 560 | static boolean isValidTypeWithExitNumber(@Type int type) { |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 561 | 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 Parameswaran | 686008f | 2020-12-10 19:20:02 -0800 | [diff] [blame] | 567 | static boolean isValidTypeWithExitAngle(@Type int type) { |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 568 | 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 Pereira | 5dd252d | 2021-01-07 20:30:13 -0800 | [diff] [blame] | 583 | /** |
| 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 Pereira | 07502ba | 2021-01-21 09:38:30 -0800 | [diff] [blame] | 587 | * 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 Pereira | 5dd252d | 2021-01-07 20:30:13 -0800 | [diff] [blame] | 590 | * |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 591 | * @param type one of the {@code TYPE_*} static constants defined in this class |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 592 | * @throws IllegalArgumentException if {@code type} is not a valid maneuver type |
Jorge Pereira | 5dd252d | 2021-01-07 20:30:13 -0800 | [diff] [blame] | 593 | */ |
| 594 | public Builder(@Type int type) { |
| 595 | if (!isValidType(type)) { |
| 596 | throw new IllegalArgumentException("Maneuver must have a valid type"); |
| 597 | } |
Jorge Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 598 | mType = type; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 599 | } |
| 600 | |
| 601 | /** |
Jorge Pereira | 07502ba | 2021-01-21 09:38:30 -0800 | [diff] [blame] | 602 | * Sets an image representing the maneuver. |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 603 | * |
Billy Lam | 09c4af2 | 2021-05-20 22:49:29 -0700 | [diff] [blame] | 604 | * <h4>Icon Sizing Guidance</h4> |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 605 | * |
Billy Lam | 09c4af2 | 2021-05-20 22:49:29 -0700 | [diff] [blame] | 606 | * 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 Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 610 | * |
| 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 Pereira | 07502ba | 2021-01-21 09:38:30 -0800 | [diff] [blame] | 613 | * |
| 614 | * @throws NullPointerException if {@code icon} is {@code null} |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 615 | */ |
| 616 | @NonNull |
Jorge Pereira | 07502ba | 2021-01-21 09:38:30 -0800 | [diff] [blame] | 617 | public Builder setIcon(@NonNull CarIcon icon) { |
Jorge Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 618 | mIcon = requireNonNull(icon); |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 619 | 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 Pereira | 3c4013f | 2021-01-20 17:24:19 -0800 | [diff] [blame] | 637 | * @throws IllegalArgumentException if {@code type} does not include a exit number, or |
| 638 | * if {@code roundaboutExitNumber} is not greater than |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 639 | * zero |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 640 | */ |
| 641 | @NonNull |
Ram Parameswaran | 25c966e | 2021-01-15 11:42:53 -0800 | [diff] [blame] | 642 | public Builder setRoundaboutExitNumber(@IntRange(from = 1) int roundaboutExitNumber) { |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 643 | 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 Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 650 | mIsRoundaboutExitNumberSet = true; |
| 651 | mRoundaboutExitNumber = roundaboutExitNumber; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 652 | 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 Pereira | 3c4013f | 2021-01-20 17:24:19 -0800 | [diff] [blame] | 666 | * @throws IllegalArgumentException if {@code type} does not include a exit angle or if |
| 667 | * {@code roundaboutExitAngle} is not greater than zero |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 668 | * and less than or equal to 360 degrees |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 669 | */ |
| 670 | @NonNull |
Ram Parameswaran | 25c966e | 2021-01-15 11:42:53 -0800 | [diff] [blame] | 671 | public Builder setRoundaboutExitAngle( |
| 672 | @IntRange(from = 1, to = 360) int roundaboutExitAngle) { |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 673 | 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 Pereira | 0515c67 | 2021-01-28 13:41:54 -0800 | [diff] [blame] | 679 | mIsRoundaboutExitAngleSet = true; |
| 680 | mRoundaboutExitAngle = roundaboutExitAngle; |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 681 | 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 Pereira | 3c4013f | 2021-01-20 17:24:19 -0800 | [diff] [blame] | 688 | * not been set, or if it includes an exit angle and one |
Jorge Pereira | df8ed58 | 2021-01-28 07:32:11 -0800 | [diff] [blame] | 689 | * has not been set |
Ram Parameswaran | 619cc5f | 2020-11-03 21:07:41 -0800 | [diff] [blame] | 690 | */ |
| 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 | } |