Implement Resource Checker for Hardware Capability Detection
Resolved 💬 2 comments Opened Oct 20, 2025 by sanchitmonga22 Closed Oct 20, 2025
Priority
HIGH
Context
The Resource Checker monitors system resources (CPU, GPU, memory, thermal state) to determine which models can run efficiently. The iOS SDK has a complete ResourceChecker. The Kotlin SDK is missing this infrastructure.
Current State
- Status: Infrastructure does not exist
- Impact: Cannot determine optimal model selection based on device capabilities
- iOS Has: Complete ResourceChecker with hardware detection
iOS Reference Implementation
- Service:
sdk/runanywhere-swift/Sources/RunAnywhere/Infrastructure/ResourceChecker.swift - Detectors: ProcessorDetector, GPUDetector, NeuralEngineDetector, ThermalMonitor
iOS Architecture Pattern
public final class ResourceChecker: Sendable {
public func checkResources() async -> ResourceCapability
public var availableMemory: Int { get async }
public var thermalState: ThermalState { get async }
}
public struct ResourceCapability {
public let processorType: ProcessorType
public let gpuCapability: GPUCapability
public let neuralEngineAvailable: Bool
public let availableMemoryGB: Int
}
Implementation Plan
1. Define Common Interfaces (commonMain)
// commonMain/kotlin/com/runanywhere/sdk/infrastructure/resources/ResourceChecker.kt
interface ResourceChecker {
suspend fun checkResources(): ResourceCapability
val availableMemoryMB: Long
val thermalState: ThermalState
}
data class ResourceCapability(
val processorType: ProcessorType,
val gpuCapability: GPUCapability,
val acceleratorAvailable: Boolean,
val availableMemoryMB: Long,
val thermalState: ThermalState,
val batteryLevel: Int? = null
)
enum class ProcessorType {
ARM_V7, ARM_V8, ARM64, X86, X86_64, UNKNOWN
}
enum class GPUCapability {
NONE, LOW, MEDIUM, HIGH, ULTRA
}
enum class ThermalState {
NOMINAL, FAIR, SERIOUS, CRITICAL
}
2. Platform Implementations
Android (androidMain)
// androidMain/kotlin/com/runanywhere/sdk/infrastructure/resources/AndroidResourceChecker.kt
class AndroidResourceChecker(
private val context: Context
) : ResourceChecker {
private val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
private val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
override suspend fun checkResources(): ResourceCapability {
return ResourceCapability(
processorType = detectProcessorType(),
gpuCapability = detectGPUCapability(),
acceleratorAvailable = detectNNAPISupport(),
availableMemoryMB = availableMemoryMB,
thermalState = thermalState,
batteryLevel = getBatteryLevel()
)
}
override val availableMemoryMB: Long
get() {
val memInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memInfo)
return memInfo.availMem / (1024 * 1024)
}
override val thermalState: ThermalState
get() {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val thermalService = context.getSystemService(PowerManager::class.java)
when (thermalService.currentThermalStatus) {
PowerManager.THERMAL_STATUS_NONE -> ThermalState.NOMINAL
PowerManager.THERMAL_STATUS_LIGHT -> ThermalState.FAIR
PowerManager.THERMAL_STATUS_MODERATE -> ThermalState.SERIOUS
else -> ThermalState.CRITICAL
}
} else {
ThermalState.NOMINAL
}
}
private fun detectProcessorType(): ProcessorType {
val abi = Build.SUPPORTED_ABIS.firstOrNull() ?: ""
return when {
abi.contains("arm64") -> ProcessorType.ARM64
abi.contains("armeabi") -> ProcessorType.ARM_V7
abi.contains("x86_64") -> ProcessorType.X86_64
abi.contains("x86") -> ProcessorType.X86
else -> ProcessorType.UNKNOWN
}
}
private fun detectGPUCapability(): GPUCapability {
val glRenderer = try {
val glView = GLSurfaceView(context)
// Get GL_RENDERER string
"Unknown"
} catch (e: Exception) {
"Unknown"
}
return when {
glRenderer.contains("Adreno 7") -> GPUCapability.ULTRA
glRenderer.contains("Adreno 6") -> GPUCapability.HIGH
glRenderer.contains("Mali-G") -> GPUCapability.HIGH
glRenderer.contains("Adreno 5") -> GPUCapability.MEDIUM
else -> GPUCapability.LOW
}
}
private fun detectNNAPISupport(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
}
private fun getBatteryLevel(): Int {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
}
}
JVM (jvmMain)
// jvmMain/kotlin/com/runanywhere/sdk/infrastructure/resources/JvmResourceChecker.kt
class JvmResourceChecker : ResourceChecker {
private val runtime = Runtime.getRuntime()
private val osBean = ManagementFactory.getOperatingSystemMXBean()
override suspend fun checkResources(): ResourceCapability {
return ResourceCapability(
processorType = detectProcessorType(),
gpuCapability = detectGPUCapability(),
acceleratorAvailable = false, // No NNAPI on JVM
availableMemoryMB = availableMemoryMB,
thermalState = ThermalState.NOMINAL, // No thermal API on JVM
batteryLevel = null
)
}
override val availableMemoryMB: Long
get() = runtime.freeMemory() / (1024 * 1024)
override val thermalState: ThermalState
get() = ThermalState.NOMINAL
private fun detectProcessorType(): ProcessorType {
val arch = System.getProperty("os.arch").lowercase()
return when {
arch.contains("aarch64") -> ProcessorType.ARM64
arch.contains("arm") -> ProcessorType.ARM_V8
arch.contains("amd64") || arch.contains("x86_64") -> ProcessorType.X86_64
arch.contains("x86") -> ProcessorType.X86
else -> ProcessorType.UNKNOWN
}
}
private fun detectGPUCapability(): GPUCapability {
// Try to detect GPU via system properties
return GPUCapability.MEDIUM // Default for desktop
}
}
Files to Create/Modify
New Files (commonMain)
- [ ]
infrastructure/resources/ResourceChecker.kt - [ ]
infrastructure/resources/models/ResourceCapability.kt - [ ]
infrastructure/resources/models/ProcessorType.kt - [ ]
infrastructure/resources/models/GPUCapability.kt - [ ]
infrastructure/resources/models/ThermalState.kt
New Files (androidMain)
- [ ]
infrastructure/resources/AndroidResourceChecker.kt
New Files (jvmMain)
- [ ]
infrastructure/resources/JvmResourceChecker.kt
Files to Modify
- [ ]
foundation/ServiceContainer.kt(add resource checker)
Testing Requirements
- [ ] Unit tests for ResourceCapability
- [ ] Android platform tests (memory, thermal, processor)
- [ ] JVM platform tests
- [ ] GPU detection tests
- [ ] NNAPI detection tests
- [ ] Battery monitoring tests
Success Criteria
- [ ] Correctly detects processor type on Android and JVM
- [ ] Accurately reports available memory
- [ ] Thermal state monitoring works on Android
- [ ] GPU capability detection is accurate
- [ ] NNAPI support detection works
- [ ] Integrated into ServiceContainer
Estimated Effort
1-2 weeks (80-100 hours)
Dependencies
- Depends on: #147 (privacy-first logging)
- Blocks: Model selection optimization
- Related to: #148 (DeviceCapability)
🤖 Generated with Claude Code
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗