android安全问题(六) 抢先接收广播 - 内因篇之广播接收器注册流程

 导读:本文说明系统是如何注册动态广播以及静态广播,这里主要注意其注册的顺序

 

这篇文章主要是针对我前两篇文章

android安全问题(四) 抢先开机启动 - 结果篇

android安全问题(五) 抢先拦截短信 - 结果篇

之前只给出了结果,并没有给出代码分析,现在给出第一步分的分析

 

大家都知道,广播接收器分为动态注册和静态注册两种

静态接收,就是配置到manifest.xml文件中,PackageManagerService扫描后记录其信息……

动态接收,就是从代码中注册,通过调用下面的方法实现

Intent android.content.Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

(下面的流程图估计画的比较水,将就看一下吧,得补习一下UML了)

首先分析静态注册Receiver的流程

静态receiver的注册是由PackageManagerService开机的时候负责初始化

(PackageManagerService之后简称为PMS)

PMS在开机的时候会对系统一些目录逐个扫描,解析apk文件。静态广播接收器就是在PMS做这件事情的时候顺便处理的。

PMS会解析apk的manifest文件,查找这里注册的receiver,然后加载到内存中

下面看一下PMS是如何工作的

这部分内容没有什么难度,只要有耐心就行,我画了一个很简单流程图,从调用PMS的构造函数开始

注意,这里有几个同名函数,大家需要分清。并不是同一个函数调用了两次

这里只看几处

1.PMS初始化的时候干了些什么

当然,PMS会做很多很多事情,这里我们只看我们关注的,和这篇文章相关的部分

Java代码 复制代码 收藏代码
  1. // Collect all system packages.
  2. mSystemAppDir = new File(Environment.getRootDirectory(), "app");
  3. mSystemInstallObserver = new AppDirObserver(
  4. mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
  5. mSystemInstallObserver.startWatching();
  6. scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
    mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

扫描目录的顺序

system/framework

system/app

vendor/app

data/app

drm/app-private

这里以system/app目录为例

 

2.下一个要关注的地方是

void com.android.server.pm.PackageManagerService.scanDirLI(File dir, int flags, int scanMode, long currentTime)

Java代码 复制代码 收藏代码
  1. private void scanDirLI(File dir, int flags, int scanMode, long currentTime {
  2. String[] files = dir.list();
  3. ……
  4. int i;
  5. for (i=0; i<files.length; i++) {
  6. File file = new File(dir, files[i]);
  7. ……
  8. PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
  9. ……
  10. }
  11. }
private void scanDirLI(File dir, int flags, int scanMode, long currentTime {
    String[] files = dir.list();
    ……
    int i;
    for (i=0; i<files.length; i++) {
        File file = new File(dir, files[i]);
	……
        PackageParser.Package pkg = scanPackageLI(file, flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);
	……
    }
}

注意

Java代码 复制代码 收藏代码
  1. String[] files = dir.list();
String[] files = dir.list();

以及之后的for循环

 

3.之后的部分比较无聊,我们直接跳到parseApplication函数部分

Java代码 复制代码 收藏代码
  1. else if (tagName.equals("receiver")) {
  2. Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
  3. if (a == null) {
  4. mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
  5. return false;
  6. }
  7.  
  8. owner.receivers.add(a);
  9. }
else if (tagName.equals("receiver")) {
    Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
    if (a == null) {
        mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
        return false;
    }

    owner.receivers.add(a);
}

这部分就是解析manifest中的receiver部分,大家会很奇怪,receiver为什么会变成一个Activity

此Activity非彼Activity,这个Activity是PackageParser的一个内部类,结构也非常简单

你可能感兴趣的:(android,广播,接收器)