• Uncategorized

About java : How-do-I-read-CPU-stats-in-Java-from-an-Android-phone

Question Detail

I am trying to figure out the CPU usage by core, perhaps the temp if possible, and in general figure out what I can read from the CPU.

I have done some searching, and I have some code that returns the number of cores (see How can you detect a dual-core cpu on an Android device from code?). Now I am trying to figure out how to use that to get the CPU usage by core from this link (Get Memory Usage in Android).

The only problem is I’m kinda new to Java/Android, so I’m having trouble understanding what the commenters are trying to say. One comment says that you should change the delimiters on idle1 and cpu1…do I do the same for idle2 and cpu2? Any help would be appreciated, so thank you in advance!

Ok so now I have a way better understanding of what I’m doing, but cores 2-4 on my 4 core test board are all reading 0. On occasion, when I start the app, core 2 has a value > 0, but upon subsequent runs (the app updates values once per second) it returns to 0. Here is the code I currently have, thank you so much!!!

    public double readUsage(int corenum) {
    int j=0;
    int coreVal = getNumCores();
    String[] toks;
    long idle1;
    long cpu1;
    long idle2;
    long cpu2;

    try {           
            RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
            String load = reader.readLine();
            reader.seek(0);
            while (j <= corenum){
                load = reader.readLine();
                j++;
            }
            j=0;
            toks = load.split(" ");

            if (corenum == 0) {
                idle1 = Long.parseLong(toks[5]);
                cpu1 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
                      + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
            }

            else {
                idle1 = Long.parseLong(toks[4]);
                cpu1 = Long.parseLong(toks[1]) + Long.parseLong(toks[2]) + Long.parseLong(toks[3])
                        + Long.parseLong(toks[5]) + Long.parseLong(toks[6]) + Long.parseLong(toks[7]);
            }   

            try {
                 Thread.sleep(100);
            } catch (Exception e) {}

            reader.seek(0);
            while (j <= corenum){
                load = reader.readLine();
                j++;
            }
            j=0;
            reader.close();
            toks = load.split(" ");

            if (corenum == 0) {
                idle2 = Long.parseLong(toks[5]);
                cpu2 = Long.parseLong(toks[2]) + Long.parseLong(toks[3]) + Long.parseLong(toks[4])
                      + Long.parseLong(toks[6]) + Long.parseLong(toks[7]) + Long.parseLong(toks[8]);
            }

            else {
                idle2 = Long.parseLong(toks[4]);
                cpu2 = Long.parseLong(toks[1]) + Long.parseLong(toks[2]) + Long.parseLong(toks[3])
                        + Long.parseLong(toks[5]) + Long.parseLong(toks[6]) + Long.parseLong(toks[7]);
            }

           return (double)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));

    } catch (IOException ex) {
        ex.printStackTrace();
    }

    return 9999999;
}

Question Answer

You can use the code in this answer: Get Memory Usage in Android

As mentioned in the comments, you can skip the first line to get per-core data.

Per comment below, you can read each line of the file and print the usages, and then split the lines as in the provided link:

public void printCpuUsages()
{
    try
    {
        RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
        String load = reader.readLine();
        while (load != null)
        {
            Log.d("CPU", "CPU usage: " + load);
            load = reader.readLine();
        }
    }
    catch (IOException ex)
    {
        ex.printStackTrace();
    }
}

Despite that the answer seems to be valid, I have created a small parser to help the people to extract the information of “proc/stat”. The documentation can be found here.

public class Cpu {
private String name = "";
private long cpu_user = 0;
private long cpu_niced = 0;
private long cpu_system = 0;
private long cpu_idle = 0;
private long cpu_iowait = 0;
private long cpu_irq = 0;
private long cpu_softirqs = 0;

public Cpu(String name, long cpu_user, long cpu_niced, long cpu_system, long cpu_idle, long cpu_iowait, long cpu_irq, long cpu_softirqs) {
    this.name = name;
    this.cpu_user = cpu_user;
    this.cpu_niced = cpu_niced;
    this.cpu_system = cpu_system;
    this.cpu_idle = cpu_idle;
    this.cpu_iowait = cpu_iowait;
    this.cpu_irq = cpu_irq;
    this.cpu_softirqs = cpu_softirqs;
}

public long getCpuUser() {
    return cpu_user;
}

public long getCpuNiced() {
    return cpu_niced;
}

public long getCpuSystem() {
    return cpu_system;
}

public long getCpuIdle() {
    return cpu_idle;
}

public long getCpuIowait() {
    return cpu_iowait;
}

public long getCpuIrq() {
    return cpu_irq;
}

public long getCpuSoftirqs() {
    return cpu_softirqs;
}

public double getAverageIdlePercentage(){
    return ( cpu_idle * 100 ) / ( cpu_user + cpu_niced + cpu_system + cpu_idle + cpu_iowait + cpu_irq + cpu_softirqs );
}

public String getName() {
    return name;
}

public String toString(){
    String temp ="";
    temp+= name+ " ";
    temp+= cpu_user+ " ";
    temp+= cpu_niced+ " ";
    temp+= cpu_system+ " ";
    temp+= cpu_idle+ " ";
    temp+= cpu_iowait+ " ";
    temp+= cpu_irq+ " ";
    temp+= cpu_softirqs+ " ";
    return temp;
}
}

public class StatFile {

/**
 * The very first line "cpu" aggregates the numbers in all of the other "cpuN" lines.
 * These numbers identify the amount of time the CPU has spent performing different kinds of work. Time units are in USER_HZ or Jiffies (typically hundredths of a second).
 */
private List<Cpu> cpus;
/**
 * Counts of interrupts serviced since boot time, for each of the possible system interrupts. The first column is the total of all interrupts serviced; each subsequent column is the total for that particular interrupt.
 */
private List<Long> interruptions;
/**
 * The total number of context switches across all CPUs.
 */
private long ctxt = 0;

/**
 * The time at which the system booted
 */
private Date btime;

/**
 * The number of processes and threads created, which includes (but is not limited to) those created by calls to the fork() and clone() system calls.
 */
private long processes = 0;

/**
 *  The number of processes currently running on CPUs
 */
private long procs_running = 0;

/**
 * The number of processes currently blocked, waiting for I/O to complete
 */
private long procs_blocked = 0;

private List<Long> softirq;

public StatFile(){
    cpus = new ArrayList<Cpu>();
    interruptions = new ArrayList<Long>();
    ctxt = 0;
    btime = new Date();
    processes = 0;
    procs_running = 0;
    procs_blocked = 0;
    softirq = new ArrayList<Long>();
}

public List<Cpu> getCpus() {
    return cpus;
}

public void setCpus(List<Cpu> cpus) {
    this.cpus = cpus;
}

public List<Long> getInterruptions() {
    return interruptions;
}

public void setInterruptions(List<Long> interruptions) {
    this.interruptions = interruptions;
}

public long getCtxt() {
    return ctxt;
}

public void setCtxt(long ctxt) {
    this.ctxt = ctxt;
}

public Date getBtime() {
    return btime;
}

public void setBtime(Date btime) {
    this.btime = btime;
}

public long getProcesses() {
    return processes;
}

public void setProcesses(long processes) {
    this.processes = processes;
}

public long getProcs_running() {
    return procs_running;
}

public void setProcs_running(long procs_running) {
    this.procs_running = procs_running;
}

public long getProcs_blocked() {
    return procs_blocked;
}

public void setProcs_blocked(long procs_blocked) {
    this.procs_blocked = procs_blocked;
}

public List<Long> getSoftirq() {
    return softirq;
}

public void setSoftirq(List<Long> softirq) {
    this.softirq = softirq;
}
}

CpuUtils class:

public class CpuUtils {

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

 /**
 * Normal processes executing in user mode
 */
private static final int CPU_USER=1;
/**
 * Niced processes executing in user mode
 */
private static final int CPU_NICE=2;
/**
 * Processes executing in kernel mode
 */
private static final int CPU_SYSTEM=3;
/**
 * Twiddling thumbs
 */
private static final int CPU_IDLE=4;
/**
 * Waiting for I/O to complete
 */
private static final int CPU_IOWAIT=5;
/**
 * Servicing interrupts
 */
private static final int CPU_IRQ=6;
/**
 * Servicing softirqs
 */
private static final int CPU_SOFTIRQS=7;

public static StatFile parseStatsFile() {
    StatFile statFile = new StatFile();
    try {
        RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
        try {
            while (true) {
                String load = reader.readLine();
                //Avoid problem parsing doble space
                if(load!=null) {
                    Log.d(TAG, "Stat: " + load);
                    load = load.replace("  ", " ");
                    String[] tokens = load.split(" ");
                    if (tokens[0].startsWith("cpu")) {
                        Cpu cpu = parseCpuTokens(tokens);
                        statFile.getCpus().add(cpu);
                    }
                    else if(tokens[0].startsWith("intr")){
                        for(int i=1; i<tokens.length; i++){
                            statFile.getInterruptions().add(Long.parseLong(tokens[i]));
                        }
                    }
                    else if(tokens[0].startsWith("ctxt")){
                        statFile.setCtxt(Long.parseLong(tokens[1]));
                    }
                    else if(tokens[0].startsWith("btime")){
                        //time is in seconds, therefore we need it in milliseconds
                        statFile.setBtime(new Date(Long.parseLong(tokens[1])*1000));
                    }
                    else if(tokens[0].startsWith("processes")){
                        statFile.setProcesses(Long.parseLong(tokens[1]));
                    }
                    else if(tokens[0].startsWith("procs_running")){
                        statFile.setProcs_running(Long.parseLong(tokens[1]));
                    }
                    else if(tokens[0].startsWith("procs_blocked")){
                        statFile.setProcs_blocked(Long.parseLong(tokens[1]));
                    }
                    else if(tokens[0].startsWith("softirq")){
                        for(int i=1; i<tokens.length; i++){
                            statFile.getSoftirq().add(Long.parseLong(tokens[i]));
                        }
                    }
                }
                else{
                    throw new EOFException("File end reached");
                }
            }
        } catch (EOFException ex) {

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }catch (FileNotFoundException e){
        e.printStackTrace();
        throw new IllegalStateException("Unable to access the stats");
    }

    return statFile;
}

private static Cpu parseCpuTokens(String[] tokens){
    Cpu cpu = new Cpu(tokens[0],
            Long.parseLong(tokens[CPU_USER]),
            Long.parseLong(tokens[CPU_NICE]),
            Long.parseLong(tokens[CPU_SYSTEM]),
            Long.parseLong(tokens[CPU_IDLE]),
            Long.parseLong(tokens[CPU_IOWAIT]),
            Long.parseLong(tokens[CPU_IRQ]),
            Long.parseLong(tokens[CPU_SOFTIRQS]));
    return cpu;
}
}

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.