| /* |
| * Copyright (C) 2023 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 android.net.thread; |
| |
| import static java.util.Objects.requireNonNull; |
| |
| import android.annotation.FlaggedApi; |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.SystemApi; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * Represents a Thread network specific failure. |
| * |
| * @hide |
| */ |
| @FlaggedApi(ThreadNetworkFlags.FLAG_THREAD_ENABLED) |
| @SystemApi |
| public class ThreadNetworkException extends Exception { |
| /** @hide */ |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef({ |
| ERROR_INTERNAL_ERROR, |
| ERROR_ABORTED, |
| ERROR_TIMEOUT, |
| ERROR_UNAVAILABLE, |
| ERROR_BUSY, |
| ERROR_FAILED_PRECONDITION, |
| ERROR_UNSUPPORTED_CHANNEL, |
| ERROR_REJECTED_BY_PEER, |
| ERROR_RESPONSE_BAD_FORMAT, |
| ERROR_RESOURCE_EXHAUSTED, |
| ERROR_UNKNOWN, |
| ERROR_THREAD_DISABLED, |
| }) |
| public @interface ErrorCode {} |
| |
| /** |
| * The operation failed because some invariants expected by the underlying system have been |
| * broken. This error code is reserved for serious errors. The caller can do nothing to recover |
| * from this error. A bugreport should be created and sent to the Android community if this |
| * error is ever returned. |
| */ |
| public static final int ERROR_INTERNAL_ERROR = 1; |
| |
| /** |
| * The operation failed because concurrent operations are overriding this one. Retrying an |
| * aborted operation has the risk of aborting another ongoing operation again. So the caller |
| * should retry at a higher level where it knows there won't be race conditions. |
| */ |
| public static final int ERROR_ABORTED = 2; |
| |
| /** |
| * The operation failed because a deadline expired before the operation could complete. This may |
| * be caused by connectivity unavailability and the caller can retry the same operation when the |
| * connectivity issue is fixed. |
| */ |
| public static final int ERROR_TIMEOUT = 3; |
| |
| /** |
| * The operation failed because the service is currently unavailable and that this is most |
| * likely a transient condition. The caller can recover from this error by retrying with a |
| * back-off scheme. Note that it is not always safe to retry non-idempotent operations. |
| */ |
| public static final int ERROR_UNAVAILABLE = 4; |
| |
| /** |
| * The operation failed because this device is currently busy processing concurrent requests. |
| * The caller may recover from this error when the current operations has been finished. |
| */ |
| public static final int ERROR_BUSY = 5; |
| |
| /** |
| * The operation failed because required preconditions were not satisfied. For example, trying |
| * to schedule a network migration when this device is not attached will receive this error or |
| * enable Thread while User Resitration has disabled it. The caller should not retry the same |
| * operation before the precondition is satisfied. |
| */ |
| public static final int ERROR_FAILED_PRECONDITION = 6; |
| |
| /** |
| * The operation was rejected because the specified channel is currently not supported by this |
| * device in this country. For example, trying to join or migrate to a network with channel |
| * which is not supported. The caller should should change the channel or return an error to the |
| * user if the channel cannot be changed. |
| */ |
| public static final int ERROR_UNSUPPORTED_CHANNEL = 7; |
| |
| /** |
| * The operation failed because a request is rejected by the peer device. This happens because |
| * the peer device is not capable of processing the request, or a request from another device |
| * has already been accepted by the peer device. The caller may not be able to recover from this |
| * error by retrying the same operation. |
| */ |
| public static final int ERROR_REJECTED_BY_PEER = 8; |
| |
| /** |
| * The operation failed because the received response is malformed. This is typically because |
| * the peer device is misbehaving. The caller may only recover from this error by retrying with |
| * a different peer device. |
| */ |
| public static final int ERROR_RESPONSE_BAD_FORMAT = 9; |
| |
| /** |
| * The operation failed because some resource has been exhausted. For example, no enough |
| * allocated memory buffers, or maximum number of supported operations has been exceeded. The |
| * caller may retry and recover from this error when the resource has been freed. |
| */ |
| public static final int ERROR_RESOURCE_EXHAUSTED = 10; |
| |
| /** |
| * The operation failed because of an unknown error in the system. This typically indicates that |
| * the caller doesn't understand error codes added in newer Android versions. |
| */ |
| public static final int ERROR_UNKNOWN = 11; |
| |
| /** |
| * The operation failed because the Thread radio is disabled by {@link |
| * ThreadNetworkController#setEnabled}, airplane mode or device admin. The caller should retry |
| * only after Thread is enabled. |
| */ |
| public static final int ERROR_THREAD_DISABLED = 12; |
| |
| /** |
| * The operation failed because it is not supported by the platform. For example, some platforms |
| * may not support setting the target power of each channel. The caller should not retry and may |
| * return an error to the user. |
| * |
| * @hide |
| */ |
| public static final int ERROR_UNSUPPORTED_OPERATION = 13; |
| |
| private static final int ERROR_MIN = ERROR_INTERNAL_ERROR; |
| private static final int ERROR_MAX = ERROR_UNSUPPORTED_OPERATION; |
| |
| private final int mErrorCode; |
| |
| /** |
| * Creates a new {@link ThreadNetworkException} object with given error code and message. |
| * |
| * @throws IllegalArgumentException if {@code errorCode} is not a value in {@link #ERROR_} |
| * @throws NullPointerException if {@code message} is {@code null} |
| */ |
| public ThreadNetworkException(@ErrorCode int errorCode, @NonNull String message) { |
| super(requireNonNull(message, "message cannot be null")); |
| if (errorCode < ERROR_MIN || errorCode > ERROR_MAX) { |
| throw new IllegalArgumentException( |
| "errorCode cannot be " |
| + errorCode |
| + " (allowedRange = [" |
| + ERROR_MIN |
| + ", " |
| + ERROR_MAX |
| + "])"); |
| } |
| this.mErrorCode = errorCode; |
| } |
| |
| /** Returns the error code. */ |
| public @ErrorCode int getErrorCode() { |
| return mErrorCode; |
| } |
| } |