Jimmy Chen

A Programmer

(原创)pm指令源码分析

  平时在开发调试的时候用pm指令用得蛮多的,pm指令可以列出系统支持的feature、permission和当前已安装的apk等信息。所以今天我们来阅读一下pm指令的代码,做下简单分析。

Android.mk

  首先我们来查看一下编译pm指令的Android.mk,看看pm指令包含哪些源码文件。Android.mk文件路劲为frameworks/base/cmds/pm

pm指令源码

  从上面的Android.mk可以了解都pm是一个预编译的可执行文件,文件源码为pm,接下来我们查看该文件的源码

从注释处就可以看出,这是一个shell文件。因为shell在native层执行,所以需要在shell文件中通过app_process来创建一个Java进程,随后执行com.android.commands.pm.Pm包的main方法。接下来我们接着分析com.android.commands.pm.Pm的main方法。

pm.jar

  main方法如下:

main方法只是个幌子,真正做事情的是run方法

pm支持的功能用法很多,如果不清楚可以adb shell连接到手机后直接执行pm列出pm支持的用法。这一篇我们分析先分析pm isntall xxx.apkpm list packages -f方法。

pm install安装apk

  从上面run方法可知,pm install方法主要是调用runInstall方法

如果有看博主前面对PackageInstaller源码分析的博文的话,对上面部分的代码就比较好了解了。所以这里也不多做解析。

pm list packages -f

  list功能走的是runList方法

  runList通过调用runShellCommand实现。

  上面通过ServiceManager的getService方法获取到对应的service,从前面的调用可以看到,调用的service是package。博主前面对PackageManagerService的介绍有提及,这个package服务就是PackageManagerService。所以这里应该调用的是PackageManagerService的shellCommand方法。按照binder调用过程列举如下:

  1. BinderProxy.shellCommand
  2. BinderProxy.transact
  3. transactNative
  4. 通过JNI调用到android_util_Binder.cpp中的android_os_BinderProxy_transact方法
  5. binder.transact
  6. binder.shellCommand
  7. binder.onShellCommand

具体的调用大家可以按照上面的过程查看,这里就省略掉不写了。按照最后的binder.onShellCommand方法,这个方法一般到了具体的service里面,都是会被重载的,所以我们可以直接看PackageManagerService的onShellCommand方法。

  onShellCommand方法继承自ShellCommand方法,所以这里调用的是ShellCommand的exec方法。

  紧接着调用onCommand方法进行处理。

又是各种判断后调用具体的方法进行处理。这里是runList

  紧接着是packages,所以调用runListPackages方法

这篇就到这里了,pm的源码看起来还是比较简单的,但是却也是挺有用的,后续如果需要开发类似的工具,这里很多代码都是可以借鉴的。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注