Android框架开发实战:系统服务与Binder通信机制解析 Android框架开发这事儿很多人一听就觉得高不可攀觉得这是系统工程师的专属领域。但我在这个圈子里摸爬滚打了这么多年说实话框架开发的门槛并没有想象中那么高关键在于你得先弄明白框架到底在解决什么问题又是怎么把上层应用和底层硬件串起来的。这篇文章我就用自己实际踩过的坑、趟过的路把Android框架开发这个事儿从头到尾捋一遍希望能给正准备入坑或者已经在坑边徘徊的朋友一些实打实的参考。1. 项目概述框架层到底在做什么1.1 核心需求解析先说说框架开发是干嘛的。Android系统从上到下大致分这么几层应用层、框架层Framework、系统运行库层包括ART虚拟机、各种native库、Linux内核层。我们平时写App用的那些API——Activity、Service、ContentProvider、View体系、WindowManager、PackageManager全部是框架层暴露给应用层的接口。框架层本质上是应用和系统底层之间的“翻译官”和“调度中心”它把内核的复杂能力封装成一个个清晰的对象和接口让应用开发者不必直接面对Binder驱动、Socket、内存映射这些底层细节。所以框架开发的核心需求其实就两块一是扩展系统能力比如你要在系统里加一个别人没有的服务或者给某个已有服务增加新功能二是打通软硬件通道比如你的设备有一个特殊的传感器厂商就得在框架层写代码把硬件数据变成上层能识别的SensorEvent。这两块看似简单实际做起来涉及的东西非常多从Binder通信机制、AIDL接口定义到系统服务的管理方式、权限模型再到SELinux策略配置任何一个环节不熟都会被卡得死死的。我见过不少开发者应用层写得很溜但一看框架层的源码就头大原因很简单应用层开发是“你给我什么我用什么”而框架开发是“我说了算我定义规则”。思维模式的转换是入门框架开发的第一道坎。1.2 这类项目适合什么人如果你满足下面任意一条这篇文章就是写给你的已经有一年以上Android应用开发经验对Activity、Service、BroadcastReceiver这些组件的工作原理不再满足于“会用”想知道它们背后是怎么被系统管理的。在从事系统定制、行业终端、车机系统、电视盒子这类软硬一体项目的开发经常需要修改或扩展系统能力。对公司自研的ROM或者内部平台方案感兴趣想搞清楚系统服务、权限、资源管理的来龙去脉。如果你还完全不会写Android代码那建议先去把应用层基础打牢直接上框架层会非常痛苦因为框架开发涉及的知识深度和广度都远超普通应用开发没有一定的代码阅读能力、内存模型理解能力和多线程功底很容易被源码“淹死”。2. 项目整体设计与技术选型思路2.1 方案选型背后的考量做框架开发动手写代码之前必须先搞清楚一件事你要在系统哪个层次动手。同一个需求放在不同层次实现工作量、稳定性、后续维护难度天差地别。举个例子假设产品要做一个“应用启动加速”的功能。这个功能可以有三个实现层次第一层纯应用层方案。写一个后台服务监听应用启动事件提前预热某些页面。好处是简单灵活跟着系统OTA走坏处是受限多能做的事情有限。第二层框架层方案。修改ActivityTaskManager或ActivityManager里应用启动流程的代码在合适的节点做并行初始化或资源预加载。能力强很多但需要改系统代码编译进ROM风险也大。第三层底层方案。在ART虚拟机层面做启动加速或者修改内核的进程调度策略。效果最直接但可维护性最差厂商一般不轻易动这一层。我做框架选型时有一条经验原则能用上层解决的绝不往下沉能往应用层靠的绝不做系统级修改。别看框架开发听起来高大上真正的高手都在克制自己改底层的欲望因为每往下沉一层引入的不确定性就指数级增长。系统服务的崩溃可不比App的崩溃一个SystemServer崩了整个系统重启的节奏。2.2 开发模式与分工策略框架开发和普通应用开发的协作模式是完全不同的。应用开发一般一个人或者一个小团队负责一个模块就行框架开发不行它天然要求你与硬件适配、稳定性、安全、性能各个方向的团队协同。我自己参与过的典型项目里框架开发的工作流大致是这样的由架构师或技术经理明确需求落点确定要修改的模块和层次。负责该模块的框架开发工程师出详细设计文档这个文档必须包含涉及的系统服务、Binder接口改动、权限方案、SELinux策略变更点、资源文件定义、兼容性影响面。评审通过后开始开发开发过程中要同步维护HAL硬件抽象层接口的兼容性因为框架层和HAL层经常是强耦合的。完成后接入CTS/VTS兼容性测试以及内部稳定性压测这里重点看SystemServer的存活时间、ANR率、进程内存水位。最后才能集成进系统版本。这套流程看起来繁琐但能帮你挡掉大量的低级问题和后期返工。我见过有人直接在主线代码上闷头改结果改完发现和SELinux策略冲突服务起不来又花了一整周排查这种情况真的没必要。3. 核心技术基础与环境准备3.1 AOSP源码环境搭建踩坑实录做框架开发源码编译环境是最基本也最容易出问题的一环。网上教程一抓一大把但多是照搬官方文档实际操作起来坑非常多。我把自己常用的一套环境配置说下仅供参考。操作系统我用的Ubuntu 22.04 LTS64位内存不低于32GB磁盘建议预留500GB以上。AOSP全量编译对CPU核心数很敏感建议16核起步少了编译时间会让人崩溃。JDK版本要按照你编译的Android版本来选Android 12及以上用OpenJDK 11某些版本用17Android 8到11用OpenJDK 8。这一步搞错编译到一半直接报版本错误非常浪费时间。如果你的机器内存不够建议手动设置swap分区我一般分40GB左右的swap空间实测能显著降低OOM导致的编译失败概率。初始化仓库时repo这个工具得用对。很多新手镜像源配不好拉源码拉到怀疑人生。我这里说一个通用做法从清华或者中科大镜像源拉取主线代码mkdir aosp cd aosp repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-13.0.0_r1 repo sync -c -j16这里有个小技巧-c参数只拉当前分支不带历史标签和分支信息能省不少带宽和时间。如果中途因为网络中断repo sync续传即可不用重新拉。拉完源码后用repo status确认当前分支的完整性再检查有没有未同步完成的异常状态。编译前要先把环境变量和lunch选好source build/envsetup.sh lunch aosp_arm64-userdebug make -j16这个-j16不是越大越好如果你有32核可以试试make -j32但要注意内存。我见过一台128G内存的机器开-j64直接内存溢出的情况。实际经验是make线程数控制在“CPU核心数2”以内比较稳。3.2 调试工具链与真机调试经验框架开发不像应用开发不能随时在身上插个Android Studio就跑。最常见的做法是刷入userdebug版本的ROM因为它保留了adb root权限、remount系统分区等调试能力。注意userdebug和eng版本的区别eng版本有更多调试工具但稳定性差不适合日常使用。真机调试框架代码时最关键的三个工具adb logcat -b system系统服务日志单独拿一个buffer维护刷Subsystem相关崩溃时这个命令比全量logcat要清晰得多。adb shell dumpsys用于查看系统服务的内部状态、内存占用、进程信息。框架服务出了问题dumpsys的输出往往能直接定位问题模块。adb shell kill -3 pid向SystemServer进程发送SIGQUIT信号让它打印所有线程的trace信息。遇到系统服务无响应ANR时这是定位卡点最直接的手段。还有一个我自己很常用的做法修改框架层的Java代码后不一定非得整体编译出ROM再刷机可以单独编译修改的模块。source build/envsetup.sh mmm frameworks/base/services/core或者用make加模块名生成的services.jar会输出到out/target/product/xxx/system/framework/下然后你用adb remount把它推到真机上重启即可。这套“模块级编译单独push”的流程能节省大量时间不用每次都烧整个镜像。我踩过最大的坑就是推完services.jar后忘记adb shell stopadb shell start重启zygote和SystemServer导致改了半天发现跑的还是旧代码。实际上推完系统框架jar后要么直接重启设备要么用adb shell stop adb shell start热重启Android运行时。提示改native层C代码时不能只推jar因为涉及.so动态库的更新最稳妥的做法是重新生成system.img并刷机或者单独mmm对应的库后adb push到/system/lib64目录并同步刷入否则极容易出现版本不对导致的加载失败。4. 核心开发场景深度拆解4.1 新增一个系统服务的基本套路框架开发最典型的入门任务就是新增一个系统服务。比如公司要做一套设备管理能力需要在系统里新增一个服务向应用层提供设备注册、状态上报、远程指令接收的接口。这个任务几乎覆盖了框架开发的所有核心知识点我拿它当例子拆解一遍。先理解系统服务的整体结构。Android的系统服务都集中在SystemServer进程里SystemServer启动时会实例化一个个服务服务实例化之后要注册到ServiceManager实际是servicemanager这个native进程中才能被应用层通过Context.getSystemService()拿引用。一个标准的新增服务需要动这几个地方第一步定义AIDL接口。框架层服务与应用层通信靠Binder而AIDL就是Binder接口的描述方式。建议在frameworks/base/core/java/xxx/下新建AIDL文件声明你的方法同步编译生成Java接口。// IDeviceControlService.aidl package com.example.framework; interface IDeviceControlService { boolean registerDevice(String deviceId); String getDeviceStatus(String deviceId); void sendCommand(String deviceId, String command); }第二步实现服务类。新建一个继承IDeviceControlService.Stub的类放进frameworks/base/services/core/java/com/android/server/目录的合适位置。注意SystemServer加载服务时要用SystemService这个基类的方式来管理生命周期这样能自动处理启动顺序、Binder注册、开机阶段调度。public class DeviceControlService extends SystemService { private final Context mContext; private final DeviceControlServiceImpl mImpl; public DeviceControlService(Context context) { super(context); mContext context; mImpl new DeviceControlServiceImpl(context); } Override public void onStart() { publishBinderService(device_control, mImpl); } Override public void onBootPhase(int phase) { if (phase PHASE_BOOT_COMPLETED) { // 开机完成后执行初始化工作 } } private final class DeviceControlServiceImpl extends IDeviceControlService.Stub { // 具体实现 } }第三步在SystemServer中注册。找到SystemServer.java在startOtherServices()方法里找到合适的启动节点新增一行mSystemServiceManager.startService(DeviceControlService.class);。为什么用SystemServiceManager而不是手动实例化因为它能统一管理服务的启动、崩溃重启策略、阶段回调这是官方推荐的注册方式。第四步配置权限。新增的新服务如果要对应用层开放必须声明保护级别。系统服务的权限定义在frameworks/base/core/res/AndroidManifest.xml中比如permission android:namecom.example.permission.EXECUTE_DEVICE_COMMAND android:protectionLevelsignature /第五步处理SELinux。这是新人最容易忘的一步也是我最想强调的一步。即使你的权限声明好了SELinux策略不匹配应用调用服务时照样会收到PermissionDenied或Binder无法建立连接的错误。需要在system/sepolicy/下为你的服务定义service_contexts或者新版本的service_contexts合并到service_contexts列表以及对应的te文件。// service_contexts device_control u:object_r:device_control_service:s0// device_control_service.te type device_control_service, app_api_service, system_server_service, service_manager_type;到这里一个新服务的基本框架才算搭完。整个流程知识点密度很高任何一个环节不对都可能导致服务注册失败或者权限不通。4.2 Binder通信框架的命脉Binder是Android系统进程间通信IPC的基石几乎所有框架功能都建立在它之上。你要想在框架开发中游刃有余Binder的工作原理必须吃透。用生活里的例子解释Binder就像酒店的前台。住客上层应用需要某个服务比如洗衣、送餐不用直接去找洗衣房或者厨房只需要打前台电话ServiceManager/Binder驱动前台会帮你转接到相应的部门。关键点在于住客拿到的是一个“虚拟号码”Binder引用通过这个号码实际请求会被Binder驱动路由到真正的服务进程。Binder通信涉及几层内容Binder驱动位于Linux内核负责进程间数据传输、内存映射mmap、线程池管理。Binder协议包括BC_TRANSACTION这些命令字以及Parcel数据的打包解析。Binder对象模型BnInterface服务端Stub和BpInterface客户端ProxyAndroid源码里自动生成的Stub和Stub.Proxy就分别对应这两者。Binder线程池每个进程默认的Binder线程数量是有限的默认16个如果服务端的某个接口方法执行耗时较长会占用Binder线程而其他调用者就会排队或者超时。框架开发中Binder相关的坑主要集中在这几个方向主线程被阻塞导致ANR。如果一个Binder方法里做了耗时的网络请求或者文件IO且它是在系统服务的主线程中执行那么其他服务调用包括系统自带的都会卡住。正确做法是把耗时操作放到服务端的独立工作线程里执行或者用AsyncTask/Executor作为执行载体Binder方法本身立即返回。Binder对象过大。一次Binder传输的数据量默认上限是1MB跨进程map和large transaction另有限制如果你试图在Binder里传个几兆的Bitmap会直接报TransactionTooLargeException。所以框架层的接口设计尽可能传递轻量级的数据结构比如传文件路径而非文件内容。oneway调用。如果你的接口不需要等待服务端返回结果可以声明oneway关键字这样客户端调用后立即返回不阻塞Binder线程。对于命令下发类的操作非常合适但要注意oneway模式下服务端的处理是串行的如果你希望每个命令都独立处理还是得在服务端开线程。Binder死亡通知。客户端绑定了远程服务如果服务端进程挂掉客户端的Binder就变成了“死引用”。框架服务的死亡监听非常重要ServiceManager会在服务进程死亡时清理它的注册信息。自己写服务时也用linkToDeath来做好联系人管理避免死连接泄漏。Binder这块没有捷径我建议每个想做框架开发的人至少读一遍官方文档里的Binder架构介绍和AIDL源码生成过程再自己用android.os.Debug跟踪一次transact()的调用栈心里那个模型就建立了。4.3 自定义View与UI框架的扩展框架开发里UI方向的扩展和系统服务方向完全是另一种风景。很多时候产品需要一套特定的交互控件而这些控件放在应用层做太重、放在framework里反而能做成公共能力比如一个支持复杂手势的车载桌面应用或者一套统一设计的系统级弹窗都要在View层面做文章。UI框架扩展最核心的技术点在于理解View的测量measure、布局layout、绘制draw三大流程以及ViewGroup的事件分发机制。框架层开发的自定义View通常会用系统签名级别的API避免上层的种种限制。但这不代表你可以为所欲为你写的类一旦放进frameworks/base/core/java/android/view/并被系统引用就等于成了系统的一部分代码质量和兼容性要求随之暴涨。我做过一个被业务方反复要求的自定义ViewGroup一个环形扇形菜单控件。它要支持外部旋转和中心按钮点击还要动态适配不同屏幕尺寸。如果在应用层做问题不大因为你可以针对自己App的屏幕环境测试调优。但在框架层做就必须考虑多窗口、分屏、横竖屏切换各种形态还需要处理Configuration变化。在做这个控件的onLayout时我一直卡在嵌套布局的不规范上后来索性先在一张纸上画出手势到控件状态的映射关系图再动手写代码。这个过程虽然繁琐但能帮你理解为什么框架层的View代码看起来比应用层的复杂得多因为它的边界条件和状态组合数量呈指数级上升。UI框架扩展还有一个很有用的场景系统级别的侧边栏、状态栏定制、悬浮窗方案。这些都要跟WindowManagerService打交道涉及窗口层级、焦点处理、输入事件分发等框架核心模块。想做这块建议先研究系统自带StatusBar的代码Android的StatusBar本身是一个SystemUI的独立应用通过WindowManagerService将窗口添加到指定层级是理解“窗口管理和应用层解耦”的最佳学习材料。4.4 硬件对接与HAL层交互框架开发绕不开硬件对接。Android的硬件访问路径是这样的最上层是应用框架API——接着是SystemServer里相应服务的Java代码——然后通过JNI调用native层——再往下是HAL Interface比如hardware/libhardware中的hw_get_module——最后是具体厂商的.so实现——最底层是内核驱动。公司要做一功能模块比如一台上报体温的设备框架层就要打通从传感器到应用层的整条链路。这里面的难点不在Java部分而在JNI和HAL接口的对接上。JNI层要用C写一个中间层把HAL拿到的数据转换成Java可以调用的jobject或者反过来。这个过程很容易出内存泄漏和类型转换错误尤其是传byte数组时要注意JNI引用的释放。HAL层写接口时通常要定义一组标准的回调函数比如typedef struct temper_device { struct hw_device_t common; int (*init)(struct temper_device_t* dev); int (*get_temperature)(struct temper_device_t* dev, float* value); } temper_device_t;然后上层JNI通过hw_get_module(TEMP_HARDWARE_MODULE_ID)拿到这个结构体调用对应的函数指针。每次硬件数据变化底层主动回调到JNI再通过JNI调用Java层接口把值更新上去。这个链路里任何一环超时或者崩了后台日志都是碎片化的排查很痛苦。我的经验是各层多打可追踪的log并且给每一步都设定超时和异常兜底。4.5 资源与包管理框架的常用修改框架开发里PackageManagerPMS包管理服务和ResourcesManager资源管理是绕不开的两个大头。它们的代码复杂度在Android系统里数一数二动不动就上千行的方法修改时需要特别小心。PMS负责所有APK的安装、卸载、权限授予、组件查询。框架开发中常见的需求有预置应用把内部开发的APK预置到/system/app或/vendor/overlay目录刷机后自动安装且不可卸载。系统级权限白名单调整signature级权限的授予范围让特定应用能访问系统API。禁止安装第三方应用在installPackageAsUser方法里加拦截逻辑判断包名或签名后直接拒绝。应用启动管控限制后台应用的数量或白名单之外的应用不允许自启。ResourcesManager涉及的则是资源查找与主题切换。系统默认主题或者字体等都可以在ResourcesManager或AssetManager层做全局拦截和替换。常见的全局换字体方案就是在AssetManager的addAssetPath环节偷偷替换system_fonts.xml指向的资源。做这些修改时最要注意的依然是PMS的稳定性。你改的是所有应用的基础设施一个空指针就可能让整个开机流程崩掉。所以改PMS前要把所有系统包名列表和时间点记录好改动后要确保package_manager服务能快速恢复不能因为你的代码阻塞住ActivityManager的启动。5. 整个项目的实操过程记录5.1 从需求到上线完整流程作为一个已经跑完多个框架开发项目的老人给大家梳理下标准流程应该怎么走。首先不要一上来就看代码。先从需求文档中提取出“要改哪个层次”和“涉及哪个模块”然后去翻阅相关模块的系统架构图。可以把Android源码官网的架构浏览器当成地图先看清楚整个ActivityManager/WindowManager/SystemServer的模块路径。心中有地图代码才不会跑偏。其次搭建可复现的开发环境。我强烈建议在项目初期就维护一份“源码编译环境笔记”记录你的JDK版本、Python版本、repo分支、内存配置、编译时间、常见报错与排查记录。第一次编译全量系统可能需要2~4小时甚至更久环境的坑不及时记录后面重装系统时就等着哭。再次小步快跑。框架开发最忌讳一次改动几百行。哪怕你的目标功能需要写很多代码也建议先搭一个最小可运行骨架验证链路通了再逐步加逻辑。比如新增服务先让客户端能拿到服务引用能调用一个空的接口方法返回true然后再去实现具体功能。链路不通一切白搭。最后善用系统自带的测试工具。Android系统源码里每个服务模块都有对应的单元测试和instrumentation测试框架比如frameworks/base/services/tests目录下的测试几乎覆盖了所有系统服务。不是必须跑全部但至少你改动模块的子集要能通过。5.2 编译与构建细节补充来说说我个人在编译上踩过的一些具体坑。一是切换分支时缓存混乱。如果你从android-12切到android-13一定要make clean或者干脆删除out目录重新建立。我因为在切换版本后直接增量编译跑完发现代码不生效最后不得不整个重编。这个时间成本太高了。二是jack-server历史版本的内存问题。Android 8之前的版本用jack编译器经常报out of memory要改~/.jack目录下的配置。Android 10开始换成R8/D8等新链后这种问题少了但如果你编译旧版本源码还是要先查一下对应版本的编译工具链说明。三是模块编译路径混乱。单独修改一个模块时尽量在make和mmm之间保持清晰。比如你改了framework/base/core下的Java代码会生成多个jar产物framework.jar、framework2.jar等推入设备时经常出现新旧混合的情况导致界面无响应。我的习惯是每次mmm编译完后用adb shell md5sum /system/framework/framework.jar对比本机产物和设备上文件的md5确认一致再继续调试。四是磁盘空间。out目录占用极大经常50GB打底。如果是AOSP全量源码最终体积会在100GB以上。务必提前清理多余的增量备份和中间文件。5.3 框架模块的单元测试与集成验证单元测试在框架开发中的地位被很多人低估了。应用开发可以不写测试反正线上有各种兜底但在框架层一个无意的修改可能影响千万台设备必须有完善的回归测试方案。Android框架的测试分为几个层级本地单元测试用LocalUnitTests在开发机上跑不依赖设备适合测试服务里的纯逻辑部分。设备端测试通过adb部署到测试设备上跑需要Android系统的Instrumentation支持。CTS/VTS测试Google提供的兼容性测试套件强制要求通过才能通过认证。你的框架改动如果不通过CTS等于这个ROM不合法很多系统应用和服务都会出问题。我参与项目时的测试流程是先写服务层单元测试验证服务实例化和接口数据正确再写设备端测试验证Binder调用链路和权限控制最后跑对应模块的CTS集中用例。CTS很耗时但跑一次能换来上线的底气。6. 常见问题与排查经验6.1 编译与启动流程高发问题这几类问题是我在实际项目里遇到频率最高的整理个速查表方便大家快速定位问题现象常见原因解决思路编译报JDK版本错误本机JAVA_HOME指到了错误的JDK确认目标Android版本对应的JDK版本调整JAVA_HOME并重新source envsetup.shSystemServer启动崩溃服务初始化抛异常通常NullPointerException或ServiceNotFoundException查logcat中的SystemServer崩溃栈确认是哪个服务启动失败排查其onStart()实现Binder调用返回DeadObjectException对端服务被杀或Binder连接失效确认服务进程是否存活dumpsys activity services查看必要时重启框架服务权限验证失败SELinux策略未配置或权限保护级别过严检查dumpsys package和dumpsys service输出确认进程上下文与te文件的对应关系dumpsys输出为空服务未成功注册到ServiceManager确认publishBinderService是否调用servicemanager里能否查到该服务这些问题的排查逻辑其实是有通法的先看logcat再查dumpsys最后看SELinux的avc日志。SELinux的日志通常出现在dmesg或者logcat的avc段不要一上来就瞎猜。6.2 运行时崩溃与性能瓶颈定位框架层崩溃的定位比应用层难得多但有几个通用工具能大幅提速。Debuggerd当native进程崩溃时debuggerd会生成tombstone记录包括寄存器、调用栈、内存映射在内的崩溃信息。通过adb shell ls /data/tombstones能看到所有tombstone文件取最新的分析即可。Java堆栈如果进程还没挂通过kill -3或am dumpheap抓取hprof文件用Android Studio的Memory Profiler来分析内存泄漏和对象分配。Systrace解决UI卡顿和系统服务耗时问题时systrace是看事件时间线的好工具。直接运行python systrace.py --time10 -a SystemServer能抓出系统服务里哪个方法耗时最长。我还遇到过一种很隐蔽的坑系统服务里用了单例而单例在多线程环境下初始化时线程不安全导致服务时好时坏。定位这种难题光靠代码review不够要在onStart里加好同步锁必要时用CountDownLatch来做初始化屏障。6.3 兼容性测试失败的处理思路CTS失败不能只看单个case要看它是不是由你修改的模块引起的连锁反应。我遇到过CTS的Signature权限用例失败追根溯源发现是自己在PMS里错误地修改了getPackageInfo的flags判断导致曝光了本不该曝光的系统组件。处理CTS失败的通用步骤获取完整的CTS失败报告和分析日志。在本机上重现失败的case如果无法在模拟器复现就在测试设备上手动跑对应模块。用binary search的方式逐渐注释掉自己的修改定位是哪一处改动触发了失败。针对性修复后回归同类用例至少通过90%以上再上报。这里要特别提醒CTS报告的失败有时候是环境或设备引起的未必是你改的代码。先排除设备存储空间、系统时区、网络连接这些干扰因素再怀疑自己的修改。7. 个人实操中的几点总结分享文章写到这儿核心内容讲得差不多了。最后再说几句我在实际项目中有体会的话。框架开发不是“改完代码编译刷机”就结束的它其实是一个系统工程。你要有耐心读几万行源码要习惯日志里找不到明确报错要接受改一行代码可能影响几十个模块。但这些东西想通了之后会非常“上瘾”因为你看待Android系统的眼光会彻底改变。每次系统更新你不再只关心界面变了什么API而是开始分析它底层的调度、内存、Binder策略发生了哪些调整。对于刚入门的同学我建议从阅读源码开始不要急于上手改代码。可以先跟着ActivityTaskManager的应用启动路径把startActivity到ActivityRecord创建的过程读一遍再对照官方架构图找到各个模块的对应关系。把这块啃下来后面开发基本就顺了。另外团队协作时一定要有“系统全局观”。框架层的很多服务相互依赖你在A服务里加的一个延迟任务可能让B服务在某个时间点收到晚到的通知进而触发一个谁都没料到的状态。动框架代码之前建议先画一张改动影响的时序图把跨服务的调用链梳理清楚。框架开发的门槛不低但正因如此它带来的成长也是普通应用开发不太容易比拟的。你会从“调API的人”变成“定义API的人”这种角色的转换是整个职业生涯很值得体会的经历。