[Android] Implement CPU info retrieval within the about menu.
ARM only at the moment. Could potentially support x86 and MIPS if necessary. Capable of parsing the manufacturer codes and part IDs of some (but not all part numbers). If anyone knows of part numbers that aren't in the list, please report them.
This commit is contained in:
parent
521aa631dc
commit
b9e7749fe6
|
@ -17,6 +17,17 @@
|
|||
<string name="gles_three">GLES 3</string>
|
||||
<string name="desktop_gl">OpenGL</string>
|
||||
|
||||
<!-- About Menu - CPU Info -->
|
||||
<string name="cpu_abi_one">CPU ABI 1</string>
|
||||
<string name="cpu_abi_two">CPU ABI 2</string>
|
||||
<string name="cpu_info">CPU情報</string>
|
||||
<string name="cpu_type">CPUタイプ</string>
|
||||
<string name="cpu_features">CPUの命令セットと機能</string>
|
||||
<string name="num_cores">CPUコア</string>
|
||||
<string name="cpu_implementer">CPUの実装</string>
|
||||
<string name="cpu_hardware">ハードウェア</string>
|
||||
<string name="unknown_part_num">不明 (%1$d)。 我々はそれを文書化することができますので、この番号を報告してください。 </string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">現在のディレクトリ: %1$s</string>
|
||||
<string name="parent_directory">親ディレクトリ</string>
|
||||
|
|
|
@ -18,6 +18,17 @@
|
|||
<string name="gles_three">GLES 3</string>
|
||||
<string name="desktop_gl">OpenGL</string>
|
||||
|
||||
<!-- About Menu - CPU Info -->
|
||||
<string name="cpu_abi_one">CPU ABI 1</string>
|
||||
<string name="cpu_abi_two">CPU ABI 2</string>
|
||||
<string name="cpu_info">CPU Info</string>
|
||||
<string name="cpu_type">CPU Type</string>
|
||||
<string name="cpu_features">CPU Features</string>
|
||||
<string name="num_cores">Number of Cores</string>
|
||||
<string name="cpu_implementer">CPU Implementer</string>
|
||||
<string name="cpu_hardware">Hardware</string>
|
||||
<string name="unknown_part_num">Unknown (%1$d). Please report this number so it can be documented!</string>
|
||||
|
||||
<!-- Folder Browser -->
|
||||
<string name="current_dir">Current Dir: %1$s</string>
|
||||
<string name="parent_directory">Parent Directory</string>
|
||||
|
|
|
@ -57,7 +57,6 @@ public final class AboutActivity extends Activity implements TabListener
|
|||
// The adapter that manages the displaying of items in multiple About fragments.
|
||||
public static final class InfoFragmentAdapter extends ArrayAdapter<AboutFragmentItem>
|
||||
{
|
||||
private final Context ctx;
|
||||
private final int id;
|
||||
private final List<AboutFragmentItem> items;
|
||||
|
||||
|
@ -65,7 +64,6 @@ public final class AboutActivity extends Activity implements TabListener
|
|||
{
|
||||
super(ctx, id, items);
|
||||
|
||||
this.ctx = ctx;
|
||||
this.id = id;
|
||||
this.items = items;
|
||||
}
|
||||
|
@ -81,7 +79,7 @@ public final class AboutActivity extends Activity implements TabListener
|
|||
{
|
||||
if (convertView == null)
|
||||
{
|
||||
LayoutInflater vi = LayoutInflater.from(ctx);
|
||||
LayoutInflater vi = LayoutInflater.from(getContext());
|
||||
convertView = vi.inflate(id, parent, false);
|
||||
}
|
||||
|
||||
|
@ -184,7 +182,7 @@ public final class AboutActivity extends Activity implements TabListener
|
|||
}
|
||||
else if (position == 1)
|
||||
{
|
||||
return new Fragment(); // CPU
|
||||
return new CPUInfoFragment(); // CPU
|
||||
}
|
||||
else if (position == 2) // GLES 2
|
||||
{
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package org.dolphinemu.dolphinemu.about;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.about.AboutActivity.AboutFragmentItem;
|
||||
import org.dolphinemu.dolphinemu.utils.CPUHelper;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* {@link ListFragment class that is responsible
|
||||
* for displaying information related to the CPU.
|
||||
*/
|
||||
public final class CPUInfoFragment extends ListFragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false);
|
||||
List<AboutActivity.AboutFragmentItem> items = new ArrayList<AboutActivity.AboutFragmentItem>();
|
||||
|
||||
CPUHelper cpuHelper = new CPUHelper(getActivity());
|
||||
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_info), cpuHelper.getProcessorInfo()));
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_type), cpuHelper.getProcessorType()));
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_abi_one), Build.CPU_ABI));
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_abi_two), Build.CPU_ABI2));
|
||||
items.add(new AboutFragmentItem(getString(R.string.num_cores), Integer.toString(cpuHelper.getNumCores())));
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_features), cpuHelper.getFeatures()));
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_hardware), Build.HARDWARE));
|
||||
if (CPUHelper.isARM())
|
||||
items.add(new AboutFragmentItem(getString(R.string.cpu_implementer), cpuHelper.getImplementer()));
|
||||
|
||||
AboutActivity.InfoFragmentAdapter adapter = new AboutActivity.InfoFragmentAdapter(getActivity(), R.layout.about_layout, items);
|
||||
rootView.setAdapter(adapter);
|
||||
|
||||
return rootView;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,400 @@
|
|||
package org.dolphinemu.dolphinemu.utils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Utility class for retrieving information
|
||||
* from a device's CPU.
|
||||
*/
|
||||
public final class CPUHelper
|
||||
{
|
||||
private int revision;
|
||||
private int architecture;
|
||||
private int variant;
|
||||
private int numCores;
|
||||
private String implementerID = "N/A";
|
||||
private String part = "N/A";
|
||||
private String hardware = "N/A";
|
||||
private String processorInfo = "N/A";
|
||||
private String features = "N/A";
|
||||
|
||||
private final Context ctx;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param ctx The current {@link Context}.
|
||||
*/
|
||||
public CPUHelper(Context ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Should do other architectures as well (x86 and MIPS).
|
||||
// Can do differentiating between platforms by using
|
||||
// android.os.Build.CPU_ABI.
|
||||
//
|
||||
// CPU_ABI.contains("armeabi") == get ARM info.
|
||||
// CPU_ABI.contains("x86") == get x86 info.
|
||||
// CPU_ABI.contains("mips") == get MIPS info.
|
||||
//
|
||||
// However additional testing should be done across devices,
|
||||
// I highly doubt /proc/cpuinfo retains the same formatting
|
||||
// on different architectures.
|
||||
//
|
||||
// If push comes to shove, we can simply spit out the cpuinfo
|
||||
// contents. I would like to avoid this if possible, however.
|
||||
|
||||
if (Build.CPU_ABI.contains("arm"))
|
||||
{
|
||||
getARMInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e("CPUHelper", "CPU architecture not supported yet.");
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Log.e("CPUHelper", ioe.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the revision number of the CPU.
|
||||
*
|
||||
* @return the revision number of the CPU.
|
||||
*/
|
||||
public int getRevision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the architecture number of the CPU.
|
||||
*
|
||||
* @return the architecture number of the CPU.
|
||||
*/
|
||||
public int getArchitecture()
|
||||
{
|
||||
return architecture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CPU variant number.
|
||||
*
|
||||
* @return the CPU variant number.
|
||||
*/
|
||||
public int getVariant()
|
||||
{
|
||||
return variant;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total number of cores in the CPU.
|
||||
*
|
||||
* @return the total number of cores in the CPU.
|
||||
*/
|
||||
public int getNumCores()
|
||||
{
|
||||
return numCores;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the implementer of the CPU.
|
||||
*
|
||||
* @return the name of the implementer of the CPU.
|
||||
*/
|
||||
public String getImplementer()
|
||||
{
|
||||
return implementerID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specific processor type of the CPU.
|
||||
*
|
||||
* @return the specific processor type.
|
||||
*/
|
||||
public String getProcessorType()
|
||||
{
|
||||
return part;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal name of the hardware.
|
||||
*
|
||||
* @return the internal name of the hardware.
|
||||
*/
|
||||
public String getHardware()
|
||||
{
|
||||
return hardware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the processor info string.
|
||||
*
|
||||
* @return the processor info string.
|
||||
*/
|
||||
public String getProcessorInfo()
|
||||
{
|
||||
return processorInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the features supported by the CPU.
|
||||
*
|
||||
* @return the features supported by the CPU.
|
||||
*/
|
||||
public String getFeatures()
|
||||
{
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this CPU is using the ARM architecture.
|
||||
*
|
||||
* @return true if this CPU uses the ARM architecture; false otherwise.
|
||||
*/
|
||||
public static boolean isARM()
|
||||
{
|
||||
return Build.CPU_ABI.contains("arm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this CPU is using the x86 architecture.
|
||||
*
|
||||
* @return true if this CPU uses the x86 architecture; false otherwise.
|
||||
*/
|
||||
public static boolean isX86()
|
||||
{
|
||||
return Build.CPU_ABI.contains("x86");
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this CPU is using the MIPS architecture.
|
||||
*
|
||||
* @return true if this CPU uses the MIPS architecture; false otherwise.
|
||||
*/
|
||||
public static boolean isMIPS()
|
||||
{
|
||||
return Build.CPU_ABI.contains("mips");
|
||||
}
|
||||
|
||||
// Retrieves information for ARM CPUs.
|
||||
private void getARMInfo() throws IOException
|
||||
{
|
||||
File info = new File("/proc/cpuinfo");
|
||||
if (info.exists())
|
||||
{
|
||||
BufferedReader br = new BufferedReader(new FileReader(info));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
if (line.contains("Processor\t:"))
|
||||
{
|
||||
this.processorInfo = parseLine(line);
|
||||
}
|
||||
else if (line.contains("Hardware\t:"))
|
||||
{
|
||||
this.hardware = parseLine(line);
|
||||
}
|
||||
else if (line.contains("Features\t:"))
|
||||
{
|
||||
this.features = parseLine(line);
|
||||
}
|
||||
else if (line.contains("CPU implementer\t:"))
|
||||
{
|
||||
this.implementerID = parseArmID(Integer.decode(parseLine(line)));
|
||||
}
|
||||
// Intentional lack of "\t:" sometimes the tab isn't present.
|
||||
else if (line.contains("CPU architecture"))
|
||||
{
|
||||
this.architecture = Integer.decode(parseLine(line));
|
||||
}
|
||||
else if (line.contains("CPU part\t:"))
|
||||
{
|
||||
this.part = parseArmPartNumber(Integer.decode(parseLine(line)));
|
||||
}
|
||||
else if (line.contains("CPU revision\t:"))
|
||||
{
|
||||
this.revision = Integer.decode(parseLine(line));
|
||||
}
|
||||
else if (line.contains("CPU variant\t:"))
|
||||
{
|
||||
this.variant = Integer.decode(parseLine(line));
|
||||
}
|
||||
else if (line.contains("processor\t:")) // Lower case indicates a specific core number
|
||||
{
|
||||
this.numCores++;
|
||||
}
|
||||
}
|
||||
|
||||
br.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Basic function for parsing cpuinfo format strings.
|
||||
// cpuinfo format strings consist of [label:info] parts.
|
||||
// We only want to retrieve the info portion so we split
|
||||
// them using ':' as a delimeter.
|
||||
private String parseLine(String line)
|
||||
{
|
||||
String[] temp = line.split(":");
|
||||
if (temp.length != 2)
|
||||
return "N/A";
|
||||
|
||||
return temp[1].trim();
|
||||
}
|
||||
|
||||
// Parses an ARM CPU ID.
|
||||
private String parseArmID(int id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case 0x41:
|
||||
return "ARM Limited";
|
||||
|
||||
case 0x44:
|
||||
return "Digital Equipment Corporation";
|
||||
|
||||
case 0x4D:
|
||||
return "Freescale Semiconductor Inc.";
|
||||
|
||||
case 0x51:
|
||||
return "Qualcomm Inc.";
|
||||
|
||||
case 0x56:
|
||||
return "Marvell Semiconductor Inc.";
|
||||
|
||||
case 0x69:
|
||||
return "Intel Corporation";
|
||||
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
// Parses the ARM CPU Part number.
|
||||
private String parseArmPartNumber(int partNum)
|
||||
{
|
||||
switch (partNum)
|
||||
{
|
||||
// Qualcomm part numbers.
|
||||
case 0x00F:
|
||||
return "Qualcomm Scorpion";
|
||||
|
||||
case 0x02D:
|
||||
return "Qualcomm Dual Scorpion";
|
||||
|
||||
case 0x04D:
|
||||
return "Qualcomm Dual Krait";
|
||||
|
||||
case 0x06F:
|
||||
return "Qualcomm Quad Krait";
|
||||
|
||||
// Marvell Semiconductor part numbers
|
||||
case 0x131:
|
||||
return "Marvell Feroceon";
|
||||
|
||||
case 0x581:
|
||||
return "Marvell PJ4/PJ4b";
|
||||
|
||||
case 0x584:
|
||||
return "Marvell Dual PJ4/PJ4b";
|
||||
|
||||
// Official ARM part numbers.
|
||||
case 0x920:
|
||||
return "ARM920";
|
||||
|
||||
case 0x922:
|
||||
return "ARM922";
|
||||
|
||||
case 0x926:
|
||||
return "ARM926";
|
||||
|
||||
case 0x940:
|
||||
return "ARM940";
|
||||
|
||||
case 0x946:
|
||||
return "ARM946";
|
||||
|
||||
case 0x966:
|
||||
return "ARM966";
|
||||
|
||||
case 0x968:
|
||||
return "ARM968";
|
||||
|
||||
case 0xB02:
|
||||
return "ARM11 MPCore";
|
||||
|
||||
case 0xB36:
|
||||
return "ARM1136";
|
||||
|
||||
case 0xB56:
|
||||
return "ARM1156";
|
||||
|
||||
case 0xB76:
|
||||
return "ARM1176";
|
||||
|
||||
case 0xC05:
|
||||
return "ARM Cortex A5";
|
||||
|
||||
case 0xC07:
|
||||
return "ARM Cortex-A7 MPCore";
|
||||
|
||||
case 0xC08:
|
||||
return "ARM Cortex A8";
|
||||
|
||||
case 0xC09:
|
||||
return "ARM Cortex A9";
|
||||
|
||||
case 0xC0C:
|
||||
return "ARM Cortex A12";
|
||||
|
||||
case 0xC0F:
|
||||
return "ARM Cortex A15";
|
||||
|
||||
case 0xC14:
|
||||
return "ARM Cortex R4";
|
||||
|
||||
case 0xC15:
|
||||
return "ARM Cortex R5";
|
||||
|
||||
case 0xC20:
|
||||
return "ARM Cortex M0";
|
||||
|
||||
case 0xC21:
|
||||
return "ARM Cortex M1";
|
||||
|
||||
case 0xC23:
|
||||
return "ARM Cortex M3";
|
||||
|
||||
case 0xC24:
|
||||
return "ARM Cortex M4";
|
||||
|
||||
case 0xC60:
|
||||
return "ARM Cortex M0+";
|
||||
|
||||
case 0xD03:
|
||||
return "ARM Cortex A53";
|
||||
|
||||
case 0xD07:
|
||||
return "ARM Cortex A57 MPCore";
|
||||
|
||||
|
||||
default: // Unknown/Not yet added to list.
|
||||
return String.format(ctx.getString(R.string.unknown_part_num), partNum);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue