1 /* 2 * Copyright (C) 2023 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 android.net.thread; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 import android.annotation.SystemApi; 25 26 import com.android.net.thread.flags.Flags; 27 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 31 /** 32 * Represents a Thread network specific failure. 33 * 34 * @hide 35 */ 36 @FlaggedApi(Flags.FLAG_THREAD_ENABLED) 37 @SystemApi 38 public class ThreadNetworkException extends Exception { 39 /** @hide */ 40 @Retention(RetentionPolicy.SOURCE) 41 @IntDef({ 42 ERROR_INTERNAL_ERROR, 43 ERROR_ABORTED, 44 ERROR_TIMEOUT, 45 ERROR_UNAVAILABLE, 46 ERROR_BUSY, 47 ERROR_FAILED_PRECONDITION, 48 ERROR_UNSUPPORTED_CHANNEL, 49 ERROR_REJECTED_BY_PEER, 50 ERROR_RESPONSE_BAD_FORMAT, 51 ERROR_RESOURCE_EXHAUSTED, 52 ERROR_UNKNOWN, 53 ERROR_THREAD_DISABLED, 54 }) 55 public @interface ErrorCode {} 56 57 /** 58 * The operation failed because some invariants expected by the underlying system have been 59 * broken. This error code is reserved for serious errors. The caller can do nothing to recover 60 * from this error. A bugreport should be created and sent to the Android community if this 61 * error is ever returned. 62 */ 63 public static final int ERROR_INTERNAL_ERROR = 1; 64 65 /** 66 * The operation failed because concurrent operations are overriding this one. Retrying an 67 * aborted operation has the risk of aborting another ongoing operation again. So the caller 68 * should retry at a higher level where it knows there won't be race conditions. 69 */ 70 public static final int ERROR_ABORTED = 2; 71 72 /** 73 * The operation failed because a deadline expired before the operation could complete. This may 74 * be caused by connectivity unavailability and the caller can retry the same operation when the 75 * connectivity issue is fixed. 76 */ 77 public static final int ERROR_TIMEOUT = 3; 78 79 /** 80 * The operation failed because the service is currently unavailable and that this is most 81 * likely a transient condition. The caller can recover from this error by retrying with a 82 * back-off scheme. Note that it is not always safe to retry non-idempotent operations. 83 */ 84 public static final int ERROR_UNAVAILABLE = 4; 85 86 /** 87 * The operation failed because this device is currently busy processing concurrent requests. 88 * The caller may recover from this error when the current operations has been finished. 89 */ 90 public static final int ERROR_BUSY = 5; 91 92 /** 93 * The operation failed because required preconditions were not satisfied. For example, trying 94 * to schedule a network migration when this device is not attached will receive this error or 95 * enable Thread while User Resitration has disabled it. The caller should not retry the same 96 * operation before the precondition is satisfied. 97 */ 98 public static final int ERROR_FAILED_PRECONDITION = 6; 99 100 /** 101 * The operation was rejected because the specified channel is currently not supported by this 102 * device in this country. For example, trying to join or migrate to a network with channel 103 * which is not supported. The caller should should change the channel or return an error to the 104 * user if the channel cannot be changed. 105 */ 106 public static final int ERROR_UNSUPPORTED_CHANNEL = 7; 107 108 /** 109 * The operation failed because a request is rejected by the peer device. This happens because 110 * the peer device is not capable of processing the request, or a request from another device 111 * has already been accepted by the peer device. The caller may not be able to recover from this 112 * error by retrying the same operation. 113 */ 114 public static final int ERROR_REJECTED_BY_PEER = 8; 115 116 /** 117 * The operation failed because the received response is malformed. This is typically because 118 * the peer device is misbehaving. The caller may only recover from this error by retrying with 119 * a different peer device. 120 */ 121 public static final int ERROR_RESPONSE_BAD_FORMAT = 9; 122 123 /** 124 * The operation failed because some resource has been exhausted. For example, no enough 125 * allocated memory buffers, or maximum number of supported operations has been exceeded. The 126 * caller may retry and recover from this error when the resource has been freed. 127 */ 128 public static final int ERROR_RESOURCE_EXHAUSTED = 10; 129 130 /** 131 * The operation failed because of an unknown error in the system. This typically indicates that 132 * the caller doesn't understand error codes added in newer Android versions. 133 */ 134 public static final int ERROR_UNKNOWN = 11; 135 136 /** 137 * The operation failed because the Thread radio is disabled by {@link 138 * ThreadNetworkController#setEnabled}, airplane mode or device admin. The caller should retry 139 * only after Thread is enabled. 140 */ 141 public static final int ERROR_THREAD_DISABLED = 12; 142 143 /** 144 * The operation failed because the feature is not supported by the platform. For example, some 145 * platforms may not support setting the target power of each channel. The caller should not 146 * retry and may return an error to the user. 147 */ 148 public static final int ERROR_UNSUPPORTED_FEATURE = 13; 149 150 private static final int ERROR_MIN = ERROR_INTERNAL_ERROR; 151 private static final int ERROR_MAX = ERROR_UNSUPPORTED_FEATURE; 152 153 private final int mErrorCode; 154 155 /** 156 * Creates a new {@link ThreadNetworkException} object with given error code and message. 157 * 158 * @throws IllegalArgumentException if {@code errorCode} is not a value in {@link #ERROR_} 159 * @throws NullPointerException if {@code message} is {@code null} 160 */ ThreadNetworkException(@rrorCode int errorCode, @NonNull String message)161 public ThreadNetworkException(@ErrorCode int errorCode, @NonNull String message) { 162 super(requireNonNull(message, "message cannot be null")); 163 if (errorCode < ERROR_MIN || errorCode > ERROR_MAX) { 164 throw new IllegalArgumentException( 165 "errorCode cannot be " 166 + errorCode 167 + " (allowedRange = [" 168 + ERROR_MIN 169 + ", " 170 + ERROR_MAX 171 + "])"); 172 } 173 this.mErrorCode = errorCode; 174 } 175 176 /** Returns the error code. */ getErrorCode()177 public @ErrorCode int getErrorCode() { 178 return mErrorCode; 179 } 180 } 181