mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-15 02:36:12 -04:00
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.
This commit is contained in:
@@ -5,7 +5,7 @@ import eu.darken.capod.common.theming.ThemeColor
|
||||
import eu.darken.capod.common.theming.ThemeMode
|
||||
import eu.darken.capod.common.theming.ThemeStyle
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesContainer
|
||||
import eu.darken.capod.reaction.core.autoconnect.AutoConnectCondition
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import eu.darken.capod.common.theming.ThemeColor
|
||||
import eu.darken.capod.common.theming.ThemeMode
|
||||
import eu.darken.capod.common.theming.ThemeStyle
|
||||
import eu.darken.capod.main.core.MonitorMode
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesContainer
|
||||
|
||||
@@ -11,7 +11,7 @@ import eu.darken.capod.main.core.PermissionTool
|
||||
import eu.darken.capod.monitor.core.DeviceMonitor
|
||||
import eu.darken.capod.monitor.core.PodDevice
|
||||
import eu.darken.capod.monitor.core.worker.MonitorControl
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package eu.darken.capod.monitor.core
|
||||
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.HasCase
|
||||
import eu.darken.capod.pods.core.HasChargeDetectionDual
|
||||
import eu.darken.capod.pods.core.HasEarDetection
|
||||
import eu.darken.capod.pods.core.HasEarDetectionDual
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasCase
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasChargeDetectionDual
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasEarDetection
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasEarDetectionDual
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting
|
||||
import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.ApplePods
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -238,7 +239,7 @@ class PodDeviceTest : BaseTest() {
|
||||
val ble = mockk<DualApplePods>(relaxed = true) {
|
||||
every { model } returns PodModel.AIRPODS_PRO3
|
||||
every { this@mockk.address } returns bleRpa
|
||||
every { meta } returns eu.darken.capod.pods.core.apple.ApplePods.AppleMeta(profile = profile)
|
||||
every { meta } returns ApplePods.AppleMeta(profile = profile)
|
||||
}
|
||||
val device = PodDevice(ble = ble, aap = null)
|
||||
device.address shouldBe bondedAddress
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.monitor.core
|
||||
|
||||
import eu.darken.capod.common.fromHex
|
||||
import eu.darken.capod.pods.core.apple.protocol.RPAChecker
|
||||
import eu.darken.capod.pods.core.apple.ble.protocol.RPAChecker
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.junit.jupiter.api.Test
|
||||
import testhelpers.BaseTest
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core
|
||||
package eu.darken.capod.pods.core.apple
|
||||
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -77,4 +77,4 @@ class ModelFeaturesTest : BaseTest() {
|
||||
model.features.hasDualPods shouldBe true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -1,9 +1,11 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap
|
||||
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothSocket
|
||||
import eu.darken.capod.common.bluetooth.l2cap.L2capSocketFactory
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapCommand
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.matchers.maps.shouldBeEmpty
|
||||
import io.kotest.matchers.shouldBe
|
||||
+45
-10
@@ -1,5 +1,6 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap
|
||||
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -35,7 +36,10 @@ class AapPodStateTest : BaseTest() {
|
||||
val state = AapPodState(
|
||||
connectionState = AapPodState.ConnectionState.READY,
|
||||
settings = mapOf(
|
||||
AapSetting.AncMode::class to AapSetting.AncMode(AapSetting.AncMode.Value.ON, listOf(AapSetting.AncMode.Value.ON)),
|
||||
AapSetting.AncMode::class to AapSetting.AncMode(
|
||||
AapSetting.AncMode.Value.ON,
|
||||
listOf(AapSetting.AncMode.Value.ON)
|
||||
),
|
||||
)
|
||||
)
|
||||
val updated = state.withSetting(
|
||||
@@ -51,7 +55,10 @@ class AapPodStateTest : BaseTest() {
|
||||
val state = AapPodState(
|
||||
connectionState = AapPodState.ConnectionState.READY,
|
||||
settings = mapOf(
|
||||
AapSetting.AncMode::class to AapSetting.AncMode(AapSetting.AncMode.Value.ON, listOf(AapSetting.AncMode.Value.ON)),
|
||||
AapSetting.AncMode::class to AapSetting.AncMode(
|
||||
AapSetting.AncMode.Value.ON,
|
||||
listOf(AapSetting.AncMode.Value.ON)
|
||||
),
|
||||
)
|
||||
)
|
||||
val updated = state.withSetting(
|
||||
@@ -75,9 +82,21 @@ class AapPodStateTest : BaseTest() {
|
||||
fun `battery accessors map to correct types`() {
|
||||
val state = AapPodState(
|
||||
batteries = mapOf(
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(AapPodState.BatteryType.LEFT, 0.8f, AapPodState.ChargingState.NOT_CHARGING),
|
||||
AapPodState.BatteryType.RIGHT to AapPodState.Battery(AapPodState.BatteryType.RIGHT, 0.77f, AapPodState.ChargingState.CHARGING),
|
||||
AapPodState.BatteryType.CASE to AapPodState.Battery(AapPodState.BatteryType.CASE, 0.48f, AapPodState.ChargingState.CHARGING),
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(
|
||||
AapPodState.BatteryType.LEFT,
|
||||
0.8f,
|
||||
AapPodState.ChargingState.NOT_CHARGING
|
||||
),
|
||||
AapPodState.BatteryType.RIGHT to AapPodState.Battery(
|
||||
AapPodState.BatteryType.RIGHT,
|
||||
0.77f,
|
||||
AapPodState.ChargingState.CHARGING
|
||||
),
|
||||
AapPodState.BatteryType.CASE to AapPodState.Battery(
|
||||
AapPodState.BatteryType.CASE,
|
||||
0.48f,
|
||||
AapPodState.ChargingState.CHARGING
|
||||
),
|
||||
),
|
||||
)
|
||||
state.batteryLeft shouldBe 0.8f
|
||||
@@ -99,7 +118,11 @@ class AapPodStateTest : BaseTest() {
|
||||
fun `headset battery for single-pod devices`() {
|
||||
val state = AapPodState(
|
||||
batteries = mapOf(
|
||||
AapPodState.BatteryType.SINGLE to AapPodState.Battery(AapPodState.BatteryType.SINGLE, 0.6f, AapPodState.ChargingState.NOT_CHARGING),
|
||||
AapPodState.BatteryType.SINGLE to AapPodState.Battery(
|
||||
AapPodState.BatteryType.SINGLE,
|
||||
0.6f,
|
||||
AapPodState.ChargingState.NOT_CHARGING
|
||||
),
|
||||
),
|
||||
)
|
||||
state.batteryHeadset shouldBe 0.6f
|
||||
@@ -110,7 +133,11 @@ class AapPodStateTest : BaseTest() {
|
||||
fun `isCharging true for CHARGING state`() {
|
||||
val state = AapPodState(
|
||||
batteries = mapOf(
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(AapPodState.BatteryType.LEFT, 0.8f, AapPodState.ChargingState.CHARGING),
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(
|
||||
AapPodState.BatteryType.LEFT,
|
||||
0.8f,
|
||||
AapPodState.ChargingState.CHARGING
|
||||
),
|
||||
),
|
||||
)
|
||||
state.isLeftCharging shouldBe true
|
||||
@@ -120,7 +147,11 @@ class AapPodStateTest : BaseTest() {
|
||||
fun `isCharging true for CHARGING_OPTIMIZED state`() {
|
||||
val state = AapPodState(
|
||||
batteries = mapOf(
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(AapPodState.BatteryType.LEFT, 0.8f, AapPodState.ChargingState.CHARGING_OPTIMIZED),
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(
|
||||
AapPodState.BatteryType.LEFT,
|
||||
0.8f,
|
||||
AapPodState.ChargingState.CHARGING_OPTIMIZED
|
||||
),
|
||||
),
|
||||
)
|
||||
state.isLeftCharging shouldBe true
|
||||
@@ -130,7 +161,11 @@ class AapPodStateTest : BaseTest() {
|
||||
fun `isCharging false for NOT_CHARGING`() {
|
||||
val state = AapPodState(
|
||||
batteries = mapOf(
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(AapPodState.BatteryType.LEFT, 0.8f, AapPodState.ChargingState.NOT_CHARGING),
|
||||
AapPodState.BatteryType.LEFT to AapPodState.Battery(
|
||||
AapPodState.BatteryType.LEFT,
|
||||
0.8f,
|
||||
AapPodState.ChargingState.NOT_CHARGING
|
||||
),
|
||||
),
|
||||
)
|
||||
state.isLeftCharging shouldBe false
|
||||
+99
-95
@@ -1,22 +1,12 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap.devices
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState.BatteryType
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState.ChargingState
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.AncMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.AdaptiveAudioNoise
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ConversationalAwareness
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ConversationalAwarenessState
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic.EndCallMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic.MuteMicMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.NcWithOneAirPod
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PersonalizedVolume
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PressHoldDuration
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PressSpeed
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ToneVolume
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.VolumeSwipe
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.VolumeSwipeLength
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapCommand
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapMessage
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.BaseAapSessionTest
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.DefaultAapDeviceProfile
|
||||
import io.kotest.matchers.collections.shouldContainExactly
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
@@ -66,10 +56,12 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class InitExtTests {
|
||||
@Test fun `returned for Pro 2`() { DefaultAapDeviceProfile(PodModel.AIRPODS_PRO2).encodeInitExt().shouldNotBeNull() }
|
||||
@Test
|
||||
fun `returned for Pro 2`() { DefaultAapDeviceProfile(PodModel.AIRPODS_PRO2).encodeInitExt().shouldNotBeNull() }
|
||||
@Test fun `returned for Pro 3`() { DefaultAapDeviceProfile(PodModel.AIRPODS_PRO3).encodeInitExt().shouldNotBeNull() }
|
||||
@Test fun `returned for AP4 ANC`() { DefaultAapDeviceProfile(PodModel.AIRPODS_GEN4_ANC).encodeInitExt().shouldNotBeNull() }
|
||||
@Test fun `null for basic AirPods`() { DefaultAapDeviceProfile(PodModel.AIRPODS_GEN3).encodeInitExt().shouldBeNull() }
|
||||
@Test
|
||||
fun `null for basic AirPods`() { DefaultAapDeviceProfile(PodModel.AIRPODS_GEN3).encodeInitExt().shouldBeNull() }
|
||||
@Test fun `null for Pro 1`() { DefaultAapDeviceProfile(PodModel.AIRPODS_PRO).encodeInitExt().shouldBeNull() }
|
||||
@Test fun `null for Max`() { DefaultAapDeviceProfile(PodModel.AIRPODS_MAX).encodeInitExt().shouldBeNull() }
|
||||
|
||||
@@ -83,25 +75,25 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class SupportedAncModesTests {
|
||||
private fun ancModesFor(model: PodModel): List<AncMode.Value> {
|
||||
private fun ancModesFor(model: PodModel): List<AapSetting.AncMode.Value> {
|
||||
val p = DefaultAapDeviceProfile(model)
|
||||
return decodeSetting<AncMode>(settingsMessage(0x0D, 0x02)).let {
|
||||
return decodeSetting<AapSetting.AncMode>(settingsMessage(0x0D, 0x02)).let {
|
||||
// Can't use the outer profile, need per-model profile
|
||||
(p.decodeSetting(settingsMessage(0x0D, 0x02))!!.second as AncMode).supported
|
||||
(p.decodeSetting(settingsMessage(0x0D, 0x02))!!.second as AapSetting.AncMode).supported
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Pro 2 supports ON, TRANSPARENCY, ADAPTIVE`() {
|
||||
ancModesFor(PodModel.AIRPODS_PRO2) shouldContainExactly listOf(
|
||||
AncMode.Value.ON, AncMode.Value.TRANSPARENCY, AncMode.Value.ADAPTIVE,
|
||||
AapSetting.AncMode.Value.ON, AapSetting.AncMode.Value.TRANSPARENCY, AapSetting.AncMode.Value.ADAPTIVE,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Pro 1 supports ON, TRANSPARENCY only`() {
|
||||
ancModesFor(PodModel.AIRPODS_PRO) shouldContainExactly listOf(
|
||||
AncMode.Value.ON, AncMode.Value.TRANSPARENCY,
|
||||
AapSetting.AncMode.Value.ON, AapSetting.AncMode.Value.TRANSPARENCY,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -113,7 +105,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test
|
||||
fun `Max supports ON, TRANSPARENCY only`() {
|
||||
ancModesFor(PodModel.AIRPODS_MAX) shouldContainExactly listOf(
|
||||
AncMode.Value.ON, AncMode.Value.TRANSPARENCY,
|
||||
AapSetting.AncMode.Value.ON, AapSetting.AncMode.Value.TRANSPARENCY,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -122,22 +114,26 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class AncModeTests {
|
||||
@Test fun `encode OFF`() { profile.encodeCommand(AapCommand.SetAncMode(AncMode.Value.OFF))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode ON`() { profile.encodeCommand(AapCommand.SetAncMode(AncMode.Value.ON))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `encode TRANSPARENCY`() { profile.encodeCommand(AapCommand.SetAncMode(AncMode.Value.TRANSPARENCY))[7] shouldBe 0x03.toByte() }
|
||||
@Test fun `encode ADAPTIVE`() { profile.encodeCommand(AapCommand.SetAncMode(AncMode.Value.ADAPTIVE))[7] shouldBe 0x04.toByte() }
|
||||
@Test fun `encode OFF`() { profile.encodeCommand(AapCommand.SetAncMode(AapSetting.AncMode.Value.OFF))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode ON`() { profile.encodeCommand(AapCommand.SetAncMode(AapSetting.AncMode.Value.ON))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `encode TRANSPARENCY`() { profile.encodeCommand(AapCommand.SetAncMode(AapSetting.AncMode.Value.TRANSPARENCY))[7] shouldBe 0x03.toByte() }
|
||||
@Test fun `encode ADAPTIVE`() { profile.encodeCommand(AapCommand.SetAncMode(AapSetting.AncMode.Value.ADAPTIVE))[7] shouldBe 0x04.toByte() }
|
||||
|
||||
@Test fun `decode OFF`() { decodeSetting<AncMode>(settingsMessage(0x0D, 0x01)).current shouldBe AncMode.Value.OFF }
|
||||
@Test fun `decode ON`() { decodeSetting<AncMode>(settingsMessage(0x0D, 0x02)).current shouldBe AncMode.Value.ON }
|
||||
@Test fun `decode TRANSPARENCY`() { decodeSetting<AncMode>(settingsMessage(0x0D, 0x03)).current shouldBe AncMode.Value.TRANSPARENCY }
|
||||
@Test fun `decode ADAPTIVE`() { decodeSetting<AncMode>(settingsMessage(0x0D, 0x04)).current shouldBe AncMode.Value.ADAPTIVE }
|
||||
@Test
|
||||
fun `decode OFF`() { decodeSetting<AapSetting.AncMode>(settingsMessage(0x0D, 0x01)).current shouldBe AapSetting.AncMode.Value.OFF }
|
||||
@Test
|
||||
fun `decode ON`() { decodeSetting<AapSetting.AncMode>(settingsMessage(0x0D, 0x02)).current shouldBe AapSetting.AncMode.Value.ON }
|
||||
@Test
|
||||
fun `decode TRANSPARENCY`() { decodeSetting<AapSetting.AncMode>(settingsMessage(0x0D, 0x03)).current shouldBe AapSetting.AncMode.Value.TRANSPARENCY }
|
||||
@Test
|
||||
fun `decode ADAPTIVE`() { decodeSetting<AapSetting.AncMode>(settingsMessage(0x0D, 0x04)).current shouldBe AapSetting.AncMode.Value.ADAPTIVE }
|
||||
@Test fun `decode unknown wire value returns null`() { profile.decodeSetting(settingsMessage(0x0D, 0x99)).shouldBeNull() }
|
||||
|
||||
@Test
|
||||
fun `round-trip all modes`() {
|
||||
for (mode in AncMode.Value.entries) {
|
||||
for (mode in AapSetting.AncMode.Value.entries) {
|
||||
val encoded = profile.encodeCommand(AapCommand.SetAncMode(mode))
|
||||
val decoded = decodeSetting<AncMode>(AapMessage.parse(encoded)!!)
|
||||
val decoded = decodeSetting<AapSetting.AncMode>(AapMessage.Companion.parse(encoded)!!)
|
||||
decoded.current shouldBe mode
|
||||
}
|
||||
}
|
||||
@@ -149,8 +145,8 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
inner class ConversationalAwarenessTests {
|
||||
@Test fun `encode enabled`() { profile.encodeCommand(AapCommand.SetConversationalAwareness(true))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode disabled`() { profile.encodeCommand(AapCommand.SetConversationalAwareness(false))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `decode enabled`() { decodeSetting<ConversationalAwareness>(settingsMessage(0x28, 0x01)).enabled shouldBe true }
|
||||
@Test fun `decode disabled`() { decodeSetting<ConversationalAwareness>(settingsMessage(0x28, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode enabled`() { decodeSetting<AapSetting.ConversationalAwareness>(settingsMessage(0x28, 0x01)).enabled shouldBe true }
|
||||
@Test fun `decode disabled`() { decodeSetting<AapSetting.ConversationalAwareness>(settingsMessage(0x28, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode unknown value returns null`() { profile.decodeSetting(settingsMessage(0x28, 0x00)).shouldBeNull() }
|
||||
}
|
||||
|
||||
@@ -158,18 +154,20 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class PressSpeedTests {
|
||||
@Test fun `encode default`() { profile.encodeCommand(AapCommand.SetPressSpeed(PressSpeed.Value.DEFAULT))[7] shouldBe 0x00.toByte() }
|
||||
@Test fun `encode slower`() { profile.encodeCommand(AapCommand.SetPressSpeed(PressSpeed.Value.SLOWER))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode slowest`() { profile.encodeCommand(AapCommand.SetPressSpeed(PressSpeed.Value.SLOWEST))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `decode default`() { decodeSetting<PressSpeed>(settingsMessage(0x17, 0x00)).value shouldBe PressSpeed.Value.DEFAULT }
|
||||
@Test fun `decode slower`() { decodeSetting<PressSpeed>(settingsMessage(0x17, 0x01)).value shouldBe PressSpeed.Value.SLOWER }
|
||||
@Test fun `encode default`() { profile.encodeCommand(AapCommand.SetPressSpeed(AapSetting.PressSpeed.Value.DEFAULT))[7] shouldBe 0x00.toByte() }
|
||||
@Test fun `encode slower`() { profile.encodeCommand(AapCommand.SetPressSpeed(AapSetting.PressSpeed.Value.SLOWER))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode slowest`() { profile.encodeCommand(AapCommand.SetPressSpeed(AapSetting.PressSpeed.Value.SLOWEST))[7] shouldBe 0x02.toByte() }
|
||||
@Test
|
||||
fun `decode default`() { decodeSetting<AapSetting.PressSpeed>(settingsMessage(0x17, 0x00)).value shouldBe AapSetting.PressSpeed.Value.DEFAULT }
|
||||
@Test
|
||||
fun `decode slower`() { decodeSetting<AapSetting.PressSpeed>(settingsMessage(0x17, 0x01)).value shouldBe AapSetting.PressSpeed.Value.SLOWER }
|
||||
@Test fun `decode unknown returns null`() { profile.decodeSetting(settingsMessage(0x17, 0x99)).shouldBeNull() }
|
||||
|
||||
@Test
|
||||
fun `round-trip all values`() {
|
||||
for (v in PressSpeed.Value.entries) {
|
||||
for (v in AapSetting.PressSpeed.Value.entries) {
|
||||
val encoded = profile.encodeCommand(AapCommand.SetPressSpeed(v))
|
||||
decodeSetting<PressSpeed>(AapMessage.parse(encoded)!!).value shouldBe v
|
||||
decodeSetting<AapSetting.PressSpeed>(AapMessage.Companion.parse(encoded)!!).value shouldBe v
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,14 +176,16 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class PressHoldDurationTests {
|
||||
@Test fun `encode shorter`() { profile.encodeCommand(AapCommand.SetPressHoldDuration(PressHoldDuration.Value.SHORTER))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `decode shortest`() { decodeSetting<PressHoldDuration>(settingsMessage(0x18, 0x02)).value shouldBe PressHoldDuration.Value.SHORTEST }
|
||||
@Test
|
||||
fun `encode shorter`() { profile.encodeCommand(AapCommand.SetPressHoldDuration(AapSetting.PressHoldDuration.Value.SHORTER))[7] shouldBe 0x01.toByte() }
|
||||
@Test
|
||||
fun `decode shortest`() { decodeSetting<AapSetting.PressHoldDuration>(settingsMessage(0x18, 0x02)).value shouldBe AapSetting.PressHoldDuration.Value.SHORTEST }
|
||||
|
||||
@Test
|
||||
fun `round-trip all values`() {
|
||||
for (v in PressHoldDuration.Value.entries) {
|
||||
for (v in AapSetting.PressHoldDuration.Value.entries) {
|
||||
val encoded = profile.encodeCommand(AapCommand.SetPressHoldDuration(v))
|
||||
decodeSetting<PressHoldDuration>(AapMessage.parse(encoded)!!).value shouldBe v
|
||||
decodeSetting<AapSetting.PressHoldDuration>(AapMessage.Companion.parse(encoded)!!).value shouldBe v
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,8 +196,8 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
inner class NcOneAirPodTests {
|
||||
@Test fun `encode enabled`() { profile.encodeCommand(AapCommand.SetNcWithOneAirPod(true))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `encode disabled`() { profile.encodeCommand(AapCommand.SetNcWithOneAirPod(false))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `decode enabled`() { decodeSetting<NcWithOneAirPod>(settingsMessage(0x1B, 0x01)).enabled shouldBe true }
|
||||
@Test fun `decode disabled`() { decodeSetting<NcWithOneAirPod>(settingsMessage(0x1B, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode enabled`() { decodeSetting<AapSetting.NcWithOneAirPod>(settingsMessage(0x1B, 0x01)).enabled shouldBe true }
|
||||
@Test fun `decode disabled`() { decodeSetting<AapSetting.NcWithOneAirPod>(settingsMessage(0x1B, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode unknown returns null`() { profile.decodeSetting(settingsMessage(0x1B, 0x00)).shouldBeNull() }
|
||||
}
|
||||
|
||||
@@ -208,22 +208,24 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test fun `encode level 50`() { profile.encodeCommand(AapCommand.SetToneVolume(50))[7] shouldBe 50.toByte() }
|
||||
@Test fun `encode clamps to min 15`() { profile.encodeCommand(AapCommand.SetToneVolume(0))[7] shouldBe 0x0F.toByte() }
|
||||
@Test fun `encode clamps to max 100`() { profile.encodeCommand(AapCommand.SetToneVolume(200))[7] shouldBe 0x64.toByte() }
|
||||
@Test fun `decode level`() { decodeSetting<ToneVolume>(settingsMessage(0x1F, 50)).level shouldBe 50 }
|
||||
@Test fun `decode level`() { decodeSetting<AapSetting.ToneVolume>(settingsMessage(0x1F, 50)).level shouldBe 50 }
|
||||
}
|
||||
|
||||
// ── Volume Swipe Length ──────────────────────────────────
|
||||
|
||||
@Nested
|
||||
inner class VolumeSwipeLengthTests {
|
||||
@Test fun `encode longest`() { profile.encodeCommand(AapCommand.SetVolumeSwipeLength(VolumeSwipeLength.Value.LONGEST))[7] shouldBe 0x02.toByte() }
|
||||
@Test fun `decode longer`() { decodeSetting<VolumeSwipeLength>(settingsMessage(0x23, 0x01)).value shouldBe VolumeSwipeLength.Value.LONGER }
|
||||
@Test
|
||||
fun `encode longest`() { profile.encodeCommand(AapCommand.SetVolumeSwipeLength(AapSetting.VolumeSwipeLength.Value.LONGEST))[7] shouldBe 0x02.toByte() }
|
||||
@Test
|
||||
fun `decode longer`() { decodeSetting<AapSetting.VolumeSwipeLength>(settingsMessage(0x23, 0x01)).value shouldBe AapSetting.VolumeSwipeLength.Value.LONGER }
|
||||
@Test fun `decode unknown returns null`() { profile.decodeSetting(settingsMessage(0x23, 0x99)).shouldBeNull() }
|
||||
|
||||
@Test
|
||||
fun `round-trip all values`() {
|
||||
for (v in VolumeSwipeLength.Value.entries) {
|
||||
for (v in AapSetting.VolumeSwipeLength.Value.entries) {
|
||||
val encoded = profile.encodeCommand(AapCommand.SetVolumeSwipeLength(v))
|
||||
decodeSetting<VolumeSwipeLength>(AapMessage.parse(encoded)!!).value shouldBe v
|
||||
decodeSetting<AapSetting.VolumeSwipeLength>(AapMessage.Companion.parse(encoded)!!).value shouldBe v
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -233,7 +235,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Nested
|
||||
inner class VolumeSwipeTests {
|
||||
@Test fun `encode enabled`() { profile.encodeCommand(AapCommand.SetVolumeSwipe(true))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `decode disabled`() { decodeSetting<VolumeSwipe>(settingsMessage(0x25, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode disabled`() { decodeSetting<AapSetting.VolumeSwipe>(settingsMessage(0x25, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode unknown returns null`() { profile.decodeSetting(settingsMessage(0x25, 0x00)).shouldBeNull() }
|
||||
}
|
||||
|
||||
@@ -242,7 +244,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Nested
|
||||
inner class PersonalizedVolumeTests {
|
||||
@Test fun `encode enabled`() { profile.encodeCommand(AapCommand.SetPersonalizedVolume(true))[7] shouldBe 0x01.toByte() }
|
||||
@Test fun `decode disabled`() { decodeSetting<PersonalizedVolume>(settingsMessage(0x26, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode disabled`() { decodeSetting<AapSetting.PersonalizedVolume>(settingsMessage(0x26, 0x02)).enabled shouldBe false }
|
||||
@Test fun `decode unknown returns null`() { profile.decodeSetting(settingsMessage(0x26, 0x00)).shouldBeNull() }
|
||||
}
|
||||
|
||||
@@ -253,7 +255,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test fun `encode level 50`() { profile.encodeCommand(AapCommand.SetAdaptiveAudioNoise(50))[7] shouldBe 50.toByte() }
|
||||
@Test fun `encode clamps to 0`() { profile.encodeCommand(AapCommand.SetAdaptiveAudioNoise(-5))[7] shouldBe 0x00.toByte() }
|
||||
@Test fun `encode clamps to 100`() { profile.encodeCommand(AapCommand.SetAdaptiveAudioNoise(150))[7] shouldBe 0x64.toByte() }
|
||||
@Test fun `decode level`() { decodeSetting<AdaptiveAudioNoise>(settingsMessage(0x2E, 64)).level shouldBe 64 }
|
||||
@Test fun `decode level`() { decodeSetting<AapSetting.AdaptiveAudioNoise>(settingsMessage(0x2E, 64)).level shouldBe 64 }
|
||||
}
|
||||
|
||||
// ── EndCall / MuteMic ────────────────────────────────────
|
||||
@@ -262,7 +264,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
inner class EndCallMuteMicTests {
|
||||
@Test
|
||||
fun `encode single press mute, double press end call`() {
|
||||
val bytes = profile.encodeCommand(AapCommand.SetEndCallMuteMic(MuteMicMode.SINGLE_PRESS, EndCallMode.DOUBLE_PRESS))
|
||||
val bytes = profile.encodeCommand(AapCommand.SetEndCallMuteMic(AapSetting.EndCallMuteMic.MuteMicMode.SINGLE_PRESS, AapSetting.EndCallMuteMic.EndCallMode.DOUBLE_PRESS))
|
||||
bytes[6] shouldBe 0x24.toByte()
|
||||
bytes[7] shouldBe 0x21.toByte()
|
||||
bytes[8] shouldBe 0x23.toByte()
|
||||
@@ -271,30 +273,30 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Test
|
||||
fun `decode standard format 0x21`() {
|
||||
val ecm = decodeSetting<EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 21 22 03 00"))
|
||||
ecm.muteMic shouldBe MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe EndCallMode.SINGLE_PRESS
|
||||
val ecm = decodeSetting<AapSetting.EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 21 22 03 00"))
|
||||
ecm.muteMic shouldBe AapSetting.EndCallMuteMic.MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe AapSetting.EndCallMuteMic.EndCallMode.SINGLE_PRESS
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decode compact format 0x20 combined 0x02`() {
|
||||
val ecm = decodeSetting<EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 20 02 00 00"))
|
||||
ecm.muteMic shouldBe MuteMicMode.SINGLE_PRESS
|
||||
ecm.endCall shouldBe EndCallMode.DOUBLE_PRESS
|
||||
val ecm = decodeSetting<AapSetting.EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 20 02 00 00"))
|
||||
ecm.muteMic shouldBe AapSetting.EndCallMuteMic.MuteMicMode.SINGLE_PRESS
|
||||
ecm.endCall shouldBe AapSetting.EndCallMuteMic.EndCallMode.DOUBLE_PRESS
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decode compact format 0x20 combined 0x03`() {
|
||||
val ecm = decodeSetting<EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 20 03 00 00"))
|
||||
ecm.muteMic shouldBe MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe EndCallMode.SINGLE_PRESS
|
||||
val ecm = decodeSetting<AapSetting.EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 20 03 00 00"))
|
||||
ecm.muteMic shouldBe AapSetting.EndCallMuteMic.MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe AapSetting.EndCallMuteMic.EndCallMode.SINGLE_PRESS
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decode compact format subtype 0x00 from real Pro 3`() {
|
||||
val ecm = decodeSetting<EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 00 03 00 00"))
|
||||
ecm.muteMic shouldBe MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe EndCallMode.SINGLE_PRESS
|
||||
val ecm = decodeSetting<AapSetting.EndCallMuteMic>(aapMessage("04 00 04 00 09 00 24 00 03 00 00"))
|
||||
ecm.muteMic shouldBe AapSetting.EndCallMuteMic.MuteMicMode.DOUBLE_PRESS
|
||||
ecm.endCall shouldBe AapSetting.EndCallMuteMic.EndCallMode.SINGLE_PRESS
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -307,8 +309,8 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
|
||||
@Nested
|
||||
inner class ConversationAwarenessStateTests {
|
||||
@Test fun `speaking start`() { decodeSetting<ConversationalAwarenessState>(aapMessage("04 00 04 00 4B 00 01")).speaking shouldBe true }
|
||||
@Test fun `speaking stop`() { decodeSetting<ConversationalAwarenessState>(aapMessage("04 00 04 00 4B 00 04")).speaking shouldBe false }
|
||||
@Test fun `speaking start`() { decodeSetting<AapSetting.ConversationalAwarenessState>(aapMessage("04 00 04 00 4B 00 01")).speaking shouldBe true }
|
||||
@Test fun `speaking stop`() { decodeSetting<AapSetting.ConversationalAwarenessState>(aapMessage("04 00 04 00 4B 00 04")).speaking shouldBe false }
|
||||
@Test fun `empty payload returns null`() { profile.decodeSetting(aapMessage("04 00 04 00 4B 00")).shouldBeNull() }
|
||||
}
|
||||
|
||||
@@ -319,8 +321,8 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test
|
||||
fun `decode single left pod`() {
|
||||
val r = profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 85, 0x02, 0x00))!!
|
||||
r[BatteryType.LEFT]!!.percent shouldBe 0.85f
|
||||
r[BatteryType.LEFT]!!.charging shouldBe ChargingState.NOT_CHARGING
|
||||
r[AapPodState.BatteryType.LEFT]!!.percent shouldBe 0.85f
|
||||
r[AapPodState.BatteryType.LEFT]!!.charging shouldBe AapPodState.ChargingState.NOT_CHARGING
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -332,17 +334,17 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
0x08, 0x00, 50, 0x02, 0x00,
|
||||
))!!
|
||||
r.size shouldBe 3
|
||||
r[BatteryType.RIGHT]!!.percent shouldBe 0.9f
|
||||
r[BatteryType.RIGHT]!!.charging shouldBe ChargingState.CHARGING
|
||||
r[BatteryType.LEFT]!!.percent shouldBe 0.8f
|
||||
r[BatteryType.CASE]!!.percent shouldBe 0.5f
|
||||
r[AapPodState.BatteryType.RIGHT]!!.percent shouldBe 0.9f
|
||||
r[AapPodState.BatteryType.RIGHT]!!.charging shouldBe AapPodState.ChargingState.CHARGING
|
||||
r[AapPodState.BatteryType.LEFT]!!.percent shouldBe 0.8f
|
||||
r[AapPodState.BatteryType.CASE]!!.percent shouldBe 0.5f
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decode headset (single)`() {
|
||||
val r = profile.decodeBattery(batteryMessage(0x01, 0x01, 0x00, 60, 0x04, 0x00))!!
|
||||
r[BatteryType.SINGLE]!!.percent shouldBe 0.6f
|
||||
r[BatteryType.SINGLE]!!.charging shouldBe ChargingState.DISCONNECTED
|
||||
r[AapPodState.BatteryType.SINGLE]!!.percent shouldBe 0.6f
|
||||
r[AapPodState.BatteryType.SINGLE]!!.charging shouldBe AapPodState.ChargingState.DISCONNECTED
|
||||
}
|
||||
|
||||
@Test fun `skips percent above 100`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 127, 0x02, 0x00))!! shouldBe emptyMap() }
|
||||
@@ -351,22 +353,24 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test fun `skips unknown type`() { profile.decodeBattery(batteryMessage(0x01, 0x10, 0x00, 50, 0x02, 0x00))!! shouldBe emptyMap() }
|
||||
@Test fun `handles truncated entry`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 50))!! shouldBe emptyMap() }
|
||||
@Test fun `non-battery message returns null`() { profile.decodeBattery(settingsMessage(0x0D, 0x02)).shouldBeNull() }
|
||||
@Test fun `zero percent is valid`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 0, 0x01, 0x00))!![BatteryType.LEFT]!!.percent shouldBe 0f }
|
||||
@Test fun `100 percent is valid`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 100, 0x02, 0x00))!![BatteryType.LEFT]!!.percent shouldBe 1f }
|
||||
@Test
|
||||
fun `zero percent is valid`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 0, 0x01, 0x00))!![AapPodState.BatteryType.LEFT]!!.percent shouldBe 0f }
|
||||
@Test
|
||||
fun `100 percent is valid`() { profile.decodeBattery(batteryMessage(0x01, 0x04, 0x00, 100, 0x02, 0x00))!![AapPodState.BatteryType.LEFT]!!.percent shouldBe 1f }
|
||||
|
||||
@Test
|
||||
fun `CHARGING_OPTIMIZED state 0x05`() {
|
||||
val r = profile.decodeBattery(batteryMessage(0x03, 0x04, 0x01, 80, 0x05, 0x01, 0x02, 0x01, 79, 0x05, 0x01, 0x08, 0x01, 48, 0x01, 0x01))!!
|
||||
r[BatteryType.LEFT]!!.charging shouldBe ChargingState.CHARGING_OPTIMIZED
|
||||
r[BatteryType.RIGHT]!!.charging shouldBe ChargingState.CHARGING_OPTIMIZED
|
||||
r[BatteryType.CASE]!!.charging shouldBe ChargingState.CHARGING
|
||||
r[AapPodState.BatteryType.LEFT]!!.charging shouldBe AapPodState.ChargingState.CHARGING_OPTIMIZED
|
||||
r[AapPodState.BatteryType.RIGHT]!!.charging shouldBe AapPodState.ChargingState.CHARGING_OPTIMIZED
|
||||
r[AapPodState.BatteryType.CASE]!!.charging shouldBe AapPodState.ChargingState.CHARGING
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `pods out of case, case disconnected`() {
|
||||
val r = profile.decodeBattery(batteryMessage(0x03, 0x04, 0x01, 80, 0x02, 0x01, 0x02, 0x01, 77, 0x02, 0x01, 0x08, 0x01, 0, 0x04, 0x01))!!
|
||||
r[BatteryType.CASE]!!.percent shouldBe 0f
|
||||
r[BatteryType.CASE]!!.charging shouldBe ChargingState.DISCONNECTED
|
||||
r[AapPodState.BatteryType.CASE]!!.percent shouldBe 0f
|
||||
r[AapPodState.BatteryType.CASE]!!.charging shouldBe AapPodState.ChargingState.DISCONNECTED
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -374,9 +378,9 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
val msg = aapMessage("04 00 04 00 04 00 03 04 01 50 05 01 02 01 4F 05 01 08 01 30 01 01")
|
||||
val r = profile.decodeBattery(msg)!!
|
||||
r.size shouldBe 3
|
||||
r[BatteryType.LEFT]!!.percent shouldBe 0.8f
|
||||
r[BatteryType.RIGHT]!!.percent shouldBe 0.79f
|
||||
r[BatteryType.CASE]!!.percent shouldBe 0.48f
|
||||
r[AapPodState.BatteryType.LEFT]!!.percent shouldBe 0.8f
|
||||
r[AapPodState.BatteryType.RIGHT]!!.percent shouldBe 0.79f
|
||||
r[AapPodState.BatteryType.CASE]!!.percent shouldBe 0.48f
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +401,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
val enc = ByteArray(16) { 0x22.toByte() }
|
||||
val payload = byteArrayOf(0x02, 0x01, 0x00, 16, 0x00, *irk, 0x04, 0x00, 16, 0x00, *enc)
|
||||
val raw = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x31, 0x00) + payload
|
||||
val result = profile.decodePrivateKeyResponse(AapMessage.parse(raw)!!)!!
|
||||
val result = profile.decodePrivateKeyResponse(AapMessage.Companion.parse(raw)!!)!!
|
||||
result.irk shouldBe irk
|
||||
result.encKey shouldBe enc
|
||||
}
|
||||
@@ -406,7 +410,7 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
fun `decode response with only IRK`() {
|
||||
val irk = ByteArray(16) { 0xAA.toByte() }
|
||||
val raw = byteArrayOf(0x04, 0x00, 0x04, 0x00, 0x31, 0x00, 0x01, 0x01, 0x00, 16, 0x00, *irk)
|
||||
val result = profile.decodePrivateKeyResponse(AapMessage.parse(raw)!!)!!
|
||||
val result = profile.decodePrivateKeyResponse(AapMessage.Companion.parse(raw)!!)!!
|
||||
result.irk shouldBe irk
|
||||
result.encKey.shouldBeNull()
|
||||
}
|
||||
@@ -421,4 +425,4 @@ class DefaultAapDeviceProfileTest : BaseAapSessionTest() {
|
||||
@Test fun `unknown setting ID returns null`() { profile.decodeSetting(settingsMessage(0x7F, 0x01)).shouldBeNull() }
|
||||
@Test fun `non-settings command returns null`() { profile.decodeSetting(aapMessage("04 00 04 00 1D 00 01 02 03 04")).shouldBeNull() }
|
||||
@Test fun `payload too short returns null`() { profile.decodeSetting(aapMessage("04 00 04 00 09 00 0D")).shouldBeNull() }
|
||||
}
|
||||
}
|
||||
+31
-44
@@ -1,22 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState.BatteryType
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState.ChargingState
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.AdaptiveAudioNoise
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.AncMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ConversationalAwareness
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ConversationalAwarenessState
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic.EndCallMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.EndCallMuteMic.MuteMicMode
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.NcWithOneAirPod
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PersonalizedVolume
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PressHoldDuration
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.PressSpeed
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.ToneVolume
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.VolumeSwipe
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapSetting.VolumeSwipeLength
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.AapSetting
|
||||
import eu.darken.capod.pods.core.apple.aap.protocol.BaseAapSessionTest
|
||||
import io.kotest.matchers.collections.shouldContainExactly
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
@@ -79,18 +66,18 @@ class AirPodsPro3AapSessionTest : BaseAapSessionTest() {
|
||||
fun `in case charging - pods CHARGING_OPTIMIZED, case CHARGING`() {
|
||||
val r =
|
||||
profile.decodeBattery(aapMessage("04 00 04 00 04 00 03 04 01 50 05 01 02 01 4F 05 01 08 01 30 01 01"))!!
|
||||
r[BatteryType.LEFT]!!.let { it.percent shouldBe 0.8f; it.charging shouldBe ChargingState.CHARGING_OPTIMIZED }
|
||||
r[BatteryType.RIGHT]!!.let { it.percent shouldBe 0.79f; it.charging shouldBe ChargingState.CHARGING_OPTIMIZED }
|
||||
r[BatteryType.CASE]!!.let { it.percent shouldBe 0.48f; it.charging shouldBe ChargingState.CHARGING }
|
||||
r[AapPodState.BatteryType.LEFT]!!.let { it.percent shouldBe 0.8f; it.charging shouldBe AapPodState.ChargingState.CHARGING_OPTIMIZED }
|
||||
r[AapPodState.BatteryType.RIGHT]!!.let { it.percent shouldBe 0.79f; it.charging shouldBe AapPodState.ChargingState.CHARGING_OPTIMIZED }
|
||||
r[AapPodState.BatteryType.CASE]!!.let { it.percent shouldBe 0.48f; it.charging shouldBe AapPodState.ChargingState.CHARGING }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `out of case - pods NOT_CHARGING, case DISCONNECTED`() {
|
||||
val r =
|
||||
profile.decodeBattery(aapMessage("04 00 04 00 04 00 03 02 01 4D 02 01 04 01 50 02 01 08 01 00 04 01"))!!
|
||||
r[BatteryType.RIGHT]!!.charging shouldBe ChargingState.NOT_CHARGING
|
||||
r[BatteryType.LEFT]!!.charging shouldBe ChargingState.NOT_CHARGING
|
||||
r[BatteryType.CASE]!!.charging shouldBe ChargingState.DISCONNECTED
|
||||
r[AapPodState.BatteryType.RIGHT]!!.charging shouldBe AapPodState.ChargingState.NOT_CHARGING
|
||||
r[AapPodState.BatteryType.LEFT]!!.charging shouldBe AapPodState.ChargingState.NOT_CHARGING
|
||||
r[AapPodState.BatteryType.CASE]!!.charging shouldBe AapPodState.ChargingState.DISCONNECTED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,57 +103,57 @@ class AirPodsPro3AapSessionTest : BaseAapSessionTest() {
|
||||
@Nested
|
||||
inner class SettingsSessionTests {
|
||||
@Test fun `ANC mode ON`() {
|
||||
val anc = decodeSetting<AncMode>("04 00 04 00 09 00 0D 02 00 00 00")
|
||||
anc.current shouldBe AncMode.Value.ON
|
||||
val anc = decodeSetting<AapSetting.AncMode>("04 00 04 00 09 00 0D 02 00 00 00")
|
||||
anc.current shouldBe AapSetting.AncMode.Value.ON
|
||||
anc.supported shouldContainExactly listOf(
|
||||
AncMode.Value.ON,
|
||||
AncMode.Value.TRANSPARENCY,
|
||||
AncMode.Value.ADAPTIVE
|
||||
AapSetting.AncMode.Value.ON,
|
||||
AapSetting.AncMode.Value.TRANSPARENCY,
|
||||
AapSetting.AncMode.Value.ADAPTIVE
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun `press hold duration DEFAULT`() {
|
||||
decodeSetting<PressHoldDuration>("04 00 04 00 09 00 18 00 00 00 00").value shouldBe PressHoldDuration.Value.DEFAULT
|
||||
decodeSetting<AapSetting.PressHoldDuration>("04 00 04 00 09 00 18 00 00 00 00").value shouldBe AapSetting.PressHoldDuration.Value.DEFAULT
|
||||
}
|
||||
|
||||
@Test fun `press speed DEFAULT`() {
|
||||
decodeSetting<PressSpeed>("04 00 04 00 09 00 17 00 00 00 00").value shouldBe PressSpeed.Value.DEFAULT
|
||||
decodeSetting<AapSetting.PressSpeed>("04 00 04 00 09 00 17 00 00 00 00").value shouldBe AapSetting.PressSpeed.Value.DEFAULT
|
||||
}
|
||||
|
||||
@Test fun `volume swipe ON`() {
|
||||
decodeSetting<VolumeSwipe>("04 00 04 00 09 00 25 01 00 00 00").enabled shouldBe true
|
||||
decodeSetting<AapSetting.VolumeSwipe>("04 00 04 00 09 00 25 01 00 00 00").enabled shouldBe true
|
||||
}
|
||||
|
||||
@Test fun `volume swipe length DEFAULT`() {
|
||||
decodeSetting<VolumeSwipeLength>("04 00 04 00 09 00 23 00 00 00 00").value shouldBe VolumeSwipeLength.Value.DEFAULT
|
||||
decodeSetting<AapSetting.VolumeSwipeLength>("04 00 04 00 09 00 23 00 00 00 00").value shouldBe AapSetting.VolumeSwipeLength.Value.DEFAULT
|
||||
}
|
||||
|
||||
@Test fun `tone volume 80`() {
|
||||
decodeSetting<ToneVolume>("04 00 04 00 09 00 1F 50 50 00 00").level shouldBe 0x50
|
||||
decodeSetting<AapSetting.ToneVolume>("04 00 04 00 09 00 1F 50 50 00 00").level shouldBe 0x50
|
||||
}
|
||||
|
||||
@Test fun `end call mute mic - subtype 0x00`() {
|
||||
decodeSetting<EndCallMuteMic>("04 00 04 00 09 00 24 00 03 00 00").let { it.muteMic shouldBe MuteMicMode.DOUBLE_PRESS; it.endCall shouldBe EndCallMode.SINGLE_PRESS }
|
||||
decodeSetting<AapSetting.EndCallMuteMic>("04 00 04 00 09 00 24 00 03 00 00").let { it.muteMic shouldBe AapSetting.EndCallMuteMic.MuteMicMode.DOUBLE_PRESS; it.endCall shouldBe AapSetting.EndCallMuteMic.EndCallMode.SINGLE_PRESS }
|
||||
}
|
||||
|
||||
@Test fun `conversational awareness OFF`() {
|
||||
decodeSetting<ConversationalAwareness>("04 00 04 00 09 00 28 02 00 00 00").enabled shouldBe false
|
||||
decodeSetting<AapSetting.ConversationalAwareness>("04 00 04 00 09 00 28 02 00 00 00").enabled shouldBe false
|
||||
}
|
||||
|
||||
@Test fun `conversational awareness ON after reconnect`() {
|
||||
decodeSetting<ConversationalAwareness>("04 00 04 00 09 00 28 01 00 00 00").enabled shouldBe true
|
||||
decodeSetting<AapSetting.ConversationalAwareness>("04 00 04 00 09 00 28 01 00 00 00").enabled shouldBe true
|
||||
}
|
||||
|
||||
@Test fun `personalized volume OFF`() {
|
||||
decodeSetting<PersonalizedVolume>("04 00 04 00 09 00 26 02 00 00 00").enabled shouldBe false
|
||||
decodeSetting<AapSetting.PersonalizedVolume>("04 00 04 00 09 00 26 02 00 00 00").enabled shouldBe false
|
||||
}
|
||||
|
||||
@Test fun `adaptive audio noise 50`() {
|
||||
decodeSetting<AdaptiveAudioNoise>("04 00 04 00 09 00 2E 32 00 00 00").level shouldBe 0x32
|
||||
decodeSetting<AapSetting.AdaptiveAudioNoise>("04 00 04 00 09 00 2E 32 00 00 00").level shouldBe 0x32
|
||||
}
|
||||
|
||||
@Test fun `NC one airpod OFF`() {
|
||||
decodeSetting<NcWithOneAirPod>("04 00 04 00 09 00 1B 02 00 00 00").enabled shouldBe false
|
||||
decodeSetting<AapSetting.NcWithOneAirPod>("04 00 04 00 09 00 1B 02 00 00 00").enabled shouldBe false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,11 +162,11 @@ class AirPodsPro3AapSessionTest : BaseAapSessionTest() {
|
||||
@Nested
|
||||
inner class AncModeSwitchingTests {
|
||||
@Test fun `device echoes TRANSPARENCY`() {
|
||||
decodeSetting<AncMode>("04 00 04 00 09 00 0D 03 00 00 00").current shouldBe AncMode.Value.TRANSPARENCY
|
||||
decodeSetting<AapSetting.AncMode>("04 00 04 00 09 00 0D 03 00 00 00").current shouldBe AapSetting.AncMode.Value.TRANSPARENCY
|
||||
}
|
||||
|
||||
@Test fun `device echoes ADAPTIVE`() {
|
||||
decodeSetting<AncMode>("04 00 04 00 09 00 0D 04 00 00 00").current shouldBe AncMode.Value.ADAPTIVE
|
||||
decodeSetting<AapSetting.AncMode>("04 00 04 00 09 00 0D 04 00 00 00").current shouldBe AapSetting.AncMode.Value.ADAPTIVE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +174,7 @@ class AirPodsPro3AapSessionTest : BaseAapSessionTest() {
|
||||
|
||||
@Test
|
||||
fun `conversation awareness state - not speaking`() {
|
||||
decodeSetting<ConversationalAwarenessState>("04 00 04 00 4B 00 00").speaking shouldBe false
|
||||
decodeSetting<AapSetting.ConversationalAwarenessState>("04 00 04 00 4B 00 00").speaking shouldBe false
|
||||
}
|
||||
|
||||
// ── Unhandled Messages ───────────────────────────────────
|
||||
@@ -210,4 +197,4 @@ class AirPodsPro3AapSessionTest : BaseAapSessionTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap.protocol
|
||||
|
||||
import io.kotest.matchers.collections.shouldBeEmpty
|
||||
import io.kotest.matchers.collections.shouldHaveSize
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap.protocol
|
||||
|
||||
import io.kotest.matchers.nulls.shouldBeNull
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
package eu.darken.capod.pods.core.apple.protocol.aap
|
||||
package eu.darken.capod.pods.core.apple.aap.protocol
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import testhelpers.BaseTest
|
||||
|
||||
/**
|
||||
* Shared base for AAP protocol tests. Provides hex parsing, message builders,
|
||||
* and type-safe setting extraction — mirrors [eu.darken.capod.pods.core.apple.BaseBlePodsTest]
|
||||
* and type-safe setting extraction — mirrors [eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest]
|
||||
* for the BLE path.
|
||||
*
|
||||
* Subclasses set [podModel] to get a correctly-configured [profile].
|
||||
+7
-5
@@ -1,9 +1,11 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
package eu.darken.capod.pods.core.apple.ble
|
||||
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.airpods.AirPodsGen1
|
||||
import eu.darken.capod.pods.core.apple.airpods.AirPodsPro
|
||||
import eu.darken.capod.pods.core.apple.misc.UnknownAppleSnapshotBle
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.ApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.airpods.AirPodsGen1
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.airpods.AirPodsPro
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.misc.UnknownAppleSnapshotBle
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.types.instanceOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
+5
-3
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
package eu.darken.capod.pods.core.apple.ble.devices
|
||||
|
||||
import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
@@ -6,8 +6,10 @@ import eu.darken.capod.common.SystemClockWrap
|
||||
import eu.darken.capod.common.bluetooth.BleScanResult
|
||||
import eu.darken.capod.common.fromHex
|
||||
import eu.darken.capod.common.serialization.SerializationModule
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.protocol.ContinuityProtocol
|
||||
import eu.darken.capod.pods.core.apple.ble.AppleFactory
|
||||
import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.ble.AppleFactoryModule
|
||||
import eu.darken.capod.pods.core.apple.ble.protocol.ContinuityProtocol
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import io.mockk.MockKAnnotations
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
package eu.darken.capod.pods.core.apple.ble.devices
|
||||
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
package eu.darken.capod.pods.core.apple.ble.devices
|
||||
|
||||
import eu.darken.capod.pods.core.apple.airpods.HasStateDetectionAirPods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.airpods.HasStateDetectionAirPods
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package eu.darken.capod.pods.core.apple
|
||||
package eu.darken.capod.pods.core.apple.ble.devices
|
||||
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+5
-5
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.common.isBitSet
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package eu.darken.capod.pods.core.apple.airpods
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.airpods
|
||||
|
||||
import eu.darken.capod.common.toHex
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.airpods.HasStateDetectionAirPods
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.airpods.HasStateDetectionAirPods
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
package eu.darken.capod.pods.core.apple.beats
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.beats
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.HasAppleColor
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.HasAppleColor
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.misc
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.misc
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.misc
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.misc
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.misc
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.misc
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.misc
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.misc
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package eu.darken.capod.pods.core.apple.misc
|
||||
package eu.darken.capod.pods.core.apple.ble.devices.misc
|
||||
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.BaseBlePodsTest
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.BaseBlePodsTest
|
||||
import io.kotest.matchers.shouldBe
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -3,16 +3,14 @@ package eu.darken.capod.reaction.core.aap
|
||||
import eu.darken.capod.common.bluetooth.BluetoothDevice2
|
||||
import eu.darken.capod.common.bluetooth.BluetoothManager2
|
||||
import eu.darken.capod.monitor.core.BlePodMonitor
|
||||
import eu.darken.capod.pods.core.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.PodModel
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapConnectionManager
|
||||
import eu.darken.capod.pods.core.apple.ble.BlePodSnapshot
|
||||
import eu.darken.capod.pods.core.apple.PodModel
|
||||
import eu.darken.capod.pods.core.apple.aap.AapConnectionManager
|
||||
|
||||
import eu.darken.capod.pods.core.apple.protocol.aap.AapPodState
|
||||
import eu.darken.capod.pods.core.apple.aap.AapPodState
|
||||
import eu.darken.capod.profiles.core.AppleDeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfile
|
||||
import eu.darken.capod.profiles.core.DeviceProfilesRepo
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
@@ -29,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import testhelpers.BaseTest
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class AapAutoConnectTest : BaseTest() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.darken.capod.reaction.core.autoconnect
|
||||
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.mockk
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package eu.darken.capod.reaction.core.popup
|
||||
|
||||
import eu.darken.capod.pods.core.apple.DualApplePods
|
||||
import eu.darken.capod.pods.core.apple.ble.devices.DualApplePods
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.mockk.mockk
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
|
||||
Reference in New Issue
Block a user