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

Commit c944445c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "bluetooth_irk_api" into sc-dev

* changes:
  IRK: Pipe IRK through to host stack
  Check for null address before doing permission requirements check
  Allow null scan filters as some existing use cases require them.
  Revert "Revert "Enforce BluetoothPrivileged Permission for ScanFilter APIs""
parents f853461b b0edab38
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -1489,6 +1489,7 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object,
  jfieldID addressFid =
      env->GetFieldID(entryClazz, "address", "Ljava/lang/String;");
  jfieldID addrTypeFid = env->GetFieldID(entryClazz, "addr_type", "B");
  jfieldID irkTypeFid = env->GetFieldID(entryClazz, "irk", "[B");
  jfieldID uuidFid = env->GetFieldID(entryClazz, "uuid", "Ljava/util/UUID;");
  jfieldID uuidMaskFid =
      env->GetFieldID(entryClazz, "uuid_mask", "Ljava/util/UUID;");
@@ -1514,6 +1515,30 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object,

    curr.addr_type = env->GetByteField(current.get(), addrTypeFid);

    // Zero out Apcf IRK, maybe set later if one was passed
    int j;
    for (j = 0; j < 16; j++) {
      curr.irk[j] = 0;
    }

    ScopedLocalRef<jbyteArray> irkByteArray(
        env, (jbyteArray)env->GetObjectField(current.get(), irkTypeFid));

    if (irkByteArray.get() != nullptr) {
      int len = env->GetArrayLength(irkByteArray.get());
      // IRK is 128 bits or 16 octets, set the bytes or zero it out
      if (len != 16) {
        ALOGE("%s: Invalid IRK length '%d'; expected 16", __func__, len);
        jniThrowIOException(env, EINVAL);
      }
      jbyte* irkBytes = env->GetByteArrayElements(irkByteArray.get(), NULL);
      if (irkBytes != NULL) {
        for (int j = 0; j < len; j++) {
          curr.irk[i] = irkBytes[i];
        }
      }
    }

    ScopedLocalRef<jobject> uuid(env,
                                 env->GetObjectField(current.get(), uuidFid));
    if (uuid.get() != NULL) {
+35 −1
Original line number Diff line number Diff line
@@ -2270,6 +2270,7 @@ public class GattService extends ProfileService {
        enforcePrivilegedPermissionIfNeeded(settings);
        String callingPackage = attributionSource.getPackageName();
        settings = enforceReportDelayFloor(settings);
        enforcePrivilegedPermissionIfNeeded(filters);
        final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages);
        scanClient.userHandle = UserHandle.of(UserHandle.getCallingUserId());
        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
@@ -2326,7 +2327,7 @@ public class GattService extends ProfileService {
        }
        enforcePrivilegedPermissionIfNeeded(settings);
        settings = enforceReportDelayFloor(settings);

        enforcePrivilegedPermissionIfNeeded(filters);
        UUID uuid = UUID.randomUUID();
        if (DBG) {
            Log.d(TAG, "startScan(PI) - UUID=" + uuid);
@@ -3673,6 +3674,39 @@ public class GattService extends ProfileService {
        return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
    }

    /*
     * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods.  This
     * requires that the permissions be BLUETOOTH_PRIVILEGED.
     */
    @SuppressLint("AndroidFrameworkRequiresPermission")
    private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) {
        if (DBG) {
            Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")");
        }
        // Some 3p API cases may have null filters, need to allow
        if (filters != null) {
            for (ScanFilter filter : filters) {
                // The only case to enforce here is if there is an address
                // If there is an address, enforce if the correct combination criteria is met.
                if (filter.getDeviceAddress() != null) {
                    // At this point we have an address, that means a caller used the
                    // setDeviceAddress(address) public API for the ScanFilter
                    // We don't want to enforce if the type is PUBLIC and the IRK is null
                    // However, if we have a different type that means the caller used a new
                    // @SystemApi such as setDeviceAddress(address, type) or
                    // setDeviceAddress(address, type, irk) which are both @SystemApi and require
                    // permissions to be enforced
                    if (filter.getAddressType()
                            == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) {
                        // Do not enforce
                    } else {
                        enforcePrivilegedPermission();
                    }
                }
            }
        }
    }

    // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be
    // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission.
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+10 −2
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.util.UUID;
        public byte type;
        public String address;
        public byte addr_type;
        public byte[] irk;
        public UUID uuid;
        public UUID uuid_mask;
        public String name;
@@ -61,11 +62,12 @@ import java.util.UUID;

    private Set<Entry> mEntries = new HashSet<Entry>();

    void addDeviceAddress(String address, byte type) {
    void addDeviceAddress(String address, byte type, byte[] irk) {
        Entry entry = new Entry();
        entry.type = TYPE_DEVICE_ADDRESS;
        entry.address = address;
        entry.addr_type = type;
        entry.irk = irk;
        mEntries.add(entry);
    }

@@ -179,7 +181,13 @@ import java.util.UUID;
            addName(filter.getDeviceName());
        }
        if (filter.getDeviceAddress() != null) {
            addDeviceAddress(filter.getDeviceAddress(), DEVICE_TYPE_ALL);
            byte addressType = (byte) filter.getAddressType();
            // If addressType == iADDRESS_TYPE_PUBLIC (0) then this is the original
            // setDeviceAddress(address) API path which provided DEVICE_TYPE_ALL (2) which might map
            // to the stack value for address type of BTM_BLE_STATIC (2)
            // Additionally, we shouldn't confuse device type with address type.
            addDeviceAddress(filter.getDeviceAddress(),
                    ((addressType == 0) ? DEVICE_TYPE_ALL : addressType), filter.getIrk());
        }
        if (filter.getServiceUuid() != null) {
            if (filter.getServiceUuidMask() == null) {