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代码- // 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);
// 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代码- 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);
- ……
- }
- }
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代码- String[] files = dir.list();
String[] files = dir.list();
以及之后的for循环
3.之后的部分比较无聊,我们直接跳到parseApplication函数部分
Java代码- 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);
- }
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
- 《Android第一行代码》笔记
- Android开心消消乐代码实例详解
- Android的static静态变量
- Android同一套代码打多个APP包并能够在同一个手机上安装运行
- android实现短按电源键关机的实现代码
- strcpy函数在android中的实现
- android sqlite 批量插入数据优化代码