package tv.danmaku.android.util;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeMap;
import java.util.TreeSet;
import android.support.v4.util.LongSparseArray;
import android.text.TextUtils;
/* -
* Qualcomm CPU part list:
*
* 0x00f
* MSM8255, glacier, HTC
* MSM8255, zeus, Sony Ericsson Xperia PLAY
* MSM8255, mogami, Sony Ericsson Xperia neo V
*
* 0x02d
* QCT_MSM8X60_SURF
* MSM8260, pyramid, HTC Sensation
* MSM8X60, mione
* MSM8260, doubleshot, HTC DoubleShot
*/
public class CpuInfo {
// #define ARM_CPUID_ARM1026 0x4106a262
// #define ARM_CPUID_ARM926 0x41069265
// #define ARM_CPUID_ARM946 0x41059461
// #define ARM_CPUID_TI915T 0x54029152
// #define ARM_CPUID_TI925T 0x54029252
// #define ARM_CPUID_SA1100 0x4401A11B
// #define ARM_CPUID_SA1110 0x6901B119
// #define ARM_CPUID_PXA250 0x69052100
// #define ARM_CPUID_PXA255 0x69052d00
// #define ARM_CPUID_PXA260 0x69052903
// #define ARM_CPUID_PXA261 0x69052d05
// #define ARM_CPUID_PXA262 0x69052d06
// #define ARM_CPUID_PXA270 0x69054110
// #define ARM_CPUID_PXA270_A0 0x69054110
// #define ARM_CPUID_PXA270_A1 0x69054111
// #define ARM_CPUID_PXA270_B0 0x69054112
// #define ARM_CPUID_PXA270_B1 0x69054113
// #define ARM_CPUID_PXA270_C0 0x69054114
// #define ARM_CPUID_PXA270_C5 0x69054117
// #define ARM_CPUID_ARM1136 0x4117b363
// #define ARM_CPUID_ARM1136_R2 0x4107b362
// #define ARM_CPUID_ARM1176 0x410fb767
// #define ARM_CPUID_ARM11MPCORE 0x410fb022
// #define ARM_CPUID_CORTEXA8 0x410fc080
// #define ARM_CPUID_CORTEXA8_R2 0x412fc083
// #define ARM_CPUID_CORTEXA9 0x410fc090
// #define ARM_CPUID_CORTEXM3 0x410fc231
// -#define ARM_CPUID_ARM1026 0x4106a262
// -#define ARM_CPUID_ARM926 0x41069265
// -#define ARM_CPUID_ARM946 0x41059461
// #define ARM_CPUID_TI915T 0x54029152
// #define ARM_CPUID_TI925T 0x54029252
// -#define ARM_CPUID_SA1100 0x4401A11B
// -#define ARM_CPUID_SA1110 0x6901B119
// -#define ARM_CPUID_PXA250 0x69052100
// -#define ARM_CPUID_PXA255 0x69052d00
// -#define ARM_CPUID_PXA260 0x69052903
// -#define ARM_CPUID_PXA261 0x69052d05
// -#define ARM_CPUID_PXA262 0x69052d06
// -#define ARM_CPUID_PXA270 0x69054110
// -#define ARM_CPUID_PXA270_A0 0x69054110
// -#define ARM_CPUID_PXA270_A1 0x69054111
// -#define ARM_CPUID_PXA270_B0 0x69054112
// -#define ARM_CPUID_PXA270_B1 0x69054113
// -#define ARM_CPUID_PXA270_C0 0x69054114
// -#define ARM_CPUID_PXA270_C5 0x69054117
// -#define ARM_CPUID_ARM1136 0x4117b363
// -#define ARM_CPUID_ARM1136_R2 0x4107b362
// -#define ARM_CPUID_ARM1176 0x410fb767
// -#define ARM_CPUID_ARM11MPCORE 0x410fb022
// -#define ARM_CPUID_CORTEXA8 0x410fc080
// -#define ARM_CPUID_CORTEXA9 0x410fc090
// -#define ARM_CPUID_CORTEXA15 0x412fc0f1
// -#define ARM_CPUID_CORTEXM3 0x410fc231
// -#define ARM_CPUID_ANY 0xffffffff
// CPU implementer
public static final int CPU_IMPL_ARM_LIMITED = 0x41; // 'A'
public static final int CPU_IMPL_DEC = 0x44; // 'D'
public static final int CPU_IMPL_MOTO = 0x4d; // 'M'
public static final int CPU_IMPL_QUALCOMM = 0x51; // 'Q'
public static final int CPU_IMPL_MARVELL = 0x56; // 'V'
public static final int CPU_IMPL_INTEL = 0x69; // 'i'
public static LongSparseArray<String> sCpuImplementerMap = new LongSparseArray<String>() {
{
put(CPU_IMPL_ARM_LIMITED, "ARM");
put(CPU_IMPL_DEC, "DEC");
put(CPU_IMPL_MOTO, "Moto");
put(CPU_IMPL_QUALCOMM, "Qualcomm");
put(CPU_IMPL_MARVELL, "Marvell");
put(CPU_IMPL_INTEL, "Intel");
}
};
// CPU part:
// ARMv6 xScale
public static final int CPU_PART_PXA910 = 0x840;
// ARMv6
public static final int CPU_PART_ARM926 = 0x926;
public static final int CPU_PART_ARM946 = 0x946;
public static final int CPU_PART_ARM1026 = 0xa26;
public static final int CPU_PART_ARM1136 = 0xb36;
public static final int CPU_PART_ARM1156 = 0xb56;
public static final int CPU_PART_ARM1176 = 0xb76;
public static final int CPU_PART_ARM11_MPCORE = 0xb02;
// ARMv7 Cortex-A
public static final int CPU_PART_CORTEX_A5 = 0xc05;
public static final int CPU_PART_CORTEX_A7 = 0xc07;
public static final int CPU_PART_CORTEX_A8 = 0xc08;
public static final int CPU_PART_CORTEX_A9 = 0xc09;
public static final int CPU_PART_CORTEX_A15 = 0xc0f;
public static final int CPU_PART_CORTEX_R4 = 0xc14;
public static final int CPU_PART_CORTEX_R5 = 0xc15;
public static final int CPU_PART_CORTEX_M3 = 0xc23;
// Qualcomm CPU part: (Maybe)
public static final int CPU_PART_QUALCOMM_S1_S2 = 0x00f;
public static final int CPU_PART_QUALCOMM_S3 = 0x02d;
public static final int CPU_PART_QUALCOMM_S4 = 0x04d;
// CPU architecture
public static final String CPU_ARCHITECTURE_7 = "7";
public static final String CPU_ARCHITECTURE_6TEJ = "6TEJ";
public static final String CPU_ARCHITECTURE_5TE = "5TE";
private boolean mHasARMv7;
private boolean mHasARMv6;
private boolean mHasARMv5;
private String mProcess;
private static CpuInfo sInstance;
public static LongSparseArray<String> sCpuPartMap = new LongSparseArray<String>() {
{
put(CPU_PART_PXA910, "PXA910");
put(CPU_PART_ARM1136, "ARM1136");
put(CPU_PART_CORTEX_A5, "Cortex-A5");
put(CPU_PART_CORTEX_A7, "Cortex-A7");
put(CPU_PART_CORTEX_A8, "Cortex-A8");
put(CPU_PART_CORTEX_A9, "Cortex-A9");
put(CPU_PART_CORTEX_A15, "Cortex-A15");
put(CPU_PART_ARM926, "ARM926");
put(CPU_PART_ARM946, "ARM946");
put(CPU_PART_ARM1026, "ARM1026");
put(CPU_PART_ARM1156, "ARM1156");
put(CPU_PART_ARM1176, "ARM1176");
put(CPU_PART_ARM11_MPCORE, "ARM11-MPCore");
put(CPU_PART_QUALCOMM_S1_S2, "Qualcomm S1/S2");
put(CPU_PART_QUALCOMM_S3, "Qualcomm S3");
put(CPU_PART_QUALCOMM_S4, "Qualcomm S4");
}
};
public String mRawCpuInfo = new String();
public TreeMap<String, String> mRawInfoMap = new TreeMap<String, String>();
public int mCpuPart;
public int mCpuImplementer;
public TreeSet<String> mFeatureSet = new TreeSet<String>();
public static String getRawCpuInfo() {
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("/proc/cpuinfo");
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
String text = StreamHelper.readStreamLineByLine(inputStream);
StreamHelper.closeStream(inputStream);
return text;
}
public String getParsedCpuInfo() {
StringBuilder parsedCpuInfo = new StringBuilder();
parsedCpuInfo.append("CPU implementer : ");
parsedCpuInfo.append(getCpuImplementerText());
parsedCpuInfo.append("\n");
parsedCpuInfo.append("CPU part : ");
parsedCpuInfo.append(getCpuPartText());
parsedCpuInfo.append("\n");
parsedCpuInfo.append("NEON : ");
parsedCpuInfo.append(supportNeon() ? "Yes" : "No");
parsedCpuInfo.append("\n");
return parsedCpuInfo.toString();
}
public static CpuInfo parseCpuInfo() {
if (sInstance != null)
return sInstance;
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream("/proc/cpuinfo");
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader buffReader = new BufferedReader(reader);
try {
inputStream = new FileInputStream("/proc/cpuinfo");
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
CpuInfo cpuInfo = new CpuInfo();
try {
StringBuilder infoBuilder = new StringBuilder();
String line;
while ((line = buffReader.readLine()) != null) {
cpuInfo.addCpuInfo(line);
infoBuilder.append(line);
infoBuilder.append('\n');
}
cpuInfo.mRawCpuInfo = infoBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
cpuInfo = null;
} finally {
try {
buffReader.close();
reader.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
sInstance = cpuInfo;
return cpuInfo;
}
public void addCpuInfo(String line) {
String[] lineInfo = line.split(":", 2);
if (lineInfo.length >= 2) {
addCpuInfo(lineInfo[0], lineInfo[1]);
}
}
public void addCpuInfo(String key, String value) {
key = key.toLowerCase().trim();
value = value.trim();
mRawInfoMap.put(key, value);
if (key.equals("processor") && TextUtils.isEmpty(mProcess)) {
mProcess = value;
value = value.toLowerCase();
if (value.startsWith("armv7")) {
mHasARMv7 = true;
} else if (value.startsWith("armv6")) {
mHasARMv6 = true;
} else if (value.startsWith("arm926ej-s")) {
mHasARMv5 = true;
} else if (value.startsWith("marvell 88sv331x")) {
mHasARMv5 = true;
}
} else if (key.equals("cpu part")) {
value = value.toLowerCase();
int pos = value.toLowerCase().indexOf('x');
if (-1 == pos) {
mCpuPart = Integer.parseInt(value);
} else {
mCpuPart = Integer.parseInt(value.substring(pos + 1), 16);
}
} else if (key.equals("cpu implementer")) {
value = value.toLowerCase();
int pos = value.toLowerCase().indexOf('x');
if (-1 == pos) {
mCpuImplementer = Integer.parseInt(value);
} else {
mCpuImplementer = Integer
.parseInt(value.substring(pos + 1), 16);
}
} else if (key.equals("features")) {
value = value.toLowerCase();
String[] features = value.split(" ");
for (String featureItem : features) {
mFeatureSet.add(featureItem.trim());
}
}
}
public String getCpuImplementerText() {
String cpuPartText = sCpuImplementerMap.get(mCpuImplementer);
if (TextUtils.isEmpty(cpuPartText)) {
return String.format("Unknown:0x%x", mCpuImplementer);
}
return cpuPartText;
}
public String getCpuPartText() {
String cpuPartText = sCpuPartMap.get(mCpuPart);
if (TextUtils.isEmpty(cpuPartText)) {
return String.format("Unknown:0x%x", mCpuPart);
}
return cpuPartText;
}
public boolean isKnownCpuId() {
return sCpuPartMap.get(mCpuPart) != null;
}
private String optCpuRawInfoItem(String key) {
if (TextUtils.isEmpty(key))
return "";
String value = mRawInfoMap.get(key);
if (TextUtils.isEmpty(value))
return "";
return value;
}
public String getCpuIdString() {
String hardware = optCpuRawInfoItem("hardware").trim()
.replace(' ', '_');
String implementer = optCpuRawInfoItem("cpu implementer");
String architecture = optCpuRawInfoItem("cpu architecture");
String variant = optCpuRawInfoItem("cpu variant");
String part = optCpuRawInfoItem("cpu part");
String revision = optCpuRawInfoItem("cpu revision");
String featureList = optCpuRawInfoItem("features").replace(' ', '_');
StringBuilder sb = new StringBuilder();
sb.append(hardware);
sb.append('.');
sb.append(implementer);
sb.append('.');
sb.append(architecture);
sb.append('.');
sb.append(variant);
sb.append('.');
sb.append(part);
sb.append('.');
sb.append(revision);
sb.append('.');
sb.append(featureList);
sb.append('.');
sb.append(mProcess == null ? "" : mProcess);
return sb.toString();
}
public boolean isCortexA5() {
return CPU_PART_CORTEX_A5 == mCpuPart;
}
public boolean isCortexA7() {
return CPU_PART_CORTEX_A7 == mCpuPart;
}
public boolean isCortexA8() {
return CPU_PART_CORTEX_A8 == mCpuPart;
}
public boolean isCortexA9() {
return CPU_PART_CORTEX_A9 == mCpuPart;
}
public boolean isCortexA15() {
return CPU_PART_CORTEX_A15 == mCpuPart;
}
public boolean isSnapdragon_S1_or_S2() {
if (mCpuImplementer != CPU_IMPL_QUALCOMM)
return false;
return CPU_PART_QUALCOMM_S1_S2 == mCpuPart;
}
public boolean isSnapdragon_S3() {
if (mCpuImplementer != CPU_IMPL_QUALCOMM)
return false;
return CPU_PART_QUALCOMM_S3 == mCpuPart;
}
public boolean isSnapdragon_S4() {
if (mCpuImplementer != CPU_IMPL_QUALCOMM)
return false;
return CPU_PART_QUALCOMM_S4 == mCpuPart;
}
public String getCpuArchitecture() {
return mRawInfoMap.get("cpu architecture");
}
public boolean hasArmv7() {
return mHasARMv7;
}
public boolean hasArmv6() {
return mHasARMv6;
}
public boolean hasArmv5() {
return mHasARMv5;
}
public boolean supportNeon() {
return mFeatureSet.contains("neon");
}
public boolean supportVfpv3D16() {
if (mFeatureSet.contains("vfpv3-d16"))
return true;
if (mFeatureSet.contains("vfpv3d16"))
return true;
return false;
}
public boolean supportVfp() {
return mFeatureSet.contains("vfp");
}
}