This commit is contained in:
lhyqy5 2025-10-28 16:48:17 +08:00
parent 6cde51f782
commit e2be896d11
30 changed files with 2299 additions and 27 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "myphoneinfo/andinfo/src/main/cpp/cpuinfo"]
path = myphoneinfo/andinfo/src/main/cpp/cpuinfo
url = https://github.com/pytorch/cpuinfo

@ -0,0 +1 @@
Subproject commit 877328f188a3c7d1fa855871a278eb48d530c4c0

View File

@ -0,0 +1,5 @@
package com.xyzshell.ksp_annotations
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class AutoBuilder

View File

@ -0,0 +1 @@
com.xyzshell.ksp_processor.AutoBuilderProcessorProvider

View File

@ -0,0 +1,118 @@
package com.xyzshell.ksp_processor
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.validate
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.writeTo
import com.xyzshell.ksp_annotations.AutoBuilder
class AutoBuilderProcessor(
private val codeGenerator: CodeGenerator,
private val logger: KSPLogger
) : SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation(AutoBuilder::class.qualifiedName!!)
val ret = symbols.filter { !it.validate() }.toList()
symbols
.filter { it is KSClassDeclaration && it.validate() }
.forEach { it ->
generateBuilderClass(it as KSClassDeclaration)
}
return ret
}
private fun generateBuilderClass(classDeclaration: KSClassDeclaration) {
val packageName = classDeclaration.containingFile!!.packageName.asString()
val className = classDeclaration.simpleName.asString()
val builderClassName = "${className}Builder"
logger.info("Generating builder for $className")
// 获取类的构造函数参数
val constructor = classDeclaration.primaryConstructor
if (constructor == null) {
logger.error("Class $className must have a primary constructor", classDeclaration)
return
}
val properties = constructor.parameters
// 创建Builder类
val builderClass = TypeSpec.classBuilder(builderClassName)
.addKdoc("Auto-generated builder for %L", className)
// 添加属性字段
properties.forEach { param ->
val paramName = param.name!!.asString()
val paramType = param.type.resolve()
val typeName = paramType.toClassName()
builderClass.addProperty(
PropertySpec.builder(paramName, typeName.copy(nullable = true))
.mutable()
.initializer("null")
.addModifiers(KModifier.PRIVATE)
.build()
)
}
// 添加setter方法
properties.forEach { param ->
val paramName = param.name!!.asString()
val paramType = param.type.resolve()
val typeName = paramType.toClassName()
val setterMethod = FunSpec.builder(paramName)
.addParameter(paramName, typeName)
.returns(ClassName(packageName, builderClassName))
.addStatement("this.%L = %L", paramName, paramName)
.addStatement("return this")
.build()
builderClass.addFunction(setterMethod)
}
// 添加build方法
val buildMethod = FunSpec.builder("build")
.returns(ClassName(packageName, className))
.apply {
val paramNames = properties.map { it.name!!.asString() }
val paramChecks = paramNames.map { paramName ->
"checkNotNull($paramName) { \"$paramName must be set\" }"
}
addStatement(
"return %T(%L)",
ClassName(packageName, className),
paramChecks.joinToString(", ")
)
}
.build()
builderClass.addFunction(buildMethod)
// 添加静态工厂方法
val companionObject = TypeSpec.companionObjectBuilder()
.addFunction(
FunSpec.builder("builder")
.returns(ClassName(packageName, builderClassName))
.addStatement("return %T()", ClassName(packageName, builderClassName))
.build()
)
.build()
builderClass.addType(companionObject)
// 生成文件
val file = FileSpec.builder(packageName, builderClassName)
.addType(builderClass.build())
.build()
file.writeTo(codeGenerator, Dependencies(true, classDeclaration.containingFile!!))
}
}

View File

@ -0,0 +1,14 @@
package com.xyzshell.ksp_processor
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
class AutoBuilderProcessorProvider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return AutoBuilderProcessor(
codeGenerator = environment.codeGenerator,
logger = environment.logger
)
}
}

View File

@ -12,8 +12,16 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
}
}
ndkVersion = "26.1.10909125"
buildTypes {
release {
isMinifyEnabled = false

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.22.1)
project("andinfo")
add_subdirectory(cpuinfo)
add_library(andinfo SHARED
CpuInfoUtils.cpp
CpuJni.cpp)
target_link_libraries(andinfo
android
log
cpuinfo)

View File

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
#define LOG_TAG "CpuUtils"
#include <android/log.h>
#include <cpuinfo.h>
#include <jni.h>
#include "CpuJni.h"
#include "jni_utils.h"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define CPUINFO_JNI_FUNC(func_name, clazz_lowercase, cpuinfo_func_name) \
extern "C" \
JNIEXPORT void JNICALL \
Java_com_xyzshell_andinfo_libs_cpu_utils_CpuInfoUtils_get##func_name(JNIEnv *env, \
jobject thiz, \
jobject arraylist) { \
auto cpuJni = CpuJni(env); \
auto addMethodID = getArrayListAddMethodID(env, arraylist); \
\
cpuinfo_initialize(); \
\
auto elements_count = cpuinfo_get_##cpuinfo_func_name##_count(); \
\
auto elements = cpuinfo_get_##cpuinfo_func_name(); \
\
for (int i = 0; i < elements_count; i++) { \
env->CallBooleanMethod( \
arraylist, addMethodID, \
cpuJni.clazz_lowercase##ToJava(&elements[i])); \
JNI_CHECK(env); \
} \
\
cpuinfo_deinitialize(); \
}
CPUINFO_JNI_FUNC(Processors, processor, processors)
CPUINFO_JNI_FUNC(Cores, core, cores)
CPUINFO_JNI_FUNC(Clusters, cluster, clusters)
CPUINFO_JNI_FUNC(Packages, package, packages)
CPUINFO_JNI_FUNC(Uarchs, uarchInfo, uarchs)
CPUINFO_JNI_FUNC(L1iCaches, cache, l1i_caches)
CPUINFO_JNI_FUNC(L1dCaches, cache, l1d_caches)
CPUINFO_JNI_FUNC(L2Caches, cache, l2_caches)
CPUINFO_JNI_FUNC(L3Caches, cache, l3_caches)
CPUINFO_JNI_FUNC(L4Caches, cache, l4_caches)

View File

@ -0,0 +1,181 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
#include "CpuJni.h"
#include <cpuinfo.h>
#include "jni_utils.h"
jobject CpuJni::cacheToJava(const struct cpuinfo_cache *cache) {
if (cache == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
cacheClazz, cacheFromCpuInfoMethodID,
cache->size,
cache->associativity,
cache->sets,
cache->partitions,
cache->line_size,
cache->flags,
cache->processor_start,
cache->processor_count
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::clusterToJava(const struct cpuinfo_cluster *cluster) {
if (cluster == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
clusterClazz, clusterFromCpuInfoMethodID,
cluster->processor_start,
cluster->processor_count,
cluster->core_start,
cluster->core_count,
cluster->cluster_id,
packageToJava(cluster->package),
cluster->vendor,
cluster->uarch,
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
cluster->cpuid,
#else
0,
#endif
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
cluster->midr,
#else
0,
#endif
cluster->frequency
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::coreToJava(const struct cpuinfo_core *core) {
if (core == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
coreClazz, coreFromCpuInfoMethodID,
core->processor_start,
core->processor_count,
core->core_id,
clusterToJava(core->cluster),
packageToJava(core->package),
core->vendor,
core->uarch,
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
core->cpuid,
#else
0,
#endif
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
core->midr,
#else
0,
#endif
core->frequency
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::packageToJava(const struct cpuinfo_package *package) {
if (package == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
packageClazz, packageFromCpuInfoMethodID,
mEnv->NewStringUTF(package->name),
package->processor_start,
package->processor_count,
package->core_start,
package->core_count,
package->cluster_start,
package->cluster_count
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::processorToJava(const struct cpuinfo_processor *processor) {
if (processor == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
processorClazz, processorFromCpuInfoMethodID,
processor->smt_id,
coreToJava(processor->core),
clusterToJava(processor->cluster),
packageToJava(processor->package),
processor->linux_id,
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
processor->apic_id,
#else
0,
#endif
processorCacheToJava(processor)
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::processorCacheToJava(const struct cpuinfo_processor *processor) {
if (processor == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
processorCacheClazz, processorCacheFromCpuInfoMethodID,
cacheToJava(processor->cache.l1i),
cacheToJava(processor->cache.l1d),
cacheToJava(processor->cache.l2),
cacheToJava(processor->cache.l3),
cacheToJava(processor->cache.l4)
);
JNI_CHECK(mEnv);
return object;
}
jobject CpuJni::uarchInfoToJava(const struct cpuinfo_uarch_info *uarchInfo) {
if (uarchInfo == nullptr) {
return nullptr;
}
auto object = mEnv->CallStaticObjectMethod(
uarchInfoClazz, uarchInfoFromCpuInfoMethodID,
uarchInfo->uarch,
#if CPUINFO_ARCH_X86 || CPUINFO_ARCH_X86_64
uarchInfo->cpuid,
#else
0,
#endif
#if CPUINFO_ARCH_ARM || CPUINFO_ARCH_ARM64
uarchInfo->midr,
#else
0,
#endif
uarchInfo->processor_count,
uarchInfo->core_count
);
JNI_CHECK(mEnv);
return object;
}

View File

@ -0,0 +1,112 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <cpuinfo.h>
#include <cstdlib>
#include <jni.h>
#include "jni_utils.h"
#define CPU_PACKAGE "com/xyzshell/andinfo/libs/cpu/models"
#define CPU_CLASS_SIG(clazz) "L" CPU_PACKAGE "/" #clazz ";"
#define DECLARE_CPU_CLASS(clazz, fromCpuInfo_args_signature) \
inline static jclass get##clazz##Class(JNIEnv *env) { \
auto clazzObject = env->FindClass(CPU_PACKAGE "/" #clazz); \
JNI_CHECK(env); \
return clazzObject; \
} \
\
inline static jmethodID get##clazz##FromCpuInfoMethodID(JNIEnv *env, jclass clazzObject) { \
auto methodID = env->GetStaticMethodID( \
clazzObject, \
"fromCpuInfo", "(" fromCpuInfo_args_signature ")" CPU_CLASS_SIG(clazz)); \
JNI_CHECK(env); \
return methodID; \
}
DECLARE_CPU_CLASS(Cache, "IIIIIIII")
DECLARE_CPU_CLASS(Cluster, "IIIII" CPU_CLASS_SIG(Package) "IIIIJ")
DECLARE_CPU_CLASS(Core, "III" CPU_CLASS_SIG(Cluster) CPU_CLASS_SIG(Package) "IIIIJ")
DECLARE_CPU_CLASS(Package, STRING_CLASS_SIG "IIIIII")
DECLARE_CPU_CLASS(Processor,
"I" CPU_CLASS_SIG(Core) CPU_CLASS_SIG(Cluster) CPU_CLASS_SIG(
Package) "II" CPU_CLASS_SIG(ProcessorCache))
DECLARE_CPU_CLASS(ProcessorCache,
CPU_CLASS_SIG(Cache) CPU_CLASS_SIG(Cache) CPU_CLASS_SIG(Cache) CPU_CLASS_SIG(
Cache) CPU_CLASS_SIG(Cache))
DECLARE_CPU_CLASS(Tlb, "IIJ")
DECLARE_CPU_CLASS(TraceCache, "II")
DECLARE_CPU_CLASS(Uarch, "I")
DECLARE_CPU_CLASS(UarchInfo, "IIIII")
DECLARE_CPU_CLASS(Vendor, "I")
#define DEFINE_CLASS_ATTRIBUTES(clazz_lowercase) \
jclass clazz_lowercase##Clazz; \
jmethodID clazz_lowercase##FromCpuInfoMethodID;
#define FILL_CLASS_ATTRIBUTES(env, clazz_lowercase, clazz) \
this->clazz_lowercase##Clazz = get##clazz##Class(env); \
this->clazz_lowercase##FromCpuInfoMethodID = \
get##clazz##FromCpuInfoMethodID(env, clazz_lowercase##Clazz);
struct CpuJni {
explicit CpuJni(JNIEnv *env) : mEnv(env) {
FILL_CLASS_ATTRIBUTES(env, cache, Cache)
FILL_CLASS_ATTRIBUTES(env, cluster, Cluster)
FILL_CLASS_ATTRIBUTES(env, core, Core)
FILL_CLASS_ATTRIBUTES(env, package, Package)
FILL_CLASS_ATTRIBUTES(env, processor, Processor)
FILL_CLASS_ATTRIBUTES(env, processorCache, ProcessorCache)
FILL_CLASS_ATTRIBUTES(env, tlb, Tlb)
FILL_CLASS_ATTRIBUTES(env, traceCache, TraceCache)
FILL_CLASS_ATTRIBUTES(env, uarch, Uarch)
FILL_CLASS_ATTRIBUTES(env, uarchInfo, UarchInfo)
FILL_CLASS_ATTRIBUTES(env, vendor, Vendor)
}
JNIEnv *mEnv;
DEFINE_CLASS_ATTRIBUTES(cache)
DEFINE_CLASS_ATTRIBUTES(cluster)
DEFINE_CLASS_ATTRIBUTES(core)
DEFINE_CLASS_ATTRIBUTES(package)
DEFINE_CLASS_ATTRIBUTES(processor)
DEFINE_CLASS_ATTRIBUTES(processorCache)
DEFINE_CLASS_ATTRIBUTES(tlb)
DEFINE_CLASS_ATTRIBUTES(traceCache)
DEFINE_CLASS_ATTRIBUTES(uarch)
DEFINE_CLASS_ATTRIBUTES(uarchInfo)
DEFINE_CLASS_ATTRIBUTES(vendor)
jobject cacheToJava(const struct cpuinfo_cache *cache);
jobject clusterToJava(const struct cpuinfo_cluster *cluster);
jobject coreToJava(const struct cpuinfo_core *core);
jobject packageToJava(const struct cpuinfo_package *package);
jobject processorToJava(const struct cpuinfo_processor *processor);
jobject processorCacheToJava(const struct cpuinfo_processor *processor);
jobject uarchInfoToJava(const struct cpuinfo_uarch_info *uarchInfo);
};
#undef DEFINE_CLASS_ATTRIBUTES
#undef FILL_CLASS_ATTRIBUTES

@ -0,0 +1 @@
Subproject commit 877328f188a3c7d1fa855871a278eb48d530c4c0

View File

@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <cstdlib>
#include <jni.h>
#define JNI_CHECK(env) \
do { \
if (env->ExceptionCheck()) { \
env->ExceptionDescribe(); \
abort(); \
} \
} while (0)
#define OBJECT_CLASS_SIG "Ljava/lang/Object;"
#define STRING_CLASS_SIG "Ljava/lang/String;"
static jmethodID getArrayListAddMethodID(JNIEnv *env, jobject object) {
auto arrayListClazz = env->GetObjectClass(object);
JNI_CHECK(env);
auto methodID = env->GetMethodID(arrayListClazz, "add", "(" OBJECT_CLASS_SIG ")Z");
JNI_CHECK(env);
return methodID;
}

View File

@ -1,33 +1,71 @@
package com.xyzshell.andinfo.libs
import android.os.Build
import android.util.Log
import com.xyzshell.andinfo.libs.cpu.models.Cache
import com.xyzshell.andinfo.libs.cpu.models.Cluster
import com.xyzshell.andinfo.libs.cpu.models.Core
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
class CpuInfo {
private val cores: Int = 0
val processors: List<Processor>
get() = CpuInfoUtils.getProcessors()
init {
val cores: List<Core>
get() = CpuInfoUtils.getCores()
val clusters: List<Cluster>
get() = CpuInfoUtils.getClusters()
val packages: List<Package>
get() = CpuInfoUtils.getPackages()
val uarchs: List<UarchInfo>
get() = CpuInfoUtils.getUarchs()
val l1iCaches: List<Cache>
get() = CpuInfoUtils.getL1iCaches()
val l1dCaches: List<Cache>
get() = CpuInfoUtils.getL1dCaches()
val l2Caches: List<Cache>
get() = CpuInfoUtils.getL2Caches()
val l3Caches: List<Cache>
get() = CpuInfoUtils.getL3Caches()
val l4Caches: List<Cache>
get() = CpuInfoUtils.getL4Caches()
}
fun text() : String {
val sb = StringBuilder()
ReadFile().also {
it.read(
"/proc/cpuinfo",
{ line:String, idx:Int ->
sb.appendLine(line)
false
}
)
}
val res = sb.toString()
Log.i("[AND INFO]", res)
return res
}
fun cores() : Int {
return Runtime.getRuntime().availableProcessors()
}
fun hardware(): String {
return Build.HARDWARE
return if (processors.isNotEmpty()) {
processors[0].cpuPackage?.name ?: "未知"
} else {
"未知"
}
}
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")
}
stringBuilder.append("核心数量: ${cores.size}\n")
cores.forEachIndexed { index, core ->
stringBuilder.append(" 核心 ${index}: ID=${core.coreId}, 频率=${core.frequency}Hz\n")
}
// 可以根据需要添加更多详细信息
return stringBuilder.toString()
}
companion object {
init {
System.loadLibrary("andinfo")
}
}
}

View File

@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `struct cpuinfo_cache`
*/
data class Cache(
/**
* Cache size in bytes
*/
val size: UInt,
/**
* Number of ways of associativity
*/
val associativity: UInt,
/**
* Number of sets
*/
val sets: UInt,
/**
* Number of partitions
*/
val partitions: UInt,
/**
* Line size in bytes
*/
val lineSize: UInt,
/**
* Binary characteristics of the cache (unified cache, inclusive cache,
* cache with complex indexing).
*
* @see `CPUINFO_CACHE_UNIFIED`, `CPUINFO_CACHE_INCLUSIVE`,
* `CPUINFO_CACHE_COMPLEX_INDEXING`
*/
val flags: UInt,
/**
* Index of the first logical processor that shares this cache
*/
val processorStart: UInt,
/**
* Number of logical processors that share this cache
*/
val processorCount: UInt,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
size: Int,
associativity: Int,
sets: Int,
partitions: Int,
lineSize: Int,
flags: Int,
processorStart: Int,
processorCount: Int,
) = Cache(
size.toUInt(),
associativity.toUInt(),
sets.toUInt(),
partitions.toUInt(),
lineSize.toUInt(),
flags.toUInt(),
processorStart.toUInt(),
processorCount.toUInt(),
)
}
}

View File

@ -0,0 +1,99 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `struct cpuinfo_cluster`
*/
data class Cluster(
/**
* Index of the first logical processor in the cluster
*/
val processorStart: UInt,
/**
* Number of logical processors in the cluster
*/
val processorCount: UInt,
/**
* Index of the first core in the cluster
*/
val coreStart: UInt,
/**
* Number of cores on the cluster
*/
val coreCount: UInt,
/**
* Cluster ID within a package
*/
val clusterId: UInt,
/**
* Physical package containing the cluster
*/
val cpuPackage: Package,
/**
* CPU microarchitecture vendor of the cores in the cluster
*/
val vendor: Vendor,
/**
* CPU microarchitecture of the cores in the cluster
*/
val uarch: Uarch,
/**
* x86 only
*
* Value of CPUID leaf 1 EAX register of the cores in the cluster
*/
val cpuid: UInt?,
/**
* ARM and ARM64 only
*
* Value of Main ID Register (MIDR) of the cores in the cluster
*/
val midr: Midr?,
/**
* Clock rate (non-Turbo) of the cores in the cluster, in Hz
*/
val frequency: ULong,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
processorStart: Int,
processorCount: Int,
coreStart: Int,
coreCount: Int,
clusterId: Int,
cpuPackage: Package,
vendor: Int,
uarch: Int,
cpuid: Int,
midr: Int,
frequency: Long,
) = Cluster(
processorStart.toUInt(),
processorCount.toUInt(),
coreStart.toUInt(),
coreCount.toUInt(),
clusterId.toUInt(),
cpuPackage,
Vendor.fromCpuInfo(vendor),
Uarch.fromCpuInfo(uarch),
cpuid.takeUnless { it == 0 }?.toUInt(),
midr.takeUnless { it == 0 }?.let { Midr.fromCpuInfo(it) },
frequency.toULong(),
)
}
}

View File

@ -0,0 +1,92 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `struct cpuinfo_core`
*/
data class Core(
/**
* Index of the first logical processor on this core.
*/
val processorStart: UInt,
/**
* Number of logical processors on this core
*/
val processorCount: UInt,
/**
* Core ID within a package
*/
val coreId: UInt,
/**
* Cluster containing this core
*/
val cluster: Cluster,
/**
* Physical package containing this core.
*/
val cpuPackage: Package,
/**
* Vendor of the CPU microarchitecture for this core
*/
val vendor: Vendor,
/**
* CPU microarchitecture for this core
*/
val uarch: Uarch,
/**
* x86 only
*
* Value of CPUID leaf 1 EAX register for this core
*/
val cpuid: UInt?,
/**
* ARM and ARM64 only
*
* Value of Main ID Register (MIDR) for this core
*/
val midr: Midr?,
/**
* Clock rate (non-Turbo) of the core, in Hz
*/
val frequency: ULong,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
processorStart: Int,
processorCount: Int,
coreId: Int,
cluster: Cluster,
cpuPackage: Package,
vendor: Int,
uarch: Int,
cpuId: Int,
midr: Int,
frequency: Long,
) = Core(
processorStart.toUInt(),
processorCount.toUInt(),
coreId.toUInt(),
cluster,
cpuPackage,
Vendor.fromCpuInfo(vendor),
Uarch.fromCpuInfo(uarch),
cpuId.takeUnless { it == 0 }?.toUInt(),
midr.takeUnless { it == 0 }?.let { Midr.fromCpuInfo(it) },
frequency.toULong(),
)
}
}

View File

@ -0,0 +1,104 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
import okio.FileSystem
import okio.Path
import okio.Path.Companion.toPath
data class LinuxCpu(
val id: Int,
) {
private val cpuBaseDir = CPUINFO_BASE_DIR / "cpu${id}"
init {
require(FILESYSTEM.exists(cpuBaseDir)) { "CPU $id doesn't exist" }
}
val isOnline: Boolean?
get() = getIntArray(ONLINE_CPUS)?.contains(id)
/**
* Current frequency, in Hz.
*/
val currentFrequencyHz: Long?
get() = getLong(cpuBaseDir / CPUINFO_CURRENT_FREQ)?.let { it * 1000 }
/**
* Minimum frequency, in Hz.
*/
val minimumFrequencyHz: Long?
get() = getLong(cpuBaseDir / CPUINFO_MINIMUM_FREQ)?.let { it * 1000 }
/**
* Maximum frequency, in Hz.
*/
val maximumFrequencyHz: Long?
get() = getLong(cpuBaseDir / CPUINFO_MAXIMUM_FREQ)?.let { it * 1000 }
/**
* Current frequency, in Hz.
*/
val scalingCurrentFrequencyHz: Long?
get() = getLong(cpuBaseDir / SCALING_CURRENT_FREQ)?.let { it * 1000 }
/**
* Minimum frequency, in Hz.
*/
val scalingMinimumFrequencyHz: Long?
get() = getLong(cpuBaseDir / SCALING_MINIMUM_FREQ)?.let { it * 1000 }
/**
* Maximum frequency, in Hz.
*/
val scalingMaximumFrequencyHz: Long?
get() = getLong(cpuBaseDir / SCALING_MAXIMUM_FREQ)?.let { it * 1000 }
// File utils
private fun getString(path: Path) = runCatching {
FILESYSTEM.read(path) {
readUtf8Line()
}
}.getOrNull()
private fun getLong(path: Path) = getString(path)?.toLongOrNull()
private fun getIntArray(path: Path) = getString(path)?.let {
mutableListOf<Int>().apply {
for (item in it.split(",")) {
val values = item.split('-')
assert(values.size <= 2)
if (values.size == 1) {
add(values.first().toInt())
} else if (values.size == 2) {
for (i in values[0].toInt()..values[1].toInt()) {
add(i)
}
}
}
}.toTypedArray()
}
companion object {
val CPUINFO_BASE_DIR = "/sys/devices/system/cpu".toPath()
private val FILESYSTEM = FileSystem.SYSTEM
private val ONLINE_CPUS = CPUINFO_BASE_DIR / "online"
private const val CPUINFO_CURRENT_FREQ = "cpufreq/cpuinfo_cur_freq"
private const val CPUINFO_MINIMUM_FREQ = "cpufreq/cpuinfo_min_freq"
private const val CPUINFO_MAXIMUM_FREQ = "cpufreq/cpuinfo_max_freq"
private const val SCALING_CURRENT_FREQ = "cpufreq/scaling_cur_freq"
private const val SCALING_MINIMUM_FREQ = "cpufreq/scaling_min_freq"
private const val SCALING_MAXIMUM_FREQ = "cpufreq/scaling_max_freq"
fun fromProcessor(processor: Processor) = LinuxCpu(processor.linuxId.toInt())
}
}

View File

@ -0,0 +1,68 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* ARM and ARM64 only
*
* B4.1.105 MIDR, Main ID Register, VMSA
*/
data class Midr(
val implementer: Implementer,
val variant: UByte,
val architecture: Architecture,
val primaryPartNumber: UInt,
val revision: UByte,
) {
enum class Implementer(val value: UByte) {
UNKNOWN(0x00U),
// From ARM spec
ARM(0x41U),
DEC(0x44U),
MOTOROLA(0x4DU),
QUALCOMM(0x51U),
MARVELL(0x56U),
INTEL(0x69U),
// Implementers not declared in the spec, taken from cpuinfo's arm/uarch.c
BROADCOM(0x42U),
CAVIUM(0x43U),
HUAWEI(0x48U),
NVIDIA(0x4EU),
APM(0x50U),
SAMSUNG(0x53U);
companion object {
fun fromValue(value: UByte) = entries.firstOrNull { it.value == value } ?: UNKNOWN
}
}
enum class Architecture(val value: UByte) {
ARMV4(0x1U),
ARMV4T(0x2U),
ARMV5(0x3U),
ARMV5T(0x4U),
ARMV5TE(0x5U),
ARMV5TEJ(0x6U),
ARMV6(0x7U),
DEFINED_BY_CPUID(0xFU);
companion object {
fun fromValue(value: UByte) = entries.first { it.value == value }
}
}
companion object {
fun fromCpuInfo(value: Int) = Midr(
Implementer.fromValue(value.shr(24).and(0xFF).toUByte()),
value.shr(20).and(0xF).toUByte(),
Architecture.fromValue(value.shr(16).and(0xF).toUByte()),
value.shr(4).and(0xFFF).toUInt(),
value.and(0xF).toUByte(),
)
}
}

View File

@ -0,0 +1,64 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
data class Package(
/**
* SoC or processor chip model name
*/
val name: String,
/**
* Index of the first logical processor on this physical package
*/
val processorStart: UInt,
/**
* Number of logical processors on this physical package
*/
val processorCount: UInt,
/**
* Index of the first core on this physical package
*/
val coreStart: UInt,
/**
* Number of cores on this physical package
*/
val coreCount: UInt,
/**
* Index of the first cluster of cores on this physical package
*/
val clusterStart: UInt,
/**
* Number of clusters of cores on this physical package
*/
val clusterCount: UInt,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
name: String,
processorStart: Int,
processorCount: Int,
coreStart: Int,
coreCount: Int,
clusterStart: Int,
clusterCount: Int,
) = Package(
name,
processorStart.toUInt(),
processorCount.toUInt(),
coreStart.toUInt(),
coreCount.toUInt(),
clusterStart.toUInt(),
clusterCount.toUInt(),
)
}
}

View File

@ -0,0 +1,78 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
import com.xyzshell.andinfo.libs.cpu.models.Cache
import com.xyzshell.andinfo.libs.cpu.models.Cluster
import com.xyzshell.andinfo.libs.cpu.models.Core
import com.xyzshell.andinfo.libs.cpu.models.Package
import com.xyzshell.andinfo.libs.cpu.models.ProcessorCache
/**
* `struct cpuinfo_processor`
*/
data class Processor(
/**
* SMT (hyperthread) ID within a core
*/
val smtId: UInt,
/**
* Core containing this logical processor
*/
val core: Core,
/**
* Cluster of cores containing this logical processor
*/
val cluster: Cluster,
/**
* Physical package containing this logical processor
*/
val cpuPackage: Package,
/**
* Linux-specific ID for the logical processor:
* - Linux kernel exposes information about this logical processor in
* /sys/devices/system/cpu/cpu<linux_id>/
* - Bit <linux_id> in the cpu_set_t identifies this logical processor
*/
val linuxId: UInt,
/**
* x86 only
*
* APIC ID (unique x86-specific ID of the logical processor)
*/
val apicId: UInt?,
/**
* @see ProcessorCache
*/
val cache: ProcessorCache,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
smtId: Int,
core: Core,
cluster: Cluster,
cpuPackage: Package,
linuxId: Int,
apicId: Int,
cache: ProcessorCache,
) = Processor(
smtId.toUInt(),
core,
cluster,
cpuPackage,
linuxId.toUInt(),
apicId.takeUnless { it == 0 }?.toUInt(),
cache,
)
}
}

View File

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
import com.xyzshell.andinfo.libs.cpu.models.Cache
/**
* `struct cpuinfo_processor { struct {...} cache }`
*/
data class ProcessorCache(
/**
* Level 1 instruction cache
*/
val l1i: Cache?,
/**
* Level 1 data cache
*/
val l1d: Cache?,
/**
* Level 2 unified or data cache
*/
val l2: Cache?,
/**
* Level 3 unified or data cache
*/
val l3: Cache?,
/**
* Level 4 unified or data cache
*/
val l4: Cache?,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
l1i: Cache?,
l1d: Cache?,
l2: Cache?,
l3: Cache?,
l4: Cache?,
) = ProcessorCache(
l1i,
l1d,
l2,
l3,
l4,
)
}
}

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `struct cpuinfo_tlb`
*/
data class Tlb(
val entries: UInt,
val associativity: UInt,
val pages: ULong,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
entries: Int,
associativity: Int,
pages: Long,
) = Tlb(
entries.toUInt(),
associativity.toUInt(),
pages.toULong(),
)
}
}

View File

@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `struct cpuinfo_trace_cache`
*/
data class TraceCache(
val uops: UInt,
val associativity: UInt,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
uops: Int,
associativity: Int,
) = TraceCache(
uops.toUInt(),
associativity.toUInt(),
)
}
}

View File

@ -0,0 +1,651 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `enum cpuinfo_uarch`
*
* Processor microarchitecture
*
* Processors with different microarchitectures often have different instruction
* performance characteristics, and may have dramatically different pipeline
* organization.
*/
enum class Uarch(
val value: UInt,
) {
/**
* Microarchitecture is unknown, or the library failed to get
* information about the microarchitecture from OS
*/
UNKNOWN(0U),
/**
* Pentium and Pentium MMX microarchitecture.
*/
P5(0x00100100U),
/**
* Intel Quark microarchitecture.
*/
QUARK(0x00100101U),
/**
* Pentium Pro, Pentium II, and Pentium III.
*/
P6(0x00100200U),
/**
* Pentium M.
*/
DOTHAN(0x00100201U),
/**
* Intel Core microarchitecture.
*/
YONAH(0x00100202U),
/**
* Intel Core 2 microarchitecture on 65 nm process.
*/
CONROE(0x00100203U),
/**
* Intel Core 2 microarchitecture on 45 nm process.
*/
PENRYN(0x00100204U),
/**
* Intel Nehalem and Westmere microarchitectures (Core i3/i5/i7 1st
* gen).
*/
NEHALEM(0x00100205U),
/**
* Intel Sandy Bridge microarchitecture (Core i3/i5/i7 2nd gen).
*/
SANDY_BRIDGE(0x00100206U),
/**
* Intel Ivy Bridge microarchitecture (Core i3/i5/i7 3rd gen).
*/
IVY_BRIDGE(0x00100207U),
/**
* Intel Haswell microarchitecture (Core i3/i5/i7 4th gen).
*/
HASWELL(0x00100208U),
/**
* Intel Broadwell microarchitecture.
*/
BROADWELL(0x00100209U),
/**
* Intel Sky Lake microarchitecture (14 nm, including
* Kaby/Coffee/Whiskey/Amber/Comet/Cascade/Cooper Lake).
*/
SKY_LAKE(0x0010020AU),
/**
* DEPRECATED (Intel Kaby Lake microarchitecture).
*/
//KABY_LAKE(0x0010020AU),
/**
* Intel Palm Cove microarchitecture (10 nm, Cannon Lake).
*/
PALM_COVE(0x0010020BU),
/**
* Intel Sunny Cove microarchitecture (10 nm, Ice Lake).
*/
SUNNY_COVE(0x0010020CU),
/**
* Pentium 4 with Willamette, Northwood, or Foster cores.
*/
WILLAMETTE(0x00100300U),
/**
* Pentium 4 with Prescott and later cores.
*/
PRESCOTT(0x00100301U),
/**
* Intel Atom on 45 nm process.
*/
BONNELL(0x00100400U),
/**
* Intel Atom on 32 nm process.
*/
SALTWELL(0x00100401U),
/**
* Intel Silvermont microarchitecture (22 nm out-of-order Atom).
*/
SILVERMOUNT(0x00100402U),
/**
* Intel Airmont microarchitecture (14 nm out-of-order Atom).
*/
AIRMONT(0x00100403U),
/**
* Intel Goldmont microarchitecture (Denverton, Apollo Lake).
*/
GOLDMONT(0x00100404U),
/**
* Intel Goldmont Plus microarchitecture (Gemini Lake).
*/
GOLDMONT_PLUS(0x00100405U),
/**
* Intel Knights Ferry HPC boards.
*/
KNIGHTS_FERRY(0x00100500U),
/**
* Intel Knights Corner HPC boards (aka Xeon Phi).
*/
KNIGHTS_CORNER(0x00100501U),
/**
* Intel Knights Landing microarchitecture (second-gen MIC).
*/
KNIGHTS_LANDING(0x00100502U),
/**
* Intel Knights Hill microarchitecture (third-gen MIC).
*/
KNIGHTS_HILL(0x00100503U),
/**
* Intel Knights Mill Xeon Phi.
*/
KNIGHTS_MILL(0x00100504U),
/**
* Intel/Marvell XScale series.
*/
XSCALE(0x00100600U),
/**
* AMD K5.
*/
K5(0x00200100U),
/**
* AMD K6 and alike.
*/
K6(0x00200101U),
/**
* AMD Athlon and Duron.
*/
K7(0x00200102U),
/**
* AMD Athlon 64, Opteron 64.
*/
K8(0x00200103U),
/**
* AMD Family 10h (Barcelona, Istambul, Magny-Cours).
*/
K10(0x00200104U),
/**
* AMD Bulldozer microarchitecture
* Zambezi FX-series CPUs, Zurich, Valencia and Interlagos Opteron CPUs.
*/
BULLDOZER(0x00200105U),
/**
* AMD Piledriver microarchitecture
* Vishera FX-series CPUs, Trinity and Richland APUs, Delhi, Seoul, Abu
* Dhabi Opteron CPUs.
*/
PILEDRIVER(0x00200106U),
/**
* AMD Steamroller microarchitecture (Kaveri APUs).
*/
STEAMROLLER(0x00200107U),
/**
* AMD Excavator microarchitecture (Carizzo APUs).
*/
EXCAVATOR(0x00200108U),
/**
* AMD Zen microarchitecture (12/14 nm Ryzen and EPYC CPUs).
*/
ZEN(0x00200109U),
/**
* AMD Zen 2 microarchitecture (7 nm Ryzen and EPYC CPUs).
*/
ZEN2(0x0020010AU),
/**
* AMD Zen 3 microarchitecture.
*/
ZEN3(0x0020010BU),
/**
* AMD Zen 4 microarchitecture.
*/
ZEN4(0x0020010CU),
/**
* NSC Geode and AMD Geode GX and LX.
*/
GEODE(0x00200200U),
/**
* AMD Bobcat mobile microarchitecture.
*/
BOBCAT(0x00200201U),
/**
* AMD Jaguar mobile microarchitecture.
*/
JAGUAR(0x00200202U),
/**
* AMD Puma mobile microarchitecture.
*/
PUMA(0x00200203U),
/**
* ARM7 series.
*/
ARM7(0x00300100U),
/**
* ARM9 series.
*/
ARM9(0x00300101U),
/**
* ARM 1136, ARM 1156, ARM 1176, or ARM 11MPCore.
*/
ARM11(0x00300102U),
/**
* ARM Cortex-A5.
*/
CORTEX_A5(0x00300205U),
/**
* ARM Cortex-A7.
*/
CORTEX_A7(0x00300207U),
/**
* ARM Cortex-A8.
*/
CORTEX_A8(0x00300208U),
/**
* ARM Cortex-A9.
*/
CORTEX_A9(0x00300209U),
/**
* ARM Cortex-A12.
*/
CORTEX_A12(0x00300212U),
/**
* ARM Cortex-A15.
*/
CORTEX_A15(0x00300215U),
/**
* ARM Cortex-A17.
*/
CORTEX_A17(0x00300217U),
/**
* ARM Cortex-A32.
*/
CORTEX_A32(0x00300332U),
/**
* ARM Cortex-A35.
*/
CORTEX_A35(0x00300335U),
/**
* ARM Cortex-A53.
*/
CORTEX_A53(0x00300353U),
/**
* ARM Cortex-A55 revision 0 (restricted dual-issue capabilities
* compared to revision 1+).
*/
CORTEX_A55R0(0x00300354U),
/**
* ARM Cortex-A55.
*/
CORTEX_A55(0x00300355U),
/**
* ARM Cortex-A57.
*/
CORTEX_A57(0x00300357U),
/**
* ARM Cortex-A65.
*/
CORTEX_A65(0x00300365U),
/**
* ARM Cortex-A72.
*/
CORTEX_A72(0x00300372U),
/**
* ARM Cortex-A73.
*/
CORTEX_A73(0x00300373U),
/**
* ARM Cortex-A75.
*/
CORTEX_A75(0x00300375U),
/**
* ARM Cortex-A76.
*/
CORTEX_A76(0x00300376U),
/**
* ARM Cortex-A77.
*/
CORTEX_A77(0x00300377U),
/**
* ARM Cortex-A78.
*/
CORTEX_A78(0x00300378U),
/**
* ARM Neoverse N1.
*/
NEOVERSE_N1(0x00300400U),
/**
* ARM Neoverse E1.
*/
NEOVERSE_E1(0x00300401U),
/**
* ARM Neoverse V1.
*/
NEOVERSE_V1(0x00300402U),
/**
* ARM Neoverse N2.
*/
NEOVERSE_N2(0x00300403U),
/**
* ARM Neoverse V2.
*/
NEOVERSE_V2(0x00300404U),
/**
* ARM Cortex-X1.
*/
CORTEX_X1(0x00300501U),
/**
* ARM Cortex-X2.
*/
CORTEX_X2(0x00300502U),
/**
* ARM Cortex-X3.
*/
CORTEX_X3(0x00300503U),
/**
* ARM Cortex-X4.
*/
CORTEX_X4(0x00300504U),
/**
* ARM Cortex-A510.
*/
CORTEX_A510(0x00300551U),
/**
* ARM Cortex-A520.
*/
CORTEX_A520(0x00300552U),
/**
* ARM Cortex-A710.
*/
CORTEX_A710(0x00300571U),
/**
* ARM Cortex-A715.
*/
CORTEX_A715(0x00300572U),
/**
* ARM Cortex-A720.
*/
CORTEX_A720(0x00300573U),
/**
* Qualcomm Scorpion.
*/
SCORPION(0x00400100U),
/**
* Qualcomm Krait.
*/
KRAIT(0x00400101U),
/**
* Qualcomm Kryo.
*/
KRYO(0x00400102U),
/**
* Qualcomm Falkor.
*/
FALKOR(0x00400103U),
/**
* Qualcomm Saphira.
*/
SAPHIRA(0x00400104U),
/**
* Nvidia Denver.
*/
DENVER(0x00500100U),
/**
* Nvidia Denver 2.
*/
DENVER2(0x00500101U),
/**
* Nvidia Carmel.
*/
CARMEL(0x00500102U),
/**
* Samsung Exynos M1 (Exynos 8890 big cores).
*/
EXYNOS_M1(0x00600100U),
/**
* Samsung Exynos M2 (Exynos 8895 big cores).
*/
EXYNOS_M2(0x00600101U),
/**
* Samsung Exynos M3 (Exynos 9810 big cores).
*/
EXYNOS_M3(0x00600102U),
/**
* Samsung Exynos M4 (Exynos 9820 big cores).
*/
EXYNOS_M4(0x00600103U),
/**
* Samsung Exynos M5 (Exynos 9830 big cores).
*/
EXYNOS_M5(0x00600104U),
/**
* Deprecated synonym for Cortex-A76
*/
//CORTEX_A76AE(0x00300376U),
/**
* Deprecated names for Exynos.
*/
//MONGOOSE_M1(0x00600100U),
//MONGOOSE_M2(0x00600101U),
//MEERKAT_M3(0x00600102U),
//MEERKAT_M4(0x00600103U),
/**
* Apple A6 and A6X processors.
*/
SWIFT(0x00700100U),
/**
* Apple A7 processor.
*/
CYCLONE(0x00700101U),
/**
* Apple A8 and A8X processor.
*/
TYPHOON(0x00700102U),
/**
* Apple A9 and A9X processor.
*/
TWISTER(0x00700103U),
/**
* Apple A10 and A10X processor.
*/
HURRICANE(0x00700104U),
/**
* Apple A11 processor (big cores).
*/
MONSOON(0x00700105U),
/**
* Apple A11 processor (little cores).
*/
MISTRAL(0x00700106U),
/**
* Apple A12 processor (big cores).
*/
VORTEX(0x00700107U),
/**
* Apple A12 processor (little cores).
*/
TEMPEST(0x00700108U),
/**
* Apple A13 processor (big cores).
*/
LIGHTNING(0x00700109U),
/**
* Apple A13 processor (little cores).
*/
THUNDER(0x0070010AU),
/**
* Apple A14 / M1 processor (big cores).
*/
FIRESTORM(0x0070010BU),
/**
* Apple A14 / M1 processor (little cores).
*/
ICESTORM(0x0070010CU),
/**
* Apple A15 / M2 processor (big cores).
*/
AVALANCHE(0x0070010DU),
/**
* Apple A15 / M2 processor (little cores).
*/
BLIZZARD(0x0070010EU),
/**
* Cavium ThunderX.
*/
THUNDERX(0x00800100U),
/**
* Cavium ThunderX2 (originally Broadcom Vulkan).
*/
THUNDERX2(0x00800200U),
/**
* Marvell PJ4.
*/
PJ4(0x00900100U),
/**
* Broadcom Brahma B15.
*/
BRAHMA_B15(0x00A00100U),
/**
* Broadcom Brahma B53.
*/
BRAHMA_B53(0x00A00101U),
/**
* Applied Micro X-Gene.
*/
XGENE(0x00B00100U),
/**
* Hygon Dhyana (a modification of AMD Zen for Chinese market).
*/
DHYANA(0x01000100U),
/**
* HiSilicon TaiShan v110 (Huawei Kunpeng 920 series processors).
*/
TAISHAN_V110(0x00C00100U);
companion object {
@JvmStatic
fun fromCpuInfo(value: Int) = value.toUInt().let {
entries.firstOrNull { uarch -> uarch.value == it } ?: UNKNOWN
}
}
}

View File

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
import com.xyzshell.andinfo.libs.cpu.models.Midr
import com.xyzshell.andinfo.libs.cpu.models.Uarch
/**
* `struct cpuinfo_uarch_info`
*/
data class UarchInfo(
/**
* Type of CPU microarchitecture
*/
val uarch: Uarch,
/**
* Value of CPUID leaf 1 EAX register for the microarchitecture
*/
val cpuid: UInt?,
/**
* Value of Main ID Register (MIDR) for the microarchitecture
*/
val midr: Midr?,
/**
* Number of logical processors with the microarchitecture
*/
val processorCount: UInt,
/**
* Number of cores with the microarchitecture
*/
val coreCount: UInt,
) {
companion object {
@JvmStatic
fun fromCpuInfo(
uarch: Int,
cpuId: Int,
midr: Int,
processorCount: Int,
coreCount: Int,
) = UarchInfo(
Uarch.fromCpuInfo(uarch),
cpuId.takeUnless { it == 0 }?.toUInt(),
midr.takeUnless { it == 0 }?.let { Midr.fromCpuInfo(it) },
processorCount.toUInt(),
coreCount.toUInt(),
)
}
}

View File

@ -0,0 +1,229 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.models
/**
* `enum cpuinfo_vendor`
*
* Vendor of processor core design
*/
enum class Vendor(
val value: UInt,
) {
/**
* Processor vendor is not known to the library, or the library failed
* to get vendor information from the OS.
*/
UNKNOWN(0U),
/**
* Intel Corporation. Vendor of x86, x86-64, IA64, and ARM processor
* microarchitectures.
*
* Sold its ARM design subsidiary in 2006. The last ARM processor design
* was released in 2004.
*/
INTEL(1U),
/**
* Advanced Micro Devices, Inc. Vendor of x86 and x86-64 processor
* microarchitectures.
*/
AMD(2U),
/**
* ARM Holdings plc. Vendor of ARM and ARM64 processor
* microarchitectures.
*/
ARM(3U),
/**
* Qualcomm Incorporated. Vendor of ARM and ARM64 processor
* microarchitectures.
*/
QUALCOMM(4U),
/**
* Apple Inc. Vendor of ARM and ARM64 processor microarchitectures.
*/
APPLE(5U),
/**
* Samsung Electronics Co., Ltd. Vendir if ARM64 processor
* microarchitectures.
*/
SAMSUNG(6U),
/**
* Nvidia Corporation. Vendor of ARM64-compatible processor
* microarchitectures.
*/
NVIDIA(7U),
/**
* MIPS Technologies, Inc. Vendor of MIPS processor microarchitectures.
*/
MIPS(8U),
/**
* International Business Machines Corporation. Vendor of PowerPC
* processor microarchitectures.
*/
IBM(9U),
/**
* Ingenic Semiconductor. Vendor of MIPS processor microarchitectures.
*/
INGENIC(10U),
/**
* VIA Technologies, Inc. Vendor of x86 and x86-64 processor
* microarchitectures.
*
* Processors are designed by Centaur Technology, a subsidiary of VIA
* Technologies.
*/
VIA(11U),
/**
* Cavium, Inc. Vendor of ARM64 processor microarchitectures.
*/
CAVIUM(12U),
/**
* Broadcom, Inc. Vendor of ARM processor microarchitectures.
*/
BROADCOM(13U),
/**
* Applied Micro Circuits Corporation (APM). Vendor of ARM64 processor
* microarchitectures.
*/
APM(14U),
/**
* Huawei Technologies Co., Ltd. Vendor of ARM64 processor
* microarchitectures.
*
* Processors are designed by HiSilicon, a subsidiary of Huawei.
*/
HUAWEI(15U),
/**
* Hygon (Chengdu Haiguang Integrated Circuit Design Co., Ltd), Vendor
* of x86-64 processor microarchitectures.
*
* Processors are variants of AMD cores.
*/
HYGON(16U),
/**
* SiFive, Inc. Vendor of RISC-V processor microarchitectures.
*/
SIFIVE(17U),
/**
* Texas Instruments Inc. Vendor of ARM processor microarchitectures.
*/
TEXAS_INSTRUMENTS(30U),
/**
* Marvell Technology Group Ltd. Vendor of ARM processor
* microarchitectures.
*/
MARVELL(31U),
/**
* RDC Semiconductor Co., Ltd. Vendor of x86 processor
* microarchitectures.
*/
RDC(32U),
/**
* DM&P Electronics Inc. Vendor of x86 processor microarchitectures.
*/
DMP(33U),
/**
* Motorola, Inc. Vendor of PowerPC and ARM processor
* microarchitectures.
*/
MOTOROLA(34U),
/**
* Transmeta Corporation. Vendor of x86 processor microarchitectures.
*
* Now defunct. The last processor design was released in 2004.
* Transmeta processors implemented VLIW ISA and used binary translation
* to execute x86 code.
*/
TRANSMETA(50U),
/**
* Cyrix Corporation. Vendor of x86 processor microarchitectures.
*
* Now defunct. The last processor design was released in 1996.
*/
CYRIX(51U),
/**
* Rise Technology. Vendor of x86 processor microarchitectures.
*
* Now defunct. The last processor design was released in 1999.
*/
RISE(52U),
/**
* National Semiconductor. Vendor of x86 processor microarchitectures.
*
* Sold its x86 design subsidiary in 1999. The last processor design was
* released in 1998.
*/
NSC(53U),
/**
* Silicon Integrated Systems. Vendor of x86 processor
* microarchitectures.
*
* Sold its x86 design subsidiary in 2001. The last processor design was
* released in 2001.
*/
SIS(54U),
/**
* NexGen. Vendor of x86 processor microarchitectures.
*
* Now defunct. The last processor design was released in 1994.
* NexGen designed the first x86 microarchitecture which decomposed x86
* instructions into simple microoperations.
*/
NEXGEN(55U),
/**
* United Microelectronics Corporation. Vendor of x86 processor
* microarchitectures.
*
* Ceased x86 in the early 1990s. The last processor design was released
* in 1991. Designed U5C and U5D processors. Both are 486 level.
*/
UMC(56U),
/**
* Digital Equipment Corporation. Vendor of ARM processor
* microarchitecture.
*
* Sold its ARM designs in 1997. The last processor design was released
* in 1997.
*/
DEC(57U);
companion object {
@JvmStatic
fun fromCpuInfo(value: Int) = value.toUInt().let {
entries.firstOrNull { vendor -> vendor.value == it } ?: UNKNOWN
}
}
}

View File

@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: Sebastiano Barezzi
* SPDX-License-Identifier: Apache-2.0
*/
package com.xyzshell.andinfo.libs.cpu.utils
import com.xyzshell.andinfo.libs.cpu.models.Cache
import com.xyzshell.andinfo.libs.cpu.models.Cluster
import com.xyzshell.andinfo.libs.cpu.models.Core
import com.xyzshell.andinfo.libs.cpu.models.Package
import com.xyzshell.andinfo.libs.cpu.models.Processor
import com.xyzshell.andinfo.libs.cpu.models.UarchInfo
object CpuInfoUtils {
fun getProcessors() = ArrayList<Processor>().apply {
getProcessors(this)
}.toList()
fun getCores() = ArrayList<Core>().apply {
getCores(this)
}.toList()
fun getClusters() = ArrayList<Cluster>().apply {
getClusters(this)
}.toList()
fun getPackages() = ArrayList<Package>().apply {
getPackages(this)
}.toList()
fun getUarchs() = ArrayList<UarchInfo>().apply {
getUarchs(this)
}.toList()
fun getL1iCaches() = ArrayList<Cache>().apply {
getL1iCaches(this)
}.toList()
fun getL1dCaches() = ArrayList<Cache>().apply {
getL1dCaches(this)
}.toList()
fun getL2Caches() = ArrayList<Cache>().apply {
getL2Caches(this)
}.toList()
fun getL3Caches() = ArrayList<Cache>().apply {
getL3Caches(this)
}.toList()
fun getL4Caches() = ArrayList<Cache>().apply {
getL4Caches(this)
}.toList()
private external fun getProcessors(processors: ArrayList<Processor>)
private external fun getCores(cores: ArrayList<Core>)
private external fun getClusters(clusters: ArrayList<Cluster>)
private external fun getPackages(packages: ArrayList<Package>)
private external fun getUarchs(uarchs: ArrayList<UarchInfo>)
private external fun getL1iCaches(l1iCaches: ArrayList<Cache>)
private external fun getL1dCaches(l1dCaches: ArrayList<Cache>)
private external fun getL2Caches(l2Caches: ArrayList<Cache>)
private external fun getL3Caches(l3Caches: ArrayList<Cache>)
private external fun getL4Caches(l4Caches: ArrayList<Cache>)
}

View File

@ -20,6 +20,12 @@ android {
vectorDrawables {
useSupportLibrary = true
}
externalNativeBuild {
cmake {
cppFlags += "-std=c++17"
}
}
}
buildTypes {

View File

@ -62,7 +62,7 @@ fun MainView(name: String, modifier: Modifier = Modifier) {
}
Card(modifier= Modifier.fillMaxWidth().padding(10.dp)){
Text("硬件:${AndInfo.instance.cpu.hardware()}")
Text("核心数:${AndInfo.instance.cpu.cores()}")
Text("核心数:${AndInfo.instance.cpu.cores.size}")
Button(onClick = {showDialog.value = true}) { Text("cpu") }
}
}