• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 android.bluetooth.BluetoothSocket.SocketType;
20 
21 import static java.util.Objects.requireNonNull;
22 
23 import android.annotation.FlaggedApi;
24 import android.annotation.IntDef;
25 import android.annotation.IntRange;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresNoPermission;
29 import android.annotation.SystemApi;
30 
31 import com.android.bluetooth.flags.Flags;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 import java.nio.charset.StandardCharsets;
36 import java.util.UUID;
37 
38 /**
39  * Defines parameters for creating Bluetooth server and client socket channels.
40  *
41  * <p>Used with {@link BluetoothAdapter#listenUsingSocketSettings} to create a server socket and
42  * {@link BluetoothDevice#createUsingSocketSettings} to create a client socket.
43  *
44  * @see BluetoothAdapter#listenUsingSocketSettings
45  * @see BluetoothDevice#createUsingSocketSettings
46  */
47 @FlaggedApi(Flags.FLAG_SOCKET_SETTINGS_API)
48 public final class BluetoothSocketSettings {
49 
50     private static final int L2CAP_PSM_UNSPECIFIED = -1;
51 
52     /**
53      * Annotation to define the data path used for Bluetooth socket communication. This determines
54      * how data flows between the application and the Bluetooth controller.
55      *
56      * @hide
57      */
58     @IntDef(
59             prefix = {"DATA_PATH_"},
60             value = {DATA_PATH_NO_OFFLOAD, DATA_PATH_HARDWARE_OFFLOAD})
61     @Retention(RetentionPolicy.SOURCE)
62     public @interface SocketDataPath {}
63 
64     /**
65      * Non-offload data path where the application's socket data is processed by the main Bluetooth
66      * stack.
67      *
68      * @hide
69      */
70     @SystemApi public static final int DATA_PATH_NO_OFFLOAD = 0;
71 
72     /**
73      * Hardware offload data path where the application's socket data is processed by a offloaded
74      * application running on the low-power processor.
75      *
76      * <p>Using this data path requires the {@code BLUETOOTH_PRIVILEGED} permission, which will be
77      * checked when a socket connection or channel is created.
78      *
79      * @hide
80      */
81     @SystemApi public static final int DATA_PATH_HARDWARE_OFFLOAD = 1;
82 
83     /**
84      * Maximum size (in bytes) of a data packet that can be received from the endpoint when using
85      * {@link #DATA_PATH_HARDWARE_OFFLOAD}.
86      */
87     @SystemApi private static final int HARDWARE_OFFLOAD_PACKET_MAX_SIZE = 65535;
88 
89     /**
90      * Maximum length (in bytes) of a socket name when using {@link #DATA_PATH_HARDWARE_OFFLOAD}.
91      */
92     @SystemApi private static final int HARDWARE_OFFLOAD_SOCKET_NAME_MAX_LENGTH = 127;
93 
94     /**
95      * Constant representing an invalid hub ID. This value indicates that a hub ID has not been
96      * assigned or is not valid.
97      *
98      * @hide
99      */
100     private static final long INVALID_HUB_ID = 0;
101 
102     /**
103      * Constant representing an invalid hub endpoint ID. This value indicates that an endpoint ID
104      * has not been assigned or is not valid.
105      *
106      * @hide
107      */
108     private static final long INVALID_ENDPOINT_ID = 0;
109 
110     /** Type of the Bluetooth socket */
111     @SocketType private final int mSocketType;
112 
113     /** Encryption requirement for the Bluetooth socket. */
114     private final boolean mEncryptionRequired;
115 
116     /** Authentication requirement for the Bluetooth socket. */
117     private final boolean mAuthenticationRequired;
118 
119     /** L2CAP Protocol/Service Multiplexer (PSM) for the Bluetooth Socket. */
120     private final int mL2capPsm;
121 
122     /** RFCOMM service name associated with the Bluetooth socket. */
123     private final String mRfcommServiceName;
124 
125     /** RFCOMM service UUID associated with the Bluetooth socket. */
126     private final UUID mRfcommUuid;
127 
128     /**
129      * Specifies the data path used for this socket, influencing how data is transmitted and
130      * processed. Select the appropriate data path based on performance and power consumption
131      * requirements:
132      *
133      * <ul>
134      *   <li>{@link #DATA_PATH_NO_OFFLOAD}: Suitable for applications that require the full
135      *       processing capabilities of the main Bluetooth stack.
136      *   <li>{@link #DATA_PATH_HARDWARE_OFFLOAD}: Optimized for lower power consumption by utilizing
137      *       an offloaded application running on a dedicated low-power processor.
138      * </ul>
139      */
140     private final @SocketDataPath int mDataPath;
141 
142     /**
143      * A user-friendly name for this socket, primarily for debugging and logging. This name should
144      * be descriptive and can help identify the socket during development and troubleshooting.
145      *
146      * <p>When using {@link #DATA_PATH_HARDWARE_OFFLOAD}, this name is also passed to the offloaded
147      * application running on the low-power processor. This allows the offloaded application to
148      * identify and manage the socket.
149      */
150     private final String mSocketName;
151 
152     /**
153      * When using {@link #DATA_PATH_HARDWARE_OFFLOAD}, this identifies the hub hosting the endpoint.
154      *
155      * <p>Hub represents a logical/physical representation of multiple endpoints. A pair of {@code
156      * mHubId} and {@code mEndpointId} uniquely identifies the endpoint globally.
157      */
158     private final long mHubId;
159 
160     /**
161      * When using {@link #DATA_PATH_HARDWARE_OFFLOAD}, this identifies the specific endpoint within
162      * the hub that is associated with this socket.
163      */
164     private final long mEndpointId;
165 
166     /**
167      * The maximum size (in bytes) of a single data packet that can be received from the endpoint
168      * when using {@link #DATA_PATH_HARDWARE_OFFLOAD}.
169      */
170     private final int mMaximumPacketSize;
171 
172     /**
173      * Returns the type of the Bluetooth socket.
174      *
175      * <p>Defaults to {@code BluetoothSocket#TYPE_RFCOMM}.
176      */
177     @RequiresNoPermission
178     @SocketType
getSocketType()179     public int getSocketType() {
180         return mSocketType;
181     }
182 
183     /** Returns the L2CAP PSM value used for a BluetoothSocket#TYPE_LE socket. */
184     @RequiresNoPermission
getL2capPsm()185     public @IntRange(from = 128, to = 255) int getL2capPsm() {
186         return mL2capPsm;
187     }
188 
189     /**
190      * Returns the RFCOMM service name used for a BluetoothSocket#TYPE_RFCOMM socket.
191      *
192      * <p>Defaults to {@code null}.
193      */
194     @Nullable
195     @RequiresNoPermission
getRfcommServiceName()196     public String getRfcommServiceName() {
197         return mRfcommServiceName;
198     }
199 
200     /**
201      * Returns the RFCOMM service UUID used for a BluetoothSocket#TYPE_RFCOMM socket.
202      *
203      * <p>Defaults to {@code null}.
204      */
205     @Nullable
206     @RequiresNoPermission
getRfcommUuid()207     public UUID getRfcommUuid() {
208         return mRfcommUuid;
209     }
210 
211     /**
212      * Checks if encryption is enabled for the Bluetooth socket.
213      *
214      * <p>Defaults to {@code false}.
215      */
216     @RequiresNoPermission
isEncryptionRequired()217     public boolean isEncryptionRequired() {
218         return mEncryptionRequired;
219     }
220 
221     /**
222      * Checks if authentication is enabled for the Bluetooth socket.
223      *
224      * <p>Defaults to {@code false}.
225      */
226     @RequiresNoPermission
isAuthenticationRequired()227     public boolean isAuthenticationRequired() {
228         return mAuthenticationRequired;
229     }
230 
231     /**
232      * Returns the data path used for this socket. The data path determines how data is routed and
233      * processed for the socket connection.
234      *
235      * <p>Defaults to {@link #DATA_PATH_NO_OFFLOAD}.
236      *
237      * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
238      * available through the System API.
239      *
240      * @hide
241      */
242     @SystemApi
243     @RequiresNoPermission
getDataPath()244     public @SocketDataPath int getDataPath() {
245         return mDataPath;
246     }
247 
248     /**
249      * Returns the user-friendly name assigned to this socket. This name is primarily used for
250      * debugging and logging purposes.
251      *
252      * <p>When using {@link #DATA_PATH_HARDWARE_OFFLOAD}, this name is also passed to the offloaded
253      * application running on the low-power processor.
254      *
255      * <p>Defaults to {@code null} if no name was explicitly set.
256      *
257      * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
258      * available through the System API.
259      *
260      * @hide
261      */
262     @SystemApi
263     @NonNull
264     @RequiresNoPermission
getSocketName()265     public String getSocketName() {
266         return mSocketName;
267     }
268 
269     /**
270      * Returns the ID of the hub associated with this socket when using {@link
271      * #DATA_PATH_HARDWARE_OFFLOAD}.
272      *
273      * <p>If the data path is not set to {@link #DATA_PATH_HARDWARE_OFFLOAD}, this method returns
274      * {@link #INVALID_HUB_ID}.
275      *
276      * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
277      * available through the System API.
278      *
279      * @hide
280      */
281     @SystemApi
282     @RequiresNoPermission
getHubId()283     public long getHubId() {
284         if (mDataPath != DATA_PATH_HARDWARE_OFFLOAD) {
285             return INVALID_HUB_ID;
286         }
287         return mHubId;
288     }
289 
290     /**
291      * Returns the ID of the endpoint within the hub associated with this socket when using {@link
292      * #DATA_PATH_HARDWARE_OFFLOAD}. An endpoint represents a specific point of communication within
293      * the hub.
294      *
295      * <p>If the data path is not set to {@link #DATA_PATH_HARDWARE_OFFLOAD}, this method returns
296      * {@link #INVALID_ENDPOINT_ID}.
297      *
298      * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
299      * available through the System API.
300      *
301      * @hide
302      */
303     @SystemApi
304     @RequiresNoPermission
getEndpointId()305     public long getEndpointId() {
306         if (mDataPath != DATA_PATH_HARDWARE_OFFLOAD) {
307             return INVALID_ENDPOINT_ID;
308         }
309         return mEndpointId;
310     }
311 
312     /**
313      * Returns the requested maximum size (in bytes) of a data packet that can be received from the
314      * endpoint associated with this socket when using {@link #DATA_PATH_HARDWARE_OFFLOAD}.
315      *
316      * <p>Defaults to {@link #HARDWARE_OFFLOAD_PACKET_MAX_SIZE}.
317      *
318      * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
319      * available through the System API.
320      *
321      * @hide
322      */
323     @SystemApi
324     @RequiresNoPermission
getRequestedMaximumPacketSize()325     public int getRequestedMaximumPacketSize() {
326         return mMaximumPacketSize;
327     }
328 
329     /**
330      * Returns a {@link String} that describes each BluetoothSocketSettings parameter current value.
331      */
332     @Override
toString()333     public String toString() {
334         StringBuilder builder = new StringBuilder("BluetoothSocketSettings{");
335         builder.append("mSocketType=")
336                 .append(mSocketType)
337                 .append(", mEncryptionRequired=")
338                 .append(mEncryptionRequired)
339                 .append(", mAuthenticationRequired=")
340                 .append(mAuthenticationRequired);
341         if (mSocketType == BluetoothSocket.TYPE_RFCOMM) {
342             builder.append(", mRfcommServiceName=")
343                     .append(mRfcommServiceName)
344                     .append(", mRfcommUuid=")
345                     .append(mRfcommUuid);
346         } else {
347             builder.append(", mL2capPsm=").append(mL2capPsm);
348         }
349         if (mDataPath == DATA_PATH_HARDWARE_OFFLOAD) {
350             builder.append(", mDataPath=")
351                     .append(mDataPath)
352                     .append(", mSocketName=")
353                     .append(mSocketName)
354                     .append(", mHubId=")
355                     .append(mHubId)
356                     .append(", mEndpointId=")
357                     .append(mEndpointId)
358                     .append(", mMaximumPacketSize=")
359                     .append(mMaximumPacketSize);
360         }
361         builder.append("}");
362         return builder.toString();
363     }
364 
BluetoothSocketSettings( int socketType, int l2capPsm, boolean encryptionRequired, boolean authenticationRequired, String rfcommServiceName, UUID rfcommUuid, int dataPath, String socketName, long hubId, long endpointId, int maximumPacketSize)365     private BluetoothSocketSettings(
366             int socketType,
367             int l2capPsm,
368             boolean encryptionRequired,
369             boolean authenticationRequired,
370             String rfcommServiceName,
371             UUID rfcommUuid,
372             int dataPath,
373             String socketName,
374             long hubId,
375             long endpointId,
376             int maximumPacketSize) {
377         mSocketType = socketType;
378         mL2capPsm = l2capPsm;
379         mEncryptionRequired = encryptionRequired;
380         mAuthenticationRequired = authenticationRequired;
381         mRfcommUuid = rfcommUuid;
382         mRfcommServiceName = rfcommServiceName;
383         mDataPath = dataPath;
384         mSocketName = socketName;
385         mHubId = hubId;
386         mEndpointId = endpointId;
387         mMaximumPacketSize = maximumPacketSize;
388     }
389 
390     /** Builder for {@link BluetoothSocketSettings}. */
391     @FlaggedApi(Flags.FLAG_SOCKET_SETTINGS_API)
392     public static final class Builder {
393         private int mSocketType = BluetoothSocket.TYPE_RFCOMM;
394         private int mL2capPsm = L2CAP_PSM_UNSPECIFIED;
395         private boolean mEncryptionRequired = false;
396         private boolean mAuthenticationRequired = false;
397         private String mRfcommServiceName = null;
398         private UUID mRfcommUuid = null;
399         private int mDataPath = DATA_PATH_NO_OFFLOAD;
400         private String mSocketName = BluetoothSocket.DEFAULT_SOCKET_NAME;
401         private long mHubId = INVALID_HUB_ID;
402         private long mEndpointId = INVALID_ENDPOINT_ID;
403         private int mMaximumPacketSize = HARDWARE_OFFLOAD_PACKET_MAX_SIZE;
404 
Builder()405         public Builder() {}
406 
407         /**
408          * Sets the socket type.
409          *
410          * <p>Must be one of:
411          *
412          * <ul>
413          *   <li>{@link BluetoothSocket#TYPE_RFCOMM}
414          *   <li>{@link BluetoothSocket#TYPE_LE}
415          * </ul>
416          *
417          * <p>Defaults to {@code BluetoothSocket#TYPE_RFCOMM}.
418          *
419          * @param socketType The type of socket.
420          * @return This builder.
421          * @throws IllegalArgumentException If {@code socketType} is invalid.
422          */
423         @NonNull
424         @RequiresNoPermission
setSocketType(@ocketType int socketType)425         public Builder setSocketType(@SocketType int socketType) {
426             if (socketType != BluetoothSocket.TYPE_RFCOMM
427                     && socketType != BluetoothSocket.TYPE_LE) {
428                 throw new IllegalArgumentException("invalid socketType - " + socketType);
429             }
430             mSocketType = socketType;
431             return this;
432         }
433 
434         /**
435          * Sets the L2CAP PSM (Protocol/Service Multiplexer) for the Bluetooth socket.
436          *
437          * <p>This is only used for {@link BluetoothSocket#TYPE_LE} sockets.
438          *
439          * <p>Valid PSM values for {@link BluetoothSocket#TYPE_LE} sockets is ranging from 128
440          * (0x80) to 255 (0xFF).
441          *
442          * <p>Application using this API is responsible for obtaining protocol/service multiplexer
443          * (PSM) value from remote device.
444          *
445          * @param l2capPsm The L2CAP PSM value.
446          * @return This builder.
447          * @throws IllegalArgumentException If l2cap PSM is not in given range.
448          */
449         @NonNull
450         @RequiresNoPermission
setL2capPsm(@ntRangefrom = 128, to = 255) int l2capPsm)451         public Builder setL2capPsm(@IntRange(from = 128, to = 255) int l2capPsm) {
452             if (l2capPsm < 128 || l2capPsm > 255) {
453                 throw new IllegalArgumentException("invalid L2cap PSM - " + l2capPsm);
454             }
455             mL2capPsm = l2capPsm;
456             return this;
457         }
458 
459         /**
460          * Sets the encryption requirement for the Bluetooth socket.
461          *
462          * <p>Defaults to {@code false}.
463          *
464          * @param encryptionRequired {@code true} if encryption is required for this socket, {@code
465          *     false} otherwise.
466          * @return This builder.
467          */
468         @NonNull
469         @RequiresNoPermission
setEncryptionRequired(boolean encryptionRequired)470         public Builder setEncryptionRequired(boolean encryptionRequired) {
471             mEncryptionRequired = encryptionRequired;
472             return this;
473         }
474 
475         /**
476          * Sets the authentication requirement for the Bluetooth socket.
477          *
478          * <p>Defaults to {@code false}.
479          *
480          * @param authenticationRequired {@code true} if authentication is required for this socket,
481          *     {@code false} otherwise.
482          * @return This builder.
483          */
484         @NonNull
485         @RequiresNoPermission
setAuthenticationRequired(boolean authenticationRequired)486         public Builder setAuthenticationRequired(boolean authenticationRequired) {
487             mAuthenticationRequired = authenticationRequired;
488             return this;
489         }
490 
491         /**
492          * Sets the RFCOMM service name associated with the Bluetooth socket.
493          *
494          * <p>This name is used to identify the service when a remote device searches for it using
495          * SDP.
496          *
497          * <p>This is only used for {@link BluetoothSocket#TYPE_RFCOMM} sockets.
498          *
499          * <p>Defaults to {@code null}.
500          *
501          * @param rfcommServiceName The RFCOMM service name.
502          * @return This builder.
503          */
504         @NonNull
505         @RequiresNoPermission
setRfcommServiceName(@onNull String rfcommServiceName)506         public Builder setRfcommServiceName(@NonNull String rfcommServiceName) {
507             mRfcommServiceName = rfcommServiceName;
508             return this;
509         }
510 
511         /**
512          * Sets the RFCOMM service UUID associated with the Bluetooth socket.
513          *
514          * <p>This UUID is used to uniquely identify the service when a remote device searches for
515          * it using SDP.
516          *
517          * <p>This is only used for {@link BluetoothSocket#TYPE_RFCOMM} sockets.
518          *
519          * <p>Defaults to {@code null}.
520          *
521          * @param rfcommUuid The RFCOMM service UUID.
522          * @return This builder.
523          */
524         @NonNull
525         @RequiresNoPermission
setRfcommUuid(@onNull UUID rfcommUuid)526         public Builder setRfcommUuid(@NonNull UUID rfcommUuid) {
527             mRfcommUuid = rfcommUuid;
528             return this;
529         }
530 
531         /**
532          * Sets the data path for this socket. The data path determines how data is routed and
533          * processed for the socket connection.
534          *
535          * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
536          * available through the System API.
537          *
538          * @param dataPath The desired data path for the socket.
539          * @return This Builder object to allow for method chaining.
540          * @throws IllegalArgumentException If {@code dataPath} is an invalid value.
541          * @hide
542          */
543         @SystemApi
544         @NonNull
545         @RequiresNoPermission
setDataPath(@ocketDataPath int dataPath)546         public Builder setDataPath(@SocketDataPath int dataPath) {
547             if (dataPath < DATA_PATH_NO_OFFLOAD || dataPath > DATA_PATH_HARDWARE_OFFLOAD) {
548                 throw new IllegalArgumentException("Invalid dataPath - " + dataPath);
549             }
550             mDataPath = dataPath;
551             return this;
552         }
553 
554         /**
555          * Sets a user-friendly name for this socket. This name is primarily used for debugging and
556          * logging purposes.
557          *
558          * <p>When using {@link #DATA_PATH_HARDWARE_OFFLOAD}, this name is also passed to the
559          * offloaded application running on low-power processor.
560          *
561          * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
562          * available through the System API.
563          *
564          * @param socketName The desired name for the socket. This should be a descriptive name that
565          *     helps identify the socket during development and troubleshooting. The socket name
566          *     cannot exceed {@link #HARDWARE_OFFLOAD_SOCKET_NAME_MAX_LENGTH} bytes in length when
567          *     encoded in UTF-8.
568          * @return This Builder object to allow for method chaining.
569          * @throws IllegalArgumentException if the provided `socketName` exceeds {@link
570          *     #HARDWARE_OFFLOAD_SOCKET_NAME_MAX_LENGTH} bytes when encoded in UTF-8.
571          * @hide
572          */
573         @SystemApi
574         @NonNull
575         @RequiresNoPermission
setSocketName(@onNull String socketName)576         public Builder setSocketName(@NonNull String socketName) {
577             byte[] socketNameBytes = requireNonNull(socketName).getBytes(StandardCharsets.UTF_8);
578             if (socketNameBytes.length > HARDWARE_OFFLOAD_SOCKET_NAME_MAX_LENGTH) {
579                 throw new IllegalArgumentException(
580                         "Socket name cannot exceed "
581                                 + HARDWARE_OFFLOAD_SOCKET_NAME_MAX_LENGTH
582                                 + " bytes in length when encoded in UTF-8.");
583             }
584             mSocketName = requireNonNull(socketName);
585             return this;
586         }
587 
588         /**
589          * Sets the ID of the hub to be associated with this socket when using {@link
590          * #DATA_PATH_HARDWARE_OFFLOAD}.
591          *
592          * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
593          * available through the System API.
594          *
595          * @param hubId The ID of the hub.
596          * @return This Builder object to allow for method chaining.
597          * @hide
598          */
599         @SystemApi
600         @NonNull
601         @RequiresNoPermission
setHubId(long hubId)602         public Builder setHubId(long hubId) {
603             mHubId = hubId;
604             return this;
605         }
606 
607         /**
608          * Sets the ID of the endpoint within the hub to be associated with this socket when using
609          * {@link #DATA_PATH_HARDWARE_OFFLOAD}. An endpoint represents a specific point of
610          * communication within the hub.
611          *
612          * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
613          * available through the System API.
614          *
615          * @param endpointId The ID of the endpoint within the hub.
616          * @return This Builder object to allow for method chaining.
617          * @hide
618          */
619         @SystemApi
620         @NonNull
621         @RequiresNoPermission
setEndpointId(long endpointId)622         public Builder setEndpointId(long endpointId) {
623             mEndpointId = endpointId;
624             return this;
625         }
626 
627         /**
628          * Sets the requested maximum size (in bytes) of a data packet that can be received from the
629          * endpoint associated with this socket when using {@link #DATA_PATH_HARDWARE_OFFLOAD}.
630          *
631          * <p>The main Bluetooth stack may adjust this value based on the actual capabilities
632          * negotiated with the peer device during connection establishment. To get the final
633          * negotiated value, use {@link BluetoothSocket#getMaxReceivePacketSize()} after the socket
634          * is connected.
635          *
636          * <p>This API is part of the System API because {@link #DATA_PATH_HARDWARE_OFFLOAD} is only
637          * available through the System API.
638          *
639          * @param maximumPacketSize The maximum packet size in bytes.
640          * @return This Builder object to allow for method chaining.
641          * @hide
642          */
643         @SystemApi
644         @NonNull
645         @RequiresNoPermission
setRequestedMaximumPacketSize(int maximumPacketSize)646         public Builder setRequestedMaximumPacketSize(int maximumPacketSize) {
647             mMaximumPacketSize = maximumPacketSize;
648             return this;
649         }
650 
651         /**
652          * Builds a {@link BluetoothSocketSettings} object.
653          *
654          * @return A new {@link BluetoothSocketSettings} object with the configured parameters.
655          * @throws IllegalArgumentException on invalid parameters
656          */
657         @NonNull
658         @RequiresNoPermission
build()659         public BluetoothSocketSettings build() {
660             if (mSocketType == BluetoothSocket.TYPE_RFCOMM) {
661                 if (mRfcommUuid == null) {
662                     throw new IllegalArgumentException("RFCOMM socket with missing uuid");
663                 }
664                 if (mL2capPsm != L2CAP_PSM_UNSPECIFIED) {
665                     throw new IllegalArgumentException(
666                             "Invalid Socket config: "
667                                     + " Socket type: "
668                                     + mSocketType
669                                     + " L2cap PSM: "
670                                     + mL2capPsm);
671                 }
672             }
673             if (mSocketType == BluetoothSocket.TYPE_LE) {
674                 if (mRfcommUuid != null) {
675                     throw new IllegalArgumentException(
676                             "Invalid Socket config: "
677                                     + "Socket type: "
678                                     + mSocketType
679                                     + " Rfcomm Service Name: "
680                                     + mRfcommServiceName
681                                     + " Rfcomm Uuid: "
682                                     + mRfcommUuid);
683                 }
684             }
685             if (mDataPath == DATA_PATH_HARDWARE_OFFLOAD) {
686                 if (mHubId == INVALID_HUB_ID || mEndpointId == INVALID_ENDPOINT_ID) {
687                     throw new IllegalArgumentException(
688                             "Hub ID and endpoint ID must be set for hardware data path");
689                 }
690                 if (mMaximumPacketSize < 0) {
691                     throw new IllegalArgumentException("invalid packet size " + mMaximumPacketSize);
692                 }
693             } else {
694                 if (mHubId != INVALID_HUB_ID || mEndpointId != INVALID_ENDPOINT_ID) {
695                     throw new IllegalArgumentException(
696                             "Hub ID and endpoint ID may not be set for software data path");
697                 }
698             }
699             return new BluetoothSocketSettings(
700                     mSocketType,
701                     mL2capPsm,
702                     mEncryptionRequired,
703                     mAuthenticationRequired,
704                     mRfcommServiceName,
705                     mRfcommUuid,
706                     mDataPath,
707                     mSocketName,
708                     mHubId,
709                     mEndpointId,
710                     mMaximumPacketSize);
711         }
712     }
713 }
714