Implement Resource Checker for Hardware Capability Detection
Status Fixed / completed
Maintainer reply None cached
Activity 2 comments · opened Oct 20, 2025 · 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 ↗