unified-ble-manager 4.0.4 → 4.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -1
- package/MIGRATION_4.0.md +1 -1
- package/README.md +1 -1
- package/RELEASE.md +24 -16
- package/SBOM.cdx.json +29 -5
- package/THIRD_PARTY_LICENSES.json +9 -2
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/expo/UnifiedBleExpoRuntimeModule.java +18 -2
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidDispatcher.kt +15 -8
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/protocol/generated/NativeProtocolV2Schema.kt +2 -1
- package/android/src/main/java/com/sfourdrinier/unifiedblemanager/radio/OwnedAndroidGattRadio.kt +30 -3
- package/android/src/main/jni/UnifiedBleProtocolJsiBinding.cpp +66 -0
- package/android/src/test/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidFindingsTest.kt +17 -0
- package/docs/ADR/2026-07-4.0-backend-contract.md +16 -4
- package/docs/BONDING.md +42 -7
- package/docs/ELECTRON.md +1 -1
- package/docs/EXPO_PLUGIN.md +2 -2
- package/docs/GAPS.4.0.md +1 -1
- package/docs/GETTING_STARTED.md +4 -4
- package/docs/NODE.md +2 -2
- package/docs/PLATFORMS.md +1 -1
- package/docs/UNIFIED_SEMANTICS.md +40 -5
- package/docs/WEB.md +1 -1
- package/docs/generated/PLATFORM_SUPPORT.md +1 -1
- package/ios/Generated/NativeProtocolV2Schema.swift +2 -1
- package/lib/commonjs/backend-contract/advertisement.js +19 -0
- package/lib/commonjs/backend-contract/advertisement.js.map +1 -1
- package/lib/commonjs/backend-contract/backend.js +6 -0
- package/lib/commonjs/backend-contract/backend.js.map +1 -1
- package/lib/commonjs/backend-contract/capabilities.js +7 -0
- package/lib/commonjs/backend-contract/capabilities.js.map +1 -1
- package/lib/commonjs/backend-contract/ipc.js +7 -0
- package/lib/commonjs/backend-contract/ipc.js.map +1 -1
- package/lib/commonjs/backend-contract/primitives.js +14 -0
- package/lib/commonjs/backend-contract/primitives.js.map +1 -1
- package/lib/commonjs/backend-contract/scan-planning.js +18 -2
- package/lib/commonjs/backend-contract/scan-planning.js.map +1 -1
- package/lib/commonjs/backend-contract/scan-query.js +18 -3
- package/lib/commonjs/backend-contract/scan-query.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend-handles.js +62 -30
- package/lib/commonjs/backends/bluez/bluez-backend-handles.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend-provider.js +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend-provider.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend-runtime.js +33 -1
- package/lib/commonjs/backends/bluez/bluez-backend-runtime.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-backend.js +9 -1
- package/lib/commonjs/backends/bluez/bluez-backend.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-connection-capabilities.js +110 -0
- package/lib/commonjs/backends/bluez/bluez-connection-capabilities.js.map +1 -0
- package/lib/commonjs/backends/bluez/bluez-connection-runtime.js +164 -2
- package/lib/commonjs/backends/bluez/bluez-connection-runtime.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-dbus-next-boundary.js +200 -3
- package/lib/commonjs/backends/bluez/bluez-dbus-next-boundary.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-operation-dispatcher.js +30 -20
- package/lib/commonjs/backends/bluez/bluez-operation-dispatcher.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-property-waiters.js +55 -1
- package/lib/commonjs/backends/bluez/bluez-property-waiters.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-runtime-models.js +7 -6
- package/lib/commonjs/backends/bluez/bluez-runtime-models.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-scan-planner.js +1 -1
- package/lib/commonjs/backends/bluez/bluez-scan-planner.js.map +1 -1
- package/lib/commonjs/backends/bluez/bluez-security.js +69 -2
- package/lib/commonjs/backends/bluez/bluez-security.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-adapter-loss-cleanup.js +4 -4
- package/lib/commonjs/backends/corebluetooth/corebluetooth-adapter-loss-cleanup.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-backend.js +95 -56
- package/lib/commonjs/backends/corebluetooth/corebluetooth-backend.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-cleanup.js +10 -2
- package/lib/commonjs/backends/corebluetooth/corebluetooth-cleanup.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-connection-controls.js +65 -53
- package/lib/commonjs/backends/corebluetooth/corebluetooth-connection-controls.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-gatt-operations.js +48 -48
- package/lib/commonjs/backends/corebluetooth/corebluetooth-gatt-operations.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-handles.js +12 -12
- package/lib/commonjs/backends/corebluetooth/corebluetooth-handles.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-late-connect-cleanup.js +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-late-connect-cleanup.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-provider.js +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-provider.js.map +1 -1
- package/lib/commonjs/backends/corebluetooth/corebluetooth-runtime-capabilities.js +3 -3
- package/lib/commonjs/backends/corebluetooth/corebluetooth-runtime-capabilities.js.map +1 -1
- package/lib/commonjs/backends/reactnative/react-native-android-provider.js +26 -2
- package/lib/commonjs/backends/reactnative/react-native-android-provider.js.map +1 -1
- package/lib/commonjs/backends/reactnative/react-native-android-security.js +15 -1
- package/lib/commonjs/backends/reactnative/react-native-android-security.js.map +1 -1
- package/lib/commonjs/backends/reactnative/react-native-restoration.js +8 -0
- package/lib/commonjs/backends/reactnative/react-native-restoration.js.map +1 -1
- package/lib/commonjs/backends/reactnative/react-native-scan-planner.js +2 -1
- package/lib/commonjs/backends/reactnative/react-native-scan-planner.js.map +1 -1
- package/lib/commonjs/backends/scan-planning/service-uuid-scan-planner.js +36 -4
- package/lib/commonjs/backends/scan-planning/service-uuid-scan-planner.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-backend-helpers.js +9 -0
- package/lib/commonjs/backends/winrt/winrt-backend-helpers.js.map +1 -1
- package/lib/commonjs/backends/winrt/winrt-security.js +7 -0
- package/lib/commonjs/backends/winrt/winrt-security.js.map +1 -1
- package/lib/commonjs/cli-json.js +7 -0
- package/lib/commonjs/cli-json.js.map +1 -1
- package/lib/commonjs/core/core-characteristic-operations.js +13 -0
- package/lib/commonjs/core/core-characteristic-operations.js.map +1 -1
- package/lib/commonjs/core/core-gatt-handles.js +10 -0
- package/lib/commonjs/core/core-gatt-handles.js.map +1 -1
- package/lib/commonjs/core/operation-coordinator.js +10 -1
- package/lib/commonjs/core/operation-coordinator.js.map +1 -1
- package/lib/commonjs/core/unified-ble-core.js +21 -0
- package/lib/commonjs/core/unified-ble-core.js.map +1 -1
- package/lib/commonjs/diagnostics/trace-format.js +12 -0
- package/lib/commonjs/diagnostics/trace-format.js.map +1 -1
- package/lib/commonjs/electron/connection-event-stream-registry.js +8 -0
- package/lib/commonjs/electron/connection-event-stream-registry.js.map +1 -1
- package/lib/commonjs/electron/main-binding.js +16 -0
- package/lib/commonjs/electron/main-binding.js.map +1 -1
- package/lib/commonjs/electron/main-router.js +11 -0
- package/lib/commonjs/electron/main-router.js.map +1 -1
- package/lib/commonjs/electron/renderer-stream-registry.js +8 -0
- package/lib/commonjs/electron/renderer-stream-registry.js.map +1 -1
- package/lib/commonjs/electron/renderer.js +11 -0
- package/lib/commonjs/electron/renderer.js.map +1 -1
- package/lib/commonjs/expo.js +37 -1
- package/lib/commonjs/expo.js.map +1 -1
- package/lib/commonjs/implementation-version.js +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ipc/manager.js +86 -13
- package/lib/commonjs/ipc/manager.js.map +1 -1
- package/lib/commonjs/ipc/public-manager.js +229 -111
- package/lib/commonjs/ipc/public-manager.js.map +1 -1
- package/lib/commonjs/native-protocol/generated/native-protocol-v2-schema.js +2 -2
- package/lib/commonjs/native-protocol/generated/native-protocol-v2-schema.js.map +1 -1
- package/lib/commonjs/native-protocol/rn-android-boundary.js +32 -3
- package/lib/commonjs/native-protocol/rn-android-boundary.js.map +1 -1
- package/lib/commonjs/native-protocol/rn-apple-boundary.js +7 -1
- package/lib/commonjs/native-protocol/rn-apple-boundary.js.map +1 -1
- package/lib/commonjs/node-corebluetooth.js +15 -4
- package/lib/commonjs/node-corebluetooth.js.map +1 -1
- package/lib/commonjs/node-host-manager.js +14 -6
- package/lib/commonjs/node-host-manager.js.map +1 -1
- package/lib/commonjs/public/ble-manager.js +203 -63
- package/lib/commonjs/public/ble-manager.js.map +1 -1
- package/lib/commonjs/public/cleanup.js +154 -0
- package/lib/commonjs/public/cleanup.js.map +1 -0
- package/lib/commonjs/public/connection-supervisor.js +39 -3
- package/lib/commonjs/public/connection-supervisor.js.map +1 -1
- package/lib/commonjs/public/diagnostics.js +21 -0
- package/lib/commonjs/public/diagnostics.js.map +1 -1
- package/lib/commonjs/public/error-bridge.js +25 -9
- package/lib/commonjs/public/error-bridge.js.map +1 -1
- package/lib/commonjs/public/errors.js +2 -28
- package/lib/commonjs/public/errors.js.map +1 -1
- package/lib/commonjs/public/gatt.js +53 -77
- package/lib/commonjs/public/gatt.js.map +1 -1
- package/lib/commonjs/public/host-identity.js.map +1 -1
- package/lib/commonjs/public/index.js.map +1 -1
- package/lib/commonjs/public/scan-query.js +70 -3
- package/lib/commonjs/public/scan-query.js.map +1 -1
- package/lib/commonjs/public/scan-state-budget.js +11 -0
- package/lib/commonjs/public/scan-state-budget.js.map +1 -1
- package/lib/commonjs/public/security.js +4 -0
- package/lib/commonjs/public/security.js.map +1 -1
- package/lib/commonjs/public/stream-capacity.js +25 -0
- package/lib/commonjs/public/stream-capacity.js.map +1 -0
- package/lib/commonjs/public/stream-presets.js +9 -2
- package/lib/commonjs/public/stream-presets.js.map +1 -1
- package/lib/commonjs/public/streams.js +214 -0
- package/lib/commonjs/public/streams.js.map +1 -0
- package/lib/commonjs/react.js +63 -33
- package/lib/commonjs/react.js.map +1 -1
- package/lib/commonjs/tck/first-party/bluez-tck-registration.js +14 -2
- package/lib/commonjs/tck/first-party/bluez-tck-registration.js.map +1 -1
- package/lib/commonjs/testing/deterministic/deterministic-scan-planner.js +1 -1
- package/lib/commonjs/testing/deterministic/deterministic-scan-planner.js.map +1 -1
- package/lib/commonjs/testing/deterministic/deterministic-security.js +8 -0
- package/lib/commonjs/testing/deterministic/deterministic-security.js.map +1 -1
- package/lib/module/backend-contract/advertisement.js +19 -0
- package/lib/module/backend-contract/advertisement.js.map +1 -1
- package/lib/module/backend-contract/backend.js +6 -0
- package/lib/module/backend-contract/backend.js.map +1 -1
- package/lib/module/backend-contract/capabilities.js +7 -0
- package/lib/module/backend-contract/capabilities.js.map +1 -1
- package/lib/module/backend-contract/ipc.js +7 -0
- package/lib/module/backend-contract/ipc.js.map +1 -1
- package/lib/module/backend-contract/primitives.js +13 -0
- package/lib/module/backend-contract/primitives.js.map +1 -1
- package/lib/module/backend-contract/scan-planning.js +18 -2
- package/lib/module/backend-contract/scan-planning.js.map +1 -1
- package/lib/module/backend-contract/scan-query.js +19 -4
- package/lib/module/backend-contract/scan-query.js.map +1 -1
- package/lib/module/backends/bluez/bluez-backend-handles.js +62 -30
- package/lib/module/backends/bluez/bluez-backend-handles.js.map +1 -1
- package/lib/module/backends/bluez/bluez-backend-provider.js +1 -1
- package/lib/module/backends/bluez/bluez-backend-provider.js.map +1 -1
- package/lib/module/backends/bluez/bluez-backend-runtime.js +34 -2
- package/lib/module/backends/bluez/bluez-backend-runtime.js.map +1 -1
- package/lib/module/backends/bluez/bluez-backend.js +9 -1
- package/lib/module/backends/bluez/bluez-backend.js.map +1 -1
- package/lib/module/backends/bluez/bluez-connection-capabilities.js +105 -0
- package/lib/module/backends/bluez/bluez-connection-capabilities.js.map +1 -0
- package/lib/module/backends/bluez/bluez-connection-runtime.js +167 -5
- package/lib/module/backends/bluez/bluez-connection-runtime.js.map +1 -1
- package/lib/module/backends/bluez/bluez-dbus-next-boundary.js +200 -3
- package/lib/module/backends/bluez/bluez-dbus-next-boundary.js.map +1 -1
- package/lib/module/backends/bluez/bluez-operation-dispatcher.js +29 -20
- package/lib/module/backends/bluez/bluez-operation-dispatcher.js.map +1 -1
- package/lib/module/backends/bluez/bluez-property-waiters.js +54 -1
- package/lib/module/backends/bluez/bluez-property-waiters.js.map +1 -1
- package/lib/module/backends/bluez/bluez-runtime-models.js +7 -6
- package/lib/module/backends/bluez/bluez-runtime-models.js.map +1 -1
- package/lib/module/backends/bluez/bluez-scan-planner.js +1 -1
- package/lib/module/backends/bluez/bluez-scan-planner.js.map +1 -1
- package/lib/module/backends/bluez/bluez-security.js +69 -2
- package/lib/module/backends/bluez/bluez-security.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-adapter-loss-cleanup.js +4 -4
- package/lib/module/backends/corebluetooth/corebluetooth-adapter-loss-cleanup.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-backend.js +96 -57
- package/lib/module/backends/corebluetooth/corebluetooth-backend.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-cleanup.js +11 -2
- package/lib/module/backends/corebluetooth/corebluetooth-cleanup.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-connection-controls.js +66 -53
- package/lib/module/backends/corebluetooth/corebluetooth-connection-controls.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-gatt-operations.js +48 -48
- package/lib/module/backends/corebluetooth/corebluetooth-gatt-operations.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-handles.js +12 -12
- package/lib/module/backends/corebluetooth/corebluetooth-handles.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-late-connect-cleanup.js +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-late-connect-cleanup.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-provider.js +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-provider.js.map +1 -1
- package/lib/module/backends/corebluetooth/corebluetooth-runtime-capabilities.js +3 -3
- package/lib/module/backends/corebluetooth/corebluetooth-runtime-capabilities.js.map +1 -1
- package/lib/module/backends/reactnative/react-native-android-provider.js +26 -2
- package/lib/module/backends/reactnative/react-native-android-provider.js.map +1 -1
- package/lib/module/backends/reactnative/react-native-android-security.js +15 -1
- package/lib/module/backends/reactnative/react-native-android-security.js.map +1 -1
- package/lib/module/backends/reactnative/react-native-restoration.js +8 -0
- package/lib/module/backends/reactnative/react-native-restoration.js.map +1 -1
- package/lib/module/backends/reactnative/react-native-scan-planner.js +2 -1
- package/lib/module/backends/reactnative/react-native-scan-planner.js.map +1 -1
- package/lib/module/backends/scan-planning/service-uuid-scan-planner.js +36 -4
- package/lib/module/backends/scan-planning/service-uuid-scan-planner.js.map +1 -1
- package/lib/module/backends/winrt/winrt-backend-helpers.js +10 -0
- package/lib/module/backends/winrt/winrt-backend-helpers.js.map +1 -1
- package/lib/module/backends/winrt/winrt-security.js +7 -0
- package/lib/module/backends/winrt/winrt-security.js.map +1 -1
- package/lib/module/cli-json.js +7 -0
- package/lib/module/cli-json.js.map +1 -1
- package/lib/module/core/core-characteristic-operations.js +13 -0
- package/lib/module/core/core-characteristic-operations.js.map +1 -1
- package/lib/module/core/core-gatt-handles.js +10 -0
- package/lib/module/core/core-gatt-handles.js.map +1 -1
- package/lib/module/core/operation-coordinator.js +10 -1
- package/lib/module/core/operation-coordinator.js.map +1 -1
- package/lib/module/core/unified-ble-core.js +21 -0
- package/lib/module/core/unified-ble-core.js.map +1 -1
- package/lib/module/diagnostics/trace-format.js +12 -0
- package/lib/module/diagnostics/trace-format.js.map +1 -1
- package/lib/module/electron/connection-event-stream-registry.js +8 -0
- package/lib/module/electron/connection-event-stream-registry.js.map +1 -1
- package/lib/module/electron/main-binding.js +16 -0
- package/lib/module/electron/main-binding.js.map +1 -1
- package/lib/module/electron/main-router.js +11 -0
- package/lib/module/electron/main-router.js.map +1 -1
- package/lib/module/electron/renderer-stream-registry.js +8 -0
- package/lib/module/electron/renderer-stream-registry.js.map +1 -1
- package/lib/module/electron/renderer.js +11 -0
- package/lib/module/electron/renderer.js.map +1 -1
- package/lib/module/expo.js +37 -1
- package/lib/module/expo.js.map +1 -1
- package/lib/module/implementation-version.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ipc/manager.js +86 -13
- package/lib/module/ipc/manager.js.map +1 -1
- package/lib/module/ipc/public-manager.js +232 -115
- package/lib/module/ipc/public-manager.js.map +1 -1
- package/lib/module/native-protocol/generated/native-protocol-v2-schema.js +2 -2
- package/lib/module/native-protocol/generated/native-protocol-v2-schema.js.map +1 -1
- package/lib/module/native-protocol/rn-android-boundary.js +32 -3
- package/lib/module/native-protocol/rn-android-boundary.js.map +1 -1
- package/lib/module/native-protocol/rn-apple-boundary.js +7 -1
- package/lib/module/native-protocol/rn-apple-boundary.js.map +1 -1
- package/lib/module/node-corebluetooth.js +15 -4
- package/lib/module/node-corebluetooth.js.map +1 -1
- package/lib/module/node-host-manager.js +14 -6
- package/lib/module/node-host-manager.js.map +1 -1
- package/lib/module/public/ble-manager.js +204 -65
- package/lib/module/public/ble-manager.js.map +1 -1
- package/lib/module/public/cleanup.js +150 -0
- package/lib/module/public/cleanup.js.map +1 -0
- package/lib/module/public/connection-supervisor.js +39 -3
- package/lib/module/public/connection-supervisor.js.map +1 -1
- package/lib/module/public/diagnostics.js +20 -0
- package/lib/module/public/diagnostics.js.map +1 -1
- package/lib/module/public/error-bridge.js +25 -9
- package/lib/module/public/error-bridge.js.map +1 -1
- package/lib/module/public/errors.js +2 -27
- package/lib/module/public/errors.js.map +1 -1
- package/lib/module/public/gatt.js +54 -78
- package/lib/module/public/gatt.js.map +1 -1
- package/lib/module/public/host-identity.js.map +1 -1
- package/lib/module/public/index.js.map +1 -1
- package/lib/module/public/scan-query.js +70 -4
- package/lib/module/public/scan-query.js.map +1 -1
- package/lib/module/public/scan-state-budget.js +11 -0
- package/lib/module/public/scan-state-budget.js.map +1 -1
- package/lib/module/public/security.js +4 -0
- package/lib/module/public/security.js.map +1 -1
- package/lib/module/public/stream-capacity.js +21 -0
- package/lib/module/public/stream-capacity.js.map +1 -0
- package/lib/module/public/stream-presets.js +9 -2
- package/lib/module/public/stream-presets.js.map +1 -1
- package/lib/module/public/streams.js +210 -0
- package/lib/module/public/streams.js.map +1 -0
- package/lib/module/react.js +63 -33
- package/lib/module/react.js.map +1 -1
- package/lib/module/tck/first-party/bluez-tck-registration.js +14 -2
- package/lib/module/tck/first-party/bluez-tck-registration.js.map +1 -1
- package/lib/module/testing/deterministic/deterministic-scan-planner.js +1 -1
- package/lib/module/testing/deterministic/deterministic-scan-planner.js.map +1 -1
- package/lib/module/testing/deterministic/deterministic-security.js +8 -0
- package/lib/module/testing/deterministic/deterministic-security.js.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/advertisement.d.ts +9 -0
- package/lib/typescript/commonjs/src/backend-contract/advertisement.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/backend.d.ts +15 -0
- package/lib/typescript/commonjs/src/backend-contract/backend.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/capabilities.d.ts +7 -0
- package/lib/typescript/commonjs/src/backend-contract/capabilities.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/ipc.d.ts +7 -0
- package/lib/typescript/commonjs/src/backend-contract/ipc.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/primitives.d.ts +8 -0
- package/lib/typescript/commonjs/src/backend-contract/primitives.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/scan-planning.d.ts +2 -2
- package/lib/typescript/commonjs/src/backend-contract/scan-planning.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/scan-query.d.ts +12 -0
- package/lib/typescript/commonjs/src/backend-contract/scan-query.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backend-contract/security.d.ts +7 -0
- package/lib/typescript/commonjs/src/backend-contract/security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-handles.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-handles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-runtime.d.ts +11 -2
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-backend.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-capabilities.d.ts +13 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-capabilities.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-runtime.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-connection-runtime.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-dbus-contract.d.ts +3 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-dbus-contract.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-dbus-next-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-operation-dispatcher.d.ts +12 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-operation-dispatcher.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-property-waiters.d.ts +12 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-property-waiters.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-models.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-types.d.ts +2 -0
- package/lib/typescript/commonjs/src/backends/bluez/bluez-runtime-types.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-scan-planner.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-security.d.ts +0 -1
- package/lib/typescript/commonjs/src/backends/bluez/bluez-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-backend.d.ts +9 -0
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-backend.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-boundary.d.ts +17 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-cleanup.d.ts +10 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-cleanup.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-connection-controls.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/corebluetooth/corebluetooth-identity.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-provider.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-android-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-apple-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-restoration.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/reactnative/react-native-scan-planner.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/scan-planning/service-uuid-scan-planner.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-backend-helpers.d.ts +9 -0
- package/lib/typescript/commonjs/src/backends/winrt/winrt-backend-helpers.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-provider.d.ts +1 -1
- package/lib/typescript/commonjs/src/backends/winrt/winrt-security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/cli-json.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/core-characteristic-operations.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/core-gatt-handles.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/operation-coordinator.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/core/unified-ble-core.d.ts +3 -1
- package/lib/typescript/commonjs/src/core/unified-ble-core.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/diagnostics/trace-format.d.ts +12 -0
- package/lib/typescript/commonjs/src/diagnostics/trace-format.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/connection-event-stream-registry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/main-binding.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/main-router.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/renderer-stream-registry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/electron/renderer.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/expo.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/implementation-version.d.ts +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +3 -2
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ipc/manager.d.ts +5 -2
- package/lib/typescript/commonjs/src/ipc/manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/ipc/public-manager.d.ts +13 -4
- package/lib/typescript/commonjs/src/ipc/public-manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/native-protocol/generated/native-protocol-v2-schema.d.ts +1 -1
- package/lib/typescript/commonjs/src/native-protocol/generated/native-protocol-v2-schema.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/native-protocol/rn-android-boundary.d.ts +2 -2
- package/lib/typescript/commonjs/src/native-protocol/rn-android-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/native-protocol/rn-apple-boundary.d.ts +2 -2
- package/lib/typescript/commonjs/src/native-protocol/rn-apple-boundary.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/node-corebluetooth.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/ble-adapter.d.ts +3 -3
- package/lib/typescript/commonjs/src/public/ble-adapter.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/ble-manager.d.ts +68 -14
- package/lib/typescript/commonjs/src/public/ble-manager.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/cleanup.d.ts +35 -0
- package/lib/typescript/commonjs/src/public/cleanup.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/public/connection-supervisor.d.ts +5 -5
- package/lib/typescript/commonjs/src/public/connection-supervisor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/diagnostics.d.ts +20 -2
- package/lib/typescript/commonjs/src/public/diagnostics.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/error-bridge.d.ts +5 -11
- package/lib/typescript/commonjs/src/public/error-bridge.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/errors.d.ts +4 -3
- package/lib/typescript/commonjs/src/public/errors.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/gatt.d.ts +7 -13
- package/lib/typescript/commonjs/src/public/gatt.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/host-identity.d.ts +7 -1
- package/lib/typescript/commonjs/src/public/host-identity.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/index.d.ts +2 -0
- package/lib/typescript/commonjs/src/public/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/scan-query.d.ts +8 -0
- package/lib/typescript/commonjs/src/public/scan-query.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/scan-state-budget.d.ts +11 -0
- package/lib/typescript/commonjs/src/public/scan-state-budget.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/security.d.ts +6 -0
- package/lib/typescript/commonjs/src/public/security.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/stream-capacity.d.ts +16 -0
- package/lib/typescript/commonjs/src/public/stream-capacity.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/public/stream-presets.d.ts +3 -2
- package/lib/typescript/commonjs/src/public/stream-presets.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/public/streams.d.ts +44 -0
- package/lib/typescript/commonjs/src/public/streams.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/react.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/tck/first-party/bluez-tck-registration.d.ts +1 -1
- package/lib/typescript/commonjs/src/tck/first-party/bluez-tck-registration.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/testing/deterministic/deterministic-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/advertisement.d.ts +9 -0
- package/lib/typescript/module/src/backend-contract/advertisement.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/backend.d.ts +15 -0
- package/lib/typescript/module/src/backend-contract/backend.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/capabilities.d.ts +7 -0
- package/lib/typescript/module/src/backend-contract/capabilities.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/ipc.d.ts +7 -0
- package/lib/typescript/module/src/backend-contract/ipc.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/primitives.d.ts +8 -0
- package/lib/typescript/module/src/backend-contract/primitives.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/scan-planning.d.ts +2 -2
- package/lib/typescript/module/src/backend-contract/scan-planning.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/scan-query.d.ts +12 -0
- package/lib/typescript/module/src/backend-contract/scan-query.d.ts.map +1 -1
- package/lib/typescript/module/src/backend-contract/security.d.ts +7 -0
- package/lib/typescript/module/src/backend-contract/security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-handles.d.ts +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-handles.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend-runtime.d.ts +11 -2
- package/lib/typescript/module/src/backends/bluez/bluez-backend-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-backend.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-connection-capabilities.d.ts +13 -0
- package/lib/typescript/module/src/backends/bluez/bluez-connection-capabilities.d.ts.map +1 -0
- package/lib/typescript/module/src/backends/bluez/bluez-connection-runtime.d.ts +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-connection-runtime.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-dbus-contract.d.ts +3 -1
- package/lib/typescript/module/src/backends/bluez/bluez-dbus-contract.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-dbus-next-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-operation-dispatcher.d.ts +12 -0
- package/lib/typescript/module/src/backends/bluez/bluez-operation-dispatcher.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-property-waiters.d.ts +12 -0
- package/lib/typescript/module/src/backends/bluez/bluez-property-waiters.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-models.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-types.d.ts +2 -0
- package/lib/typescript/module/src/backends/bluez/bluez-runtime-types.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-scan-planner.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/bluez/bluez-security.d.ts +0 -1
- package/lib/typescript/module/src/backends/bluez/bluez-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-backend.d.ts +9 -0
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-backend.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-boundary.d.ts +17 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-cleanup.d.ts +10 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-cleanup.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-connection-controls.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/corebluetooth/corebluetooth-identity.d.ts +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-android-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-android-provider.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-android-security.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-apple-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-restoration.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/reactnative/react-native-scan-planner.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/scan-planning/service-uuid-scan-planner.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-backend-helpers.d.ts +9 -0
- package/lib/typescript/module/src/backends/winrt/winrt-backend-helpers.d.ts.map +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-provider.d.ts +1 -1
- package/lib/typescript/module/src/backends/winrt/winrt-security.d.ts.map +1 -1
- package/lib/typescript/module/src/cli-json.d.ts.map +1 -1
- package/lib/typescript/module/src/core/core-characteristic-operations.d.ts.map +1 -1
- package/lib/typescript/module/src/core/core-gatt-handles.d.ts.map +1 -1
- package/lib/typescript/module/src/core/operation-coordinator.d.ts.map +1 -1
- package/lib/typescript/module/src/core/unified-ble-core.d.ts +3 -1
- package/lib/typescript/module/src/core/unified-ble-core.d.ts.map +1 -1
- package/lib/typescript/module/src/diagnostics/trace-format.d.ts +12 -0
- package/lib/typescript/module/src/diagnostics/trace-format.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/connection-event-stream-registry.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/main-binding.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/main-router.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/renderer-stream-registry.d.ts.map +1 -1
- package/lib/typescript/module/src/electron/renderer.d.ts.map +1 -1
- package/lib/typescript/module/src/expo.d.ts.map +1 -1
- package/lib/typescript/module/src/implementation-version.d.ts +1 -1
- package/lib/typescript/module/src/index.d.ts +3 -2
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/ipc/manager.d.ts +5 -2
- package/lib/typescript/module/src/ipc/manager.d.ts.map +1 -1
- package/lib/typescript/module/src/ipc/public-manager.d.ts +13 -4
- package/lib/typescript/module/src/ipc/public-manager.d.ts.map +1 -1
- package/lib/typescript/module/src/native-protocol/generated/native-protocol-v2-schema.d.ts +1 -1
- package/lib/typescript/module/src/native-protocol/generated/native-protocol-v2-schema.d.ts.map +1 -1
- package/lib/typescript/module/src/native-protocol/rn-android-boundary.d.ts +2 -2
- package/lib/typescript/module/src/native-protocol/rn-android-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/native-protocol/rn-apple-boundary.d.ts +2 -2
- package/lib/typescript/module/src/native-protocol/rn-apple-boundary.d.ts.map +1 -1
- package/lib/typescript/module/src/node-corebluetooth.d.ts.map +1 -1
- package/lib/typescript/module/src/public/ble-adapter.d.ts +3 -3
- package/lib/typescript/module/src/public/ble-adapter.d.ts.map +1 -1
- package/lib/typescript/module/src/public/ble-manager.d.ts +68 -14
- package/lib/typescript/module/src/public/ble-manager.d.ts.map +1 -1
- package/lib/typescript/module/src/public/cleanup.d.ts +35 -0
- package/lib/typescript/module/src/public/cleanup.d.ts.map +1 -0
- package/lib/typescript/module/src/public/connection-supervisor.d.ts +5 -5
- package/lib/typescript/module/src/public/connection-supervisor.d.ts.map +1 -1
- package/lib/typescript/module/src/public/diagnostics.d.ts +20 -2
- package/lib/typescript/module/src/public/diagnostics.d.ts.map +1 -1
- package/lib/typescript/module/src/public/error-bridge.d.ts +5 -11
- package/lib/typescript/module/src/public/error-bridge.d.ts.map +1 -1
- package/lib/typescript/module/src/public/errors.d.ts +4 -3
- package/lib/typescript/module/src/public/errors.d.ts.map +1 -1
- package/lib/typescript/module/src/public/gatt.d.ts +7 -13
- package/lib/typescript/module/src/public/gatt.d.ts.map +1 -1
- package/lib/typescript/module/src/public/host-identity.d.ts +7 -1
- package/lib/typescript/module/src/public/host-identity.d.ts.map +1 -1
- package/lib/typescript/module/src/public/index.d.ts +2 -0
- package/lib/typescript/module/src/public/index.d.ts.map +1 -1
- package/lib/typescript/module/src/public/scan-query.d.ts +8 -0
- package/lib/typescript/module/src/public/scan-query.d.ts.map +1 -1
- package/lib/typescript/module/src/public/scan-state-budget.d.ts +11 -0
- package/lib/typescript/module/src/public/scan-state-budget.d.ts.map +1 -1
- package/lib/typescript/module/src/public/security.d.ts +6 -0
- package/lib/typescript/module/src/public/security.d.ts.map +1 -1
- package/lib/typescript/module/src/public/stream-capacity.d.ts +16 -0
- package/lib/typescript/module/src/public/stream-capacity.d.ts.map +1 -0
- package/lib/typescript/module/src/public/stream-presets.d.ts +3 -2
- package/lib/typescript/module/src/public/stream-presets.d.ts.map +1 -1
- package/lib/typescript/module/src/public/streams.d.ts +44 -0
- package/lib/typescript/module/src/public/streams.d.ts.map +1 -0
- package/lib/typescript/module/src/react.d.ts.map +1 -1
- package/lib/typescript/module/src/tck/first-party/bluez-tck-registration.d.ts +1 -1
- package/lib/typescript/module/src/tck/first-party/bluez-tck-registration.d.ts.map +1 -1
- package/lib/typescript/module/src/testing/deterministic/deterministic-security.d.ts.map +1 -1
- package/native/PREBUILDS.json +5 -5
- package/native/electron/corebluetooth/prebuilds/darwin-arm64/unified_ble_corebluetooth.node +0 -0
- package/native/electron/corebluetooth/prebuilds/darwin-x64/unified_ble_corebluetooth.node +0 -0
- package/native/electron/winrt/prebuilds/win32-arm64/unified_ble_winrt.node +0 -0
- package/native/electron/winrt/prebuilds/win32-x64/unified_ble_winrt.node +0 -0
- package/native/protocol/generated/NativeProtocolV2Schema.hpp +3 -2
- package/native/protocol/schema/native-protocol-v2-abi.json +9 -2
- package/native/protocol/schema/native-protocol-v2.json +3 -2
- package/native/protocol/src/NativeProtocolV2Codec.cpp +48 -4
- package/native/tauri/Cargo.toml +14 -0
- package/native/tauri/src/btleplug_dispatcher.rs +422 -10
- package/native/tauri/src/capabilities.rs +3 -1
- package/package.json +7 -4
- package/src/backend-contract/advertisement.ts +28 -0
- package/src/backend-contract/backend.ts +15 -0
- package/src/backend-contract/capabilities.ts +7 -0
- package/src/backend-contract/ipc.ts +7 -0
- package/src/backend-contract/primitives.ts +13 -0
- package/src/backend-contract/scan-planning.ts +15 -0
- package/src/backend-contract/scan-query.ts +33 -3
- package/src/backend-contract/security.ts +7 -0
- package/src/backends/bluez/bluez-backend-handles.ts +110 -49
- package/src/backends/bluez/bluez-backend-provider.ts +1 -1
- package/src/backends/bluez/bluez-backend-runtime.ts +36 -1
- package/src/backends/bluez/bluez-backend.ts +11 -1
- package/src/backends/bluez/bluez-connection-capabilities.ts +144 -0
- package/src/backends/bluez/bluez-connection-runtime.ts +203 -8
- package/src/backends/bluez/bluez-dbus-contract.ts +3 -1
- package/src/backends/bluez/bluez-dbus-next-boundary.ts +188 -3
- package/src/backends/bluez/bluez-operation-dispatcher.ts +39 -34
- package/src/backends/bluez/bluez-property-waiters.ts +60 -1
- package/src/backends/bluez/bluez-runtime-models.ts +6 -5
- package/src/backends/bluez/bluez-runtime-types.ts +2 -0
- package/src/backends/bluez/bluez-scan-planner.ts +6 -1
- package/src/backends/bluez/bluez-security.ts +72 -2
- package/src/backends/corebluetooth/corebluetooth-adapter-loss-cleanup.ts +4 -4
- package/src/backends/corebluetooth/corebluetooth-backend.ts +118 -58
- package/src/backends/corebluetooth/corebluetooth-boundary.ts +20 -1
- package/src/backends/corebluetooth/corebluetooth-cleanup.ts +12 -3
- package/src/backends/corebluetooth/corebluetooth-connection-controls.ts +65 -57
- package/src/backends/corebluetooth/corebluetooth-gatt-operations.ts +48 -48
- package/src/backends/corebluetooth/corebluetooth-handles.ts +12 -12
- package/src/backends/corebluetooth/corebluetooth-late-connect-cleanup.ts +1 -1
- package/src/backends/corebluetooth/corebluetooth-provider.ts +1 -1
- package/src/backends/corebluetooth/corebluetooth-runtime-capabilities.ts +3 -3
- package/src/backends/reactnative/react-native-android-provider.ts +38 -1
- package/src/backends/reactnative/react-native-android-security.ts +15 -1
- package/src/backends/reactnative/react-native-restoration.ts +8 -0
- package/src/backends/reactnative/react-native-scan-planner.ts +11 -1
- package/src/backends/scan-planning/service-uuid-scan-planner.ts +54 -3
- package/src/backends/winrt/winrt-backend-helpers.ts +9 -0
- package/src/backends/winrt/winrt-security.ts +9 -0
- package/src/cli-json.ts +7 -0
- package/src/core/core-characteristic-operations.ts +13 -0
- package/src/core/core-gatt-handles.ts +10 -0
- package/src/core/operation-coordinator.ts +10 -1
- package/src/core/unified-ble-core.ts +22 -0
- package/src/diagnostics/trace-format.ts +12 -0
- package/src/electron/connection-event-stream-registry.ts +8 -0
- package/src/electron/main-binding.ts +16 -0
- package/src/electron/main-router.ts +11 -0
- package/src/electron/renderer-stream-registry.ts +8 -0
- package/src/electron/renderer.ts +11 -0
- package/src/expo.ts +44 -1
- package/src/implementation-version.ts +1 -1
- package/src/index.ts +26 -2
- package/src/ipc/manager.ts +76 -18
- package/src/ipc/public-manager.ts +311 -121
- package/src/native-protocol/generated/native-protocol-v2-schema.ts +2 -1
- package/src/native-protocol/rn-android-boundary.ts +42 -6
- package/src/native-protocol/rn-apple-boundary.ts +11 -2
- package/src/node-corebluetooth.ts +15 -4
- package/src/node-host-manager.ts +14 -6
- package/src/public/ble-adapter.ts +5 -3
- package/src/public/ble-manager.ts +304 -99
- package/src/public/cleanup.ts +255 -0
- package/src/public/connection-supervisor.ts +62 -28
- package/src/public/diagnostics.ts +46 -2
- package/src/public/error-bridge.ts +40 -24
- package/src/public/errors.ts +5 -35
- package/src/public/gatt.ts +60 -104
- package/src/public/host-identity.ts +7 -1
- package/src/public/index.ts +19 -0
- package/src/public/scan-query.ts +82 -4
- package/src/public/scan-state-budget.ts +11 -0
- package/src/public/security.ts +15 -0
- package/src/public/stream-capacity.ts +18 -0
- package/src/public/stream-presets.ts +21 -3
- package/src/public/streams.ts +315 -0
- package/src/react.ts +81 -38
- package/src/tck/first-party/bluez-tck-registration.ts +19 -3
- package/src/testing/deterministic/deterministic-scan-planner.ts +1 -0
- package/src/testing/deterministic/deterministic-security.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `unified-ble-manager` are documented here.
|
|
4
4
|
|
|
5
|
-
## [
|
|
5
|
+
## [4.0.6] - 2026-08-26
|
|
6
|
+
|
|
7
|
+
The first release cut against a live peripheral on Android as well as Linux. Most of it is defects that only real hardware surfaced, several of them boundaries that discarded evidence and so presented a specific fault as silence. Does not retag `v4.0.5`.
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
|
|
11
|
+
- A Tauri disconnect that fails no longer leaves the peer owned when the platform can prove it was released. btleplug's CoreBluetooth `disconnect()` never resolves once the peripheral has left its internal map, so the call is bounded and the outcome decided by a fresh state reading: gone means released, still connected means the retry keeps ownership. On BlueZ the state reading is classified before it is stringified, because a removed D-Bus device object is not a failed question but the answer to it - previously that case was treated as unknowable and the peer stayed owned until the process restarted. Genuine indeterminacy - a D-Bus timeout, the daemon gone, the adapter pulled - still retains ownership (#145, #154).
|
|
12
|
+
|
|
13
|
+
- BlueZ no longer reports a pairing it could not stop as `cancelled`. `Device1.CancelPairing` rejections were all swallowed, so a refusal from bluetoothd — `org.bluez.Error.Failed`, `NotAuthorized`, a D-Bus timeout, the daemon gone — left the in-flight `Pair` running while `cancelPairing()` returned `cancelled` and the abort/deadline path did the same. A caller told no bond exists while one is still being made cannot recover, because it never learns to look. Only the two rejections that prove nothing is left running are treated as success — `org.bluez.Error.DoesNotExist` and `org.freedesktop.DBus.Error.UnknownObject`, an answer to the question rather than a failure to answer it, the same pair the Tauri disconnect path classifies for the same reason. Anything else now surfaces as `platform.failure` carrying the D-Bus error name (#143).
|
|
14
|
+
|
|
15
|
+
- `scan()` works on React Native Android again, and so does every other control-plane operation there. The Android dispatcher stamped a hardcoded `1` on field 1 of every result and event it built while the native codec has required version 2 since the schema was frozen, so all of them — `scanStarted`, a connect completing, a connect failing, a cancellation, a bond state change, a lost link — were rejected at the JSI boundary as version-incompatible and dropped. A scan therefore never received its terminal: the radio discovered the peripheral 38 times in one four-minute capture and the application was handed nothing. The stamp now comes from the generated `NATIVE_PROTOCOL_VERSION`, so it cannot drift from the version the codec validates against (#140).
|
|
16
|
+
- A record the codec refuses is no longer only written to logcat: the Android binding counts quarantined records per attachment and emits a `recordQuarantined` diagnostic in place of the record it could not deliver, so an application learns that the boundary discarded something it was asked to deliver (#140).
|
|
17
|
+
- A version-incompatible record names its kind, the version it carried and the version expected, so a quarantined record identifies its emitter instead of leaving four record kinds to choose between (#140).
|
|
18
|
+
- `adapter.waitUntilReady()` no longer reports a radio that is still starting up as one the caller is not permitted to use. The React Native Android boundary answers `authorization: 'unavailable'` until the radio publishes its first authoritative state, and the readiness gate maps that value to `permission.denied` — so the one API whose purpose is to wait that window out failed on the very state it exists to wait for, on a phone with Bluetooth switched on and all four runtime permissions granted. The pending snapshot now reports `authorization: 'unknown'`, the value its `availability` and `power` siblings already carried for the same reason: the absence of a measurement is never a denial, so no readiness gate may block on it (#156).
|
|
19
|
+
- BlueZ states its connection-control truth instead of omitting the concept: `connection:priority` and `connection:parameters` are now registered as explicitly `unsupported`, with limitations naming the BlueZ D-Bus gap (no LE connection-parameter API on `org.bluez.Device1`/`Adapter1`, BlueZ 5.85), the privilege requirement of the alternatives (`CAP_NET_ADMIN` kernel mgmt socket and root-only debugfs — neither a live per-connection update), and the consequence that GATT traffic may run at a multi-hundred-millisecond peer-negotiated interval. `requestPriority()`, `parameters()`, and `parameterEvents()` fail closed with that reason attached (`BleError.limitations` and `platform.safeMessage`) instead of a bare `capability.unsupported` that taught nothing while a slow link looked like a peripheral fault (#149).
|
|
20
|
+
- BlueZ `security.pair()` no longer fires `Device1.Pair` when the operation is aborted or times out while the just-works agent is still registering; it re-checks cancellation after agent registration so a cancelled pairing never proceeds on the daemon (#143).
|
|
21
|
+
- BlueZ `security.pair()` reports `paired` (not `cancelled`) when an abort or deadline lands after `Device1.Pair` has already completed the bond, so a bond that was actually created is never reported as if it never happened (#143).
|
|
22
|
+
- Android `security.pair()` no longer reports a timed-out pairing as `cancelled` when native cancellation is unavailable and it cannot actually stop the in-flight bond; the deadline path now fails closed with `capability.unsupported`, matching the abort path, so a bond that may still complete is never misreported as cancelled (#143).
|
|
23
|
+
|
|
24
|
+
### Additions
|
|
25
|
+
|
|
26
|
+
- `FindOptions` accepts `duplicates` and `delivery`, so the `find()` convenience can be pointed at a peripheral that advertises in dense bursts instead of being abandoned for a hand-driven `scan()`. Both default to the values `find()` has always used (`'coalesced'` and `'latest'`), so nothing changes for existing callers (#148).
|
|
27
|
+
- BlueZ pairing dispatch: `org.bluez.Device1.Pair`, `org.bluez.Device1.CancelPairing`, and `org.bluez.Adapter1.RemoveDevice` are now allowed through the dbus-next boundary, and the backend registers a just-works (`NoInputNoOutput`) `org.bluez.Agent1` on its own bus (not the system default) so a client-initiated pairing can complete without an external agent (#141, #143).
|
|
28
|
+
|
|
29
|
+
### Changes
|
|
30
|
+
|
|
31
|
+
- The Node convenience factories (`createBluezBleManager` and siblings) now select the first adapter (ordered deterministically by id) when the caller names no `adapterId`, instead of failing on a multi-adapter host. A single-adapter machine needs no configuration and a multi-adapter host picks the same controller every run; pass `adapterId` to target a specific controller (e.g. a second USB dongle used for debugging). The low-level provider is unchanged: it still requires an explicit selection and never silently substitutes one (#143).
|
|
32
|
+
- `PairOptions.secureConnections` (`'require' | 'prefer' | 'disallow'`, default `'prefer'`): request an LE pairing generation. `'prefer'` defers to the platform. No current backend exposes per-pairing generation selection, so `'require'` and `'disallow'` fail closed with `capability.unsupported` on BlueZ, WinRT, Android **and the deterministic `/testing` backend** rather than being silently ignored; the contract is in place for a backend that can honour it. The deterministic backend previously ignored the field and reported a Secure Connections bond under the exact option that forbids one, so a consumer's suite could pass against a contract every real radio rejects — the one way test infrastructure can actively mislead. A test that asserted a successful pair under `'require'` or `'disallow'` now sees `capability.unsupported`, which is what production would have done (#144, #143).
|
|
33
|
+
|
|
34
|
+
### Documentation
|
|
35
|
+
|
|
36
|
+
- Every hardcoded timing and capacity constant in `src/` is now classified as a protocol invariant, a safety bound, or host policy, and each one that stays fixed carries a comment at its definition saying why. Undocumented constants were the defect: a fixed deadline that is never explained reads as a device fault when a slower host misses it (#148).
|
|
37
|
+
- `find()`'s 10 s fallback deadline and `adapter.waitUntilReady()`'s 10 s fallback deadline are named constants shared between the in-process and IPC managers, so the same logical operation cannot expire at two different times either side of the IPC boundary (#148).
|
|
38
|
+
|
|
39
|
+
## [4.0.5] - 2026-08-25
|
|
40
|
+
|
|
41
|
+
First release cut against a live peripheral. Every fix below came from driving a real CGM from an Android phone and a Linux/BlueZ host, and several are defects no unit test had reason to catch. Does not retag `v4.0.4`.
|
|
42
|
+
|
|
43
|
+
### Fixes
|
|
44
|
+
|
|
45
|
+
- `readiness()` no longer reports a working radio as `unavailable` before the Android adapter publishes its authoritative state; a boundary that has not yet been told the radio's state is a pending condition, not an absent radio (#116, #128).
|
|
46
|
+
- The direct-GATT backend is shared by CoreBluetooth and React Native Android, so its diagnostics now name the platform that is actually running — `[unified-ble:android-gatt.*]` rather than `[CoreBluetoothBackend.*]` — and its operation ids are `direct-gatt.*` instead of `corebluetooth.*`. Scan-stop cleanup timeouts carry the platform identity instead of `platform: null` (#117, #128, #132).
|
|
47
|
+
- An address known out of band can now enter the system: `ScanClause.addresses` and `connect({ address })`, gated on the reported `peer:address-targeting` capability, with pending BlueZ semantics that complete whenever the peripheral next advertises, and Android `ScanFilter.setDeviceAddress`. Hosts that cannot express a radio address — CoreBluetooth, Web, and the IPC transport — report the capability unsupported and fail closed rather than advertising something they cannot honour (#118, #128, #131, #133).
|
|
48
|
+
- `ScanOptions.platform` is honoured instead of unconditionally rejected, so consumers can select Android scan mode; peripherals that advertise infrequently are no longer effectively undiscoverable behind the platform default duty cycle. Gated on `scan:platform-options` in the public, core and IPC paths; `match-lost` and pre-26 `legacy: false` fail closed rather than silently doing something else (#120, #130).
|
|
49
|
+
- BlueZ GATT works again: occurrences are decimal indices rather than D-Bus object paths, so `discover()` no longer fails with `protocol.violation: public-gatt.occurrence` on every device — a regression introduced when the public validator was tightened without migrating the backend. Two same-UUID services are now distinctly addressable, which neither the old leniency nor the strict check managed (#123, #129).
|
|
50
|
+
- The BlueZ boundary decodes the `y` and `a{qv}` D-Bus variants that BlueZ 5.85 actually sends, and routes `Adapter1.ConnectDevice` through the boundary instead of rejecting it as locally unsupported; without these the backend could not attach at all (#128).
|
|
51
|
+
- Public BLE resources are portable across copies, and closing an adapter watch's value stream tears the watch down instead of leaving a 25 ms poll timer and an abort listener alive (#122).
|
|
52
|
+
- `@babel/runtime` is declared as a production dependency. The emitted CommonJS imports its helpers, so an external linked checkout failed with `MODULE_NOT_FOUND` while repository-local tests passed against a transitive copy — a packaging gap only a real consumer could surface (#134, #135).
|
|
53
|
+
- A database stream is finalized after an invalidation retry succeeds, and per-subscription React cleanup and failed IPC CCCDs stay owned (#127).
|
|
54
|
+
|
|
55
|
+
### Compatibility
|
|
56
|
+
|
|
57
|
+
- Native protocol ABI 3 → 4. A JavaScript bundle carrying the new scan fields now fails attachment negotiation against an older native binary instead of failing at scan-start — or, worse, silently selecting the opposite scan mode.
|
|
58
|
+
|
|
59
|
+
### Release integrity
|
|
60
|
+
|
|
61
|
+
- Cut from the exact `main` merge commit through the tag-driven trusted-publishing workflow.
|
|
62
|
+
- Intended for publication as `latest`; this does not promote backend support labels. The live-hardware runs behind these fixes are development evidence, not qualification evidence.
|
|
6
63
|
|
|
7
64
|
## [4.0.4] - 2026-08-25
|
|
8
65
|
|
package/MIGRATION_4.0.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# Migrating from react-native-ble-plx
|
|
4
4
|
|
|
5
|
-
The current package is `4.0.
|
|
5
|
+
The current package is `4.0.6`. The `4.0.0` release is a new package and a new contract. It is **not a source-compatible rename**. There is no `new BleManager()` facade, no Base64 characteristic values, and no public transaction IDs.
|
|
6
6
|
|
|
7
7
|
This page is for a React Native app that already uses `react-native-ble-plx`. Web, Electron, Node, and Tauri are new hosts — use those pages after you understand the RN rewrite.
|
|
8
8
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
It is an evolution of `react-native-ble-plx`, rewritten as a **cross-platform unified product**. One bytes-first BLE model and lifecycle semantics across hosts, with host-specific construction and ownership. The root package never picks a radio for you, and it will not quietly fall back to a simulator or a different backend.
|
|
8
8
|
|
|
9
|
-
Install `unified-ble-manager` from npm (`4.0.
|
|
9
|
+
Install `unified-ble-manager` from npm (`4.0.6` on `latest`). The root import does not pick a radio. Package SemVer and backend support labels are independent: each radio backend stays Experimental until live-radio evidence says otherwise. See [`docs/PLATFORMS.md`](docs/PLATFORMS.md).
|
|
10
10
|
|
|
11
11
|
> Sponsored by [Imagi Explain](https://imagiexplain.com) — researched, narrated whiteboard explainers from a prompt, a PDF, or your notes.
|
|
12
12
|
|
package/RELEASE.md
CHANGED
|
@@ -81,7 +81,7 @@ Active `4.0.0-rc.*` release-train candidates publish to npm `latest` so a bare `
|
|
|
81
81
|
|
|
82
82
|
On release day, set `release_candidate` to the exact candidate required by the
|
|
83
83
|
release plan. RC2, RC3, RC4, `4.0.0-rc.4.1`, and RC5 are already immutable
|
|
84
|
-
once tagged. Stable `4.0.0`, `4.0.1`, `4.0.2`, and `4.0.
|
|
84
|
+
once tagged. Stable `4.0.0`, `4.0.1`, `4.0.2`, `4.0.3`, `4.0.4`, and `4.0.5` are immutable. `4.0.6` is the current train head.
|
|
85
85
|
|
|
86
86
|
```sh
|
|
87
87
|
release_candidate=4.0.0-rc.N
|
|
@@ -133,7 +133,7 @@ The `v4.0.3` tag is immutable published history. Do not recreate or move it.
|
|
|
133
133
|
git tag -a v4.0.3 -m "v4.0.3"
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
## Releasing 4.0.
|
|
136
|
+
## Releasing 4.0.6
|
|
137
137
|
|
|
138
138
|
The source version is prepared on `main` before the tag. The release workflow verifies that every initial release tag points at the exact current `main` commit before publication; do not create that tag from a side branch or an older commit. Do not retag immutable `v4.0.0`, `v4.0.1`, `v4.0.2`, or `v4.0.3`.
|
|
139
139
|
|
|
@@ -145,12 +145,12 @@ git checkout main
|
|
|
145
145
|
git pull --ff-only origin main
|
|
146
146
|
|
|
147
147
|
test "$(git branch --show-current)" = "main"
|
|
148
|
-
test "$(node -p "require('./package.json').version")" = "4.0.
|
|
148
|
+
test "$(node -p "require('./package.json').version")" = "4.0.6"
|
|
149
149
|
git diff --exit-code
|
|
150
150
|
git diff --cached --exit-code
|
|
151
151
|
|
|
152
|
-
git tag -a v4.0.
|
|
153
|
-
git push origin v4.0.
|
|
152
|
+
git tag -a v4.0.6 -m "v4.0.6"
|
|
153
|
+
git push origin v4.0.6
|
|
154
154
|
```
|
|
155
155
|
|
|
156
156
|
Do not push another commit to `main` between the final verification and the tag push.
|
|
@@ -178,26 +178,34 @@ Stable versions publish to `latest`. Active `4.0.0-rc.*` candidates also publish
|
|
|
178
178
|
|
|
179
179
|
## Post-release verification
|
|
180
180
|
|
|
181
|
-
After the workflow succeeds:
|
|
181
|
+
After the workflow succeeds, verify the registry rather than the workflow log:
|
|
182
|
+
a green publish job and a package a consumer can actually install are not the
|
|
183
|
+
same claim.
|
|
182
184
|
|
|
183
185
|
```sh
|
|
184
|
-
|
|
186
|
+
version=4.0.6
|
|
185
187
|
|
|
186
|
-
npm view "unified-ble-manager@$
|
|
188
|
+
npm view "unified-ble-manager@$version" version
|
|
187
189
|
npm view unified-ble-manager dist-tags --json
|
|
188
|
-
npm view "unified-ble-manager@$
|
|
189
|
-
npm view "unified-ble-manager@$
|
|
190
|
+
npm view "unified-ble-manager@$version" repository --json
|
|
191
|
+
npm view "unified-ble-manager@$version" license
|
|
192
|
+
npm view "unified-ble-manager@$version" dist.integrity
|
|
190
193
|
```
|
|
191
194
|
|
|
192
195
|
Then verify:
|
|
193
196
|
|
|
194
|
-
- npm `latest` resolves to the
|
|
197
|
+
- npm `latest` resolves to the released version (a stable release moves
|
|
198
|
+
`latest`; a prerelease must leave it alone and publish to `next`);
|
|
195
199
|
- the npm package page shows provenance for the published artifact;
|
|
196
|
-
- the GitHub Release exists at
|
|
197
|
-
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
- the GitHub Release exists at that tag, and is marked prerelease only if the
|
|
201
|
+
version is one;
|
|
202
|
+
- its attached tarball/SBOM/license artifacts correspond to the release
|
|
203
|
+
workflow output;
|
|
204
|
+
- a clean consumer, in a directory outside this repository, can install
|
|
205
|
+
`unified-ble-manager` with no version pin and import the documented host
|
|
206
|
+
entrypoints. This is the check that catches a packaging gap the repository's
|
|
207
|
+
own tests cannot see: `@babel/runtime` shipped undeclared in 4.0.4 and only a
|
|
208
|
+
real external consumer surfaced it.
|
|
201
209
|
|
|
202
210
|
## Failed release or partial publish
|
|
203
211
|
|
package/SBOM.cdx.json
CHANGED
|
@@ -6,20 +6,20 @@
|
|
|
6
6
|
"metadata": {
|
|
7
7
|
"component": {
|
|
8
8
|
"type": "library",
|
|
9
|
-
"bom-ref": "pkg:npm/unified-ble-manager@4.0.
|
|
9
|
+
"bom-ref": "pkg:npm/unified-ble-manager@4.0.6",
|
|
10
10
|
"name": "unified-ble-manager",
|
|
11
|
-
"version": "4.0.
|
|
11
|
+
"version": "4.0.6",
|
|
12
12
|
"licenses": [
|
|
13
13
|
{
|
|
14
14
|
"expression": "Apache-2.0"
|
|
15
15
|
}
|
|
16
16
|
],
|
|
17
|
-
"purl": "pkg:npm/unified-ble-manager@4.0.
|
|
17
|
+
"purl": "pkg:npm/unified-ble-manager@4.0.6"
|
|
18
18
|
},
|
|
19
19
|
"properties": [
|
|
20
20
|
{
|
|
21
21
|
"name": "unified-ble-manager:pnpm-lock-sha256",
|
|
22
|
-
"value": "
|
|
22
|
+
"value": "5fb778bd200cb93f552ec61264d53829dca5bdd27623ccc692d4d9bcbf9ec296"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"name": "unified-ble-manager:dependency-scope",
|
|
@@ -28,6 +28,25 @@
|
|
|
28
28
|
]
|
|
29
29
|
},
|
|
30
30
|
"components": [
|
|
31
|
+
{
|
|
32
|
+
"type": "library",
|
|
33
|
+
"bom-ref": "pkg:npm/%40babel/runtime@7.29.7",
|
|
34
|
+
"group": "@babel",
|
|
35
|
+
"name": "runtime",
|
|
36
|
+
"version": "7.29.7",
|
|
37
|
+
"licenses": [
|
|
38
|
+
{
|
|
39
|
+
"expression": "MIT"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"purl": "pkg:npm/%40babel/runtime@7.29.7",
|
|
43
|
+
"properties": [
|
|
44
|
+
{
|
|
45
|
+
"name": "unified-ble-manager:license-source",
|
|
46
|
+
"value": "package-metadata"
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
31
50
|
{
|
|
32
51
|
"type": "library",
|
|
33
52
|
"bom-ref": "pkg:npm/%40isaacs/fs-minipass@4.0.1",
|
|
@@ -428,6 +447,10 @@
|
|
|
428
447
|
}
|
|
429
448
|
],
|
|
430
449
|
"dependencies": [
|
|
450
|
+
{
|
|
451
|
+
"ref": "pkg:npm/%40babel/runtime@7.29.7",
|
|
452
|
+
"dependsOn": []
|
|
453
|
+
},
|
|
431
454
|
{
|
|
432
455
|
"ref": "pkg:npm/%40isaacs/fs-minipass@4.0.1",
|
|
433
456
|
"dependsOn": [
|
|
@@ -537,8 +560,9 @@
|
|
|
537
560
|
"dependsOn": []
|
|
538
561
|
},
|
|
539
562
|
{
|
|
540
|
-
"ref": "pkg:npm/unified-ble-manager@4.0.
|
|
563
|
+
"ref": "pkg:npm/unified-ble-manager@4.0.6",
|
|
541
564
|
"dependsOn": [
|
|
565
|
+
"pkg:npm/%40babel/runtime@7.29.7",
|
|
542
566
|
"pkg:npm/%40tauri-apps/api@2.11.1",
|
|
543
567
|
"pkg:npm/node-addon-api@8.9.0",
|
|
544
568
|
"pkg:npm/node-gyp@12.4.0"
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
"schemaVersion": "1.0.0",
|
|
5
5
|
"package": {
|
|
6
6
|
"name": "unified-ble-manager",
|
|
7
|
-
"version": "4.0.
|
|
7
|
+
"version": "4.0.6"
|
|
8
8
|
},
|
|
9
9
|
"source": {
|
|
10
10
|
"method": "pnpm-lock production graph with installed-manifest license audit",
|
|
11
11
|
"lockfile": "pnpm-lock.yaml",
|
|
12
|
-
"lockfileSha256": "
|
|
12
|
+
"lockfileSha256": "5fb778bd200cb93f552ec61264d53829dca5bdd27623ccc692d4d9bcbf9ec296"
|
|
13
13
|
},
|
|
14
14
|
"reviewedOverrides": [
|
|
15
15
|
{
|
|
@@ -27,6 +27,13 @@
|
|
|
27
27
|
],
|
|
28
28
|
"unresolved": [],
|
|
29
29
|
"packages": [
|
|
30
|
+
{
|
|
31
|
+
"name": "@babel/runtime",
|
|
32
|
+
"version": "7.29.7",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"licenseSource": "package-metadata",
|
|
35
|
+
"purl": "pkg:npm/%40babel/runtime@7.29.7"
|
|
36
|
+
},
|
|
30
37
|
{
|
|
31
38
|
"name": "@isaacs/fs-minipass",
|
|
32
39
|
"version": "4.0.1",
|
|
@@ -247,13 +247,29 @@ public final class UnifiedBleExpoRuntimeModule extends NativeUnifiedBleExpoRunti
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/**
|
|
251
|
+
* Read a manifest meta-data flag without assuming how the platform typed it.
|
|
252
|
+
*
|
|
253
|
+
* <p>The config plugin writes {@code android:value="true"}, but the Android manifest parser
|
|
254
|
+
* coerces the literals {@code "true"} and {@code "false"} into a {@link Boolean} before they
|
|
255
|
+
* reach the {@link Bundle}. Reading such an entry with {@code getString} logs a type warning and
|
|
256
|
+
* yields {@code null}, so the caller silently falls back to its default and every configuration
|
|
257
|
+
* digests identically - which defeats the purpose of a digest that exists to detect drift.
|
|
258
|
+
*/
|
|
259
|
+
private static boolean metadataFlag(Bundle metadata, String key, boolean fallback) {
|
|
260
|
+
final Object value = metadata.get(key);
|
|
261
|
+
if (value instanceof Boolean) return (Boolean) value;
|
|
262
|
+
if (value instanceof String) return Boolean.parseBoolean((String) value);
|
|
263
|
+
return fallback;
|
|
264
|
+
}
|
|
265
|
+
|
|
250
266
|
private String configurationDigest(String legacyLocationPolicy) {
|
|
251
267
|
final Bundle metadata = applicationMetadata();
|
|
252
268
|
final String canonical = "unified-ble-expo-runtime-v1\n"
|
|
253
269
|
+ "platform=android\n"
|
|
254
270
|
+ "legacyLocationPolicy=" + legacyLocationPolicy + "\n"
|
|
255
|
-
+ "neverForLocation=" + metadata
|
|
256
|
-
+ "requiredHardware=" + metadata
|
|
271
|
+
+ "neverForLocation=" + metadataFlag(metadata, NEVER_FOR_LOCATION_METADATA, false) + "\n"
|
|
272
|
+
+ "requiredHardware=" + metadataFlag(metadata, REQUIRED_HARDWARE_METADATA, false) + "\n";
|
|
257
273
|
try {
|
|
258
274
|
final byte[] digest = MessageDigest.getInstance("SHA-256")
|
|
259
275
|
.digest(canonical.getBytes(StandardCharsets.UTF_8));
|
|
@@ -6,6 +6,7 @@ import android.bluetooth.BluetoothGattCharacteristic
|
|
|
6
6
|
import android.content.Context
|
|
7
7
|
import android.os.Build
|
|
8
8
|
import android.os.SystemClock
|
|
9
|
+
import com.sfourdrinier.unifiedblemanager.protocol.generated.NATIVE_PROTOCOL_VERSION
|
|
9
10
|
import com.sfourdrinier.unifiedblemanager.protocol.generated.RecordKind
|
|
10
11
|
import com.sfourdrinier.unifiedblemanager.radio.OwnedAndroidGattRadio
|
|
11
12
|
import com.sfourdrinier.unifiedblemanager.radio.OwnedRadioTeardownFailure
|
|
@@ -255,7 +256,8 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
255
256
|
scanMode = options.requiredSignedInteger(3).toInt(),
|
|
256
257
|
callbackType = options.requiredSignedInteger(4).toInt(),
|
|
257
258
|
legacyScan = options.requiredBoolean(5),
|
|
258
|
-
allowDuplicates = options.requiredBoolean(2)
|
|
259
|
+
allowDuplicates = options.requiredBoolean(2),
|
|
260
|
+
deviceAddresses = options.optionalStringList(6).toTypedArray()
|
|
259
261
|
)
|
|
260
262
|
emitSuccess(command, "scanStarted")
|
|
261
263
|
} catch (error: Exception) {
|
|
@@ -765,7 +767,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
765
767
|
private fun emitSuccess(command: ProtocolWireRecord, kind: String, additions: Map<Int, ProtocolWireValue> = emptyMap()) {
|
|
766
768
|
if (!isPending(command)) return
|
|
767
769
|
val fields = mutableMapOf<Int, ProtocolWireValue>(
|
|
768
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
770
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
769
771
|
2 to ProtocolWireValue.StringValue(kind),
|
|
770
772
|
3 to ProtocolWireValue.RecordValue(terminal(command, "succeeded"))
|
|
771
773
|
)
|
|
@@ -797,7 +799,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
797
799
|
val result = ProtocolWireRecord(
|
|
798
800
|
RecordKind.RESULT,
|
|
799
801
|
mapOf(
|
|
800
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
802
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
801
803
|
2 to ProtocolWireValue.StringValue(dispatcherResultKindFor(command.requiredString(3))),
|
|
802
804
|
3 to ProtocolWireValue.RecordValue(terminal(command, "failed", code)),
|
|
803
805
|
10 to ProtocolWireValue.RecordValue(error)
|
|
@@ -813,7 +815,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
813
815
|
val result = ProtocolWireRecord(
|
|
814
816
|
RecordKind.RESULT,
|
|
815
817
|
mapOf(
|
|
816
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
818
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
817
819
|
2 to ProtocolWireValue.StringValue("cancelled"),
|
|
818
820
|
3 to ProtocolWireValue.RecordValue(terminal(command, "failed", "cancelled")),
|
|
819
821
|
10 to ProtocolWireValue.RecordValue(
|
|
@@ -840,7 +842,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
840
842
|
val result = ProtocolWireRecord(
|
|
841
843
|
RecordKind.RESULT,
|
|
842
844
|
mapOf(
|
|
843
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
845
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
844
846
|
2 to ProtocolWireValue.StringValue("cancelled"),
|
|
845
847
|
3 to ProtocolWireValue.RecordValue(terminal(command, "succeeded")),
|
|
846
848
|
8 to ProtocolWireValue.StringValue(state)
|
|
@@ -865,7 +867,7 @@ class UnifiedBleProtocolAndroidDispatcher(
|
|
|
865
867
|
val event = ProtocolWireRecord(
|
|
866
868
|
RecordKind.EVENT,
|
|
867
869
|
mapOf(
|
|
868
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
870
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
869
871
|
2 to ProtocolWireValue.StringValue("native-security-state-${SystemClock.elapsedRealtimeNanos()}"),
|
|
870
872
|
3 to ProtocolWireValue.StringValue("securityStateChanged"),
|
|
871
873
|
4 to ProtocolWireValue.RecordValue(attachment),
|
|
@@ -1111,7 +1113,7 @@ internal fun connectionLostEvent(
|
|
|
1111
1113
|
return ProtocolWireRecord(
|
|
1112
1114
|
RecordKind.EVENT,
|
|
1113
1115
|
mapOf(
|
|
1114
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
1116
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
1115
1117
|
2 to ProtocolWireValue.StringValue("native-connection-lost-$nativeHandle-$ingressOrdinal"),
|
|
1116
1118
|
3 to ProtocolWireValue.StringValue("connectionLost"),
|
|
1117
1119
|
4 to ProtocolWireValue.RecordValue(connection.requiredRecord(1)),
|
|
@@ -1133,7 +1135,7 @@ internal fun databaseChangedEvent(
|
|
|
1133
1135
|
return ProtocolWireRecord(
|
|
1134
1136
|
RecordKind.EVENT,
|
|
1135
1137
|
mapOf(
|
|
1136
|
-
1 to ProtocolWireValue.UnsignedIntegerValue(
|
|
1138
|
+
1 to ProtocolWireValue.UnsignedIntegerValue(NATIVE_PROTOCOL_VERSION.toLong()),
|
|
1137
1139
|
2 to ProtocolWireValue.StringValue("native-database-changed-$nativeHandle-$ingressOrdinal"),
|
|
1138
1140
|
3 to ProtocolWireValue.StringValue("databaseChanged"),
|
|
1139
1141
|
4 to ProtocolWireValue.RecordValue(attachment),
|
|
@@ -1180,6 +1182,11 @@ private fun ProtocolWireRecord.requiredStringList(fieldId: Int): List<String> {
|
|
|
1180
1182
|
return if (value is ProtocolWireValue.StringListValue) value.value else throw IllegalArgumentException("String list field is missing")
|
|
1181
1183
|
}
|
|
1182
1184
|
|
|
1185
|
+
private fun ProtocolWireRecord.optionalStringList(fieldId: Int): List<String> {
|
|
1186
|
+
val value = fields[fieldId] ?: return emptyList()
|
|
1187
|
+
return if (value is ProtocolWireValue.StringListValue) value.value else throw IllegalArgumentException("String list field is malformed")
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1183
1190
|
private fun Boolean?.toNativeConnectableState(): Int = when (this) {
|
|
1184
1191
|
true -> 1
|
|
1185
1192
|
false -> 0
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
package com.sfourdrinier.unifiedblemanager.protocol.generated
|
|
4
4
|
|
|
5
5
|
const val NATIVE_PROTOCOL_VERSION: Int = 2
|
|
6
|
-
const val NATIVE_PROTOCOL_ABI_VERSION: Int =
|
|
6
|
+
const val NATIVE_PROTOCOL_ABI_VERSION: Int = 4
|
|
7
7
|
const val NATIVE_PROTOCOL_CONTROL_SURFACE_VERSION: Int = 2
|
|
8
8
|
const val MAXIMUM_CONTROL_RECORD_BYTES: Int = 262144
|
|
9
9
|
const val MAXIMUM_BINARY_PAYLOAD_BYTES: Int = 524288
|
|
@@ -223,6 +223,7 @@ val NATIVE_PROTOCOL_FIELDS: List<FieldDescriptor> = listOf(
|
|
|
223
223
|
FieldDescriptor(RecordKind.SCAN_OPTIONS, 3, "scanMode", "int64", true),
|
|
224
224
|
FieldDescriptor(RecordKind.SCAN_OPTIONS, 4, "callbackType", "int64", true),
|
|
225
225
|
FieldDescriptor(RecordKind.SCAN_OPTIONS, 5, "legacyScan", "boolean", true),
|
|
226
|
+
FieldDescriptor(RecordKind.SCAN_OPTIONS, 6, "deviceAddresses", "strings", false),
|
|
226
227
|
FieldDescriptor(RecordKind.ADAPTER_STATE_SNAPSHOT, 1, "availability", "enum:adapterAvailability", true),
|
|
227
228
|
FieldDescriptor(RecordKind.ADAPTER_STATE_SNAPSHOT, 2, "authorization", "enum:adapterAuthorization", true),
|
|
228
229
|
FieldDescriptor(RecordKind.ADAPTER_STATE_SNAPSHOT, 3, "power", "enum:adapterPower", true),
|
package/android/src/main/java/com/sfourdrinier/unifiedblemanager/radio/OwnedAndroidGattRadio.kt
CHANGED
|
@@ -394,8 +394,16 @@ class OwnedAndroidGattRadio(private val context: Context) {
|
|
|
394
394
|
scanMode: Int,
|
|
395
395
|
callbackType: Int = ScanSettings.CALLBACK_TYPE_ALL_MATCHES,
|
|
396
396
|
legacyScan: Boolean = true,
|
|
397
|
-
allowDuplicates: Boolean = true
|
|
397
|
+
allowDuplicates: Boolean = true,
|
|
398
|
+
deviceAddresses: Array<out String> = emptyArray()
|
|
398
399
|
) {
|
|
400
|
+
// ScanSettings.Builder.setLegacy exists only on API 26+; below that the
|
|
401
|
+
// platform can only run a legacy scan, so accepting legacyScan=false would
|
|
402
|
+
// silently ignore the caller's extended-advertising request. Fail closed
|
|
403
|
+
// before any scan state is touched.
|
|
404
|
+
require(legacyScan || Build.VERSION.SDK_INT >= 26) {
|
|
405
|
+
"legacyScan=false requires ScanSettings.Builder.setLegacy (API 26+); this device cannot honour it"
|
|
406
|
+
}
|
|
399
407
|
val normalizedServiceUuids = normalizeScanServiceUuids(serviceUuids?.toList() ?: emptyList())
|
|
400
408
|
check(scanCallback == null) { "Android scan cleanup is still owned by a prior scan" }
|
|
401
409
|
scanSeenDeviceIds.clear()
|
|
@@ -404,6 +412,7 @@ class OwnedAndroidGattRadio(private val context: Context) {
|
|
|
404
412
|
val builder = ScanSettings.Builder()
|
|
405
413
|
.setScanMode(
|
|
406
414
|
when (scanMode) {
|
|
415
|
+
-1 -> ScanSettings.SCAN_MODE_OPPORTUNISTIC
|
|
407
416
|
0 -> ScanSettings.SCAN_MODE_LOW_POWER
|
|
408
417
|
1 -> ScanSettings.SCAN_MODE_BALANCED
|
|
409
418
|
2 -> ScanSettings.SCAN_MODE_LOW_LATENCY
|
|
@@ -417,8 +426,26 @@ class OwnedAndroidGattRadio(private val context: Context) {
|
|
|
417
426
|
}
|
|
418
427
|
val settings = builder.build()
|
|
419
428
|
val filters = mutableListOf<ScanFilter>()
|
|
420
|
-
|
|
421
|
-
|
|
429
|
+
val normalizedAddresses = deviceAddresses.map { it.uppercase() }.distinct()
|
|
430
|
+
if (normalizedAddresses.isEmpty()) {
|
|
431
|
+
normalizedServiceUuids.forEach { uuid ->
|
|
432
|
+
filters.add(ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(uuid)).build())
|
|
433
|
+
}
|
|
434
|
+
} else if (normalizedServiceUuids.isEmpty()) {
|
|
435
|
+
normalizedAddresses.forEach { address ->
|
|
436
|
+
filters.add(ScanFilter.Builder().setDeviceAddress(address).build())
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
normalizedAddresses.forEach { address ->
|
|
440
|
+
normalizedServiceUuids.forEach { uuid ->
|
|
441
|
+
filters.add(
|
|
442
|
+
ScanFilter.Builder()
|
|
443
|
+
.setDeviceAddress(address)
|
|
444
|
+
.setServiceUuid(ParcelUuid.fromString(uuid))
|
|
445
|
+
.build()
|
|
446
|
+
)
|
|
447
|
+
}
|
|
448
|
+
}
|
|
422
449
|
}
|
|
423
450
|
val cb = object : ScanCallback() {
|
|
424
451
|
override fun onScanResult(callbackType: Int, result: AndroidScanResult) {
|
|
@@ -67,6 +67,10 @@ struct JsiEventSinkState final {
|
|
|
67
67
|
protocol::AndroidIngressOrdinalAllocator ingressOrdinalAllocator{1U};
|
|
68
68
|
protocol::AndroidJsiBinaryCleanupLedger binaryCleanupLedger{
|
|
69
69
|
kMaximumBinaryCleanupReferences};
|
|
70
|
+
// A record the codec refuses never reaches JavaScript, so nothing downstream
|
|
71
|
+
// can count it. The tally lives here so the diagnostic that replaces the
|
|
72
|
+
// dropped record can say how many have been lost on this attachment.
|
|
73
|
+
std::atomic<std::uint64_t> quarantinedRecords{0U};
|
|
70
74
|
};
|
|
71
75
|
|
|
72
76
|
std::mutex eventSinkStatesMutex;
|
|
@@ -1339,6 +1343,30 @@ bool deliverNativeResult(
|
|
|
1339
1343
|
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
1340
1344
|
const protocol::ProtocolRecord& result);
|
|
1341
1345
|
|
|
1346
|
+
bool deliverNativeEvent(
|
|
1347
|
+
const std::shared_ptr<JsiEventSinkState>& state,
|
|
1348
|
+
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
1349
|
+
const protocol::ProtocolRecord& event);
|
|
1350
|
+
|
|
1351
|
+
protocol::ProtocolRecord diagnosticEvent(
|
|
1352
|
+
jlong nativeHandle,
|
|
1353
|
+
const std::shared_ptr<JsiEventSinkState>& state,
|
|
1354
|
+
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
1355
|
+
const std::string& code,
|
|
1356
|
+
const std::string& message);
|
|
1357
|
+
|
|
1358
|
+
// Report a record the codec refused. The dropped record cannot be recovered --
|
|
1359
|
+
// it is malformed by definition -- but the application is entitled to learn
|
|
1360
|
+
// that the boundary discarded something it was asked to deliver, which a
|
|
1361
|
+
// logcat line alone does not tell it. The diagnostic is built natively, so it
|
|
1362
|
+
// carries a correct version stamp and survives the validation that the
|
|
1363
|
+
// quarantined record failed.
|
|
1364
|
+
void reportQuarantinedRecord(
|
|
1365
|
+
jlong nativeHandle,
|
|
1366
|
+
const std::shared_ptr<JsiEventSinkState>& state,
|
|
1367
|
+
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
1368
|
+
const char* reason);
|
|
1369
|
+
|
|
1342
1370
|
bool emitRecordFromJava(JNIEnv* environment, jlong nativeHandle, jbyteArray encodedRecord) {
|
|
1343
1371
|
if (encodedRecord == nullptr) {
|
|
1344
1372
|
return false;
|
|
@@ -1403,6 +1431,7 @@ bool emitRecordFromJava(JNIEnv* environment, jlong nativeHandle, jbyteArray enco
|
|
|
1403
1431
|
"UnifiedBleProtocol",
|
|
1404
1432
|
"emitRecordNative quarantined invalid Android record: %s",
|
|
1405
1433
|
error.what());
|
|
1434
|
+
reportQuarantinedRecord(nativeHandle, state, activeRuntime, error.what());
|
|
1406
1435
|
if (decodedRecord.has_value() && decodedRecord->kind == protocol::RecordKind::result) {
|
|
1407
1436
|
requestFatalAttachment(
|
|
1408
1437
|
state,
|
|
@@ -1412,6 +1441,43 @@ bool emitRecordFromJava(JNIEnv* environment, jlong nativeHandle, jbyteArray enco
|
|
|
1412
1441
|
}
|
|
1413
1442
|
}
|
|
1414
1443
|
|
|
1444
|
+
void reportQuarantinedRecord(
|
|
1445
|
+
jlong nativeHandle,
|
|
1446
|
+
const std::shared_ptr<JsiEventSinkState>& state,
|
|
1447
|
+
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
1448
|
+
const char* reason) {
|
|
1449
|
+
const auto quarantined = state->quarantinedRecords.fetch_add(1U) + 1U;
|
|
1450
|
+
try {
|
|
1451
|
+
if (!deliverNativeEvent(
|
|
1452
|
+
state,
|
|
1453
|
+
activeRuntime,
|
|
1454
|
+
diagnosticEvent(
|
|
1455
|
+
nativeHandle,
|
|
1456
|
+
state,
|
|
1457
|
+
activeRuntime,
|
|
1458
|
+
"recordQuarantined",
|
|
1459
|
+
std::string("Android record was quarantined and not delivered (") +
|
|
1460
|
+
std::to_string(quarantined) + " on this attachment): " +
|
|
1461
|
+
(reason == nullptr ? "unknown error" : reason)))) {
|
|
1462
|
+
__android_log_print(
|
|
1463
|
+
ANDROID_LOG_ERROR,
|
|
1464
|
+
"UnifiedBleProtocol",
|
|
1465
|
+
"Android quarantine diagnostic was rejected handle=%lld quarantined=%llu",
|
|
1466
|
+
static_cast<long long>(nativeHandle),
|
|
1467
|
+
static_cast<unsigned long long>(quarantined));
|
|
1468
|
+
}
|
|
1469
|
+
} catch (const std::exception& error) {
|
|
1470
|
+
// The quarantine path is already the failure path; a diagnostic that cannot
|
|
1471
|
+
// be built must not replace the original record's failure with its own.
|
|
1472
|
+
__android_log_print(
|
|
1473
|
+
ANDROID_LOG_ERROR,
|
|
1474
|
+
"UnifiedBleProtocol",
|
|
1475
|
+
"Android quarantine diagnostic could not be built handle=%lld: %s",
|
|
1476
|
+
static_cast<long long>(nativeHandle),
|
|
1477
|
+
error.what());
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1415
1481
|
bool deliverNativeResult(
|
|
1416
1482
|
const std::shared_ptr<JsiEventSinkState>& state,
|
|
1417
1483
|
const std::shared_ptr<protocol::NativeProtocolControlRuntime>& activeRuntime,
|
|
@@ -231,6 +231,23 @@ class UnifiedBleProtocolAndroidFindingsTest {
|
|
|
231
231
|
assertTrue(Regex("return device.getAddress\\(\\)").containsMatchIn(addressProjection))
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
// Regression guard for issue #140: the dispatcher stamped a literal 1 on
|
|
235
|
+
// field 1 of every control-plane record while the codec required 2, so every
|
|
236
|
+
// result it emitted -- including the one describing a failed connect -- was
|
|
237
|
+
// quarantined by the native codec and never reached JavaScript. The stamp has
|
|
238
|
+
// to follow the generated schema, not a number typed next to the field id.
|
|
239
|
+
@Test
|
|
240
|
+
fun `dispatcher records stamp the generated protocol version`() {
|
|
241
|
+
val source = readAndroidSource(
|
|
242
|
+
"android/src/main/java/com/sfourdrinier/unifiedblemanager/protocol/UnifiedBleProtocolAndroidDispatcher.kt"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
assertTrue(source.contains("import com.sfourdrinier.unifiedblemanager.protocol.generated.NATIVE_PROTOCOL_VERSION"))
|
|
246
|
+
val stamps = Regex("""\n\s*1 to ProtocolWireValue\.UnsignedIntegerValue\((.+)\),""").findAll(source).toList()
|
|
247
|
+
assertTrue(stamps.isNotEmpty())
|
|
248
|
+
assertTrue(stamps.all { it.groupValues[1] == "NATIVE_PROTOCOL_VERSION.toLong()" })
|
|
249
|
+
}
|
|
250
|
+
|
|
234
251
|
private fun readAndroidSource(relativePath: String): String {
|
|
235
252
|
val candidates = listOf(
|
|
236
253
|
File(relativePath),
|
|
@@ -23,10 +23,22 @@ normative behavioral authority.
|
|
|
23
23
|
## Contract shape and version skew
|
|
24
24
|
|
|
25
25
|
`BackendProvider` reports loadability, lists adapters, requires a stable
|
|
26
|
-
host-scoped adapter selection
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
host-scoped adapter selection, and creates one backend bound to that adapter.
|
|
27
|
+
Loadability, adapter presence, adapter power, and authorization are different
|
|
28
|
+
states. The low-level provider never silently substitutes a different adapter:
|
|
29
|
+
a named selection that is absent or stale fails `adapter.unavailable`.
|
|
30
|
+
|
|
31
|
+
Choosing a *default* adapter when the caller names none is an ergonomics
|
|
32
|
+
concern that belongs one layer up, not in the provider. The Node convenience
|
|
33
|
+
factories (`createBluezBleManager` and its siblings) select the first adapter,
|
|
34
|
+
ordered deterministically by id, so the common single-adapter machine needs no
|
|
35
|
+
configuration and a multi-adapter host still picks the same controller every
|
|
36
|
+
run; a caller targets a specific controller by passing `adapterId`. This
|
|
37
|
+
supersedes the earlier stance that ambiguous selection must fail: forcing every
|
|
38
|
+
caller to name an adapter is poor ergonomics for the common case. The
|
|
39
|
+
`adapter.selection-required` / `adapter.ambiguous` codes remain in the taxonomy
|
|
40
|
+
for a provider that genuinely cannot pick, but the first-party host factories do
|
|
41
|
+
not push that choice onto the caller.
|
|
30
42
|
|
|
31
43
|
`BleCentralBackend` owns these required components:
|
|
32
44
|
|