原创不易,转载请标明出处。若阅读过程当中发现问题,请不吝指教,比心~java
这是一个基于 Android 10 源码,全面分析 Android通知系统实现原理 的系列,这是第二篇,全系列将覆盖:android
为了让读者更全面地了解 系统通知服务总体流程,这一篇咱们会先简单介绍 手机是如何在启动的过程当中拉起NMS服务的,涉及到 Zygote进程的启动 和 System进程启动;而后介绍 NMS服务的功能实现 以及 如何获取到NMS服务。数组
简单说明:下文出现的简写bash
NM -> NotificationManager
NMS -> NotificationManagerService
Sysui -> SystemUI
复制代码
相关类:app
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/services/java/com/android/server/SystemServer.java
复制代码
咱们知道(不知道就伪装知道吧),手机启动的过程当中,init进程 是第一个启动的进程,该进程在启动的过程当中会去启动一个叫 Zygote
的进程,Zygote
进程在启动的过程当中会去建立一个虚拟机对象,后续其余进程的启动则是直接从Zygote
进程fork,从而达到每一个进程都拥有一个独立虚拟机的目的,这是题外话了。其中 System进程 就是 Zygote
进程在启动的过程当中fork出来的一个进程,这是一个系统进程,负责在开机的时候启动各类核心系统服务,例如AMS、PMS、NMS
等常见的服务。框架
下面来看看Zygote
是如何一步步启动 NMS服务的吧:socket
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static void main(String argv[]) {
......
try {
......
boolean startSystemServer = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
}
......
}
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
......
}
......
}
复制代码
ZygoteInit.main
函数中的argv
数组会带有start-system-server
字段,代表Zygote
进程须要启动System
进程,上面startSystemServer=true
,也就是接下来执行的是forkSystemServer
方法:ide
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
// Prepare the arguments and forks for the system server process.
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {
......
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer", // 步骤1:指定 System进程 的入口类为 com.android.server.SystemServer 的 main 方法
};
ZygoteArguments parsedArgs = null;
int pid;
try {
......
// 步骤2:经过 Zygote 去 fork System 进程
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// 步骤3:pid = 0 表示子进程fork成功
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
复制代码
有三个主要的步骤:函数
com.android.server.SystemServer 的 main函数
为 System
进程的程序入口Zygote 去 fork System
进程,并返回一个进程id,咱们知道,当fork返回的id为0时表示子进程fork成功,也就是步骤3要执行的handleSystemServerProcess
函数,该函数会进一步完成System
进程的启动工做,往下走的主要工做就是去到native层了,这里就再也不跟踪了(不行了)上面分析了,Zygote
进程启建立了System
进程并指定了程序入口为SystemServer.main()
,咱们接下来看看这个入口函数作了什么事:post
SystemServer().run()
/*frameworks/base/services/java/com/android/server/SystemServer.java*/
// The main entry point from zygote.
public static void main(String[] args) {
new SystemServer().run();
}
复制代码
run
方法在作好各类准备工做以后,就开始开启各类系统服务,NMS的启动在startOtherServices()
函数中执行/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void run() {
try {
......
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
}
......
}
复制代码
经过SystemServiceManager.startService()
启动NMS服务,SystemServiceManager
是一个专门用于建立、启动以及管理各系统服务生命周期事件的管理类
/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void startOtherServices() {
......
mSystemServiceManager.startService(NotificationManagerService.class);
......
}
复制代码
startService
函数的内容很简单,最终直接执行到NMS服务的onStart
函数。
/*frameworks/base/services/core/java/com/android/server/SystemServiceManager.java*/
public void startService(@NonNull final SystemService service) {
mServices.add(service);
try {
service.onStart();
}
......
}
复制代码
到这里,NMS服务的启动流程和启动时机就分析完了,稍微总结下:NMS服务是一个常驻在System进程中的系统服务,在手机系统启动的过程当中被拉起。
这一节咱们会从框架上来看看NMS服务的大致功能与实现,先简单说明下:
INotificationManager.aidl
定义了系统通知服务指望暴露给其余客户端的各类接口;NotificationManagerService
实现了INotificationManager.aidl
这个接口,并将Binder
代理对象注册到了ServiceManager
中去,以便其余服务与应用调用,如NotificationManager
相关类以下:
1. frameworks/base/core/java/android/app/NotificationManager.java
2. frameworks/base/core/java/android/app/INotificationManager.aidl
3. frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java
复制代码
下面开始分析,咱们上面讲过,系统在启动NMS服务的时候,调用了 NotificationManagerService.onStart()
函数,这是系统通知服务的入口,该函数主要完成了:
NotificationManagerService
中一系列成员变量的赋值(经过init(...)
方法),如AMS、PMS
类的代理对象的获取,各类辅助类实例的建立等等INotificationManager.aidl
接口的Binder代理对象mService
注册到ServiceManager
上面屡次提到INotificationManager.aidl
这个接口文件,咱们看下这个接口:该文件主要定义了这么几种类型的接口:
/*frameworks/base/core/java/android/app/INotificationManager.aidl*/
- 通知的添加(包括更新)、删除操做,即咱们前面讲到的 `notify、cancel` 等接口的实现,如`enqueueNotificationWithTag(...)`
- 通知属性的设置和判断,如是否容许显示某应用的通知、是否容许显示通知圆点(桌面图标右上角上的角标)等,如`setShowBadge(String pkg, int uid, boolean showBadge)`
- 通知`channel`的增删改查,如`createNotificationChannels(...)`
- 通知列表的获取如`StatusBarNotification[] getActiveNotifications(String callingPkg)`
- 通知状态监听相关接口,如`registerListener(in INotificationListener listener, in ComponentName component, int userid)`
- ......
复制代码
一、2点的内容不展开讲,感兴趣的童鞋直接看下NMS的onStart
方法便可,这里咱们直接看第3点,咱们来看看INotificationManager.aidl
的实现和注册过程:
NMS 实现 INotificationManager.aidl
/*frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java*/
final IBinder mService = new INotificationManager.Stub() {
@Override
public void enqueueToast(String pkg, ITransientNotification callback, int duration, int displayId) {......}
@Override
......
}
复制代码
将Binder
代理对象注册到ServiceManager
:
/*frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java*/
@Override
public void onStart() {
// 各成员变量的初始化 与 注册各类广播监听器
......
// 注册到ServiceManager
publishBinderService(Context.NOTIFICATION_SERVICE, mService, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL);
}
protected final void publishBinderService(String name, IBinder service,
boolean allowIsolated, int dumpPriority) {
ServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
复制代码
其中 NOTIFICATION_SERVICE
的值为"notification"
, 这样其余服务或应用就能够经过ServiceManager
来获取到 name 为 notification 的 INotificationManager Binder代理对象
了, 从而达到与其交互的目的了,例如咱们上面讲到的,开发者操做通知的入口类NotificationManager
,look look:
/*frameworks/base/core/java/android/app/NotificationManager.java*/
private static INotificationManager sService;
static public INotificationManager getService()
{
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService("notification");
sService = INotificationManager.Stub.asInterface(b);
return sService;
}
复制代码
能够看到NotificationManager
直接经过查询得到ServiceManager
中 name 为 notification 的 Binder对象,并经过asInterface
方法将这个服务端的Binder
对象转换成客户端所需的 AIDL 接口类型的对象,而后保存到成员变量sService
中,以供后续调用。
须要注意的是,ServiceManager
中注册的服务是不支持普通应用获取的,咱们知道,当咱们须要发送通知的时候,发送的入口以下:
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notiTag, notiId, notification);
复制代码
这里getSystemService(String name)
是Activity
的方法,并非ServiceManager
提供的,Android为了不这些系统服务直接与用户打交道,统一提供了代理类供用户获取服务。
像NotificationManagerService
面向用户的代理类为NotificationManager
,ActivityManagerService
面向用户的代理类为ActivityManager
,这些代理类均被注册在一个叫SystemServiceRegistry
的管理类中(代码路径frameworks/base/core/java/android/app/SystemServiceRegistry.java
),当咱们调用Activity
的getSystemService(String name)
方法去获取系统服务时,最终会获取到SystemServiceRegistry
中的对应代理类,从而咱们就能够利用这些代理类来间接与各类系统服务交互了。