Last active
August 29, 2015 14:26
-
-
Save Cheesebaron/33d5fca0efd0eb3a237a to your computer and use it in GitHub Desktop.
Year classification for Android. Based on Facebook's device-year-class: https://github.com/facebook/device-year-class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Linq; | |
using Android.OS; | |
using Android.Util; | |
namespace DeviceYearClass | |
{ | |
public class DeviceInfo | |
{ | |
public const int DeviceInfoUnknown = -1; | |
private static readonly object LockCpu = new object(); | |
private static readonly object LockFreq = new object(); | |
private static readonly object LockMem = new object(); | |
public static int NumberOfCpuCores | |
{ | |
get | |
{ | |
lock (LockCpu) | |
{ | |
if (Build.VERSION.SdkInt <= BuildVersionCodes.GingerbreadMr1) | |
return 1; | |
var directories = Directory.GetDirectories("/sys/devices/system/cpu/"); | |
try | |
{ | |
var cores = | |
directories.Where(file => file.StartsWith("/sys/devices/system/cpu/cpu")) | |
.Count( | |
file => file.Substring(27).All(char.IsNumber)); | |
return cores; | |
} | |
catch (Exception ex) | |
{ | |
Log.Debug("DeviceInfo", "GetNumberOfCpuCores failed with exception: {0}", ex); | |
return DeviceInfoUnknown; | |
} | |
} | |
} | |
} | |
public static int GetCpuMaxFreqKHz | |
{ | |
get | |
{ | |
lock (LockFreq) | |
{ | |
var maxFreq = DeviceInfoUnknown; | |
try | |
{ | |
for (var i = 0; i < NumberOfCpuCores; i++) | |
{ | |
var fileName = "/sys/devices/system/cpu/cpu" + i + | |
"/cpufreq/cpuinfo_max_freq"; | |
if (!File.Exists(fileName)) continue; | |
var lines = File.ReadAllLines(fileName); | |
maxFreq = lines.Select(int.Parse).Concat(new[] {maxFreq}).Max(); | |
} | |
} | |
catch (FormatException) | |
{ | |
// fall through to /proc/cpuinfo | |
} | |
try | |
{ | |
if (maxFreq == DeviceInfoUnknown) | |
{ | |
var lines = File.ReadAllLines("/proc/cpuinfo"); | |
foreach ( | |
var freq in | |
lines.Where(line => line.ToLower().StartsWith("cpu mhz")).Select( | |
line => | |
new string(line.Where(c => c >= '0' && c <= '9').ToArray())) | |
.Select( | |
int.Parse).Where(freq => freq > maxFreq)) | |
{ | |
maxFreq = (freq*1000); | |
} | |
} | |
} | |
catch (FormatException) | |
{ | |
maxFreq = DeviceInfoUnknown; | |
} | |
return maxFreq; | |
} | |
} | |
} | |
public static long TotalMemory | |
{ | |
get | |
{ | |
lock (LockMem) | |
{ | |
long totalMem = DeviceInfoUnknown; | |
try | |
{ | |
var lines = File.ReadAllLines("/proc/meminfo"); | |
foreach (var mem in from line in lines | |
where line.ToLower().StartsWith("memtotal") | |
select new string(line.Where(c => c >= '0' && c <= '9').ToArray()) | |
into memStr | |
select long.Parse(memStr)) | |
{ | |
totalMem = mem*1024L; | |
} | |
} | |
catch (FormatException) {} | |
return totalMem; | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | |
android:orientation="vertical" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent" | |
android:padding="16dp"> | |
<TextView | |
android:id="@+id/numberOfCpusLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Number of CPUs" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/numberOfCpus" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/cpuMaxFreqLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="CPU Max Frequency" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/cpuMaxFreq" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/totalMemLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Total Memory" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/totalMem" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/numCoresYearLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Number of Cores Year" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/numCoresYear" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/clockSpeedYearLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Clock Speed Year" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/clockSpeedYear" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/memoryYearLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Memory Year" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/memoryYear" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
<TextView | |
android:id="@+id/overallYearLabel" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="Overall Year" | |
android:textStyle="bold" /> | |
<TextView | |
android:id="@+id/overallYear" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:text="N/A" /> | |
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.App; | |
using Android.OS; | |
using Android.Widget; | |
using DeviceYearClass; | |
namespace Sample | |
{ | |
[Activity(Label = "Sample", MainLauncher = true, Icon = "@drawable/icon")] | |
public class MainActivity : Activity | |
{ | |
protected override void OnCreate(Bundle bundle) | |
{ | |
base.OnCreate(bundle); | |
// Set our view from the "main" layout resource | |
SetContentView(Resource.Layout.Main); | |
var cpuCores = FindViewById<TextView>(Resource.Id.numberOfCpus); | |
cpuCores.Text = "" + DeviceInfo.NumberOfCpuCores; | |
var maxFreq = FindViewById<TextView>(Resource.Id.cpuMaxFreq); | |
maxFreq.Text = string.Format("{0} kHz", DeviceInfo.GetCpuMaxFreqKHz); | |
var totalMem = FindViewById<TextView>(Resource.Id.totalMem); | |
totalMem.Text = string.Format("{0} Bytes", DeviceInfo.TotalMemory); | |
var cpuCoresYear = FindViewById<TextView>(Resource.Id.numCoresYear); | |
cpuCoresYear.Text = string.Format("{0}", YearClass.NumberOfCoresYear); | |
var clockSpeedYear = FindViewById<TextView>(Resource.Id.clockSpeedYear); | |
clockSpeedYear.Text = string.Format("{0}", YearClass.ClockSpeedYear); | |
var memoryYear = FindViewById<TextView>(Resource.Id.memoryYear); | |
memoryYear.Text = string.Format("{0}", YearClass.RamYear); | |
var overallYear = FindViewById<TextView>(Resource.Id.overallYear); | |
overallYear.Text = string.Format("{0}", YearClass.Year); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using Android.Util; | |
namespace DeviceYearClass | |
{ | |
public class YearClass | |
{ | |
private const long Mb = 1024*1024; | |
private const int MhzInKhz = 1000; | |
public const int ClassUnknown = -1; | |
public const int Class2008 = 2008; | |
public const int Class2009 = 2009; | |
public const int Class2010 = 2010; | |
public const int Class2011 = 2011; | |
public const int Class2012 = 2012; | |
public const int Class2013 = 2013; | |
public const int Class2014 = 2014; | |
private static int _yearCategory = ClassUnknown; | |
public static int Year | |
{ | |
get | |
{ | |
if (_yearCategory == ClassUnknown) | |
{ | |
var componentYears = new List<int>(); | |
ConditionallyAdd(componentYears, NumberOfCoresYear); | |
ConditionallyAdd(componentYears, ClockSpeedYear); | |
ConditionallyAdd(componentYears, RamYear); | |
if (!componentYears.Any()) | |
return ClassUnknown; | |
componentYears.Sort(); | |
if ((componentYears.Count & 0x01) == 1) // Odd number; pluck the median. | |
{ | |
_yearCategory = componentYears[componentYears.Count / 2]; | |
Log.Debug("YearClass", "Odd number: {0}", _yearCategory); | |
return _yearCategory; | |
} | |
// Even number, Average the two "center" values. | |
var baseIndex = componentYears.Count/2 - 1; | |
_yearCategory = componentYears[baseIndex] + | |
(componentYears[baseIndex + 1] - componentYears[baseIndex])/2; | |
Log.Debug("YearClass", "Even number: {0}", _yearCategory); | |
} | |
return _yearCategory; | |
} | |
} | |
private static void ConditionallyAdd(ICollection<int> list, int value) | |
{ | |
if (value != ClassUnknown) | |
list.Add(value); | |
} | |
public static int NumberOfCoresYear | |
{ | |
get | |
{ | |
var cores = DeviceInfo.NumberOfCpuCores; | |
if (cores < 1) return ClassUnknown; | |
if (cores == 1) return Class2008; | |
if (cores <= 3) return Class2011; | |
return Class2012; | |
} | |
} | |
public static int ClockSpeedYear | |
{ | |
get | |
{ | |
var clockSpeedKHz = DeviceInfo.GetCpuMaxFreqKHz; | |
if (clockSpeedKHz == DeviceInfo.DeviceInfoUnknown) return ClassUnknown; | |
if (clockSpeedKHz <= 528 * MhzInKhz) return Class2008; | |
if (clockSpeedKHz <= 620 * MhzInKhz) return Class2009; | |
if (clockSpeedKHz <= 1020 * MhzInKhz) return Class2010; | |
if (clockSpeedKHz <= 1220* MhzInKhz) return Class2011; | |
if (clockSpeedKHz <= 1520* MhzInKhz) return Class2012; | |
if (clockSpeedKHz <= 2020 * MhzInKhz) return Class2013; | |
return Class2014; | |
} | |
} | |
public static int RamYear | |
{ | |
get | |
{ | |
var totalRam = DeviceInfo.TotalMemory; | |
if (totalRam <= 0) return ClassUnknown; | |
if (totalRam <= 192 * Mb) return Class2008; | |
if (totalRam <= 290 * Mb) return Class2009; | |
if (totalRam <= 512 * Mb) return Class2010; | |
if (totalRam <= 1024 * Mb) return Class2011; | |
if (totalRam <= 1536 * Mb) return Class2012; | |
if (totalRam <= 2048 * Mb) return Class2013; | |
return Class2014; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment