Monday, September 22, 2014

Calling Android services from ADB shell

Many android automation recipes contain references to the "service call" command:

# service
Usage: service [-h|-?]
    service list
    service check SERVICE
    service call SERVICE CODE [i32 INT | s16 STR] ...
Options:
  i32: Write the integer INT into the send parcel.
  s16: Write the UTF-16 string STR into the send parcel.


The command is indeed very useful. But the problem is that the calling "CODES" are android version specific and recipes often get out dated sometimes even after a minor version update. I am frequently being asked to update those codes for my recipes. I decided to share a small bash script I have been using to look up service codes for specific Android versions:


This script checks the Android version of your phone and the java package name of the service you specified as a parameter. Then the script downloads the service AIDL file for your phone's Android version from https://android.googlesource.com and parses it. So obviously it only works for the standard Android services it can find the source code for.

This is how I usually run the script. For example let's find out the calling code for "getCallState()" method of the "phone" service. I usually have multiple phones connected to my system so I need to specify which one to use by setting the ANDROID_SERIAL variable first. If you have just a single phone connected you can skip that part:

~$ ANDROID_SERIAL=XXXXXXXXXX ./get_android_service_call_numbers.sh phone | grep getCallState
ANDROID_SERIAL=XXXXXXXXXX
ro.build.version.release=4.4.4
TAG=android-4.4.4_r1
SERVICE=phone
SERVICE_PACKAGE=com.android.internal.telephony.ITelephony
    32 int getCallState()




3 comments:

  1. Made some changes to work in MacOsX https://gist.github.com/bycosta/ecf652465d6931eb20de/revisions but still not getting the methods and it's integers, could you explain what are you doing on those pipes in the ParseServiceAIDL function?

    ReplyDelete
  2. cool as hell, just what I needed at the moment for bluetooth_manager service

    ReplyDelete
  3. The pipes in ParseAIDLblah should be:

    gcc -P -E - | tr -d '\n\r' | tr '{};' '\n\n\n' | grep -v ^$ | sed -e '1,/interface\s/ d' | cat -n

    To explain...it uses the gcc preprocessor to strip comments, then it strips newlines, so it is one long line...then it uses tr to turn semicolons into 3 newlines (1 necessary and 2 extra??), then it uses grep -v to get rid of the extras, then it uses sed to strip out everything before the "interface" line, leaving just the member functions, then cat -n to display the list of methods with line numbers.

    gcc has to be before tr, or "//" single-line comments wipe out the whole string.

    thanks!

    ReplyDelete