Skip to content

Commit

Permalink
CPU frequencies and governor control via CMParts
Browse files Browse the repository at this point in the history
CPUSettings will be restored on boot when "Set on boot" is checked.

Change-Id: I83805cee8537c5d34a0284fc6e93af0003751bee
  • Loading branch information
NameLessJedi authored and hyperb1iss committed Jan 30, 2011
1 parent d2ec209 commit c5f4243
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 4 deletions.
23 changes: 20 additions & 3 deletions AndroidManifest.xml
Expand Up @@ -6,15 +6,21 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.HARDWARE_TEST" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<application android:label="@string/app_name"
android:icon="@drawable/cm_icon">
<activity android:name=".activities.MainActivity"
android:label="@string/app_name">
<receiver android:name=".intents.CPUReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
<activity android:name=".activities.MainActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Expand Down Expand Up @@ -92,12 +98,22 @@
<category android:name="com.cyanogenmod.cmparts.SHORTCUT" />
</intent-filter>
</activity>
<activity android:name=".activities.CPUActivity" android:label="@string/cpu_settings_title">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity android:name=".activities.HapticTweaksActivity"
android:label="@string/haptic_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity android:name=".activities.HapticTweaksActivity" android:label="@string/haptic_title">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<activity android:name=".activities.HapticAdjust"
android:label="@string/title_haptic_menu">
<intent-filter>
Expand Down Expand Up @@ -203,5 +219,6 @@

<service android:enabled="true" android:name=".services.RenderFXService" />
<service android:enabled="true" android:name=".services.BatteryService" />
<service android:enabled="true" android:name=".services.CPUService" />
</application>
</manifest>
10 changes: 10 additions & 0 deletions res/values/strings.xml
Expand Up @@ -489,4 +489,14 @@
<string name="phone_goggles_confirmation_none">None</string>
<string name="phone_goggles_confirmation_prompt">Prompt</string>
<string name="phone_goggles_confirmation_maths">Math problems</string>

<!-- CPU Settings strings -->
<string name="cpu_settings_title">CPU settings</string>
<string name="cpu_title">CPU settings</string>
<string name="cpu_summary">Governor and clock settings</string>
<string name="cpu_governors_list">List of available governors\nCurrently selected: %S</string>
<string name="cpu_min_freq">Minimum CPU frequency\nCurrently: %s</string>
<string name="cpu_max_freq">Maximum CPU frequency\nCurrently: %s</string>
<string name="cpu_set_on_boot">Set on boot</string>
<string name="cpu_set_on_boot_summary">Restore CPU settings on boot</string>
</resources>
16 changes: 16 additions & 0 deletions res/xml/cpu_settings.xml
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<ListPreference android:key="pref_cpu_gov" android:dialogTitle="Available governors"
android:title="Available governors" />

<ListPreference android:key="pref_freq_min" android:dialogTitle="Min CPU frequency"
android:title="Min CPU frequency" android:summary="Minimum CPU frequency" />

<ListPreference android:key="pref_freq_max" android:dialogTitle="Max CPU frequency"
android:title="Max CPU frequency" android:summary="Maximum CPU frequency" />

<CheckBoxPreference android:key="pref_set_on_boot"
android:title="@string/cpu_set_on_boot" android:summary="@string/cpu_set_on_boot_summary"/>

</PreferenceScreen>
8 changes: 7 additions & 1 deletion res/xml/performance_settings.xml
Expand Up @@ -5,6 +5,12 @@
<PreferenceCategory android:key="general_category"
android:title="@string/general_title">

<PreferenceScreen android:key="cpu_settings" android:title="@string/cpu_title" android:summary="@string/cpu_summary">
<intent android:action="android.intent.action.MAIN"
android:targetPackage="com.cyanogenmod.cmparts"
android:targetClass="com.cyanogenmod.cmparts.activities.CPUActivity" />
</PreferenceScreen>

<ListPreference android:key="pref_compcache_size"
android:dialogTitle="@string/pref_compcache_title"
android:title="@string/pref_compcache_title"
Expand Down Expand Up @@ -34,4 +40,4 @@

</PreferenceCategory>

</PreferenceScreen>
</PreferenceScreen>
181 changes: 181 additions & 0 deletions src/com/cyanogenmod/cmparts/activities/CPUActivity.java
@@ -0,0 +1,181 @@
package com.cyanogenmod.cmparts.activities;

import com.cyanogenmod.cmparts.R;

import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.Process;

//
// CPU Related Settings
//
public class CPUActivity extends PreferenceActivity implements Preference.OnPreferenceChangeListener {

public static final String GOV_PREF = "pref_cpu_gov";
public static final String GOVERNORS_LIST_FILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors";
public static final String GOVERNOR = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor";

public static final String MIN_FREQ_PREF = "pref_freq_min";
public static final String MAX_FREQ_PREF = "pref_freq_max";
public static final String FREQ_LIST_FILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies";
public static final String FREQ_MAX_FILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq";
public static final String FREQ_MIN_FILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq";
public static final String SOB_PREF = "pref_set_on_boot";
private static final String TAG = "CPUSettings";
private String GOV_FMT;
private String MIN_FMT;
private String MAX_FMT;

private ListPreference govPref;
private ListPreference minFreqPref;
private ListPreference maxFreqPref;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

GOV_FMT = getString(R.string.cpu_governors_list);
MIN_FMT = getString(R.string.cpu_min_freq);
MAX_FMT = getString(R.string.cpu_max_freq);

String[] Governors = readOneLine(GOVERNORS_LIST_FILE).split(" ");
String[] FreqValues = readOneLine(FREQ_LIST_FILE).split(" ");
String[] Freqs;
String temp;

Freqs = new String[FreqValues.length];
for(int i=0; i <Freqs.length; i++) {
Freqs[i] = MHerzed(FreqValues[i]);
}

setTitle(R.string.cpu_title);
addPreferencesFromResource(R.xml.cpu_settings);

PreferenceScreen PrefScreen = getPreferenceScreen();

temp = readOneLine(GOVERNOR);

govPref = (ListPreference) PrefScreen.findPreference(GOV_PREF);
govPref.setEntryValues(Governors);
govPref.setEntries(Governors);
govPref.setValue(temp);
govPref.setSummary(String.format(GOV_FMT, temp));
govPref.setOnPreferenceChangeListener(this);

temp = readOneLine(FREQ_MIN_FILE);

minFreqPref = (ListPreference) PrefScreen.findPreference(MIN_FREQ_PREF);
minFreqPref.setEntryValues(FreqValues);
minFreqPref.setEntries(Freqs);
minFreqPref.setValue(temp);
minFreqPref.setSummary(String.format(MIN_FMT, MHerzed(temp)));
minFreqPref.setOnPreferenceChangeListener(this);

temp = readOneLine(FREQ_MAX_FILE);

maxFreqPref = (ListPreference) PrefScreen.findPreference(MAX_FREQ_PREF);
maxFreqPref.setEntryValues(FreqValues);
maxFreqPref.setEntries(Freqs);
maxFreqPref.setValue(temp);
maxFreqPref.setSummary(String.format(MAX_FMT, MHerzed(temp)));
maxFreqPref.setOnPreferenceChangeListener(this);
}

@Override
public void onResume() {
String temp;

super.onResume();

temp = readOneLine(FREQ_MAX_FILE);
maxFreqPref.setValue(temp);
maxFreqPref.setSummary(String.format(MAX_FMT, MHerzed(temp)));

temp = readOneLine(FREQ_MIN_FILE);
minFreqPref.setValue(temp);
minFreqPref.setSummary(String.format(MIN_FMT, MHerzed(temp)));

temp = readOneLine(GOVERNOR);
govPref.setSummary(String.format(GOV_FMT, temp));
}

public boolean onPreferenceChange(Preference preference, Object newValue) {
String fname = "";

if (newValue != null) {
if (preference == govPref) {
fname = GOVERNOR;
} else if (preference == minFreqPref) {
fname = FREQ_MIN_FILE;
} else if (preference == maxFreqPref) {
fname = FREQ_MAX_FILE;
}

if (writeOneLine(fname, (String) newValue)) {
if (preference == govPref) {
govPref.setSummary(String.format(GOV_FMT, (String) newValue));
} else if (preference == minFreqPref) {
minFreqPref.setSummary(String.format(MIN_FMT, MHerzed((String) newValue)));
} else if (preference == maxFreqPref) {
maxFreqPref.setSummary(String.format(MAX_FMT, MHerzed((String) newValue)));
}
return true;
} else {
return false;
}
}
return false;
}

public static String readOneLine(String fname) {
BufferedReader br;
String line = null;

try {
br = new BufferedReader (new FileReader(fname), 512);
try {
line = br.readLine();
} finally {
br.close();
}
} catch (Exception e) {
Log.e(TAG, "IO Exception when reading /sys/ file", e);
}
return line;
}

public static boolean writeOneLine(String fname, String value) {
try {
FileWriter fw = new FileWriter(fname);
try {
fw.write(value);
} finally {
fw.close();
}
} catch(IOException e) {
String Error = "Error writing to " + fname + ". Exception: ";
Log.e(TAG, Error, e);
return false;
}
return true;
}


private String MHerzed(String str) {
String temp;

temp = str.substring(0, str.length() - 3);

return (temp + " MHz");
}
}
25 changes: 25 additions & 0 deletions src/com/cyanogenmod/cmparts/intents/CPUReceiver.java
@@ -0,0 +1,25 @@
package com.cyanogenmod.cmparts.intents;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.SystemProperties;

public class CPUReceiver extends BroadcastReceiver {

private static final String CPU_SETTINGS_PROP = "sys.cpufreq.restored";

@Override
public void onReceive(Context ctx, Intent intent) {
if (SystemProperties.getBoolean(CPU_SETTINGS_PROP, false) == false &&
intent.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
SystemProperties.set(CPU_SETTINGS_PROP, "true");
ComponentName cmp = new ComponentName(ctx.getPackageName(),
com.cyanogenmod.cmparts.services.CPUService.class.getName());
ctx.startService(new Intent().setComponent(cmp));
} else {
SystemProperties.set(CPU_SETTINGS_PROP,"false");
}
}
}
62 changes: 62 additions & 0 deletions src/com/cyanogenmod/cmparts/services/CPUService.java
@@ -0,0 +1,62 @@
package com.cyanogenmod.cmparts.services;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import java.util.Arrays;
import java.util.List;

import com.cyanogenmod.cmparts.activities.CPUActivity;

public class CPUService extends Service {

private static final String TAG = "CPUSettings";

@Override
public IBinder onBind(Intent intent) {
return null;
}


@Override
public void onCreate() {

SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(this);

if (mPrefs.getBoolean(CPUActivity.SOB_PREF, false) == false) {
Log.i(TAG, "Restore disabled by user preference.");
return;
}

String mGov = mPrefs.getString(CPUActivity.GOV_PREF, null);
String mMinFreq = mPrefs.getString(CPUActivity.MIN_FREQ_PREF, null);
String mMaxFreq = mPrefs.getString(CPUActivity.MAX_FREQ_PREF, null);
boolean noSettings = (mGov==null) && (mMinFreq==null) && (mMaxFreq==null);

if (noSettings) {
Log.i(TAG, "No settings saved. Nothing to restore.");
} else {
List GovLst = Arrays.asList(
CPUActivity.readOneLine(CPUActivity.GOVERNORS_LIST_FILE).split(" "));
List FreqLst = Arrays.asList(
CPUActivity.readOneLine(CPUActivity.FREQ_LIST_FILE).split(" "));
if (mGov != null && GovLst.contains(mGov)) {
CPUActivity.writeOneLine(CPUActivity.GOVERNOR, mGov);
}
if (mMaxFreq != null && FreqLst.contains(mMaxFreq)) {
CPUActivity.writeOneLine(CPUActivity.FREQ_MAX_FILE, mMaxFreq);
}
if (mMinFreq != null && FreqLst.contains(mMinFreq)) {
CPUActivity.writeOneLine(CPUActivity.FREQ_MIN_FILE, mMinFreq);
}
Log.i(TAG, "CPU Settings restored.");
}
return;
}
}

0 comments on commit c5f4243

Please sign in to comment.