diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/CpuInfo.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/CpuInfo.kt index d2a767b..3204cc4 100644 --- a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/CpuInfo.kt +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/CpuInfo.kt @@ -1,5 +1,6 @@ package com.xyzshell.andinfo.libs +import android.os.Build import com.xyzshell.andinfo.libs.cpu.models.Cache import com.xyzshell.andinfo.libs.cpu.models.Cluster import com.xyzshell.andinfo.libs.cpu.models.Core @@ -7,60 +8,640 @@ import com.xyzshell.andinfo.libs.cpu.models.Package import com.xyzshell.andinfo.libs.cpu.models.Processor import com.xyzshell.andinfo.libs.cpu.models.UarchInfo import com.xyzshell.andinfo.libs.cpu.utils.CpuInfoUtils +import java.io.File +/** + * CPU 信息类 + * 用于获取设备处理器的详细信息,包括核心数、频率、架构、缓存等 + */ class CpuInfo { + + // ==================== 基础处理器信息 ==================== + + /** + * 获取所有逻辑处理器列表 + * @return 逻辑处理器列表 + */ val processors: List get() = CpuInfoUtils.getProcessors() + /** + * 获取所有物理核心列表 + * @return 物理核心列表 + */ val cores: List get() = CpuInfoUtils.getCores() + /** + * 获取所有核心集群列表(大小核分组) + * @return 集群列表 + */ val clusters: List get() = CpuInfoUtils.getClusters() + /** + * 获取所有物理封装(芯片)列表 + * @return 封装列表 + */ val packages: List get() = CpuInfoUtils.getPackages() + /** + * 获取所有微架构信息列表 + * @return 微架构信息列表 + */ val uarchs: List get() = CpuInfoUtils.getUarchs() + // ==================== 缓存信息 ==================== + + /** + * L1 指令缓存列表 + * @return L1i 缓存列表 + */ val l1iCaches: List get() = CpuInfoUtils.getL1iCaches() + /** + * L1 数据缓存列表 + * @return L1d 缓存列表 + */ val l1dCaches: List get() = CpuInfoUtils.getL1dCaches() + /** + * L2 缓存列表 + * @return L2 缓存列表 + */ val l2Caches: List get() = CpuInfoUtils.getL2Caches() + /** + * L3 缓存列表 + * @return L3 缓存列表 + */ val l3Caches: List get() = CpuInfoUtils.getL3Caches() + /** + * L4 缓存列表 + * @return L4 缓存列表 + */ val l4Caches: List get() = CpuInfoUtils.getL4Caches() - fun hardware(): String { - return if (processors.isNotEmpty()) { - processors[0].cpuPackage?.name ?: "未知" + // ==================== 处理器名称和供应商 ==================== + + /** + * 获取处理器名称(SoC 型号) + * @return 处理器名称,例如 "Qualcomm Snapdragon 888" + */ + fun getProcessorName(): String { + return if (packages.isNotEmpty()) { + packages[0].name } else { "未知" } } + /** + * 获取处理器供应商 + * @return 供应商名称,例如 "Qualcomm", "ARM", "Intel" 等 + */ + fun getVendor(): String { + return if (cores.isNotEmpty()) { + cores[0].vendor.name + } else { + "未知" + } + } + + // ==================== 核心数量信息 ==================== + + /** + * 获取物理核心总数 + * @return 核心数量 + */ + fun getCoreCount(): Int { + return cores.size + } + + /** + * 获取逻辑处理器总数 + * @return 逻辑处理器数量 + */ + fun getProcessorCount(): Int { + return processors.size + } + + // ==================== 大小核信息 ==================== + + /** + * 大小核信息数据类 + * @property bigCoreCount 大核数量 + * @property midCoreCount 中核数量 + * @property littleCoreCount 小核数量 + * @property bigCoreFreq 大核最高频率(Hz) + * @property midCoreFreq 中核最高频率(Hz) + * @property littleCoreFreq 小核最高频率(Hz) + */ + data class ClusterInfo( + val bigCoreCount: Int, + val midCoreCount: Int, + val littleCoreCount: Int, + val bigCoreFreq: ULong, + val midCoreFreq: ULong, + val littleCoreFreq: ULong + ) + + /** + * 获取大小核信息 + * @return 大小核信息对象 + */ + fun getClusterInfo(): ClusterInfo { + if (clusters.isEmpty()) { + return ClusterInfo(0, 0, 0, 0UL, 0UL, 0UL) + } + + // 按频率排序集群 + val sortedClusters = clusters.sortedByDescending { cluster -> + cores.filter { it.cluster.clusterId == cluster.clusterId } + .maxOfOrNull { it.frequency } ?: 0UL + } + + return when (sortedClusters.size) { + 1 -> ClusterInfo( + 0, 0, sortedClusters[0].coreCount.toInt(), + 0UL, 0UL, + cores.filter { it.cluster.clusterId == sortedClusters[0].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL + ) + 2 -> ClusterInfo( + sortedClusters[0].coreCount.toInt(), + 0, + sortedClusters[1].coreCount.toInt(), + cores.filter { it.cluster.clusterId == sortedClusters[0].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL, + 0UL, + cores.filter { it.cluster.clusterId == sortedClusters[1].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL + ) + else -> ClusterInfo( + sortedClusters[0].coreCount.toInt(), + sortedClusters[1].coreCount.toInt(), + sortedClusters[2].coreCount.toInt(), + cores.filter { it.cluster.clusterId == sortedClusters[0].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL, + cores.filter { it.cluster.clusterId == sortedClusters[1].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL, + cores.filter { it.cluster.clusterId == sortedClusters[2].clusterId } + .maxOfOrNull { it.frequency } ?: 0UL + ) + } + } + + // ==================== 制程和架构 ==================== + + /** + * 制程信息数据类 + * @property process 制程工艺,例如 "4nm", "5nm", "7nm" 等 + * @property foundry 代工厂,例如 "台积电", "三星" 等 + * @property node 详细制程节点,例如 "TSMC N4P", "Samsung 4LPE" 等 + */ + data class ProcessInfo( + val process: String, + val foundry: String, + val node: String = "" + ) + + /** + * 获取制程信息(根据 SoC 型号查询) + * @return 制程信息对象,包含制程工艺和代工厂 + */ + fun getProcessInfo(): ProcessInfo { + val processorName = getProcessorName().lowercase() + + return when { + // 高通 Snapdragon 8 系列 + "snapdragon 8 gen 3" in processorName || "sm8650" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4P") + "snapdragon 8 gen 2" in processorName || "sm8550" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "snapdragon 8 gen 1" in processorName || "sm8450" in processorName -> + ProcessInfo("4nm", "三星", "Samsung 4LPE") + "snapdragon 888+" in processorName || "sm8350-ab" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "snapdragon 888" in processorName || "sm8350" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "snapdragon 870" in processorName || "sm8250-ac" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7P") + "snapdragon 865+" in processorName || "sm8250-ab" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7P") + "snapdragon 865" in processorName || "sm8250" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7P") + + // 高通 Snapdragon 7 系列 + "snapdragon 7+ gen 2" in processorName || "sm7475" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "snapdragon 778g" in processorName || "sm7325" in processorName -> + ProcessInfo("6nm", "台积电", "TSMC N6") + + // 高通 Snapdragon 6 系列 + "snapdragon 695" in processorName || "sm6375" in processorName -> + ProcessInfo("6nm", "台积电", "TSMC N6") + + // 联发科 Dimensity 9000 系列 + "dimensity 9300" in processorName || "mt6989" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4P") + "dimensity 9200+" in processorName || "mt6985" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "dimensity 9200" in processorName || "mt6983" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "dimensity 9000+" in processorName || "mt6985" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "dimensity 9000" in processorName || "mt6983" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + + // 联发科 Dimensity 8000 系列 + "dimensity 8300" in processorName || "mt6897" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "dimensity 8200" in processorName || "mt6896" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "dimensity 8100" in processorName || "mt6895" in processorName -> + ProcessInfo("5nm", "台积电", "TSMC N5") + + // 联发科 Dimensity 1000 系列 + "dimensity 1200" in processorName || "mt6893" in processorName -> + ProcessInfo("6nm", "台积电", "TSMC N6") + "dimensity 1080" in processorName || "mt6877" in processorName -> + ProcessInfo("6nm", "台积电", "TSMC N6") + + // 联发科 Helio 系列 + "helio g99" in processorName || "mt6789" in processorName -> + ProcessInfo("6nm", "台积电", "TSMC N6") + + // 三星 Exynos + "exynos 2400" in processorName || "s5e9945" in processorName -> + ProcessInfo("4nm", "三星", "Samsung 4LPP+") + "exynos 2200" in processorName || "s5e9925" in processorName -> + ProcessInfo("4nm", "三星", "Samsung 4LPE") + "exynos 2100" in processorName || "s5e9840" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "exynos 1080" in processorName || "s5e1080" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "exynos 1380" in processorName || "s5e8835" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "exynos 1280" in processorName || "s5e8825" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + + // 谷歌 Tensor + "tensor g3" in processorName || "gs301" in processorName -> + ProcessInfo("4nm", "三星", "Samsung 4LPP+") + "tensor g2" in processorName || "gs201" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "tensor g1" in processorName || "gs101" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + "tensor" in processorName -> + ProcessInfo("5nm", "三星", "Samsung 5LPE") + + // 华为麒麟 + "kirin 9000" in processorName -> + ProcessInfo("5nm", "台积电", "TSMC N5") + "kirin 9000e" in processorName -> + ProcessInfo("5nm", "台积电", "TSMC N5") + "kirin 990" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7+") + "kirin 980" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7") + "kirin 810" in processorName -> + ProcessInfo("7nm", "台积电", "TSMC N7") + + // 苹果 A 系列(参考) + "apple a17" in processorName -> + ProcessInfo("3nm", "台积电", "TSMC N3B") + "apple a16" in processorName -> + ProcessInfo("4nm", "台积电", "TSMC N4") + "apple a15" in processorName -> + ProcessInfo("5nm", "台积电", "TSMC N5P") + "apple a14" in processorName -> + ProcessInfo("5nm", "台积电", "TSMC N5") + + // 默认情况 + else -> ProcessInfo("未知", "未知", "") + } + } + + /** + * 获取制程信息(字符串格式,兼容旧版本) + * @return 制程信息,例如 "5nm", "7nm" 等 + */ + fun getProcess(): String { + return getProcessInfo().process + } + + /** + * 获取代工厂信息 + * @return 代工厂名称,例如 "台积电", "三星" 等 + */ + fun getFoundry(): String { + return getProcessInfo().foundry + } + + /** + * 获取详细制程节点 + * @return 制程节点,例如 "TSMC N4P", "Samsung 5LPE" 等 + */ + fun getProcessNode(): String { + return getProcessInfo().node.ifEmpty { getProcessInfo().process } + } + + /** + * 获取 CPU 架构 + * @return 架构名称,例如 "Cortex-A78", "Cortex-X1" 等 + */ + fun getArchitecture(): String { + return if (cores.isNotEmpty()) { + cores[0].uarch.name + } else { + "未知" + } + } + + /** + * 获取所有核心的架构列表(去重) + * @return 架构列表 + */ + fun getAllArchitectures(): List { + return cores.map { it.uarch.name }.distinct() + } + + // ==================== ABI 信息 ==================== + + /** + * 获取当前设备的主 ABI + * @return ABI 字符串,例如 "arm64-v8a", "armeabi-v7a" 等 + */ + fun getAbi(): String { + return Build.SUPPORTED_ABIS.firstOrNull() ?: "未知" + } + + /** + * 获取所有支持的 ABI 列表 + * @return ABI 列表 + */ + fun getSupportedAbis(): List { + return Build.SUPPORTED_ABIS.toList() + } + + // ==================== 频率信息 ==================== + + /** + * 单个核心的频率信息 + * @property coreId 核心 ID + * @property currentFreq 当前频率(KHz) + * @property minFreq 最小频率(KHz) + * @property maxFreq 最大频率(KHz) + * @property availableFreqs 可用频率列表(KHz) + */ + data class CoreFrequencyInfo( + val coreId: Int, + val currentFreq: Long, + val minFreq: Long, + val maxFreq: Long, + val availableFreqs: List + ) + + /** + * 获取所有核心的详细频率信息 + * @return 核心频率信息列表 + */ + fun getCoreFrequencies(): List { + val result = mutableListOf() + + for (i in 0 until getCoreCount()) { + val currentFreq = readFrequency("/sys/devices/system/cpu/cpu$i/cpufreq/scaling_cur_freq") + val minFreq = readFrequency("/sys/devices/system/cpu/cpu$i/cpufreq/cpuinfo_min_freq") + val maxFreq = readFrequency("/sys/devices/system/cpu/cpu$i/cpufreq/cpuinfo_max_freq") + val availableFreqs = readAvailableFrequencies("/sys/devices/system/cpu/cpu$i/cpufreq/scaling_available_frequencies") + + result.add(CoreFrequencyInfo(i, currentFreq, minFreq, maxFreq, availableFreqs)) + } + + return result + } + + /** + * 读取频率值 + * @param path 频率文件路径 + * @return 频率值(KHz),失败返回 0 + */ + private fun readFrequency(path: String): Long { + return try { + File(path).readText().trim().toLongOrNull() ?: 0L + } catch (e: Exception) { + 0L + } + } + + /** + * 读取可用频率列表 + * @param path 可用频率文件路径 + * @return 频率列表(KHz) + */ + private fun readAvailableFrequencies(path: String): List { + return try { + File(path).readText().trim() + .split("\\s+".toRegex()) + .mapNotNull { it.toLongOrNull() } + } catch (e: Exception) { + emptyList() + } + } + + // ==================== 调频器信息 ==================== + + /** + * 获取指定核心的调频器 + * @param coreId 核心 ID + * @return 调频器名称,例如 "schedutil", "interactive" 等 + */ + fun getGovernor(coreId: Int): String { + return try { + File("/sys/devices/system/cpu/cpu$coreId/cpufreq/scaling_governor") + .readText().trim() + } catch (e: Exception) { + "未知" + } + } + + /** + * 获取所有核心的调频器 + * @return 调频器列表 + */ + fun getAllGovernors(): List { + return (0 until getCoreCount()).map { getGovernor(it) } + } + + /** + * 获取可用的调频器列表 + * @param coreId 核心 ID + * @return 可用调频器列表 + */ + fun getAvailableGovernors(coreId: Int = 0): List { + return try { + File("/sys/devices/system/cpu/cpu$coreId/cpufreq/scaling_available_governors") + .readText().trim() + .split("\\s+".toRegex()) + } catch (e: Exception) { + emptyList() + } + } + + // ==================== CPU 特性 ==================== + + /** + * 获取 CPU 特性列表(从 /proc/cpuinfo 读取 Features) + * @return CPU 特性列表 + */ + fun getCpuFeatures(): List { + return try { + File("/proc/cpuinfo").readLines() + .find { it.startsWith("Features") } + ?.substringAfter(":") + ?.trim() + ?.split("\\s+".toRegex()) ?: emptyList() + } catch (e: Exception) { + emptyList() + } + } + + // ==================== /proc/cpuinfo 原始信息 ==================== + + /** + * 获取 /proc/cpuinfo 的完整内容 + * @return /proc/cpuinfo 文件内容 + */ + fun getProcCpuInfo(): String { + return try { + File("/proc/cpuinfo").readText() + } catch (e: Exception) { + "无法读取 /proc/cpuinfo" + } + } + + /** + * 解析 /proc/cpuinfo 为键值对映射 + * @return 解析后的映射表 + */ + fun parseProcCpuInfo(): Map { + val result = mutableMapOf() + try { + File("/proc/cpuinfo").readLines().forEach { line -> + if (line.contains(":")) { + val parts = line.split(":", limit = 2) + if (parts.size == 2) { + result[parts[0].trim()] = parts[1].trim() + } + } + } + } catch (e: Exception) { + // 忽略错误 + } + return result + } + + // ==================== 兼容性方法 ==================== + + /** + * 获取硬件名称(兼容旧版本) + * @return 处理器名称 + */ + @Deprecated("使用 getProcessorName() 替代", ReplaceWith("getProcessorName()")) + fun hardware(): String { + return getProcessorName() + } + + /** + * 获取文本格式的 CPU 信息摘要 + * @return 格式化的文本信息 + */ fun text(): String { - val stringBuilder = StringBuilder() - stringBuilder.append("处理器数量: ${processors.size}\n") - processors.forEachIndexed { index, processor -> - stringBuilder.append(" 处理器 ${index}: ${processor.cpuPackage?.name ?: "未知"}\n") - stringBuilder.append(" 核心: ${processor.core?.coreId ?: "未知"}\n") - stringBuilder.append(" 集群: ${processor.cluster?.clusterId ?: "未知"}\n") + val sb = StringBuilder() + + // 基本信息 + sb.append("=== CPU 基本信息 ===\n") + sb.append("处理器名称: ${getProcessorName()}\n") + sb.append("供应商: ${getVendor()}\n") + val processInfo = getProcessInfo() + sb.append("制程工艺: ${processInfo.process}\n") + sb.append("代工厂: ${processInfo.foundry}\n") + if (processInfo.node.isNotEmpty()) { + sb.append("制程节点: ${processInfo.node}\n") } - stringBuilder.append("核心数量: ${cores.size}\n") - cores.forEachIndexed { index, core -> - stringBuilder.append(" 核心 ${index}: ID=${core.coreId}, 频率=${core.frequency}Hz\n") + sb.append("物理核心数: ${getCoreCount()}\n") + sb.append("逻辑处理器数: ${getProcessorCount()}\n") + + // 大小核信息 + val clusterInfo = getClusterInfo() + sb.append("\n=== 大小核配置 ===\n") + if (clusterInfo.bigCoreCount > 0) { + sb.append("大核: ${clusterInfo.bigCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.bigCoreFreq)}\n") + } + if (clusterInfo.midCoreCount > 0) { + sb.append("中核: ${clusterInfo.midCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.midCoreFreq)}\n") + } + if (clusterInfo.littleCoreCount > 0) { + sb.append("小核: ${clusterInfo.littleCoreCount} 个, 最高频率: ${formatFrequency(clusterInfo.littleCoreFreq)}\n") + } + + // 架构信息 + sb.append("\n=== 架构信息 ===\n") + sb.append("架构: ${getAllArchitectures().joinToString(", ")}\n") + sb.append("ABI: ${getAbi()}\n") + sb.append("支持的 ABI: ${getSupportedAbis().joinToString(", ")}\n") + + // 调频器 + sb.append("\n=== 调频器 ===\n") + sb.append("当前调频器: ${getGovernor(0)}\n") + sb.append("可用调频器: ${getAvailableGovernors().joinToString(", ")}\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=== 缓存信息 ===\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 特性 ===\n") + sb.append(features.joinToString(" ")) + sb.append("\n") + } + + return sb.toString() + } + + /** + * 格式化频率显示 + * @param freqHz 频率(Hz) + * @return 格式化后的频率字符串 + */ + private fun formatFrequency(freqHz: ULong): String { + return when { + freqHz >= 1_000_000_000UL -> String.format("%.2f GHz", freqHz.toDouble() / 1_000_000_000) + freqHz >= 1_000_000UL -> String.format("%.0f MHz", freqHz.toDouble() / 1_000_000) + freqHz >= 1_000UL -> String.format("%.0f KHz", freqHz.toDouble() / 1_000) + else -> "$freqHz Hz" } - // 可以根据需要添加更多详细信息 - return stringBuilder.toString() } companion object { diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/DisplayInfo.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/DisplayInfo.kt index ac76cf6..5bf26f6 100644 --- a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/DisplayInfo.kt +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/DisplayInfo.kt @@ -6,11 +6,20 @@ import android.os.Build import android.view.Display import android.graphics.Point import android.util.DisplayMetrics +import kotlin.math.sqrt + +/** + * 显示信息类,用于获取设备屏幕相关信息 + */ class DisplayInfo(private val context: Context) { private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager + /** + * 获取默认显示器信息 + * @return 默认显示器信息对象,如果获取失败返回 null + */ fun getDefaultDisplayInfo(): DefaultDisplayInfo? { val defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY) ?: return null @@ -22,13 +31,24 @@ class DisplayInfo(private val context: Context) { val mode = defaultDisplay.mode val refreshRate = mode.refreshRate - - val isHdr = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - defaultDisplay.hdrCapabilities?.supportedHdrTypes?.isNotEmpty() ?: false + // 计算 PPI (每英寸像素数) + val ppi = calculatePPI(displayMetrics.widthPixels, displayMetrics.heightPixels, displayMetrics.densityDpi) + // 获取支持的刷新率列表 + val supportedRefreshRates = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + defaultDisplay.supportedModes.map { it.refreshRate }.distinct().sorted() } else { - false + listOf(refreshRate) } + // 检查是否支持 HDR 及 HDR 类型 + val hdrTypes = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + defaultDisplay.mode?.supportedHdrTypes?.map { getHdrTypeName(it) } ?: emptyList() + } else { + emptyList() + } + val isHdr = hdrTypes.isNotEmpty() + + // 检查是否支持广色域 val isWideColorGamut = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { defaultDisplay.isWideColorGamut } else { @@ -43,22 +63,81 @@ class DisplayInfo(private val context: Context) { densityDpi = displayMetrics.densityDpi, xdpi = displayMetrics.xdpi, ydpi = displayMetrics.ydpi, + ppi = ppi, refreshRate = refreshRate, + supportedRefreshRates = supportedRefreshRates, isHdr = isHdr, + hdrTypes, isWideColorGamut = isWideColorGamut ) } + /** + * 获取 HDR 类型名称 + * @param hdrType HDR 类型常量 + * @return HDR 类型名称 + */ + private fun getHdrTypeName(hdrType: Int): String { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + when (hdrType) { + Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION -> "Dolby Vision" + Display.HdrCapabilities.HDR_TYPE_HDR10 -> "HDR10" + Display.HdrCapabilities.HDR_TYPE_HLG -> "HLG" + Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS -> "HDR10+" + else -> "Unknown HDR Type ($hdrType)" + } + } else { + "Unknown" + } + } + /** + * 计算屏幕 PPI (每英寸像素数) + * @param widthPixels 屏幕宽度像素 + * @param heightPixels 屏幕高度像素 + * @param densityDpi 屏幕密度 DPI + * @return PPI 值 + */ + private fun calculatePPI(widthPixels: Int, heightPixels: Int, densityDpi: Int): Double { + // 使用勾股定理计算对角线像素数 + val diagonalPixels = sqrt((widthPixels * widthPixels + heightPixels * heightPixels).toDouble()) + + // 通过 densityDpi 计算屏幕对角线英寸数 + // 160 DPI 是 Android 的基准密度 (mdpi) + val diagonalInches = diagonalPixels / densityDpi + + // PPI = 对角线像素数 / 对角线英寸数 + return diagonalPixels / diagonalInches + } + + /** + * 默认显示器信息数据类 + * @property id 显示器 ID + * @property name 显示器名称 + * @property widthPixels 屏幕宽度(像素) + * @property heightPixels 屏幕高度(像素) + * @property densityDpi 屏幕密度 DPI + * @property xdpi X 轴每英寸像素数 + * @property ydpi Y 轴每英寸像素数 + * @property ppi 屏幕 PPI(每英寸像素数) + * @property refreshRate 当前刷新率(Hz) + * @property supportedRefreshRates 支持的刷新率列表(Hz) + * @property isHdr 是否支持 HDR + * @property hdrTypes 支持的 HDR 类型列表 + * @property isWideColorGamut 是否支持广色域 + */ data class DefaultDisplayInfo( - val id: Int, - val name: String, - val widthPixels: Int, - val heightPixels: Int, - val densityDpi: Int, - val xdpi: Float, - val ydpi: Float, - val refreshRate: Float, - val isHdr: Boolean, - val isWideColorGamut: Boolean + val id: Int, // 显示器 ID + val name: String, // 显示器名称 + val widthPixels: Int, // 屏幕宽度(像素) + val heightPixels: Int, // 屏幕高度(像素) + val densityDpi: Int, // 屏幕密度 DPI + val xdpi: Float, // X 轴 DPI + val ydpi: Float, // Y 轴 DPI + val ppi: Double, // 屏幕 PPI + val refreshRate: Float, // 当前刷新率(Hz) + val supportedRefreshRates: List, // 支持的刷新率列表(Hz) + val isHdr: Boolean, // 是否支持 HDR + val hdrTypes: List, // 支持的 HDR 类型列表 + val isWideColorGamut: Boolean // 是否支持广色域 ) } diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/utils/WebService.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/utils/WebService.kt index 9746309..14c96cc 100644 --- a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/utils/WebService.kt +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/utils/WebService.kt @@ -1,14 +1,32 @@ package com.xyzshell.andinfo.utils +import android.util.Base64 import com.google.gson.Gson import okhttp3.* import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody.Companion.toRequestBody import java.io.IOException +import javax.crypto.Cipher +import javax.crypto.spec.SecretKeySpec class WebService { private val client = OkHttpClient() val gson = Gson() + // AES 密钥 (必须是 16/24/32 字节) + private val aesKey = "e67cbcee5e573d1b" + + // AES 加密 + fun encrypt(plainText: String): String { + return try { + val secretKey = SecretKeySpec(aesKey.toByteArray(), "AES") + val cipher = Cipher.getInstance("AES") + cipher.init(Cipher.ENCRYPT_MODE, secretKey) + val encryptedBytes = cipher.doFinal(plainText.toByteArray()) + Base64.encodeToString(encryptedBytes, Base64.NO_WRAP) + } catch (e: Exception) { + throw Exception("加密失败: ${e.message}") + } + } fun postData(url: String, jsonData: String, callback: (String?, Exception?) -> Unit) { val mediaType = "application/json; charset=utf-8".toMediaType() val body = jsonData.toRequestBody(mediaType)