Loading android/app/jni/com_android_bluetooth_gatt.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1771,6 +1771,9 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object, jfieldID adTypeFid = env->GetFieldID(entryClazz, "ad_type", "I"); jfieldID dataFid = env->GetFieldID(entryClazz, "data", "[B"); jfieldID dataMaskFid = env->GetFieldID(entryClazz, "data_mask", "[B"); jfieldID orgFid = env->GetFieldID(entryClazz, "org_id", "I"); jfieldID TDSFlagsFid = env->GetFieldID(entryClazz, "tds_flags", "I"); jfieldID TDSFlagsMaskFid = env->GetFieldID(entryClazz, "tds_flags_mask", "I"); for (int i = 0; i < numFilters; ++i) { ApcfCommand curr{}; Loading Loading @@ -1863,6 +1866,10 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object, env->ReleaseByteArrayElements(data_mask.get(), data_array, JNI_ABORT); } } curr.org_id = env->GetIntField(current.get(), orgFid); curr.tds_flags = env->GetIntField(current.get(), TDSFlagsFid); curr.tds_flags_mask = env->GetIntField(current.get(), TDSFlagsMaskFid); native_filters.push_back(curr); } Loading android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +13 −1 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ class AdapterProperties { private boolean mIsLeExtendedAdvertisingSupported; private boolean mIsLePeriodicAdvertisingSupported; private int mLeMaximumAdvertisingDataLength; private boolean mIsOffloadedTransportDiscoveryDataScanSupported; private int mIsDynamicAudioBufferSizeSupported; private int mDynamicAudioBufferSizeSupportedCodecsGroup1; Loading Loading @@ -579,6 +580,14 @@ class AdapterProperties { return mTotNumOfTrackableAdv; } /** * @return the isOffloadedTransportDiscoveryDataScanSupported */ public boolean isOffloadedTransportDiscoveryDataScanSupported() { return mIsOffloadedTransportDiscoveryDataScanSupported; } /** * @return the maximum number of connected audio devices */ Loading Loading @@ -1081,6 +1090,7 @@ class AdapterProperties { mIsLeConnectedIsochronousStreamCentralSupported = ((0xFF & ((int) val[25])) != 0); mIsLeIsochronousBroadcasterSupported = ((0xFF & ((int) val[26])) != 0); mIsLePeriodicAdvertisingSyncTransferRecipientSupported = ((0xFF & ((int) val[27])) != 0); mIsOffloadedTransportDiscoveryDataScanSupported = ((0x01 & ((int) val[28])) != 0); Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller" + " mNumOfAdvertisementInstancesSupported = " Loading Loading @@ -1108,7 +1118,9 @@ class AdapterProperties { + " mIsLeIsochronousBroadcasterSupported = " + mIsLeIsochronousBroadcasterSupported + " mIsLePeriodicAdvertisingSyncTransferRecipientSupported = " + mIsLePeriodicAdvertisingSyncTransferRecipientSupported); + mIsLePeriodicAdvertisingSyncTransferRecipientSupported + " mIsOffloadedTransportDiscoveryDataScanSupported = " + mIsOffloadedTransportDiscoveryDataScanSupported); invalidateIsOffloadedFilteringSupportedCache(); } Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +39 −0 Original line number Diff line number Diff line Loading @@ -4525,6 +4525,7 @@ public class AdapterService extends Service { receiver.propagateException(e); } } @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, Loading Loading @@ -4587,6 +4588,33 @@ public class AdapterService extends Service { } return BluetoothStatusCodes.SUCCESS; } @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) @Override public void isOffloadedTransportDiscoveryDataScanSupported( AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(isOffloadedTransportDiscoveryDataScanSupported(source)); } catch (RuntimeException e) { receiver.propagateException(e); } } private int isOffloadedTransportDiscoveryDataScanSupported( AttributionSource attributionSource) { AdapterService service = getService(); if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isOffloadedTransportDiscoveryDataScanSupported") || !Utils.checkScanPermissionForDataDelivery( service, attributionSource, "isOffloadedTransportDiscoveryDataScanSupported")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; } enforceBluetoothPrivilegedPermission(service); return service.isOffloadedTransportDiscoveryDataScanSupported(); } } /** Loading Loading @@ -5809,6 +5837,17 @@ public class AdapterService extends Service { return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); } /** * Return if offloaded TDS filter is supported. * @return true if supported */ public int isOffloadedTransportDiscoveryDataScanSupported() { if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) { return BluetoothStatusCodes.FEATURE_SUPPORTED; } return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; } /** * Notify the UID and package name of the app, and the address of associated active device * Loading android/app/src/com/android/bluetooth/gatt/ScanFilterQueue.java +33 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.bluetooth.gatt; import android.bluetooth.BluetoothAssignedNumbers.OrganizationId; import android.bluetooth.BluetoothUuid; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.TransportBlockFilter; import android.os.ParcelUuid; import java.util.Arrays; Loading @@ -39,6 +41,7 @@ import java.util.UUID; public static final int TYPE_LOCAL_NAME = 4; public static final int TYPE_MANUFACTURER_DATA = 5; public static final int TYPE_SERVICE_DATA = 6; public static final int TYPE_TRANSPORT_DISCOVERY_DATA = 7; public static final int TYPE_ADVERTISING_DATA_TYPE = 8; // Max length is 31 - 3(flags) - 2 (one byte for length and one byte for type). Loading @@ -60,6 +63,9 @@ import java.util.UUID; public int ad_type; public byte[] data; public byte[] data_mask; public int org_id; public int tds_flags; public int tds_flags_mask; } private Set<Entry> mEntries = new HashSet<Entry>(); Loading Loading @@ -147,6 +153,18 @@ import java.util.UUID; mEntries.add(entry); } void addTransportDiscoveryData(int orgId, int tdsFlags, int tdsFlagsMask, byte[] transportData, byte[] transportDataMask) { Entry entry = new Entry(); entry.type = TYPE_TRANSPORT_DISCOVERY_DATA; entry.org_id = orgId; entry.tds_flags = tdsFlags; entry.tds_flags_mask = tdsFlagsMask; entry.data = transportData; entry.data_mask = transportDataMask; mEntries.add(entry); } void addAdvertisingDataType(int adType, byte[] data, byte[] dataMask) { Entry entry = new Entry(); entry.type = TYPE_ADVERTISING_DATA_TYPE; Loading Loading @@ -241,6 +259,21 @@ import java.util.UUID; addAdvertisingDataType(filter.getAdvertisingDataType(), filter.getAdvertisingData(), filter.getAdvertisingDataMask()); } final TransportBlockFilter transportBlockFilter = filter.getTransportBlockFilter(); if (transportBlockFilter != null) { if (transportBlockFilter.getOrgId() == OrganizationId.WIFI_ALLIANCE_NEIGHBOR_AWARENESS_NETWORKING) { addTransportDiscoveryData(transportBlockFilter.getOrgId(), transportBlockFilter.getTdsFlags(), transportBlockFilter.getTdsFlagsMask(), transportBlockFilter.getWifiNanHash(), null); } else { addTransportDiscoveryData(transportBlockFilter.getOrgId(), transportBlockFilter.getTdsFlags(), transportBlockFilter.getTdsFlagsMask(), transportBlockFilter.getTransportData(), transportBlockFilter.getTransportDataMask()); } } } private byte[] concate(ParcelUuid serviceDataUuid, byte[] serviceData) { Loading android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.bluetooth.le.ScanSettings.SCAN_MODE_SCREEN_OFF_BALANCED; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.anyString; Loading @@ -40,9 +41,13 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.bluetooth.le.TransportDiscoveryData; import android.content.Context; import android.location.LocationManager; import android.os.Binder; Loading @@ -61,6 +66,7 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.btservice.MetricsLogger; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.List; Loading Loading
android/app/jni/com_android_bluetooth_gatt.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1771,6 +1771,9 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object, jfieldID adTypeFid = env->GetFieldID(entryClazz, "ad_type", "I"); jfieldID dataFid = env->GetFieldID(entryClazz, "data", "[B"); jfieldID dataMaskFid = env->GetFieldID(entryClazz, "data_mask", "[B"); jfieldID orgFid = env->GetFieldID(entryClazz, "org_id", "I"); jfieldID TDSFlagsFid = env->GetFieldID(entryClazz, "tds_flags", "I"); jfieldID TDSFlagsMaskFid = env->GetFieldID(entryClazz, "tds_flags_mask", "I"); for (int i = 0; i < numFilters; ++i) { ApcfCommand curr{}; Loading Loading @@ -1863,6 +1866,10 @@ static void gattClientScanFilterAddNative(JNIEnv* env, jobject object, env->ReleaseByteArrayElements(data_mask.get(), data_array, JNI_ABORT); } } curr.org_id = env->GetIntField(current.get(), orgFid); curr.tds_flags = env->GetIntField(current.get(), TDSFlagsFid); curr.tds_flags_mask = env->GetIntField(current.get(), TDSFlagsMaskFid); native_filters.push_back(curr); } Loading
android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +13 −1 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ class AdapterProperties { private boolean mIsLeExtendedAdvertisingSupported; private boolean mIsLePeriodicAdvertisingSupported; private int mLeMaximumAdvertisingDataLength; private boolean mIsOffloadedTransportDiscoveryDataScanSupported; private int mIsDynamicAudioBufferSizeSupported; private int mDynamicAudioBufferSizeSupportedCodecsGroup1; Loading Loading @@ -579,6 +580,14 @@ class AdapterProperties { return mTotNumOfTrackableAdv; } /** * @return the isOffloadedTransportDiscoveryDataScanSupported */ public boolean isOffloadedTransportDiscoveryDataScanSupported() { return mIsOffloadedTransportDiscoveryDataScanSupported; } /** * @return the maximum number of connected audio devices */ Loading Loading @@ -1081,6 +1090,7 @@ class AdapterProperties { mIsLeConnectedIsochronousStreamCentralSupported = ((0xFF & ((int) val[25])) != 0); mIsLeIsochronousBroadcasterSupported = ((0xFF & ((int) val[26])) != 0); mIsLePeriodicAdvertisingSyncTransferRecipientSupported = ((0xFF & ((int) val[27])) != 0); mIsOffloadedTransportDiscoveryDataScanSupported = ((0x01 & ((int) val[28])) != 0); Log.d(TAG, "BT_PROPERTY_LOCAL_LE_FEATURES: update from BT controller" + " mNumOfAdvertisementInstancesSupported = " Loading Loading @@ -1108,7 +1118,9 @@ class AdapterProperties { + " mIsLeIsochronousBroadcasterSupported = " + mIsLeIsochronousBroadcasterSupported + " mIsLePeriodicAdvertisingSyncTransferRecipientSupported = " + mIsLePeriodicAdvertisingSyncTransferRecipientSupported); + mIsLePeriodicAdvertisingSyncTransferRecipientSupported + " mIsOffloadedTransportDiscoveryDataScanSupported = " + mIsOffloadedTransportDiscoveryDataScanSupported); invalidateIsOffloadedFilteringSupportedCache(); } Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +39 −0 Original line number Diff line number Diff line Loading @@ -4525,6 +4525,7 @@ public class AdapterService extends Service { receiver.propagateException(e); } } @RequiresPermission(allOf = { android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, Loading Loading @@ -4587,6 +4588,33 @@ public class AdapterService extends Service { } return BluetoothStatusCodes.SUCCESS; } @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) @Override public void isOffloadedTransportDiscoveryDataScanSupported( AttributionSource source, SynchronousResultReceiver receiver) { try { receiver.send(isOffloadedTransportDiscoveryDataScanSupported(source)); } catch (RuntimeException e) { receiver.propagateException(e); } } private int isOffloadedTransportDiscoveryDataScanSupported( AttributionSource attributionSource) { AdapterService service = getService(); if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isOffloadedTransportDiscoveryDataScanSupported") || !Utils.checkScanPermissionForDataDelivery( service, attributionSource, "isOffloadedTransportDiscoveryDataScanSupported")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; } enforceBluetoothPrivilegedPermission(service); return service.isOffloadedTransportDiscoveryDataScanSupported(); } } /** Loading Loading @@ -5809,6 +5837,17 @@ public class AdapterService extends Service { return mAdapterProperties.getTotalNumOfTrackableAdvertisements(); } /** * Return if offloaded TDS filter is supported. * @return true if supported */ public int isOffloadedTransportDiscoveryDataScanSupported() { if (mAdapterProperties.isOffloadedTransportDiscoveryDataScanSupported()) { return BluetoothStatusCodes.FEATURE_SUPPORTED; } return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; } /** * Notify the UID and package name of the app, and the address of associated active device * Loading
android/app/src/com/android/bluetooth/gatt/ScanFilterQueue.java +33 −0 Original line number Diff line number Diff line Loading @@ -16,8 +16,10 @@ package com.android.bluetooth.gatt; import android.bluetooth.BluetoothAssignedNumbers.OrganizationId; import android.bluetooth.BluetoothUuid; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.TransportBlockFilter; import android.os.ParcelUuid; import java.util.Arrays; Loading @@ -39,6 +41,7 @@ import java.util.UUID; public static final int TYPE_LOCAL_NAME = 4; public static final int TYPE_MANUFACTURER_DATA = 5; public static final int TYPE_SERVICE_DATA = 6; public static final int TYPE_TRANSPORT_DISCOVERY_DATA = 7; public static final int TYPE_ADVERTISING_DATA_TYPE = 8; // Max length is 31 - 3(flags) - 2 (one byte for length and one byte for type). Loading @@ -60,6 +63,9 @@ import java.util.UUID; public int ad_type; public byte[] data; public byte[] data_mask; public int org_id; public int tds_flags; public int tds_flags_mask; } private Set<Entry> mEntries = new HashSet<Entry>(); Loading Loading @@ -147,6 +153,18 @@ import java.util.UUID; mEntries.add(entry); } void addTransportDiscoveryData(int orgId, int tdsFlags, int tdsFlagsMask, byte[] transportData, byte[] transportDataMask) { Entry entry = new Entry(); entry.type = TYPE_TRANSPORT_DISCOVERY_DATA; entry.org_id = orgId; entry.tds_flags = tdsFlags; entry.tds_flags_mask = tdsFlagsMask; entry.data = transportData; entry.data_mask = transportDataMask; mEntries.add(entry); } void addAdvertisingDataType(int adType, byte[] data, byte[] dataMask) { Entry entry = new Entry(); entry.type = TYPE_ADVERTISING_DATA_TYPE; Loading Loading @@ -241,6 +259,21 @@ import java.util.UUID; addAdvertisingDataType(filter.getAdvertisingDataType(), filter.getAdvertisingData(), filter.getAdvertisingDataMask()); } final TransportBlockFilter transportBlockFilter = filter.getTransportBlockFilter(); if (transportBlockFilter != null) { if (transportBlockFilter.getOrgId() == OrganizationId.WIFI_ALLIANCE_NEIGHBOR_AWARENESS_NETWORKING) { addTransportDiscoveryData(transportBlockFilter.getOrgId(), transportBlockFilter.getTdsFlags(), transportBlockFilter.getTdsFlagsMask(), transportBlockFilter.getWifiNanHash(), null); } else { addTransportDiscoveryData(transportBlockFilter.getOrgId(), transportBlockFilter.getTdsFlags(), transportBlockFilter.getTdsFlagsMask(), transportBlockFilter.getTransportData(), transportBlockFilter.getTransportDataMask()); } } } private byte[] concate(ParcelUuid serviceDataUuid, byte[] serviceData) { Loading
android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java +6 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static android.bluetooth.le.ScanSettings.SCAN_MODE_SCREEN_OFF_BALANCED; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.anyString; Loading @@ -40,9 +41,13 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.bluetooth.le.TransportDiscoveryData; import android.content.Context; import android.location.LocationManager; import android.os.Binder; Loading @@ -61,6 +66,7 @@ import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.btservice.MetricsLogger; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; import java.util.List; Loading