During my research on dynodroid, I wanted to know the effectiveness of my technique in terms of the method coverage (No of methods in side the app which are triggered at least once) of the app under test.
For this I have made few modifications to the dalvik profiling facility to get this information in most desirable way. Note: The trace facility provided by android is way too verbose, collects lot of data (like timings, thread info etc) and will stop once the size of the trace reach certain size. Thus not suitable for my purpose (i.e get all the methods only inside the app, that are called at least once)
I have made few changes to the following files of the android sources:
- dalvik/vm/Profile.h
- dalvik/vm/Profile.cpp
- dalvik/vm/Globals.h
- dalvik/vm/oo/Object.h
- dalvik/vm/Dvm.mk
- dalvik/vm/native/dalvik_system_Zygote.cpp
The changed files (for 4.3) , along with the app : RandomMusicPlayer are present at: https://github.com/Machiry/DalvikUtils/tree/master/DexMethodCoverage
Note: These changes will disable the default tracing facility in android, you will no longer be able to use the trace facility of android.
Usage:
Assuming you built the android image with the above changes and using it.
1) You need to first tell the dalvik, which app you are interested, this information can be reliably provided by providing the information about the dex file contained in the app. You can specify the dex file info by providing its checksum. Each dex file has a checksum in the header which uniquely identifies itself. After installing the app on the device/emulator, you can get the odex (optimized dex file) form the: /data/dalvik-cache folder of the device, the file name generally contains the app package name.
For ex: after installing the app RandomMusicPlayer (whose package name is: com.example.android.musicplayer), I found the odex in the dalvik-cache as:
/data/dalvik-cache/data@app@com.example.android.musicplayer-1.apk@classes.dex
Next, get the odex file by using adb pull.
adb pull /data/dalvik-cache/data@app@com.example.android.musicplayer-1.apk@classes.dex .
sdk_install_folder/build-tools/18.0.1/dexdump -f data@app@com.example.android.musicplayer-1.apk@classes.dex | grep checksum | head -n 2 | tail -n 1
Usually, you will get output of the form : checksum : 0dbf1e3d
Now copy only the checksum i.e: 0dbf1e3d to a file named : toTrackDexFile.txt, also copy the package name of the app you want to track to a file named: toTrackPackage.txt
for the RandomMusicPlayer app:
toTrackDexFile.txt contains (This mostly will be different if you rebuild the app):
0dbf1e3d
toTrackPackage.txt contains (This should be same for a given app):
com.example.android.musicplayer
After this:
- adb push toTrackDexFile.txt /sdcard/toTrackDexFile.txt
- adb push toTrackPackage.txt /sdcard/toTrackPackage.txt
in the same order.
Then you can start the app and use it, all the methods that are called will be logged in logcat. to get the filtered logs use:
adb logcat | grep DVM_M3_Method , you will find all the methods in the corresponding dex file which were called atleast once.
Note: In the log you will see the method only once irrespective of the number of times that method is actually called.
Have fun.