package com.blackice.control.fragments; import java.io.File; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.Resources; import android.os.Bundle; import android.os.SystemProperties; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceCategory; import android.preference.PreferenceGroup; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.util.Log; import com.blackice.control.R; import com.blackice.control.BlackICEPreferenceFragment; import com.blackice.control.tools.VoltageControl; import com.blackice.control.util.CMDProcessor; import com.blackice.control.util.Helpers; public class Performance extends BlackICEPreferenceFragment implements OnSharedPreferenceChangeListener, OnPreferenceChangeListener { public static final String TAG = "Performance"; public static final String KEY_MAX_CPU = "max_cpu"; public static final String KEY_MIN_CPU = "min_cpu"; public static final String KEY_GOV = "gov"; public static final String KEY_CPU_BOOT = "cpu_boot"; public static final String KEY_MINFREE = "free_memory"; public static final String KEY_FASTCHARGE = "fast_charge_boot"; private static final String STEPS = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies"; private static final String MAX_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq"; private static final String MIN_FREQ = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq"; private static final String GETALL_GOV = "sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"; private static final String CUR_GOV = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"; public static final String MINFREE = "/sys/module/lowmemorykiller/parameters/minfree"; private static final String SCROLLINGCACHE_PREF = "pref_scrollingcache"; private static final String SCROLLINGCACHE_PERSIST_PROP = "persist.sys.scrollingcache"; private static final String SCROLLINGCACHE_DEFAULT = "1"; private String[] ALL_GOV; private int[] SPEED_STEPS; private ListPreference mMinCpu; private ListPreference mMaxCpu; private ListPreference mSetGov; private ListPreference mFreeMem; private ListPreference mScrollingCachePref; private SharedPreferences preferences; private boolean doneLoading = false; private CheckBoxPreference mFastCharge; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); super.onCreate(savedInstanceState); preferences.registerOnSharedPreferenceChangeListener(this); addPreferencesFromResource(R.xml.performance); final int frequencies[] = getFrequencies(); final String freqList[] = getMHz(frequencies); final String freqValues[] = getValues(frequencies); final String maxFreq = (Helpers.getFile(MAX_FREQ).trim()); final String minFreq = (Helpers.getFile(MIN_FREQ).trim()); final String maxInMhz = (Integer.toString((Integer.parseInt(maxFreq) / 1000)) + " MHz"); final String minInMhz = (Integer.toString((Integer.parseInt(minFreq) / 1000)) + " MHz"); final String govs[] = getAllGovs(); final String currentGov = (Helpers.getFile(CUR_GOV).trim()); mMaxCpu = (ListPreference) findPreference(KEY_MAX_CPU); mMaxCpu.setEntries(freqList); mMaxCpu.setEntryValues(freqValues); mMaxCpu.setValue(maxFreq); mMaxCpu.setSummary(getString(R.string.ps_set_max, maxInMhz)); mMinCpu = (ListPreference) findPreference(KEY_MIN_CPU); mMinCpu.setEntries(freqList); mMinCpu.setEntryValues(freqValues); mMinCpu.setValue(minFreq); mMinCpu.setSummary(getString(R.string.ps_set_min, minInMhz)); mSetGov = (ListPreference) findPreference(KEY_GOV); mSetGov.setEntries(govs); mSetGov.setEntryValues(govs); mSetGov.setValue(currentGov); mSetGov.setSummary(getString(R.string.ps_set_gov, currentGov)); mScrollingCachePref = (ListPreference) findPreference(SCROLLINGCACHE_PREF); mScrollingCachePref.setValue(Helpers.getSystemProp(SCROLLINGCACHE_PERSIST_PROP, SCROLLINGCACHE_DEFAULT)); mScrollingCachePref.setOnPreferenceChangeListener(this); final int minFree = getMinFreeValue(); final String values[] = getResources().getStringArray(R.array.minfree_values); String closestValue = preferences.getString(KEY_MINFREE, values[0]); if (minFree < 37) closestValue = values[0]; else if (minFree < 62) closestValue = values[1]; else if (minFree < 77) closestValue = values[2]; else if (minFree < 90) closestValue = values[3]; else closestValue = values[4]; mFreeMem = (ListPreference) findPreference(KEY_MINFREE); mFreeMem.setValue(closestValue); mFreeMem.setSummary(getString(R.string.ps_free_memory, minFree + "mb")); PreferenceScreen ps = (PreferenceScreen) findPreference("volt_control"); if (!new File(VoltageControl.MV_TABLE0).exists()) { ((PreferenceCategory) getPreferenceScreen().findPreference("cpu")) .removePreference(ps); } mFastCharge = (CheckBoxPreference) findPreference(KEY_FASTCHARGE); mFastCharge.setChecked(preferences.getBoolean(KEY_FASTCHARGE, false)); if (!hasFastCharge) { ((PreferenceGroup) findPreference("kernel")).removePreference(mFastCharge); } com.blackice.control.fragments.ColorTuningPreference ct = (com.blackice.control.fragments.ColorTuningPreference) findPreference("color_tuning"); com.blackice.control.fragments.GammaTuningPreference gt = (com.blackice.control.fragments.GammaTuningPreference) findPreference("gamma_tuning"); if (!hasColorTuning) { ((PreferenceCategory) getPreferenceScreen().findPreference("kernel")) .removePreference(ct); ((PreferenceCategory) getPreferenceScreen().findPreference("kernel")) .removePreference(gt); } doneLoading = true; } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { String key = preference.getKey(); if (KEY_FASTCHARGE.equals(key)) { if (preferences.getBoolean(KEY_FASTCHARGE, false)) { Resources res = getActivity().getResources(); String warningMessage = res.getString(R.string.fast_charge_warning); String cancel = res.getString(R.string.cancel); String ok = res.getString(R.string.ok); new AlertDialog.Builder(getActivity()) .setMessage(warningMessage) .setNegativeButton(cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { preferences.edit().putBoolean(KEY_FASTCHARGE, false).apply(); mFastCharge.setChecked(false); } }) .setPositiveButton(ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { preferences.edit().putBoolean(KEY_FASTCHARGE, true).apply(); mFastCharge.setChecked(true); } }) .create() .show(); return true; } } return super.onPreferenceTreeClick(preferenceScreen, preference); } @Override public void onSharedPreferenceChanged( final SharedPreferences sharedPreferences, String key) { if (doneLoading) { if (key.equals(KEY_MAX_CPU)) { final String value = preferences.getString(key, null); final String maxInMhz = (Integer.toString((Integer.parseInt(value) / 1000)) + " MHz"); if (!sendCpu(key, value, MAX_FREQ)) Helpers.sendMsg(getActivity(), getString(R.string.toast_min_max_error01)); else mMaxCpu.setSummary(getString(R.string.ps_set_max, maxInMhz)); } else if (key.equals(KEY_MIN_CPU)) { final String value = preferences.getString(key, null); final String minInMhz = (Integer.toString((Integer.parseInt(value) / 1000)) + " MHz"); if (!sendCpu(key, value, MIN_FREQ)) Helpers.sendMsg(getActivity(), getString(R.string.toast_min_max_error02)); else mMinCpu.setSummary(getString(R.string.ps_set_min, minInMhz)); } else if (key.equals(KEY_GOV)) { final String value = preferences.getString(key, null); if ((new CMDProcessor().su .runWaitFor("busybox echo " + value + " > " + CUR_GOV)).success()) mSetGov.setSummary(getString(R.string.ps_set_gov, value)); } else if (key.equals(KEY_MINFREE)) { String values = preferences.getString(key, null); if (!values.equals(null)) new CMDProcessor().su .runWaitFor("busybox echo " + values + " > " + MINFREE); mFreeMem.setSummary(getString(R.string.ps_free_memory, getMinFreeValue() + "mb")); } } } String[] getMHz(int freqs[]) { int freqInMHz[] = new int[freqs.length]; for (int i = 0; i < freqs.length; i++) freqInMHz[i] = freqs[i] / 1000; String steps[] = new String[freqs.length]; for (int i = 0; i < freqs.length; i++) steps[i] = Integer.toString(freqInMHz[i]) + " MHz"; return steps; } String[] getValues(int freqs[]) { final String steps[] = new String[freqs.length]; for (int i = 0; i < freqs.length; i++) steps[i] = Integer.toString(freqs[i]); return steps; } int[] getFrequencies() { String freqs = Helpers.getFile(STEPS); if (freqs != null && freqs != "") { String[] freqList = freqs.trim().split("[ \n]+"); SPEED_STEPS = new int[freqList.length]; for (int i = 0; i < freqList.length; i++) { SPEED_STEPS[i] = (Integer.parseInt(freqList[i])); } } else { CMDProcessor cmd = new CMDProcessor(); CMDProcessor.CommandResult r = cmd.su .runWaitFor("busybox cut -d ' ' -f1 /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); freqs = r.stdout; if (freqs != null && freqs != "") { String[] freqList = freqs.trim().split("[ \n]+"); SPEED_STEPS = new int[freqList.length]; for (int i = 0; i < freqList.length; i++) { SPEED_STEPS[i] = (Integer.parseInt(freqList[i])); } } else { SPEED_STEPS = new int[] { 1000000, 800000, 600000, 300000 }; Log.d(TAG, "Failed getting steps"); } } return SPEED_STEPS; } public String[] getAllGovs() { String govs = Helpers.getFile(GETALL_GOV); if (govs != null && govs != "") { String[] govList = govs.trim().split(" "); ALL_GOV = new String[govList.length]; for (int i = 0; i < govList.length; i++) { ALL_GOV[i] = govList[i]; } } else { ALL_GOV = new String[] { "ondemand", "userspace", "performance" }; } return ALL_GOV; } private int getMinFreeValue() { int emptyApp = 0; String MINFREE_LINE = Helpers.getFile(MINFREE); String EMPTY_APP = MINFREE_LINE.substring(MINFREE_LINE.lastIndexOf(",") + 1); if (!EMPTY_APP.equals(null) || !EMPTY_APP.equals("")) { try { int mb = Integer.parseInt(EMPTY_APP.trim()) * 4 / 1024; emptyApp = (int) Math.ceil(mb); } catch (NumberFormatException nfe) { Log.i(TAG, "error processing " + EMPTY_APP); } } return emptyApp; } private boolean sendCpu(final String key, final String value, final String fname) { final int maxCpu = Integer.parseInt((Helpers.getFile(MAX_FREQ).trim())); final int minCpu = Integer.parseInt((Helpers.getFile(MIN_FREQ).trim())); final int newCpu = Integer.parseInt(value); final CMDProcessor cmd = new CMDProcessor(); Boolean isOk = true; String goodCpu = value; if (key.equals(KEY_MAX_CPU)) { if (newCpu < minCpu) { isOk = false; goodCpu = Integer.toString(maxCpu); } } else if (key.equals(KEY_MIN_CPU)) { if (newCpu > maxCpu) { isOk = false; goodCpu = Integer.toString(minCpu); } } if (isOk) { cmd.su.runWaitFor("busybox echo " + value + " > " + fname); if (new File("/sys/devices/system/cpu/cpu1").isDirectory()) { String cpu1 = fname.replace("cpu0", "cpu1"); cmd.su.runWaitFor("busybox echo " + value + " > " + cpu1); } } else { final SharedPreferences.Editor editor = preferences.edit(); editor.putString(key, goodCpu); editor.commit(); if (key.equals(KEY_MAX_CPU)) mMaxCpu.setValue(goodCpu); else if (key.equals(KEY_MIN_CPU)) mMinCpu.setValue(goodCpu); } return isOk; } public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference == mScrollingCachePref) { if (newValue != null) { Helpers.setSystemProp(SCROLLINGCACHE_PERSIST_PROP, (String) newValue); return true; } } return false; } }