Use grep with python subproccess.check_output and adb logcat - android

I am trying to write a python function that captures the time it takes for an android device to get gps fix. I want to do this by capturing the timestamp of the logcat record which mentions that system time is syncronised with GPS. So I submit an adb logcat with timestamp and grep for "Setting system time at". The I want to give the timestamp value of this line to a varialble. Specifically I want to capture the characters 10-18 of this line as this reflects the exact time from device boot. Once the string has been detected once I want the function to exit and my program to continue.
I try in the following:
cmdtimegps='adb logcat -v time| grep "Setting system time at"'
w=subprocess.check_output(cmdtimegps.split())
print w
My main problem is making the command (adb logcat -v time| grep SetTimeFromGPSService) work. I get a "/system/bin/sh: grep: not found" error. Any help with this or advice on the following steps would be very welcome. Many thanks in advance,

You have a couple of problems. First, this is a piped shell command so you need to pass the string without splitting it into a list and set shell=True. Second, check_output is a bad choice here because it only returns after the program terminates but your particular command runs forever.
A better solution is to stop grepping and have python process the command. Then you can kill it when you see the data you want.
proc = subprocess.Popen(['adb', 'logcat', '-v', 'time'], stdout=subprocess.PIPE)
for line in proc.stdout:
if "Setting system time at" in line:
proc.kill()
break
proc.wait()

Related

Filter android adb logs in terminal when using Timber

In my app, I am using Timber as a logger. I am accessing the logs from the terminal via adb using this isntruction:
./adb logcat com.company.my_app:D
I do get the logs but the issue is that I am getting a crazy amount of noise from the OS (ie SurfaceFlinger , GraphicBuffer, vndksupport) which make the logs harder to read.
Is there a way to filter the logs like in Android Studio and just get logs from my app. Thank you !
P.S. I have trie a few answers from here but none of them remove the noise.
What works best for me is to grep for the process ID which is displayed in every log line. In the example below 7098 is printed with every log line.
08-10 18:48:39.825 7098 7144 D NetworkModule: --> END POST
So this is the adb instruction used to get filtered logs:
adb logcat | grep -F "7098"
Note: the process ID is not static and it is going to change if app is hard-closed or device is restarted.
I don't know if it is the best solution, but it works in my case.

Capture output from adb logcat

I am automating an Android application and I need to be able to capture logs while I am running the automation tests. I have tried using a terminal emulator but this only seems to give console logs. Next I tried using
log = subprocess.check_output(["adb", "logcat"])
But when I do this my automation script stops indefinitely (presumably because it is waiting to continue after the logcat capture is complete), which does not work for me because I need the logcat to run in the background, while my script is running. So maybe 'Popen' is the way to go, and then pipe the output? Thank you!
The logs are always "running in the background", it's just whether you're looking at them. I would suggest instead, when you need a log dump, using
adb logcat -d
which will dump what it currently has, then exit.
So at the start of your test run:
subprocess.call(shlex.split('adb logcat -c'))
to clear the logs.
So at the end (and before any restart), dump the logs:
log = subprocess.check_output(shlex.split('adb logcat -d'))
with open("loggy.file", "w") as f:
f.write(log)

Any way to grab a snapshot of current logcat output without opening up the output stream?

I'm trying to grab some filtered output from logcat through command line, but would prefer to not have a logcat stream opened up for automation purposes.
Here's my use case: I want to clear logcat, perform some instrumentation tests with AccessibilityChecks enabled, then check logcat for Accessibility errors that the class has found in my UI.
Currently, here's what I can do via command line:
//clear logcat history:
adb logcat -c
// Run instrumentation tests at this time.
// Run following command when tests done:
adb logcat AccessibilityValidator:E *:S
// ctrl-c to close stream
This does what it is supposed to. I will see just the Accessibility errors printed out. The problem is that I do not want to open up a logcat stream. I'd like to get the results as is, right at the point that my instrumentation tests have completed. Opening up a stream is not very ideal as I would then need to pipe in a ctrl-C to my pipeline to close the stream. I would really like to get a snapshot of the output in plain text. Is such a thing possible?
Thank you!
Edit: I was able to find what I believe is a working solution - I just needed to add the -d flag. This will not open a stream and will print the contents of the logcat file. Combine with my filtering, I am able to get exactly what I was looking for.
I was able to find what I believe is a working solution - I just needed to add the -d flag. -d will dump the logs and exit. This will not open a stream and will print the contents of the logcat file to stdout. Combine with my filtering, I am able to get exactly what I was looking for.
The command I needed is:
adb logcat -d AccessibilityValidator:E *:S

ADB shell script to send AT commands to a modem-cannot return control to a shell and capture output

I already posted similar question, but still could not get my job done, so this a a second attempt, where
I would like to more clearly state my stumbling block.
So basically I am in Android phone's adb shell, communicating with the GPRS modem by sending AT commands.
I am able to do it by redirecting at command to the device file representing the modem; and I can read back
the response using cat utility running on the background (started earlier). I implemented it in a script
which can send a single AT command and read back the response. For example, here is the script to
send at+cops? to get the name of the operator the mobile is camping on:
#SendATCommand script
cat /dev/pts/7 &
echo -e at+cops?\\r > /dev/pts/7
The output looks as follows:
# ./sendATCommand
./sendATCommand
#
+COPS: 0,0,"AT&T",6
OK
/dev/pts/7: invalid length
Now here are two problems which I cannot resolve:
I still need to manually press ENTER button to get back adb shell prompt "#". Is there a way to return
to "#" prompt programmatically? Again, I am in adb shell.
The displayed response cannot be captured, neither in a variable, nor in file, (such as(#./sendATCommand > output.txt) Output.txt file will be empty. I tried various redirections, but still did not get it to work.
Can anyone please help me resolve those two problems (if ever possible)? Ultimately I want this little script to be
called from a "super" script (e.g. Perl or Powershell) running on PC to which my Android device is
connected, but there is no way to do it until those two problems resolved. Thanks a lot in advance!
I suggest that you try out my atinout program which should be exactly what you are asking for: a program to send AT commands from the command line and capture the output.
In your case the result should be like
$ echo 'at+cops?' | atinout - /dev/pts/7 -
+COPS: 0,0,"AT&T",6
OK
$
and to capture the output just put a file name instead of the last -.
I had similar problems with redirecting output to file. I resolved my problem by adding CMD /c in front of the echo command. I.e. if I understand correctly you need to tell the system that it needs to wait until command finishes executing and only then redirect output to a file. I was doing it in DOS.
Since you are running on ANDROID try adding sh -c in front of your command. Hope it helps.

How to sync Kernel time and logcat time?

I am working on an Android phone based on the Linux Kernel. I'm using kmsg for kernel logs and adb logcat -v time for platform logs. The problem is Kernel logs shows time from 0.000000 and logcat is showing from the start of system time ( For example, if time on the phone is 10.43.00, it'll show the first log from this time )
Now I am unable to compare events from these 2 logs as the time base ( reference) is different. Can anyone kindly point out how to sync these 2 times?
Another solution would be similar to jpg's answer, but in the other direction, redirect
the kernel messages into logcat. This is better, because too many logcat messages might overload the serial console (if you have it active).
you can run this in an android shell:
cat /proc/kmsg | while read LINE; do echo '\06kernel\0'$LINE'\0' > /dev/log/main; done
or this in a host shell:
adb shell '(cat /proc/kmsg | while read LINE; do echo \\06kernel\\0$LINE\\0 > /dev/log/main; done)'
The first time you start the command you will see all of the current dmesg messages in one place, but any further messages will be interleaved, when they appear.
and then examine logcat in a different shell. If you examine logcat with -v time, then the kernel messages will contain both the logcat and the kernel timestamps. Of course there may be delays between the two.
Another, even simpler way to see messages interleaved would be:
adb shell '(logcat & cat /proc/kmsg) > /path/to/log/file'
But in this case it's a little harder to identify messages coming from the kernel, and you can't tell how kernel timestamps relate to logcat timestamps.
you can create a single file containing both kernel and platform logs as follows:
$adb shell
$logcat -v time -f /dev/kmsg | cat /proc/kmsg > /data/klog_plog_log.txt
you can differentiate both the logs using time stamps in the platform logs. And then pull the file to your local drive using
adb pull /data/klog_plog_log.txt > sample.txt
Refer http://jai-tech.blogspot.com/2012/01/taking-kernel-and-platform-logs-of.html . Hope this helps.
Regards,
JP
Pavan,
Perhaps with you can tag your logcat prints with the time since last boot? This should be closer to the time shown in kmsg.
Time since last boot can be retrieved with elapsedRealtime().
The single file method described above is nice but may not always be useful as the input from logcat and kmsg might be delayed due to buffering. So you will most likely see a block of kmsg entries and then a block of logcat entries which might still be interleaved in real time.
That said, you might be able to sync kmsg time and logcat time by looking for device suspend messages in kmsg (grep UTC):
<6>[249485.550811] suspend: exit suspend, ret = 0 (2012-12-27 16:16:46.300872527 UTC)
As you can see those entries in kmsg report the current system wallclock time which can then be synchronized with the kmsg time value. Note however that the kmsg time value does not increase when the device is asleep while the wallclock time obviously does. To that end you will have to resynchronize on the wallclock time on every suspend entry and exit in order to get the correct wallclock time.
I think it can use like this:
adb shell logcat -v time -f /dev/kmsg | adb shell cat /proc/kmsg >sample.txt

Categories

Resources