Commit Graph
60 Commits
Author SHA1 Message Date
darken 71638c13ab feat: Decode AAP ear detection and stabilize ANC mode changes
Decode cmd 0x0006 as EarDetection with per-pod placement (IN_EAR, NOT_IN_EAR, IN_CASE, DISCONNECTED). Map AAP primary/secondary to left/right using BLE primary pod bit.

Queue ANC mode changes when no pod is in ear, auto-send when a pod goes in ear. Show pending mode in UI with secondary color treatment.

Debounce device-initiated ANC mode cycling during ear transitions. Skip debounce for user-initiated commands and initial handshake. Optimistic UI update on send for instant feedback.
2026-03-31 19:17:09 +02:00
darken 70e5b99e1d feat: Add connection type indicators to SignalBadge
Move BLE key and AAP connection icons into the SignalBadge pill.

Add BleKeyState enum on PodDevice to expose IRK/ENC state cleanly.

Key icon: outlined for IRK-only, solid for IRK+ENC.

Bluetooth icon shown when AAP transport is active.
2026-03-31 19:17:09 +02:00
darken f65c6e4a29 feat: Add BLE device support for 6 new Beats models
Solo Pro (0x0C20), Solo 4 (0x2520), Solo Buds (0x2620), Studio Buds (0x1120), Studio Buds+ (0x1620), Studio Pro (0x1720). Tests use handcrafted data pending real captures.
2026-03-31 19:17:09 +02:00
darken c860ecc430 feat: Integrate AAP connection freshness into signal quality indicator 2026-03-31 19:17:09 +02:00
darken a8593eecd3 refactor: Reorganize pods package into ble/ and aap/ domains
Move BLE-specific code (snapshots, devices, factories, protocol) under apple/ble/. Move AAP code under apple/aap/ with protocol/ subdirectory. PodModel stays in apple/ as the only shared type.
2026-03-31 19:17:09 +02:00
darken 4808e04146 fix: Update Dagger component reference after BaseBlePodsTest rename 2026-03-31 19:17:09 +02:00
darken c1cd99f701 feat: Add AAP L2CAP protocol support for reading and writing AirPods settings
Full integration of the Apple Accessory Protocol (AAP) over L2CAP, enabling direct communication with AirPods for 1% battery granularity, ANC mode control, Conversation Awareness toggle, and private key exchange for BLE encrypted battery.
2026-03-31 19:17:09 +02:00
darken 3fa01bb510 refactor: Rename PodDevice to BlePodSnapshot, MonitoredDevice to PodDevice, extract PodModel
Complete type rename chain: PodDevice (interface) becomes BlePodSnapshot, MonitoredDevice (facade) claims PodDevice name, Model enum extracted to top-level PodModel. Delete redundant type alias files. Fix stale comments and log tags.
2026-03-31 19:17:09 +02:00
darken e84f8762b4 Extract Model to PodModel.kt 2026-03-31 19:17:09 +02:00
darken ac21261d4d refactor: Migrate all consumers from PodDevice to MonitoredDevice
Replace direct PodDevice/PodMonitor usage with MonitoredDevice/DeviceMonitor across ViewModels, UI screens, notifications, widgets, reactions, and service. All interface cast-based property access replaced with flat MonitoredDevice properties. Make L2capSocketFactory injectable.
2026-03-31 19:17:09 +02:00
darken f751cdb37e feat: Add MonitoredDevice facade and DeviceMonitor merge point
MonitoredDevice unifies BLE and AAP data sources with dynamic resolution.

DeviceMonitor combines PodMonitor + AapConnectionManager into a single Flow.

To be renamed to PodDevice/PodMonitor when the old types are renamed to BlePodSnapshot/BlePodMonitor.
2026-03-31 19:17:09 +02:00
darken 28cd3b1340 test: Add unit tests for AAP protocol layer and Model.Features 2026-03-31 19:17:09 +02:00
darken 193a1030fb feat: Start BLE scanning with only core permissions granted
Allow the app to scan for AirPods when only BLE scan permissions are granted, without waiting for all optional permissions (notifications, overlay, etc.).

Add isScanBlocking flag to Permission enum. Gate monitor service and pod scanning on scan permissions only. Show scan-blocking permission cards with error color and sorted first. Wrap BLUETOOTH_CONNECT-dependent calls in try-catch for graceful degradation. Fix POST_NOTIFICATIONS minApiLevel from S (31) to TIRAMISU (33).
2026-03-10 16:37:43 +00:00
darken 44cd0eec2a test: Add missing AutoConnectCondition round-trip and Model encode tests 2026-03-09 20:29:19 +00:00
darken a79f6a0535 refactor: Replace Moshi with kotlinx.serialization
Remove Moshi dependency entirely, completing the migration to kotlinx.serialization. All JSON serialization now uses kotlinx with explicit @SerialName annotations for wire format stability.

- Migrate PodDeviceCache from Moshi to kotlinx Json injection

- Add MapIntByteArrayBase64Serializer for BleScanResult cache compat

- Strip @JsonClass/@Json annotations from all dual-annotated classes

- Delete Moshi adapters, ProGuard rules, and build config

- Convert compat tests to pure kotlinx round-trip tests
2026-03-09 20:29:19 +00:00
darken 8675d73a98 fix(debug): Persist recording session across app restarts
The debug recording trigger file now stores the session directory path and start timestamp. On app restart, the recorder resumes into the same session directory and log file instead of creating a new one, preserving the original start time so the short-recording guard doesn't reset.
2026-03-09 17:34:29 +00:00
darken de89c51457 fix(debug): Use human-readable UTC timestamp in debug session directory names
Parse creation time from the embedded filename timestamp instead of relying on filesystem attributes, which are non-deterministic and caused flaky test failures in CI.
2026-03-09 11:57:42 +00:00
darken a76e43ac04 chore: Use List in Zipper and add global ExperimentalMaterial3Api opt-in
Replace Array<String> with List<String> in Zipper.zip().

Add global -opt-in flag for ExperimentalMaterial3Api in build.gradle.kts

and remove per-file @OptIn annotations from 12 Compose screens.
2026-03-09 04:53:01 +00:00
darken fd0dc49396 test(debug): Add session ID round-trip and edge case tests 2026-03-09 04:53:01 +00:00
darken a5f5feacae fix(debug): Fix deadlock risk, missing IO dispatcher, and thread safety in session manager
Replace sessions.first() inside fsMutex.withLock with synchronous volatile

read to avoid potential deadlock. Wrap file deletions in IO dispatcher.

Log partial delete failures. Make pendingAutoZips thread-safe via

Collections.synchronizedSet. Add test for ext/cache same-basename IDs.
2026-03-09 04:53:01 +00:00
darken 557ee9b3ed fix(test): Fix flaky sort test that relied on filesystem creation time 2026-03-09 04:53:01 +00:00
darken 58bd0f91f5 refactor(debug): Use Instant for createdAt, extract scanSessions helpers, add pendingAutoZips guard 2026-03-09 04:53:01 +00:00
darken 62797e8ea2 test(support): Add ContactFormViewModel.State unit tests 2026-03-09 04:53:01 +00:00
darken c614e7bd4f test(debug): Add unit tests for Zipper, DebugLogZipper, RecorderModule.State, and scanSessions edge cases 2026-03-09 04:53:01 +00:00
darken 62e39ce3d2 refactor(support): Add zipFile/compressedSize to Ready, harden session manager
Add zipFile and compressedSize fields to DebugSession.Ready, populated during scan. Simplify RecorderActivityVM by reading compressed size directly from session model. Apply code review fixes: fsMutex in zipSessionAsync, CancellationException handling, ZipOutputStream use{}, atomic file moves, dedup deriveSessionId, LifecycleResumeEffect for session refresh.
2026-03-09 04:53:01 +00:00
darken 450a187b65 test(reaction): Add ViewModel and reaction logic unit tests
Extract pure decision functions from AutoConnect and PopUpReaction for testability, following the existing PlayPause pattern. Add FakeDataStoreValue test helper.

Fix reversed Duration.between args in PopUpReaction connection monitor that caused the false-positive age filter to never trigger.
2026-03-07 14:19:17 +00:00
darken 1a196689db fix(test): Move FossUpgrade tests to testFoss source set for gplay compat
FossUpgrade is foss-flavor-only, so tests referencing it must live in testFoss/ to avoid compilation failures in testGplayDebugUnitTest.
2026-03-04 15:23:34 +00:00
darken 8ada7b071d test(settings): Add missing DataStore serialization and migration compat tests
Cover round-trip tests for ThemeStyle, ThemeColor, MonitorMode, ScannerMode, AutoConnectCondition, FossUpgrade, and InstantEpochMillisSerializer. Add Moshi decode tests for ThemeStyle, ThemeColor, AutoConnectCondition, FossUpgrade, and FossUpgrade.Reason annotation parity.
2026-03-04 15:23:34 +00:00
darken a92e364ca6 refactor(settings): Migrate preferences from SharedPreferences to DataStore
Replace FlowPreference<T> wrapping SharedPreferences with DataStoreValue<T> wrapping AndroidX DataStore. Includes SharedPreferencesMigration for preserving existing user data, kotlinx-serialization for complex types (replacing Moshi for preferences), and comprehensive unit tests for the new infrastructure.
2026-03-04 15:23:34 +00:00
darken 06f4115808 feat(ui): Add theme mode, style, and color settings
Add user-facing theme preferences with three independent axes:
- Theme mode (System/Dark/Light)
- Theme style (Default/Material You/Medium Contrast/High Contrast)
- Theme color (Blue/Green/Amber)

Includes safe Moshi enum fallback for corrupted preference values,
color palettes for all combinations, and window background sync
to prevent flash during navigation transitions.
2026-02-24 18:33:33 +01:00
darken 63692595a8 refactor(ui): Migrate from Fragments to Jetpack Compose
Replace Fragment-based UI with Jetpack Compose screens, adopting
Navigation3 for type-safe routing and Material3 theming throughout.

- Replace all Fragments/ViewHolders with Compose screens and cards
- Introduce NavigationController with Navigation3 runtime
- Add CapodTheme with Material3 design system
- Migrate PopUpWindow overlay to ComposeView with proper lifecycle
- Rewrite WidgetConfigurationActivity in Compose
- Add reusable settings composables (switch, slider, list preference)
- Update Kotlin to 2.2.10, add Compose BOM 2025.06.01
- Fix reactive state for unmatched devices toggle
- Add safety timeout for BT device enumeration
- Fix profile name validation error message
2026-02-24 15:05:09 +01:00
darken 9785b5ea7f fix(playpause): Improve test coverage and clarify code comments
Add missing test cases for single-pod one-pod-mode pause direction,
EarDetectionState single-pod properties, and normal-mode steady-state.
Fix stale test comments that incorrectly claimed tests would fail.
Clarify onePodMode flow combine pattern and isWorn field semantics.
2026-02-21 06:21:07 +01:00
darken fd7f9f8ab3 Refactor PlayPause logic and fix behavior for SinglePods (e.g. AirPods Max)
Fix edge case where removing a pod while both were in ears didn't trigger pause in one-pod mode. The aggregate boolean (isEitherPodInEar) stayed true, masking the individual pod removal.

See thread by `ZV`:
https://discord.com/channels/548521543039189022/1437499888068726814
2026-02-21 06:21:07 +01:00
darken ba4445f19d Fix lid state for AirPods Gen 4
The lid state for AirPods Gen 4 was incorrectly reported as UNKNOWN when it should have been NOT_IN_CASE. This commit fixes the issue in both the ANC and non-ANC tests.
2025-09-29 14:23:56 +02:00
darken 33cab939f0 Refactor: Use DeviceProfilesRepo for keys
This commit replaces the direct usage of GeneralSettings for fetching identity and encryption keys with the DeviceProfilesRepo. BaseAirPodsTest is updated to reflect this change, mocking DeviceProfilesRepo instead of GeneralSettings.
2025-09-29 14:23:52 +02:00
darken be8f4919c8 Merge main and common module to simplify. 2025-09-29 13:36:43 +02:00
darken 1d51c207f4 Basic working data display in wear-app 2022-09-14 18:00:18 +02:00
darken f7acb5e115 Fix copy paste regressions 2022-09-14 18:00:18 +02:00
darken 2210561af3 Refactoring 2022-09-14 18:00:18 +02:00
darken 688748da36 Go multi-module: app-common, app-phone, app-wear 2022-09-14 18:00:18 +02:00
darken c437decbbf Add VarunrAirPodsPro.kt 2022-04-08 23:18:35 +02:00
darken 9f49b470fe Refactor interfaces to "single" and "dual" pods that each have one or more extra features. 2022-02-13 20:48:34 +01:00
darken ce25ad6711 Add support for Tws i99999 2022-02-12 07:45:47 +01:00
darken 8f609ca989 Handle ear detection and microphone detection for dual pods better. 2022-01-25 22:54:53 +01:00
darken 5f60f2b5eb Fix lid detection tests 2022-01-20 15:11:37 +01:00
darken 6a0b1ffdb1 Refactoring of device creation, more autonomy. 2022-01-18 13:50:55 +01:00
darken 632cfdd84b Fix test 2022-01-14 19:40:47 +01:00
darken a8f2fdf03a Add AirPods Gen3 support 2022-01-09 19:03:38 +01:00
darken 604502ae76 Revert "Fix PowerBeats3 mapping"
This reverts commit 7a5baed6
2022-01-09 18:06:18 +01:00
darken f9d39a6319 Add option to show fake devices 2022-01-06 11:59:30 +01:00