Android shell service 命令

Author Avatar
发表:11月 21, 2018 更新:11月 21, 2018
字数统计:891 字 阅读时长:4 分

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

先看一下 service 用法:

$ 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 用来列出当前可用的系统服务。
    比如:
    $ 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 用来检测指定的服务是否可用。
    比如:
    $ 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 类型。

该命令语法如下:

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
    $ adb shell service list
    43      notification: [android.app.INotificationManager] 
    
    notification 命令对应的系统服务的 aidlandroid.app.INotificationManager.aidl
  2. 其次,在 Androidframework 源码中找到对应的 aidl 文件,详细步骤为:
    • android framework 源码地址为:
      https://android.googlesource.com/platform/frameworks/base/
      
    • 找到对应的系统版本,以 android-9.0.0_r18 为例,该版本源码地址为:
      https://android.googlesource.com/platform/frameworks/base/+/android-9.0.0_r18
      
    • android.app.INotificationManager.aidl 对应的路径为 /core/java/android/app/INotificationManager.aidl,找到地址:
      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 部分片段:

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

  • service call notification 1 
    
    表示清除当前所有的通知,其中 pkg, userId 参数缺省。
  • service call notification 1 s16 'com.example.package'
    
    表示清除当前所有包名为 com.example.package 的 App 发出的通知。
  • 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