Feature: Bluetooth device enumeration#3255
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
🚧 Files skipped from review as they are similar to previous changes (9)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
🔇 Additional comments (1)
📝 WalkthroughWalkthroughAdds a public BluetoothDevice API and AbstractBluetoothDevice implementation, platform enumerators for Linux/Windows/macOS (Windows via JNA and FFM), HAL wiring, MAC-format utilities, printing/cgroup reporting, unit/integration tests, and documentation updates. ChangesBluetooth Device Enumeration
Sequence Diagram(s)sequenceDiagram
participant SystemInfo
participant HAL as HardwareAbstractionLayer
participant PlatformEnum as PlatformEnumerator
participant NativeFS as FileSystem/NativeAPI
SystemInfo->>HAL: getBluetoothDevices()
HAL->>PlatformEnum: getBluetoothDevices()
PlatformEnum->>NativeFS: enumerate adapters / query native API
NativeFS-->>PlatformEnum: adapter/device info
PlatformEnum->>HAL: List<BluetoothDevice>
HAL-->>SystemInfo: List<BluetoothDevice>
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java (1)
35-43: ⚡ Quick winEnforce the battery-level contract in the base constructor.
BluetoothDevice#getBatteryLevel()documents-1or0..100, but Line 42 currently stores raw input unchanged. Normalizing here prevents invalid values from leaking through any platform implementation.Proposed change
protected AbstractBluetoothDevice(String name, String address, String majorDeviceClass, boolean connected, boolean paired, int batteryLevel, String adapterName) { this.name = name; this.address = address; this.majorDeviceClass = majorDeviceClass; this.connected = connected; this.paired = paired; - this.batteryLevel = batteryLevel; + this.batteryLevel = batteryLevel < 0 ? -1 : Math.min(100, batteryLevel); this.adapterName = adapterName; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java` around lines 35 - 43, The constructor AbstractBluetoothDevice(String name, String address, String majorDeviceClass, boolean connected, boolean paired, int batteryLevel, String adapterName) should normalize the batteryLevel per BluetoothDevice#getBatteryLevel() contract (allowed values: -1 or 0..100) before storing it: if batteryLevel == -1 keep it, if batteryLevel < -1 set to -1, if batteryLevel > 100 clamp to 100, otherwise accept 0..100; then assign the normalized value to the batteryLevel field (so all platform implementations go through this validation).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java`:
- Around line 96-101: The paired-state for discovered BlueZ device dirs is
currently derived with boolean paired = "true".equals(props.get("Paired")),
which yields false when the Paired key is absent; update the logic in
LinuxBluetoothDevice (around the props / paired variables) to treat a missing
"Paired" key as paired when the device entry was discovered from the
paired-device listing: change to something like checking
props.containsKey("Paired") ? "true".equals(props.get("Paired")) : true so that
absence of the key preserves paired=true for devices enumerated from the
paired-device path while leaving explicit Paired values unchanged.
---
Nitpick comments:
In `@oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java`:
- Around line 35-43: The constructor AbstractBluetoothDevice(String name, String
address, String majorDeviceClass, boolean connected, boolean paired, int
batteryLevel, String adapterName) should normalize the batteryLevel per
BluetoothDevice#getBatteryLevel() contract (allowed values: -1 or 0..100) before
storing it: if batteryLevel == -1 keep it, if batteryLevel < -1 set to -1, if
batteryLevel > 100 clamp to 100, otherwise accept 0..100; then assign the
normalized value to the batteryLevel field (so all platform implementations go
through this validation).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b5d152b8-b646-47ab-b324-45691f294e1b
📒 Files selected for processing (5)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Test JDK 11, windows-latest
- GitHub Check: Test JDK 25, ubuntu-latest (+ JNA==FFM)
- GitHub Check: Test JDK 11, macos-latest
- GitHub Check: Test JDK 21, windows-latest
- GitHub Check: Test JDK 21, macos-latest
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
- GitHub Check: Analyze (java)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-04-12T19:22:09.716Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3149
File: oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacCentralProcessor.java:159-163
Timestamp: 2026-04-12T19:22:09.716Z
Learning: When reviewing OSHI hardware platform code that uses or implements `CentralProcessor`/`PhysicalProcessor.getEfficiency()`, remember the API’s counterintuitive semantics: a *higher* efficiency-class value indicates *greater performance* (lower efficiency). P-cores/“performance cores” should therefore have higher values (e.g., 1) than E-cores/“efficiency cores” (e.g., 0), as documented in the `CentralProcessor` Javadoc. Do not flag code as incorrect solely because ARM_P_CORES or Intel P-cores are assigned higher efficiency values.
Applied to files:
oshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.java
🔇 Additional comments (3)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java (1)
17-71: LGTM!oshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.java (1)
165-173: LGTM!oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.java (1)
65-68: LGTM!
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #3255 +/- ##
============================================
- Coverage 74.83% 74.15% -0.68%
Complexity 73 73
============================================
Files 391 396 +5
Lines 15814 16096 +282
Branches 2541 2589 +48
============================================
+ Hits 11834 11936 +102
- Misses 2484 2639 +155
- Partials 1496 1521 +25
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Adds Bluetooth device enumeration (issue oshi#3253): - BluetoothDevice interface in oshi-common with name, address, major device class, connected/paired status, battery level - AbstractBluetoothDevice base class - Linux implementation reading from /sys/class/bluetooth/ and /var/lib/bluetooth/ (BlueZ) - HardwareAbstractionLayer.getBluetoothDevices() default method - Wired into LinuxHardwareAbstractionLayer (shared by JNA/FFM/NF)
- LinuxBluetoothDeviceTest: covers sysfs parsing, paired-state defaults, battery level, device class parsing, fallback paths - AbstractBluetoothDeviceTest: covers getters, toString, battery normalization - SystemInfoHelper: add printBluetoothDevices(), add CgroupInfo to printOperatingSystem() - oshi-core SystemInfoTest: replace duplicated print methods with static imports from SystemInfoHelper - All SystemInfoTest variants: add Bluetooth device output after USB
a88667c to
cac243b
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java`:
- Around line 95-117: The parseMajorDeviceClass method currently returns an
empty string for major CoD values 0 and 31; update the switch in
parseMajorDeviceClass(int cod) to explicitly handle case 0 and case 31,
returning "Miscellaneous" for 0 and "Uncategorized" (or equivalent canonical
label) for 31, keeping all other existing cases unchanged so valid
classifications are preserved.
In
`@oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java`:
- Around line 130-138: The paired boolean is derived only from fAuthenticated
which misses devices returned as remembered-only; update the logic in
WindowsBluetoothDeviceFFM where paired is computed (the local variable paired
set from fAuthenticated) to consider either flag by using fRemembered ||
fAuthenticated when reading from BLUETOOTH_DEVICE_INFO_LAYOUT (same area that
reads fConnected and szName), so the WindowsBluetoothDeviceFFM constructor
receives paired=true for remembered or authenticated devices.
In
`@oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java`:
- Around line 103-105: The paired flag is currently set using only
info.fAuthenticated which misses remembered-but-not-authenticated devices;
update the logic in the method that builds the device object (where boolean
paired = info.fAuthenticated and the return new WindowsBluetoothDeviceJNA(...))
to set paired = info.fRemembered || info.fAuthenticated; apply the same fix in
the analogous code path in WindowsBluetoothDeviceFFM (where the device is
constructed there) so remembered devices are reported as paired.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 08b932fa-d002-4397-8b08-81dab5fb557b
📒 Files selected for processing (9)
oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.javaoshi-core-ffm/src/main/java/oshi/ffm/windows/BluetoothApisFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerFFM.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerJNA.javaoshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java
🚧 Files skipped from review as they are similar to previous changes (1)
- oshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Test JDK 21, macos-latest
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Test JDK 11, macos-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: Analyze (java)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-04-06T04:45:47.644Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3121
File: oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java:53-53
Timestamp: 2026-04-06T04:45:47.644Z
Learning: In the oshi/oshi project, only interfaces and classes in the root packages `oshi`, `oshi.hardware`, and `oshi.software.os` are considered the public API. Code in subpackages that represent specific implementations/platforms (e.g., `oshi.software.os.linux`, `oshi.hardware.platform.linux`, and similar subpackages) is implementation detail. When reviewing, do not treat changes to classes in these platform-specific subpackages as public API breaks (for example: making `LinuxOperatingSystem` abstract, narrowing constructor visibility, or adding/removing abstract methods should not be flagged as breaking public API).
Applied to files:
oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerJNA.java
📚 Learning: 2026-04-12T19:22:09.716Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3149
File: oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacCentralProcessor.java:159-163
Timestamp: 2026-04-12T19:22:09.716Z
Learning: When reviewing OSHI hardware platform code that uses or implements `CentralProcessor`/`PhysicalProcessor.getEfficiency()`, remember the API’s counterintuitive semantics: a *higher* efficiency-class value indicates *greater performance* (lower efficiency). P-cores/“performance cores” should therefore have higher values (e.g., 1) than E-cores/“efficiency cores” (e.g., 0), as documented in the `CentralProcessor` Javadoc. Do not flag code as incorrect solely because ARM_P_CORES or Intel P-cores are assigned higher efficiency values.
Applied to files:
oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java
🔇 Additional comments (4)
oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java (1)
35-85: LGTM!oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java (1)
54-111: LGTM!oshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java (1)
21-21: Verify the JNA binding loads the exported module.Microsoft documents these entry points in
bthprops.cpl, while JNA'sNative.load(String, ...)treats its argument as the library base name. Please verify"bthprops"resolves correctly on supported Windows builds, or loadbthprops.cplexplicitly here. (learn.microsoft.com)oshi-core-ffm/src/main/java/oshi/ffm/windows/BluetoothApisFFM.java (1)
28-28: Verify the FFM lookup targets the actual exporting module.These APIs are documented as exports from
bthprops.cpl. Please confirmlib("bthprops")resolves that module on supported Windows builds before relying on this binding. (learn.microsoft.com)
- BluetoothApis JNA interface for bthprops.cpl with struct mappings - WindowsBluetoothDeviceJNA using BluetoothFindFirst/NextDevice - BluetoothApisFFM with FFM struct layouts and method handles - WindowsBluetoothDeviceFFM using Foreign Function API - Move parseMajorDeviceClass() to AbstractBluetoothDevice (shared) - Wire into both Windows HAL variants
- MacBluetoothDeviceJNA: IOKit IOBluetoothDevice registry enumeration - MacBluetoothDeviceFFM: same via FFM IOKit bindings - Wire into both macOS HAL variants - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
4343d4d to
92af33e
Compare
- MacBluetoothDeviceJNA: IOKit IOBluetoothDevice registry enumeration - MacBluetoothDeviceFFM: same via FFM IOKit bindings - Wire into both macOS HAL variants - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
92af33e to
0aa2a61
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@oshi-common/src/main/java/oshi/util/FormatUtil.java`:
- Around line 244-251: The formatMacAddress method currently only checks
cleaned.length() == 12 before formatting; update formatMacAddress to validate
that all 12 characters are valid hexadecimal digits (e.g., match cleaned against
a hex regex like "[0-9A-Fa-f]{12}" or verify each char with Character.digit) and
only perform the colon-insert formatting when that validation passes; if
validation fails, fall back to returning raw.toUpperCase(Locale.ROOT) as before.
Ensure you reference the method name formatMacAddress and keep the existing
cleaning (replace("-", "").replace(":", "").trim()) logic.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 65f6f394-3aa4-407c-8558-4f61bb53baab
📒 Files selected for processing (8)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/test/java/oshi/util/FormatUtilTest.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
- oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java
- oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java
- oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Test JDK 21, macos-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: Analyze (java)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-04-12T19:22:09.716Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3149
File: oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacCentralProcessor.java:159-163
Timestamp: 2026-04-12T19:22:09.716Z
Learning: When reviewing OSHI hardware platform code that uses or implements `CentralProcessor`/`PhysicalProcessor.getEfficiency()`, remember the API’s counterintuitive semantics: a *higher* efficiency-class value indicates *greater performance* (lower efficiency). P-cores/“performance cores” should therefore have higher values (e.g., 1) than E-cores/“efficiency cores” (e.g., 0), as documented in the `CentralProcessor` Javadoc. Do not flag code as incorrect solely because ARM_P_CORES or Intel P-cores are assigned higher efficiency values.
Applied to files:
oshi-common/src/main/java/oshi/util/FormatUtil.java
📚 Learning: 2026-04-06T04:45:47.644Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3121
File: oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java:53-53
Timestamp: 2026-04-06T04:45:47.644Z
Learning: In the oshi/oshi project, only interfaces and classes in the root packages `oshi`, `oshi.hardware`, and `oshi.software.os` are considered the public API. Code in subpackages that represent specific implementations/platforms (e.g., `oshi.software.os.linux`, `oshi.hardware.platform.linux`, and similar subpackages) is implementation detail. When reviewing, do not treat changes to classes in these platform-specific subpackages as public API breaks (for example: making `LinuxOperatingSystem` abstract, narrowing constructor visibility, or adding/removing abstract methods should not be flagged as breaking public API).
Applied to files:
oshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.java
🔇 Additional comments (5)
oshi-common/src/main/java/oshi/util/FormatUtil.java (1)
225-235: LGTM!oshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java (1)
23-37: LGTM!oshi-common/src/test/java/oshi/util/FormatUtilTest.java (1)
160-165: LGTM!Also applies to: 167-173
oshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.java (1)
38-70: LGTM!oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.java (1)
37-69: LGTM!
4834e4f to
30022b7
Compare
|
@CodeRabbit full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
oshi-common/src/test/java/oshi/util/FormatUtilTest.java (1)
167-173: ⚡ Quick winAdd a regression case for 12-character non-hex input.
This path is now validation-sensitive (
isHex) and worth pinning with one explicit negative-case test.Suggested test addition
`@Test` void testFormatMacAddressFromString() { assertThat(FormatUtil.formatMacAddress("aa-bb-cc-dd-ee-ff"), is("AA:BB:CC:DD:EE:FF")); assertThat(FormatUtil.formatMacAddress("11:22:33:44:55:66"), is("11:22:33:44:55:66")); assertThat(FormatUtil.formatMacAddress("aabbccddeeff"), is("AA:BB:CC:DD:EE:FF")); + assertThat(FormatUtil.formatMacAddress("zzzzzzzzzzzz"), is("ZZZZZZZZZZZZ")); assertThat(FormatUtil.formatMacAddress("abcd"), is("ABCD")); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@oshi-common/src/test/java/oshi/util/FormatUtilTest.java` around lines 167 - 173, Add a negative regression test to FormatUtilTest that covers a 12-character non-hex input so the validation-sensitive path in FormatUtil.formatMacAddress is pinned; specifically, in the testFormatMacAddressFromString method add an assertion calling FormatUtil.formatMacAddress with a 12-character non-hex string (e.g., "abcdefghijkl") and assert the method returns the uppercased input (e.g., "ABCDEFGHIJKL"), referencing the FormatUtil.formatMacAddress call in FormatUtilTest.oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.java (1)
37-70: ⚡ Quick winConsider adding try-finally for native resource cleanup.
If an exception occurs during property extraction (lines 45-62), neither the current
devicenoriterwill be released, potentially leaking native IOKit handles.While IOKit property accessors typically return null rather than throw, wrapping in try-finally ensures robustness against unexpected failures.
♻️ Proposed defensive resource handling
public static List<BluetoothDevice> getBluetoothDevices() { List<BluetoothDevice> devices = new ArrayList<>(); IOIterator iter = IOKitUtilFFM.getMatchingServices(IO_BLUETOOTH_DEVICE); if (iter == null) { return Collections.emptyList(); } - IORegistryEntry device = iter.next(); - while (device != null) { - String name = device.getStringProperty("Name"); - if (name == null) { - name = device.getName(); - } - String address = device.getStringProperty("DeviceAddress"); - if (address == null) { - address = ""; - } else { - address = FormatUtil.formatMacAddress(address); + try { + IORegistryEntry device = iter.next(); + while (device != null) { + try { + String name = device.getStringProperty("Name"); + if (name == null) { + name = device.getName(); + } + String address = device.getStringProperty("DeviceAddress"); + if (address == null) { + address = ""; + } else { + address = FormatUtil.formatMacAddress(address); + } + Long cod = device.getLongProperty("ClassOfDevice"); + String majorClass = parseMajorDeviceClass(cod != null ? cod.intValue() : 0); + Long connectedVal = device.getLongProperty("Connected"); + boolean connected = connectedVal != null && connectedVal != 0; + Long pairedVal = device.getLongProperty("Paired"); + boolean paired = pairedVal != null && pairedVal != 0; + Long batteryVal = device.getLongProperty("BatteryPercent"); + int batteryLevel = batteryVal != null ? batteryVal.intValue() : -1; + + devices.add(new MacBluetoothDeviceFFM(name, address, majorClass, connected, paired, batteryLevel, "")); + } finally { + device.release(); + } + device = iter.next(); } - Long cod = device.getLongProperty("ClassOfDevice"); - String majorClass = parseMajorDeviceClass(cod != null ? cod.intValue() : 0); - Long connectedVal = device.getLongProperty("Connected"); - boolean connected = connectedVal != null && connectedVal != 0; - Long pairedVal = device.getLongProperty("Paired"); - boolean paired = pairedVal != null && pairedVal != 0; - Long batteryVal = device.getLongProperty("BatteryPercent"); - int batteryLevel = batteryVal != null ? batteryVal.intValue() : -1; - - devices.add(new MacBluetoothDeviceFFM(name, address, majorClass, connected, paired, batteryLevel, "")); - device.release(); - device = iter.next(); + } finally { + iter.release(); } - iter.release(); return Collections.unmodifiableList(devices); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.java` around lines 37 - 70, The getBluetoothDevices method can leak native handles if an exception occurs while iterating properties; wrap use of IOIterator and the per-iteration IORegistryEntry in try/finally blocks so both the current IORegistryEntry (device) and the IOIterator (iter) are always released: after obtaining iter = IOKitUtilFFM.getMatchingServices(IO_BLUETOOTH_DEVICE) check for null as now, then use try { while (...) { IORegistryEntry device = iter.next(); try { ... devices.add(new MacBluetoothDeviceFFM(...)); } finally { if (device != null) device.release(); } } } finally { iter.release(); } to guarantee cleanup in getBluetoothDevices.oshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.java (1)
26-27: ⚡ Quick winRun these parsing tests on all OSes (remove Linux-only gate).
These tests are temp-dir fixture tests and don’t require Linux runtime APIs, so the OS restriction unnecessarily reduces coverage.
Suggested patch
-import org.junit.jupiter.api.condition.EnabledOnOs; -import org.junit.jupiter.api.condition.OS; @@ -@EnabledOnOs(OS.LINUX) class LinuxBluetoothDeviceTest {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@oshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.java` around lines 26 - 27, Remove the Linux-only test gate by deleting the `@EnabledOnOs`(OS.LINUX) annotation on the LinuxBluetoothDeviceTest class so the temp-dir parsing tests in class LinuxBluetoothDeviceTest run on all OSes; ensure no other OS-specific setup remains that would require Linux runtime APIs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java`:
- Around line 71-75: The code in LinuxBluetoothDevice that builds
adapterStateDir currently tries an uppercase address then falls back to the raw
adapterAddress, which misses lowercase-only directories; update the fallback to
use adapterAddress.toLowerCase(Locale.ROOT) so the second File construction
checks the lowercase path. Modify the File adapterStateDir creation logic in the
class/method where adapterAddress is used (replace new File(varLibPath +
adapterAddress) with new File(varLibPath +
adapterAddress.toLowerCase(Locale.ROOT))).
- Around line 88-90: The current directory-name filter in LinuxBluetoothDevice
uses only a colon presence and length check on dirName; tighten this by
validating dirName against a proper hex-MAC pattern (e.g. six hex octets
separated by colons) and skip entries that don't match. Update the conditional
that references dirName (in class LinuxBluetoothDevice / the directory
enumeration loop) to test against a regex or a byte-pair parsing routine
(pattern like two hex chars then : repeated 5 times) and continue when the
validation fails so malformed names like "GG:GG:..." are excluded.
---
Nitpick comments:
In
`@oshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.java`:
- Around line 26-27: Remove the Linux-only test gate by deleting the
`@EnabledOnOs`(OS.LINUX) annotation on the LinuxBluetoothDeviceTest class so the
temp-dir parsing tests in class LinuxBluetoothDeviceTest run on all OSes; ensure
no other OS-specific setup remains that would require Linux runtime APIs.
In `@oshi-common/src/test/java/oshi/util/FormatUtilTest.java`:
- Around line 167-173: Add a negative regression test to FormatUtilTest that
covers a 12-character non-hex input so the validation-sensitive path in
FormatUtil.formatMacAddress is pinned; specifically, in the
testFormatMacAddressFromString method add an assertion calling
FormatUtil.formatMacAddress with a 12-character non-hex string (e.g.,
"abcdefghijkl") and assert the method returns the uppercased input (e.g.,
"ABCDEFGHIJKL"), referencing the FormatUtil.formatMacAddress call in
FormatUtilTest.
In
`@oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.java`:
- Around line 37-70: The getBluetoothDevices method can leak native handles if
an exception occurs while iterating properties; wrap use of IOIterator and the
per-iteration IORegistryEntry in try/finally blocks so both the current
IORegistryEntry (device) and the IOIterator (iter) are always released: after
obtaining iter = IOKitUtilFFM.getMatchingServices(IO_BLUETOOTH_DEVICE) check for
null as now, then use try { while (...) { IORegistryEntry device = iter.next();
try { ... devices.add(new MacBluetoothDeviceFFM(...)); } finally { if (device !=
null) device.release(); } } } finally { iter.release(); } to guarantee cleanup
in getBluetoothDevices.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: ac790f30-ba36-4f6e-9350-2871b36bc246
📒 Files selected for processing (27)
CHANGELOG.mdREADME.mdoshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/main/java/oshi/util/SystemInfoHelper.javaoshi-common/src/test/java/oshi/hardware/common/AbstractBluetoothDeviceTest.javaoshi-common/src/test/java/oshi/hardware/common/platform/linux/LinuxBluetoothDeviceTest.javaoshi-common/src/test/java/oshi/nativefree/SystemInfoTest.javaoshi-common/src/test/java/oshi/util/FormatUtilTest.javaoshi-core-ffm/src/main/java/oshi/ffm/windows/BluetoothApisFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacHardwareAbstractionLayerFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerFFM.javaoshi-core-ffm/src/test/java/oshi/ffm/SystemInfoTest.javaoshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/mac/MacHardwareAbstractionLayerJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerJNA.javaoshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.javaoshi-core/src/test/java/oshi/SystemInfoTest.javaoshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.javasrc/site/markdown/index.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-04-12T19:22:09.716Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3149
File: oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacCentralProcessor.java:159-163
Timestamp: 2026-04-12T19:22:09.716Z
Learning: When reviewing OSHI hardware platform code that uses or implements `CentralProcessor`/`PhysicalProcessor.getEfficiency()`, remember the API’s counterintuitive semantics: a *higher* efficiency-class value indicates *greater performance* (lower efficiency). P-cores/“performance cores” should therefore have higher values (e.g., 1) than E-cores/“efficiency cores” (e.g., 0), as documented in the `CentralProcessor` Javadoc. Do not flag code as incorrect solely because ARM_P_CORES or Intel P-cores are assigned higher efficiency values.
Applied to files:
oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.javaoshi-common/src/main/java/oshi/util/SystemInfoHelper.javaoshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java
📚 Learning: 2026-04-06T04:45:47.644Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3121
File: oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java:53-53
Timestamp: 2026-04-06T04:45:47.644Z
Learning: In the oshi/oshi project, only interfaces and classes in the root packages `oshi`, `oshi.hardware`, and `oshi.software.os` are considered the public API. Code in subpackages that represent specific implementations/platforms (e.g., `oshi.software.os.linux`, `oshi.hardware.platform.linux`, and similar subpackages) is implementation detail. When reviewing, do not treat changes to classes in these platform-specific subpackages as public API breaks (for example: making `LinuxOperatingSystem` abstract, narrowing constructor visibility, or adding/removing abstract methods should not be flagged as breaking public API).
Applied to files:
oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerJNA.javaoshi-core/src/main/java/oshi/hardware/platform/mac/MacHardwareAbstractionLayerJNA.javaoshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java
🔇 Additional comments (26)
oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxHardwareAbstractionLayer.java (1)
11-11: LGTM!Also applies to: 65-68
oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacHardwareAbstractionLayerFFM.java (1)
11-11: LGTM!Also applies to: 82-85
oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerFFM.java (1)
10-10: LGTM!Also applies to: 98-101
oshi-core/src/main/java/oshi/hardware/platform/mac/MacHardwareAbstractionLayerJNA.java (1)
10-10: LGTM!Also applies to: 87-89
oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsHardwareAbstractionLayerJNA.java (1)
10-10: LGTM!Also applies to: 98-100
oshi-common/src/main/java/oshi/util/SystemInfoHelper.java (1)
16-16: LGTM!Also applies to: 37-37, 72-85, 481-496
oshi-common/src/test/java/oshi/hardware/common/AbstractBluetoothDeviceTest.java (1)
1-57: LGTM!oshi-common/src/test/java/oshi/nativefree/SystemInfoTest.java (1)
10-10: LGTM!Also applies to: 124-126
oshi-core-ffm/src/test/java/oshi/ffm/SystemInfoTest.java (1)
12-12: LGTM!Also applies to: 143-145
oshi-core/src/test/java/oshi/SystemInfoTest.java (1)
10-31: LGTM!Also applies to: 138-140
oshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java (1)
1-38: LGTM!CHANGELOG.md (1)
7-7: LGTM!README.md (1)
33-33: LGTM!src/site/markdown/index.md (1)
33-33: LGTM!oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java (1)
10-81: LGTM!oshi-common/src/main/java/oshi/hardware/HardwareAbstractionLayer.java (1)
165-173: LGTM!oshi-common/src/main/java/oshi/hardware/common/AbstractBluetoothDevice.java (1)
35-123: LGTM!oshi-common/src/main/java/oshi/util/FormatUtil.java (1)
225-262: LGTM!oshi-common/src/test/java/oshi/util/FormatUtilTest.java (1)
160-165: LGTM!oshi-core/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceJNA.java (2)
38-71: Same resource management consideration applies here.The same try-finally pattern suggested for the FFM variant would benefit this JNA implementation for defensive native handle cleanup.
1-31: LGTM!oshi-core-ffm/src/main/java/oshi/hardware/platform/mac/MacBluetoothDeviceFFM.java (1)
1-31: LGTM!oshi-core-ffm/src/main/java/oshi/ffm/windows/BluetoothApisFFM.java (1)
1-103: LGTM!oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java (1)
1-158: LGTM!oshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java (1)
1-202: LGTM!oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java (1)
1-114: LGTM!
30022b7 to
7fcaa55
Compare
- MacBluetoothDevice in oshi-common: parses system_profiler SPBluetoothDataType output for connected/not-connected devices - Shared by JNA/FFM HALs (no native calls needed) - Replaces IOKit IOBluetoothDevice approach which only found kernel-level objects, not user-space paired devices - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
7fcaa55 to
f3acf53
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.java`:
- Around line 60-70: When toggling section flags in MacBluetoothDevice (where
variables inConnected, inNotConnected, and inDevice are set), ensure the
currently accumulating device is persisted before clearing inDevice; i.e.,
before the blocks that handle trimmed.startsWith("Connected:") and
trimmed.startsWith("Not Connected:") (and their equals(...) variants), call the
same flush/add logic used when ending a device (the logic that stores the active
device into the device list) so the last device in the previous section is not
lost—update the code in MacBluetoothDevice.java to flush the active device prior
to setting inDevice = false and switching inConnected/inNotConnected.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1fe9fcc7-1c9b-4572-b705-ead93ad6f213
📒 Files selected for processing (10)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/test/java/oshi/util/FormatUtilTest.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.javaoshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
🚧 Files skipped from review as they are similar to previous changes (6)
- oshi-common/src/main/java/oshi/util/FormatUtil.java
- oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java
- oshi-common/src/test/java/oshi/util/FormatUtilTest.java
- oshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
- oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java
- oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Test JDK 21, macos-latest
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
- GitHub Check: Analyze (java)
- GitHub Check: Codacy Static Code Analysis
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-04-12T19:22:09.716Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3149
File: oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacCentralProcessor.java:159-163
Timestamp: 2026-04-12T19:22:09.716Z
Learning: When reviewing OSHI hardware platform code that uses or implements `CentralProcessor`/`PhysicalProcessor.getEfficiency()`, remember the API’s counterintuitive semantics: a *higher* efficiency-class value indicates *greater performance* (lower efficiency). P-cores/“performance cores” should therefore have higher values (e.g., 1) than E-cores/“efficiency cores” (e.g., 0), as documented in the `CentralProcessor` Javadoc. Do not flag code as incorrect solely because ARM_P_CORES or Intel P-cores are assigned higher efficiency values.
Applied to files:
oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java
🔇 Additional comments (3)
oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java (1)
31-113: LGTM!oshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java (1)
19-201: LGTM!oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.java (1)
37-40: LGTM!
- MacBluetoothDevice in oshi-common: parses system_profiler SPBluetoothDataType output for connected/not-connected devices - Shared by JNA/FFM HALs (no native calls needed) - Replaces IOKit IOBluetoothDevice approach which only found kernel-level objects, not user-space paired devices - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
f3acf53 to
d1e4795
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java`:
- Around line 58-63: The radio handle created inside the loop can leak if
getRadioName(...) or queryDevicesForRadio(...) throws; modify the loop in
WindowsBluetoothDeviceJNA (the block that constructs new
HANDLE(phRadio.getValue())) to wrap per-radio usage in a try/finally so
Kernel32.INSTANCE.CloseHandle(hRadio) always runs: create the HANDLE hRadio as
now, then in a try block call getRadioName(hRadio) and
queryDevicesForRadio(hRadio, adapterName, devices), and call CloseHandle(hRadio)
in the finally block; keep the BluetoothFindNextRadio(hFindRadio, phRadio) loop
condition unchanged so iteration continues while ensuring each HANDLE is closed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: e04c17e8-73bc-40d7-90d3-529210e328c9
📒 Files selected for processing (10)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/test/java/oshi/util/FormatUtilTest.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.javaoshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
🚧 Files skipped from review as they are similar to previous changes (9)
- oshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
- oshi-common/src/test/java/oshi/util/FormatUtilTest.java
- oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.java
- oshi-common/src/main/java/oshi/util/FormatUtil.java
- oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java
- oshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java
- oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java
- oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.java
- oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Analyze (java)
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-04-06T04:45:47.644Z
Learnt from: dbwiddis
Repo: oshi/oshi PR: 3121
File: oshi-core/src/main/java/oshi/software/os/linux/LinuxOperatingSystem.java:53-53
Timestamp: 2026-04-06T04:45:47.644Z
Learning: In the oshi/oshi project, only interfaces and classes in the root packages `oshi`, `oshi.hardware`, and `oshi.software.os` are considered the public API. Code in subpackages that represent specific implementations/platforms (e.g., `oshi.software.os.linux`, `oshi.hardware.platform.linux`, and similar subpackages) is implementation detail. When reviewing, do not treat changes to classes in these platform-specific subpackages as public API breaks (for example: making `LinuxOperatingSystem` abstract, narrowing constructor visibility, or adding/removing abstract methods should not be flagged as breaking public API).
Applied to files:
oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java
- MacBluetoothDevice in oshi-common: parses system_profiler SPBluetoothDataType output for connected/not-connected devices - Shared by JNA/FFM HALs (no native calls needed) - Replaces IOKit IOBluetoothDevice approach which only found kernel-level objects, not user-space paired devices - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
d1e4795 to
62ff37a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@oshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.java`:
- Around line 72-76: In WindowsBluetoothDeviceFFM's loop that iterates phRadio
(the code calling getRadioName(arena, hRadio) and queryDevicesForRadio(arena,
hRadio, adapterName, devices)), ensure each native radio handle (hRadio) is
closed in a per-iteration finally block so CloseHandle(hRadio) always runs even
if getRadioName or queryDevicesForRadio throws; refactor the loop body to
capture hRadio, call getRadioName and queryDevicesForRadio inside a try, and
invoke Kernel32FFM.CloseHandle(hRadio) in the corresponding finally to prevent
native handle leaks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1e56a092-03aa-4d87-b7f3-0982bf677a13
📒 Files selected for processing (10)
oshi-common/src/main/java/oshi/hardware/BluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.javaoshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.javaoshi-common/src/main/java/oshi/util/FormatUtil.javaoshi-common/src/test/java/oshi/util/FormatUtilTest.javaoshi-core-ffm/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceFFM.javaoshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.javaoshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.javaoshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
✅ Files skipped from review due to trivial changes (1)
- oshi-core/src/test/java/oshi/hardware/platform/shared/BluetoothDeviceTest.java
🚧 Files skipped from review as they are similar to previous changes (8)
- oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacHardwareAbstractionLayer.java
- oshi-core/src/main/java/oshi/hardware/platform/windows/WindowsBluetoothDeviceJNA.java
- oshi-common/src/test/java/oshi/util/FormatUtilTest.java
- oshi-common/src/main/java/oshi/util/FormatUtil.java
- oshi-common/src/main/java/oshi/hardware/BluetoothDevice.java
- oshi-common/src/main/java/oshi/hardware/common/platform/mac/MacBluetoothDevice.java
- oshi-common/src/main/java/oshi/hardware/common/platform/linux/LinuxBluetoothDevice.java
- oshi-core/src/main/java/oshi/jna/platform/windows/BluetoothApis.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: Test JDK 25, windows-latest (+ JNA==FFM)
- GitHub Check: Test JDK 25, macos-latest (+ JNA==FFM)
- GitHub Check: Test JDK 21, macos-latest
- GitHub Check: Test JDK 25, ubuntu-latest (+ JNA==FFM)
- GitHub Check: Analyze (java)
- GitHub Check: JMH Benchmarks, macos-latest
- GitHub Check: JMH Benchmarks, ubuntu-latest
- GitHub Check: JMH Benchmarks, windows-latest
- GitHub Check: Lint (Spotless, Checkstyle, ForbiddenAPIs, Javadoc)
- MacBluetoothDevice in oshi-common: parses system_profiler SPBluetoothDataType output for connected/not-connected devices - Shared by JNA/FFM HALs (no native calls needed) - Replaces IOKit IOBluetoothDevice approach which only found kernel-level objects, not user-space paired devices - CHANGELOG.md: add entry for oshi#3255 - README.md, site index: USB Devices -> Peripheral devices (USB, Bluetooth) - Update parseMajorDeviceClass test for Miscellaneous/Uncategorized cases
62ff37a to
3f335e3
Compare
Closes #3253
Adds Bluetooth device enumeration to OSHI across Linux, Windows, and macOS.
Public API
BluetoothDeviceinterface (oshi-common): name, MAC address, major device class (CoD), connected/paired status, battery level, adapter nameHardwareAbstractionLayer.getBluetoothDevices(): default method returning empty list; overridden on supported platformsPlatform Implementations
Linux
/sys/class/bluetooth/hciX/address/var/lib/bluetooth/<adapter>/<device>/info(BlueZ)oshi-common(no native calls needed); shared by JNA/FFM/NativeFree HALsWindows (JNA + FFM)
BluetoothApis.dll(Vista+, gated byVersionHelpers)BluetoothFindFirstRadio/BluetoothFindNextRadiofor adapter enumerationBluetoothFindFirstDevice/BluetoothFindNextDevicewithBLUETOOTH_DEVICE_INFOstructBLUETOOTH_ADDRESSmapped as a proper JNAUnionwithgetAddress()/getBytes()accessorsmacOS (JNA + FFM)
IOBluetoothDeviceclassName,DeviceAddress,ClassOfDevice,Connected,Paired,BatteryPercentpropertiesShared Utilities
FormatUtil.formatMacAddress(long)andformatMacAddress(String): MAC address formatting with hex validationAbstractBluetoothDevice.parseMajorDeviceClass(int): Bluetooth CoD bit parsing (Miscellaneous through Health + Uncategorized)Other Changes
SystemInfoHelper: addedprintBluetoothDevices(), added CgroupInfo toprintOperatingSystem()oshi-core/SystemInfoTest: refactored to useSystemInfoHelperstatic imports (removed ~390 lines of duplication)SystemInfoTestvariants: print Bluetooth devices after USBREADME.md+ site index: "USB Devices" → "Peripheral devices (USB, Bluetooth)"CHANGELOG.md: entry for this PRSummary by CodeRabbit
New Features
Improvements
Documentation
Tests