Android 插件化系列文章目录

【Android 插件化】插件化简介 ( 组件化与插件化 )
【Android 插件化】插件化原理 ( JVM 内存数据 | 类加载流程 )
【Android 插件化】插件化原理 ( 类加载器 )

【Android 插件化】“ 插桩式 “ 插件化框架 ( 原理与实现思路 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 类加载器创建 | 资源加载 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 注入上下文的使用 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 获取插件入口 Activity 组件 | 加载插件 Resources 资源 )
【Android 插件化】“ 插桩式 “ 插件化框架 ( 运行应用 | 代码整理 )

【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )
【Android 插件化】Hook 插件化框架 ( Hook 实现思路 | Hook 按钮点击事件 )
【Android 插件化】Hook 插件化框架 ( Hook Activity 启动过程 | 静态代理 )
【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )


文章目录

  • Android 插件化系列文章目录
  • 前言
  • 一、Activity 任务栈相关源码
    • 1、任务栈管理者 ActivityStackSupervisor
    • 2、任务栈 ActivityStack
    • 3、Activity 启动涉及到的组件
  • 二、Activity 进程相关源码
    • 1、Instrumentation 源码分析
  • 三、博客资源

前言

上一篇博客 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动过程 | 静态代理 ) 使用了静态代理 , hook 了 Activity 的启动过程 ;

在 hook Android 的内部流程时 , 注意版本兼容 , 不同的 Android 版本底层源码实现机制可能有区别 , 需要使用不同的 hook 兼容方式 ;

hook 本身实现起来很简单 , 但是其 与底层源码耦合性太高 , 在 Android 8.08.08.0 可以 hook 住的方法 , 在 Android 10.010.010.0 可能就无法使用了 ;

Hook 插件化框架的 难点是版本兼容 , 需要逐个手动兼容 Android 低版本到最新版本 , 一旦系统更新 , 或者某厂商 ROM 更新 , 都要进行兼容测试以及改进 ;

如果 Android 高版本禁止反射 @hide 方法 , 可以在 调用链上找到一个非隐藏的方法 , 总能 hook 住 ; 极端情况下 , 使用 动态字节码技术 , 在运行时修改字节码数据 , 删除 @hide 注解 ;

插件化模块选择 : 一般的业务逻辑不建议使用插件化 ; 功能比较单一 , 业务逻辑更新比较频繁 , 并且很重要的模块 , 使用插件化实现 ;

插件化框架主要是 通过 hook 修改 Instrumentation , 以及 劫持 ActivityManagerService ;

源码分析的大忌就是死磕每一行源码的细节 , 只看自己能看懂的 , 每个方法最多看 222 层 , 不要偏离主线 ;
现在的源码参考资料很多 , 参考别人已经分析完毕的源码经验 , 可以节省很多时间 ;


一、Activity 任务栈相关源码


基于 Android 282828 源码 , 分析 Activity 的启动过程 ; ( Android 272727 , 282828 , 292929 中 Android 启动源码都进行了不同程度的改进 , 333 个版本的源码是不同的 )

1、任务栈管理者 ActivityStackSupervisor

Activity 任务栈 : ActivityStack ; Activity 启动后 , 都加入到 ActivityStack ( 任务栈 ) 中 ;

任务栈管理者 : ActivityStack 由 ActivityStackSupervisor 来管理 , ActivityStackSupervisor 中有两个数组 , 分别是

  • mHomeStack : Launcher 应用使用的任务栈 ;
  • mFocusedStack : 当前聚焦的任务栈 , 可以接收输入 , 或启动下一个 Activity ;
public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,RecentTasks.Callbacks {/** The stack containing the launcher app. Assumed to always be attached to* Display.DEFAULT_DISPLAY. */ActivityStack mHomeStack;/** The stack currently receiving input or launching the next activity. */ActivityStack mFocusedStack;
}

源码地址 : frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

2、任务栈 ActivityStack

ActivityStack ( 任务栈 ) 中存在两个集合 :

  • ArrayList<TaskRecord> mTaskHistory : 之前运行的 ( 可能仍在运行 ) 的 Activity 的历史记录 , 每个 TaskRecord 都包含了 111 个 ActivityRecord 集合 ;
  • ArrayList<ActivityRecord> mLRUActivities : 当前正在运行的 Activity 列表 , 按照最近最少使用算法 LRU 机制进行排序 , 列表中第一个 Activity 是最近最少使用的 ;

ActivityRecord 就是 Activity 的信息 , 注意不是 Activity 的实例对象 , 是历史任务栈中的一个条目 , 可以代表一个 Activity ;

TaskRecord 中 维护了 111 个 ArrayList<ActivityRecord> , 用于保存 ActivityRecord ;

class ActivityStack<T extends StackWindowController> extends ConfigurationContainerimplements StackWindowListener {/*** The back history of all previous (and possibly still* running) activities.  It contains #TaskRecord objects.*/private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();/*** List of running activities, sorted by recent usage.* The first entry in the list is the least recently used.* It contains HistoryRecord objects.*/final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();
}

3、Activity 启动涉及到的组件

ActivityThread : 应用主线程 , 每个应用都是从该主线程的 main 函数开始的 ;

  • /frameworks/base/core/java/android/app/ActivityThread.java

Instrumentation : 每个 Activity 都持有该类对象 , 档调用 startActivity 启动其它 Activity 时 , 就会调用 Instrumentation 进行先关操作 ; ActivityThread 控制 Activity 也是通过该类进行 ; 一个应用中只有一个 Instrumentation 实例对象 ;

  • /frameworks/base/core/java/android/app/Instrumentation.java

二、Activity 进程相关源码


1、Instrumentation 源码分析

在上一篇博客 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动过程 | 静态代理 ) 一、分析 Activity 启动源码 章节中分析到 , 在 Activity 中调用 startActivity , 最终调用的是 Instrumentation 的 execStartActivity 方法 ;

在 Instrumentation 中的 newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance) 方法 , 用于创建 Activity 实例 , 其中使用了 (Activity)clazz.newInstance() 创建 Activity 示例 ,

    public Activity newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id,Object lastNonConfigurationInstance) throws InstantiationException, IllegalAccessException {Activity activity = (Activity)clazz.newInstance();ActivityThread aThread = null;// Activity.attach expects a non-null Application Object.if (application == null) {application = new Application();}activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,info, title, parent, id,(Activity.NonConfigurationInstances)lastNonConfigurationInstance,new Configuration(), null /* referrer */, null /* voiceInteractor */,null /* window */, null /* activityConfigCallback */);return activity;}

在另外一个重载的 Activity newActivity(ClassLoader cl, String className, Intent intent) 方法中 , 通过指定 类加载器 ClassLoader , Activity 的全类名 , 也可以创建 Activity 实例对象 ;

Hook 劫持 Activity newActivity(ClassLoader cl, String className, Intent intent) 方法 , 传入插件包的类加载器 , 和插件包的类名 , 此时就可以初始化带上下文的 Activity ,

    public Activity newActivity(ClassLoader cl, String className,Intent intent)throws InstantiationException, IllegalAccessException,ClassNotFoundException {String pkg = intent != null && intent.getComponent() != null? intent.getComponent().getPackageName() : null;return getFactory(pkg).instantiateActivity(cl, className, intent);}
public class Instrumentation {public Activity newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id,Object lastNonConfigurationInstance) throws InstantiationException, IllegalAccessException {Activity activity = (Activity)clazz.newInstance();ActivityThread aThread = null;// Activity.attach expects a non-null Application Object.if (application == null) {application = new Application();}activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,info, title, parent, id,(Activity.NonConfigurationInstances)lastNonConfigurationInstance,new Configuration(), null /* referrer */, null /* voiceInteractor */,null /* window */, null /* activityConfigCallback */);return activity;}public Activity newActivity(ClassLoader cl, String className,Intent intent)throws InstantiationException, IllegalAccessException,ClassNotFoundException {String pkg = intent != null && intent.getComponent() != null? intent.getComponent().getPackageName() : null;return getFactory(pkg).instantiateActivity(cl, className, intent);}public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;Uri referrer = target != null ? target.onProvideReferrer() : null;if (referrer != null) {intent.putExtra(Intent.EXTRA_REFERRER, referrer);}if (mActivityMonitors != null) {synchronized (mSync) {final int N = mActivityMonitors.size();for (int i=0; i<N; i++) {final ActivityMonitor am = mActivityMonitors.get(i);ActivityResult result = null;if (am.ignoreMatchingSpecificIntents()) {result = am.onStartActivity(intent);}if (result != null) {am.mHits++;return result;} else if (am.match(who, null, intent)) {am.mHits++;if (am.isBlocking()) {return requestCode >= 0 ? am.getResult() : null;}break;}}}}try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {throw new RuntimeException("Failure from system", e);}return null;}
}

三、博客资源


博客资源 :

  • GitHub : https://github.com/han1202012/Plugin_Hook

【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 一 | Activity 进程相关源码 )相关推荐

  1. 【Android 插件化】Hook 插件化框架 ( 从 Hook 应用角度分析 Activity 启动流程 二 | AMS 进程相关源码 | 主进程相关源码 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  2. 【Android 插件化】Hook 插件化框架总结 ( 插件包管理 | Hook Activity 启动流程 | Hook 插件包资源加载 ) ★★★

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  3. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 主线程创建 Activity 实例之前使用插件 Activity 类替换占位的组件 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  4. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | AMS 启动前使用动态代理替换掉插件 Activity 类 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  5. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | 反射获取 IActivityManager 对象 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  6. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | Hook 点分析 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  7. 深入分析Android 9.0源代码——Activity启动流程

    引言 点击此处查看<深入分析Android 9.0源代码>系列的组织结构和相关说明. 1 应用进程发起启动请求 本章的调用流程如下图所示: (Context) Activity Instr ...

  8. android activity启动流程_1307页!一线大厂Android面试全套真题解析!

    /   前言   / 金九银十到了,很多读者都反映有面试的需求,所以我特地给大家准备了一点资料! 下面的题目都是大家在面试一线互联网大厂时经常遇到的面试真题和答案解析,如果大家还有其他好的题目或者好的 ...

  9. Android Instrumentation源码分析(附Activity启动流程)

    转载请注明出处:http://blog.csdn.net/ahence/article/details/54959235 Instrumentation概念 官方说明 Instrumentation类 ...

最新文章

  1. TreeMap源码分析,看了都说好
  2. 一个基于poi的excel导出程序
  3. 使用参数化SQL语句进行模糊查找
  4. 量化交易系统综述——互联网金融之二
  5. 《京东商业化数据分析师培养计划》
  6. react设置默认props
  7. jQuery的AJAX常用属性及解释
  8. SWPUACM第二次周赛
  9. php根据图片地址获取图片原始高宽,Js获取图片原始宽高的实现代码
  10. es6文档笔记(全)
  11. 自己动手写嵌入式操作系统
  12. IEEE1588v2解析(7)gPTP协议和PTP的关系
  13. 欧盟CE公告号-外贸人不得不了解的通关证书
  14. (function($){...})(jQuery)、$(function(){ })和$.fn
  15. 搭建直播平台源码用到的云技术到底是什么
  16. 通过css实现单选按钮效果
  17. 大家来找茬的部分代码
  18. PHP生成曲线统计图表示例,直方图等数据
  19. 在服务器上虚拟w7,如何在虚拟机中获取Win7 Aero特效(图)
  20. 量子计算机在日常生活中常,量子世界奇妙无比微小的量子极大将会改善我们的日常生活!...

热门文章

  1. 思科防火墙PIX ASA精华配置总结
  2. 今天浏览新闻的时候,发现一张图片特别有感触
  3. [异常特工]android常见bug跟踪
  4. JS两种声明函数的方法以及调用顺序
  5. Android 开发笔记 ListView异步加载图片
  6. HDOJ2795 Billboard【线段树】
  7. LeetCode Range Addition II
  8. redis cluster 集群重新启动关闭
  9. eclipse 集成 github
  10. Python学习记录之-----类