在代码中用 startService()
或 bindService()
时,系统内部究竟发生了什么魔法。核心在于理解 Binder IPC 机制 和 ActivityManagerService (AMS) 的角色。
一、核心原理:Binder IPC 与 ActivityManagerService (AMS)
-
Binder IPC (Inter-Process Communication)
-
问题: App 进程是沙盒隔离的。你的 App (客户端进程) 如何与系统服务 (如 AMS,运行在
system_server
进程) 或其他 App 的服务 (另一个进程) 通信? -
答案: Binder!它是 Android 最核心的跨进程通信机制。
-
核心思想 (简化模型):
- 每个进程有一块共享内核内存空间。
- 通信双方通过 Binder 驱动 (内核模块) 在这块共享内存上读写数据。
- 代理模式: 客户端拿到一个对服务端对象的 Proxy (代理) 。客户端调用 Proxy 的方法 -> Proxy 将方法名、参数打包 (序列化) 成
Parcel
-> 通过 Binder 驱动发送给服务端进程 -> 服务端收到后解包,调用真实对象的方法 -> 将结果打包回传 -> 客户端 Proxy 接收结果并返回。 - 对客户端来说,调用 Proxy 就像在调用本地对象一样(透明)。
-
在 Service 中的体现:
- 当你在 App 内绑定服务 (同进程),
Binder
对象是直接传递的(效率高)。 - 当你绑定跨进程服务(包括系统服务 AMS),你拿到的是一个
Binder
Proxy 对象。你调用它的方法,实际是通过 Binder 驱动请求远程进程的Service
执行操作。 IBinder
接口: 是 Binder 对象的核心接口。Binder
类实现了它(用于本地对象),BinderProxy
(内部类) 也实现了它(用于远程代理)。
- 当你在 App 内绑定服务 (同进程),
-
-
ActivityManagerService (AMS) - 系统服务的大管家
-
角色: Android 系统最核心的服务之一 ,运行在
system_server
进程。它管理四大组件(Activity、Service、BroadcastReceiver、ContentProvider)的整个生命周期。 -
对 Service 的职责:
- 接收 App 进程发来的
startService
,bindService
,stopService
,unbindService
等请求。 - 维护所有运行中 Service 的记录。
- 根据系统状态(内存、电量、用户交互)决定 Service 的启动、停止、绑定、解绑。
- 处理 Service 与客户端的绑定关系。
- 强制执行后台限制策略。
- 接收 App 进程发来的
-
你的 App 与 AMS 的通信: 通过 Binder IPC。你的 App 持有 AMS 的一个 Binder Proxy (
IActivityManager
)。
-
二、源码调用链路分析 (以 startService() 为例)
让我们追踪一次 startService()
的旅程。假设在 MyActivity
中调用 startService(new Intent(this, MyService.class))
:
-
ContextWrapper.startService(Intent)
(在你的
MyActivity
中调用)typescript// ContextWrapper.java @Override public ComponentName startService(Intent service) { return mBase.startService(service); // mBase 是 ContextImpl 实例 }
-
ContextImpl.startService(Intent)
(
ContextImpl
是Context
接口的真正实现者)scss// ContextImpl.java @Override public ComponentName startService(Intent service) { ... // 一些权限、用户ID检查 String resolvedType = service.resolveTypeIfNeeded(getContentResolver()); try { // 关键!调用 ActivityManagerService (AMS) 的方法 ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), // 传入 ApplicationThread (Binder对象,代表App进程) service, resolvedType, getOpPackageName(), getAttributionTag(), getUser().getIdentifier()); ... // 处理返回值 return cn; } catch (RemoteException e) { ... } }
ActivityManager.getService()
:获取到 AMS 的 Binder Proxy (IActivityManager
)。mMainThread.getApplicationThread()
:获取代表当前 App 进程的ApplicationThread
对象(它是一个Binder
对象,实现了IApplicationThread
接口)。这是 App 进程与 AMS 通信的另一条关键通道(回调通道)。
-
跨进程调用到
ActivityManagerService.startService()
- 请求通过 Binder 驱动,从你的 App 进程传递到
system_server
进程。 - AMS 收到请求:
IActivityManager.startService(IApplicationThread caller, Intent service, ...)
scss// ActivityManagerService.java @Override public ComponentName startService(IApplicationThread caller, Intent service, ...) { ... // 大量安全检查 (权限、Intent 匹配、目标 Service 是否存在等) // 解析 Intent,找到目标 Service 的信息 (ResolveInfo) // 获取调用者进程记录 (ProcessRecord) // 获取或创建目标 Service 的记录 (ServiceRecord) synchronized(this) { // 核心方法:启动服务 return startServiceLocked(caller, service, ...); } } ComponentName startServiceLocked(IApplicationThread caller, ...) { ... // 更多检查 (后台启动限制、前台权限等) // 将启动请求封装成 ServiceRecord.StartItem 并加入队列 // 关键:调用 bringUpServiceLocked() return startServiceInnerLocked(...); } ComponentName startServiceInnerLocked(...) { ... // 处理 pending 状态等 // 最终调用 bringUpServiceLocked() String error = bringUpServiceLocked(s, ...); ... } private String bringUpServiceLocked(ServiceRecord r, ...) { ... // 检查 Service 所在进程是否已启动 if (app != null && app.thread != null) { // 进程已存在 try { // 关键!通过 ApplicationThread (Binder) 回调到 App 进程,让 App 进程创建并启动 Service realStartServiceLocked(r, app, execInFg); return null; } catch (RemoteException e) { ... } } else { // 进程不存在 // 先启动 Service 所属的 App 进程 (另一个复杂过程) startProcessLocked(...); } ... } private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { ... // 设置各种状态 // 调用 App 进程 ApplicationThread 的 scheduleCreateService() 创建 Service app.thread.scheduleCreateService(r, ...); // 调用 App 进程 ApplicationThread 的 scheduleServiceArgs() 触发 onStartCommand requestServiceBindingsLocked(r, execInFg); // 如果有 pending 的绑定也一并处理 sendServiceArgsLocked(r, execInFg, true); // 触发 onStartCommand }
- 请求通过 Binder 驱动,从你的 App 进程传递到
-
回调到 App 进程 (
ApplicationThread.scheduleCreateService()
)- 请求再次通过 Binder 驱动,从
system_server
进程回到你的 App 进程。 - 你的 App 进程的
ActivityThread
内部的ApplicationThread
对象收到请求:
arduino// ActivityThread.java (内部类 ApplicationThread) public final void scheduleCreateService(IBinder token, ...) { ... // 封装消息 sendMessage(H.CREATE_SERVICE, s); }
ActivityThread
的H
(一个Handler
) 处理消息:
scala// ActivityThread.java private class H extends Handler { ... case CREATE_SERVICE: handleCreateService((CreateServiceData) msg.obj); // 处理创建服务 break; ... } private void handleCreateService(CreateServiceData data) { // 1. 获取类加载器 LoadedApk packageInfo = getPackageInfoNoCheck(...); // 2. 通过反射创建 Service 实例 !! Service service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent); // 3. 创建 Context 上下文 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); // 4. 将 Context 附加到 Service (service.attach(context, ...)) // 5. 调用 Service.onCreate() !!! service.onCreate(); // 6. 将创建好的 Service 记录到 ActivityThread 的 mServices (一个 Map<IBinder, Service>) 中 }
- 请求再次通过 Binder 驱动,从
-
回调到 App 进程 (
ApplicationThread.scheduleServiceArgs()
)- 紧接着(或在
realStartServiceLocked
中稍后),AMS 会调用scheduleServiceArgs
触发onStartCommand
:
java// ActivityThread.java (ApplicationThread) public final void scheduleServiceArgs(IBinder token, ...) { ... // 封装数据 sendMessage(H.SERVICE_ARGS, s); } // ActivityThread.H case SERVICE_ARGS: handleServiceArgs((ServiceArgsData) msg.obj); break; private void handleServiceArgs(ServiceArgsData data) { // 从 mServices Map 中根据 token 找到之前创建的 Service 对象 Service s = mServices.get(data.token); if (s != null) { try { ... // 处理参数 // 调用 Service.onStartCommand() !!! int res = s.onStartCommand(data.args, data.flags, data.startId); // 通知 AMS 服务启动完成 (通过 AMS 的 serviceDoneExecuting) ActivityManager.getService().serviceDoneExecuting(...); } catch (Exception e) { ... } } }
- 紧接着(或在
总结 startService()
链路:
MyActivity.startService()
-> ContextImpl.startService()
-> (Binder IPC) -> AMS.startService()
-> AMS.startServiceLocked()
/bringUpServiceLocked()
/realStartServiceLocked()
-> (Binder IPC) -> ApplicationThread.scheduleCreateService()
-> ActivityThread.handleCreateService()
(反射创建 Service, 调用 onCreate()
) -> ApplicationThread.scheduleServiceArgs()
-> ActivityThread.handleServiceArgs()
(调用 onStartCommand()
)。
三、源码调用链路分析 (bindService() 核心部分)
bindService()
的流程比 startService()
更复杂,因为它涉及到建立双向通信通道 (Binder)。核心在于 onBind()
和 ServiceConnection
。
-
ContextImpl.bindService()
->AMS.bindService()
(类似 startService,App 进程请求 AMS)
-
AMS 处理绑定请求 (
bindServiceLocked
)- 检查权限、目标服务、调用者进程等。
- 如果服务未运行,先启动它(类似
startService
流程)。 - 创建
ConnectionRecord
记录这次绑定。 - 调用
requestServiceBindingLocked()
。
-
AMS 请求服务端进程进行绑定 (
realStartServiceLocked
或后续流程)arduino// AMS private final boolean requestServiceBindingLocked(ServiceRecord r, ...) { ... // 通过 ApplicationThread 回调到服务端 App 进程 r.app.thread.scheduleBindService(r, ...); ... }
-
服务端进程处理绑定请求 (
ApplicationThread.scheduleBindService()
)java// ActivityThread.ApplicationThread public final void scheduleBindService(IBinder token, ...) { sendMessage(H.BIND_SERVICE, s); } // ActivityThread.H case BIND_SERVICE: handleBindService((BindServiceData) msg.obj); break; private void handleBindService(BindServiceData data) { // 从 mServices Map 中找到目标 Service Service s = mServices.get(data.token); if (s != null) { try { // 调用 Service.onBind(Intent) !!! IBinder binder = s.onBind(data.intent); // 关键!将 Service 返回的 IBinder 对象 (可能是 Binder 本地对象或 Stub) 告诉 AMS ActivityManager.getService().publishService(data.token, data.intent, binder); } catch (Exception e) { ... } } }
-
AMS 处理发布的 Binder (
publishService()
)- AMS 收到服务端进程发来的
IBinder
对象。 - 根据
ConnectionRecord
找到所有等待绑定的客户端。 - 对于每个客户端,通过客户端的
IServiceConnection
接口(也是一个 Binder 对象,由客户端在bindService()
时提供) ,调用connected(ComponentName name, IBinder service)
方法。这里的service
参数就是服务端onBind()
返回的IBinder
。
- AMS 收到服务端进程发来的
-
客户端进程收到连接 (
IServiceConnection.connected()
)- 这个
IServiceConnection
的实现通常在LoadedApk
内部 (ServiceDispatcher.InnerConnection
),它会将调用转发给开发者注册的ServiceConnection
对象:
java// LoadedApk.java (内部类 ServiceDispatcher.InnerConnection) public void connected(ComponentName name, IBinder service) throws RemoteException { // 转发给外部的 ServiceDispatcher sd.connected(name, service); } // ServiceDispatcher public void connected(ComponentName name, IBinder service) { // 回调给开发者写的 mConnection.onServiceConnected(name, service) !!! mActivityThread.post(new RunConnection(name, service, 0)); }
- 这样,在开发者的
ServiceConnection.onServiceConnected()
中,就拿到了服务端onBind()
返回的IBinder
对象。开发者可以将其转换成需要的接口类型(如自定义的Binder
子类、Messenger
或AIDL
接口),开始与服务端通信。
- 这个
总结 bindService()
核心链路:
客户端 bindService()
-> AMS.bindService()
-> (服务端进程可能启动) -> AMS.requestServiceBindingLocked()
-> (Binder IPC) -> ApplicationThread.scheduleBindService()
-> ActivityThread.handleBindService()
(调用 Service.onBind()
) -> (Binder IPC) AMS.publishService()
-> (Binder IPC) 调用客户端的 IServiceConnection.connected()
-> 客户端内部调用 ServiceConnection.onServiceConnected()
。
四、关键源码类总结
Context
/ContextImpl
: App 组件访问系统服务的入口。startService()
,bindService()
的起点。ActivityManagerService
(AMS): 系统核心服务,管理 Service 生命周期、绑定关系的中央枢纽。运行在system_server
进程。IActivityManager
: AMS 的 Binder AIDL 接口定义。App 进程持有其 Proxy 与 AMS 通信。ActivityThread
: App 进程的主线程类。负责调度四大组件的创建、生命周期回调。ApplicationThread
:ActivityThread
的内部类,实现了IApplicationThread
AIDL 接口。它是 AMS 与 App 进程通信的回调通道 。AMS 通过调用它的方法 (如scheduleCreateService
,scheduleBindService
) 来通知 App 进程执行组件操作。Service
: 开发者继承的基类。onCreate()
,onStartCommand()
,onBind()
,onUnbind()
,onDestroy()
是其核心生命周期方法。IBinder
: Binder 对象的根接口。Binder
(本地对象),BinderProxy
(远程代理),IInterface
(AIDL 接口基类) 都与之相关。是跨进程通信的基石。ServiceRecord
(AMS 内部): AMS 中代表一个运行中 Service 的数据结构。包含 Service 的所有关键信息(Intent、进程、绑定者列表、状态等)。ServiceConnection
(客户端): 开发者实现的接口,用于接收绑定成功/失败的回调 (onServiceConnected
,onServiceDisconnected
)。其内部包装了IServiceConnection
Binder 对象用于 AMS 回调。IServiceConnection
:ServiceConnection
内部通信通道的 AIDL 接口定义。AMS 通过它回调客户端。
五、总结
-
Service 的启动和绑定是 App 进程与系统服务 AMS (
system_server
进程) 以及目标服务进程之间通过 Binder IPC 协作完成的。 -
AMS 是 Service 管理的中央控制器,负责生命周期调度、权限检查、后台策略执行。
-
ApplicationThread
是 AMS 控制 App 进程的"遥控器" 。AMS 通过调用其方法 (如scheduleCreateService
,scheduleBindService
) 让 App 进程在正确时机执行 Service 的生命周期方法。 -
Binder IPC 是贯穿始终的通信基础,用于:
- App -> AMS (
IActivityManager
) - AMS -> App (
IApplicationThread
) - 服务端 Service -> 客户端 (
onBind()
返回的IBinder
及其代理) - AMS -> 客户端 (
IServiceConnection
通知绑定结果)
- App -> AMS (
-
绑定服务的核心在于服务端
onBind()
返回IBinder
,AMS 将其传递给客户端,最终回调到客户端的ServiceConnection.onServiceConnected()
。 -
理解
ServiceRecord
,ConnectionRecord
等 AMS 内部数据结构有助于理解状态管理。