GameBar: Add dynamic CPU temp detection
- Replace static overlays with runtime detection for CPU temp sensors - Add smart temperature format detection and caching - Support multiple device manufacturers and kernel variants (still need testing on older devices just was tested on 5.4(lahaina),5.10(taro),6.1(Pineapple) platforms include more sepolicy and clean some for our project Change-Id: Iaa0714b6df687203644a13da03ad048472c40164 Signed-off-by: klozz <carlosj@klozz.dev>
This commit is contained in:
@@ -6,11 +6,6 @@
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<!-- GameBar Device Paths Configuration -->
|
||||
<!-- CPU Configuration -->
|
||||
<string name="config_cpu_base_path" translatable="false">/sys/devices/system/cpu</string>
|
||||
<string name="config_cpu_temp_path" translatable="false">/sys/class/thermal/thermal_zone48/temp</string>
|
||||
<integer name="config_cpu_temp_divider">1000</integer>
|
||||
|
||||
<!-- GPU Configuration -->
|
||||
<string name="config_gpu_usage_path" translatable="false">/sys/class/kgsl/kgsl-3d0/gpu_busy_percentage</string>
|
||||
<string name="config_gpu_clock_path" translatable="false">/sys/class/kgsl/kgsl-3d0/gpuclk</string>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
settingsdebug.instant.packages u:object_r:settingslib_prop:s0
|
||||
@@ -1,2 +0,0 @@
|
||||
# SettingsLib
|
||||
system_public_prop(settingslib_prop)
|
||||
8
sepolicy/vendor/gamebar_app.te
vendored
8
sepolicy/vendor/gamebar_app.te
vendored
@@ -4,5 +4,13 @@ allow gamebar_app vendor_sysfs_kgsl:dir search;
|
||||
allow gamebar_app vendor_sysfs_kgsl:{ file lnk_file } rw_file_perms;
|
||||
allow gamebar_app vendor_sysfs_battery_supply:dir search;
|
||||
allow gamebar_app vendor_sysfs_battery_supply:file r_file_perms;
|
||||
allow gamebar_app vendor_sysfs_usb_supply:dir search;
|
||||
allow gamebar_app vendor_sysfs_usb_supply:file r_file_perms;
|
||||
allow gamebar_app proc_stat:file { read open getattr };
|
||||
allow gamebar_app vendor_sysfs_kgsl_gpuclk:file { read open getattr };
|
||||
|
||||
allow zygote gamebar_app:process dyntransition;
|
||||
allow gamebar_app self:process dyntransition;
|
||||
|
||||
allow gamebar_app hal_graphics_mapper_hwservice:hwservice_manager find;
|
||||
allow gamebar_app default_prop:file read;
|
||||
2
sepolicy/vendor/genfs_contexts
vendored
Normal file
2
sepolicy/vendor/genfs_contexts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# for battery nodes on GameBar
|
||||
genfscon sysfs /class/power_supply/battery/temp u:object_r:vendor_sysfs_battery_supply:s0
|
||||
@@ -41,13 +41,18 @@ object GameBarConfig {
|
||||
}
|
||||
|
||||
|
||||
// CPU configuration
|
||||
val cpuBasePath: String
|
||||
get() = context.getString(R.string.config_cpu_base_path)
|
||||
val cpuTempPath: String
|
||||
get() = context.getString(R.string.config_cpu_temp_path)
|
||||
// CPU configuration - now dynamic
|
||||
val cpuBasePath: String?
|
||||
get() = SysfsDetector.getCpuBasePath()
|
||||
|
||||
val cpuTempPath: String?
|
||||
get() = SysfsDetector.getCpuTempInfo().first
|
||||
val cpuTempDivider: Int
|
||||
get() = context.resources.getInteger(R.integer.config_cpu_temp_divider)
|
||||
get() = SysfsDetector.getCpuTempInfo().second
|
||||
|
||||
fun getCpuTempConfig(): Pair<String?, Int> {
|
||||
return SysfsDetector.getCpuTempInfo()
|
||||
}
|
||||
|
||||
// GPU configuration
|
||||
val gpuUsagePath: String
|
||||
@@ -82,7 +87,8 @@ object GameBarConfig {
|
||||
fun isSystemSupported(): Boolean {
|
||||
return listOf(
|
||||
SysfsDetector.getBatteryTempPath(),
|
||||
SysfsDetector.getFpsPath()
|
||||
SysfsDetector.getFpsPath(),
|
||||
SysfsDetector.getCpuTempPath()
|
||||
).any { it != null }
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,12 @@ object GameBarCpuInfo {
|
||||
|
||||
fun getCpuFrequencies(): List<String> {
|
||||
val result = mutableListOf<String>()
|
||||
val cpuDir = File(GameBarConfig.cpuBasePath)
|
||||
val basePath = GameBarConfig.cpuBasePath
|
||||
if (basePath == null) {
|
||||
return result
|
||||
}
|
||||
|
||||
val cpuDir = File(basePath)
|
||||
val files = cpuDir.listFiles { _, name -> name.matches(Regex("cpu\\d+")) }
|
||||
if (files.isNullOrEmpty()) {
|
||||
return result
|
||||
@@ -82,11 +87,14 @@ object GameBarCpuInfo {
|
||||
}
|
||||
|
||||
fun getCpuTemp(): String {
|
||||
val line = readLine(GameBarConfig.cpuTempPath) ?: return "N/A"
|
||||
val (path, divider) = GameBarConfig.getCpuTempConfig()
|
||||
if (path == null) return "N/A"
|
||||
|
||||
val line = readLine(path) ?: return "N/A"
|
||||
val cleanLine = line.trim()
|
||||
return try {
|
||||
val raw = cleanLine.toFloat()
|
||||
val celsius = raw / GameBarConfig.cpuTempDivider.toFloat()
|
||||
val celsius = raw / divider.toFloat()
|
||||
// Sanity check: CPU temp should be between 0 and 150°C
|
||||
if (celsius > 0f && celsius < 150f) {
|
||||
String.format(Locale.getDefault(), "%.1f", celsius)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.android.gamebar.utils
|
||||
import android.util.Log
|
||||
package com.android.gamebar.utils
|
||||
import android.util.Log
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@@ -72,6 +72,121 @@ object SysfsDetector {
|
||||
return Pair(path, divider)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically searches for CPU temperature node with type-based prioritization
|
||||
* For cpuss-0, cpuss-1, etc., selects the first available one
|
||||
*
|
||||
* @return The path to CPU temperature node or null if not found
|
||||
*/
|
||||
private fun findCpuTempPath(): String? {
|
||||
// Return cached path if available
|
||||
detectedPaths["cpu_temp"]?.let { return it }
|
||||
|
||||
val thermalBaseDirs = arrayOf(
|
||||
"/sys/class/thermal",
|
||||
"/sys/devices/virtual/thermal"
|
||||
)
|
||||
|
||||
// Priority order for CPU sensor types (most specific to least specific)
|
||||
// add more on newer or older devices
|
||||
val priorityTypes = arrayOf(
|
||||
"cpu_therm", // Highest priority - specific CPU thermal
|
||||
"cpuss", // CPU subsystem
|
||||
"cpu", // Generic CPU
|
||||
"cluster0" // CPU clusters
|
||||
)
|
||||
|
||||
// Scan all thermal base directories
|
||||
for (baseDirPath in thermalBaseDirs) {
|
||||
val baseDir = File(baseDirPath)
|
||||
if (!baseDir.exists() || !baseDir.isDirectory()) continue
|
||||
|
||||
Log.d(TAG, "Scanning thermal directory: $baseDirPath")
|
||||
|
||||
// First pass: search by priority type order
|
||||
for (priorityType in priorityTypes) {
|
||||
baseDir.listFiles()?.forEach { zone ->
|
||||
val typeFile = File(zone, "type")
|
||||
val tempFile = File(zone, "temp")
|
||||
|
||||
if (typeFile.exists() && tempFile.exists() && tempFile.canRead()) {
|
||||
try {
|
||||
val type = typeFile.readText().trim().lowercase()
|
||||
|
||||
// For cpuss, accept any cpuss-* variant (cpuss-0, cpuss-1, etc.)
|
||||
val isMatch = when {
|
||||
priorityType == "cpuss" && type.startsWith("cpuss") -> true
|
||||
else -> type == priorityType
|
||||
}
|
||||
|
||||
if (isMatch) {
|
||||
detectedPaths["cpu_temp"] = tempFile.absolutePath
|
||||
Log.d(TAG, "Found CPU temp (priority): ${tempFile.absolutePath} (type=$type)")
|
||||
return tempFile.absolutePath
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// Continue to next file on error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: search for any thermal zone that might be CPU-related
|
||||
baseDir.listFiles()?.forEach { zone ->
|
||||
val typeFile = File(zone, "type")
|
||||
val tempFile = File(zone, "temp")
|
||||
|
||||
if (typeFile.exists() && tempFile.exists() && tempFile.canRead()) {
|
||||
try {
|
||||
val type = typeFile.readText().trim().lowercase()
|
||||
|
||||
// Look for patterns indicating CPU sensor
|
||||
if (type.contains("cpu") ||
|
||||
type.contains("core") ||
|
||||
type.contains("cluster") ||
|
||||
type.contains("tsens") ||
|
||||
type.startsWith("thermal")) {
|
||||
|
||||
// Read value to verify it's a reasonable temperature
|
||||
val tempValue = tempFile.readText().trim().toIntOrNull()
|
||||
if (tempValue != null && tempValue in 20000..90000) { // 20-90°C in milli
|
||||
detectedPaths["cpu_temp"] = tempFile.absolutePath
|
||||
Log.d(TAG, "Found CPU temp (fallback): ${tempFile.absolutePath} (type=$type)")
|
||||
return tempFile.absolutePath
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
// Continue to next file on error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "No suitable CPU temperature node found")
|
||||
detectedPaths["cpu_temp"] = null
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets CPU temperature path and divider information
|
||||
*
|
||||
* @return Pair containing path and divider, or (null, 1000) if not found
|
||||
*/
|
||||
fun getCpuTempInfo(): Pair<String?, Int> {
|
||||
val path = getCpuTempPath()
|
||||
if (path == null) return Pair(null, 1000)
|
||||
|
||||
// Return cached divider if available
|
||||
if (detectedDividers.containsKey("cpu_temp")) {
|
||||
return Pair(path, detectedDividers["cpu_temp"]!!)
|
||||
}
|
||||
|
||||
// Auto-detect divider and cache it
|
||||
val divider = detectTemperatureDivider(path)
|
||||
detectedDividers["cpu_temp"] = divider
|
||||
return Pair(path, divider)
|
||||
}
|
||||
|
||||
// Possible paths for each hardware component
|
||||
private val BATTERY_TEMP_PATHS = arrayOf(
|
||||
"/sys/class/power_supply/battery/temp",
|
||||
@@ -118,6 +233,27 @@ object SysfsDetector {
|
||||
|
||||
fun getBatteryTempPath(): String? = detectPath("battery_temp", BATTERY_TEMP_PATHS)
|
||||
|
||||
/** @return CPU temperature sysfs path or null if not supported */
|
||||
fun getCpuTempPath(): String? = findCpuTempPath()
|
||||
|
||||
/** @return CPU base sysfs path*/
|
||||
fun getCpuBasePath(): String? {
|
||||
// Check cache first
|
||||
detectedPaths["cpu_base"]?.let { return it }
|
||||
|
||||
val path = "/sys/devices/system/cpu"
|
||||
val file = File(path)
|
||||
if (file.exists() && file.isDirectory()) {
|
||||
detectedPaths["cpu_base"] = path
|
||||
Log.d(TAG, "Using CPU base path: $path")
|
||||
return path
|
||||
}
|
||||
|
||||
Log.w(TAG, "CPU base path not found: $path")
|
||||
detectedPaths["cpu_base"] = null
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear cache and re-detect all paths (useful for debugging)
|
||||
*/
|
||||
@@ -128,11 +264,14 @@ object SysfsDetector {
|
||||
|
||||
/**
|
||||
* Check if a specific hardware component is supported
|
||||
* for future usage
|
||||
*/
|
||||
fun isComponentSupported(component: String): Boolean {
|
||||
return when (component) {
|
||||
"fps" -> getFpsPath() != null
|
||||
"battery_temp" -> getBatteryTempPath() != null
|
||||
"cpu_temp" -> getCpuTempPath() != null
|
||||
"cpu_base" -> getCpuBasePath() != null
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user