NavigationState.java
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.car.cluster.navigation;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.core.util.Preconditions;
import androidx.versionedparcelable.ParcelField;
import androidx.versionedparcelable.ParcelUtils;
import androidx.versionedparcelable.VersionedParcelable;
import androidx.versionedparcelable.VersionedParcelize;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Navigation state data to be displayed on the instrument cluster of a car. This is composed by:
* <ul>
* <li>a list of destinations.
* <li>the immediate step or steps in order to drive towards those destinations.
* </ul>
* This information can converted it to/from a {@link Parcelable} by using {@link #toParcelable()}
* and {@link #fromParcelable(Parcelable)}, in order to be used in IPC (see {@link Parcel}).
*/
@VersionedParcelize
public final class NavigationState implements VersionedParcelable {
/**
* Possible service states
*/
public enum ServiceStatus {
/**
* Default service status, indicating that navigation state data is valid and up-to-date.
*/
NORMAL,
/**
* New navigation information is being fetched, and an updated navigation state will be
* provided soon. Consumers can use this signal to display a progress indicator to the user.
*/
REROUTING,
}
@ParcelField(1)
List<Step> mSteps;
@ParcelField(2)
List<Destination> mDestinations;
@ParcelField(3)
Segment mCurrentSegment;
@ParcelField(4)
EnumWrapper<ServiceStatus> mServiceStatus;
/**
* Used by {@link VersionedParcelable}
* @hide
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
NavigationState() {
}
/**
* @hide
*/
@RestrictTo(LIBRARY_GROUP_PREFIX)
NavigationState(@NonNull List<Step> steps,
@NonNull List<Destination> destinations,
@Nullable Segment currentSegment,
@NonNull EnumWrapper<ServiceStatus> serviceStatus) {
mSteps = new ArrayList<>(steps);
mDestinations = new ArrayList<>(destinations);
mCurrentSegment = currentSegment;
mServiceStatus = Preconditions.checkNotNull(serviceStatus);
}
/**
* Builder for creating a {@link NavigationState}
*/
public static final class Builder {
private List<Step> mSteps = new ArrayList<>();
private List<Destination> mDestinations = new ArrayList<>();
private Segment mCurrentSegment;
private EnumWrapper<ServiceStatus> mServiceStatus = new EnumWrapper<>();
/**
* Add a navigation step. Steps should be provided in order of execution. It is up to the
* producer to decide how many steps in advance will be provided.
*
* @return this object for chaining
*/
@NonNull
public Builder addStep(@NonNull Step step) {
mSteps.add(Preconditions.checkNotNull(step));
return this;
}
/**
* Add a destination or intermediate stop in the navigation. Destinations should be provided
* from nearest to furthest.
*
* @return this object for chaining
*/
@NonNull
public Builder addDestination(@NonNull Destination destination) {
mDestinations.add(Preconditions.checkNotNull(destination));
return this;
}
/**
* Sets the current segment being driven, or null if the segment being driven is unknown.
*/
@NonNull
public Builder setCurrentSegment(@Nullable Segment segment) {
mCurrentSegment = segment;
return this;
}
/**
* Sets the service status (e.g.: normal operation, re-routing in progress, etc.)
*
* @param serviceStatus current service status
* @param fallbackServiceStatuses variations of the current service status (ordered from
* specific to generic), in case the main one is not
* understood by the consumer of this API. In such scenario,
* consumers will receive the first value in this list that
* they can deserialize.
* @return this object for chaining
*/
@NonNull
public Builder setServiceStatus(@NonNull ServiceStatus serviceStatus,
@NonNull ServiceStatus... fallbackServiceStatuses) {
mServiceStatus = new EnumWrapper<>(serviceStatus, fallbackServiceStatuses);
return this;
}
/**
* Returns a {@link NavigationState} built with the provided information.
*/
@NonNull
public NavigationState build() {
return new NavigationState(mSteps, mDestinations, mCurrentSegment, mServiceStatus);
}
}
/**
* Returns an unmodifiable list of navigation steps, in order of execution. It is up to the
* producer to decide how many steps in advance will be provided.
*/
@NonNull
public List<Step> getSteps() {
return Common.immutableOrEmpty(mSteps);
}
/**
* Returns an unmodifiable list of destinations and intermediate stops in the navigation, sorted
* from nearest to furthest.
*/
@NonNull
public List<Destination> getDestinations() {
return Common.immutableOrEmpty(mDestinations);
}
/**
* Returns the current segment being driven, or null if the segment being driven is unknown.
*/
@Nullable
public Segment getCurrentSegment() {
return mCurrentSegment;
}
/**
* Returns the service status (e.g.: normal operation, re-routing in progress, etc.).
*/
@NonNull
public ServiceStatus getServiceStatus() {
return EnumWrapper.getValue(mServiceStatus, ServiceStatus.NORMAL);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NavigationState that = (NavigationState) o;
return Objects.equals(getSteps(), that.getSteps())
&& Objects.equals(getDestinations(), that.getDestinations())
&& Objects.equals(getCurrentSegment(), that.getCurrentSegment())
&& Objects.equals(getServiceStatus(), that.getServiceStatus());
}
@Override
public int hashCode() {
return Objects.hash(getSteps(), getDestinations(), getCurrentSegment(), getServiceStatus());
}
@Override
public String toString() {
return String.format("{steps: %s, destinations: %s, segment: %s, serviceStatus: %s}",
mSteps, mDestinations, mCurrentSegment, mServiceStatus);
}
/**
* Returns this {@link NavigationState} as a {@link Parcelable}
*/
@NonNull
public Parcelable toParcelable() {
return ParcelUtils.toParcelable(this);
}
/**
* Creates a {@link NavigationState} based on data stored in the given {@link Parcelable}
*/
public static NavigationState fromParcelable(@Nullable Parcelable parcelable) {
return parcelable != null ? ParcelUtils.fromParcelable(parcelable) : new NavigationState();
}
}