package com.o3dr.services.android.lib.gcs.link; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.annotation.StringDef; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Conveys information about the link connection state. * <p/> * This value is returned in the {@link com.o3dr.android.client.Drone#notifyAttributeUpdated} as the * extra value {@link com.o3dr.services.android.lib.gcs.link.LinkEventExtra#EXTRA_CONNECTION_STATUS} * when the attribute event is {@link com.o3dr.services.android.lib.gcs.link.LinkEvent#LINK_STATE_UPDATED} */ public final class LinkConnectionStatus implements Parcelable { /** * Key that is used to get the {@link FailureCode} from {@link #getExtras()} * to determine what link connection error occurred. This will always be populated when {@link #FAILED} occurs. */ public static final String EXTRA_ERROR_CODE = "extra_error_code"; /** * Key that is used to retrieve information from {@link #getExtras()} about why the link connection * failure occurred. This value may be populated when {@link #FAILED} occurs, or can be null. */ public static final String EXTRA_ERROR_MSG = "extra_error_message"; /** * Key that is used to retrieve the time a link connection occurred from {@link #getExtras()}. * This is guaranteed when {@link #CONNECTED} occurs. */ public static final String EXTRA_CONNECTION_TIME = "extra_connection_time"; /** * The possible status codes that notifies what state the link connection is in. */ @StringDef({ CONNECTED, CONNECTING, DISCONNECTED, FAILED }) @Retention(RetentionPolicy.SOURCE) public @interface StatusCode { } public static final String CONNECTED = "CONNECTED"; public static final String CONNECTING = "CONNECTING"; public static final String DISCONNECTED = "DISCONNECTED"; public static final String FAILED = "FAILED"; /** * The possible failure codes that can be retrieved from the {@link #getExtras()} using key * {@link #EXTRA_ERROR_CODE}. A {@link LinkConnectionStatus.FailureCode} * is guaranteed when {@link #FAILED} occurs. * */ @IntDef({ SYSTEM_UNAVAILABLE, LINK_UNAVAILABLE, PERMISSION_DENIED, INVALID_CREDENTIALS, TIMEOUT, ADDRESS_IN_USE, UNKNOWN }) @Retention(RetentionPolicy.SOURCE) public @interface FailureCode { } /** * The system does not allow the requested connection type. */ public static final int SYSTEM_UNAVAILABLE = -1; /** * Requested device to connect to is not available. See {@link #EXTRA_ERROR_MSG} for more information. */ public static final int LINK_UNAVAILABLE = -2; /** * Unable to access the requested connection type. */ public static final int PERMISSION_DENIED = -3; /** * The provided credentials could not be authorized. */ public static final int INVALID_CREDENTIALS = -4; /** * A timeout attempting to connect to device has occurred. */ public static final int TIMEOUT = -5; /** * A {@link java.net.BindException} occurred, determining that the requested address is in use. */ public static final int ADDRESS_IN_USE = -6; /** * All errors that are not one of the listed {@link LinkConnectionStatus.FailureCode}s. * This is usually due to a device system failure. */ public static final int UNKNOWN = -7; @StatusCode private final String mStatusCode; private final Bundle mExtras; public LinkConnectionStatus(@StatusCode String statusCode, Bundle extras) { this.mStatusCode = statusCode; this.mExtras = extras; } /** * @return Returns the status of the link connection. This value is one of {@link LinkConnectionStatus.StatusCode} */ @StatusCode public String getStatusCode() { return mStatusCode; } /** * @return Returns a {@link Bundle} with additional information about the link connection. */ public Bundle getExtras() { return mExtras; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(this.mStatusCode); dest.writeBundle(this.mExtras); } private LinkConnectionStatus(Parcel in) { @StatusCode String statusCode = in.readString(); this.mStatusCode = statusCode; this.mExtras = in.readBundle(); } public static final Parcelable.Creator<LinkConnectionStatus> CREATOR = new Parcelable.Creator<LinkConnectionStatus>() { public LinkConnectionStatus createFromParcel(Parcel source) { return new LinkConnectionStatus(source); } public LinkConnectionStatus[] newArray(int size) { return new LinkConnectionStatus[size]; } }; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } LinkConnectionStatus that = (LinkConnectionStatus) o; if (mStatusCode != null ? !mStatusCode.equals(that.mStatusCode) : that.mStatusCode != null) { return false; } return !(mExtras != null ? !mExtras.equals(that.mExtras) : that.mExtras != null); } @Override public int hashCode() { int result = mStatusCode != null ? mStatusCode.hashCode() : 0; result = 31 * result + (mExtras != null ? mExtras.hashCode() : 0); return result; } @Override public String toString() { return "ConnectionResult{" + "mStatusCode='" + mStatusCode + '\'' + ", mExtras=" + mExtras + '}'; } /** * Helper method to generate the generic {@link #FAILED} {@link LinkConnectionStatus} * @param failureCode Of type {@link LinkConnectionStatus.FailureCode} * @param errMsg A message that gives more information to the client about the error. This can be null. * * @return Returns a {@link LinkConnectionStatus} with statusCode {@link #FAILED} */ public static LinkConnectionStatus newFailedConnectionStatus(@FailureCode int failureCode, @Nullable String errMsg) { Bundle extras = new Bundle(); extras.putInt(EXTRA_ERROR_CODE, failureCode); extras.putString(EXTRA_ERROR_MSG, errMsg); return new LinkConnectionStatus(FAILED, extras); } }