Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 412cbec0 authored by Stanley Tng's avatar Stanley Tng
Browse files

Unhide the LE CoC APIs

Expose the LE Connection-oriented Channels APIs for applications to use.

Test: Run the SL4A ACTS test: BleCocTest
Bug: 70683224
Change-Id: I68128bc7154966ec065091c973351f8892da9b4d
parent 80915c20
Loading
Loading
Loading
Loading
+38 −21
Original line number Diff line number Diff line
@@ -81,7 +81,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 * {@link #getBondedDevices()}; start device discovery with
 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
 * listen for incoming RFComm connection requests with {@link
 * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
 * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
 * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
 * </p>
 * <p>This class is thread safe.</p>
@@ -2967,7 +2968,7 @@ public final class BluetoothAdapter {
    /**
     * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
     * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
     * for incoming connections.
     * for incoming connections. The supported Bluetooth transport is LE only.
     * <p>A remote device connecting to this socket will be authenticated and communication on this
     * socket will be encrypted.
     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
@@ -2977,21 +2978,16 @@ public final class BluetoothAdapter {
     * closed, Bluetooth is turned off, or the application exits unexpectedly.
     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
     * defined and performed by the application.
     * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server
     * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
     * socket from another Android device that is given the PSM value.
     *
     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
     * @return an L2CAP CoC BluetoothServerSocket
     * @throws IOException on error, for example Bluetooth not available, or insufficient
     * permissions, or unable to start this CoC
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothServerSocket listenUsingL2capCoc(int transport)
    public BluetoothServerSocket listenUsingL2capChannel()
            throws IOException {
        if (transport != BluetoothDevice.TRANSPORT_LE) {
            throw new IllegalArgumentException("Unsupported transport: " + transport);
        }
        BluetoothServerSocket socket =
                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
@@ -3005,7 +3001,7 @@ public final class BluetoothAdapter {
            throw new IOException("Error: Unable to assign PSM value");
        }
        if (DBG) {
            Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to "
            Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
                    + assignedPsm);
        }
        socket.setChannel(assignedPsm);
@@ -3013,11 +3009,24 @@ public final class BluetoothAdapter {
        return socket;
    }

    /**
     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
     * API name, listenUsingL2capChannel.
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothServerSocket listenUsingL2capCoc(int transport)
            throws IOException {
        Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
        return listenUsingL2capChannel();
    }

    /**
     * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
     * assign a dynamic PSM value. This socket can be used to listen for incoming connections.
     * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
     * supported Bluetooth transport is LE only.
     * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
     * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and
     * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
     * authenticated communication channel is desired.
     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
     * {@link BluetoothServerSocket}.
@@ -3027,21 +3036,16 @@ public final class BluetoothAdapter {
     * unexpectedly.
     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
     * defined and performed by the application.
     * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this
     * server socket from another Android device that is given the PSM value.
     * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
     * socket from another Android device that is given the PSM value.
     *
     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
     * @return an L2CAP CoC BluetoothServerSocket
     * @throws IOException on error, for example Bluetooth not available, or insufficient
     * permissions, or unable to start this CoC
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
    public BluetoothServerSocket listenUsingInsecureL2capChannel()
            throws IOException {
        if (transport != BluetoothDevice.TRANSPORT_LE) {
            throw new IllegalArgumentException("Unsupported transport: " + transport);
        }
        BluetoothServerSocket socket =
                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
@@ -3055,11 +3059,24 @@ public final class BluetoothAdapter {
            throw new IOException("Error: Unable to assign PSM value");
        }
        if (DBG) {
            Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to "
            Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
                    + assignedPsm);
        }
        socket.setChannel(assignedPsm);

        return socket;
    }

    /**
     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
     * API name, listenUsingInsecureL2capChannel.
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
            throws IOException {
        Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
                    + "listenUsingInsecureL2capChannel");
        return listenUsingInsecureL2capChannel();
    }
}
+34 −22
Original line number Diff line number Diff line
@@ -1963,8 +1963,8 @@ public final class BluetoothDevice implements Parcelable {
    /**
     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
     * be used to start a secure outgoing connection to the remote device with the same dynamic
     * protocol/service multiplexer (PSM) value.
     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capCoc(int)} for
     * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for
     * peer-peer Bluetooth applications.
     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
     * <p>Application using this API is responsible for obtaining PSM value from remote device.
@@ -1975,59 +1975,71 @@ public final class BluetoothDevice implements Parcelable {
     * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int,
     * int)}.
     *
     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
     * @param psm dynamic PSM value from remote device
     * @return a CoC #BluetoothSocket ready for an outgoing connection
     * @throws IOException on error, for example Bluetooth not available, or insufficient
     * permissions
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
    public BluetoothSocket createL2capChannel(int psm) throws IOException {
        if (!isBluetoothEnabled()) {
            Log.e(TAG, "createL2capCocSocket: Bluetooth is not enabled");
            Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
            throw new IOException();
        }
        if (transport != BluetoothDevice.TRANSPORT_LE) {
            throw new IllegalArgumentException("Unsupported transport: " + transport);
        }
        if (DBG) Log.d(TAG, "createL2capCocSocket: transport=" + transport + ", psm=" + psm);
        if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm);
        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
                null);
    }

    /**
     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
     * API name, createL2capChannel.
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel");
        return createL2capChannel(psm);
    }

    /**
     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
     * be used to start a secure outgoing connection to the remote device with the same dynamic
     * protocol/service multiplexer (PSM) value.
     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingInsecureL2capCoc(int)}
     * for peer-peer Bluetooth applications.
     * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
     * <p>This is designed to be used with {@link
     * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications.
     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
     * <p>Application using this API is responsible for obtaining PSM value from remote device.
     * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
     * to man-in-the-middle attacks. Use {@link #createL2capCocSocket(int, int)} if an encrypted and
     * to man-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and
     * authenticated communication channel is possible.
     *
     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
     * @param psm dynamic PSM value from remote device
     * @return a CoC #BluetoothSocket ready for an outgoing connection
     * @throws IOException on error, for example Bluetooth not available, or insufficient
     * permissions
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
    public BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
        if (!isBluetoothEnabled()) {
            Log.e(TAG, "createInsecureL2capCocSocket: Bluetooth is not enabled");
            Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
            throw new IOException();
        }
        if (transport != BluetoothDevice.TRANSPORT_LE) {
            throw new IllegalArgumentException("Unsupported transport: " + transport);
        }
        if (DBG) {
            Log.d(TAG, "createInsecureL2capCocSocket: transport=" + transport + ", psm=" + psm);
            Log.d(TAG, "createInsecureL2capChannel: psm=" + psm);
        }
        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
                null);
    }

    /**
     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
     * API name, createInsecureL2capChannel.
     * @hide
     */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel");
        return createInsecureL2capChannel(psm);
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -203,12 +203,11 @@ public final class BluetoothServerSocket implements Closeable {
    /**
     * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
     * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
     * {#link BluetoothAdapter.listenUsingL2capCoc(int)} or {#link
     * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this
     * {#link BluetoothAdapter.listenUsingL2capChannel()} or {#link
     * BluetoothAdapter.listenUsingInsecureL2capChannel()}. The returned value is undefined if this
     * method is called on non-L2CAP server sockets.
     *
     * @return the assigned PSM or LE_PSM value depending on transport
     * @hide
     */
    public int getPsm() {
        return mChannel;
+4 −0
Original line number Diff line number Diff line
@@ -667,6 +667,10 @@ public final class BluetoothSocket implements Closeable {
     * @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
     */
    public int getConnectionType() {
        if (mType == TYPE_L2CAP_LE) {
            // Treat the LE CoC to be the same type as L2CAP.
            return TYPE_L2CAP;
        }
        return mType;
    }