public class CardImageLocal extends Card {

    public CardImageLocal(String title, String desc, String titleColor, int imageRes, ActionBarActivity fa) {
        super(title, desc, titleColor, imageRes, fa);
    }

    @Override
    public View getCardContent(Context context) {
        View v = LayoutInflater.from(context).inflate(R.layout.card_image, null);
        assert v != null;
        ((ImageView) v.findViewById(R.id.image)).setImageDrawable(fa.getResources().getDrawable(imageRes));
        ((TextView) v.findViewById(R.id.title)).setText(title);
        ((TextView) v.findViewById(R.id.title)).setTextColor(Color.parseColor(titleColor));
        ((TextView) v.findViewById(R.id.description)).setText(desc);
        return v;
    }

    public int getCardContentId() {
        return R.layout.card_image;
    }

    @Override
    public boolean convert(View convertCardView) {
        return true;
    }
} public class Helpers {

    private static final String BUILD_PROP = "/system/build.prop";
    // don't show unavoidable warnings
    @SuppressWarnings({
            "UnusedDeclaration",
            "MethodWithMultipleReturnPoints",
            "ReturnOfNull",
            "NestedAssignment",
            "DynamicRegexReplaceableByCompiledPattern",
            "BreakStatement"})

    // avoids hardcoding the tag
    private static final String TAG = Thread.currentThread().getStackTrace()[1].getClassName();

    public Helpers() {
        // dummy constructor
    }

    public static String grabString(Context context, int resID) {
        try {
            return context.getResources().getString(resID);
        } catch (NullPointerException e) {
            Log.e("GRAB_STRING", "" + e);
            return "";
        }
    }

    public static String convertStreamToString(InputStream is) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }

        return sb.toString();
    }

    public static String getStringFromFile(String filePath) throws Exception {
        File fl = new File(filePath);
        FileInputStream fin = new FileInputStream(fl);
        String ret = convertStreamToString(fin);
        fin.close();

        return ret;
    }

    public static Boolean hasBuildPropValue(String buildProp) throws Exception {
        Boolean has = false;
        String buildprop = "";
        buildprop = getStringFromFile(BUILD_PROP);
        if (buildprop.matches(buildProp + "=.+$"))
            has = true;
        return has;
    }

    /**
     * Checks device for SuperUser permission
     *
     * @return If SU was granted or denied
     */
    @SuppressWarnings("MethodWithMultipleReturnPoints")
    public static boolean checkSu() {
        if (!new File("/system/bin/su").exists()
                && !new File("/system/xbin/su").exists()) {
            Log.e(TAG, "su binary does not exist!!!");
            return false; // tell caller to bail...
        }
        try {
            if (runSuCommand("ls /data/app-private").success()) {
                Log.i(TAG, " SU exists and we have permission");
                return true;
            } else {
                Log.i(TAG, " SU exists but we don't have permission");
                return false;
            }
        } catch (NullPointerException e) {
            Log.e(TAG, "NullPointer throw while looking for su binary", e);
            return false;
        }
    }

    /**
     * Checks to see if Busybox is installed in "/system/"
     *
     * @return If busybox exists
     */
    public static boolean checkBusybox() {
        if (!new File("/system/bin/busybox").exists()
                && !new File("/system/xbin/busybox").exists()) {
            Log.e(TAG, "Busybox not in xbin or bin!");
            return false;
        }
        try {
            if (!runSuCommand("busybox mount").success()) {
                Log.e(TAG, "Busybox is there but it is borked! ");
                return false;
            }
        } catch (NullPointerException e) {
            Log.e(TAG, "NullpointerException thrown while testing busybox", e);
            return false;
        }
        return true;
    }

    public static String[] getMounts(CharSequence path) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader("/proc/mounts"), 256);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                if (line.contains(path)) {
                    return line.split(" ");
                }
            }
        } catch (FileNotFoundException ignored) {
            Log.d(TAG, "/proc/mounts does not exist");
        } catch (IOException ignored) {
            Log.d(TAG, "Error reading /proc/mounts");
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ignored) {
                    // ignored
                }
            }
        }
        return null;
    }

    public static boolean getMount(String mount) {
        String[] mounts = getMounts("/system");
        if (mounts != null && mounts.length >= 3) {
            String device = mounts[0];
            String path = mounts[1];
            String point = mounts[2];
            String preferredMountCmd = "mount -o " + mount + ",remount -t " + point + ' ' + device + ' ' + path;
            if (runSuCommand(preferredMountCmd).success()) {
                return true;
            }
        }
        String fallbackMountCmd = "busybox mount -o remount," + mount + " /system";
        return runSuCommand(fallbackMountCmd).success();
    }

    public static String readOneLine(String fname) {
        BufferedReader br = null;
        String line = null;
        try {
            br = new BufferedReader(new FileReader(fname), 1024);
            line = br.readLine();
        } catch (FileNotFoundException ignored) {
            Log.d(TAG, "File was not found! trying via shell...");
            return readFileViaShell(fname, true);
        } catch (IOException e) {
            Log.d(TAG, "IOException while reading system file", e);
            return readFileViaShell(fname, true);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException ignored) {
                    // failed to close reader
                }
            }
        }
        return line;
    }

    public static String readFileViaShell(String filePath, boolean useSu) {
        String command = "cat " + filePath;
        return useSu ? runSuCommand(command).getStdout()
                : runShellCommand(command).getStdout();
    }

    public static boolean writeOneLine(String filename, String value) {
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(filename);
            fileWriter.write(value);
        } catch (IOException e) {
            String Error = "Error writing { " + value + " } to file: " + filename;
            Log.e(TAG, Error, e);
            return false;
        } finally {
            if (fileWriter != null) {
                try {
                    fileWriter.close();
                } catch (IOException ignored) {
                    // failed to close writer
                }
            }
        }
        return true;
    }

    public static String[] getAvailableIOSchedulers() {
        String[] schedulers = null;
        String[] aux = readStringArray("/sys/block/mmcblk0/queue/scheduler");
        if (aux != null) {
            schedulers = new String[aux.length];
            for (int i = 0; i < aux.length; i++) {
                schedulers[i] = aux[i].charAt(0) == '['
                        ? aux[i].substring(1, aux[i].length() - 1)
                        : aux[i];
            }
        }
        return schedulers;
    }

    private static String[] readStringArray(String fname) {
        String line = readOneLine(fname);
        if (line != null) {
            return line.split(" ");
        }
        return null;
    }

    public static String getIOScheduler() {
        String scheduler = null;
        String[] schedulers = readStringArray("/sys/block/mmcblk0/queue/scheduler");
        if (schedulers != null) {
            for (String s : schedulers) {
                if (s.charAt(0) == '[') {
                    scheduler = s.substring(1, s.length() - 1);
                    break;
                }
            }
        }
        return scheduler;
    }

    /**
     * Long toast message
     *
     * @param context Application Context
     * @param msg     Message to send
     */
    public static void msgLong(Context context, String msg) {
        if (context != null && msg != null) {
            Toast.makeText(context, msg.trim(), Toast.LENGTH_LONG).show();
        }
    }

    /**
     * Short toast message
     *
     * @param context Application Context
     * @param msg     Message to send
     */
    public static void msgShort(Context context, String msg) {
        if (context != null && msg != null) {
            Toast.makeText(context, msg.trim(), Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Long toast message
     *
     * @param context Application Context
     * @param msg     Message to send
     */
    public static void sendMsg(Context context, String msg) {
        if (context != null && msg != null) {
            msgLong(context, msg);
        }
    }

    /**
     * Return a timestamp
     *
     * @param context Application Context
     */
    @SuppressWarnings("UnnecessaryFullyQualifiedName")
    public static String getTimestamp(Context context) {
        String timestamp = "unknown";
        Date now = new Date();
        java.text.DateFormat dateFormat = android.text.format.DateFormat.getDateFormat(context);
        java.text.DateFormat timeFormat = android.text.format.DateFormat.getTimeFormat(context);
        timestamp = dateFormat.format(now) + ' ' + timeFormat.format(now);
        return timestamp;
    }

    public static boolean isPackageInstalled(String packageName, PackageManager pm) {
        try {
            String mVersion = pm.getPackageInfo(packageName, 0).versionName;
            if (mVersion == null) {
                return false;
            }
        } catch (PackageManager.NameNotFoundException notFound) {
            Log.e(TAG, "Package could not be found!", notFound);
            return false;
        }
        return true;
    }

    public static void restartSystemUI() {
        startSuCommand("pkill -TERM -f com.android.systemui");
    }

    public static void setSystemProp(String prop, String val) {
        startSuCommand("setprop " + prop + " " + val);
    }

    public static String getSystemProp(Context context, String prop, String def) {
        String result = null;
        try {
            result = SystemPropertiesReflection.get(context, prop);
        } catch (IllegalArgumentException iae) {
            Log.e(TAG, "Failed to get prop: " + prop);
        }
        return result == null ? def : result;
    }

    // If the value is empty or null, fallback to the second property if there's one
    public static String getPropWithFallback(Context context, String[] props, String def) {
        String value = "";
        for (int i = 0; i < props.length; i++) {
            value = Helpers.getSystemProp(context, props[i], def);
            if (!value.equals(""))
                return value;
        }
        return "";
    }

    public static String toMHz(String mhzString) {
        int val = 0;
        try {
            val = Integer.valueOf(mhzString);
        } catch (NumberFormatException e) {
            Log.e("ToMHZ", e.getMessage());
        }
        return val / 1000 + " MHz";
    }

    public static int getNumOfCpus() {
        int numOfCpu = 1;
        String numOfCpus = Helpers.readOneLine("/sys/devices/system/cpu/present");
        String[] cpuCount = numOfCpus.split("-");
        if (cpuCount.length > 1) {
            try {
                int cpuStart = Integer.parseInt(cpuCount[0]);
                int cpuEnd = Integer.parseInt(cpuCount[1]);

                numOfCpu = cpuEnd - cpuStart + 1;

                if (numOfCpu < 0)
                    numOfCpu = 1;
            } catch (NumberFormatException ex) {
                numOfCpu = 1;
            }
        }
        return numOfCpu;
    }

    public static ArrayList<String> getTcpAlgorithms() {
        if (new File("/proc/sys/net/ipv4/tcp_available_congestion_control").exists()) {
            try {
                String result = String.valueOf(runShellCommand("cat /proc/sys/net/ipv4/tcp_available_congestion_control").getStdout());
                Log.e("TCP", result);
                String[] algorithms = result.split("\\s");
                ArrayList<String> holder = new ArrayList<String>();
                Collections.addAll(holder, algorithms);
                return holder;
            } catch (Exception e) {
                Log.e("getTcpAlgorithms", e.getMessage());
                return new ArrayList<String>();
            }

        } else {
            return new ArrayList<String>();
        }
    }

    public static String getCurrentTcpAlgorithm() {
        if (new File("/proc/sys/net/ipv4/tcp_congestion_control").exists()) {
            try {
                return String.valueOf(runShellCommand("cat /proc/sys/net/ipv4/tcp_congestion_control").getStdout());
            } catch (Exception e) {
                Log.e("getCurrentTcpAlgorithm", e.getMessage());
                return "NaN";
            }
        } else return "NaN";
    }

    public static void setPmrProp(String prop, Boolean isOn) {
        if (isOn)
            runSuCommand(Shell.ECHO + "\"" + prop + "=true" + "\" >> " + Shell.BUILD_PROP);
        else
            runSuCommand(Shell.ECHO + "\"" + prop + "=false" + "\" >> " + Shell.BUILD_PROP);
    }

    public static String getProp(String prop) {
        return CMDProcessor.runSuCommand("getprop " + prop).getStdout();
    }

    public static void setpropBoolean(String prop, Boolean isOn) {
        if (isOn)
            runSuCommand("setprop " + prop + " true");
        else
            runSuCommand("setprop " + prop + " false");
    }

    public static void applyBuildPropTweak(String buildProp, String propValue) {
        final String prop = buildProp;
        final String value = propValue;
        new Thread(new Runnable() {

            @Override
            public void run() {
                CMDProcessor.runSuCommand(Shell.MOUNT_SYSTEM_RW);
                CMDProcessor.runSuCommand(Shell.SED + prop + "/d\" " + Shell.BUILD_PROP);
                CMDProcessor.runSuCommand(Shell.ECHO + "\"" + prop + "=" + value + "\" >> " + Shell.BUILD_PROP);
                CMDProcessor.runSuCommand("setprop " + prop + " " + value);
                CMDProcessor.runSuCommand(Shell.MOUNT_SYSTEM_RO);
            }
        }).start();

    }

    /**
     * This method takes a square bitmap and clips it into a circle
     *
     * @param bitmap : the image to clip
     * @return the clipped bitmap
     */
    public static Bitmap getCroppedBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
                bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        // canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
        canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2,
                bitmap.getWidth() / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        //Bitmap _bmp = Bitmap.createScaledBitmap(output, 60, 60, false);
        //return _bmp;
        return output;
    }

    /**
     * This method simply allows to open an url with a shorter syntax
     */
    public static void openUrl(ActionBarActivity activity, String url) {
        activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
    }

    public static int convertSoundControlValue(int seekBarValue) {
        if (seekBarValue < 0) {
            return seekBarValue + 256;
        } else {
            return seekBarValue;
        }
    }

    public static class CMDProcessorWrapper {
        public static void runSuCommand(final String command) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    CMDProcessor.runSuCommand(command);
                }
            }).start();
        }

        public static void runShellCommand(final String command) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    CMDProcessor.runShellCommand(command);
                }
            }).start();
        }
    }

    public static int getSoundCountrolBitRepresentation(int leftGain, int rightGain) {
        return 0xFF & (0xFFFFFFFF ^ (leftGain & 0xFF) + (rightGain & 0xFF));
    }

    public static Boolean doesFileExist(String path) {
        return new File(path).exists();
    }

    public static void applySysctlValue(String key, String value) {
        Helpers.CMDProcessorWrapper.runSuCommand("busybox mount -o remount,rw /system\n" +
                        "busybox sysctl -w " + key + "=" + value + "\n" +
                        "busybox echo \'" + key + " = " + value + "\' > /system/etc/sysctl.conf\n" +
                        "busybox mount -o remount,ro /system"
        );
    }
} public class ColorControlActivity extends ActionBarActivity implements ColorControlInterface {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_color_calibration));
        setContentView(R.layout.card_color_control);
        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);

        final SeekBar brightnessSeek = (SeekBar) findViewById(R.id.brightness_seekbar);
        final SeekBar redSeek = (SeekBar) findViewById(R.id.red_seekbar);
        final SeekBar greenSeek = (SeekBar) findViewById(R.id.green_seekbar);
        final SeekBar blueSeek = (SeekBar) findViewById(R.id.blue_seekbar);

        final TextView brightnessVal = (TextView) findViewById(R.id.brightness_unit);
        final TextView redVal = (TextView) findViewById(R.id.red_unit);
        final TextView greenVal = (TextView) findViewById(R.id.green_unit);
        final TextView blueVal = (TextView) findViewById(R.id.blue_unit);

        brightnessSeek.setMax(255);
        redSeek.setMax(255);
        greenSeek.setMax(255);
        blueSeek.setMax(255);

        String[] rawCalib = CPUHelper.readOneLineNotRoot(GAMMA_KCAL).split("\\s+");
        final int[] currRed = {255};
        final int[] currGreen = {255};
        final int[] currBlue = {255};
        final int[] currBrightness = {255};

        try {
            currRed[0] = Integer.parseInt(rawCalib[0]);
            currGreen[0] = Integer.parseInt(rawCalib[1]);
            currBlue[0] = Integer.parseInt(rawCalib[2]);
        } catch (Exception e) {
            Log.e("GammaControl", e.getMessage());
        }

        if (currRed[0] == currGreen[0] && currRed[0] == currBlue[0]) {
            currBrightness[0] = currRed[0];
            brightnessSeek.setEnabled(true);
            brightnessSeek.setProgress(currBrightness[0]);
            brightnessVal.setText(getString(R.string.color_brightness) + " " + currBrightness[0]);
        } else {
            currBrightness[0] = 255;
            brightnessSeek.setProgress(255);
            brightnessSeek.setEnabled(false);
            brightnessVal.setText(getString(R.string.custom));
        }

        redSeek.setProgress(currRed[0]);
        greenSeek.setProgress(currGreen[0]);
        blueSeek.setProgress(currBlue[0]);

        redVal.setText(getString(R.string.red_val) + " " + currRed[0]);
        greenVal.setText(getString(R.string.green_val) + " " + currGreen[0]);
        blueVal.setText(getString(R.string.blue_val) + " " + currBlue[0]);

        brightnessSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean fromUser) {
                currBrightness[0] = i;
                currRed[0] = i;
                currGreen[0] = i;
                currBlue[0] = i;
                brightnessVal.setText(ColorControlActivity.this.getString(R.string.color_brightness) + " " + currBrightness[0]);

                redSeek.setProgress(i);
                blueSeek.setProgress(i);
                greenSeek.setProgress(i);
                redVal.setText(getString(R.string.red_val) + " " + currRed[0]);
                greenVal.setText(getString(R.string.green_val) + " " + currGreen[0]);
                blueVal.setText(getString(R.string.blue_val) + " " + currBlue[0]);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (currBrightness[0] < 2)
                    Toast.makeText(ColorControlActivity.this, getString(R.string.color_brightness_warning), Toast.LENGTH_LONG).show();
                else
                    CMDProcessor.runSuCommand("busybox echo \'" + currRed[0] + " " + currGreen[0] + " " + currBlue[0] + "\' > " + GAMMA_KCAL + "\nbusybox echo 1 > " + GAMMA_OK);
                    bootPrefs.edit().putString("KCAL_CONFIG", currRed[0] + " " + currGreen[0] + " " + currBlue[0]).commit();
            }
        });

        redSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                currRed[0] = i;
                redVal.setText(getString(R.string.red_val) + " " + currRed[0]);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                CMDProcessor.runSuCommand("busybox echo \'" + currRed[0] + " " + currGreen[0] + " " + currBlue[0] + "\' > " + GAMMA_KCAL + "\nbusybox echo 1 > " + GAMMA_OK);
                bootPrefs.edit().putString("KCAL_CONFIG", currRed[0] + " " + currGreen[0] + " " + currBlue[0]).commit();

                if (currRed[0] == currGreen[0] && currRed[0] == currBlue[0]) {
                    currBrightness[0] = currRed[0];
                    brightnessSeek.setProgress(currBrightness[0]);
                    brightnessVal.setText(getString(R.string.color_brightness) + " " + currBrightness[0]);
                } else {
                    currBrightness[0] = 255;
                    brightnessSeek.setProgress(255);
                    brightnessSeek.setEnabled(false);
                    brightnessVal.setText(getString(R.string.custom));
                }
            }
        });

        greenSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                currGreen[0] = i;
                greenVal.setText(getString(R.string.green_val) + " " + currGreen[0]);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                CMDProcessor.runSuCommand("busybox echo \'" + currRed[0] + " " + currGreen[0] + " " + currBlue[0] + "\' > " + GAMMA_KCAL + "\nbusybox echo 1 > " + GAMMA_OK);
                bootPrefs.edit().putString("KCAL_CONFIG", currRed[0] + " " + currGreen[0] + " " + currBlue[0]).commit();

                if (currRed[0] == currGreen[0] && currRed[0] == currBlue[0]) {
                    currBrightness[0] = currRed[0];
                    brightnessSeek.setProgress(currBrightness[0]);
                    brightnessVal.setText(getString(R.string.color_brightness) + " " + currBrightness[0]);
                } else {
                    currBrightness[0] = 255;
                    brightnessSeek.setProgress(255);
                    brightnessSeek.setEnabled(false);
                    brightnessVal.setText(getString(R.string.custom));
                }
            }
        });

        blueSeek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                currBlue[0] = i;
                blueVal.setText(getString(R.string.blue_val) + " " + currBlue[0]);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                CMDProcessor.runSuCommand("busybox echo \'" + currRed[0] + " " + currGreen[0] + " " + currBlue[0] + "\' > " + GAMMA_KCAL + "\nbusybox echo 1 > " + GAMMA_OK);
                bootPrefs.edit().putString("KCAL_CONFIG", currRed[0] + " " + currGreen[0] + " " + currBlue[0]).commit();

                if (currRed[0] == currGreen[0] && currRed[0] == currBlue[0]) {
                    currBrightness[0] = currRed[0];
                    brightnessSeek.setProgress(currBrightness[0]);
                    brightnessVal.setText(getString(R.string.color_brightness) + " " + currBrightness[0]);
                } else {
                    currBrightness[0] = 255;
                    brightnessSeek.setProgress(255);
                    brightnessSeek.setEnabled(false);
                    brightnessVal.setText(getString(R.string.custom));
                }
            }
        });

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }

        return super.onOptionsItemSelected(item);
    }
} public interface ColorControlInterface {
    public static final String GAMMA_KCAL = "/sys/devices/platform/kcal_ctrl.0/kcal";
    public static final String GAMMA_OK = "/sys/devices/platform/kcal_ctrl.0/kcal_ctrl";
} public class CPUActivity extends ActionBarActivity implements CPUInterface {

    private static SharedPreferences bootPrefs;

    public static final String TAG = "CPUSettings";


    private static LineGraph graph;
    private static Line line;
    private static int currX = 0;
    private static int counter = 0;
    private static TextView mCurFreq;
    private SeekBar mMaxSlider;
    private SeekBar mMinSlider;
    private Spinner mGeneralGovernor;
    private static Spinner mGovernor;
    private static Spinner mGovernor2;
    private static Spinner mGovernor3;
    private static Spinner mGovernor4;
    private Switch perCoreGovernor;
    private TextView mMaxSpeedText;
    private TextView mMinSpeedText;
    private TextView mCoresOnline;
    private String[] availableFrequencies;
    private String mMaxFreqSetting;
    private String mMinFreqSetting;
    private CurCPUThread mCurCPUThread;
    private Boolean mIsTegra3 = false, snakeCharmerEnabled = true;
    private int mNumOfCpus = 0;
    private int govCounterGeneral = 0, govCounter = 0, govCounter2 = 0, govCounter3 = 0, govCounter4 = 0, tcpCounter = 0;

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                return super.onOptionsItemSelected(item);
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_cpu_control));
        setContentView(R.layout.card_cpu_control);
        bootPrefs = getSharedPreferences("BOOT_PREFS", 0);

        graph = (LineGraph) findViewById(R.id.graph);
        line = new Line();
        LinePoint point = new LinePoint();
        point.setX(currX);
        point.setY(1);
        line.addPoint(point);
        line.setColor(Color.parseColor("#FFBB33"));
        graph.addLine(line);
        graph.setLineToFill(0);

        availableFrequencies = new String[0];
        String availableFrequenciesLine;

        mCoresOnline = (TextView) findViewById(R.id.cores_online);
        mGeneralGovernor = (Spinner) findViewById(R.id.general_governor);
        mGovernor = (Spinner) findViewById(R.id.governor);
        mGovernor2 = (Spinner) findViewById(R.id.governor2);
        mGovernor3 = (Spinner) findViewById(R.id.governor3);
        mGovernor4 = (Spinner) findViewById(R.id.governor4);


        Button customizeGov = (Button) findViewById(R.id.governor_customize_btn);
        customizeGov.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fm = getSupportFragmentManager();
                GovernorDialog editNameDialog = new GovernorDialog();
                editNameDialog.show(fm, "governor_fragment");
            }
        });

        if (Helpers.doesFileExist(STEPS)) {
            availableFrequenciesLine = CPUHelper.readOneLineNotRoot(STEPS);

            if (availableFrequenciesLine != null) {
                availableFrequencies = availableFrequenciesLine.split(" ");
                Arrays.sort(availableFrequencies, new Comparator<String>() {
                    @Override
                    public int compare(String object1, String object2) {
                        return Integer.valueOf(object1).compareTo(
                                Integer.valueOf(object2));
                    }
                });
            }
        }

        Switch snakeCharmer = (Switch) findViewById(R.id.snake_charmer_switch);
        if (!Helpers.doesFileExist(SNAKE_CHARMER_MAX_FREQ)) {
            LinearLayout cardSnakeCharmer = (LinearLayout) findViewById(R.id.card_snake_charmer);
            cardSnakeCharmer.setVisibility(View.GONE);
        } else {
            if (Helpers.doesFileExist(SNAKE_CHARMER_VERSION)) {
                TextView snakeTitle = (TextView) findViewById(R.id.snake_charmer);
                String snakeVersion = CPUHelper.readOneLineNotRoot(SNAKE_CHARMER_VERSION);
                snakeVersion = snakeVersion.replaceAll("version: ", "v");
                snakeTitle.setText(snakeTitle.getText() + " " + snakeVersion);
                if (snakeVersion.equals("v1.2")) {
                    TextView snakeDesc = (TextView) findViewById(R.id.snake_charmer_text);
                    snakeDesc.setText(snakeDesc.getText() + "\n" + getString(R.string.snake_charmer_built_in));
                    snakeCharmer.setEnabled(false);
                }
            }

            if (bootPrefs.getBoolean("SNAKE_CHARMER", true)) {
                snakeCharmer.setChecked(true);
                snakeCharmerEnabled = true;
            }

            snakeCharmer.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                    snakeCharmerEnabled = isOn;
                }
            });
        }

        int frequenciesNum = availableFrequencies.length - 1;

        Switch thermalControl = (Switch) findViewById(R.id.msm_thermal_switch);
        if (Helpers.doesFileExist(MSM_THERMAL)) {
            String thermal = CPUHelper.readOneLineNotRoot(MSM_THERMAL);
            if (thermal.equals("Y"))
                thermalControl.setChecked(true);
            else
                thermalControl.setChecked(false);

            thermalControl.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                    if (isChecked)
                        Helpers.CMDProcessorWrapper.runSuCommand("echo Y > " + MSM_THERMAL);
                    else
                        Helpers.CMDProcessorWrapper.runSuCommand("echo N > " + MSM_THERMAL);

                    bootPrefs.edit().putBoolean("MSM_THERMAL", isChecked).commit();
                }
            });
        }
        thermalControl.setChecked(bootPrefs.getBoolean("MSM_THERMAL", true));

        perCoreGovernor = (Switch) findViewById(R.id.per_core_governors_switch);
        perCoreGovernor.setChecked(bootPrefs.getBoolean("PER_CORE_GOV", true));

        if (perCoreGovernor.isChecked()) {
            findViewById(R.id.card_general_governor).setVisibility(View.GONE);
            findViewById(R.id.card_per_core_governors).setVisibility(View.VISIBLE);
        } else {
            findViewById(R.id.card_per_core_governors).setVisibility(View.GONE);
            findViewById(R.id.card_general_governor).setVisibility(View.VISIBLE);
        }

        perCoreGovernor.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if (isChecked) {
                    findViewById(R.id.card_general_governor).setVisibility(View.GONE);
                    findViewById(R.id.card_per_core_governors).setVisibility(View.VISIBLE);
                    handleGovernors();
                } else {
                    findViewById(R.id.card_per_core_governors).setVisibility(View.GONE);
                    findViewById(R.id.card_general_governor).setVisibility(View.VISIBLE);
                    handleGovernors();
                }

                bootPrefs.edit().putBoolean("PER_CORE_GOV", isChecked).commit();
            }
        });


        String currentIo = "";
        if (Helpers.doesFileExist(IO_SCHEDULER))
            currentIo = CPUHelper.getIOScheduler();

        String currentTcp = "";
        if (Helpers.doesFileExist(CURR_TCP_ALGORITHM))
            currentTcp = Helpers.getCurrentTcpAlgorithm();

        String curMaxSpeed = "NaN";
        if (Helpers.doesFileExist(MAX_FREQ_ALL_CORES))
            curMaxSpeed = CPUHelper.readOneLineNotRoot(MAX_FREQ_ALL_CORES);
        else if (Helpers.doesFileExist(MAX_FREQ))
            curMaxSpeed = CPUHelper.readOneLineNotRoot(MAX_FREQ);

        String curMinSpeed = "NaN";
        if (Helpers.doesFileExist(MIN_FREQ_ALL_CORES))
            curMinSpeed = CPUHelper.readOneLineNotRoot(MIN_FREQ_ALL_CORES);
        else if (Helpers.doesFileExist(MIN_FREQ))
            curMinSpeed = CPUHelper.readOneLineNotRoot(MIN_FREQ);

        if (mIsTegra3) {
            String curTegraMaxSpeed = "NaN";
            if (Helpers.doesFileExist(TEGRA_MAX_FREQ)) {
                curTegraMaxSpeed = CPUHelper.readOneLineNotRoot(TEGRA_MAX_FREQ);
                int curTegraMax = 0;
                try {
                    curTegraMax = Integer.parseInt(curTegraMaxSpeed);
                    if (curTegraMax > 0) {
                        curMaxSpeed = Integer.toString(curTegraMax);
                    }
                } catch (NumberFormatException ex) {
                    curTegraMax = 0;
                }
            }
        }

        if (Helpers.doesFileExist(NUM_OF_CPUS))
            mNumOfCpus = Helpers.getNumOfCpus();

        mCurFreq = (TextView) findViewById(R.id.currspeed);

        mMaxSlider = (SeekBar) findViewById(R.id.max_slider);
        mMaxSlider.setMax(frequenciesNum);
        mMaxSpeedText = (TextView) findViewById(R.id.max_speed_text);
        mMaxSpeedText.setText(toMHz(curMaxSpeed));
        mMaxSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
                curMaxSpeed));
        mMaxSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser)
                    setMaxSpeed(seekBar, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                startSupportActionMode(new ActionMode.Callback() {
                    @Override
                    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                        MenuInflater inflater = actionMode.getMenuInflater();
                        inflater.inflate(R.menu.contextual_menu, menu);
                        return true;
                    }

                    @Override
                    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                        return false;
                    }

                    @Override
                    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                        switch (menuItem.getItemId()) {
                            case R.id.apply:
                                if (mMaxFreqSetting != null && !mMaxFreqSetting.isEmpty()) {
                                    bootPrefs.edit().putString("CPU_MAX_FREQ", mMaxFreqSetting).commit();
                                    for (int i = 0; i < mNumOfCpus; i++)
                                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > "
                                                + MAX_FREQ.replace("cpu0", "cpu" + i));

                                    if (snakeCharmerEnabled)
                                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > " + SNAKE_CHARMER_MAX_FREQ);
                                }


                                if (mIsTegra3) {
                                    if (mMaxFreqSetting != null && !mMaxFreqSetting.isEmpty())
                                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > "
                                                + TEGRA_MAX_FREQ);

                                    if (snakeCharmerEnabled)
                                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > " + SNAKE_CHARMER_MAX_FREQ);
                                }
                                actionMode.finish();
                                return true;
                            default:
                                return false;
                        }
                    }

                    @Override
                    public void onDestroyActionMode(ActionMode actionMode) {

                    }
                });
            }
        });

        mMinSlider = (SeekBar) findViewById(R.id.min_slider);
        mMinSlider.setMax(frequenciesNum);
        mMinSpeedText = (TextView) findViewById(R.id.min_speed_text);
        mMinSpeedText.setText(toMHz(curMinSpeed));
        mMinSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
                curMinSpeed));
        mMinSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser)
                    setMinSpeed(seekBar, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                startSupportActionMode(new ActionMode.Callback() {
                    @Override
                    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                        MenuInflater inflater = actionMode.getMenuInflater();
                        inflater.inflate(R.menu.contextual_menu, menu);
                        return true;
                    }

                    @Override
                    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                        return false;
                    }

                    @Override
                    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                        switch (menuItem.getItemId()) {
                            case R.id.apply:
                                if (mMinFreqSetting != null && !mMinFreqSetting.isEmpty()) {
                                    bootPrefs.edit().putString("CPU_MIN_FREQ", mMinFreqSetting).commit();
                                    for (int i = 0; i < mNumOfCpus; i++)
                                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMinFreqSetting + " > "
                                                + MIN_FREQ.replace("cpu0", "cpu" + i));
                                }
                                actionMode.finish();
                                return true;
                            default:
                                return false;
                        }
                    }

                    @Override
                    public void onDestroyActionMode(ActionMode actionMode) {

                    }
                });
            }
        });

        handleGovernors();

        /** TCP Congestion Spinner */
        Spinner mTcp = (Spinner) findViewById(R.id.tcp);
        ArrayAdapter<CharSequence> tcpAdapter = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        tcpAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        ArrayList<String> algorithms = Helpers.getTcpAlgorithms();
        for (String algorithm : algorithms) tcpAdapter.add(algorithm);
        mTcp.setAdapter(tcpAdapter);
        mTcp.setSelection(algorithms.indexOf(currentTcp));
        mTcp.setOnItemSelectedListener(new TCPListener());

        onlineCoresPolling();
    }

    private void handleGovernors() {
        String currentGovernor = "";
        if (Helpers.doesFileExist(GOVERNOR))
            currentGovernor = CPUHelper.readOneLineNotRoot(GOVERNOR);

        String currentGovernor2 = "";
        if (Helpers.doesFileExist(GOVERNOR2))
            currentGovernor2 = CPUHelper.readOneLineNotRoot(GOVERNOR2);
        else
            currentGovernor2 = bootPrefs.getString("CORE1_GOVERNOR", "NaN");

        String currentGovernor3 = "";
        if (Helpers.doesFileExist(GOVERNOR3))
            currentGovernor3 = CPUHelper.readOneLineNotRoot(GOVERNOR3);
        else
            currentGovernor3 = bootPrefs.getString("CORE2_GOVERNOR", "NaN");

        String currentGovernor4 = "";
        if (Helpers.doesFileExist(GOVERNOR4))
            currentGovernor4 = CPUHelper.readOneLineNotRoot(GOVERNOR4);
        else
            currentGovernor4 = bootPrefs.getString("CORE3_GOVERNOR", "NaN");

        /** CPU Governor for all cores */
        String[] availableGovernorsGeneral = CPUHelper.readOneLineNotRoot(GOVERNORS_LIST).split(" ");
        ArrayAdapter<CharSequence> governorAdapterGeneral = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapterGeneral.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        for (String availableGovernor : availableGovernorsGeneral) {
            governorAdapterGeneral.add(availableGovernor);
        }

        mGeneralGovernor.setAdapter(governorAdapterGeneral);
        mGeneralGovernor.setSelection(Arrays.asList(availableGovernorsGeneral).indexOf(
                currentGovernor));
        mGeneralGovernor.setOnItemSelectedListener(new GeneralGovListener());

        /** CPU Governor for core 0 */
        String[] availableGovernors = CPUHelper.readOneLineNotRoot(GOVERNORS_LIST).split(" ");
        ArrayAdapter<CharSequence> governorAdapter = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapter
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (String availableGovernor : availableGovernors) {
            governorAdapter.add(availableGovernor);
        }
        mGovernor.setAdapter(governorAdapter);
        mGovernor.setSelection(Arrays.asList(availableGovernors).indexOf(
                currentGovernor));
        mGovernor.setOnItemSelectedListener(new GovListener());

        /** CPU Governor for core 1 */
        ArrayAdapter<CharSequence> governorAdapter2 = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapter2
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (String anAvailableGovernors2 : availableGovernors) {
            governorAdapter2.add(anAvailableGovernors2);
        }
        mGovernor2.setAdapter(governorAdapter2);
        mGovernor2.setSelection(Arrays.asList(availableGovernors).indexOf(
                currentGovernor2));
        mGovernor2.setOnItemSelectedListener(new GovListener2());

        /** CPU Governor for core 2 */
        ArrayAdapter<CharSequence> governorAdapter3 = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapter3
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (String anAvailableGovernors3 : availableGovernors) {
            governorAdapter3.add(anAvailableGovernors3);
        }
        mGovernor3.setAdapter(governorAdapter3);
        mGovernor3.setSelection(Arrays.asList(availableGovernors).indexOf(
                currentGovernor3));
        mGovernor3.setOnItemSelectedListener(new GovListener3());

        /** CPU Governor for core 3 */
        ArrayAdapter<CharSequence> governorAdapter4 = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapter4
                .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (String anAvailableGovernors4 : availableGovernors) {
            governorAdapter4.add(anAvailableGovernors4);
        }
        mGovernor4.setAdapter(governorAdapter4);
        mGovernor4.setSelection(Arrays.asList(availableGovernors).indexOf(
                currentGovernor4));
        mGovernor4.setOnItemSelectedListener(new GovListener4());


        /** CPU Boost */
        if (Helpers.doesFileExist(KRAIT_BOOST)) {
            Switch cpuBoostSwitch = (Switch) findViewById(R.id.krait_boost_switch);
            String cpuBoostState = CPUHelper.readOneLineNotRoot(KRAIT_BOOST);
            if (cpuBoostState.equals("Y"))
                cpuBoostSwitch.setChecked(true);
            else
                cpuBoostSwitch.setChecked(false);

            cpuBoostSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (isChecked)
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo Y > " + KRAIT_BOOST);
                    else
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo N > " + KRAIT_BOOST);
                }
            });

        } else {
            findViewById(R.id.card_krait_boost).setVisibility(View.GONE);
        }

        /** CPU Informations */
        String pvs = "NaN";
        String table = "NaN";
        TextView pvsBinning = (TextView) findViewById(R.id.pvs_bin);
        TextView pvsSpeed = (TextView) findViewById(R.id.pvs_speed);

        if (Helpers.doesFileExist(PVS_BINNING)) {
            String rawTableName = CPUHelper.readOneLineNotRoot(PVS_BINNING);
            rawTableName = rawTableName.replaceAll("[\\D]", "");
            table = rawTableName;
            String[] params = rawTableName.split("");
            if (rawTableName.length() == 3)
                pvs = params[2];
        }

        pvsBinning.setText(getString(R.string.pvs_binning) + " " + pvs);
        pvsSpeed.setText(getString(R.string.freq_table) + " " + table);
    }

    public class GeneralGovListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (govCounterGeneral > 0 && !perCoreGovernor.isChecked()) {
                @SuppressWarnings("ConstantConditions")
                String selected = parent.getItemAtPosition(pos).toString();
                // do this on all cpu's since MSM can have different governors on
                // each cpu
                // and it doesn't hurt other devices to do it

                if (Helpers.doesFileExist(GOVERNOR_ALL_CORES)) {
                    Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > " + GOVERNOR_ALL_CORES);

                } else {
                    for (int i = 0; i < mNumOfCpus; i++) {
                        Helpers.CMDProcessorWrapper.runSuCommand(
                                "busybox echo " + selected + " > " + FIRST_PART_CPU + i + SECOND_PART_GOV
                        );
                        bootPrefs.edit().putString("CORE" + i + "_GOVERNOR", selected).commit();
                    }
                }

            } else {
                govCounterGeneral++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

    public class GovListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (govCounter > 0) {
                @SuppressWarnings("ConstantConditions")
                String selected = parent.getItemAtPosition(pos).toString();
                if (!selected.equals("Core Offline")) {
                    // do this on all cpu's since MSM can have different governors on
                    // each cpu
                    // and it doesn't hurt other devices to do it
                    Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > " + GOVERNOR);
                    bootPrefs.edit().putString("CORE0_GOVERNOR", selected).commit();
                }
            } else {
                govCounter++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {

        }
    }

    public class GovListener2 implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (govCounter2 > 0 && perCoreGovernor.isChecked()) {
                @SuppressWarnings("ConstantConditions")
                String selected = parent.getItemAtPosition(pos).toString();

                // do this on all cpu's since MSM can have different governors on
                // each cpu
                // and it doesn't hurt other devices to do it
                Helpers.CMDProcessorWrapper.runSuCommand(
                        "buysbox echo 1 > " + CPUInterface.CPU1_ONLINE +
                                "\nbusybox echo " + selected + " > " + GOVERNOR2
                );
            } else {
                govCounter2++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

    public class GovListener3 implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (govCounter3 > 0 && perCoreGovernor.isChecked()) {
                @SuppressWarnings("ConstantConditions")
                String selected = parent.getItemAtPosition(pos).toString();

                // do this on all cpu's since MSM can have different governors on
                // each cpu
                // and it doesn't hurt other devices to do it
                Helpers.CMDProcessorWrapper.runSuCommand(
                        "buysbox echo 1 > " + CPUInterface.CPU2_ONLINE +
                                "\nbusybox echo " + selected + " > " + GOVERNOR3
                );
                bootPrefs.edit().putString("CORE2_GOVERNOR", selected).commit();
            } else {
                govCounter3++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

    public class GovListener4 implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (govCounter4 > 0 && perCoreGovernor.isChecked()) {
                @SuppressWarnings("ConstantConditions")
                String selected = parent.getItemAtPosition(pos).toString();

                // do this on all cpu's since MSM can have different governors on
                // each cpu
                // and it doesn't hurt other devices to do it
                Helpers.CMDProcessorWrapper.runSuCommand(
                        "buysbox echo 1 > " + CPUInterface.CPU3_ONLINE +
                                "\nbusybox echo " + selected + " > " + GOVERNOR4
                );
                bootPrefs.edit().putString("CORE3_GOVERNOR", selected).commit();
            } else {
                govCounter4++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

//    public class IOListener implements OnItemSelectedListener {
//        public void onItemSelected(AdapterView<?> parent, View view, int pos,
//                                   long id) {
//            if (schedCounter > 0) {
//                String selected = CPUHelper.getAvailableIOSchedulers()[pos];
//                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > " + IO_SCHEDULER);
//                bootPrefs.edit().putString("IO_SCHEDULER", selected).commit();
//            } else {
//                schedCounter++;
//            }
//        }
//
//        public void onNothingSelected(AdapterView<?> parent) {
//        }
//    }

    public class TCPListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (tcpCounter > 0) {
                String selected = Helpers.getTcpAlgorithms().get(pos);
                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > " + CURR_TCP_ALGORITHM + " && "
                        + SYSCTL_TCP_ALGORITHM + selected);
                bootPrefs.edit().putString("TCP_ALGORITHM", selected).commit();
            } else {
                tcpCounter++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mCurCPUThread == null) {
            mCurCPUThread = new CurCPUThread();
            mCurCPUThread.start();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mCurCPUThread.isAlive()) {
            mCurCPUThread.interrupt();
            try {
                mCurCPUThread.join();
            } catch (InterruptedException ignored) {
            }
        }
    }

    public void setMaxSpeed(SeekBar seekBar, int progress) {
        String current;
        current = availableFrequencies[progress];
        int minSliderProgress = mMinSlider.getProgress();
        if (progress <= minSliderProgress) {
            mMinSlider.setProgress(progress);
            mMinSpeedText.setText(toMHz(current));
            mMinFreqSetting = current;
        }
        mMaxSpeedText.setText(toMHz(current));
        mMaxFreqSetting = current;
    }

    public void setMinSpeed(SeekBar seekBar, int progress) {
        String current;
        current = availableFrequencies[progress];
        int maxSliderProgress = mMaxSlider.getProgress();
        if (progress >= maxSliderProgress) {
            mMaxSlider.setProgress(progress);
            mMaxSpeedText.setText(toMHz(current));
            mMaxFreqSetting = current;
        }
        mMinSpeedText.setText(toMHz(current));
        mMinFreqSetting = current;
    }

    // Convert raw collected values to formatted MhZ
    private static String toMHz(String mhzString) {
        try {
            if (Integer.valueOf(mhzString) != null) {
                int val = 0;
                try {
                    val = Integer.valueOf(mhzString);
                } catch (NumberFormatException e) {
                    Log.e("ToMHZ", e.getMessage());
                }
                return String.valueOf(val / 1000) + " MHz";
            } else
                return "NaN";
        } catch (NumberFormatException e) {
            Log.e("CPU-toMHz", e.getMessage());
            return "NaN";
        }
    }

    // Read current frequency from /sys in a separate thread
    protected class CurCPUThread extends Thread {
        private boolean mInterrupt = false;

        public void interrupt() {
            mInterrupt = true;
        }

        @Override
        public void run() {
            try {
                while (!mInterrupt) {
                    sleep(750);
                    String curFreq = "";
                    if (Helpers.doesFileExist(CURRENT_CPU))
                        curFreq = CPUHelper.readOneLineNotRoot(CURRENT_CPU);

                    mCurCPUHandler.sendMessage(mCurCPUHandler.obtainMessage(0,
                            curFreq));
                }
            } catch (InterruptedException e) {
                Log.e("CPU Thread", e.getMessage());
            }
        }

    }


    // Update real-time current frequency & stats in a separate thread
    protected static Handler mCurCPUHandler = new Handler() {
        public void handleMessage(Message msg) {
            try {
                mCurFreq.setText(toMHz((String) msg.obj));
                currX += 1;
                final int p = Integer.parseInt((String) msg.obj);
                counter++;
                addStatPoint(currX, p, line, graph);
                ArrayList<LinePoint> array = line.getPoints();
                if (line.getSize() > 10)
                    array.remove(0);
                line.setPoints(array);

                // Reset the line every 50 updates of the current frequency
                // to make-up for the lack of garbage collection in the
                // HoloGraph card
                if (counter == 50) {
                    graph.removeAllLines();
                    line = new Line();
                    LinePoint point = new LinePoint();
                    point.setX(currX);
                    point.setY(1);
                    line.addPoint(point);
                    line.setColor(Color.parseColor("#FFBB33"));
                    graph.addLine(line);
                    counter = 0;
                }
            } catch (NumberFormatException e) {
                Log.e("CPUHandler", e.getMessage());
            }
        }
    };

    // Static method to add new point to the graph
    public static void addStatPoint(int X, int Y, Line line, LineGraph graph) {
        LinePoint point = new LinePoint();
        point.setX(X);
        point.setY(Y);
        line.addPoint(point);
        graph.addLine(line);
    }

    public void onlineCoresPolling() {
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                String cores = CPUHelper.readOneLineNotRoot(OFFLINE_CPUS);
                String displayed;
                if (cores.equals("1-3"))
                    displayed = "1/4";
                else if (cores.equals("2-3"))
                    displayed = "2/4";
                else if (cores.equals("3-3"))
                    displayed = "3/4";
                else
                    displayed = "4/4";
                mCoresOnline.setText("Cores Online: " + displayed);
                onlineCoresPolling();
            }

        }, 125);
    }
} public class GPUActivity extends ActionBarActivity {

    private static SharedPreferences preferences, bootPrefs;

    private static LineGraph graph;
    private static Line line;
    private static int currX = 0;
    private static int counter = 0;
    private static TextView mCurFreq;
    private SeekBar mMaxSlider;
    private SeekBar mMinSlider;
    private TextView mMaxSpeedText;
    private TextView mMinSpeedText;
    private String[] availableFrequencies;
    private String mMaxFreqSetting;
    private String mMinFreqSetting;
    private CurCPUThread mCurCPUThread;
    private int spinnerCounter = 0;

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                Intent back = new Intent(this, MainActivity.class);
                back.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(back);

            default:
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_gpu_control));
        setContentView(R.layout.card_gpu_control);
        preferences = PreferenceManager.getDefaultSharedPreferences(this);
        bootPrefs = getSharedPreferences("BOOT_PREFS", 0);

        graph = (LineGraph) findViewById(R.id.graph);
        line = new Line();
        LinePoint point = new LinePoint();
        point.setX(currX);
        point.setY(1);
        line.addPoint(point);
        line.setColor(Color.parseColor("#FFBB33"));
        graph.addLine(line);
        graph.setLineToFill(0);

        availableFrequencies = new String[0];
        String availableFrequenciesLine = "";
        if (Helpers.doesFileExist(GPUInterface.availableFreqs)) {
            availableFrequenciesLine = CPUHelper.readOneLineNotRoot(GPUInterface.availableFreqs);
            if (availableFrequenciesLine != null) {
                availableFrequencies = availableFrequenciesLine.split(" ");
                Arrays.sort(availableFrequencies, new Comparator<String>() {
                    @Override
                    public int compare(String object1, String object2) {
                        return Integer.valueOf(object1).compareTo(
                                Integer.valueOf(object2));
                    }
                });
            }
        }

        int frequenciesNum = availableFrequencies.length - 1;

        String currentGovernor = "";
        if (Helpers.doesFileExist(GPUInterface.currGovernor))
            currentGovernor = CPUHelper.readOneLineNotRoot(GPUInterface.currGovernor);

        String curMaxSpeed = "";
        if (Helpers.doesFileExist(GPUInterface.maxFreq))
            curMaxSpeed = CPUHelper.readOneLineNotRoot(GPUInterface.maxFreq);

        String curMinSpeed = "";
        if (Helpers.doesFileExist(GPUInterface.minFreq))
            curMinSpeed = CPUHelper.readOneLineNotRoot(GPUInterface.minFreq);

        mCurFreq = (TextView) findViewById(R.id.currspeed);

        mMaxSlider = (SeekBar) findViewById(R.id.max_slider);
        mMaxSlider.setMax(frequenciesNum);
        mMaxSpeedText = (TextView) findViewById(R.id.max_speed_text);
        mMaxSpeedText.setText(toMHz(curMaxSpeed));
        mMaxSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
                curMaxSpeed));
        mMaxSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser)
                    setMaxSpeed(seekBar, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (mMaxFreqSetting != null && !mMaxFreqSetting.isEmpty()) {
                    Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMaxFreqSetting + " > "
                            + GPUInterface.maxFreq);
                    bootPrefs.edit().putString("GPU_MAX_FREQ", mMaxFreqSetting).commit();
                }
            }
        });

        mMinSlider = (SeekBar) findViewById(R.id.min_slider);
        mMinSlider.setMax(frequenciesNum);
        mMinSpeedText = (TextView) findViewById(R.id.min_speed_text);
        mMinSpeedText.setText(toMHz(curMinSpeed));
        mMinSlider.setProgress(Arrays.asList(availableFrequencies).indexOf(
                curMinSpeed));
        mMinSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser)
                    setMinSpeed(seekBar, progress);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                if (mMinFreqSetting != null && !mMinFreqSetting.isEmpty()) {
                    Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + mMinFreqSetting + " > "
                            + GPUInterface.minFreq);
                    bootPrefs.edit().putString("GPU_MIN_FREQ", mMinFreqSetting).commit();
                }
            }
        });

        Spinner mGovernor = (Spinner) findViewById(R.id.governor);
        String[] availableGovernors = new String[]{"No GPU Governors Found!"};
        if (Helpers.doesFileExist(GPUInterface.availableGovernors))
            availableGovernors = CPUHelper.readOneLineNotRoot(GPUInterface.availableGovernors)
                    .split(" ");
        ArrayAdapter<CharSequence> governorAdapter = new ArrayAdapter<CharSequence>(
                this, R.layout.spinner_row);
        governorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (int i = 0; i < availableGovernors.length; i++) {
            governorAdapter.add(availableGovernors[i]);
        }
        mGovernor.setAdapter(governorAdapter);
        mGovernor.setSelection(Arrays.asList(availableGovernors).indexOf(
                currentGovernor));
        mGovernor.setOnItemSelectedListener(new GovListener());
    }

    public class GovListener implements OnItemSelectedListener {
        public void onItemSelected(AdapterView<?> parent, View view, int pos,
                                   long id) {
            if (spinnerCounter > 0) {
                String selected = parent.getItemAtPosition(pos).toString();

                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + selected + " > "
                        + GPUInterface.currGovernor);

                bootPrefs.edit().putString("GPU_GOVERNOR", selected).commit();

                final SharedPreferences.Editor editor = preferences.edit();
                editor.putString("GPU_GOVERNOR", selected);
                editor.commit();
            } else {
                spinnerCounter++;
            }
        }

        public void onNothingSelected(AdapterView<?> parent) {
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mCurCPUThread == null) {
            mCurCPUThread = new CurCPUThread();
            mCurCPUThread.start();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mCurCPUThread.isAlive()) {
            mCurCPUThread.interrupt();
            try {
                mCurCPUThread.join();
            } catch (InterruptedException e) {
            }
        }
    }

    public void setMaxSpeed(SeekBar seekBar, int progress) {
        String current;
        current = availableFrequencies[progress];
        int minSliderProgress = mMinSlider.getProgress();
        if (progress <= minSliderProgress && !current.isEmpty()) {
            mMinSlider.setProgress(progress);
            mMinSpeedText.setText(toMHz(current));
            mMinFreqSetting = current;
        }
        mMaxSpeedText.setText(toMHz(current));
        mMaxFreqSetting = current;
        final SharedPreferences.Editor editor = preferences.edit();
        editor.putString(GPUInterface.maxFreq, current);
        editor.commit();
    }

    public void setMinSpeed(SeekBar seekBar, int progress) {
        String current;
        current = availableFrequencies[progress];
        int maxSliderProgress = mMaxSlider.getProgress();
        if (progress >= maxSliderProgress) {
            mMaxSlider.setProgress(progress);
            mMaxSpeedText.setText(toMHz(current));
            mMaxFreqSetting = current;
        }
        mMinSpeedText.setText(toMHz(current));
        mMinFreqSetting = current;
        final SharedPreferences.Editor editor = preferences.edit();
        editor.putString(GPUInterface.minFreq, current);
        editor.commit();
    }

    // Convert raw collected values to formatted MhZ
    private static String toMHz(String mhzString) {
        try {
            if (Integer.valueOf(mhzString) != null) {
                int val = 0;
                try {
                    val = Integer.valueOf(mhzString);
                } catch (NumberFormatException e) {
                    Log.e("ToMHZ", e.getMessage());
                }
                return String.valueOf(val / 1000000) + " MHz";
            } else
                return "NaN";
        } catch (NumberFormatException e) {
            Log.e("CPU-toMHz", e.getMessage());
            return "NaN";
        }
    }

    // Read current frequency from /sys in a separate thread
    protected class CurCPUThread extends Thread {
        private boolean mInterrupt = false;

        public void interrupt() {
            mInterrupt = true;
        }

        @Override
        public void run() {
            try {
                while (!mInterrupt) {
                    sleep(1000);
                    final String curFreq = CPUHelper.readOneLineNotRoot(GPUInterface.currFreq);
                    mCurCPUHandler.sendMessage(mCurCPUHandler.obtainMessage(0,
                            curFreq));
                }
            } catch (InterruptedException e) {
                Log.e("GPU Thread", e.getMessage());
            }
        }
    }


    // Update real-time current frequency & stats in a separate thread
    protected static Handler mCurCPUHandler = new Handler() {
        public void handleMessage(Message msg) {
            try {
                mCurFreq.setText(toMHz((String) msg.obj));
                currX += 1;
                final int p = Integer.parseInt((String) msg.obj);

                new Thread(new Runnable() {
                    public void run() {
                        counter++;
                        addStatPoint(currX, p, line, graph);
                        ArrayList<LinePoint> array = line.getPoints();
                        if (line.getSize() > 10)
                            array.remove(0);
                        line.setPoints(array);

                        // Reset the line every 50 updates of the current frequency
                        // to make-up for the lack of garbage collection in the
                        // HoloGraph pluggable
                        if (counter == 50) {
                            graph.removeAllLines();
                            line = new Line();
                            LinePoint point = new LinePoint();
                            point.setX(currX);
                            point.setY(1);
                            line.addPoint(point);
                            line.setColor(Color.parseColor("#FFBB33"));
                            graph.addLine(line);
                            counter = 0;
                        }
                    }
                }).start();
            } catch (NumberFormatException e) {
                Log.e("GPUHandler", e.getMessage());
            }
        }
    };

    // Static method to add new point to the graph
    public static void addStatPoint(int X, int Y, Line line, LineGraph graph) {
        LinePoint point = new LinePoint();
        point.setX(X);
        point.setY(Y);
        line.addPoint(point);
        graph.addLine(line);
    }
} public class IOTweaksActivity extends ActionBarActivity implements IOTweaksInterface {
    int schedCounter = 0, schedCounter1 = 0, readaheadCounter = 0, readaheadCounter1 = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_io_tweaks));
        setContentView(R.layout.cardsui);

        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);
        CardUI cardsUI = (CardUI) findViewById(R.id.cardsui);
        cardsUI.addStack(new CardStack(""));
        cardsUI.addStack(new CardStack(""));

        if (Helpers.doesFileExist(DYNAMIC_FSYNC_TOGGLE)) {
            cardsUI.addCard(new CardSwitchPlugin(
                    getString(R.string.dynamic_fsync),
                    getString(R.string.dynamic_fsync_desc) +
                            getString(R.string.dynamic_fsync_version) + CPUHelper.readOneLine(DYNAMIC_FSYNC_VERSION) + "\'",
                    "#1abc9c",
                    DYNAMIC_FSYNC_TOGGLE,
                    this,
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                            bootPrefs.edit().putBoolean("DYNAMIC_FSYNC", isOn).commit();
                            if (isOn)
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + DYNAMIC_FSYNC_TOGGLE);
                            else
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + DYNAMIC_FSYNC_TOGGLE);
                        }
                    }
            ));
        } else {
            cardsUI.addCard(new CardSwitchDisabled(
                            getString(R.string.dynamic_fsync),
                            getString(R.string.dyn_fsync_unsupported),
                            "#c74b46",
                            "",
                            this,
                            null)
            );
        }

        if (Helpers.doesFileExist(IO_SCHEDULER)) {
            final ArrayList<String> ioScheds = CPUHelper.getAvailableIOSchedulers();
            cardsUI.addCard(new CardSpinner(getString(R.string.io_sched_emmc),
                    getString(R.string.io_sched_emmc_desc),
                    "#1abc9c",
                    IO_SCHEDULER,
                    ioScheds.indexOf(CPUHelper.getIOScheduler()),
                    ioScheds,
                    this,
                    new AdapterView.OnItemSelectedListener() {

                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                            if (schedCounter > 0) {
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + ioScheds.get(position) + " > " + IO_SCHEDULER);
                                bootPrefs.edit().putString("IO_SCHEDULER", ioScheds.get(position)).commit();
                            }
                            schedCounter++;
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> parent) {

                        }
                    }
            ));
        }

        if (Helpers.doesFileExist(IO_SCHEDULER_SD)) {
            final ArrayList<String> ioScheds = CPUHelper.getAvailableIOSchedulersSD();
            cardsUI.addCard(new CardSpinner(getString(R.string.io_sched_sd),
                    getString(R.string.io_sched_sd_desc),
                    "#1abc9c",
                    IO_SCHEDULER_SD,
                    ioScheds.indexOf(CPUHelper.getIOSchedulerSD()),
                    ioScheds,
                    this,
                    new AdapterView.OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                            if (schedCounter1 > 0) {
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + ioScheds.get(position) + " > " + IO_SCHEDULER_SD);
                                bootPrefs.edit().putString("IO_SCHEDULER_SD", ioScheds.get(position)).commit();
                            }
                            schedCounter1++;
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> parent) {

                        }
                    }
            ));
        }

        if (Helpers.doesFileExist(EMMC_READAHEAD)) {
            final ArrayList<String> steps = new ArrayList<String>();
            steps.add("128");
            steps.add("256");
            steps.add("384");
            steps.add("512");
            steps.add("768");
            steps.add("1024");
            steps.add("1280");
            steps.add("1536");
            steps.add("1792");
            steps.add("2048");
            steps.add("3072");
            steps.add("4096");
            String currStep = CPUHelper.readOneLineNotRoot(EMMC_READAHEAD);
            int currIndex = steps.indexOf(currStep);
            cardsUI.addCard(new CardSpinner(getString(R.string.emmc_readahead),
                    getString(R.string.emmc_readahead_desc),
                    "#1abc9c",
                    EMMC_READAHEAD,
                    currIndex,
                    steps,
                    this,
                    new AdapterView.OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                            if (readaheadCounter > 0) {
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + steps.get(position) + " > " + EMMC_READAHEAD);
                                bootPrefs.edit().putString("EMMC_READAHEAD", steps.get(position)).commit();
                            }
                            readaheadCounter++;
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> parent) {

                        }
                    }
            ));
        }

        if (Helpers.doesFileExist(SD_READAHEAD)) {
            final ArrayList<String> steps = new ArrayList<String>();
            steps.add("128");
            steps.add("256");
            steps.add("384");
            steps.add("512");
            steps.add("768");
            steps.add("1024");
            steps.add("1280");
            steps.add("1536");
            steps.add("1792");
            steps.add("2048");
            steps.add("3072");
            steps.add("4096");
            String currStep = CPUHelper.readOneLineNotRoot(SD_READAHEAD);
            int currIndex = steps.indexOf(currStep);
            cardsUI.addCard(new CardSpinner(getString(R.string.sdcard_readahead),
                    getString(R.string.sdcard_readahead_desc),
                    "#1abc9c",
                    SD_READAHEAD,
                    currIndex,
                    steps,
                    this,
                    new AdapterView.OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                            if (readaheadCounter1 > 0) {
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + steps.get(position) + " > " + SD_READAHEAD);
                                bootPrefs.edit().putString("SD_READAHEAD", steps.get(position)).commit();
                            }
                            readaheadCounter1++;
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> parent) {

                        }
                    }
            ));
        }

        if (Helpers.doesFileExist(EMMC_ENTROPY_CONTRIB)) {
            cardsUI.addCard(new CardSwitchPlugin(
                    getString(R.string.emmc_entropy_contrib),
                    getString(R.string.entropy_contrib_desc),
                    "#1abc9c",
                    EMMC_ENTROPY_CONTRIB,
                    this,
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                            if (isOn)
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + EMMC_ENTROPY_CONTRIB);
                            else
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + EMMC_ENTROPY_CONTRIB);

                            bootPrefs.edit().putBoolean("EMMC_ENTROPY_CONTRIB", isOn).commit();
                        }
                    }
            ));
        }

        if (Helpers.doesFileExist(SD_ENTROPY_CONTRIB)) {
            cardsUI.addCard(new CardSwitchPlugin(
                    getString(R.string.sdcard_entropy_contrib),
                    getString(R.string.entropy_contrib_desc),
                    "#1abc9c",
                    SD_ENTROPY_CONTRIB,
                    this,
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                            if (isOn)
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + SD_ENTROPY_CONTRIB);
                            else
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + SD_ENTROPY_CONTRIB);

                            bootPrefs.edit().putBoolean("SD_ENTROPY_CONTRIB", isOn).commit();
                        }
                    }
            ));
        }

        cardsUI.refresh();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

} public class MemoryManagementActivity extends ActionBarActivity implements MemoryManagementInterface {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_mm));
        setContentView(R.layout.cardsui);

        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);
        CardUI cardsUI = (CardUI) findViewById(R.id.cardsui);
        cardsUI.addStack(new CardStack(""));
        cardsUI.addStack(new CardStack(getString(R.string.ksm_header)));

        // KERNEL SAME-PAGE MERGING
        if (Helpers.doesFileExist(KSM_TOGGLE)) {
            cardsUI.addCard(new CardSwitchPlugin(
                    getString(R.string.ksm),
                    getString(R.string.ksm_desc),
                    "#1abc9c",
                    KSM_TOGGLE,
                    this,
                    new CompoundButton.OnCheckedChangeListener() {
                        @Override
                        public void onCheckedChanged(CompoundButton compoundButton, boolean isOn) {
                            bootPrefs.edit().putBoolean("KSM_ENABLED", isOn).commit();
                            if (isOn)
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + KSM_TOGGLE);
                            else
                                Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + KSM_TOGGLE);
                        }
                    }
            ));

        } else {
            cardsUI.addCard(new CardSwitchDisabled(
                            getString(R.string.ksm),
                            getString(R.string.ksm_unsupported),
                            "#c74b46",
                            "",
                            this,
                            null)
            );
        }

        // KSM PAGES-TO-SCAN
        if (Helpers.doesFileExist(KSM_PAGES_TO_SCAN)) {
            int currPagesToScan = 100;
            try {
                currPagesToScan = Integer.valueOf(CPUHelper.readOneLineNotRoot(KSM_PAGES_TO_SCAN));
            } catch (Exception e) {
                Log.e("KSM_PAGES_TO_SCAN", e.getMessage());
            }

            final CardSeekBarGeneric cardKSMPages = new CardSeekBarGeneric(
                    getString(R.string.ksm_pages_to_scan),
                    getString(R.string.ksm_pages_to_scan_desc),
                    "#1abc9c", "",
                    KSM_PAGES_TO_SCAN,
                    512,
                    currPagesToScan,
                    this,
                    null
            );
            cardsUI.addCard(cardKSMPages);
        }

        // KSM SLEEP TIMER
        if (Helpers.doesFileExist(KSM_SLEEP_TIMER)) {
            int currTimer = 500;
            try {
                currTimer = Integer.valueOf(CPUHelper.readOneLineNotRoot(KSM_SLEEP_TIMER));
            } catch (Exception e) {
                Log.e("KSM_SLEEP_TIMER", e.getMessage());
            }

            cardsUI.addCard(new CardSeekBarGeneric(
                    getString(R.string.ksm_timer),
                    getString(R.string.ksm_timer_desc),
                    "#1abc9c", "ms",
                    KSM_SLEEP_TIMER,
                    2000,
                    currTimer,
                    this,
                    null
            ));
        }

        cardsUI.addStack(new CardStack("VM PARAMETERS"));

        // VFS CACHE PRESSURE
        String currVfs = CMDProcessor.runShellCommand("busybox sysctl " + VFS_CACHE_PRESSURE).getStdout();
        currVfs = currVfs.replaceAll("[\\D]", "");
        int vfs = 50;
        try {
            vfs = Integer.valueOf(currVfs);
        } catch (Exception e) {
            Log.e("VFS_CACHE_PRESSURE", e.getMessage());
        }
        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.vfs_cache_pressure),
                getString(R.string.vfs_cache_pressure_text),
                "#1abc9c",
                "%",
                VFS_CACHE_PRESSURE,
                100,
                vfs,
                this,
                null
        ));

        // VM SWAPPINESS
        String currSwappiness = CMDProcessor.runShellCommand("busybox sysctl " + SWAPPINESS).getStdout();
        currSwappiness = currSwappiness.replaceAll("[\\D]", "");
        int swappiness = 60;
        try {
            swappiness = Integer.valueOf(currSwappiness);
        } catch (Exception e) {
            Log.e("SWAPPINESS", e.getMessage());
        }
        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.swappiness),
                getString(R.string.swappiness_text),
                "#1abc9c",
                "%",
                SWAPPINESS,
                100,
                swappiness,
                this,
                null
        ));

        // VM DIRTY RATIO
        String currDirtyRatio = CMDProcessor.runShellCommand("busybox sysctl " + DIRTY_RATIO).getStdout();
        currDirtyRatio = currDirtyRatio.replaceAll("[\\D]", "");
        int dirtyRatio = 30;
        try {
            dirtyRatio = Integer.valueOf(currDirtyRatio);
        } catch (Exception e) {
            Log.e("DIRTY_RATIO", e.getMessage());
        }
        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.dirty_ratio),
                getString(R.string.dirty_ratio_text),
                "#1abc9c",
                "%",
                DIRTY_RATIO,
                100,
                dirtyRatio,
                this,
                null
        ));

        // VM DIRTY BACKGROUND RATIO
        String currDirtyBgRatio = CMDProcessor.runShellCommand("busybox sysctl " + DIRTY_BG_RATIO).getStdout();
        currDirtyBgRatio = currDirtyBgRatio.replaceAll("[\\D]", "");
        int dirtyBgRatio = 15;
        try {
            dirtyBgRatio = Integer.valueOf(currDirtyBgRatio);
        } catch (Exception e) {
            Log.e("DIRTY_BACKGROUND_RATIO", e.getMessage());
        }

        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.dirty_bg_ratio),
                getString(R.string.dirty_bg_ratio_text),
                "#1abc9c",
                "%",
                DIRTY_BG_RATIO,
                100,
                dirtyBgRatio,
                this,
                null
        ));

        // VM DIRTY WRITEBACK
        String currDirtyWriteback = CMDProcessor.runShellCommand("busybox sysctl " + DIRTY_WRITEBACK_CENTISECS).getStdout();
        currDirtyWriteback = currDirtyWriteback.replaceAll("[\\D]", "");
        int dirtyWriteback = 500;
        try {
            dirtyWriteback = Integer.valueOf(currDirtyWriteback);
        } catch (Exception e) {
            Log.e("DIRTY_WRITEBACK_CENTISECS", e.getMessage());
        }

        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.dirty_writeback),
                getString(R.string.dirty_writeback_text),
                "#1abc9c",
                "cs",
                DIRTY_WRITEBACK_CENTISECS,
                2000,
                dirtyWriteback,
                this,
                null
        ));

        // VM DIRTY EXPIRE
        String currDirtyExpire = CMDProcessor.runShellCommand("busybox sysctl " + DIRTY_EXPIRE_CENTISECS).getStdout();
        currDirtyExpire = currDirtyExpire.replaceAll("[\\D]", "");
        int dirtyExpire = 200;
        try {
            dirtyExpire = Integer.valueOf(currDirtyExpire);
        } catch (Exception e) {
            Log.e("DIRTY_EXPIRE_CENTISECS", e.getMessage());
        }

        cardsUI.addCard(new CardSeekBarSysctl(
                getString(R.string.dirty_expire),
                getString(R.string.dirty_expire_text),
                "#1abc9c",
                "cs",
                DIRTY_EXPIRE_CENTISECS,
                2000,
                dirtyExpire,
                this,
                null
        ));

        cardsUI.refresh();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }
} public class MiscActivity extends ActionBarActivity implements MiscInterface {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_misc));
        setContentView(R.layout.cardsui);

        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);
        CardUI cardsUI = (CardUI) findViewById(R.id.cardsui);
        cardsUI.addStack(new CardStack(""));
        cardsUI.addStack(new CardStack(""));

        if (Helpers.doesFileExist(VIBRATOR_SYSFS))
            cardsUI.addCard(new CardSeekBarVibrator(getString(R.string.vibrator_intensity), getString(R.string.vibrator_intensity_text), "#1abc9c", this));

        if (Helpers.doesFileExist(FAST_CHARGE_VERSION)) {

            // Fast Charge Warning
            cardsUI.addStack(new CardStack(getString(R.string.fast_charge_stack)));
            cardsUI.addCard(new CardTextStripe(
                            getString(R.string.fastcharge_warning),
                            getString(R.string.fastcharge_warning_text) + "\n\nFast Charge " + CPUHelper.readOneLineNotRoot(FAST_CHARGE_VERSION),
                            "#F4842D", "#F4842D", false)
            );

            final Boolean[] isManual = {false};
            int currMode = Integer.parseInt(CPUHelper.readOneLineNotRoot(FORCE_FAST_CHARGE));
            if (currMode == 2)
                isManual[0] = true;

            final View[] spinnerView = {null};

            // Fast Charge Mode
            ArrayList<String> modes = new ArrayList<String>();
            modes.add(getString(R.string.disabled));
            modes.add(getString(R.string.fast_charge_force_ac));
            modes.add(getString(R.string.manual));
            cardsUI.addCard(new CardSpinner(
                    getString(R.string.fast_charge_mode),
                    getString(R.string.fast_charge_mode_text),
                    "#1abc9c",
                    FORCE_FAST_CHARGE, Integer.parseInt(CPUHelper.readOneLineNotRoot(FORCE_FAST_CHARGE)),
                    modes,
                    this,
                    new AdapterView.OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                            bootPrefs.edit().putInt("FASTCHARGE_MODE", i).commit();
                            isManual[0] = i == 2;

                            if (spinnerView[0] != null) {
                                if (isManual[0])
                                    spinnerView[0].setEnabled(true);
                                else if (!isManual[0])
                                    spinnerView[0].setEnabled(false);
                            }

                            Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + i + " > " + FORCE_FAST_CHARGE);
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> adapterView) {

                        }
                    }
            ));

            // Fast Charge Level
            final String[] amps = CPUHelper.readOneLineNotRoot(AVAILABLE_FAST_CHARGE_LEVELS).split(" ");
            ArrayList<String> amperages = new ArrayList<String>();
            Collections.addAll(amperages, amps);
            int currLevel = amperages.indexOf(CPUHelper.readOneLineNotRoot(FAST_CHARGE_LEVEL));

            cardsUI.addCard(new CardSpinner(
                    getString(R.string.fast_charge_level),
                    getString(R.string.fast_charge_level_text), "#1abc9c", FAST_CHARGE_LEVEL, currLevel, amperages, this, new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    spinnerView[0] = adapterView;

                    if (isManual[0]) {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + amps[i] + " > " + FAST_CHARGE_LEVEL);
                        bootPrefs.edit().putString("FASTCHARGE_LEVEL", amps[i]).commit();
                        adapterView.setEnabled(true);
                    } else {
                        adapterView.setEnabled(false);
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {

                }
            }
            ));

            if (spinnerView[0] != null) {
                if (isManual[0])
                    spinnerView[0].setEnabled(true);
                else if (!isManual[0])
                    spinnerView[0].setEnabled(false);
            }
        }

        cardsUI.refresh();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

} public class PowerManagementActivity extends ActionBarActivity implements PowerManagementInterface {

    private int spinnerCounter = 0, ecoCoresCounter = 0, alucardCoresCounter = 0, hotplugCounter = 0;
    private Boolean isIntelliPlugOn;
    private LinearLayout mCardIntelliEco, mCardIntelliCores, mCardAlucardCores;
    private Spinner mEcoCoresSpinner;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_power_management));
        setContentView(R.layout.card_power_management);
        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);

        mCardIntelliEco = (LinearLayout) findViewById(R.id.card_intelliplug_eco_mode);
        mCardIntelliCores = (LinearLayout) findViewById(R.id.card_intelliplug_eco_cores);
        mCardAlucardCores = (LinearLayout) findViewById(R.id.card_alucard_cores);

        // Sched MC
        if (Helpers.doesFileExist(SCHED_MC_POWER_SAVINGS)) {
            Spinner schedMcSpinner = (Spinner) findViewById(R.id.sched_mc_spinner);
            ArrayList<String> schedMCEntries = new ArrayList<String>();
            schedMCEntries.add(getString(R.string.disabled));
            schedMCEntries.add(getString(R.string.moderate));
            schedMCEntries.add(getString(R.string.aggressive));
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.spinner_row, schedMCEntries);
            schedMcSpinner.setAdapter(adapter);
            schedMcSpinner.setSelection(Integer.valueOf(CPUHelper.readOneLineNotRoot(SCHED_MC_POWER_SAVINGS)));
            schedMcSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    bootPrefs.edit().putInt("SCHED_MC_LEVEL", i).commit();
                    if (spinnerCounter > 0)
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + i + " > " + SCHED_MC_POWER_SAVINGS);
                    else
                        spinnerCounter++;
                }

                @Override
                public void onNothingSelected(AdapterView<?> adapterView) {

                }
            });
        }

        // Hotplug Driver
        Spinner hotplugDriverSpinner = (Spinner) findViewById(R.id.hotplug_spinner);
        ArrayList<String> availableDrivers = new ArrayList<String>();
        availableDrivers.add("MPDecision");
        Boolean hasIntelliPlug = false;
        Boolean hasAlucardPlug = false;
        int intelliState = 0;
        int alucardState = 0;

        try {
            if (Helpers.doesFileExist(INTELLI_PLUG_TOGGLE)) {
                hasIntelliPlug = true;
                intelliState = Integer.parseInt(CPUHelper.readOneLineNotRoot(INTELLI_PLUG_TOGGLE));
                availableDrivers.add("Intelliplug");
            }

            if (Helpers.doesFileExist(ALUCARD_HOTPLUG_TOGGLE)) {
                hasAlucardPlug = true;
                alucardState = Integer.parseInt(CPUHelper.readOneLineNotRoot(ALUCARD_HOTPLUG_TOGGLE));
                availableDrivers.add("Alucard Hotplug");
            }

            ArrayAdapter<String> hotplugAdapter = new ArrayAdapter<String>(this, R.layout.spinner_row, availableDrivers);
            hotplugDriverSpinner.setAdapter(hotplugAdapter);

            /** If the kernel doesn't have intelliplug nor alucard hotplug */
            if (!hasAlucardPlug && !hasIntelliPlug) {
                // then default to mpdecision
                hotplugDriverSpinner.setSelection(0);

                /** If the kernel has intelliplug but not alucard hotplug */
            } else if (hasIntelliPlug && !hasAlucardPlug) {

                if (intelliState == 1) // If intelliplug is on, intelliplug is the current hotplug driver
                    hotplugDriverSpinner.setSelection(1);
                else
                    hotplugDriverSpinner.setSelection(0); // else it's mpdecision

                /** If the kernel has alucard hotplug but not intelliplug */
            } else if (!hasIntelliPlug) {

                if (alucardState == 1)
                    hotplugDriverSpinner.setSelection(2); // if alucard hotplug is on, then it's the current hotplug driver
                else
                    hotplugDriverSpinner.setSelection(0); // else it's mpdecision

                /** If the kernel has both intelliplug & alucard hotplug */
            } else {
                if (intelliState == 1 && alucardState == 0) // if intelliplug is on & alucard is off, intelliplug is the current driver
                    hotplugDriverSpinner.setSelection(1);
                else if (intelliState == 0 && alucardState == 1) // if alucard is on & intelliplug is off, alucard is the current driver
                    hotplugDriverSpinner.setSelection(2);
                else if (intelliState == 0 && alucardState == 0) // if neither alucard or intelliplug is on, mpdecision is the current driver
                    hotplugDriverSpinner.setSelection(0);
                else if (intelliState == 1 && alucardState == 1) { // if both alucard & intelliplug are on, notifiy the user and default back to mpdecision
                    Toast.makeText(this, getString(R.string.multiple_hotplug_drivers_warning), Toast.LENGTH_LONG).show();
                    hotplugDriverSpinner.setSelection(0);
                    CMDProcessor.runSuCommand("busybox echo 0 > " + INTELLI_PLUG_TOGGLE + "\nbusybox echo 0 > " + ALUCARD_HOTPLUG_TOGGLE + "\nstart mpdecision");
                }
            }

        } catch (Exception e) {
            Log.e("PowerManagement", e.getMessage());
        }

        hotplugDriverSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {

                bootPrefs.edit().putInt("HOTPLUG_DRIVER", pos).commit();
                switch (pos) {
                    case 0:
                        mCardIntelliEco.setVisibility(View.GONE);
                        mCardIntelliCores.setVisibility(View.GONE);
                        mCardAlucardCores.setVisibility(View.GONE);
                        isIntelliPlugOn = false;
                        if (hotplugCounter > 0) {
                            CMDProcessor.runSuCommand("echo 0 > " + INTELLI_PLUG_TOGGLE);
                            CMDProcessor.runSuCommand("echo 0 > " + ALUCARD_HOTPLUG_TOGGLE);
                            CMDProcessor.runSuCommand("start mpdecision");
                        } else hotplugCounter++;
                        break;

                    case 1:
                        mCardAlucardCores.setVisibility(View.GONE);
                        mCardIntelliEco.setVisibility(View.VISIBLE);
                        mCardIntelliCores.setVisibility(View.VISIBLE);
                        isIntelliPlugOn = true;
                        if (hotplugCounter > 0) {
                            CMDProcessor.runSuCommand("echo 0 > " + ALUCARD_HOTPLUG_TOGGLE);
                            CMDProcessor.runSuCommand("stop mpdecision");
                            CMDProcessor.runSuCommand("echo 1 > " + INTELLI_PLUG_TOGGLE);
                        } else hotplugCounter++;
                        break;

                    case 2:
                        mCardIntelliEco.setVisibility(View.GONE);
                        mCardIntelliCores.setVisibility(View.GONE);
                        mCardAlucardCores.setVisibility(View.VISIBLE);
                        isIntelliPlugOn = false;
                        if (hotplugCounter > 0) {
                            CMDProcessor.runSuCommand("echo 0 > " + INTELLI_PLUG_TOGGLE);
                            CMDProcessor.runSuCommand("stop mpdecision");
                            CMDProcessor.runSuCommand("echo 1 > " + ALUCARD_HOTPLUG_TOGGLE);
                        } else hotplugCounter++;
                        break;
                    default:
                        break;
                }
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        // Intelliplug Eco Mode
        if (Helpers.doesFileExist(INTELLI_PLUG_ECO_MODE)) {
            final Switch intelliEcoSwitch = (Switch) findViewById(R.id.intelliplug_eco_switch);
            int currEcoState = Integer.parseInt(CPUHelper.readOneLineNotRoot(INTELLI_PLUG_ECO_MODE));

            if (currEcoState == 0) {
                intelliEcoSwitch.setChecked(false);
                findViewById(R.id.intelliplug_eco_cores_spinner).setEnabled(false);
            } else if (currEcoState == 1) {
                intelliEcoSwitch.setChecked(true);
                findViewById(R.id.intelliplug_eco_cores_spinner).setEnabled(true);
            }

            intelliEcoSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isOn) {
                    bootPrefs.edit().putBoolean("INTELLI_PLUG_ECO", isOn).commit();

                    if (isOn) {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + INTELLI_PLUG_ECO_MODE);
                        findViewById(R.id.intelliplug_eco_cores_spinner).setEnabled(true);
                    } else {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + INTELLI_PLUG_ECO_MODE);
                        findViewById(R.id.intelliplug_eco_cores_spinner).setEnabled(false);
                    }
                }
            });
        }

        // Intelliplug eco cores
        if (Helpers.doesFileExist(INTELLI_PLUG_ECO_CORES)) {
            Spinner intelliEcoCoresSpinner = (Spinner) findViewById(R.id.intelliplug_eco_cores_spinner);
            mEcoCoresSpinner = intelliEcoCoresSpinner;
            ArrayList<String> possibleEcoCores = new ArrayList<String>();
            possibleEcoCores.add("1");
            possibleEcoCores.add("2");
            possibleEcoCores.add("3");
            ArrayAdapter<String> ecoCoresAdapter = new ArrayAdapter<String>(this, R.layout.spinner_row, possibleEcoCores);
            intelliEcoCoresSpinner.setAdapter(ecoCoresAdapter);
            intelliEcoCoresSpinner.setSelection(Integer.parseInt(CPUHelper.readOneLineNotRoot(INTELLI_PLUG_ECO_CORES)) - 1);
            if (!bootPrefs.getBoolean("INTELLI_PLUG_ECO", false))
                intelliEcoCoresSpinner.setEnabled(false);
            intelliEcoCoresSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    int toApply = position + 1;
                    if (ecoCoresCounter > 0) {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + toApply + " > " + INTELLI_PLUG_ECO_CORES);
                        bootPrefs.edit().putInt("INTELLI_PLUG_ECO_CORES", toApply).commit();
                    } else {
                        ecoCoresCounter++;
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }

        // Alucard eco cores
        if (Helpers.doesFileExist(ALUCARD_HOTPLUG_CORES)) {
            final Spinner alucardCoresSpinner = (Spinner) findViewById(R.id.alucard_cores_spinner);
            mEcoCoresSpinner = alucardCoresSpinner;
            ArrayList<String> possibleEcoCores = new ArrayList<String>();
            possibleEcoCores.add("1");
            possibleEcoCores.add("2");
            possibleEcoCores.add("3");
            possibleEcoCores.add("4");
            ArrayAdapter<String> ecoCoresAdapter = new ArrayAdapter<String>(this, R.layout.spinner_row, possibleEcoCores);
            alucardCoresSpinner.setAdapter(ecoCoresAdapter);
            alucardCoresSpinner.setSelection(Integer.parseInt(CPUHelper.readOneLineNotRoot(ALUCARD_HOTPLUG_CORES)) - 1);
            alucardCoresSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    int toApply = position + 1;
                    if (alucardCoresCounter > 0) {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo " + toApply + " > " + ALUCARD_HOTPLUG_CORES);
                        bootPrefs.edit().putInt("ALUCARD_CORES", toApply).commit();
                    } else {
                        alucardCoresCounter++;
                    }
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }

        // Power Suspend
        if (Helpers.doesFileExist(POWER_SUSPEND_TOGGLE)) {
            Switch powerSuspendSwitch = (Switch) findViewById(R.id.power_suspend_switch);
            int isPowerSuspendOn = Integer.parseInt(CPUHelper.readOneLineNotRoot(POWER_SUSPEND_TOGGLE));
            if (isPowerSuspendOn == 0)
                powerSuspendSwitch.setChecked(false);
            else if (isPowerSuspendOn == 1)
                powerSuspendSwitch.setChecked(true);

            powerSuspendSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    bootPrefs.edit().putBoolean("POWER_SUSPEND", isChecked).commit();
                    if (isChecked)
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 1 > " + POWER_SUSPEND_TOGGLE);
                    else {
                        Helpers.CMDProcessorWrapper.runSuCommand("busybox echo 0 > " + POWER_SUSPEND_TOGGLE);
                    }
                }
            });
        } else {
            findViewById(R.id.card_power_suspend).setVisibility(View.GONE);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
        }
        return super.onOptionsItemSelected(item);
    }
} public class VoltageActivity extends ActionBarActivity implements VoltageInterface {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setIcon(getResources().getDrawable(R.drawable.ic_tools_voltage_control));
        setContentView(R.layout.cardsui);

        final SharedPreferences bootPrefs = getSharedPreferences("BOOT_PREFS", 0);
        CardUI cardsUI = (CardUI) findViewById(R.id.cardsui);
        cardsUI.addStack(new CardStack(""));
        cardsUI.addStack(new CardStack(getString(R.string.voltage_control).toUpperCase()));

        if (Helpers.doesFileExist(UV_MV_TABLE)) {
            cardsUI.addCard(
                    new CardTextStripe(
                            getString(R.string.warning),
                            getString(R.string.voltage_warning_text),
                            getString(R.string.play_orange),
                            getString(R.string.play_orange),
                            false
                    )
            );


            final ArrayList<Integer> applicableVoltages = new ArrayList<Integer>();
            for (int i = 500; i < 1100; i += 5) {
                applicableVoltages.add(i);
            }

            String rawUvTable = CPUHelper.readFileViaShell(UV_MV_TABLE, false);
            String[] splitTable = rawUvTable.split("\n");
            final ArrayList<Integer> currentApplicableTable = new ArrayList<Integer>();

            // Counters to avoid applying voltage when launching the activity
            final int[] spinnerCounters = new int[splitTable.length];
            for (int i = 0; i < splitTable.length; i++)
                spinnerCounters[i] = 0;

            Boolean areDefaultsSaved = false;
            String[] defaultTable = new String[splitTable.length];

            if (!bootPrefs.getString("DEFAULT_VOLTAGE_TABLE", "null").equals("null")) {
                areDefaultsSaved = true;
                defaultTable = bootPrefs.getString("DEFAULT_VOLTAGE_TABLE", "null").split(" ");
                Log.e("Default Table", "Def Table Size: " + defaultTable.length + " // Default Table: " + bootPrefs.getString("DEFAULT_VOLTAGE_TABLE", "null"));
            }

            // for each frequency scaling step we add a card
            for (int i = 0; i < splitTable.length; i++) {
                // format each line into a frequency in MHz & a voltage in mV
                String[] separateFreqFromVolts = splitTable[i].split(":");
                String freqLabel = separateFreqFromVolts[0].replace("mhz", " MHz:");
                String intVoltage = separateFreqFromVolts[1].replaceAll("mV", "");
                intVoltage = intVoltage.replaceAll(" ", "");

                int currStepVoltage = Integer.valueOf(intVoltage);
                currentApplicableTable.add(currStepVoltage);
                ArrayList<String> possibleVoltages = new ArrayList<String>();

                if (areDefaultsSaved) {
                    for (int k = 500; k < 1100; k += 5) {
                        if (k == Integer.valueOf(defaultTable[i]))
                            possibleVoltages.add(k + " mV (default)");
                        else
                            possibleVoltages.add(k + " mV");
                    }

                } else {
                    for (int k = 500; k < 1100; k += 5) {
                        if (k == currStepVoltage)
                            possibleVoltages.add(k + " mV (default)");
                        else
                            possibleVoltages.add(k + " mV");
                    }
                }

                int currIndex = possibleVoltages.indexOf(currStepVoltage + " mV (default)");
                if (currIndex == -1)
                    currIndex = possibleVoltages.indexOf(currStepVoltage + " mV");

                final int currStep = i;

                cardsUI.addCard(new CardSpinnerVoltage(
                        "",
                        freqLabel,
                        "#1abc9c",
                        "",
                        currIndex,
                        possibleVoltages,
                        this,
                        new AdapterView.OnItemSelectedListener() {
                            @Override
                            public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long l) {
                                if (spinnerCounters[currStep] > 0) {
                                    String toApply = "busybox echo \"";
                                    String defaultTable = "";
                                    currentApplicableTable.set(currStep, applicableVoltages.get(pos));

                                    for (int j = 0; j < currentApplicableTable.size(); j++) {
                                        if (j == 0) {
                                            toApply += currentApplicableTable.get(j);
                                            defaultTable += currentApplicableTable.get(j);
                                        } else {
                                            toApply += " " + currentApplicableTable.get(j);
                                            defaultTable += " " + currentApplicableTable.get(j);
                                        }
                                    }

                                    toApply += "\" > " + UV_MV_TABLE;
                                    CMDProcessor.runSuCommand(toApply);
                                    bootPrefs.edit().putString("CURRENT_VOLTAGE_TABLE", defaultTable).commit();
                                    Log.e("toApply", toApply);
                                } else spinnerCounters[currStep]++;
                            }

                            @Override
                            public void onNothingSelected(AdapterView<?> adapterView) {

                            }
                        }
                ));
            }

            if (bootPrefs.getString("DEFAULT_VOLTAGE_TABLE", "null").equals("null")) {
                String table = "";
                for (int j = 0; j < currentApplicableTable.size(); j++) {
                    if (j == 0)
                        table += currentApplicableTable.get(j);
                    else
                        table += " " + currentApplicableTable.get(j);
                }
                bootPrefs.edit().putString("DEFAULT_VOLTAGE_TABLE", table).commit();
            }
        }

        cardsUI.refresh();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.voltage, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onBackPressed();
                break;
            case R.id.reset_default:
                String defaultTable = getSharedPreferences("BOOT_PREFS", 0).getString("DEFAULT_VOLTAGE_TABLE", "null");
                if (defaultTable.equals("null"))
                    CMDProcessor.runSuCommand("busybox echo \"" + defaultTable + "\" > " + VoltageInterface.UV_MV_TABLE);
                else
                    Toast.makeText(this, "Default not found!", Toast.LENGTH_LONG).show();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public android.support.v4.app.FragmentManager getSupportFragmentManager() {
        return null;
    }
} public interface VoltageInterface {
    public static final String UV_MV_TABLE = "/sys/devices/system/cpu/cpu0/cpufreq/UV_mV_table";
} public class BalancedProfile extends Profile {

    @Override
    public String getCpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableCPUFreqs();
        prefs.edit().putString("CPU_MAX_FREQ", freqs[freqs.length - 1]).commit();
        return toShell(freqs[freqs.length - 1], CPUInterface.MAX_FREQ) + "\n" + toShell(freqs[freqs.length - 1], CPUInterface.SNAKE_CHARMER_MAX_FREQ);
    }

    @Override
    public String getGpuMaxFreq() {
        prefs.edit().putString("GPU_MAX_FREQ", "450000000").commit();
        return toShell("450000000", GPUInterface.maxFreq);
    }

    @Override
    public String getCPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(CPUInterface.GOVERNORS_LIST).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("intelliactive")) {
            prefs.edit().putString("CORE0_GOVERNOR", "intelliactive").commit();
            return toShell("intelliactive", CPUInterface.GOVERNOR);
        } else if (governors.contains("interactivex2")) {
            prefs.edit().putString("CORE0_GOVERNOR", "interactivex2").commit();
            return toShell("interactivex2", CPUInterface.GOVERNOR);
        } else if (governors.contains("Lionheart")) {
            prefs.edit().putString("CORE0_GOVERNOR", "Lionheart").commit();
            return toShell("Lionheart", CPUInterface.GOVERNOR);
        } else if (governors.contains("lionheart")) {
            prefs.edit().putString("CORE0_GOVERNOR", "lionheart").commit();
            return toShell("lionheart", CPUInterface.GOVERNOR);
        } else if (governors.contains("ondemand")) {
            prefs.edit().putString("CORE0_GOVERNOR", "ondemand").commit();
            return toShell("ondemand", CPUInterface.GOVERNOR);
        } else
            return "";
    }

    @Override
    public String getGPUGovernor() {
        prefs.edit().putString("GPU_GOVERNOR", "msm-adreno-tz").commit();
        return toShell("msm-adreno-tz", GPUInterface.currGovernor);
    }

    @Override
    public String getIOScheduler() {
        ArrayList<String> scheds = CPUHelper.getAvailableIOSchedulers();
        if (scheds.contains("fiops")) {
            prefs.edit().putString("IO_SCHEDULER", "fiops").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "fiops").commit();
            return toShell("fiops", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("sio", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("bfq")) {
            prefs.edit().putString("IO_SCHEDULER", "bfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "bfq").commit();
            return toShell("bfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("bfq", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("cfq")) {
            prefs.edit().putString("IO_SCHEDULER", "cfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "cfq").commit();
            return toShell("cfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("deadline", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("row")) {
            prefs.edit().putString("IO_SCHEDULER", "row").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "row").commit();
            return toShell("row", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("row", IOTweaksInterface.IO_SCHEDULER_SD);
        } else
            return "";
    }

    @Override
    public String isIntelliplugEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG", true).commit();
        return "stop mpdecision\n" + "busybox echo 0 > " + PowerManagementInterface.MSM_MPDECISION_TOGGLE + "\n"
                + toShell("1", PowerManagementInterface.INTELLI_PLUG_TOGGLE);
    }

    @Override
    public String isEcoModeEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG_ECO", false).commit();
        return toShell("0", PowerManagementInterface.INTELLI_PLUG_ECO_MODE);
    }

    @Override
    public String isPowerSuspendEnabled() {
        prefs.edit().putBoolean("POWER_SUSPEND", true).commit();
        return toShell("1", PowerManagementInterface.POWER_SUSPEND_TOGGLE);
    }

    @Override
    public String isKSMEnabled() {
        prefs.edit().putBoolean("KSM_ENABLED", true).commit();
        return toShell("1", MemoryManagementInterface.KSM_TOGGLE);
    }

    @Override
    public String isDynFsyncEnabled() {
        prefs.edit().putBoolean("DYNAMIC_FSYNC", true).commit();
        return toShell("1", IOTweaksInterface.DYNAMIC_FSYNC_TOGGLE);
    }

    @Override
    public String isEntropyContributionEnabled() {
        prefs.edit().putBoolean("EMMC_ENTROPY_CONTRIB", false).commit();
        prefs.edit().putBoolean("SD_ENTROPY_CONTRIB", false).commit();
        return toShell("0", IOTweaksInterface.EMMC_ENTROPY_CONTRIB) + "\n" + toShell("0", IOTweaksInterface.SD_ENTROPY_CONTRIB);
    }

    @Override
    public String schedMCLevel() {
        prefs.edit().putInt("SCHED_MC_LEVEL", 1).commit();
        return toShell("1", PowerManagementInterface.SCHED_MC_POWER_SAVINGS);
    }

    @Override
    public String readahead() {
        prefs.edit().putString("EMMC_READAHEAD", "768").commit();
        prefs.edit().putString("SD_READAHEAD", "768").commit();
        return toShell("768", IOTweaksInterface.EMMC_READAHEAD) + "\n" + toShell("768", IOTweaksInterface.SD_READAHEAD);
    }

    @Override
    public String KSMpagesToScan() {
        prefs.edit().putString("KSM_PAGES_TO_SCAN", "256").commit();
        return toShell("256", MemoryManagementInterface.KSM_PAGES_TO_SCAN);
    }

    @Override
    public String KSMTimer() {
        prefs.edit().putString("KSM_SLEEP_TIMER", "1250").commit();
        return toShell("1250", MemoryManagementInterface.KSM_SLEEP_TIMER);
    }
} public class BatteryMaxProfile extends Profile {

    @Override
    public String getCpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableCPUFreqs();
        prefs.edit().putString("CPU_MAX_FREQ", freqs[freqs.length - 4]).commit();
        return toShell(freqs[freqs.length - 4], CPUInterface.MAX_FREQ) + "\n" + toShell(freqs[freqs.length - 4], CPUInterface.SNAKE_CHARMER_MAX_FREQ);
    }

    @Override
    public String getGpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableGPUFreqs();
        List<String> frequencies = Arrays.asList(freqs);
        if (frequencies.contains("320000000")) {
            prefs.edit().putString("GPU_MAX_FREQ", "320000000").commit();
            return toShell("320000000", GPUInterface.maxFreq);
        } else if (frequencies.size() >= 3) {
            prefs.edit().putString("GPU_MAX_FREQ", frequencies.get(3)).commit();
            return frequencies.get(3);
        } else return "";
    }

    @Override
    public String getCPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(CPUInterface.GOVERNORS_LIST).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("powersave")) {
            prefs.edit().putString("CORE0_GOVERNOR", "powersave").commit();
            return toShell("powersave", CPUInterface.GOVERNOR);
        } else if (governors.contains("conservative")) {
            prefs.edit().putString("CORE0_GOVERNOR", "conservative").commit();
            return toShell("conservative", CPUInterface.GOVERNOR);
        } else if (governors.contains("intellidemand")) {
            prefs.edit().putString("CORE0_GOVERNOR", "intellidemand").commit();
            return toShell("intellidemand", CPUInterface.GOVERNOR);
        } else
            return "";
    }

    @Override
    public String getGPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(GPUInterface.availableGovernors).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("powersave")) {
            prefs.edit().putString("GPU_GOVERNOR", "powersave").commit();
            return toShell("powersave", GPUInterface.currGovernor);
        } else if (governors.contains("simple_ondemand")) {
            prefs.edit().putString("GPU_GOVERNOR", "simple_ondemand").commit();
            return toShell("simple_ondemand", GPUInterface.currGovernor);
        } else if (governors.contains("msm_cpufreq")) {
            prefs.edit().putString("GPU_GOVERNOR", "msm_cpufreq").commit();
            return toShell("msm_cpufreq", GPUInterface.currGovernor);
        } else {
            prefs.edit().putString("GPU_GOVERNOR", "msm-adreno-tz").commit();
            return toShell("msm-adreno-tz", GPUInterface.currGovernor);
        }
    }

    @Override
    public String getIOScheduler() {
        ArrayList<String> scheds = CPUHelper.getAvailableIOSchedulers();
        if (scheds.contains("noop")) {
            prefs.edit().putString("IO_SCHEDULER", "noop").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "noop").commit();
            return toShell("noop", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("noop", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("sio")) {
            prefs.edit().putString("IO_SCHEDULER", "sio").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "sio").commit();
            return toShell("sio", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("sio", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("bfq")) {
            prefs.edit().putString("IO_SCHEDULER", "bfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "bfq").commit();
            return toShell("bfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("bfq", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("deadline")) {
            prefs.edit().putString("IO_SCHEDULER", "deadline").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "deadline").commit();
            return toShell("deadline", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("deadline", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("row")) {
            prefs.edit().putString("IO_SCHEDULER", "row").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "row").commit();
            return toShell("row", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("row", IOTweaksInterface.IO_SCHEDULER_SD);
        } else
            return "";
    }

    @Override
    public String isIntelliplugEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG", true).commit();
        return "stop mpdecision\n" + "busybox echo 0 > " + PowerManagementInterface.MSM_MPDECISION_TOGGLE + "\n"
                + toShell("1", PowerManagementInterface.INTELLI_PLUG_TOGGLE);
    }

    @Override
    public String isEcoModeEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG_ECO", true).commit();
        return toShell("1", PowerManagementInterface.INTELLI_PLUG_ECO_MODE);
    }

    @Override
    public String isPowerSuspendEnabled() {
        prefs.edit().putBoolean("POWER_SUSPEND", true).commit();
        return toShell("1", PowerManagementInterface.POWER_SUSPEND_TOGGLE);
    }

    @Override
    public String isKSMEnabled() {
        prefs.edit().putBoolean("KSM_ENABLED", false).commit();
        return toShell("0", MemoryManagementInterface.KSM_TOGGLE);
    }

    @Override
    public String isDynFsyncEnabled() {
        prefs.edit().putBoolean("DYNAMIC_FSYNC", false).commit();
        return toShell("0", IOTweaksInterface.DYNAMIC_FSYNC_TOGGLE);
    }

    @Override
    public String isEntropyContributionEnabled() {
        prefs.edit().putBoolean("EMMC_ENTROPY_CONTRIB", false).commit();
        prefs.edit().putBoolean("SD_ENTROPY_CONTRIB", false).commit();
        return toShell("0", IOTweaksInterface.EMMC_ENTROPY_CONTRIB) + "\n" + toShell("0", IOTweaksInterface.SD_ENTROPY_CONTRIB);
    }

    @Override
    public String schedMCLevel() {
        prefs.edit().putInt("SCHED_MC_LEVEL", 2).commit();
        return toShell("2", PowerManagementInterface.SCHED_MC_POWER_SAVINGS);
    }

    @Override
    public String readahead() {
        prefs.edit().putString("EMMC_READAHEAD", "512").commit();
        prefs.edit().putString("SD_READAHEAD", "512").commit();
        return toShell("512", IOTweaksInterface.EMMC_READAHEAD) + "\n" + toShell("512", IOTweaksInterface.SD_READAHEAD);
    }

    @Override
    public String KSMpagesToScan() {
        prefs.edit().putString("KSM_PAGES_TO_SCAN", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_PAGES_TO_SCAN);
    }

    @Override
    public String KSMTimer() {
        prefs.edit().putString("KSM_SLEEP_TIMER", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_SLEEP_TIMER);
    }
} public class BatteryProfile extends Profile {

    @Override
    public String getCpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableCPUFreqs();
        prefs.edit().putString("CPU_MAX_FREQ", freqs[freqs.length - 3]).commit();
        return toShell(freqs[freqs.length - 3], CPUInterface.MAX_FREQ) + "\n" + toShell(freqs[freqs.length - 3], CPUInterface.SNAKE_CHARMER_MAX_FREQ);
    }

    @Override
    public String getGpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableGPUFreqs();
        List<String> frequencies = Arrays.asList(freqs);
        if (frequencies.contains("389000000")) {
            prefs.edit().putString("GPU_MAX_FREQ", "389000000").commit();
            return toShell("389000000", GPUInterface.maxFreq);
        } else if (frequencies.contains("320000000")) {
            prefs.edit().putString("GPU_MAX_FREQ", "320000000").commit();
            return toShell("320000000", GPUInterface.maxFreq);
        } else {
            prefs.edit().putString("GPU_MAX_FREQ", "450000000").commit();
            return toShell("450000000", GPUInterface.maxFreq);
        }
    }

    @Override
    public String getCPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(CPUInterface.GOVERNORS_LIST).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("intellidemand")) {
            prefs.edit().putString("CORE0_GOVERNOR", "intellidemand").commit();
            return toShell("intellidemand", CPUInterface.GOVERNOR) + "\necho 50 > /sys/devices/system/cpu/cpufreq/intellidemand/powersave_bias";
        } else if (governors.contains("lionheart")) {
            prefs.edit().putString("CORE0_GOVERNOR", "lionheart").commit();
            return toShell("lionheart", CPUInterface.GOVERNOR);
        } else if (governors.contains("Lionheart")) {
            prefs.edit().putString("CORE0_GOVERNOR", "Lionheart").commit();
            return toShell("Lionheart", CPUInterface.GOVERNOR);
        } else if (governors.contains("lagfree")) {
            prefs.edit().putString("CORE0_GOVERNOR", "lagfree").commit();
            return toShell("lagfree", CPUInterface.GOVERNOR);
        } else if (governors.contains("conservative")) {
            prefs.edit().putString("CORE0_GOVERNOR", "conservative").commit();
            return toShell("conservative", CPUInterface.GOVERNOR);
        } else
            return "";
    }

    @Override
    public String getGPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(GPUInterface.availableGovernors).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("powersave")) {
            prefs.edit().putString("GPU_GOVERNOR", "powersave").commit();
            return toShell("powersave", GPUInterface.currGovernor);
        } else if (governors.contains("simple_ondemand")) {
            prefs.edit().putString("GPU_GOVERNOR", "simple_ondemand").commit();
            return toShell("simple_ondemand", GPUInterface.currGovernor);
        } else if (governors.contains("msm_cpufreq")) {
            prefs.edit().putString("GPU_GOVERNOR", "msm_cpufreq").commit();
            return toShell("msm_cpufreq", GPUInterface.currGovernor);
        } else {
            prefs.edit().putString("GPU_GOVERNOR", "msm-adreno-tz").commit();
            return toShell("msm-adreno-tz", GPUInterface.currGovernor);
        }
    }

    @Override
    public String getIOScheduler() {
        ArrayList<String> scheds = CPUHelper.getAvailableIOSchedulers();
        if (scheds.contains("sio")) {
            prefs.edit().putString("IO_SCHEDULER", "sio").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "sio").commit();
            return toShell("sio", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("sio", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("bfq")) {
            prefs.edit().putString("IO_SCHEDULER", "bfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "bfq").commit();
            return toShell("bfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("bfq", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("deadline")) {
            prefs.edit().putString("IO_SCHEDULER", "deadline").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "deadline").commit();
            return toShell("deadline", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("deadline", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("row")) {
            prefs.edit().putString("IO_SCHEDULER", "row").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "row").commit();
            return toShell("row", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("row", IOTweaksInterface.IO_SCHEDULER_SD);
        } else
            return "";
    }

    @Override
    public String isIntelliplugEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG", true).commit();
        return "stop mpdecision\n" + "busybox echo 0 > " + PowerManagementInterface.MSM_MPDECISION_TOGGLE + "\n"
                + toShell("1", PowerManagementInterface.INTELLI_PLUG_TOGGLE);
    }

    @Override
    public String isEcoModeEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG_ECO", true).commit();
        return toShell("1", PowerManagementInterface.INTELLI_PLUG_ECO_MODE);
    }

    @Override
    public String isPowerSuspendEnabled() {
        prefs.edit().putBoolean("POWER_SUSPEND", true).commit();
        return toShell("1", PowerManagementInterface.POWER_SUSPEND_TOGGLE);
    }

    @Override
    public String isKSMEnabled() {
        prefs.edit().putBoolean("KSM_ENABLED", false).commit();
        return toShell("0", MemoryManagementInterface.KSM_TOGGLE);
    }

    @Override
    public String isDynFsyncEnabled() {
        prefs.edit().putBoolean("DYNAMIC_FSYNC", false).commit();
        return toShell("0", IOTweaksInterface.DYNAMIC_FSYNC_TOGGLE);
    }

    @Override
    public String isEntropyContributionEnabled() {
        prefs.edit().putBoolean("EMMC_ENTROPY_CONTRIB", false).commit();
        prefs.edit().putBoolean("SD_ENTROPY_CONTRIB", false).commit();
        return toShell("0", IOTweaksInterface.EMMC_ENTROPY_CONTRIB) + "\n" + toShell("0", IOTweaksInterface.SD_ENTROPY_CONTRIB);
    }

    @Override
    public String schedMCLevel() {
        prefs.edit().putInt("SCHED_MC_LEVEL", 2).commit();
        return toShell("2", PowerManagementInterface.SCHED_MC_POWER_SAVINGS);
    }

    @Override
    public String readahead() {
        prefs.edit().putString("EMMC_READAHEAD", "512").commit();
        prefs.edit().putString("SD_READAHEAD", "512").commit();
        return toShell("512", IOTweaksInterface.EMMC_READAHEAD) + "\n" + toShell("512", IOTweaksInterface.SD_READAHEAD);
    }

    @Override
    public String KSMpagesToScan() {
        prefs.edit().putString("KSM_PAGES_TO_SCAN", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_PAGES_TO_SCAN);
    }

    @Override
    public String KSMTimer() {
        prefs.edit().putString("KSM_SLEEP_TIMER", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_SLEEP_TIMER);
    }
} public class BenchmarkProfile extends Profile {
    @Override
    public String getCpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableCPUFreqs();
        return toShell(freqs[freqs.length - 1], CPUInterface.MAX_FREQ) + "\n" + toShell(freqs[freqs.length - 1], CPUInterface.SNAKE_CHARMER_MAX_FREQ);
    }

    @Override
    public String getGpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableGPUFreqs();
        return toShell(freqs[freqs.length - 1], GPUInterface.maxFreq);
    }

    @Override
    public String getCPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(CPUInterface.GOVERNORS_LIST).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("performance"))
            return toShell("performance", CPUInterface.GOVERNOR);
        else if (governors.contains("intelliactive"))
            return toShell("intelliactive", CPUInterface.GOVERNOR);
        else if (governors.contains("wheatley"))
            return toShell("wheatley", CPUInterface.GOVERNOR);
        else if (governors.contains("smartassV2"))
            return toShell("wheatley", CPUInterface.GOVERNOR);
        else if (governors.contains("Lionheart"))
            return toShell("Lionheart", CPUInterface.GOVERNOR);
        else if (governors.contains("lionheart"))
            return toShell("lionheart", CPUInterface.GOVERNOR);
        else if (governors.contains("ondemand"))
            return toShell("ondemand", CPUInterface.GOVERNOR);
        else
            return "";
    }

    @Override
    public String getGPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(GPUInterface.availableGovernors).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("performance"))
            return toShell("performance", GPUInterface.currGovernor);
        else if (governors.contains("msm-adreno-tz"))
            return toShell("msm-adreno-tz", GPUInterface.currGovernor);
        else
            return "";
    }

    @Override
    public String getIOScheduler() {
        ArrayList<String> scheds = CPUHelper.getAvailableIOSchedulers();
        if (scheds.contains("fiops"))
            return toShell("fiops", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("sio", IOTweaksInterface.IO_SCHEDULER_SD);
        else if (scheds.contains("bfq"))
            return toShell("bfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("bfq", IOTweaksInterface.IO_SCHEDULER_SD);
        else if (scheds.contains("cfq"))
            return toShell("cfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("deadline", IOTweaksInterface.IO_SCHEDULER_SD);
        else if (scheds.contains("row"))
            return toShell("row", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("row", IOTweaksInterface.IO_SCHEDULER_SD);
        else
            return "";
    }

    @Override
    public String isIntelliplugEnabled() {
        return "start mpdecision\n" + "busybox echo 1 > " + PowerManagementInterface.MSM_MPDECISION_TOGGLE + "\n"
                + toShell("0", PowerManagementInterface.INTELLI_PLUG_TOGGLE);
    }

    @Override
    public String isEcoModeEnabled() {
        return toShell("0", PowerManagementInterface.INTELLI_PLUG_ECO_MODE);
    }

    @Override
    public String isPowerSuspendEnabled() {
        return toShell("0", PowerManagementInterface.POWER_SUSPEND_TOGGLE);
    }

    @Override
    public String isKSMEnabled() {
        return toShell("1", MemoryManagementInterface.KSM_TOGGLE);
    }

    @Override
    public String isDynFsyncEnabled() {
        return toShell("1", IOTweaksInterface.DYNAMIC_FSYNC_TOGGLE);
    }

    @Override
    public String isEntropyContributionEnabled() {
        return toShell("0", IOTweaksInterface.EMMC_ENTROPY_CONTRIB) + "\n" + toShell("0", IOTweaksInterface.SD_ENTROPY_CONTRIB);
    }

    @Override
    public String schedMCLevel() {
        return toShell("0", PowerManagementInterface.SCHED_MC_POWER_SAVINGS);
    }

    @Override
    public String readahead() {
        return toShell("1280", IOTweaksInterface.EMMC_READAHEAD) + "\n" + toShell("1280", IOTweaksInterface.SD_READAHEAD);
    }

    @Override
    public String KSMpagesToScan() {
        return toShell("512", MemoryManagementInterface.KSM_PAGES_TO_SCAN);
    }

    @Override
    public String KSMTimer() {
        return toShell("500", MemoryManagementInterface.KSM_SLEEP_TIMER);
    }
} public class PerformanceProfile extends Profile {

    @Override
    public String getCpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableCPUFreqs();
        prefs.edit().putString("CPU_MAX_FREQ", freqs[freqs.length - 1]).commit();
        return toShell(freqs[freqs.length - 1], CPUInterface.MAX_FREQ) + "\n" + toShell(freqs[freqs.length - 1], CPUInterface.SNAKE_CHARMER_MAX_FREQ);
    }

    @Override
    public String getGpuMaxFreq() {
        String[] freqs = CPUHelper.getAvailableGPUFreqs();
        prefs.edit().putString("GPU_MAX_FREQ", freqs[freqs.length - 1]).commit();
        return toShell(freqs[freqs.length - 1], GPUInterface.maxFreq);
    }

    @Override
    public String getCPUGovernor() {
        String[] govs = CPUHelper.readOneLineNotRoot(CPUInterface.GOVERNORS_LIST).split(" ");
        List<String> governors = Arrays.asList(govs);
        if (governors.contains("intelliactive")) {
            prefs.edit().putString("CORE0_GOVERNOR", "intelliactive").commit();
            return toShell("intelliactive", CPUInterface.GOVERNOR);
        } else if (governors.contains("wheatley")) {
            prefs.edit().putString("CORE0_GOVERNOR", "wheatley").commit();
            return toShell("wheatley", CPUInterface.GOVERNOR);
        } else if (governors.contains("smartassV2")) {
            prefs.edit().putString("CORE0_GOVERNOR", "smartassV2").commit();
            return toShell("smartassV2", CPUInterface.GOVERNOR);
        } else if (governors.contains("interactivex2")) {
            prefs.edit().putString("CORE0_GOVERNOR", "interactivex2").commit();
            return toShell("interactivex2", CPUInterface.GOVERNOR);
        } else if (governors.contains("badass")) {
            prefs.edit().putString("CORE0_GOVERNOR", "badass").commit();
            return toShell("badass", CPUInterface.GOVERNOR);
        } else if (governors.contains("")) {
            prefs.edit().putString("CORE0_GOVERNOR", "interactive").commit();
            return toShell("interactive", CPUInterface.GOVERNOR);
        } else
            return "";
    }

    @Override
    public String getGPUGovernor() {
        prefs.edit().putString("GPU_GOVERNOR", "msm-adreno-tz").commit();
        return toShell("msm-adreno-tz", GPUInterface.currGovernor);
    }

    @Override
    public String getIOScheduler() {
        ArrayList<String> scheds = CPUHelper.getAvailableIOSchedulers();
        if (scheds.contains("fiops")) {
            prefs.edit().putString("IO_SCHEDULER", "fiops").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "fiops").commit();
            return toShell("fiops", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("sio", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("bfq")) {
            prefs.edit().putString("IO_SCHEDULER", "bfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "bfq").commit();
            return toShell("bfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("bfq", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("cfq")) {
            prefs.edit().putString("IO_SCHEDULER", "cfq").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "cfq").commit();
            return toShell("cfq", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("deadline", IOTweaksInterface.IO_SCHEDULER_SD);
        } else if (scheds.contains("row")) {
            prefs.edit().putString("IO_SCHEDULER", "row").commit();
            prefs.edit().putString("IO_SCHEDULER_SD", "row").commit();
            return toShell("row", IOTweaksInterface.IO_SCHEDULER) + "\n" + toShell("row", IOTweaksInterface.IO_SCHEDULER_SD);
        } else
            return "";
    }

    @Override
    public String isIntelliplugEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG", false).commit();
        return "start mpdecision\n" + "busybox echo 1 > " + PowerManagementInterface.MSM_MPDECISION_TOGGLE + "\n"
                + toShell("0", PowerManagementInterface.INTELLI_PLUG_TOGGLE);
    }

    @Override
    public String isEcoModeEnabled() {
        prefs.edit().putBoolean("INTELLI_PLUG_ECO", false).commit();
        return toShell("0", PowerManagementInterface.INTELLI_PLUG_ECO_MODE);
    }

    @Override
    public String isPowerSuspendEnabled() {
        prefs.edit().putBoolean("POWER_SUSPEND", true).commit();
        return toShell("0", PowerManagementInterface.POWER_SUSPEND_TOGGLE);
    }

    @Override
    public String isKSMEnabled() {
        prefs.edit().putBoolean("KSM_ENABLED", true).commit();
        return toShell("1", MemoryManagementInterface.KSM_TOGGLE);
    }

    @Override
    public String isDynFsyncEnabled() {
        prefs.edit().putBoolean("DYNAMIC_FSYNC", true).commit();
        return toShell("1", IOTweaksInterface.DYNAMIC_FSYNC_TOGGLE);
    }

    @Override
    public String isEntropyContributionEnabled() {
        prefs.edit().putBoolean("EMMC_ENTROPY_CONTRIB", false).commit();
        prefs.edit().putBoolean("SD_ENTROPY_CONTRIB", false).commit();
        return toShell("0", IOTweaksInterface.EMMC_ENTROPY_CONTRIB) + "\n" + toShell("0", IOTweaksInterface.SD_ENTROPY_CONTRIB);
    }

    @Override
    public String schedMCLevel() {
        prefs.edit().putInt("SCHED_MC_LEVEL", 0).commit();
        return toShell("0", PowerManagementInterface.SCHED_MC_POWER_SAVINGS);
    }

    @Override
    public String readahead() {
        prefs.edit().putString("EMMC_READAHEAD", "1024").commit();
        prefs.edit().putString("SD_READAHEAD", "1024").commit();
        return toShell("1024", IOTweaksInterface.EMMC_READAHEAD) + "\n" + toShell("1024", IOTweaksInterface.SD_READAHEAD);
    }

    @Override
    public String KSMpagesToScan() {
        prefs.edit().putString("KSM_PAGES_TO_SCAN", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_PAGES_TO_SCAN);
    }

    @Override
    public String KSMTimer() {
        prefs.edit().putString("KSM_SLEEP_TIMER", "0").commit();
        return toShell("0", MemoryManagementInterface.KSM_SLEEP_TIMER);
    }
} public class ProfileEnabler {
    public static void enableProfile(Profile profile, Context context) {
        profile.setSharedPrefs(context.getSharedPreferences("BOOT_PREFS", 0));
        Helpers.CMDProcessorWrapper.runSuCommand(
                profile.getCpuMaxFreq() + "\n"
                        + profile.getCPUGovernor() + "\n"
                        + profile.getGpuMaxFreq() + "\n"
                        + profile.getGPUGovernor() + "\n"
                        + profile.getIOScheduler() + "\n"
                        + profile.isIntelliplugEnabled() + "\n"
                        + profile.isEcoModeEnabled() + "\n"
                        + profile.isPowerSuspendEnabled() + "\n"
                        + profile.isKSMEnabled() + "\n"
                        + profile.KSMpagesToScan() + "\n"
                        + profile.KSMTimer() + "\n"
                        + profile.isDynFsyncEnabled() + "\n"
                        + profile.isEntropyContributionEnabled() + "\n"
                        + profile.readahead() + "\n"
                        + profile.schedMCLevel()
        );
        SharedPreferences bootPrefs  = context.getSharedPreferences("BOOT_PREFS", 0);
    }
} public abstract class Card extends AbstractCard {

    protected View mCardLayout;
    private OnCardSwiped onCardSwipedListener;
    private OnClickListener mListener;

    public Card() {

    }

    public Card(String title) {
        this.title = title;
    }

    public Card(ActionBarActivity fa) {
        this.fa = fa;
    }

    public Card(String title, String desc) {
        this.title = title;
        this.desc = desc;
    }

    public Card(String title, String desc, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.fa = fa;
    }

    public Card(String title, String desc, String titleColor, TextWatcher textWatcher, View.OnFocusChangeListener focusListener) {
        this.title = title;
        this.desc = desc;
        this.titleColor = titleColor;
        this.textWatcher = textWatcher;
        this.focusListener = focusListener;
    }

    public Card(String title, String desc, String url, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.url = url;
        this.fa = fa;
    }

    public Card(String title, String desc, String type) {
        this.title = title;
        this.desc = desc;
        this.type = type;
    }

    public Card(String title, int image) {
        this.title = title;
        this.image = image;
    }

    public Card(String title, String desc, int image) {
        this.title = title;
        this.desc = desc;
        this.image = image;
    }

    public Card(String title, String desc, String titleColor, int imageRes, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.imageRes = imageRes;
        this.titleColor = titleColor;
        this.fa = fa;
    }

    public Card(String title, String desc, String titleColor,
                String stripeColor, Boolean isClickable) {
        this.title = title;
        this.desc = desc;
        this.titleColor = titleColor;
        this.stripeColor = stripeColor;
        this.isClickable = isClickable;
    }

    public Card(String titlePlay, String description, String color,
                String titleColor, Boolean hasOverflow, Boolean isClickable) {

        this.titlePlay = titlePlay;
        this.description = description;
        this.color = color;
        this.titleColor = titleColor;
        this.hasOverflow = hasOverflow;
        this.isClickable = isClickable;
    }

    public Card(String titlePlay, String description, int imageRes, String titleColor, Boolean hasOverflow,
                Boolean isClickable) {

        this.titlePlay = titlePlay;
        this.description = description;
        this.titleColor = titleColor;
        this.hasOverflow = hasOverflow;
        this.isClickable = isClickable;
        this.imageRes = imageRes;
    }

    public Card(String title, String desc, String titleColor, Boolean hasOverflow,
                Boolean isClickable) {

        this.title = title;
        this.desc = desc;
        this.titleColor = titleColor;
        this.hasOverflow = hasOverflow;
        this.isClickable = isClickable;
    }

    public Card(String title, String desc, String titleColor, String url, int duration, int rating, int likes, int comments) {
        this.title = title;
        this.desc = desc;
        this.titleColor = titleColor;
        this.url = url;
        this.duration = duration;
        this.rating = rating;
        this.likes = likes;
        this.comments = comments;
    }

    // Card with Seekbar & EditText
    public Card(String title, String desc, String unit, int seekBarMax, int seekBarProgress, ActionBarActivity fa, ActionMode.Callback callback) {
        this.title = title;
        this.desc = desc;
        this.unit = unit;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.fa = fa;
        this.callback = callback;
    }

    // Card with Seekbar
    public Card(String title, String desc, String color, String unit, String prop, int seekBarMax, int seekBarProgress, ActionBarActivity fa, SeekBar.OnSeekBarChangeListener seekBarChangeListener) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.unit = unit;
        this.prop = prop;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.fa = fa;
        this.listener = seekBarChangeListener;
    }

    // Card with Seekbar & EditText for PmR build.prop Plugins
    public Card(String title, String desc, String unit, String prop, int seekBarMax, int seekBarProgress, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.unit = unit;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.fa = fa;
        this.prop = prop;
    }


    // Card with Seekbar & EditText for PmR build.prop Plugins
    public Card(String title, String desc, String unit, String prop, int seekBarMax, int seekBarProgress, ActionBarActivity fa, ActionMode.Callback callback) {
        this.title = title;
        this.desc = desc;
        this.unit = unit;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.fa = fa;
        this.prop = prop;
        this.callback = callback;
    }

    // Card with Seekbar & EditText for PmR build.prop Plugins
    public Card(String title, String desc, String color, String unit, String prop, int seekBarMax, int seekBarProgress, int seekBarProgress2, ActionBarActivity fa, ActionMode.Callback callback) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.unit = unit;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.seekBarProgress2 = seekBarProgress2;
        this.fa = fa;
        this.prop = prop;
        this.callback = callback;
    }

    // Card with Seekbar & EditText for PmR build.prop Plugins
    public Card(String title, String desc, String color, String unit, String prop, int seekBarMax, int seekBarProgress, ActionBarActivity fa, ActionMode.Callback callback) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.unit = unit;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.fa = fa;
        this.prop = prop;
        this.callback = callback;
    }

    // Card with Seekbar & EditText for PmR build.prop Plugins
    public Card(String title, String desc, String color, String unit, String prop, int seekBarMin, int seekBarMax, int seekBarProgress, int seekBarProgress2, ActionBarActivity fa, ActionMode.Callback callback) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.unit = unit;
        this.seekbarMin = seekBarMin;
        this.seekBarMax = seekBarMax;
        this.seekBarProgress = seekBarProgress;
        this.seekBarProgress2 = seekBarProgress2;
        this.fa = fa;
        this.prop = prop;
        this.callback = callback;
    }

    // Card with Spinner
    public Card(String title, String desc, ArrayList<String> spinnerEntries, ActionBarActivity fa, AdapterView.OnItemSelectedListener onItemSelectedListener) {
        this.title = title;
        this.desc = desc;
        this.spinnerEntries = spinnerEntries;
        this.fa = fa;
        this.onItemSelectedListener = onItemSelectedListener;
    }

    // Card with Spinner
    public Card(String title, String desc, String prop, ArrayList<String> spinnerEntries, ActionBarActivity fa, AdapterView.OnItemSelectedListener onItemSelectedListener) {
        this.title = title;
        this.desc = desc;
        this.spinnerEntries = spinnerEntries;
        this.fa = fa;
        this.onItemSelectedListener = onItemSelectedListener;
        this.prop = prop;
    }

    // Card with Spinner
    public Card(String title, String desc, String prop, int currentItem, ArrayList<String> spinnerEntries, ActionBarActivity fa, AdapterView.OnItemSelectedListener onItemSelectedListener) {
        this.title = title;
        this.desc = desc;
        this.spinnerEntries = spinnerEntries;
        this.fa = fa;
        this.onItemSelectedListener = onItemSelectedListener;
        this.prop = prop;
        this.currentItem = currentItem;
    }


    // Card with Spinner
    public Card(String title, String desc, String color, String prop, int currentItem, ArrayList<String> spinnerEntries, ActionBarActivity fa, AdapterView.OnItemSelectedListener onItemSelectedListener) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.currentItem = currentItem;
        this.spinnerEntries = spinnerEntries;
        this.fa = fa;
        this.onItemSelectedListener = onItemSelectedListener;
        this.prop = prop;
    }

    // Card with Switch
    public Card(String title, String desc, ActionBarActivity fa, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
        this.title = title;
        this.desc = desc;
        this.fa = fa;
        this.onCheckedChangeListener = onCheckedChangeListener;
    }

    // Card with Switch
    public Card(String title, String desc, String prop, ActionBarActivity fa, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
        this.title = title;
        this.desc = desc;
        this.fa = fa;
        this.prop = prop;
        this.onCheckedChangeListener = onCheckedChangeListener;
    }

    // Card with Switch
    public Card(String title, String desc, String color, String prop, ActionBarActivity fa, CompoundButton.OnCheckedChangeListener onCheckedChangeListener) {
        this.title = title;
        this.desc = desc;
        this.color = color;
        this.fa = fa;
        this.prop = prop;
        this.onCheckedChangeListener = onCheckedChangeListener;
    }

    // Card with Button
    public Card(String title, String desc, String buttonText1, String cmd1, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.buttonText1 = buttonText1;
        this.fa = fa;
        this.cmd1 = cmd1;
    }

    // Card with 2 Buttons
    public Card(String title, String desc, String buttonText1, String buttonText2, String cmd1, String cmd2, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.buttonText1 = buttonText1;
        this.buttonText2 = buttonText2;
        this.fa = fa;
        this.cmd1 = cmd1;
        this.cmd2 = cmd2;
    }

    // Card for downloading files
    public Card(String title, String desc, String url, String filePath, String buttonText1, ActionBarActivity fa) {
        this.title = title;
        this.desc = desc;
        this.fa = fa;
        this.url = url;
        this.filePath = filePath;
        this.buttonText1 = buttonText1;
    }

    // Card with dynamic image loading using Picasso by Square
    public Card(String title, String desc, String titleColor, String url) {
        this.title = title;
        this.desc = desc;
        this.titleColor = titleColor;
        this.url = url;
    }

    public Card(String username, String annotation, String avatarUrl, String imageUrl, String imageTitle, String resharedDesc, String resharedText,
                String resharedFrom, String originalTitle, int plusOnes, Boolean isReshared) {
        this.username = username;
        this.annotation = annotation;
        this.avatarUrl = avatarUrl;
        this.imageUrl = imageUrl;
        this.imageTitle = imageTitle;
        this.resharedDesc = resharedDesc;
        this.resharedText = resharedText;
        this.resharedFrom = resharedFrom;
        this.originalTitle = originalTitle;
        this.plusOnes = plusOnes;
        this.isReshared = isReshared;
    }

    public void setMarginBottom(int marginBottom) {
        this.marginBottom = marginBottom;
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public View getView(Context context, boolean swipable) {

        View view = LayoutInflater.from(context).inflate(getCardLayout(), null);

        mCardLayout = view;

        try {
            if (view != null) ((FrameLayout) view.findViewById(R.id.cardContent))
                    .addView(getCardContent(context));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        // ((TextView) view.findViewById(R.id.title)).setText(this.title);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        int bottom = Utils.convertDpToPixelInt(context, 12);
        lp.setMargins(0, 0, 0, bottom);

        if (view != null) {
            view.setLayoutParams(lp);
            view.setHasTransientState(true);
        }

        return view;
    }

    @SuppressLint("NewApi")
    @Override
    public View getView(Context context) {

        View view = LayoutInflater.from(context).inflate(getCardLayout(), null);

        mCardLayout = view;

        try {
            if (view != null) ((FrameLayout) view.findViewById(R.id.cardContent))
                    .addView(getCardContent(context));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        // ((TextView) view.findViewById(R.id.title)).setText(this.title);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        int bottom = Utils.convertDpToPixelInt(context, 12);
        lp.setMargins(0, 0, 0, bottom);

        if (view != null) {
            view.setLayoutParams(lp);
            view.setHasTransientState(true);
        }

        return view;
    }

    @SuppressLint("NewApi")
    public View getViewLast(Context context) {

        View view = LayoutInflater.from(context).inflate(getLastCardLayout(),
                null);

        mCardLayout = view;

        try {
            if (view != null) ((FrameLayout) view.findViewById(R.id.cardContent))
                    .addView(getCardContent(context));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        // ((TextView) view.findViewById(R.id.title)).setText(this.title);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        int bottom = Utils.convertDpToPixelInt(context, 12);
        lp.setMargins(0, 0, 0, bottom);

        if (view != null) {
            view.setLayoutParams(lp);
            view.setHasTransientState(true);
        }
        return view;
    }

    @SuppressLint("NewApi")
    public View getViewFirst(Context context) {

        View view = LayoutInflater.from(context).inflate(getFirstCardLayout(),
                null);

        mCardLayout = view;

        try {
            if (view != null) ((FrameLayout) view.findViewById(R.id.cardContent))
                    .addView(getCardContent(context));
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

        // ((TextView) view.findViewById(R.id.title)).setText(this.title);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        int bottom = Utils.convertDpToPixelInt(context, 12);
        lp.setMargins(0, 0, 0, bottom);

        if (view != null) {
            view.setLayoutParams(lp);
            view.setHasTransientState(true);
        }

        return view;
    }

    public abstract View getCardContent(Context context);

    public OnClickListener getClickListener() {
        return mListener;
    }

    public void setOnClickListener(OnClickListener listener) {
        mListener = listener;
    }

    public void OnSwipeCard() {
        if (onCardSwipedListener != null)
            onCardSwipedListener.onCardSwiped(this, mCardLayout);
        // TODO: find better implementation to get card-object's used content
        // layout (=> implementing getCardContent());
    }

    public OnCardSwiped getOnCardSwipedListener() {
        return onCardSwipedListener;
    }

    public void setOnCardSwipedListener(OnCardSwiped onEpisodeSwipedListener) {
        this.onCardSwipedListener = onEpisodeSwipedListener;
    }

    protected int getCardLayout() {
        return R.layout.item_card;
    }

    protected int getId() {
        return R.id.cardContent;
    }

    protected int getLastCardLayout() {
        return R.layout.item_card_empty_last;
    }

    protected int getFirstCardLayout() {
        return R.layout.item_play_card_empty_first;
    }

    /**
     * Attempt to reuse convertCardView.  Should not modify convertCardView if it's
     * not compatible.  The implementer should check the card content part and
     * verify that it matches.
     *
     * @param convertCardView the view to convert, with root Id equal to Card.getId()
     * @return true on success, false if not compatible
     */
    public abstract boolean convert(View convertCardView);

    public interface OnCardSwiped {
        public void onCardSwiped(Card card, View layout);
    }

}
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import com.androguide.honamicontrol.R;
import com.androguide.honamicontrol.cards.CardImageLocal;
import com.androguide.honamicontrol.helpers.Helpers;
import com.androguide.honamicontrol.kernel.colorcontrol.ColorControlActivity;
import com.androguide.honamicontrol.kernel.colorcontrol.ColorControlInterface;
import com.androguide.honamicontrol.kernel.cpucontrol.CPUActivity;
import com.androguide.honamicontrol.kernel.gpucontrol.GPUActivity;
import com.androguide.honamicontrol.kernel.iotweaks.IOTweaksActivity;
import com.androguide.honamicontrol.kernel.memory.MemoryManagementActivity;
import com.androguide.honamicontrol.kernel.misc.MiscActivity;
import com.androguide.honamicontrol.kernel.powermanagement.PowerManagementActivity;
import com.androguide.honamicontrol.kernel.voltagecontrol.VoltageActivity;
import com.androguide.honamicontrol.kernel.voltagecontrol.VoltageInterface;
import com.androguide.honamicontrol.profiles.BalancedProfile;
import com.androguide.honamicontrol.profiles.BatteryMaxProfile;
import com.androguide.honamicontrol.profiles.BatteryProfile;
import com.androguide.honamicontrol.profiles.BenchmarkProfile;
import com.androguide.honamicontrol.profiles.PerformanceProfile;
import com.androguide.honamicontrol.profiles.ProfileEnabler;
import com.fima.cardsui.objects.Card;
import com.fima.cardsui.objects.CardStack;
import com.fima.cardsui.views.CardUI;
import java.util.ArrayList;

        gammaControl.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fa.startActivity(new Intent(fa, ColorControlActivity.class));
            }
        });


        CardImageLocal powerManagement = new CardImageLocal(
                fa.getString(R.string.kernel_power_management),
                fa.getString(R.string.kernel_power_management_desc),
                sectionColor,
                R.drawable.ic_tools_power_management,
                fa
        );

        powerManagement.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fa.startActivity(new Intent(fa, PowerManagementActivity.class));
            }
        });

        CardImageLocal ioTweaks = new CardImageLocal(
                fa.getString(R.string.kernel_io_tweaks),
                fa.getString(R.string.kernel_io_tweaks_desc),
                sectionColor,
                R.drawable.ic_tools_io_tweaks,
                fa
        );

        ioTweaks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fa.startActivity(new Intent(fa, IOTweaksActivity.class));
            }
        });

        CardImageLocal mm = new CardImageLocal(
                fa.getString(R.string.memory_management),
                fa.getString(R.string.memory_management_text),
                sectionColor,
                R.drawable.ic_tools_mm,
                fa
        );

        mm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fa.startActivity(new Intent(fa, MemoryManagementActivity.class));
            }
        });

        CardImageLocal misc = new CardImageLocal(
                fa.getString(R.string.kernel_misc),
                fa.getString(R.string.kernel_misc_desc),
                sectionColor,
                R.drawable.ic_tools_misc,
                fa
        );

        misc.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                fa.startActivity(new Intent(fa, MiscActivity.class));
            }
        });

        mCardUI.addCard(cpuControl);

        if (Helpers.doesFileExist(VoltageInterface.UV_MV_TABLE))
            mCardUI.addCard(voltageControl);

        mCardUI.addCard(gpuControl);

        if (Helpers.doesFileExist(ColorControlInterface.GAMMA_KCAL))
            mCardUI.addCard(gammaControl);

        mCardUI.addCard(powerManagement);
        mCardUI.addCard(ioTweaks);
        mCardUI.addCard(mm);
        mCardUI.addCard(misc);
        mCardUI.refresh();
        return ll;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.profiles, menu);
        MenuItem item = menu.findItem(R.id.profile_spinner);
        View spinner = item != null ? item.getActionView() : null;
        if (spinner instanceof android.widget.Spinner) {
            final SharedPreferences profilePrefs = super.getActivity().getSharedPreferences("PROFILES", 0);
            Spinner profiles = (Spinner) spinner;
            profiles.setAdapter(ArrayAdapter.createFromResource(super.getActivity(), R.array.profiles_array, R.layout.spinner_action_row));
            profiles.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

                @Override
                public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                    final int currProfile = profilePrefs.getInt("CURR_PROFILE", 5);
                    ActionBarActivity context = (ActionBarActivity) getActivity();
                    switch (i) {
                        case 0:
                            if (profileCounter > 0 && i != currProfile)
                                ProfileEnabler.enableProfile(new BatteryMaxProfile(), context);
                            profileCounter++;
                            break;
                        case 1:
                            if (profileCounter > 0 && i != currProfile)
                                ProfileEnabler.enableProfile(new BatteryProfile(), context);
                            profileCounter++;
                            break;
                        case 2:
                            if (profileCounter > 0 && i != currProfile)
                                ProfileEnabler.enableProfile(new BalancedProfile(), context);
                            profileCounter++;
                            break;
                        case 3:
                            if (profileCounter > 0 && i != currProfile)
                                ProfileEnabler.enableProfile(new PerformanceProfile(), context);