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