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