com.grarak.kerneladiutor.utils.kernel.cpu.CPUFreq.java Source code

Java tutorial

Introduction

Here is the source code for com.grarak.kerneladiutor.utils.kernel.cpu.CPUFreq.java

Source

/*
 * Copyright (C) 2015-2016 Willi Ye <williye97@gmail.com>
 *
 * This file is part of Kernel Adiutor.
 *
 * Kernel Adiutor is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Kernel Adiutor is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Kernel Adiutor.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.grarak.kerneladiutor.utils.kernel.cpu;

import android.content.Context;
import android.util.Log;
import android.util.SparseArray;

import com.grarak.kerneladiutor.R;
import com.grarak.kerneladiutor.fragments.ApplyOnBootFragment;
import com.grarak.kerneladiutor.utils.Device;
import com.grarak.kerneladiutor.utils.Utils;
import com.grarak.kerneladiutor.utils.kernel.cpuhotplug.CoreCtl;
import com.grarak.kerneladiutor.utils.kernel.cpuhotplug.MPDecision;
import com.grarak.kerneladiutor.utils.kernel.cpuhotplug.QcomBcl;
import com.grarak.kerneladiutor.utils.root.Control;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Created by willi on 19.04.16.
 */
public class CPUFreq {

    private static final String CPU_PRESENT = "/sys/devices/system/cpu/present";
    private static final String CUR_FREQ = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq";
    private static final String AVAILABLE_FREQS = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_available_frequencies";
    public static final String TIME_STATE = "/sys/devices/system/cpu/cpufreq/stats/cpu%d/time_in_state";
    public static final String TIME_STATE_2 = "/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state";
    private static final String OPP_TABLE = "/sys/devices/system/cpu/cpu%d/opp_table";

    private static final String CPU_MAX_FREQ = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq";
    private static final String CPU_MAX_FREQ_KT = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq_kt";
    private static final String HARD_CPU_MAX_FREQ = "/sys/kernel/cpufreq_hardlimit/scaling_max_freq";
    private static final String CPU_MIN_FREQ = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq";
    private static final String HARD_CPU_MIN_FREQ = "/sys/kernel/cpufreq_hardlimit/scaling_min_freq";
    private static final String CPU_MAX_SCREEN_OFF_FREQ = "/sys/devices/system/cpu/cpu%d/cpufreq/screen_off_max_freq";
    public static final String CPU_ONLINE = "/sys/devices/system/cpu/cpu%d/online";
    private static final String CPU_MSM_CPUFREQ_LIMIT = "/sys/kernel/msm_cpufreq_limit/cpufreq_limit";
    private static final String CPU_ENABLE_OC = "/sys/devices/system/cpu/cpu%d/cpufreq/enable_oc";
    public static final String CPU_LOCK_FREQ = "/sys/kernel/cpufreq_hardlimit/userspace_dvfs_lock";
    private static final String CPU_SCALING_GOVERNOR = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor";
    private static final String CPU_AVAILABLE_GOVERNORS = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_available_governors";
    private static final String CPU_GOVERNOR_TUNABLES = "/sys/devices/system/cpu/cpufreq/%s";
    private static final String CPU_GOVERNOR_TUNABLES_CORE = "/sys/devices/system/cpu/cpu%d/cpufreq/%s";

    private static int sCpuCount;
    private static int sBigCpu = -1;
    private static int sLITTLECpu = -1;
    public static int sCoreCtlMinCpu;
    private static SparseArray<List<Integer>> sFreqs = new SparseArray<>();
    private static String[] sGovernors;

    private static final String TAG = CPUFreq.class.getSimpleName();

    public static String getGovernorTunablesPath(int cpu, String governor) {
        if (Utils.existFile(Utils.strFormat(CPU_GOVERNOR_TUNABLES_CORE, cpu, governor))) {
            return CPU_GOVERNOR_TUNABLES_CORE.replace("%s", governor);
        } else {
            return Utils.strFormat(CPU_GOVERNOR_TUNABLES, governor);
        }
    }

    public static boolean isOffline(int cpu) {
        return getCurFreq(cpu) == 0;
    }

    public static void applyCpu(String path, String value, int min, int max, Context context) {
        boolean cpulock = Utils.existFile(CPU_LOCK_FREQ);
        if (cpulock) {
            run(Control.write("0", CPU_LOCK_FREQ), null, null);
        }
        boolean mpdecision = MPDecision.supported() && MPDecision.isMpdecisionEnabled();
        if (mpdecision) {
            MPDecision.enableMpdecision(false, null);
        }
        for (int i = min; i <= max; i++) {
            boolean offline = isOffline(i);
            if (offline) {
                onlineCpu(i, true, false, null);
            }
            run(Control.chmod("644", Utils.strFormat(path, i)), null, null);
            run(Control.write(value, Utils.strFormat(path, i)), null, null);
            run(Control.chmod("444", Utils.strFormat(path, i)), null, null);
            if (offline) {
                onlineCpu(i, false, false, null);
            }
        }
        if (mpdecision) {
            MPDecision.enableMpdecision(true, null);
        }
        if (cpulock) {
            run(Control.write("1", CPU_LOCK_FREQ), null, null);
        }
        if (context != null) {
            if (isBigLITTLE()) {
                List<Integer> bigCpus = getBigCpuRange();
                List<Integer> littleCpus = getLITTLECpuRange();
                run("#" + new ApplyCpu(path, value, min, max, bigCpus.toArray(new Integer[bigCpus.size()]),
                        littleCpus.toArray(new Integer[littleCpus.size()]), sCoreCtlMinCpu).toString(), path + min,
                        context);
            } else {
                run("#" + new ApplyCpu(path, value, min, max).toString(), path + min, context);
            }
        }
    }

    public static class ApplyCpu {
        private String mJson;
        private String mPath;
        private String mValue;
        private int mMin;
        private int mMax;

        // big.LITTLE
        private List<Integer> mBigCpus;
        private List<Integer> mLITTLECpus;
        private int mCoreCtlMin;

        private ApplyCpu(String path, String value, int min, int max) {
            try {
                JSONObject main = new JSONObject();
                init(main, path, value, min, max);
                mJson = main.toString();
            } catch (JSONException ignored) {
            }
        }

        private ApplyCpu(String path, String value, int min, int max, Integer[] bigCpus, Integer[] littleCpus,
                int corectlmin) {
            try {
                JSONObject main = new JSONObject();
                init(main, path, value, min, max);

                // big.LITTLE
                JSONArray bigCpusArray = new JSONArray();
                for (int cpu : bigCpus) {
                    bigCpusArray.put(cpu);
                }
                main.put("bigCpus", bigCpusArray);
                mBigCpus = Arrays.asList(bigCpus);

                JSONArray LITTLECpusArray = new JSONArray();
                for (int cpu : littleCpus) {
                    LITTLECpusArray.put(cpu);
                }
                main.put("LITTLECpus", LITTLECpusArray);
                mLITTLECpus = Arrays.asList(littleCpus);

                main.put("corectlmin", mCoreCtlMin = corectlmin);

                mJson = main.toString();
            } catch (JSONException ignored) {
            }
        }

        private void init(JSONObject main, String path, String value, int min, int max) throws JSONException {
            main.put("path", mPath = path);
            main.put("value", mValue = value);
            main.put("min", mMin = min);
            main.put("max", mMax = max);
        }

        public ApplyCpu(String json) {
            try {
                JSONObject main = new JSONObject(json);
                mPath = getString(main, "path");
                mValue = getString(main, "value");
                mMin = getInt(main, "min");
                mMax = getInt(main, "max");

                // big.LITTLE
                Integer[] bigCpus = getIntArray(main, "bigCpus");
                if (bigCpus != null) {
                    mBigCpus = Arrays.asList(bigCpus);
                }

                Integer[] LITTLECpus = getIntArray(main, "LITTLECpus");
                if (LITTLECpus != null) {
                    mLITTLECpus = Arrays.asList(LITTLECpus);
                }

                mCoreCtlMin = getInt(main, "corectlmin");

                mJson = json;
            } catch (JSONException ignored) {
            }
        }

        private Integer[] getIntArray(JSONObject jsonObject, String key) {
            try {
                JSONArray array = jsonObject.getJSONArray(key);
                Integer[] integers = new Integer[array.length()];
                for (int i = 0; i < integers.length; i++) {
                    integers[i] = array.getInt(i);
                }
                return integers;
            } catch (JSONException ignored) {
                return null;
            }
        }

        private String getString(JSONObject jsonObject, String key) {
            try {
                return jsonObject.getString(key);
            } catch (JSONException ignored) {
                return null;
            }
        }

        private int getInt(JSONObject jsonObject, String key) {
            try {
                return jsonObject.getInt(key);
            } catch (JSONException ignored) {
                return -1;
            }
        }

        public int getCoreCtlMin() {
            return mCoreCtlMin;
        }

        public List<Integer> getLITTLECpuRange() {
            return mLITTLECpus;
        }

        public List<Integer> getBigCpuRange() {
            return mBigCpus;
        }

        public boolean isBigLITTLE() {
            return getBigCpuRange() != null && getLITTLECpuRange() != null;
        }

        public int getMax() {
            return mMax;
        }

        public int getMin() {
            return mMin;
        }

        public String getValue() {
            return mValue;
        }

        public String getPath() {
            return mPath;
        }

        public String toString() {
            return mJson;
        }
    }

    public static void setGovernor(String governor, int min, int max, Context context) {
        applyCpu(CPU_SCALING_GOVERNOR, governor, min, max, context);
    }

    public static String getGovernor(boolean forceRead) {
        return getGovernor(getBigCpu(), forceRead);
    }

    public static String getGovernor(int cpu, boolean forceRead) {
        boolean offline = forceRead && isOffline(cpu);
        if (offline) {
            onlineCpu(cpu, true, false, null);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        String value = "";
        if (Utils.existFile(Utils.strFormat(CPU_SCALING_GOVERNOR, cpu))) {
            value = Utils.readFile(Utils.strFormat(CPU_SCALING_GOVERNOR, cpu));
        }

        if (offline) {
            onlineCpu(cpu, false, false, null);
        }
        return value;
    }

    public static List<String> getGovernors() {
        if (sGovernors == null) {
            boolean offline = isOffline(0);
            if (offline) {
                onlineCpu(0, true, false, null);
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if (Utils.existFile(Utils.strFormat(CPU_AVAILABLE_GOVERNORS, 0))) {
                sGovernors = Utils.readFile(Utils.strFormat(CPU_AVAILABLE_GOVERNORS, 0)).split(" ");
            }

            if (offline) {
                onlineCpu(0, false, false, null);
            }
        }
        if (sGovernors == null)
            return getGovernors();
        return Arrays.asList(sGovernors);
    }

    private static int getFreq(int cpu, String path, boolean forceRead) {
        boolean offline = forceRead && isOffline(cpu);
        if (offline) {
            onlineCpu(cpu, true, false, null);

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        int freq = 0;
        String value = Utils.readFile(Utils.strFormat(path, cpu));
        if (value != null)
            freq = Utils.strToInt(value);

        if (offline) {
            onlineCpu(cpu, false, false, null);
        }
        return freq;
    }

    public static void setMaxScreenOffFreq(int freq, int min, int max, Context context) {
        applyCpu(CPU_MAX_SCREEN_OFF_FREQ, String.valueOf(freq), min, max, context);
    }

    public static int getMaxScreenOffFreq(boolean forceRead) {
        return getMaxScreenOffFreq(getBigCpu(), forceRead);
    }

    public static int getMaxScreenOffFreq(int cpu, boolean forceRead) {
        return getFreq(cpu, CPU_MAX_SCREEN_OFF_FREQ, forceRead);
    }

    public static boolean hasMaxScreenOffFreq() {
        return hasMaxScreenOffFreq(getBigCpu());
    }

    public static boolean hasMaxScreenOffFreq(int cpu) {
        return Utils.existFile(Utils.strFormat(CPU_MAX_SCREEN_OFF_FREQ, cpu));
    }

    public static void setMinFreq(int freq, int min, int max, Context context) {
        int maxFreq = getMaxFreq(min, false);
        if (maxFreq != 0 && freq > maxFreq) {
            setMaxFreq(freq, min, max, context);
        }
        if (MSMPerformance.hasCpuMinFreq()) {
            for (int i = min; i <= max; i++) {
                MSMPerformance.setCpuMinFreq(freq, i, context);
            }
        }
        applyCpu(CPU_MIN_FREQ, String.valueOf(freq), min, max, context);
        if (Utils.existFile(HARD_CPU_MIN_FREQ)) {
            run(Control.write(String.valueOf(freq), HARD_CPU_MIN_FREQ), HARD_CPU_MIN_FREQ, context);
        }
    }

    public static int getMinFreq(boolean forceRead) {
        return getMinFreq(getBigCpu(), forceRead);
    }

    public static int getMinFreq(int cpu, boolean forceRead) {
        return getFreq(cpu, CPU_MIN_FREQ, forceRead);
    }

    public static void setMaxFreq(int freq, int min, int max, Context context) {
        if (Utils.existFile(CPU_MSM_CPUFREQ_LIMIT)
                && freq > Utils.strToInt(Utils.readFile(CPU_MSM_CPUFREQ_LIMIT))) {
            run(Control.write(String.valueOf(freq), CPU_MSM_CPUFREQ_LIMIT), CPU_MSM_CPUFREQ_LIMIT, context);
        }
        int minFreq = getMinFreq(min, false);
        if (minFreq != 0 && freq < minFreq) {
            setMinFreq(freq, min, max, context);
        }
        if (Utils.existFile(Utils.strFormat(CPU_ENABLE_OC, 0))) {
            for (int i = min; i <= max; i++) {
                run(Control.write("1", Utils.strFormat(CPU_ENABLE_OC, i)), Utils.strFormat(CPU_ENABLE_OC, i),
                        context);
            }
        }
        if (MSMPerformance.hasCpuMaxFreq()) {
            for (int i = min; i <= max; i++) {
                MSMPerformance.setCpuMaxFreq(freq, i, context);
            }
        }
        if (Utils.existFile(Utils.strFormat(CPU_MAX_FREQ_KT, 0))) {
            applyCpu(CPU_MAX_FREQ_KT, String.valueOf(freq), min, max, context);
        } else {
            applyCpu(CPU_MAX_FREQ, String.valueOf(freq), min, max, context);
        }
        if (Utils.existFile(HARD_CPU_MAX_FREQ)) {
            run(Control.write(String.valueOf(freq), HARD_CPU_MAX_FREQ), HARD_CPU_MAX_FREQ, context);
        }
    }

    public static int getMaxFreq(boolean forceRead) {
        return getMaxFreq(getBigCpu(), forceRead);
    }

    public static int getMaxFreq(int cpu, boolean forceRead) {
        if (Utils.existFile(Utils.strFormat(CPU_MAX_FREQ_KT, cpu))) {
            return getFreq(cpu, CPU_MAX_FREQ_KT, forceRead);
        } else {
            return getFreq(cpu, CPU_MAX_FREQ, forceRead);
        }
    }

    public static List<String> getAdjustedFreq(Context context) {
        return getAdjustedFreq(getBigCpu(), context);
    }

    public static List<String> getAdjustedFreq(int cpu, Context context) {
        List<String> freqs = new ArrayList<>();
        if (getFreqs(cpu) != null) {
            for (int freq : getFreqs(cpu)) {
                freqs.add((freq / 1000) + context.getString(R.string.mhz));
            }
        }
        return freqs;
    }

    public static List<Integer> getFreqs() {
        return getFreqs(getBigCpu());
    }

    public static List<Integer> getFreqs(int cpu) {
        if (sFreqs.indexOfKey(cpu) < 0) {
            if (Utils.existFile(Utils.strFormat(OPP_TABLE, cpu))
                    || Utils.existFile(Utils.strFormat(TIME_STATE, cpu))
                    || Utils.existFile(Utils.strFormat(TIME_STATE_2, cpu))) {
                String file;
                if (Utils.existFile(Utils.strFormat(OPP_TABLE, cpu))) {
                    file = Utils.strFormat(OPP_TABLE, cpu);
                } else if (Utils.existFile(Utils.strFormat(TIME_STATE, cpu))) {
                    file = Utils.strFormat(TIME_STATE, cpu);
                } else {
                    file = Utils.strFormat(TIME_STATE_2, cpu);
                }
                String[] valueArray = Utils.readFile(file).trim().split("\\r?\\n");
                List<Integer> freqs = new ArrayList<>();
                for (String freq : valueArray) {
                    long freqInt = Utils.strToLong(freq.split(" ")[0]);
                    if (file.endsWith("opp_table")) {
                        freqInt /= 1000;
                    }
                    freqs.add((int) freqInt);
                }
                sFreqs.put(cpu, freqs);
            } else if (Utils.existFile(Utils.strFormat(AVAILABLE_FREQS, cpu))) {
                int readcpu = cpu;
                boolean offline = isOffline(cpu);
                if (offline) {
                    onlineCpu(cpu, true, false, null);
                }
                if (!Utils.existFile(Utils.strFormat(Utils.strFormat(AVAILABLE_FREQS, cpu)))) {
                    readcpu = 0;
                }
                String values;
                if ((values = Utils.readFile(Utils.strFormat(AVAILABLE_FREQS, readcpu))) != null) {
                    String[] valueArray = values.split(" ");
                    List<Integer> freqs = new ArrayList<>();
                    for (String freq : valueArray) {
                        freqs.add(Utils.strToInt(freq));
                    }
                    sFreqs.put(cpu, freqs);
                }
                if (offline) {
                    onlineCpu(cpu, false, false, null);
                }
            }
        }
        if (sFreqs.indexOfKey(cpu) < 0) {
            return null;
        }
        List<Integer> freqs = sFreqs.get(cpu);
        Collections.sort(freqs);
        return freqs;
    }

    public static int getCurFreq(int cpu) {
        if (Utils.existFile(Utils.strFormat(CUR_FREQ, cpu))) {
            String value = Utils.readFile(Utils.strFormat(CUR_FREQ, cpu));
            if (value != null) {
                return Utils.strToInt(value);
            }
        }
        return 0;
    }

    public static void onlineCpu(int cpu, boolean online, boolean onlineSys, Context context) {
        onlineCpu(cpu, online, ApplyOnBootFragment.CPU, onlineSys, context);
    }

    public static void onlineCpu(int cpu, boolean online, String category, boolean onlineSys, Context context) {
        if (!onlineSys) {
            if (QcomBcl.supported()) {
                QcomBcl.online(online, category, context);
            }
            if (CoreCtl.hasMinCpus() && getBigCpuRange().contains(cpu)) {
                CoreCtl.setMinCpus(online ? getBigCpuRange().size() : sCoreCtlMinCpu, cpu, category, context);
            }
            if (MSMPerformance.hasMaxCpus()) {
                MSMPerformance.setMaxCpus(online ? getBigCpuRange().size() : -1,
                        online ? getLITTLECpuRange().size() : -1, category, context);
            }
        }
        Control.runSetting(Control.chmod("644", Utils.strFormat(CPU_ONLINE, cpu)), category,
                Utils.strFormat(CPU_ONLINE, cpu) + "chmod644", context);
        Control.runSetting(Control.write(online ? "1" : "0", Utils.strFormat(CPU_ONLINE, cpu)), category,
                Utils.strFormat(CPU_ONLINE, cpu), context);
        Control.runSetting(Control.chmod("444", Utils.strFormat(CPU_ONLINE, cpu)), category,
                Utils.strFormat(CPU_ONLINE, cpu) + "chmod444", context);
    }

    public static List<Integer> getLITTLECpuRange() {
        List<Integer> list = new ArrayList<>();
        if (!isBigLITTLE()) {
            for (int i = 0; i < getCpuCount(); i++) {
                list.add(i);
            }
        } else if (getLITTLECpu() == 0) {
            for (int i = 0; i < getBigCpu(); i++) {
                list.add(i);
            }
        } else {
            for (int i = getLITTLECpu(); i < getCpuCount(); i++) {
                list.add(i);
            }
        }
        return list;
    }

    public static List<Integer> getBigCpuRange() {
        List<Integer> list = new ArrayList<>();
        if (!isBigLITTLE()) {
            for (int i = 0; i < getCpuCount(); i++) {
                list.add(i);
            }
        } else if (getBigCpu() == 0) {
            for (int i = 0; i < getLITTLECpu(); i++) {
                list.add(i);
            }
        } else {
            for (int i = getBigCpu(); i < getCpuCount(); i++) {
                list.add(i);
            }
        }
        return list;
    }

    public static int getLITTLECpu() {
        isBigLITTLE();
        return sLITTLECpu < 0 ? 0 : sLITTLECpu;
    }

    public static int getBigCpu() {
        isBigLITTLE();
        return sBigCpu < 0 ? 0 : sBigCpu;
    }

    public static boolean isBigLITTLE() {
        if (sBigCpu == -1 || sLITTLECpu == -1) {
            if (getCpuCount() <= 4 && !is8996()
                    || (Device.getBoard().startsWith("mt6") && !Device.getBoard().startsWith("mt6595")))
                return false;

            if (is8996()) {
                sBigCpu = 2;
                sLITTLECpu = 0;
            } else {
                List<Integer> cpu0Freqs = getFreqs(0);
                List<Integer> cpu4Freqs = getFreqs(4);
                if (cpu0Freqs != null && cpu4Freqs != null) {
                    int cpu0Max = cpu0Freqs.get(cpu0Freqs.size() - 1);
                    int cpu4Max = cpu4Freqs.get(cpu4Freqs.size() - 1);
                    if (cpu0Max > cpu4Max || (cpu0Max == cpu4Max && cpu0Freqs.size() > cpu4Freqs.size())) {
                        sBigCpu = 0;
                        sLITTLECpu = 4;
                    } else {
                        sBigCpu = 4;
                        sLITTLECpu = 0;
                    }
                }
            }

            if (sBigCpu == -1 || sLITTLECpu == -1) {
                sBigCpu = -2;
                sLITTLECpu = -2;
            }
        }

        return sBigCpu >= 0 && sLITTLECpu >= 0;
    }

    private static boolean is8996() {
        String board = Device.getBoard();
        return board.equalsIgnoreCase("msm8996") || board.equalsIgnoreCase("msm8996pro");
    }

    public static int getCpuCount() {
        if (sCpuCount == 0 && Utils.existFile(CPU_PRESENT)) {
            try {
                String output = Utils.readFile(CPU_PRESENT);
                sCpuCount = output.equals("0") ? 1 : Integer.parseInt(output.split("-")[1]) + 1;
            } catch (Exception ignored) {
            }
        }
        if (sCpuCount == 0) {
            sCpuCount = Runtime.getRuntime().availableProcessors();
        }
        return sCpuCount;
    }

    public static float[] getCpuUsage() {
        try {
            Usage[] usage1 = getUsages();
            Thread.sleep(500);
            Usage[] usage2 = getUsages();

            if (usage1 != null && usage2 != null) {
                float[] pers = new float[usage1.length];
                for (int i = 0; i < usage1.length; i++) {
                    long idle1 = usage1[i].getIdle();
                    long up1 = usage1[i].getUptime();

                    long idle2 = usage2[i].getIdle();
                    long up2 = usage2[i].getUptime();

                    float cpu = -1f;
                    if (idle1 >= 0 && up1 >= 0 && idle2 >= 0 && up2 >= 0) {
                        if ((up2 + idle2) > (up1 + idle1) && up2 >= up1) {
                            cpu = (up2 - up1) / (float) ((up2 + idle2) - (up1 + idle1));
                            cpu *= 100.0f;
                        }
                    }

                    pers[i] = cpu < 0 ? 0 : cpu > 100 ? 100 : cpu;
                }
                return pers;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static Usage[] getUsages() {
        try {
            RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
            Usage[] usage = new Usage[getCpuCount() + 1];
            for (int i = 0; i < usage.length; i++)
                usage[i] = new Usage(reader.readLine());
            reader.close();
            return usage;
        } catch (FileNotFoundException e) {
            Log.i(TAG, "/proc/stat does not exist");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static class Usage {

        private long[] stats;

        private Usage(String stats) {
            if (stats == null)
                return;

            String[] values = stats.replace("  ", " ").split(" ");
            this.stats = new long[values.length - 1];
            for (int i = 0; i < this.stats.length; i++) {
                this.stats[i] = Utils.strToLong(values[i + 1]);
            }
        }

        public long getUptime() {
            if (stats == null)
                return -1L;
            long l = 0L;
            for (int i = 0; i < stats.length; i++) {
                if (i != 3)
                    l += stats[i];
            }
            return l;
        }

        private long getIdle() {
            try {
                return stats == null ? -1L : stats[3];
            } catch (ArrayIndexOutOfBoundsException e) {
                return -1L;
            }
        }

    }

    private static void run(String command, String id, Context context) {
        Control.runSetting(command, ApplyOnBootFragment.CPU, id, context);
    }

}