0%

Android shell service 命令

Android Shell 中有 service 命令,其二进制文件位于 /system/bin/service,该命令可以用来调试,甚至是应用于开发。

用法

先看一下 service 用法:

1
2
3
4
5
6
7
8
9
10
11
$ adb shell service
Usage: service [-h|-?]
service list
service check SERVICE
service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...
Options:
i32: Write the 32-bit integer N into the send parcel.
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.
s16: Write the UTF-16 string STR into the send parcel.
  1. service / service -h / service -? 都是用来获取 service 命令帮助信息的命令。

  2. service list 用来列出当前可用的系统服务。
    比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ adb shell service list
    Found 126 services:
    0 sip: [android.net.sip.ISipService]
    1 Genyd: [com.genymotion.genyd.IGenydService]
    2 SystemPatcher: [com.genymotion.systempatcher.ISystemPatcher]
    3 carrier_config: [com.android.internal.telephony.ICarrierConfigLoader]
    4 phone: [com.android.internal.telephony.ITelephony]
    ...
    43 notification: [android.app.INotificationManager]
    ...
  3. service check SERVICE 用来检测指定的服务是否可用。
    比如:

    1
    2
    $ adb shell service check notification
    Service notification: found

    表示 notification 服务可用。

  4. service call 命令用来调用服务中的方法,具体在下文单独说明。

service call 命令

service call SERVICE CODE [i32 N | i64 N | f N | d N | s16 STR ] ...
此命令用来调用服务中的方法,其中:

  • SERVICE 代表服务名称;
  • CODE 代表所要调用的的服务中的方法在其 aidl 文件中对应的位置,第几个位置就调第几个方法;
  • [i32 N | i64 N | f N | d N | s16 STR ] ... 表示方法的参数,其中:i32 表示 int 类型,i64 表示 long 类型,f 表示 float 类型,d 表示 double 类型,s16 表示 String 类型。

该命令语法如下:

1
2
3
service call <your_service_name> <number at which the founction in your_service_name.aidl> <type of argument> <argument>

service call <服务名> <服务名.aidl中的第几个方法> <参数类型> <参数值>

那么 SERVICE 所代表的系统服务的 aidl 源文件到底在哪儿看呢?下文以 notification 系统服务为例。

  1. 首先调用 service list 找到指定系统服务对应的 aidl

    1
    2
    $ adb shell service list
    43 notification: [android.app.INotificationManager]

    notification 命令对应的系统服务的 aidlandroid.app.INotificationManager.aidl

  2. 其次,在 Androidframework 源码中找到对应的 aidl 文件,详细步骤为:

    • android framework 源码地址为:

      1
      https://android.googlesource.com/platform/frameworks/base/
    • 找到对应的系统版本,以 android-9.0.0_r18 为例,该版本源码地址为:

      1
      https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r18
    • android.app.INotificationManager.aidl 对应的路径为 /core/java/android/app/INotificationManager.aidl,找到地址:

      1
      https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r18/core/java/android/app/INotificationManager.aidl

    最终地址为:android-9.0.0_r18 INotificationManager.aidl

我们看一下 android-9.0.0_r18 版本的 INotificationManager.aidl 部分片段:

1
2
3
4
5
6
7
8
9
10
11
12
interface INotificationManager
{
void cancelAllNotifications(String pkg, int userId);
void clearData(String pkg, int uid, boolean fromApp);
void enqueueToast(String pkg, ITransientNotification callback, int duration);
void cancelToast(String pkg, ITransientNotification callback);
void finishToken(String pkg, ITransientNotification callback);
void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
in Notification notification, int userId);
void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
// ... 省略
}

cancelAllNotifications() 对应的 CODE 就是 1

  • 1
    service call notification 1

    表示清除当前所有的通知,其中 pkg, userId 参数缺省。

  • 1
    service call notification 1 s16 'com.example.package'

    表示清除当前所有包名为 com.example.package 的 App 发出的通知。

  • 1
    service call notification 2 s16 'com.example.package' i32 108 i32 1

    表示调用 clearData("com.example.package", 108, 1); 其中布尔值 true132 1 表示。

小结

service call CODE 中的 CODE 根据当前系统版本对应的 aidl 变化而变化,适用于调试,而应用于产品开发则需要充分考虑版本问题。

参考

Answer - Where to find description of all ‘/system/bin/service’ calls