Android logging levels - android

I'm having a little difficulty configuring Android logging. Here's what my code looks like:
if (Log.isLoggable("MY_TAG", Log.VERBOSE)) {
Log.v("MY_TAG", "Here's a log message");
}
Pretty simple, right?
However, I'm having quite a bit of difficulty getting the Log.isLoggable("MY_TAG", Log.VERBOSE) to return true.
Per http://developer.android.com/reference/android/util/Log.html, I tried adding a local.prop file to the /data/ directory which looks like this:
log.tag.MY_TAG=VERBOSE
but no luck. I also tried:
System.setProperty("log.tag.MY_TAG", String.valueOf(Log.VERBOSE));
but that doesn't work either.
Any ideas on what I'm doing wrong here? I'm running Android 2.1-update1 on a Nexus 1 if that makes any difference.

Try
adb shell setprop log.tag.MyAppTag VERBOSE

It seems that later versions of Android want /data/local.prop to be writable by root only. The adb push command appears to initially create files with granting everyone read/write access (because default file mask is 777). Android, wisely, ignores /data/local.prop since this can be a security risk.
I have only experimented with Android 2.3.3, and 4.1.2. The former has no issues with reading a local.prop that is world writable, while the latter appears to silently ignore the file's contents.
Creating a local.prop file as described in the original question:
log.tag.MY_TAG=VERBOSE
And then pushing it onto the device as follows seems to do the trick:
adb push local.prop /data/local.prop
adb shell chmod 644 /data/local.prop
adb shell chown root.root /data/local.prop
adb reboot
You can double check to make sure that the values in local.prop were read by executing:
adb shell getprop | grep log.tag
So in summary:
/data/local.prop is only read during boot.
Later versions of Android appear to require that the permissions on the /data/local.prop file must be properly set, or it will not be read. The file must be writable by root only.
Using adb shell setprop log.tag.MyAppTag VERBOSE also work. The issue is that the property values are lost after a reboot.

An important goal is to not ship a production app with a ton of log calls left in it, increasing its size, and even possibly even impacting its performance.
To do this, my recommendation is to put these constants at the top of each class that is going to have log calls:
static final boolean DEBUG = false;
static final String TAG = "<MyClass>"
Now where you log, do this:
if (DEBUG) Log.v(TAG, "Something");
Turn on your logs by changing the DEBUG constant to true. (If you want, you could have one class with these statics for all of your app's code to use... That makes sense for a small app, but as things get large it is nice to decide which parts to turn logging on.)
By doing this, when you build your app with DEBUG = false, all of your logging code not only isn't executed, but is completely stripped out of your app. This is nice because it allows you to leave fairly extensive logging in your code to be turned on when you need it, without worrying about how that will impact the size of your shipping app. Basically just throw logs in wherever you need them and don't worry about leaving them in.
This is the approach that a lot of the Android framework takes. For example, the Activity ManagerService.
This has those constants at the top, and various log lines sprinkled throughout based on them. (And a bunch of other sub-debug constants for various aspects of it, since this file is ridiculously stupidly large.)

Related

How to make multi-devices dump with AndroidViewClient/dump command?

I'd like to compare the screen of my devices (many) so I'm using AndroidViewClient tool to get the hierarchy of my screens with the dump command in a terminal.
However, my devices are all linked with my computer at the same time, and the dump command seem to work on only one device. So when I use the command, I get the dump of the first device in the device list when I use adb devices.
My goal is to compare screens. So what I want is to specify which device I want to use for my dump in the terminal (and then doing it for all my devices to compare).
Is there a solution of this ? because the only solution I found yet is to make an adb -s [device serial_number] shell uiautomator dump, which offer the possibility to chose which device we want to use among those who are attached, but it produce an xml file (and this is why I need AndroidViewClient's dump, because I don't want the xml file).
In other words, is there a way to specify a device with the dump command in a terminal without disconnecting my USBs successively (keep only one device connected at the same time) ?
Thank you very much in advance !
If I understand correctly, you want to dump different devices that are already available through adb.
Getting help you can see that dump accepts an optional command line parameter which is the serialno
$ dump --help
usage: dump [OPTION]... [serialno]
...
You can also take a look at --multi-device option for culebra that can generate tests that run on many devices at the same time.

How to execute ADB commands within an app

I've got a partially rooted android device. By partial root, I mean that I can only run root commands through ADB. I've figured out how to run these commands locally from within a terminal emulator on the device itself. My question is, how would I go about writing the code for an Android application that executes an ADB command (or multiple commands) from a button press? I can't find anything that explains how to run direct ADB commands through an app interface. Just to clarify, anything that involves "su" will not work on this device. It only accepts ADB input for root access.
Not sure if it works on Android, but have you tried this:
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("adb do something as root");
If you provide more info about what exactly you need to use adb for in this manner, there may be a better workaround. It is very unlikely you actually need this behavior in app, and I believe it would be generally frowned upon. It sounds like you want your app to have root, but this seems like a very unportable and unnecessary approach.

scaling_max_freq resists being altered despite write permission

I am trying to change the value stored in /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq which is currently set to "1512000". I am attempting to do this via adb shell.
I type su and then navigate to /sys/devices/system/cpu/cpu0/cpufreq. I then type
chmod 777 scaling_max_freq
I confirm that the chmod worked by typing
ls -l scaling_max_freq
and sure enough it is listed as -rwxrwxrwx. I then type
echo 124200 > scaling_max_freq
and then
cat scaling_max_freq
sadly this reports that the file is unchanged as "1512000". None of the lines executed responded with any kind of error.
Maybe the governor is immediately overwriting this? Maybe I need some extra type of permission? Maybe this is somehow fundamentally not allowed on an android device and I need to control the clock speeds via a different mechanism altogether? The problem must be soluable somehow as it it performed by SetCPU.
BTW, this was all on a rooted Sony xperia z, Android 4.4.2, build number 10.5.A.0.230
Someone suggested attempting to write to scaling_min_freq... I tried it and to my surprise it worked. I was even more surprised when, afterwards I set scaling_max_freq and that worked too. I found this amazing because this document suggests that if anything you should set them in the reverse order.
Anyway, it all seems to be working now.

Android command list

I have many questions about Android command. I do not know where I should start But, anyway, I have put all question related Android commands. Here ;
Is subset of Linux commands come in Android by default ? Or, Are we installing something ?
In system/bin, there are lots of commands. Where can I find their meaning ? I have tried man, but man is not built in.
Can I start and stop application via start and stop command ?
Why cannot I run the reboot from terminal emulator ? The error permission is denied.
NOTE : feel free to reedit the question, if you see meaningless part.
Is subset of Linux commands come in Android by default ? Or, Are we installing something ?
A subset exists by default within the system. Things like ls, cd, mkdir, cat etc... are present. You can gain access to a wider range by installing Busy Box on a rooted device, as stated by Zac.
In system/bin, there are lots of commands. Where can I find their meaning ? I have tried man, but man is not built in.
The ADB Page is a good place to start. That covers many of the basic ADB and shell commands. It states near the bottom:
"For a complete list of commands and programs, start an emulator instance and use the adb -help command."
So you can use adb -help on an emualator or device to see a full list of the ADB and shell commands (note I think this list will be android specific commands only, it won't include things like cd,ls and other basic unix commands).
Can I start and stop application via start and stop command ?
No, it states on the ADB dev page:
start ........ Starts (restarts) an emulator/device instance.
stop ........ Stops execution of an emulator/device instance.
To start an application you'll use the am utility iirc it will look something like am start com.your.packagename It's been a while though, I might have syntax wrong. The instructions are listend if you issue the am command by itself with no params in a shell.
Why cannot I run the reboot from terminal emulator ? The error permission is denied.
The system prevents applications from rebooting the device unless they are signed with the same key as the OS. When you use the terminal emulator you are restricted to whatever permissions that application has declared. The reboot permission is not granted to any third party applications, so it won't work correctly from any terminals. You could probably do it if your device was rooted and you used su though
EDIT:
Here is another good resource that lists more of the shell commands
There are not many Linux commands included in android, however if you are rooted you can easily install busybox which has a large range of linux commands.
You need to have root access to reboot your device via the command line (to prevent any old app being able to do it)

Setting Android Log Levels

Is it possible to set the log levels on a device that is not rooted?
so I want to change the device log level somehow to "debug". is this something that can be done?
since its not rooted i dont think setprop will work.
i can also not change the local.prop file since i do not have permissions to do so.
other than maybe getting lucky and finding a hidden menu that has the log levels in it.
is there a way for me to enhance the log level some other way?
thanks for the help.
setprop:
is temporary until you reboot your device, even on rooted phones.
you can persist properties through reboots if you write them into local.prop which is only possible on rooted phones.
some properties are read-only and can only be changed if you change some init files. That might be even impossible on rooted phones.
each device (or firmware) can have a different set of properties. A rooted phone wouldn't have automatically more.
Loglevels:
If the code that prints the log says Log.d() then it will be on "debug" level and you can't change that unless you change the code and recompile it. There is nothing that hides log messages if you execute a Log.? regardless of level.
the Android framework hides some log messages if you have a release build of your firmware. To show those you need to recompile your firmware as debug build. No chance to get those to show on a rooted phone either.
some messages are controlled by a local variable in the code like if (LOCAL_LOGV) Log.v(... - you need to change the code here to see those too.
some messages are controlled by Config.LOGV (= always false) see Config. No way to change the broken behaviour here either. You need to recompile.
some other logmessages are hidden until you enable a property:
example
public static final boolean DEBUG_SQL_CACHE =
Log.isLoggable("SQLiteCompiledSql", Log.VERBOSE);
// somewhere in code
if (SQLiteDebug.DEBUG_SQL_CACHE) {
Log.d(TAG, "secret message!");
}
if you do adb shell setprop log.tag.SQLiteCompiledSql VERBOSE you should see those messages popping up. Log#isLoggable()
There is no global loglevel I know of.
Let me suggest a tiny replacement for the standard log class (I'm the author)
https://github.com/zserge/log
It's backwards compatible, so you only need to modify your imports. Then you can set the minimal log level for your app via Log.level(Log.D) or Log.level(Log.W) etc, or you can disable logs using Log.useLog(false). No need to modify your existing logging code.
Despite of its small size this logger works with both, JVM and Android, allows you to skip the "tag" parameter, simplifies logging of multiple values separated by commas or using a format string. So it's really convenient, easy to migrate to, and only adds ~4 kilobytes to your APK size.

Categories

Resources