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

Commit 815a8c9f authored by Jayden Kim's avatar Jayden Kim
Browse files

Update Socket API to get L2CAP channel ID through native stack

Test: m -j

Bug: 326256996
Bug: 326351678
Change-Id: Icdfa55450091ab136fa2cdd7a4c618247c2c3610
parent c8958243
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -34,5 +34,7 @@ interface IBluetoothSocketManager
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    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);
    int getL2capLocalChannelId(in ParcelUuid connectionUuid, in AttributionSource attributionSource);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    int getL2capRemoteChannelId(in ParcelUuid connectionUuid, in AttributionSource attributionSource);
}
+50 −0
Original line number Diff line number Diff line
@@ -48,6 +48,15 @@ struct formatter<bt_discovery_state_t> : enum_formatter<bt_discovery_state_t> {
};
}  // namespace fmt

static Uuid from_java_uuid(jlong uuid_msb, jlong uuid_lsb) {
  std::array<uint8_t, Uuid::kNumBytes128> uu;
  for (int i = 0; i < 8; i++) {
    uu[7 - i] = (uuid_msb >> (8 * i)) & 0xFF;
    uu[15 - i] = (uuid_lsb >> (8 * i)) & 0xFF;
  }
  return Uuid::From128BitBE(uu);
}

namespace android {
// Both

@@ -59,6 +68,7 @@ namespace android {
#define BLE_ADDR_RANDOM 0x01

const jint INVALID_FD = -1;
const jint INVALID_CID = -1;

static jmethodID method_oobDataReceivedCallback;
static jmethodID method_stateChangeCallback;
@@ -2139,6 +2149,42 @@ static jboolean pbapPseDynamicVersionUpgradeIsEnabledNative(JNIEnv* /* env */,
             : JNI_FALSE;
}

static jint getSocketL2capLocalChannelIdNative(JNIEnv* /* env */,
                                               jobject /* obj */,
                                               jlong conn_uuid_lsb,
                                               jlong conn_uuid_msb) {
  log::verbose("");

  if (!sBluetoothSocketInterface) {
    return INVALID_CID;
  }
  uint16_t cid;
  Uuid uuid = from_java_uuid(conn_uuid_msb, conn_uuid_lsb);
  if (sBluetoothSocketInterface->get_l2cap_local_cid(uuid, &cid) !=
      BT_STATUS_SUCCESS) {
    return INVALID_CID;
  }
  return (jint)cid;
}

static jint getSocketL2capRemoteChannelIdNative(JNIEnv* /* env */,
                                                jobject /* obj */,
                                                jlong conn_uuid_lsb,
                                                jlong conn_uuid_msb) {
  log::verbose("");

  if (!sBluetoothSocketInterface) {
    return INVALID_CID;
  }
  uint16_t cid;
  Uuid uuid = from_java_uuid(conn_uuid_msb, conn_uuid_lsb);
  if (sBluetoothSocketInterface->get_l2cap_remote_cid(uuid, &cid) !=
      BT_STATUS_SUCCESS) {
    return INVALID_CID;
  }
  return (jint)cid;
}

int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {
  const JNINativeMethod methods[] = {
      {"initNative", "(ZZI[Ljava/lang/String;ZLjava/lang/String;)Z",
@@ -2201,6 +2247,10 @@ int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {
       (void*)getRemotePbapPceVersionNative},
      {"pbapPseDynamicVersionUpgradeIsEnabledNative", "()Z",
       (void*)pbapPseDynamicVersionUpgradeIsEnabledNative},
      {"getSocketL2capLocalChannelIdNative", "(JJ)I",
       (void*)getSocketL2capLocalChannelIdNative},
      {"getSocketL2capRemoteChannelIdNative", "(JJ)I",
       (void*)getSocketL2capRemoteChannelIdNative},
  };
  const int result = REGISTER_NATIVE_METHODS(
      env, "com/android/bluetooth/btservice/AdapterNativeInterface", methods);
+19 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.bluetooth.btservice;

import android.bluetooth.OobData;
import android.os.ParcelUuid;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -246,6 +247,18 @@ public class AdapterNativeInterface {
        return isLogRedactionEnabledNative();
    }

    int getSocketL2capLocalChannelId(ParcelUuid connectionUuid) {
        return getSocketL2capLocalChannelIdNative(
                connectionUuid.getUuid().getLeastSignificantBits(),
                connectionUuid.getUuid().getMostSignificantBits());
    }

    int getSocketL2capRemoteChannelId(ParcelUuid connectionUuid) {
        return getSocketL2capRemoteChannelIdNative(
                connectionUuid.getUuid().getLeastSignificantBits(),
                connectionUuid.getUuid().getMostSignificantBits());
    }

    /**********************************************************************************************/
    /*********************************** callbacks from native ************************************/
    /**********************************************************************************************/
@@ -352,4 +365,10 @@ public class AdapterNativeInterface {
    private native boolean pbapPseDynamicVersionUpgradeIsEnabledNative();

    private native boolean isLogRedactionEnabledNative();

    private native int getSocketL2capLocalChannelIdNative(
            long connectionUuidLsb, long connectionUuidMsb);

    private native int getSocketL2capRemoteChannelIdNative(
            long connectionUuidLsb, long connectionUuidMsb);
}
+21 −6
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {

    private static final int INVALID_FD = -1;

    private static final int INVALID_CID = -1;

    private AdapterService mService;

    BluetoothSocketManagerBinder(AdapterService service) {
@@ -99,18 +101,31 @@ class BluetoothSocketManagerBinder extends IBluetoothSocketManager.Stub {
    }

    @Override
    public boolean checkPermissionForL2capChannelInfo(AttributionSource source) {
    public int getL2capLocalChannelId(ParcelUuid connectionUuid, AttributionSource source) {
        AdapterService service = mService;
        if (service == null
                || !Utils.callerIsSystemOrActiveOrManagedUser(
                        service, TAG, "getL2capLocalChannelId")
                || !Utils.checkConnectPermissionForDataDelivery(
                        service, source, "BluetoothSocketManagerBinder getL2capLocalChannelId")) {
            return INVALID_CID;
        }
        Utils.enforceBluetoothPrivilegedPermission(service);
        return service.getNative().getSocketL2capLocalChannelId(connectionUuid);
    }

    @Override
    public int getL2capRemoteChannelId(ParcelUuid connectionUuid, AttributionSource source) {
        AdapterService service = mService;
        if (service == null
                || !Utils.callerIsSystemOrActiveOrManagedUser(
                service, TAG, "checkPermissionForL2capChannelInfo")
                        service, TAG, "getL2capRemoteChannelId")
                || !Utils.checkConnectPermissionForDataDelivery(
                service, source,
                "BluetoothSocketManagerBinder checkPermissionForL2capChannelInfo")) {
            return false;
                        service, source, "BluetoothSocketManagerBinder getL2capRemoteChannelId")) {
            return INVALID_CID;
        }
        Utils.enforceBluetoothPrivilegedPermission(service);
        return true;
        return service.getNative().getSocketL2capRemoteChannelId(connectionUuid);
    }

    private void enforceActiveUser() {
+33 −31
Original line number Diff line number Diff line
@@ -156,13 +156,12 @@ public final class BluetoothSocket implements Closeable {
    @UnsupportedAppUsage private int mPort; /* RFCOMM channel or L2CAP psm */
    private String mServiceName;

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

    private ByteBuffer mL2capBuffer = null;
    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 mL2capLocalCid = 0;
    private int mL2capRemoteCid = 0;
    private ParcelUuid mConnectionUuid;

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

        mServiceName = s.mServiceName;
        mExcludeSdp = s.mExcludeSdp;
@@ -743,6 +741,7 @@ public final class BluetoothSocket implements Closeable {
                    mPfd.close();
                    mPfd = null;
                }
                mConnectionUuid = null;
            }
        }
    }
@@ -856,6 +855,13 @@ public final class BluetoothSocket implements Closeable {
                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
            })
    public int getL2capLocalChannelId() throws IOException {
        if (mType != TYPE_L2CAP_LE) {
            throw new BluetoothSocketException(BluetoothSocketException.L2CAP_UNKNOWN);
        }
        if (mSocketState != SocketState.CONNECTED || mConnectionUuid == null) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        int cid;
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            throw new BluetoothSocketException(BluetoothSocketException.BLUETOOTH_OFF_FAILURE);
@@ -865,22 +871,17 @@ public final class BluetoothSocket implements Closeable {
            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");
            }
            cid =
                    socketManager.getL2capLocalChannelId(
                            mConnectionUuid, AttributionSource.myAttributionSource());
        } 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) {
        if (cid == -1) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        return mL2capLocalCid;
        return cid;
    }

    /**
@@ -898,6 +899,13 @@ public final class BluetoothSocket implements Closeable {
                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
            })
    public int getL2capRemoteChannelId() throws IOException {
        if (mType != TYPE_L2CAP_LE) {
            throw new BluetoothSocketException(BluetoothSocketException.L2CAP_UNKNOWN);
        }
        if (mSocketState != SocketState.CONNECTED || mConnectionUuid == null) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        int cid;
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            throw new BluetoothSocketException(BluetoothSocketException.BLUETOOTH_OFF_FAILURE);
@@ -907,22 +915,17 @@ public final class BluetoothSocket implements Closeable {
            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");
            }
            cid =
                    socketManager.getL2capRemoteChannelId(
                            mConnectionUuid, AttributionSource.myAttributionSource());
        } 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) {
        if (cid == -1) {
            throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
        }
        return mL2capRemoteCid;
        return cid;
    }

    /** @hide */
@@ -961,8 +964,9 @@ public final class BluetoothSocket implements Closeable {
        int status = bb.getInt();
        mMaxTxPacketSize = (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
        long uuidLsb = bb.getLong();
        long uuidMsb = bb.getLong();
        mConnectionUuid = new ParcelUuid(new UUID(uuidMsb, uuidLsb));
        String RemoteAddr = convertAddr(addr);
        if (VDBG) {
            Log.d(
@@ -979,10 +983,8 @@ public final class BluetoothSocket implements Closeable {
                            + mMaxRxPacketSize
                            + " MaxTxPktSize: "
                            + mMaxTxPacketSize
                            + " mL2capLocalCid: "
                            + String.format("0x%04x", mL2capLocalCid)
                            + " mL2capRemoteCid: "
                            + String.format("0x%04x", mL2capRemoteCid));
                            + " mConnectionUuid: "
                            + mConnectionUuid.toString());
        }
        if (status != 0) {
            throw new IOException("Connection failure, status: " + status);
Loading