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.bluetooth; 18 19 import static java.lang.annotation.RetentionPolicy.SOURCE; 20 21 import android.annotation.FlaggedApi; 22 import android.annotation.IntDef; 23 import android.annotation.NonNull; 24 25 import com.android.bluetooth.flags.Flags; 26 27 import java.io.IOException; 28 import java.lang.annotation.Retention; 29 30 /** 31 * Thrown when an error occurs during a Bluetooth Socket related exception. 32 * 33 * <p>This is currently only intended to be thrown for a failure during {@link 34 * BluetoothSocket#connect()} operation. 35 */ 36 public class BluetoothSocketException extends IOException { 37 38 @Retention(SOURCE) 39 @IntDef({ 40 UNSPECIFIED, 41 L2CAP_UNKNOWN, 42 L2CAP_ACL_FAILURE, 43 L2CAP_CLIENT_SECURITY_FAILURE, 44 L2CAP_INSUFFICIENT_AUTHENTICATION, 45 L2CAP_INSUFFICIENT_AUTHORIZATION, 46 L2CAP_INSUFFICIENT_ENCRYPT_KEY_SIZE, 47 L2CAP_INSUFFICIENT_ENCRYPTION, 48 L2CAP_INVALID_SOURCE_CID, 49 L2CAP_SOURCE_CID_ALREADY_ALLOCATED, 50 L2CAP_UNACCEPTABLE_PARAMETERS, 51 L2CAP_INVALID_PARAMETERS, 52 L2CAP_NO_RESOURCES, 53 L2CAP_NO_PSM_AVAILABLE, 54 L2CAP_TIMEOUT, 55 BLUETOOTH_OFF_FAILURE, 56 SOCKET_MANAGER_FAILURE, 57 SOCKET_CLOSED, 58 SOCKET_CONNECTION_FAILURE, 59 NULL_DEVICE, 60 RPC_FAILURE, 61 UNIX_FILE_SOCKET_CREATION_FAILURE, 62 }) 63 private @interface ErrorCode {} 64 65 /** 66 * Error code representing a failure during {@link BluetoothSocket}. The reason for failure 67 * isn't specified. 68 */ 69 public static final int UNSPECIFIED = 0; 70 71 /** 72 * Error code during connect when socket connection fails for unknown reason during L2CAP 73 * connection. 74 */ 75 public static final int L2CAP_UNKNOWN = 1; 76 77 /** Error code during connect when there is an ACL connection failure. */ 78 public static final int L2CAP_ACL_FAILURE = 2; 79 80 /** 81 * Error code during connect when security clearance fails on the client during L2CAP 82 * connection. 83 */ 84 public static final int L2CAP_CLIENT_SECURITY_FAILURE = 3; 85 86 /** 87 * Error code during connect when authentication fails on the peer device during L2CAP 88 * connection. 89 */ 90 public static final int L2CAP_INSUFFICIENT_AUTHENTICATION = 4; 91 92 /** 93 * Error code during connect when authorization fails on the peer device during L2CAP 94 * connection. 95 */ 96 public static final int L2CAP_INSUFFICIENT_AUTHORIZATION = 5; 97 98 /** 99 * Error code during connect indicating insufficient encryption key size on the peer device 100 * during L2CAP connection. 101 */ 102 public static final int L2CAP_INSUFFICIENT_ENCRYPT_KEY_SIZE = 6; 103 104 /** 105 * Error code during connect for insufficient encryption from the peer device during L2CAP 106 * connection. 107 */ 108 public static final int L2CAP_INSUFFICIENT_ENCRYPTION = 7; 109 110 /** 111 * Error code during connect for invalid Channel ID from the peer device during L2CAP 112 * connection. 113 */ 114 public static final int L2CAP_INVALID_SOURCE_CID = 8; 115 116 /** 117 * Error code during connect for already allocated Channel ID from the peer device during L2CAP 118 * connection. 119 */ 120 public static final int L2CAP_SOURCE_CID_ALREADY_ALLOCATED = 9; 121 122 /** 123 * Error code during connect for unacceptable Parameters from the peer device during L2CAP 124 * connection. 125 */ 126 public static final int L2CAP_UNACCEPTABLE_PARAMETERS = 10; 127 128 /** 129 * Error code during connect for invalid parameters from the peer device during L2CAP 130 * connection. 131 */ 132 public static final int L2CAP_INVALID_PARAMETERS = 11; 133 134 /** Error code during connect when no resources are available for L2CAP connection. */ 135 public static final int L2CAP_NO_RESOURCES = 12; 136 137 /** Error code during connect when no PSM is available for L2CAP connection. */ 138 public static final int L2CAP_NO_PSM_AVAILABLE = 13; 139 140 /** Error code during connect when L2CAP connection timeout. */ 141 public static final int L2CAP_TIMEOUT = 14; 142 143 /** Error code during connect when Bluetooth is off and socket connection is triggered. */ 144 public static final int BLUETOOTH_OFF_FAILURE = 15; 145 146 /** Error code during connect when socket manager is not available. */ 147 public static final int SOCKET_MANAGER_FAILURE = 16; 148 149 /** Error code during connect when socket is closed. */ 150 public static final int SOCKET_CLOSED = 17; 151 152 /** Error code during connect for generic socket connection failures. */ 153 public static final int SOCKET_CONNECTION_FAILURE = 18; 154 155 /** Error code during connect when null device attempts to do socket connection. */ 156 public static final int NULL_DEVICE = 19; 157 158 /** Error code during connect when a Runtime RPC exception occurs. */ 159 public static final int RPC_FAILURE = 20; 160 161 /** Error code during connect when the UNIX socket connection creation fails. */ 162 @FlaggedApi(Flags.FLAG_UNIX_FILE_SOCKET_CREATION_FAILURE) 163 public static final int UNIX_FILE_SOCKET_CREATION_FAILURE = 21; 164 165 /* Corresponding messages for respective error codes. */ 166 private static final String UNSPECIFIED_MSG = "A Bluetooth Socket failure occurred"; 167 private static final String L2CAP_UNKNOWN_MSG = "Connection failed for unknown reason"; 168 private static final String L2CAP_ACL_FAILURE_MSG = "ACL connection failed"; 169 private static final String L2CAP_CLIENT_SECURITY_FAILURE_MSG = 170 "Client security clearance failed"; 171 private static final String L2CAP_INSUFFICIENT_AUTHENTICATION_MSG = 172 "Insufficient authentication"; 173 private static final String L2CAP_INSUFFICIENT_AUTHORIZATION_MSG = "Insufficient authorization"; 174 private static final String L2CAP_INSUFFICIENT_ENCRYPT_KEY_SIZE_MSG = 175 "Insufficient encryption key size"; 176 private static final String L2CAP_INSUFFICIENT_ENCRYPTION_MSG = "Insufficient encryption"; 177 private static final String L2CAP_INVALID_SOURCE_CID_MSG = "Invalid source CID"; 178 private static final String L2CAP_SOURCE_CID_ALREADY_ALLOCATED_MSG = 179 "Source CID already allocated"; 180 private static final String L2CAP_UNACCEPTABLE_PARAMETERS_MSG = "Unacceptable Parameters"; 181 private static final String L2CAP_INVALID_PARAMETERS_MSG = "Invalid Parameters"; 182 private static final String L2CAP_NO_RESOURCES_MSG = "No resources Available"; 183 private static final String L2CAP_NO_PSM_AVAILABLE_MSG = "No PSM available"; 184 private static final String L2CAP_TIMEOUT_MSG = "Connection Timeout"; 185 private static final String BLUETOOTH_OFF_FAILURE_MSG = "Bluetooth is off"; 186 private static final String SOCKET_MANAGER_FAILURE_MSG = "bt get socket manager failed"; 187 private static final String SOCKET_CLOSED_MSG = "socket closed"; 188 private static final String SOCKET_CONNECTION_FAILURE_MSG = "bt socket connect failed"; 189 private static final String NULL_DEVICE_MSG = "Connect is called on null device"; 190 private static final String UNIX_FILE_SOCKET_CREATION_FAILURE_MSG = 191 "Null file descriptor returned"; 192 193 @ErrorCode private final int mErrorCode; 194 195 /** 196 * Create a {@link BluetoothSocketException} with an error code and custom error message. 197 * 198 * @param code : error code representing the reason for failure. 199 * @param msg : Custom error message associated to the failure. 200 */ BluetoothSocketException(@rrorCode int code, @NonNull String msg)201 public BluetoothSocketException(@ErrorCode int code, @NonNull String msg) { 202 super(msg); 203 this.mErrorCode = code; 204 } 205 206 /** 207 * Create a {@link BluetoothSocketException} with an error code. A generic error message is 208 * generated based on the {@code code} provided. 209 * 210 * @param code : error code representing the reason for failure. 211 */ BluetoothSocketException(@rrorCode int code)212 public BluetoothSocketException(@ErrorCode int code) { 213 this(code, getMessage(code)); 214 } 215 216 /** Returns the error code associated to this failure. */ getErrorCode()217 public @ErrorCode int getErrorCode() { 218 return mErrorCode; 219 } 220 getMessage(@rrorCode int code)221 private static String getMessage(@ErrorCode int code) { 222 switch (code) { 223 case BLUETOOTH_OFF_FAILURE: 224 return BLUETOOTH_OFF_FAILURE_MSG; 225 case SOCKET_MANAGER_FAILURE: 226 return SOCKET_MANAGER_FAILURE_MSG; 227 case SOCKET_CLOSED: 228 return SOCKET_CLOSED_MSG; 229 case SOCKET_CONNECTION_FAILURE: 230 return SOCKET_CONNECTION_FAILURE_MSG; 231 case NULL_DEVICE: 232 return NULL_DEVICE_MSG; 233 case UNIX_FILE_SOCKET_CREATION_FAILURE: 234 return UNIX_FILE_SOCKET_CREATION_FAILURE_MSG; 235 case L2CAP_ACL_FAILURE: 236 return L2CAP_ACL_FAILURE_MSG; 237 case L2CAP_CLIENT_SECURITY_FAILURE: 238 return L2CAP_CLIENT_SECURITY_FAILURE_MSG; 239 case L2CAP_INSUFFICIENT_AUTHENTICATION: 240 return L2CAP_INSUFFICIENT_AUTHENTICATION_MSG; 241 case L2CAP_INSUFFICIENT_AUTHORIZATION: 242 return L2CAP_INSUFFICIENT_AUTHORIZATION_MSG; 243 case L2CAP_INSUFFICIENT_ENCRYPT_KEY_SIZE: 244 return L2CAP_INSUFFICIENT_ENCRYPT_KEY_SIZE_MSG; 245 case L2CAP_INSUFFICIENT_ENCRYPTION: 246 return L2CAP_INSUFFICIENT_ENCRYPTION_MSG; 247 case L2CAP_INVALID_SOURCE_CID: 248 return L2CAP_INVALID_SOURCE_CID_MSG; 249 case L2CAP_SOURCE_CID_ALREADY_ALLOCATED: 250 return L2CAP_SOURCE_CID_ALREADY_ALLOCATED_MSG; 251 case L2CAP_UNACCEPTABLE_PARAMETERS: 252 return L2CAP_UNACCEPTABLE_PARAMETERS_MSG; 253 case L2CAP_INVALID_PARAMETERS: 254 return L2CAP_INVALID_PARAMETERS_MSG; 255 case L2CAP_NO_RESOURCES: 256 return L2CAP_NO_RESOURCES_MSG; 257 case L2CAP_NO_PSM_AVAILABLE: 258 return L2CAP_NO_PSM_AVAILABLE_MSG; 259 case L2CAP_TIMEOUT: 260 return L2CAP_TIMEOUT_MSG; 261 case L2CAP_UNKNOWN: 262 return L2CAP_UNKNOWN_MSG; 263 case UNSPECIFIED: 264 default: 265 return UNSPECIFIED_MSG; 266 } 267 } 268 } 269