Compare commits

..

No commits in common. "264a45f4db891748a872eda9b4ea536049541970" and "a59073b0af86c954bf1ad70040e642709094cbcd" have entirely different histories.

10 changed files with 220 additions and 3055 deletions

View File

@ -1,3 +0,0 @@
{
"FSharp.suggestGitignore": false
}

View File

@ -1,263 +0,0 @@
# CpuInfo 核心详细信息使用示例
## 新增功能说明
`CpuInfo` 类新增了获取每个 CPU 核心详细信息的功能,包括:
- 每个核心的最大频率
- 每个核心的最小频率
- 每个核心的当前频率
- 每个核心的速度度量值
- 可用频率列表
## 核心数据类
### CoreDetailedInfo
```kotlin
data class CoreDetailedInfo(
val core: Core, // 核心基本信息
val currentFrequency: Long, // 当前频率Hz
val minFrequency: Long, // 最小频率Hz
val maxFrequency: Long, // 最大频率Hz
val availableFrequencies: List<Long>, // 可用频率列表Hz
val speedMetric: Double // 速度度量值GHz
)
```
## 使用示例
### 1. 获取所有核心的详细信息
```kotlin
val cpuInfo = CpuInfo()
// 获取所有核心的详细信息
val detailedCores = cpuInfo.getCoresDetailedInfo()
detailedCores.forEachIndexed { index, coreInfo ->
println("CPU $index:")
println(" 架构: ${coreInfo.core.uarch.name}")
println(" 供应商: ${coreInfo.core.vendor.name}")
println(" 当前频率: ${coreInfo.currentFrequency / 1_000_000} MHz")
println(" 最小频率: ${coreInfo.minFrequency / 1_000_000} MHz")
println(" 最大频率: ${coreInfo.maxFrequency / 1_000_000} MHz")
println(" 速度度量: ${String.format("%.2f GHz", coreInfo.speedMetric)}")
println(" 可用频率数量: ${coreInfo.availableFrequencies.size}")
}
```
### 2. 获取指定核心的详细信息
```kotlin
val cpuInfo = CpuInfo()
// 获取第一个核心(大核)的详细信息
val core0 = cpuInfo.getCoreDetailedInfo(0)
core0?.let {
println("大核信息:")
println("当前频率: ${it.currentFrequency / 1_000_000} MHz")
println("最大频率: ${it.maxFrequency / 1_000_000} MHz")
println("最小频率: ${it.minFrequency / 1_000_000} MHz")
println("速度度量: ${it.speedMetric} GHz")
}
```
### 3. 获取所有核心的频率列表
```kotlin
val cpuInfo = CpuInfo()
// 获取所有核心的最大频率
val maxFreqs = cpuInfo.getCoresMaxFrequencies()
println("所有核心最大频率: ${maxFreqs.map { it / 1_000_000 }} MHz")
// 获取所有核心的最小频率
val minFreqs = cpuInfo.getCoresMinFrequencies()
println("所有核心最小频率: ${minFreqs.map { it / 1_000_000 }} MHz")
// 获取所有核心的当前频率
val currentFreqs = cpuInfo.getCoresCurrentFrequencies()
println("所有核心当前频率: ${currentFreqs.map { it / 1_000_000 }} MHz")
// 获取所有核心的速度度量值
val speedMetrics = cpuInfo.getCoresSpeedMetrics()
println("所有核心速度度量: ${speedMetrics.map { String.format("%.2f", it) }} GHz")
```
### 4. 分析大小核配置
```kotlin
val cpuInfo = CpuInfo()
val detailedCores = cpuInfo.getCoresDetailedInfo()
// 按最大频率排序,找出大核和小核
val sortedByFreq = detailedCores.sortedByDescending { it.maxFrequency }
println("大核(性能核心):")
sortedByFreq.take(2).forEachIndexed { index, core ->
println(" 核心 ${core.core.processorStart}: ${core.core.uarch.name}, ${core.maxFrequency / 1_000_000} MHz")
}
println("\n小核效率核心:")
sortedByFreq.takeLast(6).forEach { core ->
println(" 核心 ${core.core.processorStart}: ${core.core.uarch.name}, ${core.maxFrequency / 1_000_000} MHz")
}
```
### 5. 监控实时频率变化
```kotlin
val cpuInfo = CpuInfo()
// 创建一个协程来监控频率变化
lifecycleScope.launch {
while (isActive) {
val currentFreqs = cpuInfo.getCoresCurrentFrequencies()
println("实时频率:")
currentFreqs.forEachIndexed { index, freq ->
println(" CPU$index: ${freq / 1_000_000} MHz")
}
delay(1000) // 每秒更新一次
}
}
```
### 6. 计算 CPU 负载百分比
```kotlin
val cpuInfo = CpuInfo()
val detailedCores = cpuInfo.getCoresDetailedInfo()
detailedCores.forEachIndexed { index, core ->
// 计算当前频率占最大频率的百分比
val loadPercentage = if (core.maxFrequency > 0) {
(core.currentFrequency.toDouble() / core.maxFrequency * 100)
} else {
0.0
}
println("CPU$index 负载: ${String.format("%.1f%%", loadPercentage)}")
}
```
### 7. 在 Compose UI 中显示
```kotlin
@Composable
fun CpuCoresList() {
val cpuInfo = remember { CpuInfo() }
var detailedCores by remember { mutableStateOf(cpuInfo.getCoresDetailedInfo()) }
// 自动刷新
LaunchedEffect(Unit) {
while (true) {
delay(1000)
detailedCores = cpuInfo.getCoresDetailedInfo()
}
}
LazyColumn {
itemsIndexed(detailedCores) { index, core ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "CPU $index",
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(8.dp))
Text("架构: ${core.core.uarch.name}")
Text("当前: ${core.currentFrequency / 1_000_000} MHz")
Text("范围: ${core.minFrequency / 1_000_000} - ${core.maxFrequency / 1_000_000} MHz")
Text("速度度量: ${String.format("%.2f GHz", core.speedMetric)}")
// 频率进度条
LinearProgressIndicator(
progress = if (core.maxFrequency > 0) {
core.currentFrequency.toFloat() / core.maxFrequency
} else 0f,
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp)
)
}
}
}
}
}
```
## 获取 CPU 性能摘要
使用 `text()` 方法可以获取完整的 CPU 信息摘要(包括新增的核心详细信息):
```kotlin
val cpuInfo = CpuInfo()
val summary = cpuInfo.text()
println(summary)
```
输出示例:
```
=== CPU Basic Info ===
Processor Name: Qualcomm Snapdragon 888
Vendor: ARM
Process: 5nm
Foundry: Samsung
Process Node: Samsung 5LPE
Physical Cores: 8
Logical Processors: 8
=== Core Cluster Configuration ===
Big Cores: 1, Max Frequency: 2.84 GHz
Mid Cores: 3, Max Frequency: 2.42 GHz
Little Cores: 4, Max Frequency: 1.80 GHz
=== Architecture Info ===
Architecture: Cortex-X1, Cortex-A78, Cortex-A55
ABI: arm64-v8a
Supported ABIs: arm64-v8a, armeabi-v7a, armeabi
=== Performance Metrics ===
Performance Level: Flagship
Performance Index: 95.2
Total Score: 17984.5
BogoMIPS: 38.40
=== Governor ===
Current Governor: schedutil
Available Governors: schedutil, performance, powersave
=== Core Detailed Info ===
CPU0: Current=2.84 GHz, Range=300 MHz-2.84 GHz, Metric=2.84 GHz, Arch=Cortex-X1
CPU1: Current=2.42 GHz, Range=300 MHz-2.42 GHz, Metric=2.42 GHz, Arch=Cortex-A78
...
```
## 注意事项
1. **频率单位**: 所有频率值都以 Hz赫兹为单位返回
- 转换为 MHz: `frequency / 1_000_000`
- 转换为 GHz: `frequency / 1_000_000_000.0`
2. **权限**: 读取频率信息不需要特殊权限
3. **实时性**: `currentFrequency` 是实时读取的,会随 CPU 负载变化而变化
4. **可用频率**: 某些设备可能不提供 `availableFrequencies` 列表,返回空列表
5. **速度度量**: `speedMetric` 是根据最大频率计算的,单位为 GHz可以用来比较不同核心的性能
6. **中英文**: 所有返回的文本信息已改为英文,中文保留在注释中
## 兼容性
- 最低 Android 版本: 与原 CpuInfo 类相同
- 支持所有架构: ARM, ARM64, x86, x86_64
- 向后兼容: 所有原有方法保持不变

View File

@ -1,523 +0,0 @@
# DisplayInfo 屏幕尺寸功能使用示例
## 新增功能说明
`DisplayInfo` 类新增了获取屏幕物理尺寸的功能,支持以下单位:
- **英寸 (inches)**: 国际通用的屏幕尺寸单位
- **毫米 (mm)**: 公制单位,更精确的物理尺寸
可以获取:
- 对角线尺寸(屏幕大小)
- 宽度尺寸
- 高度尺寸
## 核心数据类
### ScreenSize
```kotlin
data class ScreenSize(
val diagonalInches: Double, // 对角线尺寸(英寸)
val diagonalMm: Double, // 对角线尺寸(毫米)
val widthInches: Double, // 宽度(英寸)
val widthMm: Double, // 宽度(毫米)
val heightInches: Double, // 高度(英寸)
val heightMm: Double // 高度(毫米)
)
```
### DefaultDisplayInfo (已更新)
现在包含 `screenSize: ScreenSize` 字段,提供完整的屏幕物理尺寸信息。
## 使用示例
### 1. 获取完整的屏幕尺寸信息
```kotlin
val displayInfo = DisplayInfo(context)
// 获取完整的屏幕尺寸信息
val screenSize = displayInfo.getScreenSize()
screenSize?.let {
println("=== Screen Size ===")
println("Diagonal: ${String.format("%.2f", it.diagonalInches)}\" (${String.format("%.1f", it.diagonalMm)} mm)")
println("Width: ${String.format("%.2f", it.widthInches)}\" (${String.format("%.1f", it.widthMm)} mm)")
println("Height: ${String.format("%.2f", it.heightInches)}\" (${String.format("%.1f", it.heightMm)} mm)")
}
```
输出示例:
```
=== Screen Size ===
Diagonal: 6.67" (169.4 mm)
Width: 2.91" (73.9 mm)
Height: 6.32" (160.5 mm)
```
### 2. 获取屏幕对角线尺寸
```kotlin
val displayInfo = DisplayInfo(context)
// 获取对角线尺寸(英寸)
val diagonalInches = displayInfo.getScreenDiagonalInches()
println("Screen Size: ${String.format("%.2f", diagonalInches)}\"")
// 获取对角线尺寸(毫米)
val diagonalMm = displayInfo.getScreenDiagonalMm()
println("Screen Size: ${String.format("%.1f", diagonalMm)} mm")
```
输出示例:
```
Screen Size: 6.67"
Screen Size: 169.4 mm
```
### 3. 获取屏幕宽度和高度
```kotlin
val displayInfo = DisplayInfo(context)
// 获取宽度
val widthInches = displayInfo.getScreenWidthInches()
val widthMm = displayInfo.getScreenWidthMm()
println("Screen Width: ${String.format("%.2f", widthInches)}\" / ${String.format("%.1f", widthMm)} mm")
// 获取高度
val heightInches = displayInfo.getScreenHeightInches()
val heightMm = displayInfo.getScreenHeightMm()
println("Screen Height: ${String.format("%.2f", heightInches)}\" / ${String.format("%.1f", heightMm)} mm")
```
输出示例:
```
Screen Width: 2.91" / 73.9 mm
Screen Height: 6.32" / 160.5 mm
```
### 4. 从 DefaultDisplayInfo 获取完整信息
```kotlin
val displayInfo = DisplayInfo(context)
val defaultDisplayInfo = displayInfo.getDefaultDisplayInfo()
defaultDisplayInfo?.let { info ->
println("=== Display Information ===")
println("Name: ${info.name}")
println("Resolution: ${info.widthPixels} x ${info.heightPixels}")
println("Density: ${info.densityDpi} dpi")
println("PPI: ${String.format("%.1f", info.ppi)}")
println("Refresh Rate: ${info.refreshRate} Hz")
// 屏幕尺寸
println("\n=== Screen Size ===")
println("Diagonal: ${String.format("%.2f", info.screenSize.diagonalInches)}\"")
println("Size: ${String.format("%.2f", info.screenSize.widthInches)}\" x ${String.format("%.2f", info.screenSize.heightInches)}\"")
println("Size (mm): ${String.format("%.1f", info.screenSize.widthMm)} x ${String.format("%.1f", info.screenSize.heightMm)} mm")
// HDR 信息
if (info.isHdr) {
println("\n=== HDR Support ===")
println("HDR Types: ${info.hdrTypes.joinToString(", ")}")
}
// 广色域
if (info.isWideColorGamut) {
println("Wide Color Gamut: Supported")
}
}
```
输出示例:
```
=== Display Information ===
Name: Built-in Screen
Resolution: 1080 x 2400
Density: 393 dpi
PPI: 395.6
Refresh Rate: 120.0 Hz
=== Screen Size ===
Diagonal: 6.67"
Size: 2.91" x 6.32"
Size (mm): 73.9 x 160.5 mm
=== HDR Support ===
HDR Types: HDR10, HDR10+
Wide Color Gamut: Supported
```
### 5. 计算屏幕纵横比
```kotlin
val displayInfo = DisplayInfo(context)
val screenSize = displayInfo.getScreenSize()
screenSize?.let {
// 计算纵横比
val aspectRatio = it.widthInches / it.heightInches
// 判断常见纵横比
val ratioName = when {
aspectRatio.isCloseTo(9.0 / 16.0, 0.01) -> "16:9"
aspectRatio.isCloseTo(9.0 / 18.0, 0.01) -> "18:9 (2:1)"
aspectRatio.isCloseTo(9.0 / 19.5, 0.01) -> "19.5:9"
aspectRatio.isCloseTo(9.0 / 20.0, 0.01) -> "20:9"
aspectRatio.isCloseTo(9.0 / 21.0, 0.01) -> "21:9"
aspectRatio.isCloseTo(3.0 / 4.0, 0.01) -> "4:3"
else -> String.format("%.2f:1", 1.0 / aspectRatio)
}
println("Screen Aspect Ratio: $ratioName")
}
// 辅助函数
fun Double.isCloseTo(target: Double, tolerance: Double): Boolean {
return kotlin.math.abs(this - target) < tolerance
}
```
### 6. 计算屏幕面积
```kotlin
val displayInfo = DisplayInfo(context)
val screenSize = displayInfo.getScreenSize()
screenSize?.let {
// 计算面积(平方英寸)
val areaInches = it.widthInches * it.heightInches
// 计算面积(平方厘米)
val areaCm = (it.widthMm / 10.0) * (it.heightMm / 10.0)
println("Screen Area: ${String.format("%.2f", areaInches)} in²")
println("Screen Area: ${String.format("%.2f", areaCm)} cm²")
}
```
输出示例:
```
Screen Area: 18.39 in²
Screen Area: 118.65 cm²
```
### 7. 在 Jetpack Compose 中显示
```kotlin
@Composable
fun ScreenSizeCard() {
val context = LocalContext.current
val displayInfo = remember { DisplayInfo(context) }
val defaultDisplayInfo = remember { displayInfo.getDefaultDisplayInfo() }
defaultDisplayInfo?.let { info ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
elevation = CardDefaults.cardElevation(4.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Display Information",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(16.dp))
// 分辨率和密度
InfoSection(title = "Resolution & Density") {
InfoRow("Resolution", "${info.widthPixels} x ${info.heightPixels} px")
InfoRow("Density", "${info.densityDpi} dpi")
InfoRow("PPI", String.format("%.1f", info.ppi))
}
Spacer(modifier = Modifier.height(12.dp))
// 屏幕尺寸
InfoSection(title = "Screen Size") {
InfoRow(
"Diagonal",
String.format("%.2f\" (%.1f mm)",
info.screenSize.diagonalInches,
info.screenSize.diagonalMm
)
)
InfoRow(
"Width",
String.format("%.2f\" (%.1f mm)",
info.screenSize.widthInches,
info.screenSize.widthMm
)
)
InfoRow(
"Height",
String.format("%.2f\" (%.1f mm)",
info.screenSize.heightInches,
info.screenSize.heightMm
)
)
}
Spacer(modifier = Modifier.height(12.dp))
// 刷新率
InfoSection(title = "Refresh Rate") {
InfoRow("Current", "${info.refreshRate.toInt()} Hz")
if (info.supportedRefreshRates.size > 1) {
InfoRow(
"Supported",
info.supportedRefreshRates.joinToString(", ") { "${it.toInt()} Hz" }
)
}
}
// HDR 和色域
if (info.isHdr || info.isWideColorGamut) {
Spacer(modifier = Modifier.height(12.dp))
InfoSection(title = "Advanced Features") {
if (info.isHdr) {
InfoRow("HDR", info.hdrTypes.joinToString(", "))
}
if (info.isWideColorGamut) {
InfoRow("Color Gamut", "Wide Color Gamut")
}
}
}
}
}
}
}
@Composable
fun InfoSection(title: String, content: @Composable () -> Unit) {
Column {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(8.dp))
content()
}
}
@Composable
fun InfoRow(label: String, value: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
textAlign = TextAlign.End,
modifier = Modifier.weight(1f, fill = false)
)
}
}
```
### 8. 比较设备屏幕大小
```kotlin
fun compareScreenSizes(context: Context) {
val displayInfo = DisplayInfo(context)
val screenSize = displayInfo.getScreenSize() ?: return
println("=== Screen Size Comparison ===")
val diagonal = screenSize.diagonalInches
val category = when {
diagonal < 4.5 -> "Compact Phone (< 4.5\")"
diagonal < 5.5 -> "Standard Phone (4.5\" - 5.5\")"
diagonal < 6.5 -> "Large Phone (5.5\" - 6.5\")"
diagonal < 7.5 -> "Phablet (6.5\" - 7.5\")"
diagonal < 10.0 -> "Small Tablet (7.5\" - 10\")"
diagonal < 13.0 -> "Standard Tablet (10\" - 13\")"
else -> "Large Tablet (> 13\")"
}
println("Device Category: $category")
println("Screen Diagonal: ${String.format("%.2f", diagonal)}\"")
// 与常见设备比较
println("\nComparison with common sizes:")
println("iPhone 15 Pro Max: ~6.7\"")
println("Samsung Galaxy S24 Ultra: ~6.8\"")
println("iPad Pro 11\": ~11\"")
println("iPad Pro 12.9\": ~12.9\"")
}
```
### 9. 计算最佳查看距离
```kotlin
fun calculateOptimalViewingDistance(context: Context) {
val displayInfo = DisplayInfo(context)
val defaultInfo = displayInfo.getDefaultDisplayInfo() ?: return
// 基于 PPI 和屏幕尺寸计算最佳查看距离
// 一般建议:对于 300+ PPI最佳查看距离约为屏幕对角线的 1.5-2 倍
val diagonalInches = defaultInfo.screenSize.diagonalInches
val ppi = defaultInfo.ppi
val minDistance = diagonalInches * 1.5
val maxDistance = diagonalInches * 2.0
// 转换为厘米
val minDistanceCm = minDistance * 2.54
val maxDistanceCm = maxDistance * 2.54
println("=== Optimal Viewing Distance ===")
println("Screen: ${String.format("%.2f", diagonalInches)}\" @ ${String.format("%.0f", ppi)} PPI")
println("Recommended distance: ${String.format("%.1f", minDistanceCm)} - ${String.format("%.1f", maxDistanceCm)} cm")
println(" (${String.format("%.1f", minDistance)} - ${String.format("%.1f", maxDistance)} inches)")
}
```
### 10. 检测屏幕类型
```kotlin
fun detectScreenType(context: Context): String {
val displayInfo = DisplayInfo(context)
val defaultInfo = displayInfo.getDefaultDisplayInfo() ?: return "Unknown"
val diagonal = defaultInfo.screenSize.diagonalInches
val widthPixels = defaultInfo.widthPixels
val heightPixels = defaultInfo.heightPixels
val ppi = defaultInfo.ppi
// 计算纵横比
val aspectRatio = widthPixels.toDouble() / heightPixels.toDouble()
return buildString {
// 设备类型
append(when {
diagonal < 7.0 -> "Smartphone"
diagonal < 10.0 -> "Phablet/Small Tablet"
else -> "Tablet"
})
append(" | ")
// 屏幕质量
append(when {
ppi >= 500 -> "Ultra High Density"
ppi >= 400 -> "Very High Density"
ppi >= 300 -> "High Density"
ppi >= 200 -> "Medium Density"
else -> "Low Density"
})
append(" | ")
// 纵横比类型
append(when {
aspectRatio < 0.5 -> "Ultra-wide (21:9+)"
aspectRatio < 0.52 -> "Wide (20:9)"
aspectRatio < 0.54 -> "Wide (19.5:9)"
aspectRatio < 0.58 -> "Standard (18:9)"
aspectRatio < 0.60 -> "Standard (16:9)"
else -> "Traditional (4:3)"
})
}
}
// 使用示例
val screenType = detectScreenType(context)
println("Screen Type: $screenType")
// 输出: "Smartphone | Very High Density | Wide (20:9)"
```
## 技术细节
### 计算方法
1. **对角线尺寸**
```
diagonal_inches = √(width_inches² + height_inches²)
```
2. **宽度/高度转换**
```
width_inches = width_pixels / xdpi
height_inches = height_pixels / ydpi
```
3. **英寸到毫米转换**
```
millimeters = inches × 25.4
```
### 精确度说明
- 计算基于设备报告的 `xdpi``ydpi`
- 大多数设备提供准确的 DPI 信息
- 某些低端设备可能报告不准确的 DPI导致尺寸计算偏差
- 对角线尺寸通常误差在 ±0.1 英寸以内
## 注意事项
1. **DPI 准确性**:计算依赖于系统报告的 DPI 值,大多数现代设备提供准确的值
2. **单位转换**
- 1 英寸 = 25.4 毫米
- 1 英寸 = 2.54 厘米
3. **屏幕对角线**:通常所说的屏幕尺寸指的是对角线长度(如 6.7 英寸手机)
4. **无需权限**:获取屏幕尺寸信息不需要任何特殊权限
5. **兼容性**:支持所有 Android 版本,使用标准 Android API
6. **性能**:计算是轻量级的,可以频繁调用而不影响性能
## 常见屏幕尺寸参考
### 智能手机
- **紧凑型**: 4.0" - 5.0"
- **标准型**: 5.0" - 6.0"
- **大屏型**: 6.0" - 6.5"
- **超大屏**: 6.5" - 7.0"
### 平板电脑
- **小型平板**: 7" - 8"
- **标准平板**: 9" - 10"
- **大型平板**: 11" - 13"
### 物理尺寸示例
- **iPhone 15 Pro Max**: 6.7" (约 170 mm)
- **Samsung Galaxy S24 Ultra**: 6.8" (约 173 mm)
- **iPad Air**: 10.9" (约 277 mm)
- **iPad Pro**: 12.9" (约 328 mm)
## 扩展用途
屏幕尺寸信息可以用于:
- UI 布局自适应
- 字体大小调整
- 图片资源选择
- 视频播放优化
- 游戏控制布局
- 阅读体验优化
- 设备分类统计
- 用户体验研究

View File

@ -1,472 +0,0 @@
# GpuInfo 增强功能使用示例
## 新增功能说明
`GpuInfo` 类已增强并修复以下功能:
- 修复了 `getOpenGLVersion()` 可能返回空值的问题
- 新增 GPU 最大频率获取
- 新增 GPU 架构信息
- 新增 GPU 缓存大小
- 新增 GPU 内存带宽
- 新增计算单元和着色单元数量
- 所有返回文本已国际化为英文
## 核心数据类
### GpuDetailedInfo
```kotlin
data class GpuDetailedInfo(
val maxFrequency: Int?, // 最大频率MHz
val architecture: String?, // 架构名称
val cacheSize: Int?, // 缓存大小KB
val bandwidth: Double?, // 内存带宽GB/s
val computeUnits: Int?, // 计算单元数量
val shadingUnits: Int? // 着色单元数量
)
```
## 支持的 GPU 型号
### Qualcomm Adreno 系列
- Adreno 740, 730, 725, 720, 710, 702
- Adreno 690, 660, 650, 640, 630, 620
### ARM Mali 系列
- Mali-G720, G715, G710, G610
- Mali-G78, G77, G76, G72, G71
- Mali-G68, G57, G52, G51
### Apple GPU
- A17/M3, A16/M2, A15/M1
### PowerVR 系列
- PowerVR GE8320
## 使用示例
### 1. 获取基本 GPU 信息
```kotlin
val gpuInfo = GpuInfo(context)
// 获取供应商
val vendor = gpuInfo.getVendorName()
println("GPU Vendor: $vendor")
// 获取型号
val renderer = gpuInfo.getRendererName()
println("GPU Model: $renderer")
// 获取设备类型
val deviceType = gpuInfo.getDeviceTypeDescription()
println("Device Type: $deviceType")
// 获取 OpenGL ES 版本(已修复)
val glVersion = gpuInfo.getOpenGLVersion()
println("OpenGL ES Version: $glVersion")
// 获取 Vulkan 版本
val vkVersion = gpuInfo.getVulkanApiVersion()
println("Vulkan Version: $vkVersion")
```
### 2. 获取 GPU 详细规格
```kotlin
val gpuInfo = GpuInfo(context)
// 获取完整的 GPU 详细信息
val detailedInfo = gpuInfo.getGpuDetailedInfo()
println("=== GPU Specifications ===")
println("Architecture: ${detailedInfo.architecture}")
println("Max Frequency: ${detailedInfo.maxFrequency} MHz")
println("Cache Size: ${detailedInfo.cacheSize} KB")
println("Memory Bandwidth: ${detailedInfo.bandwidth} GB/s")
println("Compute Units: ${detailedInfo.computeUnits}")
println("Shading Units: ${detailedInfo.shadingUnits}")
```
### 3. 获取单个规格属性
```kotlin
val gpuInfo = GpuInfo(context)
// 获取最大频率
val maxFreq = gpuInfo.getMaxFrequency()
println("Max Frequency: ${maxFreq ?: "Unknown"} MHz")
// 获取架构
val arch = gpuInfo.getArchitecture()
println("Architecture: ${arch ?: "Unknown"}")
// 获取缓存大小
val cache = gpuInfo.getCacheSize()
println("Cache: ${cache ?: "Unknown"} KB")
// 获取带宽
val bandwidth = gpuInfo.getBandwidth()
println("Bandwidth: ${bandwidth ?: "Unknown"} GB/s")
// 获取计算单元
val computeUnits = gpuInfo.getComputeUnits()
println("Compute Units: ${computeUnits ?: "Unknown"}")
// 获取着色单元
val shadingUnits = gpuInfo.getShadingUnits()
println("Shading Units: ${shadingUnits ?: "Unknown"}")
```
### 4. 获取完整的 GPU 摘要
```kotlin
val gpuInfo = GpuInfo(context)
// 获取格式化的完整摘要
val summary = gpuInfo.getGpuSummary()
println(summary)
```
输出示例:
```
=== GPU Basic Info ===
Vendor: Qualcomm
Model: Adreno (TM) 730
Type: Integrated GPU
=== GPU Specifications ===
Architecture: Adreno 730
Max Frequency: 818 MHz
Cache Size: 1536 KB
Memory Bandwidth: 44.8 GB/s
Compute Units: 6
Shading Units: 768
=== Vulkan Info ===
Supported: Yes
API Version: 1.3.0
Driver Version: 512
--- Vulkan Device ---
Device Name: Adreno (TM) 730
Device ID: 43051011
Vendor ID: 0x5143
Registered Vendor: Qualcomm
Device Type: Integrated GPU
API Version: 1.3.0
=== OpenGL ES Info ===
Vendor: Qualcomm
Renderer: Adreno (TM) 730
Version: OpenGL ES 3.2
Extension Count: 247
=== EGL Info ===
Vendor: Qualcomm
Version: 1.5
Client API: OpenGL_ES
Extension Count: 52
```
### 5. 计算 GPU 性能指标
```kotlin
val gpuInfo = GpuInfo(context)
val detailedInfo = gpuInfo.getGpuDetailedInfo()
// 计算理论峰值性能GFLOPS
// 公式:着色单元 * 频率 * 2 (FMA operations)
val theoreticalGFLOPS = detailedInfo.shadingUnits?.let { units ->
detailedInfo.maxFrequency?.let { freq ->
(units * freq * 2) / 1000.0
}
}
println("Theoretical Peak Performance: ${theoreticalGFLOPS?.let {
String.format("%.1f GFLOPS", it)
} ?: "Unknown"}")
// 计算带宽利用率(假设某个应用需要 10 GB/s
val requiredBandwidth = 10.0
val bandwidthUtilization = detailedInfo.bandwidth?.let {
(requiredBandwidth / it * 100).coerceIn(0.0, 100.0)
}
println("Bandwidth Utilization: ${bandwidthUtilization?.let {
String.format("%.1f%%", it)
} ?: "Unknown"}")
```
### 6. 比较不同 GPU
```kotlin
fun compareGpus(gpu1Name: String, gpu2Name: String) {
val gpuInfo = GpuInfo(context)
// 模拟获取两个 GPU 的信息(实际使用中,这些可能来自数据库)
val spec1 = gpuInfo.getGpuSpecsByRenderer(gpu1Name.lowercase())
val spec2 = gpuInfo.getGpuSpecsByRenderer(gpu2Name.lowercase())
println("=== GPU Comparison ===")
println("GPU 1: $gpu1Name")
println(" Max Freq: ${spec1.maxFrequency} MHz")
println(" Bandwidth: ${spec1.bandwidth} GB/s")
println(" Compute Units: ${spec1.computeUnits}")
println("\nGPU 2: $gpu2Name")
println(" Max Freq: ${spec2.maxFrequency} MHz")
println(" Bandwidth: ${spec2.bandwidth} GB/s")
println(" Compute Units: ${spec2.computeUnits}")
// 简单性能比较
val perfScore1 = (spec1.maxFrequency ?: 0) * (spec1.computeUnits ?: 0)
val perfScore2 = (spec2.maxFrequency ?: 0) * (spec2.computeUnits ?: 0)
println("\nPerformance Score:")
println(" $gpu1Name: $perfScore1")
println(" $gpu2Name: $perfScore2")
if (perfScore1 > perfScore2) {
val diff = ((perfScore1 - perfScore2).toDouble() / perfScore2 * 100)
println(" $gpu1Name is ${String.format("%.1f%%", diff)} faster")
} else if (perfScore2 > perfScore1) {
val diff = ((perfScore2 - perfScore1).toDouble() / perfScore1 * 100)
println(" $gpu2Name is ${String.format("%.1f%%", diff)} faster")
}
}
// 使用示例
compareGpus("Adreno 730", "Mali-G78")
```
### 7. 在 Jetpack Compose 中显示
```kotlin
@Composable
fun GpuInfoCard() {
val context = LocalContext.current
val gpuInfo = remember { GpuInfo(context) }
val detailedInfo = remember { gpuInfo.getGpuDetailedInfo() }
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
elevation = CardDefaults.cardElevation(4.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "GPU Information",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(16.dp))
// 基本信息
InfoRow("Vendor", gpuInfo.getVendorName() ?: "Unknown")
InfoRow("Model", gpuInfo.getRendererName() ?: "Unknown")
InfoRow("Type", gpuInfo.getDeviceTypeDescription() ?: "Unknown")
Divider(modifier = Modifier.padding(vertical = 8.dp))
// 详细规格
Text(
text = "Specifications",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(8.dp))
detailedInfo.architecture?.let {
InfoRow("Architecture", it)
}
detailedInfo.maxFrequency?.let {
InfoRow("Max Frequency", "$it MHz")
}
detailedInfo.cacheSize?.let {
InfoRow("Cache Size", "$it KB")
}
detailedInfo.bandwidth?.let {
InfoRow("Bandwidth", String.format("%.1f GB/s", it))
}
detailedInfo.computeUnits?.let {
InfoRow("Compute Units", it.toString())
}
detailedInfo.shadingUnits?.let {
InfoRow("Shading Units", it.toString())
}
Divider(modifier = Modifier.padding(vertical = 8.dp))
// API 信息
Text(
text = "API Support",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(8.dp))
InfoRow("OpenGL ES", gpuInfo.getOpenGLVersion() ?: "Unknown")
InfoRow("Vulkan", gpuInfo.getVulkanApiVersion() ?: "Not Supported")
InfoRow("EGL", gpuInfo.getEglVersion() ?: "Unknown")
}
}
}
@Composable
fun InfoRow(label: String, value: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium
)
}
}
```
### 8. 检测 GPU 能力
```kotlin
fun checkGpuCapabilities(context: Context) {
val gpuInfo = GpuInfo(context)
val detailedInfo = gpuInfo.getGpuDetailedInfo()
println("=== GPU Capabilities Check ===")
// 检查是否适合游戏
val isGoodForGaming = (detailedInfo.maxFrequency ?: 0) > 600 &&
(detailedInfo.computeUnits ?: 0) >= 4 &&
(detailedInfo.bandwidth ?: 0.0) > 25.0
println("Suitable for Gaming: ${if (isGoodForGaming) "Yes" else "No"}")
// 检查是否支持高端图形
val supportsHighEndGraphics = gpuInfo.isVulkanSupported() &&
(detailedInfo.shadingUnits ?: 0) > 512
println("High-End Graphics Support: ${if (supportsHighEndGraphics) "Yes" else "No"}")
// 检查 AI/ML 能力
val goodForAI = (detailedInfo.computeUnits ?: 0) >= 6 &&
(detailedInfo.bandwidth ?: 0.0) > 40.0
println("Good for AI/ML: ${if (goodForAI) "Yes" else "No"}")
// 推荐图形质量设置
val recommendedQuality = when {
(detailedInfo.maxFrequency ?: 0) > 800 &&
(detailedInfo.computeUnits ?: 0) >= 6 -> "Ultra"
(detailedInfo.maxFrequency ?: 0) > 650 &&
(detailedInfo.computeUnits ?: 0) >= 4 -> "High"
(detailedInfo.maxFrequency ?: 0) > 500 -> "Medium"
else -> "Low"
}
println("Recommended Graphics Quality: $recommendedQuality")
}
```
### 9. OpenGL ES 版本检测增强
```kotlin
val gpuInfo = GpuInfo(context)
// 修复后的 getOpenGLVersion() 方法
val glVersion = gpuInfo.getOpenGLVersion()
when {
glVersion == null || glVersion == "Unknown" -> {
println("OpenGL ES: Not available or unknown")
}
glVersion.contains("3.2") -> {
println("OpenGL ES 3.2: Full support for modern graphics")
}
glVersion.contains("3.1") -> {
println("OpenGL ES 3.1: Good support for most features")
}
glVersion.contains("3.0") -> {
println("OpenGL ES 3.0: Basic modern graphics support")
}
glVersion.contains("2.0") -> {
println("OpenGL ES 2.0: Legacy support only")
}
else -> {
println("OpenGL ES: $glVersion")
}
}
```
## 注意事项
1. **规格数据来源**: GPU 规格信息基于公开的硬件数据库,对于未识别的 GPU 型号,规格字段将返回 `null`
2. **OpenGL ES 版本修复**:
- 修复了可能返回 `null` 的问题
- 如果无法从 EGL 获取,会尝试从 Vulkan 推断
- 最坏情况返回 "Unknown" 而不是 `null`
3. **精确性**:
- 频率和带宽值是理论最大值,实际运行时可能更低
- 不同设备批次可能有轻微差异
4. **权限**: 获取 GPU 信息不需要特殊权限
5. **性能**:
- GPU 信息获取是轻量级操作
- 建议在应用启动时获取一次并缓存
6. **兼容性**:
- 支持 Android 5.0 (API 21) 及以上
- Vulkan 信息需要 Android 7.0 (API 24) 及以上
7. **国际化**: 所有返回的文本信息已改为英文,中文保留在注释中
## 已修复的问题
### getOpenGLVersion() 返回 null
**问题**: 在某些设备上,`getOpenGLVersion()` 可能返回 `null`
**原因**: EGL 上下文创建失败或 GL 字符串查询失败
**解决方案**:
1. 添加了回退机制:从 Vulkan 版本推断 OpenGL ES 支持
2. 确保总是返回非 null 值(至少返回 "Unknown"
3. 增加了错误处理
## 扩展建议
如果需要添加更多 GPU 型号的支持,可以在 `getGpuSpecsByRenderer()` 方法中添加新的匹配规则:
```kotlin
"your_gpu_name" in renderer -> GpuDetailedInfo(
maxFrequency = 850, // MHz
architecture = "Architecture Name",
cacheSize = 1024, // KB
bandwidth = 38.4, // GB/s
computeUnits = 5,
shadingUnits = 640
)
```
## 性能分级参考
根据获取的 GPU 信息,可以进行性能分级:
- **旗舰级**: 频率 > 800 MHz, 带宽 > 45 GB/s, 计算单元 >= 6
- **高端**: 频率 > 650 MHz, 带宽 > 35 GB/s, 计算单元 >= 4
- **中端**: 频率 > 500 MHz, 带宽 > 20 GB/s, 计算单元 >= 3
- **入门级**: 其他

View File

@ -1,671 +0,0 @@
# StorageInfo 存储空间详细信息使用示例
## 新增功能说明
`StorageInfo` 类已增强,新增以下功能:
- **Apps & Data 大小**: 应用程序和用户数据占用的存储空间
- **System 大小**: 系统分区占用的存储空间
- **Free 大小**: 可用的存储空间
- **Cache 大小**: 缓存占用的存储空间
- **存储分解信息**: 详细的存储空间使用情况分析
- **存储摘要**: 格式化的完整存储信息
## 核心数据类
### StorageBreakdown
```kotlin
data class StorageBreakdown(
val totalSpace: Long, // 总空间(字节)
val usedSpace: Long, // 已使用空间(字节)
val freeSpace: Long, // 可用空间(字节)
val systemSize: Long, // 系统占用(字节)
val appsAndDataSize: Long, // 应用和数据占用(字节)
val cacheSize: Long, // 缓存占用(字节)
val otherSize: Long // 其他占用(字节)
) {
val usedPercentage: Double // 已使用百分比
val freePercentage: Double // 可用百分比
}
```
## 使用示例
### 1. 获取基本存储信息
```kotlin
val storageInfo = StorageInfo(context)
// 直接访问属性获取大小
val appsDataSize = storageInfo.applicationsAndDataSize
println("Apps & Data: ${storageInfo.formatBytes(appsDataSize)}")
val systemSize = storageInfo.systemSize
println("System: ${storageInfo.formatBytes(systemSize)}")
val freeSpace = storageInfo.internalStorageAvailableSpace
println("Free: ${storageInfo.formatBytes(freeSpace)}")
val cacheSize = storageInfo.cacheSize
println("Cache: ${storageInfo.formatBytes(cacheSize)}")
```
输出示例:
```
Apps & Data: 18.5 GB
System: 8.2 GB
Free: 32.1 GB
Cache: 1.2 GB
```
### 2. 获取格式化的存储信息
```kotlin
val storageInfo = StorageInfo(context)
// 直接获取格式化的字符串
val appsData = storageInfo.getFormattedAppsAndDataSize()
val system = storageInfo.getFormattedSystemSize()
val free = storageInfo.getFormattedFreeSpace()
val cache = storageInfo.getFormattedCacheSize()
println("Apps & Data: $appsData")
println("System: $system")
println("Free: $free")
println("Cache: $cache")
```
### 3. 获取完整的存储分解信息
```kotlin
val storageInfo = StorageInfo(context)
// 获取详细的存储分解
val breakdown = storageInfo.getInternalStorageBreakdown()
println("=== Storage Breakdown ===")
println("Total: ${storageInfo.formatBytes(breakdown.totalSpace)}")
println("Used: ${storageInfo.formatBytes(breakdown.usedSpace)} (${String.format("%.1f%%", breakdown.usedPercentage)})")
println("Free: ${storageInfo.formatBytes(breakdown.freeSpace)} (${String.format("%.1f%%", breakdown.freePercentage)})")
println()
println("Breakdown:")
println(" System: ${storageInfo.formatBytes(breakdown.systemSize)}")
println(" Apps & Data: ${storageInfo.formatBytes(breakdown.appsAndDataSize)}")
println(" Cache: ${storageInfo.formatBytes(breakdown.cacheSize)}")
println(" Other: ${storageInfo.formatBytes(breakdown.otherSize)}")
```
输出示例:
```
=== Storage Breakdown ===
Total: 128.00 GB
Used: 85.4 GB (66.7%)
Free: 42.6 GB (33.3%)
Breakdown:
System: 8.2 GB
Apps & Data: 18.5 GB
Cache: 1.2 GB
Other: 57.5 GB
```
### 4. 获取存储使用百分比
```kotlin
val storageInfo = StorageInfo(context)
// 获取使用百分比
val usedPercentage = storageInfo.getUsagePercentage()
println("Storage Used: ${String.format("%.1f%%", usedPercentage)}")
// 获取可用百分比
val freePercentage = storageInfo.getFreePercentage()
println("Storage Free: ${String.format("%.1f%%", freePercentage)}")
// 判断存储状态
when {
usedPercentage > 90 -> println("Warning: Storage almost full!")
usedPercentage > 80 -> println("Storage is getting full")
usedPercentage > 50 -> println("Storage usage is moderate")
else -> println("Plenty of storage available")
}
```
### 5. 获取完整的存储摘要
```kotlin
val storageInfo = StorageInfo(context)
// 获取格式化的完整摘要
val summary = storageInfo.getStorageSummary()
println(summary)
```
输出示例:
```
=== Internal Storage ===
Total: 128.00 GB
Used: 85.4 GB (66.7%)
Free: 42.6 GB (33.3%)
=== Storage Breakdown ===
System: 8.2 GB
Apps & Data: 18.5 GB
Cache: 1.2 GB
Other: 57.5 GB
=== External Storage ===
Total: 256.00 GB
Used: 128.3 GB
Free: 127.7 GB
Emulated: Yes
Removable: No
=== Storage Features ===
Encrypted: Yes
Encryption Type: FBE
File System: ext4
=== Partition Scheme ===
A/B Updates: Yes
Dynamic Partitions: Yes
Virtual A/B: Yes
```
### 6. 在 Jetpack Compose 中显示存储信息
```kotlin
@Composable
fun StorageInfoCard() {
val context = LocalContext.current
val storageInfo = remember { StorageInfo(context) }
val breakdown = remember { storageInfo.getInternalStorageBreakdown() }
Card(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
elevation = CardDefaults.cardElevation(4.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Storage Information",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
Spacer(modifier = Modifier.height(16.dp))
// 存储使用进度条
StorageProgressBar(
used = breakdown.usedSpace,
total = breakdown.totalSpace,
usedPercentage = breakdown.usedPercentage
)
Spacer(modifier = Modifier.height(16.dp))
// 总览
InfoSection(title = "Overview") {
InfoRow(
"Total",
storageInfo.formatBytes(breakdown.totalSpace)
)
InfoRow(
"Used",
"${storageInfo.formatBytes(breakdown.usedSpace)} (${String.format("%.1f%%", breakdown.usedPercentage)})"
)
InfoRow(
"Free",
"${storageInfo.formatBytes(breakdown.freeSpace)} (${String.format("%.1f%%", breakdown.freePercentage)})"
)
}
Spacer(modifier = Modifier.height(12.dp))
// 详细分解
InfoSection(title = "Breakdown") {
StorageBreakdownItem(
"System",
breakdown.systemSize,
breakdown.totalSpace,
Color(0xFF2196F3)
)
StorageBreakdownItem(
"Apps & Data",
breakdown.appsAndDataSize,
breakdown.totalSpace,
Color(0xFF4CAF50)
)
StorageBreakdownItem(
"Cache",
breakdown.cacheSize,
breakdown.totalSpace,
Color(0xFFFFC107)
)
StorageBreakdownItem(
"Other",
breakdown.otherSize,
breakdown.totalSpace,
Color(0xFF9E9E9E)
)
}
}
}
}
@Composable
fun StorageProgressBar(
used: Long,
total: Long,
usedPercentage: Double
) {
Column {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = "Storage Usage",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = String.format("%.1f%%", usedPercentage),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold
)
}
Spacer(modifier = Modifier.height(8.dp))
LinearProgressIndicator(
progress = (usedPercentage / 100).toFloat(),
modifier = Modifier
.fillMaxWidth()
.height(8.dp)
.clip(RoundedCornerShape(4.dp)),
color = when {
usedPercentage > 90 -> Color(0xFFF44336)
usedPercentage > 80 -> Color(0xFFFF9800)
else -> Color(0xFF4CAF50)
}
)
}
}
@Composable
fun StorageBreakdownItem(
label: String,
size: Long,
total: Long,
color: Color
) {
val storageInfo = StorageInfo(LocalContext.current)
val percentage = if (total > 0) (size.toDouble() / total * 100) else 0.0
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
modifier = Modifier
.size(12.dp)
.background(color, CircleShape)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = label,
style = MaterialTheme.typography.bodyMedium
)
}
Text(
text = "${storageInfo.formatBytes(size)} (${String.format("%.1f%%", percentage)})",
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium
)
}
}
@Composable
fun InfoSection(title: String, content: @Composable () -> Unit) {
Column {
Text(
text = title,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(8.dp))
content()
}
}
@Composable
fun InfoRow(label: String, value: String) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium,
textAlign = TextAlign.End,
modifier = Modifier.weight(1f, fill = false)
)
}
}
```
### 7. 存储空间监控
```kotlin
class StorageMonitor(private val context: Context) {
private val storageInfo = StorageInfo(context)
/**
* 检查存储状态
*/
fun checkStorageStatus(): StorageStatus {
val freeSpace = storageInfo.internalStorageAvailableSpace
val usedPercentage = storageInfo.getUsagePercentage()
return when {
freeSpace < 1024 * 1024 * 1024 -> // < 1 GB
StorageStatus.CRITICAL
usedPercentage > 90 ->
StorageStatus.LOW
usedPercentage > 80 ->
StorageStatus.WARNING
else ->
StorageStatus.HEALTHY
}
}
/**
* 获取存储建议
*/
fun getStorageRecommendation(): String {
val status = checkStorageStatus()
val cacheSize = storageInfo.cacheSize
return when (status) {
StorageStatus.CRITICAL -> {
"Critical: Storage almost full! Clear ${storageInfo.formatBytes(cacheSize)} cache immediately."
}
StorageStatus.LOW -> {
"Warning: Low storage space. Consider clearing cache or removing unused apps."
}
StorageStatus.WARNING -> {
"Storage is getting full. You may want to free up some space."
}
StorageStatus.HEALTHY -> {
"Storage is healthy. ${storageInfo.getFormattedFreeSpace()} available."
}
}
}
enum class StorageStatus {
HEALTHY, WARNING, LOW, CRITICAL
}
}
// 使用示例
val monitor = StorageMonitor(context)
val status = monitor.checkStorageStatus()
val recommendation = monitor.getStorageRecommendation()
println("Storage Status: $status")
println("Recommendation: $recommendation")
```
### 8. 计算可安装应用数量
```kotlin
fun estimateInstallableApps(context: Context): Int {
val storageInfo = StorageInfo(context)
val freeSpace = storageInfo.internalStorageAvailableSpace
// 平均应用大小约 50 MB
val averageAppSize = 50 * 1024 * 1024L
// 保留 2 GB 作为系统缓冲
val reservedSpace = 2L * 1024 * 1024 * 1024
val availableForApps = maxOf(0L, freeSpace - reservedSpace)
return (availableForApps / averageAppSize).toInt()
}
// 使用示例
val estimatedApps = estimateInstallableApps(context)
println("You can install approximately $estimatedApps more apps")
```
### 9. 存储趋势分析
```kotlin
class StorageTrendAnalyzer(private val context: Context) {
private val storageInfo = StorageInfo(context)
private val prefs = context.getSharedPreferences("storage_trend", Context.MODE_PRIVATE)
/**
* 记录当前存储使用情况
*/
fun recordCurrentUsage() {
val used = storageInfo.internalStorageUsedSpace
val timestamp = System.currentTimeMillis()
prefs.edit()
.putLong("last_used", used)
.putLong("last_timestamp", timestamp)
.apply()
}
/**
* 计算每日平均增长
*/
fun getDailyGrowth(): Long {
val currentUsed = storageInfo.internalStorageUsedSpace
val lastUsed = prefs.getLong("last_used", 0)
val lastTimestamp = prefs.getLong("last_timestamp", 0)
if (lastUsed == 0L || lastTimestamp == 0L) {
return 0L
}
val daysPassed = (System.currentTimeMillis() - lastTimestamp) / (24 * 60 * 60 * 1000)
if (daysPassed == 0L) return 0L
val growth = currentUsed - lastUsed
return growth / daysPassed
}
/**
* 预估空间耗尽时间
*/
fun estimateDaysUntilFull(): Int {
val dailyGrowth = getDailyGrowth()
if (dailyGrowth <= 0) return Int.MAX_VALUE
val freeSpace = storageInfo.internalStorageAvailableSpace
val reservedSpace = 1L * 1024 * 1024 * 1024 // 保留 1 GB
val usableSpace = maxOf(0L, freeSpace - reservedSpace)
return (usableSpace / dailyGrowth).toInt()
}
}
// 使用示例
val analyzer = StorageTrendAnalyzer(context)
analyzer.recordCurrentUsage()
val dailyGrowth = analyzer.getDailyGrowth()
val daysUntilFull = analyzer.estimateDaysUntilFull()
println("Daily Growth: ${StorageInfo(context).formatBytes(dailyGrowth)}")
if (daysUntilFull < 365) {
println("Storage will be full in approximately $daysUntilFull days")
}
```
### 10. 比较不同类别的存储占用
```kotlin
fun compareStorageCategories(context: Context) {
val storageInfo = StorageInfo(context)
val breakdown = storageInfo.getInternalStorageBreakdown()
data class CategoryInfo(val name: String, val size: Long)
val categories = listOf(
CategoryInfo("System", breakdown.systemSize),
CategoryInfo("Apps & Data", breakdown.appsAndDataSize),
CategoryInfo("Cache", breakdown.cacheSize),
CategoryInfo("Other", breakdown.otherSize)
)
// 按大小排序
val sorted = categories.sortedByDescending { it.size }
println("=== Storage Usage by Category ===")
sorted.forEachIndexed { index, category ->
val percentage = (category.size.toDouble() / breakdown.totalSpace * 100)
val bar = "█".repeat((percentage / 2).toInt().coerceIn(0, 50))
println(
"${index + 1}. ${category.name.padEnd(15)} " +
"${storageInfo.formatBytes(category.size).padStart(10)} " +
"(${String.format("%5.1f%%", percentage)}) $bar"
)
}
// 找出占用最大的类别
val largest = sorted.first()
println("\nLargest category: ${largest.name} (${storageInfo.formatBytes(largest.size)})")
}
```
输出示例:
```
=== Storage Usage by Category ===
1. Other 57.5 GB ( 44.9%) ██████████████████████
2. Apps & Data 18.5 GB ( 14.5%) ███████
3. System 8.2 GB ( 6.4%) ███
4. Cache 1.2 GB ( 0.9%)
Largest category: Other (57.5 GB)
```
## 技术细节
### 计算方法
1. **Apps & Data 大小**
- 扫描 `/data/data` (应用数据)
- 扫描 `/data/app` (已安装应用)
- 递归计算目录大小
2. **System 大小**
- 使用 `StatFs` 读取 `/system` 分区大小
- 包括系统应用和核心文件
3. **Cache 大小**
- 扫描 `/data/cache` (系统缓存)
- 包括应用缓存目录
4. **Free 大小**
- 使用 `StatFs.availableBlocksLong` 获取可用块
- 乘以块大小得到字节数
### 存储分类
- **System**: 操作系统和系统应用
- **Apps & Data**: 用户安装的应用和数据
- **Cache**: 临时文件和缓存
- **Other**: 媒体文件、下载等其他内容
## 注意事项
1. **权限**
- 基本存储信息无需特殊权限
- 某些目录可能因权限限制无法访问
2. **性能**
- 计算目录大小是耗时操作
- 建议在后台线程执行
- 考虑缓存结果
3. **精确度**
- 由于权限限制,某些大小可能不完全精确
- 系统文件和隐藏文件可能未计入
4. **存储单位**
- 1 KB = 1024 bytes
- 1 MB = 1024 KB
- 1 GB = 1024 MB
5. **兼容性**
- 支持 Android 5.0 (API 21) 及以上
- 某些特性需要更高 API 级别
## 性能优化建议
### 异步加载
```kotlin
// 在协程中加载
lifecycleScope.launch(Dispatchers.IO) {
val storageInfo = StorageInfo(context)
val breakdown = storageInfo.getInternalStorageBreakdown()
withContext(Dispatchers.Main) {
// 更新 UI
updateStorageUI(breakdown)
}
}
```
### 缓存结果
```kotlin
class CachedStorageInfo(context: Context) {
private val storageInfo = StorageInfo(context)
private var cachedBreakdown: StorageBreakdown? = null
private var lastUpdateTime: Long = 0
fun getBreakdown(forceRefresh: Boolean = false): StorageBreakdown {
val now = System.currentTimeMillis()
val cacheExpired = now - lastUpdateTime > 5 * 60 * 1000 // 5 分钟
if (cachedBreakdown == null || cacheExpired || forceRefresh) {
cachedBreakdown = storageInfo.getInternalStorageBreakdown()
lastUpdateTime = now
}
return cachedBreakdown!!
}
}
```
## 常见应用场景
1. **存储管理应用**: 显示详细的存储使用情况
2. **清理工具**: 识别可清理的缓存和临时文件
3. **应用市场**: 检查是否有足够空间安装应用
4. **备份工具**: 评估备份所需空间
5. **文件管理器**: 提供存储概览
6. **设置应用**: 显示系统存储信息
7. **性能监控**: 跟踪存储趋势
8. **用户提醒**: 低存储空间警告

View File

@ -163,10 +163,10 @@ class CameraInfo(private val context: Context) {
*/
fun getCameraFacingText(characteristics: CameraCharacteristics): String {
return when (getCameraFacing(characteristics)) {
CameraFacing.BACK -> "Back" // 后置
CameraFacing.FRONT -> "Front" // 前置
CameraFacing.EXTERNAL -> "External" // 外置
else -> "Unknown" // 未知
CameraFacing.BACK -> "后置"
CameraFacing.FRONT -> "前置"
CameraFacing.EXTERNAL -> "外置"
else -> "未知"
}
}
@ -233,8 +233,8 @@ class CameraInfo(private val context: Context) {
CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG -> "GBRG (Bayer)"
CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR -> "BGGR (Bayer)"
CameraCharacteristics.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB -> "RGB"
5 -> "Mono/NIR" // 单色/近红外
else -> "Unknown" // 未知
5 -> "Mono/NIR (单色/近红外)" // MONO/NIR
else -> "未知"
}
}
}
@ -409,8 +409,8 @@ class CameraInfo(private val context: Context) {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL -> "FULL"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY -> "LEGACY"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 -> "LEVEL_3"
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) "EXTERNAL" else "Unknown" // 未知
else -> "Unknown" // 未知
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) "EXTERNAL" else "未知"
else -> "未知"
}
}
}
@ -430,10 +430,10 @@ class CameraInfo(private val context: Context) {
fun getFaceDetectionModes(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES)?.map {
when (it) {
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_OFF -> "Off" // 关闭
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_SIMPLE -> "Simple" // 简单
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_FULL -> "Full" // 完整
else -> "Unknown" // 未知
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_OFF -> "关闭"
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_SIMPLE -> "简单"
CameraCharacteristics.STATISTICS_FACE_DETECT_MODE_FULL -> "完整"
else -> "未知"
}
}
}
@ -480,17 +480,17 @@ class CameraInfo(private val context: Context) {
val features = mutableListOf<String>()
val capabilities = getAvailableCapabilities(characteristics)
if (capabilities.contains(CameraCapability.RAW)) features.add("RAW Capture") // RAW拍摄
if (capabilities.contains(CameraCapability.BURST_CAPTURE)) features.add("Burst Capture") // 连拍
if (capabilities.contains(CameraCapability.DEPTH_OUTPUT)) features.add("Depth Output") // 景深输出
if (capabilities.contains(CameraCapability.CONSTRAINED_HIGH_SPEED_VIDEO)) features.add("High Speed Video") // 高速视频
if (capabilities.contains(CameraCapability.MANUAL_SENSOR)) features.add("Manual Mode") // 手动模式
if (capabilities.contains(CameraCapability.MONOCHROME)) features.add("Monochrome Mode") // 黑白模式
if (capabilities.contains(CameraCapability.ULTRA_HIGH_RESOLUTION_SENSOR)) features.add("Ultra High Resolution") // 超高分辨率
if (capabilities.contains(CameraCapability.RAW)) features.add("RAW拍摄")
if (capabilities.contains(CameraCapability.BURST_CAPTURE)) features.add("连拍")
if (capabilities.contains(CameraCapability.DEPTH_OUTPUT)) features.add("景深输出")
if (capabilities.contains(CameraCapability.CONSTRAINED_HIGH_SPEED_VIDEO)) features.add("高速视频")
if (capabilities.contains(CameraCapability.MANUAL_SENSOR)) features.add("手动模式")
if (capabilities.contains(CameraCapability.MONOCHROME)) features.add("黑白模式")
if (capabilities.contains(CameraCapability.ULTRA_HIGH_RESOLUTION_SENSOR)) features.add("超高分辨率")
if (capabilities.contains(CameraCapability.DYNAMIC_RANGE_TEN_BIT)) features.add("10-bit HDR")
if (hasOpticalStabilization(characteristics)) features.add("Optical Stabilization") // 光学防抖
if (hasVideoStabilization(characteristics)) features.add("Video Stabilization") // 视频防抖
if (hasOpticalStabilization(characteristics)) features.add("光学防抖")
if (hasVideoStabilization(characteristics)) features.add("视频防抖")
return features
}
@ -503,13 +503,13 @@ class CameraInfo(private val context: Context) {
fun getAutoExposureModes(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)?.map {
when (it) {
CameraCharacteristics.CONTROL_AE_MODE_OFF -> "Off" // 关闭
CameraCharacteristics.CONTROL_AE_MODE_ON -> "Auto" // 自动
CameraCharacteristics.CONTROL_AE_MODE_ON_AUTO_FLASH -> "Auto Flash" // 自动闪光
CameraCharacteristics.CONTROL_AE_MODE_ON_ALWAYS_FLASH -> "Always Flash" // 强制闪光
CameraCharacteristics.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE -> "Auto Flash Redeye" // 防红眼
CameraCharacteristics.CONTROL_AE_MODE_ON_EXTERNAL_FLASH -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) "External Flash" else "Unknown" // 外置闪光/未知
else -> "Unknown" // 未知
CameraCharacteristics.CONTROL_AE_MODE_OFF -> "关闭"
CameraCharacteristics.CONTROL_AE_MODE_ON -> "自动"
CameraCharacteristics.CONTROL_AE_MODE_ON_AUTO_FLASH -> "自动闪光"
CameraCharacteristics.CONTROL_AE_MODE_ON_ALWAYS_FLASH -> "强制闪光"
CameraCharacteristics.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE -> "防红眼"
CameraCharacteristics.CONTROL_AE_MODE_ON_EXTERNAL_FLASH -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) "外置闪光" else "未知"
else -> "未知"
}
}
}
@ -520,13 +520,13 @@ class CameraInfo(private val context: Context) {
fun getAutoFocusModes(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES)?.map {
when (it) {
CameraCharacteristics.CONTROL_AF_MODE_OFF -> "Off" // 关闭
CameraCharacteristics.CONTROL_AF_MODE_AUTO -> "Auto" // 自动
CameraCharacteristics.CONTROL_AF_MODE_MACRO -> "Macro" // 微距
CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO -> "Continuous Video" // 连续视频
CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE -> "Continuous Picture" // 连续拍照
CameraCharacteristics.CONTROL_AF_MODE_OFF -> "关闭"
CameraCharacteristics.CONTROL_AF_MODE_AUTO -> "自动"
CameraCharacteristics.CONTROL_AF_MODE_MACRO -> "微距"
CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO -> "连续视频"
CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE -> "连续拍照"
CameraCharacteristics.CONTROL_AF_MODE_EDOF -> "EDOF"
else -> "Unknown" // 未知
else -> "未知"
}
}
}
@ -537,16 +537,16 @@ class CameraInfo(private val context: Context) {
fun getWhiteBalanceModes(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES)?.map {
when (it) {
CameraCharacteristics.CONTROL_AWB_MODE_OFF -> "Off" // 关闭
CameraCharacteristics.CONTROL_AWB_MODE_AUTO -> "Auto" // 自动
CameraCharacteristics.CONTROL_AWB_MODE_INCANDESCENT -> "Incandescent" // 白炽灯
CameraCharacteristics.CONTROL_AWB_MODE_FLUORESCENT -> "Fluorescent" // 荧光灯
CameraCharacteristics.CONTROL_AWB_MODE_WARM_FLUORESCENT -> "Warm Fluorescent" // 暖荧光
CameraCharacteristics.CONTROL_AWB_MODE_DAYLIGHT -> "Daylight" // 日光
CameraCharacteristics.CONTROL_AWB_MODE_CLOUDY_DAYLIGHT -> "Cloudy" // 阴天
CameraCharacteristics.CONTROL_AWB_MODE_TWILIGHT -> "Twilight" // 黄昏
CameraCharacteristics.CONTROL_AWB_MODE_SHADE -> "Shade" // 阴影
else -> "Unknown" // 未知
CameraCharacteristics.CONTROL_AWB_MODE_OFF -> "关闭"
CameraCharacteristics.CONTROL_AWB_MODE_AUTO -> "自动"
CameraCharacteristics.CONTROL_AWB_MODE_INCANDESCENT -> "白炽灯"
CameraCharacteristics.CONTROL_AWB_MODE_FLUORESCENT -> "荧光灯"
CameraCharacteristics.CONTROL_AWB_MODE_WARM_FLUORESCENT -> "暖荧光"
CameraCharacteristics.CONTROL_AWB_MODE_DAYLIGHT -> "日光"
CameraCharacteristics.CONTROL_AWB_MODE_CLOUDY_DAYLIGHT -> "阴天"
CameraCharacteristics.CONTROL_AWB_MODE_TWILIGHT -> "黄昏"
CameraCharacteristics.CONTROL_AWB_MODE_SHADE -> "阴影"
else -> "未知"
}
}
}
@ -557,26 +557,26 @@ class CameraInfo(private val context: Context) {
fun getSceneModes(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES)?.map {
when (it) {
CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED -> "Disabled" // 禁用
CameraCharacteristics.CONTROL_SCENE_MODE_FACE_PRIORITY -> "Face Priority" // 人像优先
CameraCharacteristics.CONTROL_SCENE_MODE_ACTION -> "Action" // 运动
CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT -> "Portrait" // 人像
CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE -> "Landscape" // 风景
CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT -> "Night" // 夜景
CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT -> "Night Portrait" // 夜景人像
CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE -> "Theatre" // 剧院
CameraCharacteristics.CONTROL_SCENE_MODE_BEACH -> "Beach" // 海滩
CameraCharacteristics.CONTROL_SCENE_MODE_SNOW -> "Snow" // 雪景
CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET -> "Sunset" // 日落
CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO -> "Steady Photo" // 防抖
CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS -> "Fireworks" // 烟火
CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS -> "Sports" // 体育
CameraCharacteristics.CONTROL_SCENE_MODE_PARTY -> "Party" // 派对
CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT -> "Candlelight" // 烛光
CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE -> "Barcode" // 条形码
CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) "High Speed Video" else "Unknown" // 高速视频/未知
CameraCharacteristics.CONTROL_SCENE_MODE_DISABLED -> "禁用"
CameraCharacteristics.CONTROL_SCENE_MODE_FACE_PRIORITY -> "人像优先"
CameraCharacteristics.CONTROL_SCENE_MODE_ACTION -> "运动"
CameraCharacteristics.CONTROL_SCENE_MODE_PORTRAIT -> "人像"
CameraCharacteristics.CONTROL_SCENE_MODE_LANDSCAPE -> "风景"
CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT -> "夜景"
CameraCharacteristics.CONTROL_SCENE_MODE_NIGHT_PORTRAIT -> "夜景人像"
CameraCharacteristics.CONTROL_SCENE_MODE_THEATRE -> "剧院"
CameraCharacteristics.CONTROL_SCENE_MODE_BEACH -> "海滩"
CameraCharacteristics.CONTROL_SCENE_MODE_SNOW -> "雪景"
CameraCharacteristics.CONTROL_SCENE_MODE_SUNSET -> "日落"
CameraCharacteristics.CONTROL_SCENE_MODE_STEADYPHOTO -> "防抖"
CameraCharacteristics.CONTROL_SCENE_MODE_FIREWORKS -> "烟火"
CameraCharacteristics.CONTROL_SCENE_MODE_SPORTS -> "体育"
CameraCharacteristics.CONTROL_SCENE_MODE_PARTY -> "派对"
CameraCharacteristics.CONTROL_SCENE_MODE_CANDLELIGHT -> "烛光"
CameraCharacteristics.CONTROL_SCENE_MODE_BARCODE -> "条形码"
CameraCharacteristics.CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) "高速视频" else "未知"
CameraCharacteristics.CONTROL_SCENE_MODE_HDR -> "HDR"
else -> "Unknown" // 未知
else -> "未知"
}
}
}
@ -587,16 +587,16 @@ class CameraInfo(private val context: Context) {
fun getColorEffects(characteristics: CameraCharacteristics): List<String>? {
return characteristics.get(CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS)?.map {
when (it) {
CameraCharacteristics.CONTROL_EFFECT_MODE_OFF -> "Off" // 关闭
CameraCharacteristics.CONTROL_EFFECT_MODE_MONO -> "Mono" // 黑白
CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE -> "Negative" // 负片
CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE -> "Solarize" // 曝光
CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA -> "Sepia" // 棕褐色
CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE -> "Posterize" // 海报化
CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD -> "Whiteboard" // 白板
CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD -> "Blackboard" // 黑板
CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA -> "Aqua" // 水蓝
else -> "Unknown" // 未知
CameraCharacteristics.CONTROL_EFFECT_MODE_OFF -> "关闭"
CameraCharacteristics.CONTROL_EFFECT_MODE_MONO -> "黑白"
CameraCharacteristics.CONTROL_EFFECT_MODE_NEGATIVE -> "负片"
CameraCharacteristics.CONTROL_EFFECT_MODE_SOLARIZE -> "曝光"
CameraCharacteristics.CONTROL_EFFECT_MODE_SEPIA -> "棕褐色"
CameraCharacteristics.CONTROL_EFFECT_MODE_POSTERIZE -> "海报化"
CameraCharacteristics.CONTROL_EFFECT_MODE_WHITEBOARD -> "白板"
CameraCharacteristics.CONTROL_EFFECT_MODE_BLACKBOARD -> "黑板"
CameraCharacteristics.CONTROL_EFFECT_MODE_AQUA -> "水蓝"
else -> "未知"
}
}
}

View File

@ -32,63 +32,6 @@ class CpuInfo {
val cores: List<Core>
get() = CpuInfoUtils.getCores()
/**
* 增强的核心信息数据类
* 包含核心的基本信息以及实时频率和性能度量
* @property core 核心基本信息
* @property currentFrequency 当前频率Hz
* @property minFrequency 最小频率Hz
* @property maxFrequency 最大频率Hz
* @property availableFrequencies 可用频率列表Hz
* @property speedMetric 速度度量值
*/
data class CoreDetailedInfo(
val core: Core,
val currentFrequency: Long,
val minFrequency: Long,
val maxFrequency: Long,
val availableFrequencies: List<Long>,
val speedMetric: Double
)
/**
* 获取所有核心的详细信息包含频率和速度度量
* @return 详细核心信息列表
*/
fun getCoresDetailedInfo(): List<CoreDetailedInfo> {
val coresList = cores
val result = mutableListOf<CoreDetailedInfo>()
coresList.forEachIndexed { index, core ->
val currentFreq = readFrequency("/sys/devices/system/cpu/cpu$index/cpufreq/scaling_cur_freq") * 1000 // Convert KHz to Hz
val minFreq = readFrequency("/sys/devices/system/cpu/cpu$index/cpufreq/cpuinfo_min_freq") * 1000
val maxFreq = readFrequency("/sys/devices/system/cpu/cpu$index/cpufreq/cpuinfo_max_freq") * 1000
val availableFreqs = readAvailableFrequencies("/sys/devices/system/cpu/cpu$index/cpufreq/scaling_available_frequencies")
.map { it * 1000 } // Convert KHz to Hz
// Calculate speed metric for this core
// Speed metric = (current_freq / max_freq) * 100, or use max_freq as baseline
val speedMetric = if (maxFreq > 0) {
(maxFreq.toDouble() / 1_000_000_000.0) // Convert to GHz as metric
} else {
0.0
}
result.add(
CoreDetailedInfo(
core = core,
currentFrequency = currentFreq,
minFrequency = minFreq,
maxFrequency = maxFreq,
availableFrequencies = availableFreqs,
speedMetric = speedMetric
)
)
}
return result
}
/**
* 获取所有核心集群列表大小核分组
* @return 集群列表
@ -157,7 +100,7 @@ class CpuInfo {
return if (packages.isNotEmpty()) {
packages[0].name
} else {
"Unknown" // 未知
"未知"
}
}
@ -169,7 +112,7 @@ class CpuInfo {
return if (cores.isNotEmpty()) {
cores[0].vendor.name
} else {
"Unknown" // 未知
"未知"
}
}
@ -262,7 +205,7 @@ class CpuInfo {
/**
* 制程信息数据类
* @property process 制程工艺例如 "4nm", "5nm", "7nm"
* @property foundry 代工厂例如 "TSMC", "Samsung"
* @property foundry 代工厂例如 "台积电", "三星"
* @property node 详细制程节点例如 "TSMC N4P", "Samsung 4LPE"
*/
data class ProcessInfo(
@ -281,110 +224,110 @@ class CpuInfo {
return when {
// 高通 Snapdragon 8 系列
"snapdragon 8 gen 3" in processorName || "sm8650" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4P") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4P")
"snapdragon 8 gen 2" in processorName || "sm8550" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"snapdragon 8 gen 1" in processorName || "sm8450" in processorName ->
ProcessInfo("4nm", "Samsung", "Samsung 4LPE") // 三星
ProcessInfo("4nm", "三星", "Samsung 4LPE")
"snapdragon 888+" in processorName || "sm8350-ab" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"snapdragon 888" in processorName || "sm8350" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"snapdragon 870" in processorName || "sm8250-ac" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7P") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7P")
"snapdragon 865+" in processorName || "sm8250-ab" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7P") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7P")
"snapdragon 865" in processorName || "sm8250" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7P") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7P")
// 高通 Snapdragon 7 系列
"snapdragon 7+ gen 2" in processorName || "sm7475" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"snapdragon 778g" in processorName || "sm7325" in processorName ->
ProcessInfo("6nm", "TSMC", "TSMC N6") // 台积电
ProcessInfo("6nm", "台积电", "TSMC N6")
// 高通 Snapdragon 6 系列
"snapdragon 695" in processorName || "sm6375" in processorName ->
ProcessInfo("6nm", "TSMC", "TSMC N6") // 台积电
ProcessInfo("6nm", "台积电", "TSMC N6")
// 联发科 Dimensity 9000 系列
"dimensity 9300" in processorName || "mt6989" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4P") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4P")
"dimensity 9200+" in processorName || "mt6985" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"dimensity 9200" in processorName || "mt6983" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"dimensity 9000+" in processorName || "mt6985" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"dimensity 9000" in processorName || "mt6983" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
// 联发科 Dimensity 8000 系列
"dimensity 8300" in processorName || "mt6897" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"dimensity 8200" in processorName || "mt6896" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"dimensity 8100" in processorName || "mt6895" in processorName ->
ProcessInfo("5nm", "TSMC", "TSMC N5") // 台积电
ProcessInfo("5nm", "台积电", "TSMC N5")
// 联发科 Dimensity 1000 系列
"dimensity 1200" in processorName || "mt6893" in processorName ->
ProcessInfo("6nm", "TSMC", "TSMC N6") // 台积电
ProcessInfo("6nm", "台积电", "TSMC N6")
"dimensity 1080" in processorName || "mt6877" in processorName ->
ProcessInfo("6nm", "TSMC", "TSMC N6") // 台积电
ProcessInfo("6nm", "台积电", "TSMC N6")
// 联发科 Helio 系列
"helio g99" in processorName || "mt6789" in processorName ->
ProcessInfo("6nm", "TSMC", "TSMC N6") // 台积电
ProcessInfo("6nm", "台积电", "TSMC N6")
// 三星 Exynos
"exynos 2400" in processorName || "s5e9945" in processorName ->
ProcessInfo("4nm", "Samsung", "Samsung 4LPP+") // 三星
ProcessInfo("4nm", "三星", "Samsung 4LPP+")
"exynos 2200" in processorName || "s5e9925" in processorName ->
ProcessInfo("4nm", "Samsung", "Samsung 4LPE") // 三星
ProcessInfo("4nm", "三星", "Samsung 4LPE")
"exynos 2100" in processorName || "s5e9840" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"exynos 1080" in processorName || "s5e1080" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"exynos 1380" in processorName || "s5e8835" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"exynos 1280" in processorName || "s5e8825" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
// 谷歌 Tensor
"tensor g3" in processorName || "gs301" in processorName ->
ProcessInfo("4nm", "Samsung", "Samsung 4LPP+") // 三星
ProcessInfo("4nm", "三星", "Samsung 4LPP+")
"tensor g2" in processorName || "gs201" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"tensor g1" in processorName || "gs101" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
"tensor" in processorName ->
ProcessInfo("5nm", "Samsung", "Samsung 5LPE") // 三星
ProcessInfo("5nm", "三星", "Samsung 5LPE")
// 华为麒麟
"kirin 9000" in processorName ->
ProcessInfo("5nm", "TSMC", "TSMC N5") // 台积电
ProcessInfo("5nm", "台积电", "TSMC N5")
"kirin 9000e" in processorName ->
ProcessInfo("5nm", "TSMC", "TSMC N5") // 台积电
ProcessInfo("5nm", "台积电", "TSMC N5")
"kirin 990" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7+") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7+")
"kirin 980" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7")
"kirin 810" in processorName ->
ProcessInfo("7nm", "TSMC", "TSMC N7") // 台积电
ProcessInfo("7nm", "台积电", "TSMC N7")
// 苹果 A 系列(参考)
"apple a17" in processorName ->
ProcessInfo("3nm", "TSMC", "TSMC N3B") // 台积电
ProcessInfo("3nm", "台积电", "TSMC N3B")
"apple a16" in processorName ->
ProcessInfo("4nm", "TSMC", "TSMC N4") // 台积电
ProcessInfo("4nm", "台积电", "TSMC N4")
"apple a15" in processorName ->
ProcessInfo("5nm", "TSMC", "TSMC N5P") // 台积电
ProcessInfo("5nm", "台积电", "TSMC N5P")
"apple a14" in processorName ->
ProcessInfo("5nm", "TSMC", "TSMC N5") // 台积电
ProcessInfo("5nm", "台积电", "TSMC N5")
// 默认情况
else -> ProcessInfo("Unknown", "Unknown", "") // 未知
else -> ProcessInfo("未知", "未知", "")
}
}
@ -420,7 +363,7 @@ class CpuInfo {
return if (cores.isNotEmpty()) {
cores[0].uarch.name
} else {
"Unknown" // 未知
"未知"
}
}
@ -439,7 +382,7 @@ class CpuInfo {
* @return ABI 字符串例如 "arm64-v8a", "armeabi-v7a"
*/
fun getAbi(): String {
return Build.SUPPORTED_ABIS.firstOrNull() ?: "Unknown" // 未知
return Build.SUPPORTED_ABIS.firstOrNull() ?: "未知"
}
/**
@ -515,218 +458,6 @@ class CpuInfo {
}
}
/**
* 获取指定核心的最大频率
* @param coreId 核心 ID
* @return 最大频率KHz失败返回 0
*/
fun getMaxFrequency(coreId: Int): Long {
return readFrequency("/sys/devices/system/cpu/cpu$coreId/cpufreq/cpuinfo_max_freq")
}
/**
* 获取指定核心的最小频率
* @param coreId 核心 ID
* @return 最小频率KHz失败返回 0
*/
fun getMinFrequency(coreId: Int): Long {
return readFrequency("/sys/devices/system/cpu/cpu$coreId/cpufreq/cpuinfo_min_freq")
}
/**
* 获取指定核心的当前频率
* @param coreId 核心 ID
* @return 当前频率KHz失败返回 0
*/
fun getCurrentFrequency(coreId: Int): Long {
return readFrequency("/sys/devices/system/cpu/cpu$coreId/cpufreq/scaling_cur_freq")
}
/**
* 获取所有核心的最大频率列表
* @return 最大频率列表KHz
*/
fun getAllMaxFrequencies(): List<Long> {
return (0 until getCoreCount()).map { getMaxFrequency(it) }
}
/**
* 获取所有核心的最小频率列表
* @return 最小频率列表KHz
*/
fun getAllMinFrequencies(): List<Long> {
return (0 until getCoreCount()).map { getMinFrequency(it) }
}
/**
* 获取所有核心的当前频率列表
* @return 当前频率列表KHz
*/
fun getAllCurrentFrequencies(): List<Long> {
return (0 until getCoreCount()).map { getCurrentFrequency(it) }
}
/**
* 获取系统中所有核心的最高最大频率
* @return 最高频率KHz
*/
fun getSystemMaxFrequency(): Long {
return getAllMaxFrequencies().maxOrNull() ?: 0L
}
/**
* 获取系统中所有核心的最低最小频率
* @return 最低频率KHz
*/
fun getSystemMinFrequency(): Long {
return getAllMinFrequencies().minOrNull() ?: 0L
}
// ==================== CPU 速度度量 ====================
/**
* /proc/cpuinfo 读取 BogoMIPS
* BogoMIPS Linux 内核在启动时计算的 CPU 性能度量值
* @return BogoMIPS 如果无法读取则返回 null
*/
fun getBogoMips(): Double? {
return try {
File("/proc/cpuinfo").readLines()
.find { it.startsWith("BogoMIPS") }
?.substringAfter(":")
?.trim()
?.toDoubleOrNull()
} catch (e: Exception) {
null
}
}
/**
* 获取所有核心的 BogoMIPS 值列表
* @return BogoMIPS 列表
*/
fun getAllBogoMips(): List<Double> {
return try {
File("/proc/cpuinfo").readLines()
.filter { it.startsWith("BogoMIPS") }
.mapNotNull { line ->
line.substringAfter(":")
.trim()
.toDoubleOrNull()
}
} catch (e: Exception) {
emptyList()
}
}
/**
* CPU 速度度量数据类
* @property totalScore 总体性能评分基于频率和核心数计算
* @property maxFrequency 系统最高频率KHz
* @property avgMaxFrequency 所有核心最大频率的平均值KHz
* @property bogoMips BogoMIPS 如果可用
* @property performanceIndex 性能指数0-100
*/
data class CpuSpeedMetric(
val totalScore: Double,
val maxFrequency: Long,
val avgMaxFrequency: Double,
val bogoMips: Double?,
val performanceIndex: Double
)
/**
* 获取 CPU 速度度量值
* 综合考虑核心数频率大小核配置等因素计算性能评分
* @return CPU 速度度量对象
*/
fun getCpuSpeedMetric(): CpuSpeedMetric {
val maxFreqs = getAllMaxFrequencies()
val systemMaxFreq = maxFreqs.maxOrNull() ?: 0L
val avgMaxFreq = if (maxFreqs.isNotEmpty()) {
maxFreqs.average()
} else {
0.0
}
// 计算总体评分(基于频率和核心数)
// 公式:(平均最大频率 * 核心数) / 1000000归一化到合理范围
val totalScore = (avgMaxFreq * getCoreCount()) / 1000.0
// 获取 BogoMIPS
val bogoMips = getBogoMips()
// 计算性能指数0-100
// 基准8核心 @ 3.0GHz = 100分
val baselineScore = 8.0 * 3_000_000 / 1000.0 // 24000
val performanceIndex = ((totalScore / baselineScore) * 100).coerceIn(0.0, 150.0)
return CpuSpeedMetric(
totalScore = totalScore,
maxFrequency = systemMaxFreq,
avgMaxFrequency = avgMaxFreq,
bogoMips = bogoMips,
performanceIndex = performanceIndex
)
}
/**
* 获取 CPU 性能等级评估
* @return 性能等级描述旗舰级高端中端入门级
*/
fun getCpuPerformanceLevel(): String {
val metric = getCpuSpeedMetric()
return when {
metric.performanceIndex >= 90 -> "Flagship" // 旗舰级
metric.performanceIndex >= 70 -> "High-end" // 高端
metric.performanceIndex >= 50 -> "Mid-range" // 中端
metric.performanceIndex >= 30 -> "Entry-level" // 入门级
else -> "Low-end" // 低端
}
}
/**
* 获取指定核心的详细信息
* @param coreIndex 核心索引从0开始
* @return 详细核心信息如果索引无效则返回 null
*/
fun getCoreDetailedInfo(coreIndex: Int): CoreDetailedInfo? {
if (coreIndex < 0 || coreIndex >= cores.size) return null
return getCoresDetailedInfo().getOrNull(coreIndex)
}
/**
* 获取所有核心的最大频率列表实时从系统读取
* @return 最大频率列表Hz
*/
fun getCoresMaxFrequencies(): List<Long> {
return getCoresDetailedInfo().map { it.maxFrequency }
}
/**
* 获取所有核心的最小频率列表实时从系统读取
* @return 最小频率列表Hz
*/
fun getCoresMinFrequencies(): List<Long> {
return getCoresDetailedInfo().map { it.minFrequency }
}
/**
* 获取所有核心的当前频率列表实时从系统读取
* @return 当前频率列表Hz
*/
fun getCoresCurrentFrequencies(): List<Long> {
return getCoresDetailedInfo().map { it.currentFrequency }
}
/**
* 获取所有核心的速度度量值列表
* @return 速度度量值列表GHz
*/
fun getCoresSpeedMetrics(): List<Double> {
return getCoresDetailedInfo().map { it.speedMetric }
}
// ==================== 调频器信息 ====================
/**
@ -739,7 +470,7 @@ class CpuInfo {
File("/sys/devices/system/cpu/cpu$coreId/cpufreq/scaling_governor")
.readText().trim()
} catch (e: Exception) {
"Unknown" // 未知
"未知"
}
}
@ -794,7 +525,7 @@ class CpuInfo {
return try {
File("/proc/cpuinfo").readText()
} catch (e: Exception) {
"Unable to read /proc/cpuinfo" // 无法读取 /proc/cpuinfo
"无法读取 /proc/cpuinfo"
}
}
@ -838,74 +569,60 @@ class CpuInfo {
val sb = StringBuilder()
// 基本信息
sb.append("=== CPU Basic Info ===\n") // CPU 基本信息
sb.append("Processor Name: ${getProcessorName()}\n") // 处理器名称
sb.append("Vendor: ${getVendor()}\n") // 供应商
sb.append("=== CPU 基本信息 ===\n")
sb.append("处理器名称: ${getProcessorName()}\n")
sb.append("供应商: ${getVendor()}\n")
val processInfo = getProcessInfo()
sb.append("Process: ${processInfo.process}\n") // 制程工艺
sb.append("Foundry: ${processInfo.foundry}\n") // 代工厂
sb.append("制程工艺: ${processInfo.process}\n")
sb.append("代工厂: ${processInfo.foundry}\n")
if (processInfo.node.isNotEmpty()) {
sb.append("Process Node: ${processInfo.node}\n") // 制程节点
sb.append("制程节点: ${processInfo.node}\n")
}
sb.append("Physical Cores: ${getCoreCount()}\n") // 物理核心数
sb.append("Logical Processors: ${getProcessorCount()}\n") // 逻辑处理器数
sb.append("物理核心数: ${getCoreCount()}\n")
sb.append("逻辑处理器数: ${getProcessorCount()}\n")
// 大小核信息
val clusterInfo = getClusterInfo()
sb.append("\n=== Core Cluster Configuration ===\n") // 大小核配置
sb.append("\n=== 大小核配置 ===\n")
if (clusterInfo.bigCoreCount > 0) {
sb.append("Big Cores: ${clusterInfo.bigCoreCount}, Max Frequency: ${formatFrequency(clusterInfo.bigCoreFreq)}\n") // 大核
sb.append("大核: ${clusterInfo.bigCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.bigCoreFreq)}\n")
}
if (clusterInfo.midCoreCount > 0) {
sb.append("Mid Cores: ${clusterInfo.midCoreCount}, Max Frequency: ${formatFrequency(clusterInfo.midCoreFreq)}\n") // 中核
sb.append("中核: ${clusterInfo.midCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.midCoreFreq)}\n")
}
if (clusterInfo.littleCoreCount > 0) {
sb.append("Little Cores: ${clusterInfo.littleCoreCount}, Max Frequency: ${formatFrequency(clusterInfo.littleCoreFreq)}\n") // 小核
sb.append("小核: ${clusterInfo.littleCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.littleCoreFreq)}\n")
}
// 架构信息
sb.append("\n=== Architecture Info ===\n") // 架构信息
sb.append("Architecture: ${getAllArchitectures().joinToString(", ")}\n") // 架构
sb.append("\n=== 架构信息 ===\n")
sb.append("架构: ${getAllArchitectures().joinToString(", ")}\n")
sb.append("ABI: ${getAbi()}\n")
sb.append("Supported ABIs: ${getSupportedAbis().joinToString(", ")}\n") // 支持的 ABI
// CPU 性能评估
val speedMetric = getCpuSpeedMetric()
sb.append("\n=== Performance Metrics ===\n") // 性能指标
sb.append("Performance Level: ${getCpuPerformanceLevel()}\n") // 性能等级
sb.append("Performance Index: ${String.format("%.1f", speedMetric.performanceIndex)}\n") // 性能指数
sb.append("Total Score: ${String.format("%.1f", speedMetric.totalScore)}\n") // 总体评分
speedMetric.bogoMips?.let {
sb.append("BogoMIPS: ${String.format("%.2f", it)}\n")
}
sb.append("支持的 ABI: ${getSupportedAbis().joinToString(", ")}\n")
// 调频器
sb.append("\n=== Governor ===\n") // 调频器
sb.append("Current Governor: ${getGovernor(0)}\n") // 当前调频器
sb.append("Available Governors: ${getAvailableGovernors().joinToString(", ")}\n") // 可用调频器
sb.append("\n=== 调频器 ===\n")
sb.append("当前调频器: ${getGovernor(0)}\n")
sb.append("可用调频器: ${getAvailableGovernors().joinToString(", ")}\n")
// 核心详细信息(包含实时频率和速度度量)
sb.append("\n=== Core Detailed Info ===\n") // 核心详细信息
val detailedCores = getCoresDetailedInfo()
detailedCores.forEachIndexed { index, coreInfo ->
sb.append("CPU$index: ")
sb.append("Current=${formatFrequency(coreInfo.currentFrequency.toULong())}, ") // 当前
sb.append("Range=${formatFrequency(coreInfo.minFrequency.toULong())}-${formatFrequency(coreInfo.maxFrequency.toULong())}, ") // 范围
sb.append("Metric=${String.format("%.2f GHz", coreInfo.speedMetric)}, ") // 度量值
sb.append("Arch=${coreInfo.core.uarch.name}\n") // 架构
// 核心详细频率
sb.append("\n=== 核心频率信息 ===\n")
getCoreFrequencies().forEach { freq ->
sb.append("CPU${freq.coreId}: 当前=${formatFrequency(freq.currentFreq.toULong() * 1000UL)}, ")
sb.append("范围=${formatFrequency(freq.minFreq.toULong() * 1000UL)}-${formatFrequency(freq.maxFreq.toULong() * 1000UL)}\n")
}
// 缓存信息
sb.append("\n=== Cache Info ===\n") // 缓存信息
sb.append("L1i Cache: ${l1iCaches.size}\n") // L1i 缓存
sb.append("L1d Cache: ${l1dCaches.size}\n") // L1d 缓存
sb.append("L2 Cache: ${l2Caches.size}\n") // L2 缓存
sb.append("L3 Cache: ${l3Caches.size}\n") // L3 缓存
sb.append("\n=== 缓存信息 ===\n")
sb.append("L1i 缓存: ${l1iCaches.size}\n")
sb.append("L1d 缓存: ${l1dCaches.size}\n")
sb.append("L2 缓存: ${l2Caches.size}\n")
sb.append("L3 缓存: ${l3Caches.size}\n")
// CPU 特性
val features = getCpuFeatures()
if (features.isNotEmpty()) {
sb.append("\n=== CPU Features ===\n") // CPU 特性
sb.append("\n=== CPU 特性 ===\n")
sb.append(features.joinToString(" "))
sb.append("\n")
}

View File

@ -55,14 +55,6 @@ class DisplayInfo(private val context: Context) {
false
}
// 计算屏幕物理尺寸
val screenSize = calculateScreenSize(
displayMetrics.widthPixels,
displayMetrics.heightPixels,
displayMetrics.xdpi,
displayMetrics.ydpi
)
return DefaultDisplayInfo(
id = defaultDisplay.displayId,
name = defaultDisplay.name,
@ -76,8 +68,7 @@ class DisplayInfo(private val context: Context) {
supportedRefreshRates = supportedRefreshRates,
isHdr = isHdr,
hdrTypes,
isWideColorGamut = isWideColorGamut,
screenSize = screenSize
isWideColorGamut = isWideColorGamut
)
}
@ -118,118 +109,6 @@ class DisplayInfo(private val context: Context) {
return diagonalPixels / diagonalInches
}
/**
* 计算屏幕物理尺寸
* @param widthPixels 屏幕宽度像素
* @param heightPixels 屏幕高度像素
* @param xdpi X 轴每英寸像素数
* @param ydpi Y 轴每英寸像素数
* @return 屏幕尺寸信息
*/
private fun calculateScreenSize(
widthPixels: Int,
heightPixels: Int,
xdpi: Float,
ydpi: Float
): ScreenSize {
// 计算宽度(英寸)
val widthInches = widthPixels / xdpi.toDouble()
// 计算高度(英寸)
val heightInches = heightPixels / ydpi.toDouble()
// 计算对角线(英寸)使用勾股定理
val diagonalInches = sqrt(widthInches * widthInches + heightInches * heightInches)
// 转换为毫米 (1 英寸 = 25.4 毫米)
val widthMm = widthInches * 25.4
val heightMm = heightInches * 25.4
val diagonalMm = diagonalInches * 25.4
return ScreenSize(
diagonalInches = diagonalInches,
diagonalMm = diagonalMm,
widthInches = widthInches,
widthMm = widthMm,
heightInches = heightInches,
heightMm = heightMm
)
}
/**
* 获取屏幕尺寸英寸和毫米
* @return 屏幕尺寸信息如果获取失败返回 null
*/
fun getScreenSize(): ScreenSize? {
return getDefaultDisplayInfo()?.screenSize
}
/**
* 获取屏幕对角线尺寸英寸
* @return 对角线尺寸英寸
*/
fun getScreenDiagonalInches(): Double? {
return getScreenSize()?.diagonalInches
}
/**
* 获取屏幕对角线尺寸毫米
* @return 对角线尺寸毫米
*/
fun getScreenDiagonalMm(): Double? {
return getScreenSize()?.diagonalMm
}
/**
* 获取屏幕宽度英寸
* @return 屏幕宽度英寸
*/
fun getScreenWidthInches(): Double? {
return getScreenSize()?.widthInches
}
/**
* 获取屏幕宽度毫米
* @return 屏幕宽度毫米
*/
fun getScreenWidthMm(): Double? {
return getScreenSize()?.widthMm
}
/**
* 获取屏幕高度英寸
* @return 屏幕高度英寸
*/
fun getScreenHeightInches(): Double? {
return getScreenSize()?.heightInches
}
/**
* 获取屏幕高度毫米
* @return 屏幕高度毫米
*/
fun getScreenHeightMm(): Double? {
return getScreenSize()?.heightMm
}
/**
* 屏幕尺寸信息数据类
* @property diagonalInches 对角线尺寸英寸
* @property diagonalMm 对角线尺寸毫米
* @property widthInches 宽度英寸
* @property widthMm 宽度毫米
* @property heightInches 高度英寸
* @property heightMm 高度毫米
*/
data class ScreenSize(
val diagonalInches: Double, // 对角线尺寸(英寸)
val diagonalMm: Double, // 对角线尺寸(毫米)
val widthInches: Double, // 宽度(英寸)
val widthMm: Double, // 宽度(毫米)
val heightInches: Double, // 高度(英寸)
val heightMm: Double // 高度(毫米)
)
/**
* 默认显示器信息数据类
* @property id 显示器 ID
@ -245,7 +124,6 @@ class DisplayInfo(private val context: Context) {
* @property isHdr 是否支持 HDR
* @property hdrTypes 支持的 HDR 类型列表
* @property isWideColorGamut 是否支持广色域
* @property screenSize 屏幕物理尺寸
*/
data class DefaultDisplayInfo(
val id: Int, // 显示器 ID
@ -260,7 +138,6 @@ class DisplayInfo(private val context: Context) {
val supportedRefreshRates: List<Float>, // 支持的刷新率列表Hz
val isHdr: Boolean, // 是否支持 HDR
val hdrTypes: List<String>, // 支持的 HDR 类型列表
val isWideColorGamut: Boolean, // 是否支持广色域
val screenSize: ScreenSize // 屏幕物理尺寸
val isWideColorGamut: Boolean // 是否支持广色域
)
}

View File

@ -21,24 +21,6 @@ class GpuInfo(private val context: Context) {
System.loadLibrary("andinfo")
}
/**
* GPU 详细信息数据类
* @property maxFrequency 最大频率MHz
* @property architecture GPU 架构
* @property cacheSize 缓存大小KB
* @property bandwidth 内存带宽GB/s
* @property computeUnits 计算单元数量
* @property shadingUnits 着色单元数量
*/
data class GpuDetailedInfo(
val maxFrequency: Int?, // MHz
val architecture: String?, // 架构名称
val cacheSize: Int?, // KB
val bandwidth: Double?, // GB/s
val computeUnits: Int?, // 计算单元
val shadingUnits: Int? // 着色单元
)
/**
* 获取完整的 GPU 信息
* 包括 Vulkan 物理设备信息和 EGL 信息
@ -125,24 +107,7 @@ class GpuInfo(private val context: Context) {
*/
fun getOpenGLVersion(): String? {
val gpuInfo = getGpuInformation()
val glVersion = gpuInfo.eglInformation?.glInformation?.glVersion
// 如果从 EGL 获取失败,尝试从系统属性获取
if (glVersion.isNullOrEmpty()) {
return try {
// 尝试从 Vulkan 信息推断
val vkVersion = getVulkanApiVersion()
if (vkVersion != null) {
"OpenGL ES 3.2" // Vulkan 1.0+ 通常支持 GLES 3.2
} else {
"Unknown" // 未知
}
} catch (e: Exception) {
"Unknown" // 未知
}
}
return glVersion
return gpuInfo.eglInformation?.glInformation?.glVersion
}
/**
@ -207,328 +172,12 @@ class GpuInfo(private val context: Context) {
}
/**
* 获取 GPU 设备类型的描述
* @return 设备类型描述
* 获取 GPU 设备类型的中文描述
* @return 设备类型中文描述
*/
fun getDeviceTypeDescription(): String? {
return getDeviceType()?.let {
vkPhysicalDeviceTypeToString[it.value] // 使用英文
}
}
/**
* 获取 GPU 详细信息频率架构缓存带宽等
* 基于 GPU 型号名称推断硬件规格
* @return GPU 详细信息
*/
fun getGpuDetailedInfo(): GpuDetailedInfo {
val rendererName = getRendererName()?.lowercase() ?: ""
return getGpuSpecsByRenderer(rendererName)
}
/**
* 获取 GPU 最大频率
* @return 最大频率MHz如果无法获取则返回 null
*/
fun getMaxFrequency(): Int? {
return getGpuDetailedInfo().maxFrequency
}
/**
* 获取 GPU 架构
* @return GPU 架构名称
*/
fun getArchitecture(): String? {
return getGpuDetailedInfo().architecture
}
/**
* 获取 GPU 缓存大小
* @return 缓存大小KB
*/
fun getCacheSize(): Int? {
return getGpuDetailedInfo().cacheSize
}
/**
* 获取 GPU 内存带宽
* @return 内存带宽GB/s
*/
fun getBandwidth(): Double? {
return getGpuDetailedInfo().bandwidth
}
/**
* 获取计算单元数量
* @return 计算单元数量
*/
fun getComputeUnits(): Int? {
return getGpuDetailedInfo().computeUnits
}
/**
* 获取着色单元数量
* @return 着色单元数量
*/
fun getShadingUnits(): Int? {
return getGpuDetailedInfo().shadingUnits
}
/**
* 根据 GPU 渲染器名称获取硬件规格
* 包含常见移动 GPU 的规格数据
*/
private fun getGpuSpecsByRenderer(renderer: String): GpuDetailedInfo {
return when {
// Qualcomm Adreno 系列
"adreno 740" in renderer -> GpuDetailedInfo(
maxFrequency = 680,
architecture = "Adreno 740",
cacheSize = 2048,
bandwidth = 51.2,
computeUnits = 6,
shadingUnits = 768
)
"adreno 730" in renderer -> GpuDetailedInfo(
maxFrequency = 818,
architecture = "Adreno 730",
cacheSize = 1536,
bandwidth = 44.8,
computeUnits = 6,
shadingUnits = 768
)
"adreno 725" in renderer -> GpuDetailedInfo(
maxFrequency = 790,
architecture = "Adreno 725",
cacheSize = 1024,
bandwidth = 38.4,
computeUnits = 5,
shadingUnits = 640
)
"adreno 720" in renderer -> GpuDetailedInfo(
maxFrequency = 800,
architecture = "Adreno 720",
cacheSize = 1024,
bandwidth = 35.2,
computeUnits = 5,
shadingUnits = 640
)
"adreno 710" in renderer -> GpuDetailedInfo(
maxFrequency = 770,
architecture = "Adreno 710",
cacheSize = 768,
bandwidth = 28.8,
computeUnits = 4,
shadingUnits = 512
)
"adreno 702" in renderer -> GpuDetailedInfo(
maxFrequency = 845,
architecture = "Adreno 702",
cacheSize = 512,
bandwidth = 25.6,
computeUnits = 3,
shadingUnits = 384
)
"adreno 690" in renderer -> GpuDetailedInfo(
maxFrequency = 840,
architecture = "Adreno 690",
cacheSize = 1536,
bandwidth = 44.8,
computeUnits = 6,
shadingUnits = 768
)
"adreno 660" in renderer -> GpuDetailedInfo(
maxFrequency = 900,
architecture = "Adreno 660",
cacheSize = 1024,
bandwidth = 51.2,
computeUnits = 6,
shadingUnits = 512
)
"adreno 650" in renderer -> GpuDetailedInfo(
maxFrequency = 587,
architecture = "Adreno 650",
cacheSize = 1024,
bandwidth = 34.1,
computeUnits = 4,
shadingUnits = 512
)
"adreno 640" in renderer -> GpuDetailedInfo(
maxFrequency = 675,
architecture = "Adreno 640",
cacheSize = 768,
bandwidth = 29.9,
computeUnits = 4,
shadingUnits = 384
)
"adreno 630" in renderer -> GpuDetailedInfo(
maxFrequency = 710,
architecture = "Adreno 630",
cacheSize = 512,
bandwidth = 29.9,
computeUnits = 4,
shadingUnits = 256
)
"adreno 620" in renderer -> GpuDetailedInfo(
maxFrequency = 650,
architecture = "Adreno 620",
cacheSize = 256,
bandwidth = 25.6,
computeUnits = 2,
shadingUnits = 256
)
// ARM Mali 系列
"mali-g720" in renderer -> GpuDetailedInfo(
maxFrequency = 800,
architecture = "Mali-G720 (5th Gen Valhall)",
cacheSize = 2048,
bandwidth = 68.3,
computeUnits = 16,
shadingUnits = 256
)
"mali-g715" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G715 (4th Gen Valhall)",
cacheSize = 1536,
bandwidth = 51.2,
computeUnits = 11,
shadingUnits = 176
)
"mali-g710" in renderer -> GpuDetailedInfo(
maxFrequency = 848,
architecture = "Mali-G710 (3rd Gen Valhall)",
cacheSize = 1536,
bandwidth = 51.2,
computeUnits = 10,
shadingUnits = 160
)
"mali-g610" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G610 (3rd Gen Valhall)",
cacheSize = 1024,
bandwidth = 42.7,
computeUnits = 6,
shadingUnits = 96
)
"mali-g78" in renderer -> GpuDetailedInfo(
maxFrequency = 848,
architecture = "Mali-G78 (2nd Gen Valhall)",
cacheSize = 2048,
bandwidth = 51.2,
computeUnits = 24,
shadingUnits = 384
)
"mali-g77" in renderer -> GpuDetailedInfo(
maxFrequency = 800,
architecture = "Mali-G77 (1st Gen Valhall)",
cacheSize = 1024,
bandwidth = 42.7,
computeUnits = 11,
shadingUnits = 176
)
"mali-g76" in renderer -> GpuDetailedInfo(
maxFrequency = 800,
architecture = "Mali-G76 (2nd Gen Bifrost)",
cacheSize = 768,
bandwidth = 34.1,
computeUnits = 12,
shadingUnits = 192
)
"mali-g72" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G72 (1st Gen Bifrost)",
cacheSize = 512,
bandwidth = 29.9,
computeUnits = 18,
shadingUnits = 288
)
"mali-g71" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G71 (1st Gen Bifrost)",
cacheSize = 512,
bandwidth = 27.7,
computeUnits = 16,
shadingUnits = 256
)
"mali-g68" in renderer -> GpuDetailedInfo(
maxFrequency = 950,
architecture = "Mali-G68 (2nd Gen Valhall)",
cacheSize = 1024,
bandwidth = 44.8,
computeUnits = 6,
shadingUnits = 96
)
"mali-g57" in renderer -> GpuDetailedInfo(
maxFrequency = 950,
architecture = "Mali-G57 (1st Gen Valhall)",
cacheSize = 512,
bandwidth = 25.6,
computeUnits = 5,
shadingUnits = 80
)
"mali-g52" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G52 (2nd Gen Bifrost)",
cacheSize = 256,
bandwidth = 17.0,
computeUnits = 4,
shadingUnits = 64
)
"mali-g51" in renderer -> GpuDetailedInfo(
maxFrequency = 850,
architecture = "Mali-G51 (1st Gen Bifrost)",
cacheSize = 256,
bandwidth = 14.9,
computeUnits = 4,
shadingUnits = 64
)
// Apple GPU参考
"apple" in renderer && ("a17" in renderer || "m3" in renderer) -> GpuDetailedInfo(
maxFrequency = 1398,
architecture = "Apple GPU (A17/M3)",
cacheSize = 3072,
bandwidth = 102.4,
computeUnits = 6,
shadingUnits = 768
)
"apple" in renderer && ("a16" in renderer || "m2" in renderer) -> GpuDetailedInfo(
maxFrequency = 1338,
architecture = "Apple GPU (A16/M2)",
cacheSize = 2560,
bandwidth = 68.3,
computeUnits = 5,
shadingUnits = 640
)
"apple" in renderer && ("a15" in renderer || "m1" in renderer) -> GpuDetailedInfo(
maxFrequency = 1296,
architecture = "Apple GPU (A15/M1)",
cacheSize = 2048,
bandwidth = 68.3,
computeUnits = 5,
shadingUnits = 640
)
// PowerVR 系列
"powervr" in renderer && "ge8320" in renderer -> GpuDetailedInfo(
maxFrequency = 680,
architecture = "PowerVR GE8320",
cacheSize = 128,
bandwidth = 10.7,
computeUnits = 2,
shadingUnits = 32
)
// 默认情况
else -> GpuDetailedInfo(
maxFrequency = null,
architecture = "Unknown", // 未知
cacheSize = null,
bandwidth = null,
computeUnits = null,
shadingUnits = null
)
vkPhysicalDeviceTypeToStringChinese[it.value]
}
}
@ -539,73 +188,60 @@ class GpuInfo(private val context: Context) {
fun getGpuSummary(): String {
val sb = StringBuilder()
val gpuInfo = getGpuInformation()
val detailedInfo = getGpuDetailedInfo()
sb.append("=== GPU Basic Info ===\n") // GPU 基本信息
getVendorName()?.let { sb.append("Vendor: $it\n") } // 供应商
getRendererName()?.let { sb.append("Model: $it\n") } // 型号
getDeviceTypeDescription()?.let { sb.append("Type: $it\n") } // 类型
// GPU 详细规格
sb.append("\n=== GPU Specifications ===\n") // GPU 规格
detailedInfo.architecture?.let { sb.append("Architecture: $it\n") } // 架构
detailedInfo.maxFrequency?.let { sb.append("Max Frequency: $it MHz\n") } // 最大频率
detailedInfo.cacheSize?.let { sb.append("Cache Size: $it KB\n") } // 缓存大小
detailedInfo.bandwidth?.let { sb.append("Memory Bandwidth: ${String.format("%.1f", it)} GB/s\n") } // 内存带宽
detailedInfo.computeUnits?.let { sb.append("Compute Units: $it\n") } // 计算单元
detailedInfo.shadingUnits?.let { sb.append("Shading Units: $it\n") } // 着色单元
sb.append("=== GPU 基本信息 ===\n")
getVendorName()?.let { sb.append("供应商: $it\n") }
getRendererName()?.let { sb.append("型号: $it\n") }
getDeviceTypeDescription()?.let { sb.append("类型: $it\n") }
// Vulkan 信息
if (isVulkanSupported()) {
sb.append("\n=== Vulkan Info ===\n") // Vulkan 信息
sb.append("Supported: Yes\n") // 支持
getVulkanApiVersion()?.let { sb.append("API Version: $it\n") } // API 版本
getVulkanDriverVersion()?.let { sb.append("Driver Version: $it\n") } // 驱动版本
sb.append("\n=== Vulkan 信息 ===\n")
sb.append("支持: 是\n")
getVulkanApiVersion()?.let { sb.append("API 版本: $it\n") }
getVulkanDriverVersion()?.let { sb.append("驱动版本: $it\n") }
gpuInfo.vkPhysicalDevices?.forEach { device ->
sb.append("\n--- Vulkan Device ---\n") // Vulkan 设备
sb.append("Device Name: ${device.deviceName}\n") // 设备名称
sb.append("Device ID: ${device.deviceId}\n") // 设备 ID
sb.append("Vendor ID: 0x${device.vendorId.toString(16)}\n") // 供应商 ID
sb.append("\n--- Vulkan 设备 ---\n")
sb.append("设备名称: ${device.deviceName}\n")
sb.append("设备 ID: ${device.deviceId}\n")
sb.append("供应商 ID: 0x${device.vendorId.toString(16)}\n")
device.registeredVendorId?.let {
sb.append("Registered Vendor: ${getVendorName(it)}\n") // 注册供应商
sb.append("注册供应商: ${getVendorName(it)}\n")
}
sb.append("Device Type: ${vkPhysicalDeviceTypeToString[device.deviceType.value]}\n") // 设备类型
sb.append("设备类型: ${vkPhysicalDeviceTypeToStringChinese[device.deviceType.value]}\n")
val ver = device.apiVersion
sb.append("API Version: ${ver.major}.${ver.minor}.${ver.patch}") // API 版本
sb.append("API 版本: ${ver.major}.${ver.minor}.${ver.patch}")
if (ver.variant > 0) {
sb.append(" (Variant: ${ver.variant})") // 变体
sb.append(" (变体: ${ver.variant})")
}
sb.append("\n")
}
} else {
sb.append("\n=== Vulkan Info ===\n") // Vulkan 信息
sb.append("Supported: No\n") // 支持
sb.append("\n=== Vulkan 信息 ===\n")
sb.append("支持: 否\n")
}
// OpenGL ES 信息
sb.append("\n=== OpenGL ES Info ===\n") // OpenGL ES 信息
sb.append("\n=== OpenGL ES 信息 ===\n")
gpuInfo.eglInformation?.glInformation?.let { gl ->
gl.glVendor?.let { sb.append("Vendor: $it\n") } // 供应商
gl.glRenderer?.let { sb.append("Renderer: $it\n") } // 渲染器
gl.glVersion?.let { sb.append("Version: $it\n") } // 版本
gl.glVendor?.let { sb.append("供应商: $it\n") }
gl.glRenderer?.let { sb.append("渲染器: $it\n") }
gl.glVersion?.let { sb.append("版本: $it\n") }
val extCount = getOpenGLExtensionCount()
sb.append("Extension Count: $extCount\n") // 扩展数量
} ?: run {
val glVersion = getOpenGLVersion()
sb.append("Version: ${glVersion ?: "Unknown"}\n") // 版本
sb.append("扩展数量: $extCount\n")
}
// EGL 信息
sb.append("\n=== EGL Info ===\n") // EGL 信息
sb.append("\n=== EGL 信息 ===\n")
gpuInfo.eglInformation?.let { egl ->
egl.eglVendor?.let { sb.append("Vendor: $it\n") } // 供应商
egl.eglVersion?.let { sb.append("Version: $it\n") } // 版本
egl.eglVendor?.let { sb.append("供应商: $it\n") }
egl.eglVersion?.let { sb.append("版本: $it\n") }
egl.eglClientApi?.let { apis ->
sb.append("Client API: ${apis.joinToString(", ")}\n") // 客户端 API
sb.append("客户端 API: ${apis.joinToString(", ")}\n")
}
val extCount = getEglExtensionCount()
sb.append("Extension Count: $extCount\n") // 扩展数量
sb.append("扩展数量: $extCount\n")
}
return sb.toString()
@ -638,7 +274,7 @@ class GpuInfo(private val context: Context) {
* 从注册的 Vulkan 供应商 ID 获取名称
*/
private fun getVendorName(vendorId: VkVendorId): String {
return vkVendorIdToString[vendorId] ?: "Unknown" // 未知
return vkVendorIdToStringChinese[vendorId] ?: vkVendorIdToString[vendorId] ?: "Unknown"
}
/**
@ -656,10 +292,21 @@ class GpuInfo(private val context: Context) {
* Vulkan 物理设备类型映射英文
*/
val vkPhysicalDeviceTypeToString = mapOf(
VkPhysicalDeviceType.OTHER.value to "Other", // 其他
VkPhysicalDeviceType.INTEGRATED_GPU.value to "Integrated GPU", // 集成显卡
VkPhysicalDeviceType.DISCRETE_GPU.value to "Discrete GPU", // 独立显卡
VkPhysicalDeviceType.VIRTUAL_GPU.value to "Virtual GPU", // 虚拟显卡
VkPhysicalDeviceType.OTHER.value to "Other",
VkPhysicalDeviceType.INTEGRATED_GPU.value to "Integrated GPU",
VkPhysicalDeviceType.DISCRETE_GPU.value to "Discrete GPU",
VkPhysicalDeviceType.VIRTUAL_GPU.value to "Virtual GPU",
VkPhysicalDeviceType.CPU.value to "CPU",
)
/**
* Vulkan 物理设备类型映射中文
*/
val vkPhysicalDeviceTypeToStringChinese = mapOf(
VkPhysicalDeviceType.OTHER.value to "其他",
VkPhysicalDeviceType.INTEGRATED_GPU.value to "集成显卡",
VkPhysicalDeviceType.DISCRETE_GPU.value to "独立显卡",
VkPhysicalDeviceType.VIRTUAL_GPU.value to "虚拟显卡",
VkPhysicalDeviceType.CPU.value to "CPU",
)
@ -667,14 +314,28 @@ class GpuInfo(private val context: Context) {
* Vulkan 注册供应商 ID 映射英文
*/
val vkVendorIdToString = mapOf(
VkVendorId.KHRONOS to "Khronos", // Khronos科纳斯
VkVendorId.VIV to "Vivante", // Vivante维万特
VkVendorId.VSI to "VeriSilicon", // VeriSilicon芯原
VkVendorId.KHRONOS to "Khronos",
VkVendorId.VIV to "Vivante",
VkVendorId.VSI to "VeriSilicon",
VkVendorId.KAZAN to "Kazan",
VkVendorId.CODEPLAY to "Codeplay",
VkVendorId.MESA to "Mesa",
VkVendorId.POCL to "POCL",
VkVendorId.MOBILEYE to "Mobileye", // Mobileye移动眼
VkVendorId.MOBILEYE to "Mobileye",
)
/**
* Vulkan 注册供应商 ID 映射中文
*/
val vkVendorIdToStringChinese = mapOf(
VkVendorId.KHRONOS to "Khronos科纳斯",
VkVendorId.VIV to "Vivante维万特",
VkVendorId.VSI to "VeriSilicon芯原",
VkVendorId.KAZAN to "Kazan",
VkVendorId.CODEPLAY to "Codeplay",
VkVendorId.MESA to "Mesa",
VkVendorId.POCL to "POCL",
VkVendorId.MOBILEYE to "Mobileye移动眼",
)
/**

View File

@ -9,26 +9,6 @@ import java.io.File
class StorageInfo(private val context: Context) {
/**
* 存储分解信息数据类
* 详细展示存储空间的使用情况
*/
data class StorageBreakdown(
val totalSpace: Long, // 总空间
val usedSpace: Long, // 已使用空间
val freeSpace: Long, // 可用空间
val systemSize: Long, // 系统占用
val appsAndDataSize: Long, // 应用和数据占用
val cacheSize: Long, // 缓存占用
val otherSize: Long // 其他占用
) {
val usedPercentage: Double
get() = if (totalSpace > 0) (usedSpace.toDouble() / totalSpace * 100) else 0.0
val freePercentage: Double
get() = if (totalSpace > 0) (freeSpace.toDouble() / totalSpace * 100) else 0.0
}
// 内部存储总空间
val internalStorageTotalSpace: Long
get() = StatFs(Environment.getDataDirectory().absolutePath).let { statFs ->
@ -107,150 +87,12 @@ class StorageInfo(private val context: Context) {
0L
}
// 系统占用大小/system 分区)
// 系统占用大小
val systemSize: Long
get() = StatFs(Environment.getRootDirectory().absolutePath).let { statFs ->
statFs.blockCountLong * statFs.blockSizeLong
}
// 缓存占用大小
val cacheSize: Long
get() = try {
val cacheDir = File("/data/cache")
val appCacheDir = context.cacheDir
calculateDirectorySize(cacheDir) + calculateDirectorySize(appCacheDir)
} catch (e: Exception) {
0L
}
/**
* 获取内部存储的详细分解信息
* @return 存储分解信息
*/
fun getInternalStorageBreakdown(): StorageBreakdown {
val total = internalStorageTotalSpace
val available = internalStorageAvailableSpace
val used = total - available
// 获取各部分占用
val system = systemSize
val appsData = applicationsAndDataSize
val cache = cacheSize
val other = maxOf(0L, used - system - appsData - cache)
return StorageBreakdown(
totalSpace = total,
usedSpace = used,
freeSpace = available,
systemSize = system,
appsAndDataSize = appsData,
cacheSize = cache,
otherSize = other
)
}
/**
* 获取格式化的应用和数据占用大小
* @return 格式化后的字符串 "15.5 GB"
*/
fun getFormattedAppsAndDataSize(): String = formatBytes(applicationsAndDataSize)
/**
* 获取格式化的系统占用大小
* @return 格式化后的字符串 "8.2 GB"
*/
fun getFormattedSystemSize(): String = formatBytes(systemSize)
/**
* 获取格式化的可用空间大小
* @return 格式化后的字符串 "32.1 GB"
*/
fun getFormattedFreeSpace(): String = formatBytes(internalStorageAvailableSpace)
/**
* 获取格式化的缓存占用大小
* @return 格式化后的字符串 "1.2 GB"
*/
fun getFormattedCacheSize(): String = formatBytes(cacheSize)
/**
* 获取存储使用百分比
* @return 使用百分比0-100
*/
fun getUsagePercentage(): Double {
val total = internalStorageTotalSpace
return if (total > 0) {
(internalStorageUsedSpace.toDouble() / total * 100)
} else 0.0
}
/**
* 获取可用空间百分比
* @return 可用百分比0-100
*/
fun getFreePercentage(): Double {
val total = internalStorageTotalSpace
return if (total > 0) {
(internalStorageAvailableSpace.toDouble() / total * 100)
} else 0.0
}
/**
* 获取存储信息摘要
* @return 格式化的存储信息文本
*/
fun getStorageSummary(): String {
val breakdown = getInternalStorageBreakdown()
return buildString {
appendLine("=== Internal Storage ===")
appendLine("Total: ${formatBytes(breakdown.totalSpace)}")
appendLine("Used: ${formatBytes(breakdown.usedSpace)} (${String.format("%.1f%%", breakdown.usedPercentage)})")
appendLine("Free: ${formatBytes(breakdown.freeSpace)} (${String.format("%.1f%%", breakdown.freePercentage)})")
appendLine("\n=== Storage Breakdown ===")
appendLine("System: ${formatBytes(breakdown.systemSize)}")
appendLine("Apps & Data: ${formatBytes(breakdown.appsAndDataSize)}")
appendLine("Cache: ${formatBytes(breakdown.cacheSize)}")
appendLine("Other: ${formatBytes(breakdown.otherSize)}")
if (externalStorageTotalSpace != null) {
appendLine("\n=== External Storage ===")
appendLine("Total: ${formatBytes(externalStorageTotalSpace!!)}")
externalStorageUsedSpace?.let {
appendLine("Used: ${formatBytes(it)}")
}
externalStorageAvailableSpace?.let {
appendLine("Free: ${formatBytes(it)}")
}
appendLine("Emulated: ${if (isExternalStorageEmulated) "Yes" else "No"}")
appendLine("Removable: ${if (isExternalStorageRemovable) "Yes" else "No"}")
}
appendLine("\n=== Storage Features ===")
isInternalStorageEncrypted?.let {
appendLine("Encrypted: ${if (it) "Yes" else "No"}")
}
internalStorageEncryptionType?.let {
appendLine("Encryption Type: ${it.name}")
}
internalStorageFileSystemType?.let {
appendLine("File System: $it")
}
appendLine("\n=== Partition Scheme ===")
usesAb?.let {
appendLine("A/B Updates: ${if (it) "Yes" else "No"}")
}
usesDynamicPartitions?.let {
appendLine("Dynamic Partitions: ${if (it) "Yes" else "No"}")
}
usesVirtualAb?.let {
appendLine("Virtual A/B: ${if (it) "Yes" else "No"}")
}
}
}
// 外部存储总空间
val externalStorageTotalSpace: Long?
get() = runCatching {