34

Using adb shell or a terminal emulator on the device, entering this will clear all notifications (requires su)

service call notification 1

This will send an sms (doesn't require su)

service call isms 5 s16 "PhoneNumber" i32 0 i32 0 s16 "BodyText"

Where can I learn more about service call? I've found this question and appreciate the answer's breakdown as to what everything means. But where can I find info on what method notification 2 might be trying to call?

Running service call was incomplete and printed this usage:

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.

I ran service list and it came back with 78 services for my device including isms and notification and for most services will print what seems to be a namespace (com.android.internal.telephony.ISms for isms and android.app.INotificationManager for notification). How can I use this information to find out what I can do with each of these services?

royatirek
  • 2,437
  • 2
  • 20
  • 34
Corey Ogburn
  • 24,072
  • 31
  • 113
  • 188

5 Answers5

27

In Short

Code related to service call command are just the arguments of the function and order at which the function occur in the aidl file of that service.Here is a syntax

service call <your_service_name> <number at which the function appears in your_service_name.aidl> <type of the argument like i32 or i64> <argument>

In Detail
I faced a lot of problems to know about it and hence I will share the solution with the help of clipboard service.
First you need to know about the service you are interested in -
For that you need to look for all the service that is there for particular android system by typing

adb shell service list

Here is what you will get -

.
.
.
59  ethernet: [android.net.IEthernetManager]
60  wifip2p: [android.net.wifi.p2p.IWifiP2pManager]
61  rttmanager: [android.net.wifi.IRttManager]
62  wifiscanner: [android.net.wifi.IWifiScanner]
63  wifi: [android.net.wifi.IWifiManager]
64  overlay: [android.content.om.IOverlayManager]
65  netpolicy: [android.net.INetworkPolicyManager]
66  netstats: [android.net.INetworkStatsService]
67  network_score: [android.net.INetworkScoreService]
68  textservices: [com.android.internal.textservice.ITextServicesManager]
69  network_management: [android.os.INetworkManagementService]
70  clipboard: [android.content.IClipboard]
71  statusbar: [com.android.internal.statusbar.IStatusBarService]
.
.
.

As I am interested in clipboard service, here is how it look

70  clipboard: [android.content.IClipboard]

So from here we can summarise that the service name is clipboard service and the package path is android.content.IClipboard

Then you need to know the complete path where the IClipboard.aidl is.
To know that you need to search on google for IClipboard.aidl.
You need to look for something from android.googlesource.com website in the results, like in my case-

https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/java/android/content/IClipboard.aidl

So after +/android-4.2.2_r1 is where your path lies.Let that path be path_of_clipboard.aidl=

/core/java/android/content/IClipboard.aidl

As these service call codes are dependent on the android system, hence you need to know your android os name- In my case it is 8.1.0
So I will go to the following website where google puts there code and select my os version from the left hand side for the page -

https://android.googlesource.com/platform/frameworks/base/

In my case it is android-8.1.0_r50. Here r50 is not important. You can choose any revision. Now I will click on the link and then after that my url will look like this

https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r51

And then after adding path_of_clipboard.aidl, my complete url will look like

https://android.googlesource.com/platform/frameworks/base/+/android-8.1.0_r51/core/java/android/content/IClipboard.aidl

Here there will be many methods in the interface.Like in my case

    void setPrimaryClip(in ClipData clip, String callingPackage);
    ClipData getPrimaryClip(String pkg);
    ClipDescription getPrimaryClipDescription(String callingPackage);
    boolean hasPrimaryClip(String callingPackage);
    void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
            String callingPackage);
    void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
    /**
     * Returns true if the clipboard contains text; false otherwise.
     */
    boolean hasClipboardText(String callingPackage);

So the code for the first method i.e. setPrimaryClip will be 1 as it occured at first place and that for the last method i.e hasClipboardText will be 7 as it occured at seventh place in the aidl file. Similarly for the other methods.
So if I want to call the seventh method I will type

adb shell service call clipboard 7 

As you might have seen that I have not put the callingPackage name as it is not required.

If the method need arguments, then you can pass it like as show in this example.
Let us assume a method whose code is 8 in clipboard and that looks like this -

getDemo(String arg1, int arg2, boolean arg3)

So I will call it like this

adb shell call clipboard 8 s16 "first_argument" i32 12 i32 1

Here i32 stands for 32 bit integer and s16 for the string. We can, even pass boolean value as an integer as shown in the example.
In boolean integer 1 stands for true and 0 for false.
Source

TIP Keep the logcat open(like in android studio) to check for any error that occured while executing that adb command.

royatirek
  • 2,437
  • 2
  • 20
  • 34
  • "In my case it is android-8.1.0_r50": Are you referring to the Android version on the individual device, or the compileSdkVersion in the Gradle config? – Always Lucky Dec 11 '18 at 18:01
  • r50 is not important as they will not introduce new function in the interface file between revisions. I have edited it. – royatirek Dec 11 '18 at 18:44
  • That is good to know, and good answer btw. However, my question is: Are we looking for the installed device Android OS version, or the version the app is compiled with? (ie compileSdkVersion) – Always Lucky Dec 11 '18 at 18:56
  • We are taking about installed version on device as the version associated with the app does not make any sense to me. – royatirek Dec 11 '18 at 19:06
  • 1
    Perfect, thanks for clarifying. I wasn't sure if the compiled version of the app that was making the call altered how the shell command was interpreted. (ie app compiled with Pie SDK 28 running on an Oreo OS) – Always Lucky Dec 11 '18 at 19:14
15

Here is my post about Calling Android services from ADB shell. It includes a small bash script I use to automatically download the proper version of service source code for my specific device and then parse it to find out the transaction codes for all methods.

Alex P.
  • 30,437
  • 17
  • 118
  • 169
  • 3
    This is really the answer! Too bad it took me 2 years to find your script! For others to know, every service call is AOS/API dependent to a large extent, the lower the call number the more likely it is to be compatible across AOS versions. For higher numbers, for example `service call phone 87 i32 0 i32 1` (to set network to use 2G GSM only) will most likely to fail on all other devices than it was intended for. – not2qubit Feb 03 '17 at 11:46
  • I think strictly speaking this should be flagged as a link-only answer. Could you please review and summarise the core of the linked solution? I.e. not "what" it does (that is already here) but "how", the core of the technical solution details. @AlexP. Because I really would feel weird to flag and get a 9 year old and quite upvoted answer deleted... – Yunnosch Feb 14 '23 at 14:13
7

My first answer here so I hope will be useful for you.

To explain this small riddle let me use android 4.3.1. This link could be essential in your case. Scroll down the java code to line 669. There is waiting for you TRANSACTION block strictly related with com.android.internal.telephony.ISms service and probably your answer what you can do more.

In your case you are invoking TRANSACTION_sendText. Explanation is in line 673 where you can find

static final int TRANSACTION_sendText = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);

The last part of code consist digit "4". Each TRANSACTION number + 1 = the proper one. That is why service call isms 5 is responsible for sendText and not for sendMultipartText.

The same rule applies for all services.

I am sure that you find out how to check TRANSACTIONs for notification service now. Good fun.

msobolak
  • 71
  • 1
  • 4
  • 1
    The java file you linked to is not part of the official source code tree. It's being generated from the AIDL file - https://android.googlesource.com/platform/frameworks/base/+/android-4.3.1_r1/telephony/java/com/android/internal/telephony/ISms.aidl . I find it easier to parse too – Alex P. Sep 23 '14 at 05:06
  • @AlexP That's missing the point--the information you need to do this is *in* the compiled file. The source AIDL file doesn't have the transaction numbers at all, since they're generated when it's compiled. – Glenn Maynard Nov 28 '16 at 03:35
  • @GlennMaynard, I am not missing anything. I am more than capable of counting the lines in a text file myself - that's the whole extent of the relevant (to finding the transaction number) part of the AIDL compilation process. – Alex P. Nov 28 '16 at 09:45
  • 1
    Easier to count the number of functions (a page apart each--you're not counting lines, and there can be dozens) and hope you mentally compile the file in the same way, than to search and see the actual constant value right there? Sorry if that feels a bit contrived. – Glenn Maynard Dec 07 '16 at 00:06
1

As you already found out, running service list shows you all the available services for your device. Moreover, it shows you the java package name for each service (in your example, it's android.app.INotificationManager for notification).

You can then look up the source code for such package, given your Android release is AOSP or close to it. There you have a list of all the commands available for that service. You call the specific command by its number.

The problem is that the commands are android version specific. Alex P. has shared a bash script (https://stackoverflow.com/a/25987165/16725644) that looks up service codes for the specific Android version your device is running. The 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 file for your phone's Android version from https://android.googlesource.com and parses it. His linked bash script is awesome, although outdated with current Android releases. I have updated his script and posted it here: https://pastebin.com/xQ21EZJh

Running fine with A10 and A11 at least! But I guess it works fine with the latest releases too.

For example, I've been using it to catch the service call number to increase the background process limit, with the following command on A11:

service call activity 43 i32 xxx

The script needs a working adb environment and your device connected.

All credits to Alex P., thanks Alex!

noric
  • 36
  • 3
  • You know about the commenting privilege which you do not have, so well that you can even put it into words. You are aware of the rule https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead . In that situation please do not decide to misuse a different mechanism (an answer) for something it is not meant for and which you are not allowed yet to do. – Yunnosch Feb 13 '23 at 06:31
  • As an alternate option to deleting this or having it deleted, you can [edit] it into an actual answer to the question according to [answer]. – Yunnosch Feb 13 '23 at 06:32
0

Using service call notification 1 etc is not safe as it may do something entirely different on any device you run it on.

You can use android-svc instead. E.g. to dial a number (without calling):

android-svc --adb call 'phone.dial("555-0199")'

It also gives you information on the data types. E.g.

android-svc --adb method-signature 'phone.dial'

Will print:

void dial(String number);

It can also list methods for a given service in the first place...

This gif is taken from the repository: demo.gif


Please note that your isms call to send an SMS wouldn't work anymore in recent versions of Android, as the isms service doesn't have a sendText method anymore. You'd probably have to use sendTextForSubscriber now, which is more difficult to call because it takes way more parameters.


Also, to directly answer your question Where to find info on Android's "service call" shell command?: Look at the source code.

Usage: service [-h|-?]
       service list
       service check SERVICE
       service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR | null | fd f | nfd n | afd f ] ...
Options:
   i32: Write the 32-bit integer N into the send parcel.
   s16: Write the UTF-16 string STR into the send parcel.
AVAILABLE SINCE ANDROID 6:
   i64: Write the 64-bit integer N into the send parcel.
   f:   Write the 32-bit single-precision number N into the send parcel.
   d:   Write the 64-bit double-precision number N into the send parcel.
AVAILABLE SINCE ANDROID 11:
  null: Write a null binder into the send parcel.
    fd: Write a file descriptor for the file f to the send parcel.
   nfd: Write file descriptor n to the send parcel.
   afd: Write an ashmem file descriptor for a region containing the data from file f to the send parcel.
HIDDEN OPTION THAT HAS ALWAYS BEEN AVAILABLE:
intent: Write and Intent int the send parcel. ARGS can be action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]
Forivin
  • 14,780
  • 27
  • 106
  • 199