Time code execution in Android - android

What is the easiest to time execution in Android?
I have looked around a bit and I found TimingLogger on the Android SDK,
and instructions here. It looks very convenient.
But I can't get it work. This is my code:
TimingLogger timings = new TimingLogger("TopicLogTag", "Parsing html");
My code to time here...
timings.dumpToLog();
It's supposed to dump the times in LogCat. But I can't see anything.. I What am I doing wrong? Eclipse doesn't show any varnings. I guess it has something with verbose ouput, but I have set LogCat to show Verbose.
Thank you..

I gave it a test run and I am experiencing the same thing. It all boils down to this little bit of the description in the Javadoc for TimingLogger:
If the Log.isLoggable is not enabled
to at least the Log.VERBOSE level for
that tag at creation time then the
addSplit and dumpToLog call will do
nothing.
I did a test locally:
TimingLogger timings = new TimingLogger("MyTag", "Initialization");
Log.d("MyTag", "Is Loggable? " + Log.isLoggable("MyTag", Log.VERBOSE));
timings.dumpToLog();
And oddly, I get an output to the log:
06-28 08:35:18.693: DEBUG/MyTag(24366): Is Loggable? false
But that's it. And since it's false, I doubt TimingLogger is doing anything, based on the TimingLogger code:
90 /**
91 * Clear and initialize a TimingLogger object that will log using
92 * the tag and label that was specified previously, either via
93 * the constructor or a call to reset(tag, label). If the
94 * Log.isLoggable is not enabled to at least the Log.VERBOSE
95 * level for that tag at creation time then the addSplit and
96 * dumpToLog call will do nothing.
97 */
98 public void reset() {
99 mDisabled = !Log.isLoggable(mTag, Log.VERBOSE);
100 if (mDisabled) return;
101 if (mSplits == null) {
102 mSplits = new ArrayList<Long>();
103 mSplitLabels = new ArrayList<String>();
104 } else {
105 mSplits.clear();
106 mSplitLabels.clear();
107 }
108 addSplit(null);
109 }
I'm not sure why Log.isLoggable is returning false when it's obviously logging at above VERBOSE, since my Log.d obviously logged.
You can enable logging for that tag manually from the [Log class Javadoc][3]:
You can change the default level by
setting a system property: 'setprop
log.tag. ' Where
level is either VERBOSE, DEBUG, INFO,
WARN, ERROR, ASSERT, or SUPPRESS.
SUPPRESS will turn off all logging for
your tag. You can also create a
local.prop file that with the
following in it:
'log.tag.=' and
place that in /data/local.prop.
Which I did through adb shell:
$ adb shell
# setprop
usage: setprop <key> <value>
# setprop log.tag.MyTag VERBOSE
#
Results in:
06-28 08:53:42.447: DEBUG/MyTag(24739): Is Loggable? true
06-28 08:53:44.744: DEBUG/MyTag(24739): Initialization: begin
06-28 08:53:44.744: DEBUG/MyTag(24739): Initialization: end, 0 ms
See droidgren's comment on this answer - apparently a call to addSplit is also necessary.
[3]: http://developer.android.com/reference/android/util/Log.html#isLoggable(java.lang.String, int)

I found another more simple solution which measures the exact same time as TimingLogger, which doesn't require setprop.
private long startnow;
private long endnow;
startnow = android.os.SystemClock.uptimeMillis();
*Your time consuming code here*
endnow = android.os.SystemClock.uptimeMillis();
Log.d("MYTAG", "Execution time: " + (endnow - startnow) + " ms");

If you guys take a look at its source code, actually the implementation for the TimingLogger class is quite simple.
So what I did, which perfectly fits for my use case, was to make my own version of the class but changing the reset() method to
public void reset() {
mDisabled = false; // <- This is what has changed.
if (mDisabled) return;
if (mSplits == null) {
mSplits = new ArrayList<Long>();
mSplitLabels = new ArrayList<String>();
} else {
mSplits.clear();
mSplitLabels.clear();
}
addSplit(null);
}
The catch here is changing from
mDisabled = !Log.isLoggable(mTag, Log.VERBOSE);
to
mDisabled = false;
This way we don't have to mess with adb.

If you simply looking for logs as explained in developer.android.com, you will not be able to see logs. So use below command:
adb shell setprop log.tag.MyTag VERBOSE
Note: MyTag is the first parameter you passed when creating new TimingLogger as below:
TimingLogger timings = new TimingLogger("MyTag", "MyMethodName");
For your questions's answer, you should execute below command:
adb shell setprop log.tag.TopicLogTag VERBOSE
And there you are. Happy coding !!!

Sometimes we don't need to know the exact time that took us an operation but we want to know, why that operation took so long. Thus, for speeding up code, we only need to know some kind of relational order of parts of that operation where the one taking up the most time seems to be the one you should optimize. Therefore, android brings method tracing:
Debug.startMethodTracing("YOUR_TRACE_FILE_NAME");
// Do your operations
Debug.stopMethodTracing();
Then, the os writes the trace file containing all call infos to filesystem.
Simply drag'n'drop that file onto traceview.bat and start inspecting what calls took how long.
Benefits:
You can inspect all called functions and methods that have been called while tracing.
No need to synchronize data for multithreaded apps.
Trace is written to file automatically - no log cat magic or whatever is necessary. All data is encapsulated together, ready to be inspected.
As soon as you start adding time measuring and especially logging, you wreck your timing anyways.
Link: http://developer.android.com/tools/debugging/debugging-tracing.html

Try doing:
adb shell logcat

Related

Android - getevent command logging in thread

#Override
public void run() {
try {
exec = Runtime.getRuntime().exec("getevent | grep event1");
InputStreamReader is = new InputStreamReader(
exec.getInputStream());
String s;
BufferedReader br = new BufferedReader(is);
Log.i("br.readLine", " = " + br.readLine());
while ((s = br.readLine()) != null) {
Log.i("s2", " " + s);
}
// is.close();
// exec.destroy();
} catch (IOException e) {
Log.e("thread ioexception", " " + e.getCause());
e.printStackTrace();
}
}
I tried logging the results of the command to getevent in thread.
But put the results of the command in the buffer, the buffer is empty(null).
Perhaps as soon as this command is executed, it seems that ends without receiving any input.
While maintaining thread I want to continue to be run getevent command.
How this can be done? any idea?
Edit
getErrorStream()
getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
-d: show HID descriptor, if available
-p: show possible events (errs, dev, name, pos. events)
-i: show all device info and possible events
-l: label event types and names in plain text
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
GetErrorStream comes out as the result of a manual getevent.
If the instruction is to operate normally, it would not have been any log (the other normal commands actually did. Ex) ls )
I think getevent command seems to have caused various problems since the CALLBACK method.
Edit: I think now I got your problem. The pipe behavior is not cross-platform, as it is a functionality of the executed shell. Thats why it is not working as you expect in java. Try to use a script like the following to spawn a new shell which implements the pipe function as you expect.
String[] cmd = {
"/system/bin/sh",
"-c",
"getevent | grep event1"
};
I'll keep the rest of the answer, as it could help somebody.
I think you are executing getevent | grep event1 without the correct permissions. At least you need to be root user or in input group.
Edit: I still think you do not have the correct permissions. Of course, for running getevent no special permissions are necessary, as it can be executed by everyone. But keep in mind, that getevent reads /dev/input/*, which has the following permissions:
crw-rw---- root input 13, 64 2016-01-24 21:34 event1
Try to make sure your application is really allowed to read event1.
You should also try to use getErrorStream() instead of getInputStream() to see what is going wrong.
Regarding the second part of your question, I am not sure I understand it correctly. You want to execute the command periodically in the same thread right? (I did not, see edit below.)
Then you can simply run your code in a while(1) loop and sleep as long as you want. A bit more advanced would be to use a Timer and a TimerTask.
If you want to control every loop from outside your Thread you can simply use Object.wait() and Object.notify(). Another, also more advanced, possibility is to use Thread pools. The interesting one for you could be the SingleThreadExecutor.
Edit: As I thought, I did not understood you correctly. However, I'll keep the second part of my answer, maybe it helps someone else.
For your use case your code should work correctly. I think it does return immediately because an error is happening. As described above, try to use getErrorStream() to see what is actually happening.

Android- performing su commands programatically does not work

I need my app to perform some su commands programatically (phone is rooted).
When done using adb, the commands work.
For instance:
su -c "mkdir /sdcard/testdir" creates a directory called "testdir" in /sdcard.
When I call:
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
It just moves on and no change happens.
I tried reading the input:
DataInputStream dis = new DataInputStream(p.getInputStream());
while((temp = dis.readLine())!=null)
Log.d(ctx.TAG,"shell:"+temp);
But it reports nothing (loop does 0 iterations).
Has anyone ever faced this issue before? How can it be solved?
Needless to day, non-su commands do work programatically with this method.
Note: I gave mkdir as an example (I know it doesn't necessarily require su). I need a lot of varied commands to be performed under su
Thank you!
EDIT: when I call su -c "id" programatically, there's output that uid=0.
I can get stuck on a problem for days, and the moment I gather up the courage to ask about it on StackOverflow, it is solved within minutes.
The fix is:
p=Runtime.getRuntime().exec("su");
DataOutputStream dos = new DataOutputStream(p.getOutputStream());
dos.writeBytes("mkdir /sdcard/testdir\n");
dos.writeBytes("exit\n");
dos.flush();
dos.close();
p.waitFor();
Don't forget \n at the end of each command you write to the DataOutputStream, as it will not work without it.
You wrote that you "need varied commands to be performed under su". Note that the use of "Runtime.exec()" is discouraged by Chainfire, the developer of the most famous SuperSU root app.
It is tempting to use Runtime.getRuntime().exec("su -c [command]");, but you should be aware that [command] should be a single parameter, and thus may require quoting. Unfortunately both quoting the [command] parameter as well as passing the paramaters as separate variables to either Runtime.exec() or ProcessBuilder does not work consistently across all Android versions, and thus this construct should be avoided entirely. It is not impossible to do this right - but there's a high risk of problems.
See the How to SU Document. So you might want to follow his recommendation here:
3.2. Making the call
A common method to call su that avoids the known issues listed above is by creating an interactive shell and piping commands to it. This is done by calling Runtime.getRuntime().exec("su");, and retrieving input and output streams from the returned Process object. Doing this is a fairly straight-forward piece of code, but including the debug logs and checks it's a bit long to reproduce here.
The core code is located here: [libsuperuser :: Shell.java # GitHub]. Shell.run() is a generic call to run shell code, the following more specific (static) utility functions are the ones you will probably end up using:
List<String> Shell.SH.run(String command)
List<String> Shell.SH.run(List<String> commands)
List<String> Shell.SH.run(String[] commands)
List<String> Shell.SU.run(String command)
List<String> Shell.SU.run(List<String> commands)
List<String> Shell.SU.run(String[] commands)
The SH variants are used for a non-root shell, where the SU variants are used for a root shell. These calls return a List containing the output of the shell commands. If there was no output, the list is empty, but not null. The result is only null in case an error occured - including the user not granting your app su access. These are blocking calls.
Note that in debug compiles, all shell STDIN/STDOUT/STDERR will be logged to logcat, and these calls will (intentionally) crash your app if called from the main thread. The reason for this will be discussed in section 4. When to call su.
If you use double quotes, it will work:
su -c ""command with args""
You might be calling Runtime.getRuntime().exec() in main thread and p.waitFor() makes your main thread wait until it executes. Try calling in another thread, like the following snippet.
new Thread(){
#override
public void run(){
p = Runtime.getRuntime().exec("su -c \"mkdir /sdcard/testdir\"");
p.waitFor();
}.start();
}

How to send a 'fake' command to Appium

I'm trying to test my android application with appium and I'm looking for a solution to the following issue:
In my application I have a section that takes time (for image processing) and it sometimes can take one minute, two minute or even more depends on the image size, quality.
In my test case I'm trying to wait for lets say 30 seconds and then I'm checking if the image processing is done.
The problem is if I'm waiting too long, I got the next message:
info: [debug] Didn't get a new command in 60 secs, shutting down...
I don't want to set a 'newCommandTimeout' cause I want to cut the test time and I want to test check if its done every short period.
In addition, I can't use the wait for element or something like that of appium API because I'm using a third party library which tells me when the image processing is done.
My questions is, there is any way to send a 'fake' command to appium so every 30 seconds that my thread is back to work and if I see that the image processing is not done I'll send a fake command and then go back to sleep for 30 seconds without any worry that the appium server will be shut down due to timeout?
Not sure what you are using for wait command. Use this:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
This will wait until it finds the element on screen.
In addition to the comment here:
In order to solve this issue I use the WebDriverWait with a custom ExpectedCondition and it looks like:
new WebDriverWait(mDriver, 30) // 30 is for the time out
.withMessage("You can set any custom error message")
.until(new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver d) {
//This function will be called repeatedly until
//the return value will be true
}
});
You can see other implementations of WebDriverWait and actually I think it works with any Object instead of Boolean.

Android ndk-r9 compiler optimization issues

I recently switched to using Android ndk-r9 and am having some difficulty with my app that seems to be related to compiler optimization. I have the following function:
int GetTouchPos(GTouchEvents * pEvents, GPointF * pPos, int * pButton = 0)
{
int count = 0;
GTouchEvent * pEvent;
if (pEvents->GetCount(&count) == GResult_Ok)
{
GDebugLog((GS("GetTouchPos: count = %d"), count));
if (pEvents->GetEvent(0, &pEvent) == GResult_Ok)
{
pEvent->GetTapPos(pPos);
if (pButton)
{
pEvent->GetButton(pButton);
}
pEvent->Release();
}
}
return(count);
}
If I build my project and run it, the call to GDebugLog formats and logs the value of the variable 'count'. When I do this, 'count' is 1 and my app works correctly. However if I comment out the GDebugLog line (and make NO other changes), when I run my app, it no longer works. In the function GTouchEvents::GetCount, I also am logging what it is returning and the value is always correctly '1'. Also, I log the return from the call to the function above (i.e. GetTouchPos). When the GDebugLog line is present, the logged return value is the correct value '1'. However when I comment out the GDebugLog call, the logged return value is a seemingly random number, which looks suspiciously like an uninitialized variable.
Note that this all works with our without the GDebugLog line when I was using r8b. Also note that if I turn optimization off, this code works perfectly using r9 whether the debugging line is present or not. Also note that this behavior only presents itself when compiling for the ARM processor. The version I build for x86 works without problem.
Am I doing something questionable here that is causing the optimizer to generate incorrect code?
Can anyone shed some light on what might be happening?
Thanks.

Rather odd behaviour of Log

I wrote a very simple Android Activity:
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("TAG", "onCreate() Log call 1");
Log.d("SMS", "onCreate() Log call 2");
Log.d("TEST", "onCreate() Log call 3");
finish();
}
#Override
protected void onDestroy() {
Log.d("TAG", "onDestroy() Log call 1");
Log.d("SMS", "onDestroy() Log call 2");
Log.d("TEST", "onDestroy() Log call 3");
super.onDestroy();
}
}
I would expect this to generate 6 log messages (3 from onCreate(), 3 from onDestroy()). Here is the logcat:
04-14 17:31:58.363: D/TAG(18084): onCreate() Log call 1
04-14 17:31:58.363: D/TEST(18084): onCreate() Log call 3
04-14 17:31:59.905: D/TAG(18084): onDestroy() Log call 1
04-14 17:31:59.905: D/TEST(18084): onDestroy() Log call 3
As can be seen, the lines with the tag "SMS" don't get through. This is not, as far as I can tell a documented thing. The question is, why?
EDIT: More details on the answer.
A rather good answer is given below by Matthew Burke. In short, on the basis of the source code for logd_write.c, it seems that:
Log requests with the following tags are automatically redirected to the radio log:
HTC_RIL
tags starting with RIL
AT
GSM
STK
CDMA
PHONE
SMS
No Log requests are redirected to the events log (or the system log, see also http://elinux.org/Android_Logging_System)
All other Log requests go to the main log, the one that is usually monitored.
I should have read the documentation for logcat before I started hunting through source. According to logcat's documentation:
The Android logging system keeps multiple circular buffers for log messages, and not all of the log messages are sent to the default circular buffer.
Messages with a tag of SMS are sent to the radio buffer, not the main buffer. Hence you won't see them unless you go out of your way to do so. If you run the command:
adb logcat -b radio
you should see your missing log messages. The above information can be found in https://developer.android.com/tools/debugging/debugging-log.html.
Now, for those of you interested in code spelunking, below is my original answer:
The methods in the Log class are all wrappers around println_native which is a JNI method.
println_native performs some validation of its parameters and then calls __android_log_buf_write.
Now this latter method compares the tag parameter (from the original Log.d call) against several hard-coded strings (with the tag SMS being one of this list) and if it finds a match, winds up writing the log message to a different file!
By the way, other tags that get rerouted are GSM, STK, PHONE, CDMA, and a few others.
Relevant source can be read in
http://www.java2s.com/Open-Source/Android/android-core/platform-frameworks-base/android/util/Log.java.htm
https://pdroid.googlecode.com/svn/android-2.3.4_r1/trunk/frameworks/base/core/jni/android_util_Log.cpp
https://in-the-box.googlecode.com/svn-history/r4/trunk/InTheBoxSim/liblog/logd_write.c
http://www.takatan.net/lxr/source/drivers/staging/android/logger.h#L33
These aren't the official links and may disappear at some point. I'll try and track down the official links and edit this later this evening.
EDIT Ignore this, I'm apparently quite off base according to this.
So I thought this was interesting, and after digging through the source, I ended up finding out about Log.isLoggable():
Checks to see whether or not a log for the specified tag is loggable
at the specified level. The default level of any tag is set to INFO.
This means that any level above and including INFO will be logged.
Before you make any calls to a logging method you should check to see
if your tag should be logged. You can change the default level by
setting a system property: 'setprop log.tag. '
Where level is either VERBOSE, DEBUG, INFO, WARN, ERROR, ASSERT, or
SUPPRESS. SUPPRESS will turn off all logging for your tag. You can
also create a local.prop file that with the following in it:
'log.tag.=' and place that in /data/local.prop.
Parameters
tag
The tag to check. level The level to check. Returns
Whether or not that this is allowed to be logged.
Apparently some tags are not allowed at certain log levels, seemingly defined in /data/local.prop, but there must be some system level properties file I haven't found yet. You can check against it using something like this, though:
boolean isLoggableV = Log.isLoggable("SMS", Log.VERBOSE);
boolean isLoggableD = Log.isLoggable("SMS", Log.DEBUG);
boolean isLoggableI = Log.isLoggable("SMS", Log.INFO);
boolean isLoggableW = Log.isLoggable("SMS", Log.WARN);
boolean isLoggableE = Log.isLoggable("SMS", Log.ERROR);
boolean isLoggableA = Log.isLoggable("SMS", Log.ASSERT);
Log.v("LogTest", String.format("Verbose: %b Debug: %b Info: %b Warn: %b Error: %b Assert: %b", isLoggableV, isLoggableD, isLoggableI, isLoggableW, isLoggableE, isLoggableA));
Which for me returned the following:
Verbose: false Debug: false Info: true Warn: true Error: true Assert: true
So you can log the tag SMS at a log level of INFO and above, but not VERBOSE or DEBUG.
I have to assume this is to prevent applications from accidentally logging personal information, but it seems like a fairly crude way of doing so.

Categories

Resources