diff --git a/Source/Android/res/values-ja/strings.xml b/Source/Android/res/values-ja/strings.xml index 9d2dfe37eb..cb206ae8a2 100644 --- a/Source/Android/res/values-ja/strings.xml +++ b/Source/Android/res/values-ja/strings.xml @@ -17,6 +17,17 @@ GLES 3 OpenGL + + CPU ABI 1 + CPU ABI 2 + CPU情報 + CPUタイプ + CPUの命令セットと機能 + CPUコア + CPUの実装 + ハードウェア + 不明 (%1$d)。 我々はそれを文書化することができますので、この番号を報告してください。 + 現在のディレクトリ: %1$s 親ディレクトリ diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index b60a56e73c..0fae5bab6c 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -18,6 +18,17 @@ GLES 3 OpenGL + + CPU ABI 1 + CPU ABI 2 + CPU Info + CPU Type + CPU Features + Number of Cores + CPU Implementer + Hardware + Unknown (%1$d). Please report this number so it can be documented! + Current Dir: %1$s Parent Directory diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java index ab2bda3e0a..d544d7e6c2 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/AboutActivity.java @@ -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 { - private final Context ctx; private final int id; private final List 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 { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java new file mode 100644 index 0000000000..ddf1e0f816 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/about/CPUInfoFragment.java @@ -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 items = new ArrayList(); + + 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; + } +} diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java b/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java new file mode 100644 index 0000000000..43e6b66da4 --- /dev/null +++ b/Source/Android/src/org/dolphinemu/dolphinemu/utils/CPUHelper.java @@ -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); + } + } +}