diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1a58464 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "myphoneinfo/andinfo/src/main/cpp/cpuinfo"] + path = myphoneinfo/andinfo/src/main/cpp/cpuinfo + url = https://github.com/pytorch/cpuinfo diff --git a/android-info/myphoneinfo/andinfo/src/main/cpp/cpuinfo b/android-info/myphoneinfo/andinfo/src/main/cpp/cpuinfo new file mode 160000 index 0000000..877328f --- /dev/null +++ b/android-info/myphoneinfo/andinfo/src/main/cpp/cpuinfo @@ -0,0 +1 @@ +Subproject commit 877328f188a3c7d1fa855871a278eb48d530c4c0 diff --git a/ksp-annotations/bin/main/com/xyzshell/ksp_annotations/AutoBuilder.kt b/ksp-annotations/bin/main/com/xyzshell/ksp_annotations/AutoBuilder.kt new file mode 100644 index 0000000..fee85a0 --- /dev/null +++ b/ksp-annotations/bin/main/com/xyzshell/ksp_annotations/AutoBuilder.kt @@ -0,0 +1,5 @@ +package com.xyzshell.ksp_annotations + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.SOURCE) +annotation class AutoBuilder \ No newline at end of file diff --git a/ksp-processor/bin/main/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/ksp-processor/bin/main/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider new file mode 100644 index 0000000..0944169 --- /dev/null +++ b/ksp-processor/bin/main/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -0,0 +1 @@ +com.xyzshell.ksp_processor.AutoBuilderProcessorProvider \ No newline at end of file diff --git a/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessor.kt b/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessor.kt new file mode 100644 index 0000000..9a4cd82 --- /dev/null +++ b/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessor.kt @@ -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 { + 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!!)) + } +} \ No newline at end of file diff --git a/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessorProvider.kt b/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessorProvider.kt new file mode 100644 index 0000000..bda4c68 --- /dev/null +++ b/ksp-processor/bin/main/com/xyzshell/ksp_processor/AutoBuilderProcessorProvider.kt @@ -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 + ) + } +} \ No newline at end of file diff --git a/myphoneinfo/andinfo/build.gradle.kts b/myphoneinfo/andinfo/build.gradle.kts index 5a81721..7e03f13 100644 --- a/myphoneinfo/andinfo/build.gradle.kts +++ b/myphoneinfo/andinfo/build.gradle.kts @@ -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 @@ -46,4 +54,4 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) -} \ No newline at end of file +} diff --git a/myphoneinfo/andinfo/src/main/cpp/CMakeLists.txt b/myphoneinfo/andinfo/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..d28ba81 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/CMakeLists.txt @@ -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) diff --git a/myphoneinfo/andinfo/src/main/cpp/CpuInfoUtils.cpp b/myphoneinfo/andinfo/src/main/cpp/CpuInfoUtils.cpp new file mode 100644 index 0000000..a5c887a --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/CpuInfoUtils.cpp @@ -0,0 +1,51 @@ +/* + * SPDX-FileCopyrightText: Sebastiano Barezzi + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "CpuUtils" + +#include +#include +#include +#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) diff --git a/myphoneinfo/andinfo/src/main/cpp/CpuJni.cpp b/myphoneinfo/andinfo/src/main/cpp/CpuJni.cpp new file mode 100644 index 0000000..61e41f9 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/CpuJni.cpp @@ -0,0 +1,181 @@ +/* + * SPDX-FileCopyrightText: Sebastiano Barezzi + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CpuJni.h" + +#include +#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; +} diff --git a/myphoneinfo/andinfo/src/main/cpp/CpuJni.h b/myphoneinfo/andinfo/src/main/cpp/CpuJni.h new file mode 100644 index 0000000..75f69f3 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/CpuJni.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: Sebastiano Barezzi + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#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 diff --git a/myphoneinfo/andinfo/src/main/cpp/cpuinfo b/myphoneinfo/andinfo/src/main/cpp/cpuinfo new file mode 160000 index 0000000..877328f --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/cpuinfo @@ -0,0 +1 @@ +Subproject commit 877328f188a3c7d1fa855871a278eb48d530c4c0 diff --git a/myphoneinfo/andinfo/src/main/cpp/jni_utils.h b/myphoneinfo/andinfo/src/main/cpp/jni_utils.h new file mode 100644 index 0000000..e27cfce --- /dev/null +++ b/myphoneinfo/andinfo/src/main/cpp/jni_utils.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: Sebastiano Barezzi + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#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; +} 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 efd2d95..d2a767b 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,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 + get() = CpuInfoUtils.getProcessors() - init { + val cores: List + get() = CpuInfoUtils.getCores() - } - fun text() : String { - val sb = StringBuilder() - ReadFile().also { - it.read( - "/proc/cpuinfo", - { line:String, idx:Int -> - sb.appendLine(line) - false - } - ) + val clusters: List + get() = CpuInfoUtils.getClusters() + + val packages: List + get() = CpuInfoUtils.getPackages() + + val uarchs: List + get() = CpuInfoUtils.getUarchs() + + val l1iCaches: List + get() = CpuInfoUtils.getL1iCaches() + + val l1dCaches: List + get() = CpuInfoUtils.getL1dCaches() + + val l2Caches: List + get() = CpuInfoUtils.getL2Caches() + + val l3Caches: List + get() = CpuInfoUtils.getL3Caches() + + val l4Caches: List + get() = CpuInfoUtils.getL4Caches() + + fun hardware(): String { + return if (processors.isNotEmpty()) { + processors[0].cpuPackage?.name ?: "未知" + } else { + "未知" } - val res = sb.toString() - Log.i("[AND INFO]", res) - return res } - fun cores() : Int { - return Runtime.getRuntime().availableProcessors() + + 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() } - fun hardware() : String { - return Build.HARDWARE + + companion object { + init { + System.loadLibrary("andinfo") + } } -} \ No newline at end of file +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cache.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cache.kt new file mode 100644 index 0000000..75785ca --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cache.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cluster.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cluster.kt new file mode 100644 index 0000000..3760ee5 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Cluster.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Core.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Core.kt new file mode 100644 index 0000000..6e1fe9a --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Core.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/LinuxCpu.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/LinuxCpu.kt new file mode 100644 index 0000000..f302d02 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/LinuxCpu.kt @@ -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().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()) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Midr.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Midr.kt new file mode 100644 index 0000000..030712a --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Midr.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Package.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Package.kt new file mode 100644 index 0000000..4d3e45a --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Package.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Processor.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Processor.kt new file mode 100644 index 0000000..754c42e --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Processor.kt @@ -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/ + * - Bit 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, + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/ProcessorCache.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/ProcessorCache.kt new file mode 100644 index 0000000..3ff358d --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/ProcessorCache.kt @@ -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, + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Tlb.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Tlb.kt new file mode 100644 index 0000000..162df42 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Tlb.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/TraceCache.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/TraceCache.kt new file mode 100644 index 0000000..0d1ff72 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/TraceCache.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Uarch.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Uarch.kt new file mode 100644 index 0000000..5ac0e1f --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Uarch.kt @@ -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 + } + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/UarchInfo.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/UarchInfo.kt new file mode 100644 index 0000000..1b79eb3 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/UarchInfo.kt @@ -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(), + ) + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Vendor.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Vendor.kt new file mode 100644 index 0000000..df1a251 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/models/Vendor.kt @@ -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 + } + } +} diff --git a/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/utils/CpuInfoUtils.kt b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/utils/CpuInfoUtils.kt new file mode 100644 index 0000000..402dfe7 --- /dev/null +++ b/myphoneinfo/andinfo/src/main/java/com/xyzshell/andinfo/libs/cpu/utils/CpuInfoUtils.kt @@ -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().apply { + getProcessors(this) + }.toList() + + fun getCores() = ArrayList().apply { + getCores(this) + }.toList() + + fun getClusters() = ArrayList().apply { + getClusters(this) + }.toList() + + fun getPackages() = ArrayList().apply { + getPackages(this) + }.toList() + + fun getUarchs() = ArrayList().apply { + getUarchs(this) + }.toList() + + fun getL1iCaches() = ArrayList().apply { + getL1iCaches(this) + }.toList() + + fun getL1dCaches() = ArrayList().apply { + getL1dCaches(this) + }.toList() + + fun getL2Caches() = ArrayList().apply { + getL2Caches(this) + }.toList() + + fun getL3Caches() = ArrayList().apply { + getL3Caches(this) + }.toList() + + fun getL4Caches() = ArrayList().apply { + getL4Caches(this) + }.toList() + + private external fun getProcessors(processors: ArrayList) + private external fun getCores(cores: ArrayList) + private external fun getClusters(clusters: ArrayList) + private external fun getPackages(packages: ArrayList) + private external fun getUarchs(uarchs: ArrayList) + private external fun getL1iCaches(l1iCaches: ArrayList) + private external fun getL1dCaches(l1dCaches: ArrayList) + private external fun getL2Caches(l2Caches: ArrayList) + private external fun getL3Caches(l3Caches: ArrayList) + private external fun getL4Caches(l4Caches: ArrayList) +} diff --git a/myphoneinfo/build.gradle.kts b/myphoneinfo/build.gradle.kts index bf15744..8a7d0c2 100644 --- a/myphoneinfo/build.gradle.kts +++ b/myphoneinfo/build.gradle.kts @@ -20,6 +20,12 @@ android { vectorDrawables { useSupportLibrary = true } + + externalNativeBuild { + cmake { + cppFlags += "-std=c++17" + } + } } buildTypes { @@ -70,4 +76,4 @@ dependencies { androidTestImplementation(libs.androidx.ui.test.junit4) debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.test.manifest) -} \ No newline at end of file +} diff --git a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/MainActivity.kt b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/MainActivity.kt index 9fc283d..62ebf11 100644 --- a/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/MainActivity.kt +++ b/myphoneinfo/src/main/java/com/xyzshell/myphoneinfo/MainActivity.kt @@ -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") } } } @@ -93,4 +93,4 @@ fun GreetingPreview() { MyAndriodInfoTheme { MainView("Android") } -} \ No newline at end of file +}