3. Android系统服务基础

Android 的系统能力大多不是由应用进程直接实现的,而是由运行在 system_server 等系统进程中的系统服务统一提供。应用通过 Context.getSystemService() 拿到一个代理对象,再借助 Binder 机制跨进程调用真正的服务实现。理解这条链路,是后续学习权限校验、系统服务定制与集成的前提。

一、系统服务架构:三层协作

从整体看,Android 系统服务架构可以拆成三层:

  • 服务实现层:真正的功能代码,如 ActivityManagerService、PackageManagerService、WindowManagerService,运行在 system_server 进程中。
  • Binder 通信层:由 IBinder、Binder、BinderProxy 以及 AIDL 生成的 Stub/Proxy 组成,负责跨进程方法调用与数据序列化。
  • 客户端访问层:应用通过 Context、ServiceManager 或 getSystemService() 获取代理,以本地方法的形式调用远程服务。

系统启动时,ServiceManager 作为 Binder 的“总管家”先启动,随后各系统服务向它注册自己,客户端再按名称查询。这个“注册—查询—调用”的模型,是 Android 系统服务能够被应用发现和使用的关键。

Android 系统服务调用链路 应用进程 Context.getSystemService() IActivityManager 代理 BinderProxy Parcel 序列化参数 Binder 驱动 /dev/binder 内核态数据转发 线程池调度 一次拷贝 + 引用计数 system_server 进程 ActivityManagerService PackageManagerService WindowManagerService Binder.onTransact() transact onTransact ServiceManager addService(name, binder) getService(name) 服务注册与查询中心 注册服务 查询服务 调用要点: ① 应用只持有代理,不直接访问服务实现;② 参数与返回值必须可 Parcel 化;③ 跨进程调用可能抛出 RemoteException / SecurityException。

二、Context.getSystemService:应用的入口

Context 是应用访问系统服务的统一入口。常见用法如下:

// 获取 ActivityManager 代理
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

// 获取 PackageManager
PackageManager pm = getPackageManager();

// 获取 WindowManager
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);

// 获取 NotificationManager
NotificationManager nm = getSystemService(NotificationManager.class);

不同服务对应不同的常量名,例如 Context.ACTIVITY_SERVICE、Context.PACKAGE_SERVICE、Context.WINDOW_SERVICE。Android 6.0 之后还支持按 Class 获取,减少强制类型转换。需要注意的是,getSystemService() 返回的通常是代理对象,而不是服务本体;真正的服务运行在 system_server 中。

提示:并非所有系统服务都能通过 Context.getSystemService() 获取。部分底层服务需要借助 ServiceManager.getService() 或隐藏 API 访问,普通应用应优先使用公开接口。

三、Binder 机制:跨进程调用的核心

Binder 是 Android 特有的 IPC 机制,相比传统 Socket 或管道,它具备一次拷贝、面向对象、支持引用计数和权限校验等优势。一次典型的 Binder 调用包含以下步骤:

  1. 客户端调用代理对象的某个方法,例如 am.startActivity()。
  2. 代理将参数写入 Parcel,调用 transact() 发起请求。
  3. Binder 驱动将请求转发到服务端线程池。
  4. 服务端 onTransact() 被调用,解析参数并执行真正逻辑。
  5. 结果写回 Parcel,沿原路返回客户端。

在 AIDL 中,Stub 是服务端基类,Proxy 是客户端代理。二者共同保证跨进程调用像本地调用一样自然。Binder 还通过 uid/pid 识别调用方身份,为权限校验提供依据。

四、系统服务与应用的交互方式

应用与系统服务的交互并不只有“直接调用”一种,常见方式包括:

交互方式 典型场景 特点
直接 Binder 调用 ActivityManager、PackageManager 同步调用,返回结果直接可用
回调 / Listener LocationManager、SensorManager 服务端主动通知客户端,需注册与反注册
广播 / 系统事件 电池变化、网络切换 松耦合,适合一对多通知
ContentProvider 联系人、媒体库 基于 Binder,面向数据共享
Messenger / AIDL 自定义跨进程服务 应用自身实现服务端与客户端

五、案例:一次 startActivity 的完整链路

以 startActivity() 为例,应用进程中的 Activity 调用 startActivity(),最终会走到 Instrumentation.execStartActivity(),通过 ActivityManager.getService() 拿到 IActivityManager 代理,再调用 startActivity()。请求经 Binder 驱动进入 system_server,由 ActivityManagerService 完成权限检查、任务栈调度和进程启动决策。整个过程对应用开发者是透明的,但理解它有助于排查 SecurityException、RemoteException 以及启动超时等问题。

误区提醒:很多初学者认为 getSystemService() 返回的是服务对象本身,因而在子线程中随意调用或长期持有。实际上它只是代理,调用仍受 Binder 线程池和权限限制;在主线程执行耗时服务调用还可能引发 ANR。

六、复盘与要点清单

  • 系统服务运行在 system_server,应用通过代理访问。
  • Context.getSystemService() 是获取服务代理的标准入口。
  • Binder 负责跨进程传输,核心是 transact() 与 onTransact()。
  • 交互方式包括直接调用、回调、广播、ContentProvider 和自定义 AIDL。
  • 调用系统服务时要关注权限、线程模型和异常处理。

掌握系统服务架构、Context.getSystemService()、Binder 机制以及交互方式,就抓住了 Android 系统服务集成的“主干”。后续无论是申请权限、调用系统能力,还是扩展自定义系统服务,都会围绕这条链路展开。