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

Commit d61c8e07 authored by Jayden Kim's avatar Jayden Kim Committed by Gerrit Code Review
Browse files

Merge "Socket API to get L2CAP channel ID" into main

parents a383cd99 34602a44
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -33,4 +33,6 @@ interface IBluetoothSocketManager
    @nullable ParcelFileDescriptor createSocketChannel(int type, in @nullable String serviceName, in @nullable ParcelUuid uuid, int port, int flag);
    @nullable ParcelFileDescriptor createSocketChannel(int type, in @nullable String serviceName, in @nullable ParcelUuid uuid, int port, int flag);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void requestMaximumTxDataLength(in BluetoothDevice device);
    void requestMaximumTxDataLength(in BluetoothDevice device);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    boolean checkPermissionForL2capChannelInfo(in AttributionSource attributionSource);
}
}
+16 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.bluetooth.btservice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.IBluetoothSocketManager;
import android.bluetooth.IBluetoothSocketManager;
import android.content.AttributionSource;
import android.os.Binder;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.ParcelUuid;
import android.os.ParcelUuid;
@@ -97,6 +98,21 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
                .requestMaximumTxDataLength(Utils.getBytesFromAddress(device.getAddress()));
                .requestMaximumTxDataLength(Utils.getBytesFromAddress(device.getAddress()));
    }
    }


    @Override
    public boolean checkPermissionForL2capChannelInfo(AttributionSource source) {
        AdapterService service = mService;
        if (service == null
                || !Utils.callerIsSystemOrActiveOrManagedUser(
                service, TAG, "checkPermissionForL2capChannelInfo")
                || !Utils.checkConnectPermissionForDataDelivery(
                service, source,
                "BluetoothSocketManagerBinder checkPermissionForL2capChannelInfo")) {
            return false;
        }
        Utils.enforceBluetoothPrivilegedPermission(service);
        return true;
    }

    private void enforceActiveUser() {
    private void enforceActiveUser() {
        if (!Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG)) {
        if (!Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG)) {
            throw new SecurityException("Not allowed for non-active user");
            throw new SecurityException("Not allowed for non-active user");
+5 −0
Original line number Original line Diff line number Diff line
@@ -1011,6 +1011,11 @@ package android.bluetooth {
    method @NonNull public android.bluetooth.BluetoothSinkAudioPolicy.Builder setInBandRingtonePolicy(int);
    method @NonNull public android.bluetooth.BluetoothSinkAudioPolicy.Builder setInBandRingtonePolicy(int);
  }
  }


  public final class BluetoothSocket implements java.io.Closeable {
    method @FlaggedApi("com.android.bluetooth.flags.bt_socket_api_l2cap_cid") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getL2capLocalChannelId() throws java.io.IOException;
    method @FlaggedApi("com.android.bluetooth.flags.bt_socket_api_l2cap_cid") @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getL2capRemoteChannelId() throws java.io.IOException;
  }

  public final class BluetoothStatusCodes {
  public final class BluetoothStatusCodes {
    field public static final int ALLOWED = 400; // 0x190
    field public static final int ALLOWED = 400; // 0x190
    field public static final int ERROR_ALREADY_IN_TARGET_STATE = 26; // 0x1a
    field public static final int ERROR_ALREADY_IN_TARGET_STATE = 26; // 0x1a
+101 −2
Original line number Original line Diff line number Diff line
@@ -16,10 +16,13 @@


package android.bluetooth;
package android.bluetooth;


import android.annotation.FlaggedApi;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AttributionSource;
import android.net.LocalSocket;
import android.net.LocalSocket;
import android.os.Build;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
@@ -27,6 +30,8 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;


import com.android.bluetooth.flags.Flags;

import java.io.Closeable;
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.IOException;
@@ -151,11 +156,13 @@ public final class BluetoothSocket implements Closeable {
    @UnsupportedAppUsage private int mPort; /* RFCOMM channel or L2CAP psm */
    @UnsupportedAppUsage private int mPort; /* RFCOMM channel or L2CAP psm */
    private String mServiceName;
    private String mServiceName;


    private static final int SOCK_SIGNAL_SIZE = 20;
    private static final int SOCK_SIGNAL_SIZE = 24;


    private ByteBuffer mL2capBuffer = null;
    private ByteBuffer mL2capBuffer = null;
    private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer.
    private int mMaxTxPacketSize = 0; // The l2cap maximum packet size supported by the peer.
    private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received.
    private int mMaxRxPacketSize = 0; // The l2cap maximum packet size that can be received.
    private int mL2capLocalCid = 0;
    private int mL2capRemoteCid = 0;


    private long mSocketCreationTimeNanos = 0;
    private long mSocketCreationTimeNanos = 0;
    private long mSocketCreationLatencyNanos = 0;
    private long mSocketCreationLatencyNanos = 0;
@@ -292,6 +299,8 @@ public final class BluetoothSocket implements Closeable {
        mOutputStream = new BluetoothOutputStream(this);
        mOutputStream = new BluetoothOutputStream(this);
        mMaxRxPacketSize = s.mMaxRxPacketSize;
        mMaxRxPacketSize = s.mMaxRxPacketSize;
        mMaxTxPacketSize = s.mMaxTxPacketSize;
        mMaxTxPacketSize = s.mMaxTxPacketSize;
        mL2capLocalCid = s.mL2capLocalCid;
        mL2capRemoteCid = s.mL2capRemoteCid;


        mServiceName = s.mServiceName;
        mServiceName = s.mServiceName;
        mExcludeSdp = s.mExcludeSdp;
        mExcludeSdp = s.mExcludeSdp;
@@ -832,6 +841,90 @@ public final class BluetoothSocket implements Closeable {
        }
        }
    }
    }


    /**
     * Returns the L2CAP local channel ID associated with an open connection to this socket.
     *
     * @return the L2CAP local channel ID.
     * @throws BluetoothSocketException in case of failure, with the corresponding error code.
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_BT_SOCKET_API_L2CAP_CID)
    @RequiresPermission(
            allOf = {
                android.Manifest.permission.BLUETOOTH_CONNECT,
                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
            })
    public int getL2capLocalChannelId() throws IOException {
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            throw new BluetoothSocketException(BluetoothSocketException.BLUETOOTH_OFF_FAILURE);
        }
        try {
            IBluetoothSocketManager socketManager = bluetoothProxy.getSocketManager();
            if (socketManager == null) {
                throw new BluetoothSocketException(BluetoothSocketException.SOCKET_MANAGER_FAILURE);
            }
            if (!socketManager.checkPermissionForL2capChannelInfo(
                    AttributionSource.myAttributionSource())) {
                throw new SecurityException(
                    "Need BLUETOOTH_CONNECT and BLUETOOTH_PRIVILEGED Permission");
            }
        } catch (RemoteException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            throw new IOException("unable to send RPC: " + e.getMessage());
        }
        if (mType != TYPE_L2CAP_LE) {
            throw new BluetoothSocketException(BluetoothSocketException.L2CAP_UNKNOWN);
        }
        if (mSocketState != SocketState.CONNECTED) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        return mL2capLocalCid;
    }

    /**
     * Returns the L2CAP remote channel ID associated with an open connection to this socket.
     *
     * @return the L2CAP remote channel ID.
     * @throws BluetoothSocketException in case of failure, with the corresponding error code.
     * @hide
     */
    @SystemApi
    @FlaggedApi(Flags.FLAG_BT_SOCKET_API_L2CAP_CID)
    @RequiresPermission(
            allOf = {
                android.Manifest.permission.BLUETOOTH_CONNECT,
                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
            })
    public int getL2capRemoteChannelId() throws IOException {
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            throw new BluetoothSocketException(BluetoothSocketException.BLUETOOTH_OFF_FAILURE);
        }
        try {
            IBluetoothSocketManager socketManager = bluetoothProxy.getSocketManager();
            if (socketManager == null) {
                throw new BluetoothSocketException(BluetoothSocketException.SOCKET_MANAGER_FAILURE);
            }
            if (!socketManager.checkPermissionForL2capChannelInfo(
                    AttributionSource.myAttributionSource())) {
                throw new SecurityException(
                    "Need BLUETOOTH_CONNECT and BLUETOOTH_PRIVILEGED Permission");
            }
        } catch (RemoteException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            throw new IOException("unable to send RPC: " + e.getMessage());
        }
        if (mType != TYPE_L2CAP_LE) {
            throw new BluetoothSocketException(BluetoothSocketException.L2CAP_UNKNOWN);
        }
        if (mSocketState != SocketState.CONNECTED) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        return mL2capRemoteCid;
    }

    /** @hide */
    /** @hide */
    public ParcelFileDescriptor getParcelFileDescriptor() {
    public ParcelFileDescriptor getParcelFileDescriptor() {
        return mPfd;
        return mPfd;
@@ -868,6 +961,8 @@ public final class BluetoothSocket implements Closeable {
        int status = bb.getInt();
        int status = bb.getInt();
        mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
        mMaxTxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
        mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
        mMaxRxPacketSize = (bb.getShort() & 0xffff); // Convert to unsigned value
        mL2capLocalCid = (bb.getShort() & 0xffff); // Convert to unsigned value
        mL2capRemoteCid = (bb.getShort() & 0xffff); // Convert to unsigned value
        String RemoteAddr = convertAddr(addr);
        String RemoteAddr = convertAddr(addr);
        if (VDBG) {
        if (VDBG) {
            Log.d(
            Log.d(
@@ -883,7 +978,11 @@ public final class BluetoothSocket implements Closeable {
                            + " MaxRxPktSize: "
                            + " MaxRxPktSize: "
                            + mMaxRxPacketSize
                            + mMaxRxPacketSize
                            + " MaxTxPktSize: "
                            + " MaxTxPktSize: "
                            + mMaxTxPacketSize);
                            + mMaxTxPacketSize
                            + " mL2capLocalCid: "
                            + String.format("0x%04x", mL2capLocalCid)
                            + " mL2capRemoteCid: "
                            + String.format("0x%04x", mL2capRemoteCid));
        }
        }
        if (status != 0) {
        if (status != 0) {
            throw new IOException("Connection failure, status: " + status);
            throw new IOException("Connection failure, status: " + status);
+2 −0
Original line number Original line Diff line number Diff line
@@ -216,6 +216,8 @@ typedef struct {
  uint32_t handle;       /* The connection handle */
  uint32_t handle;       /* The connection handle */
  RawAddress rem_bda;    /* The peer address */
  RawAddress rem_bda;    /* The peer address */
  int32_t tx_mtu;        /* The transmit MTU */
  int32_t tx_mtu;        /* The transmit MTU */
  uint16_t local_cid;    /* The local CID */
  uint16_t remote_cid;   /* The remote CID */
} tBTA_JV_L2CAP_OPEN;
} tBTA_JV_L2CAP_OPEN;


/* data associated with BTA_JV_L2CAP_OPEN_EVT for LE sockets */
/* data associated with BTA_JV_L2CAP_OPEN_EVT for LE sockets */
Loading