Android随笔-Instrumentation

Android随笔-Instrumentation
一、Instrumentation 的本质定位Instrumentation 是 Android 框架在SystemServerAMS 与 应用组件Activity之间插入的一个代理层/钩子Proxy/Hook。它既负责 Activity 等组件的创建和生命周期分发又是 Android 自动化测试框架的核心基石让测试代码能够与被测应用运行在同一进程中实现对应用的精确控制和监控。它不是一个独立的进程而是作为 ActivityThread 的成员变量存在与应用运行在同一个进程中。SystemServer (AMS) ←──Binder IPC──→ ActivityThread ←──Instrumentation──→ Activity二、核心源码流程Activity 启动中的 Instrumentation2.1 调用链路全景ActivityThread.performLaunchActivity()→ Instrumentation.newActivity() // 反射创建 Activity→ Activity.attach() // 绑定 Context、Window、Token→ Instrumentation.callActivityOnCreate() // 触发生命周期→ Activity.performCreate()→ Activity.onCreate() // 开发者入口2.2 Instrumentation.newActivity() 源码解析// frameworks/base/core/java/android/app/Instrumentation.javapublicActivitynewActivity(ClassLoadercl,StringclassName,Intentintent)throwsInstantiationException,IllegalAccessException,ClassNotFoundException{Stringpkgintent!nullintent.getComponent()!null?intent.getComponent().getPackageName():null;// (1) Android 9 通过 AppComponentFactory 工厂模式创建returngetFactory(pkg).instantiateActivity(cl,className,intent);}关键点工厂模式Android 9 之后引入了 AppComponentFactory允许开发者自定义组件实例化方式插件化框架常利用此点旧版本直接反射Class.newInstance() 调用无参构造器创建 Activityattach 绑定创建后立即调用 activity.attach() 绑定 Context、Window、Token 等核心对象2.3 Instrumentation.callActivityOnCreate() 源码解析// frameworks/base/core/java/android/app/Instrumentation.javapublicvoidcallActivityOnCreate(Activityactivity,Bundleicicle){prePerformCreate(activity);// (1) 前置钩子可重写activity.performCreate(icicle);// (2) 调用 Activity.performCreate()postPerformCreate(activity);// (3) 后置钩子可重写}// Activity.javafinalvoidperformCreate(Bundleicicle){dispatchActivityPreCreated(icicle);// 分发 PreCreate 事件if(mPersistentState!null){onCreate(icicle,mPersistentState);}else{onCreate(icicle);// 最终调用开发者重写的 onCreate()}performCreateCommon();dispatchActivityPostCreated(icicle);// 分发 PostCreate 事件}关键点prePerformCreate / postPerformCreate 是空方法专门留给子类重写——这就是钩子机制测试框架如 AndroidJUnitRunner重写这些方法可以在 onCreate 前后注入 Mock 对象performCreate 是 final 方法框架严格控制生命周期调用顺序三、Instrumentation 作为钩子的设计模式3.1 为什么能 HookInstrumentation 是ActivityThread的一个成员变量// ActivityThread.javapublicfinalclassActivityThread{InstrumentationmInstrumentation;// 单例一个进程只有一个}Hook 原理通过反射替换ActivityThread 中的 mInstrumentation 字段// Hook 伪代码Class?activityThreadClassClass.forName(android.app.ActivityThread);FieldsCurrentActivityThreadFieldactivityThreadClass.getDeclaredField(sCurrentActivityThread);sCurrentActivityThreadField.setAccessible(true);ObjectcurrentActivityThreadsCurrentActivityThreadField.get(null);FieldmInstrumentationFieldactivityThreadClass.getDeclaredField(mInstrumentation);mInstrumentationField.setAccessible(true);Instrumentationoriginal(Instrumentation)mInstrumentationField.get(currentActivityThread);// 用自定义 Proxy 替换InstrumentationproxynewInstrumentationProxy(original);mInstrumentationField.set(currentActivityThread,proxy);3.2 插件化框架如何利用它以 VirtualApk 为例它重写了 Instrumentation 的三个关键方法方法作用execStartActivity拦截 startActivity 请求替换 Intent 中的目标 Activity 为坑位Activity欺骗 AMS 的 Manifest 校验newActivity当 AMS 回调创建坑位Activity 时从 Intent 中还原真实目标 Activity反射创建真正的插件 ActivitycallActivityOnCreate在onCreate之前注入插件的 Resources、Context、Application四、Instrumentation 的关键方法一览方法作用newActivity()反射创建 Activity 实例callActivityOnCreate()触发 Activity.onCreate()callActivityOnStart()触发 Activity.onStart()callActivityOnResume()触发 Activity.onResume()callActivityOnPause()触发 Activity.onPause()callActivityOnStop()触发 Activity.onStop()callActivityOnDestroy()触发 Activity.onDestroy()newApplication()创建 Application 实例callApplicationOnCreate()触发 Application.onCreate()execStartActivity()启动 Activity 的入口可拦截sendPointerSync()发送触摸事件UI 测试sendKeyDownUpSync()发送按键事件UI 测试五、核心作用1. 组件创建与生命周期代理Application 创建Instrumentation.newApplication() 负责创建 Application 对象Activity 启动Instrumentation.newActivity() 负责通过反射实例化 Activity生命周期分发所有 Activity 的生命周期回调onCreate、onResume、onPause 等实际上都是通过 Instrumentation.callActivityOnXXX() 方法分发的也就是说Activity 的启动流程中Instrumentation 是绕不开的关键节点——从 ActivityThread 到 Activity 的创建和生命周期调用都要经过它2. 自动化测试框架这是 Instrumentation 最广为人知的用途测试 APK 和被测 APK 运行在同一个进程中Instrumentation 作为桥梁实现直接交互可以发送 UI 事件点击、按键、触摸等到被测应用可以注入模拟的 Intent 启动 Activity可以控制组件生命周期检查程序运行状态支持创建模拟的系统对象MockContext、MockApplication 等进行单元测试3. 系统与应用交互的钩子类似于 Windows 的 Hook 机制Instrumentation 在系统与应用之间安装了一个监听器监听 Activity 的启动、结束等事件拦截并控制组件间的交互行为可以获取应用上下文的 Handle从而深入洞察应用内部状态4. 典型使用场景场景说明单元测试ActivityUnitTestCase可注入 MockContext/MockApplicationUI 自动化测试ActivityInstrumentationTestCase2可发送按键/触摸事件应用性能监控通过自定义 Instrumentation 统计 Activity 启动耗时热修复/插件化某些方案通过替换 Instrumentation 实现组件的动态加载自动化测试框架Espresso、UI Automator 等底层都依赖 Instrumentation5. 在 Manifest 中的配置instrumentationandroid:nameandroidx.test.runner.AndroidJUnitRunnerandroid:targetPackagecom.example.myappandroid:handleProfilingtrueandroid:functionalTestfalse/android:name指定 Instrumentation 的实现类测试 Runnerandroid:targetPackage指定被测应用的包名运行测试时AMS 会先杀掉目标应用进程然后以 Instrumentation 为入口重新启动确保测试代码和被测代码在同一进程内运行六、总结Instrumentation 的核心原理是Android 框架在「系统服务层」与「应用组件层」之间插入了一个「代理/钩子」。它通过「反射创建」「生命周期中转」「可重写钩子」三大机制实现了对 Activity 等组件的创建控制、生命周期监控和测试注入。