How to get current overall cpu usage in android - android

I want a method to get the current overall cpu usage in android! I used a method that I found in this site and it's stated below.
private float readUsage() {
try {
RandomAccessFile reader = new RandomAccessFile("/proc/stat", "r");
String load = reader.readLine();
String[] toks = load.split(" ");
long idle1 = Long.parseLong(toks[5]);
long 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]);
try {
Thread.sleep(360);
} catch (Exception e) {}
reader.seek(0);
load = reader.readLine();
reader.close();
toks = load.split(" ");
long idle2 = Long.parseLong(toks[5]);
long 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]);
return (float)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));
} catch (IOException ex) {
ex.printStackTrace();
}
return 0;
}
But this method only returns me one float value. what I need is the current usage statistics like the percentage used by the system, and the percentage used by the user! can any one help me with this. a tutorial would be nice, but if any one is generous enough to give me a good code It would be my pleasure!
thank you!

From the linux proc manual page:
/proc/stat
kernel/system statistics. Varies with architecture. Common
entries include:
cpu 3357 0 4313 1362393
The amount of time, measured in units of USER_HZ
(1/100ths of a second on most architectures, use
sysconf(_SC_CLK_TCK) to obtain the right value), that the
system spent in user mode, user mode with low priority
(nice), system mode, and the idle task, respectively.
The last value should be USER_HZ times the second entry
in the uptime pseudo-file.
You may also want to look at the source of 'top' in AOSP platform/system/core/toolbox

When you are looking at the statistics in "proc/stat"
it will provide you with the overall CPU Usage (Kernal Mode+ User Mode)
you can only get the CPU USAGE in terms of system & user mode per process proc/[pid]/stat
- 14th param :- user mode in jiffies
- 15th param :- kernal mode in jiffies
calculate the Kernel Mode Usage for all the processes/pids and can consider it as system CPU usage...

Related

I'm trying to get а real traffic stats data. But, When i count `TrafficStats.getMobileTxBytes()` for whole day its more than my data pack?

eg. I have a 1.5 GB data pack. It gives the total sum of 2.0 GB or more than that .
any idea about how to get correct speed every second.
TrafficStats.getTotalRxBytes() does not return your data pack value. It refers to the total received bytes (either wifi/mobile) since the last boot (turning ON phone). For mobile data, it will be TrafficStats.getMobileRxBytes(). More importantly, these values get reset in every reboot of device.
I have a 1.5 GB data pack. It gives the total sum of 2.0 GB or more
than that .
The android system does not know anything about your data pack. You are adding it again and again. When you call TrafficStats.getMobileRxBytes() at a moment, it returns total mobile data received upto this moment since last boot. Following is an explanation. Hope this helps.
// Suppose, you have just rebooted your device, then received 400 bytes and transmitted 300 bytes of mobile data
// After reboot, so far 'totalReceiveCount' bytes have been received by your device over mobile data.
// After reboot, so far 'totalTransmitCount' bytes have been sent from your device over mobile data.
// Hence after reboot, so far 'totalDataUsed' bytes used actually.
long totalReceiveCount = TrafficStats.getMobileRxBytes();
long totalTransmitCount = TrafficStats.getMobileTxBytes();
long totalDataUsed = totalReceiveCount + totalTransmitCount;
Log.d("Data Used", "" + totalDataUsed + " bytes"); // This will log 700 bytes
// After sometime passed, another 200 bytes have been transmitted from your device over mobile data.
totalDataUsed = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
Log.d("Data Used", "" + totalDataUsed + " bytes"); // Now this will log 900 bytes
any idea about how to get correct speed every second.
You cannot get actual speed this way. You can only calculate and show how much bytes have been received/transmitted in a second. All the speed meters in android do the same I think. Something like the following:
class SpeedMeter {
private long uptoNow = 0;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
private ScheduledFuture futureHandle;
public void startMeter() {
final Runnable meter = new Runnable() {
public void run() {
long now = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
System.out.println("Speed=" + (now - uptoNow)); // Prints value for current second
uptoNow = now;
}
};
uptoNow = TrafficStats.getMobileRxBytes() + TrafficStats.getMobileTxBytes();
futureHandle = scheduler.scheduleAtFixedRate(meter, 1, 1, SECONDS);
}
public void stopMeter() {
futureHandle.cancel(true);
}
}
And use like this:
SpeedMeter meter = new SpeedMeter();
meter.startMeter();
Although this code is not perfect, however it will suit your needs.

Not cheatable Google fit step counter

i have a question to Google Fit.
I am creating a step counter (oh wonder g). This i have already done so far and it not really hard.
But now we come to my problem. I am only reading the steps with the Sensor API. The issue is, i can add new data via for example the Google Fit app and it will be counted in my app too. This introduces cheating and i do not want this.
So i need to have a way to only read "device created" data and not manually added data. Is there a nice way to to this?
From the SDK documentation it is not really clear how to proceed here.
So i need to have a way to only read "device created" data and not
manually added data. Is there a nice way to to this?
You will want to use Private Custom Data Types to achieve that. Read about the different types of Fitness data you can upload to Google Fit here.
1. Public data types
Standard data types provided by the platform, like com.google.step_count.delta. Any app can read and write data of
these types. For more information, see Public Data Types.
2. Private custom data types
Custom data types defined by an specific app. Only the app that defines the data type can read and write data
of this type. For more information, see Custom Data Types.
3. Shareable data types
Custom data types submitted to the platform by an app developer. Once approved, any app can read data of a
shareable type, but only whitelisted apps as specified by the
developer can write data of that shareable type. For more information,
see Shareable Data Types.
I was able to do this with the help of this alogrithm. But remember due to Android fragmentation this code still removes some of the user's data and count it as penalty
private String dumpDataSet(DataSet dataSet, int x) {
List<String> days = new ArrayList<>();
days.add("Monday");
days.add("Tuesday");
days.add("Wednesday");
days.add("Thursday");
days.add("Friday");
days.add("Saturday");
days.add("Sunday");
String day = days.get(Math.round(x / 24));
Log.d(TAG, "\tDay: " + day);
Log.i(TAG, "Data returned for Data type: " + dataSet.getDataType().getName());
DateFormat dateFormat = getTimeInstance();
String text = "";
try {
for (DataPoint dp : dataSet.getDataPoints()) {
Log.i(TAG, "\tStepCount getStreamName: " + dp.getOriginalDataSource().getStreamName());
Log.i(TAG, "\tStepCount getStreamIdentifier: " + dp.getOriginalDataSource().getStreamIdentifier());
Log.i(TAG, "\tStepCount App Type: " + dp.getDataType().getName());
Log.i(TAG, "\tStepCount Type: " + dp.getOriginalDataSource().getType());
for (Field field : dp.getDataType().getFields()) {
Log.i(TAG, "\tField: " + field.getName() + " Value: " + dp.getValue(field));
text += dp.getValue(field);
String si[] = dp.getOriginalDataSource().getStreamIdentifier().toLowerCase().split(":");
if ((((si[si.length - 1].contains("soft")) || (si[si.length - 1].contains("step"))) && si[si.length - 1].contains("counter"))) {
totalSteps += Integer.parseInt(dp.getValue(field).toString());
Log.d(TAG, "\tStepCount" + " Added Steps -> " + dp.getValue(field) + " steps");
text += "\n\n";
} else {
Log.e(TAG, "\tStepCount PENALTY ---------------------------------------------------------------");
Log.e(TAG, "\tDay = " + day + " | Hour Number = " + x + " | StepCount" + " PENALTY DEDUCTED -> " + dp.getValue(field) + " steps");
Log.e(TAG, "\tStepCount PENALTY getStreamIdentifier: " + dp.getOriginalDataSource().getStreamIdentifier());
Log.e(TAG, "\tStepCount PENALTY getStreamName: " + dp.getOriginalDataSource().getStreamName());
Log.e(TAG, "\tStepCount PENALTY App Type: " + dp.getDataType().getName());
Log.e(TAG, "\tStepCount PENALTY Type: " + dp.getOriginalDataSource().getType());
Log.e(TAG, "\tStepCount PENALTY ---------------------------------------------------------------");
}
}
}
} catch (Exception ex) {
ex.getStackTrace();
}
return text;
}
----- UPDATE -----
You can also call
DataPoint.getOriginalDataSource().getAppPackageName()
to filter out smartwatches and other apps.
I tried as suggested by Ali Shah lakhani but
DataPoint.getOriginalDataSource().getAppPackageName();
/*I also tried but could not achieve what I wanted*/
DataPoint.getOriginalDataSource().getStreamName();
DataPoint.getOriginalDataSource().getStreamIdentifier();
did not work at least for me while retrieving data. I ended up using readDailyTotalFromLocalDevice() as shown below in order to capture steps captured by device only.
Fitness.HistoryApi.readDailyTotalFromLocalDevice(mApiClient, DataType.TYPE_STEP_COUNT_DELTA).await(1, TimeUnit.MINUTES)
I cross checked the same with some of the apps that avoids manual entries in their app and the count provided by the function above is exactly the same.
Note: If a user is having multiple devices and is using the app on all of them, readDailyTotalFromLocalDevice() will have different value for each and every device since the function is responsible for returning device specific data only.

Android accelerometer sampling rate statistic

I am struggling with the accelerometer sampling rate of my app.
So I decided to develope a little app just for testing the sampling rate.
Are there any mistakes in my code? The sampling rate is pretty much changing :-/
private PowerManager.WakeLock mWakeLock;
private TextView infotext;
private SensorManager sensorManager;
private long nanoNow;
private long nanoOld;
private long nanodiffsum=0;
private int i=0;
private int values=2000;
private long[] nanodiff=new long[values];
DescriptiveStatistics myDescrStat = new DescriptiveStatistics();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int tid=android.os.Process.myTid()
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
infotext = (TextView) findViewById(R.id.textView);
sensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_FASTEST);
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
}
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
if (i==0){
nanoOld=event.timestamp;
}
if (i == values) {
for (int i=1; i<nanodiff.length; i++){
myDescrStat.addValue(nanodiff[i]);
nanodiffsum+=nanodiff[i];
}
infotext.setText(
"Average:" + nanodiffsum / values + "ms\n" + " = " + (double) 1000 / (nanodiffsum /values) + "Hz" + "\n" +
"mean: " + 1000 / myDescrStat.getMean() + "\n" +
"std:" + 1000 / myDescrStat.getStandardDeviation() + "\n" +
"max:" + 1000 / myDescrStat.getMin() + "\n" +
"min:" + 1000 / myDescrStat.getMax() + "\n");
mWakeLock.release();
sensorManager.unregisterListener(this);
}else{
nanoNow=event.timestamp;
nanodiff[i]=(nanoNow-nanoOld)/1000000;
if (i%20==0)
infotext.setText("Aktuell: " + nanodiff[i] + "ms" + " = " + Math.round((double)1000/ nanodiff[i]) + "Hz" );
nanoOld=nanoNow;
i++;
}
}
}
Kindly regards,
Arthur
After a cursory look at your code I cannot see anything wrong with it (except perhaps the overzealous update of the thread priority, which makes sense in a testing app but I wouldn't use without a good reason in actual production code).
As for the irregular rate of the the SensorManager's data (spoiler alert: the same behavior applies to other sensor streams ;-) ), it is meant to be that way, and the frequency specified with SensorManager.SENSOR_DELAY_FASTEST is meant to be only a hint (which is the reason why actually you receive the time of the measurement with such accuracy at each event). This is stated in the official documentation:
rateUs : The rate sensor events are delivered at. This is only a hint to the system.
Events may be received faster or slower than the specified rate. Usually events are received faster. Source: registerListener reference page
For one part, keep in mind that Android is Linux at the core, and linux is not a real-time system (and therefore can't provide data with realtime accuracy); on the other side, Android has to cope with a lot of different hardware implementations (and sensor brands), therefore the Android developers team has probably done a wise choice to avoid any kind of commitment about the ratio of the sensor data.
Those are my 50 cents, if you want to get serious about Android Sensors programming I would suggest this book:
Professional Android Sensor Programming (Greg Milette, Adam Stroud)
I read about 1/4 of it and so far, so good (I'm in no way related to the publisher or the author).
Hope this helps

SpannableStringBuffer limited to 9,999 characters?

My app reads in large amounts of data from text files assets and displays them on-screen in a TextView. (The largest is ~450k.) I read the file in, line-by-line into a SpannableStringBuffer (since there is some metadata I remove, such as section names). This approach has worked without complaints in the two years that I've had the app on the market (over 7k active device installs), so I know that the code is reasonably correct.
However, I got a recent report from a user on a LG Lucid (LGE VS840 4G, Android 2.3.6) that the text is truncated. From log entries, my app only got 9,999 characters in the buffer. Is this a known issue with a SpannableStringBuffer? Are there other recommended ways to build a large Spannable buffer? Any suggested workarounds?
Other than keeping a separate expected length that I update each time I append to the SpannableStringBuilder, I don't even have a good way to detect the error, since the append interface returns the object, not an error!
My code that reads in the data is:
currentOffset = 0;
try {
InputStream is = getAssets().open(filename);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
ssb.clear();
jumpOffsets.clear();
ArrayList<String> sectionNamesList = new ArrayList<String>();
sectionOffsets.clear();
int offset = 0;
while (br.ready()) {
String s = br.readLine();
if (s.length() == 0) {
ssb.append("\n");
++offset;
} else if (s.charAt(0) == '\013') {
jumpOffsets.add(offset);
String name = s.substring(1);
if (name.length() > 0) {
sectionNamesList.add(name);
sectionOffsets.add(offset);
if (showSectionNames) {
ssb.append(name);
ssb.append("\n");
offset += name.length() + 1;
}
}
} else {
if (!showNikud) {
// Remove nikud based on Unicode character ranges
// Does not replace combined characters (\ufb20-\ufb4f)
// See
// http://en.wikipedia.org/wiki/Unicode_and_HTML_for_the_Hebrew_alphabet
s = s. replaceAll("[\u05b0-\u05c7]", "");
}
if (!showMeteg) {
// Remove meteg based on Unicode character ranges
// Does not replace combined characters (\ufb20-\ufb4f)
// See
// http://en.wikipedia.org/wiki/Unicode_and_HTML_for_the_Hebrew_alphabet
s = s.replaceAll("\u05bd", "");
}
ssb.append(s);
ssb.append("\n");
offset += s.length() + 1;
}
}
sectionNames = sectionNamesList.toArray(new String[0]);
currentFilename = filename;
Log.v(TAG, "ssb.length()=" + ssb.length() +
", daavenText.getText().length()=" +
daavenText.getText().length() +
", showNikud=" + showNikud +
", showMeteg=" + showMeteg +
", showSectionNames=" + showSectionNames +
", currentFilename=" + currentFilename
);
After looking over the interface, I plan to replace the showNikud and showMeteg cases with InputFilters.
Is this a known issue with a SpannableStringBuffer?
I see nothing in the source code to suggest a hard limit on the size of a SpannableStringBuffer. Given your experiences, my guess is that this is a problem particular to that device, due to a stupid decision by an engineer at the device manufacturer.
Any suggested workarounds?
If you are distributing through the Google Play Store, block this device in your console.
Or, don't use one massive TextView, but instead use several smaller TextView widgets in a ListView (so they can be recycled), perhaps one per paragraph. This should have the added benefit of reducing your memory footprint.
Or, generate HTML and display the content in a WebView.
After writing (and having the user run) a test app, it appears that his device has this arbitrary limit for SpannableStringBuilder, but not StringBuilder or StringBuffer. I tested a quick change to read into a StringBuilder and then create a SpannableString from the result. Unfortunately, that means that I can't create the spans until it is fully read in.
I have to consider using multiple TextView objects in a ListView, as well as using Html.FromHtml to see if that works better for my app's long term plans.

Tracking long-term CPU usage of apps in android

Is there any way that I can, over a period of say a week, see how much CPU each app uses? The only way that I can think of is to repeatedly parse top output but that doesn't seem like the most efficient way to do it. Is there a better way?
To add some context, basically the traceview functionality of the SDK on the phone itself: http://developer.android.com/guide/developing/debugging/debugging-tracing.html
We did it parsing top output, couldn't think of a better way. We needed to monitor all applications, and trace is only good if you need information about your own as you have to add trace code to your application in order to use it.
The app consumes 5% of CPU when running once a sec, aggregating values, writing values to log file, and displaying results on screen.
Unfortunately code is not opened (yet).
One of the problems you'd face monitoring processes over that period of time is that they'll almost certainly be destroyed and created MANY times in that period - this makes it hard to gain useful figures.
If you're not a "reinventing the wheel" type - the free version of the popular SystemPanel App shows how much CPU time each process has used (and over what period) - the full version apparently offers a detailed history of both CPU and memory usage.
You can use the Debug class to monitor the processes
or use this function to calculate CPU usage
Use /proc/stat/ for the total CPU usage (for all CPU's) . For per process usage
private float readCpuUsage(int pid) {
try {
RandomAccessFile reader = new RandomAccessFile("/proc/" + pid + "/stat", "r");
String load = reader.readLine();
String[] toks = load.split(" ");
long idle1 = Long.parseLong(toks[5]);
long 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]);
try {
Thread.sleep(360);
} catch (Exception e) {}
reader.seek(0);
load = reader.readLine();
reader.close();
toks = load.split(" ");
long idle2 = Long.parseLong(toks[5]);
long 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]);
return (float)(cpu2 - cpu1) / ((cpu2 + idle2) - (cpu1 + idle1));
} catch (IOException ex) {
ex.printStackTrace();
}
return 0;
}
source
To get the list of running processes
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks)
{
Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName());
}

Categories

Resources