From 980fd384212365fb8ef89c6bf2753795bffcecd1 Mon Sep 17 00:00:00 2001 From: mxhsnd <2049295946@qq.com> Date: Mon, 24 Aug 2026 11:32:03 +0800 Subject: [PATCH] feat: route infrared debug hardware modes --- android/app/build.gradle.kts | 1 + android/app/src/debug/AndroidManifest.xml | 4 ++ .../manager/di/DebugRoutingInfraredGateway.kt | 41 +++++++++++ .../abox/manager/di/InfraredReleaseModule.kt | 47 +++++++++++++ .../di/DebugRoutingInfraredGatewayTest.kt | 70 +++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/debug/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGateway.kt create mode 100644 android/app/src/release/kotlin/com/flagship/abox/manager/di/InfraredReleaseModule.kt create mode 100644 android/app/src/test/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGatewayTest.kt diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index f8843f4..08eb8de 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -64,6 +64,7 @@ dependencies { implementation(project(":domain")) implementation(project(":android:core:designsystem")) implementation(project(":android:core:session")) + implementation(project(":android:feature:infrared")) implementation(project(":absdk-bridge")) implementation(project(":runtime:simulation")) debugImplementation(project(":testing:fakes")) diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..c0638bc --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android/app/src/debug/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGateway.kt b/android/app/src/debug/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGateway.kt new file mode 100644 index 0000000..b3b6c01 --- /dev/null +++ b/android/app/src/debug/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGateway.kt @@ -0,0 +1,41 @@ +package com.flagship.abox.manager.di + +import com.flagship.abox.manager.domain.DeviceName +import com.flagship.abox.manager.domain.DomainResult +import com.flagship.abox.manager.domain.InfraredCode +import com.flagship.abox.manager.domain.InfraredCodeDownloadResult +import com.flagship.abox.manager.domain.InfraredGateway +import com.flagship.abox.manager.domain.ProviderProfileId +import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeMode +import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeModeStore + +class DebugRoutingInfraredGateway( + private val modeStore: InfraredRuntimeModeStore, + private val fakeGateway: InfraredGateway, + private val realGateway: InfraredGateway, +) : InfraredGateway { + + private suspend fun delegate(): InfraredGateway { + return when (modeStore.currentMode()) { + InfraredRuntimeMode.REAL_ABSDK -> realGateway + InfraredRuntimeMode.FAKE -> fakeGateway + } + } + + override suspend fun sendKey( + profileId: ProviderProfileId, + deviceName: DeviceName, + key: String, + ): DomainResult = delegate().sendKey(profileId, deviceName, key) + + override suspend fun learnKey( + profileId: ProviderProfileId, + deviceName: DeviceName, + key: String, + ): DomainResult = delegate().learnKey(profileId, deviceName, key) + + override suspend fun downloadCodes( + profileId: ProviderProfileId, + codes: List, + ): DomainResult> = delegate().downloadCodes(profileId, codes) +} diff --git a/android/app/src/release/kotlin/com/flagship/abox/manager/di/InfraredReleaseModule.kt b/android/app/src/release/kotlin/com/flagship/abox/manager/di/InfraredReleaseModule.kt new file mode 100644 index 0000000..705c2b0 --- /dev/null +++ b/android/app/src/release/kotlin/com/flagship/abox/manager/di/InfraredReleaseModule.kt @@ -0,0 +1,47 @@ +package com.flagship.abox.manager.di + +import com.flagship.abox.manager.domain.DeviceName +import com.flagship.abox.manager.domain.DomainError +import com.flagship.abox.manager.domain.DomainResult +import com.flagship.abox.manager.domain.InfraredCode +import com.flagship.abox.manager.domain.InfraredCodeDownloadResult +import com.flagship.abox.manager.domain.InfraredGateway +import com.flagship.abox.manager.domain.ProviderProfileId +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object InfraredReleaseModule { + + @Provides + @Singleton + fun provideInfraredGateway(): InfraredGateway = object : InfraredGateway { + override suspend fun sendKey( + profileId: ProviderProfileId, + deviceName: DeviceName, + key: String, + ): DomainResult = disabledFailure() + + override suspend fun learnKey( + profileId: ProviderProfileId, + deviceName: DeviceName, + key: String, + ): DomainResult = disabledFailure() + + override suspend fun downloadCodes( + profileId: ProviderProfileId, + codes: List, + ): DomainResult> = disabledFailure() + + private fun disabledFailure(): DomainResult = DomainResult.Failure( + DomainError.OperationFailed( + externalCode = "REAL_ABSDK_DISABLED", + detail = "Infrared hardware transport is disabled in release builds", + ), + ) + } +} diff --git a/android/app/src/test/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGatewayTest.kt b/android/app/src/test/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGatewayTest.kt new file mode 100644 index 0000000..339dc83 --- /dev/null +++ b/android/app/src/test/kotlin/com/flagship/abox/manager/di/DebugRoutingInfraredGatewayTest.kt @@ -0,0 +1,70 @@ +package com.flagship.abox.manager.di + +import com.flagship.abox.manager.domain.DeviceName +import com.flagship.abox.manager.domain.DomainResult +import com.flagship.abox.manager.domain.InfraredCode +import com.flagship.abox.manager.domain.ProviderProfileId +import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeMode +import com.flagship.abox.manager.infrared.runtime.InfraredRuntimeModeStore +import com.flagship.abox.manager.testing.fakes.FakeInfraredGateway +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +private class TestModeStore : InfraredRuntimeModeStore { + private val modeFlow = MutableStateFlow(InfraredRuntimeMode.FAKE) + override val mode: Flow = modeFlow + override suspend fun currentMode(): InfraredRuntimeMode = modeFlow.value + override suspend fun setMode(mode: InfraredRuntimeMode): DomainResult { + modeFlow.value = mode + return DomainResult.Success(Unit) + } +} + +class DebugRoutingInfraredGatewayTest { + + private val modeStore = TestModeStore() + private val fake = FakeInfraredGateway() + private val real = FakeInfraredGateway() + private val router = DebugRoutingInfraredGateway(modeStore, fake, real) + + private val profile = ProviderProfileId("profile1") + private val device = DeviceName("ir-1") + + @Test + fun delegatesToFakeByDefault() = runTest { + val result = router.sendKey(profile, device, "key1") + assertTrue(result is DomainResult.Success) + assertEquals(1, fake.sentKeys.size) + assertTrue(real.sentKeys.isEmpty()) + + router.learnKey(profile, device, "key2") + assertEquals(1, fake.learnedKeys.size) + assertTrue(real.learnedKeys.isEmpty()) + + router.downloadCodes(profile, listOf(InfraredCode(device, "k", "code"))) + assertEquals(1, fake.downloadCalls.size) + assertTrue(real.downloadCalls.isEmpty()) + } + + @Test + fun delegatesToRealWhenModeIsRealAbsdk() = runTest { + modeStore.setMode(InfraredRuntimeMode.REAL_ABSDK) + + val result = router.sendKey(profile, device, "key1") + assertTrue(result is DomainResult.Success) + assertTrue(fake.sentKeys.isEmpty()) + assertEquals(1, real.sentKeys.size) + + router.learnKey(profile, device, "key2") + assertTrue(fake.learnedKeys.isEmpty()) + assertEquals(1, real.learnedKeys.size) + + router.downloadCodes(profile, listOf(InfraredCode(device, "k", "code"))) + assertTrue(fake.downloadCalls.isEmpty()) + assertEquals(1, real.downloadCalls.size) + } +}