Original not easy, reproduced please indicate the source. If you find any problems in the reading process, please do not hesitate to give advice
preface
This is a based on Android 10 source code, a comprehensive analysis of the Android notification system implementation principle of the series, this is the second, the full series will cover:
- 1. This section describes how to use the Notification and common interfaces
- 2. Process for starting the system notification service
- 3. Server implementation of notification sending
- 4. Client implementation of notification sending (ING)
- 2.Android Notification System customization (ING)
Writing in the front
In order to give readers a more comprehensive understanding of the overall process of System notification service, this article will first briefly introduce how the mobile phone starts the NMS service during the startup process, which involves the startup of the Zygote process and the System process. Then it introduces the function implementation of the NMS service and how to obtain the NMS service.
Brief description: the abbreviation that appears below
NM -> NotificationManager
NMS -> NotificationManagerService
Sysui -> SystemUI
Copy the code
NMS Process for starting the system notification service
Related categories:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/services/java/com/android/server/SystemServer.java
Copy the code
As we know (or pretend to know), the init process is the first process to start when the phone starts. This process will start a process called Zygote, which will create a virtual machine object as it starts. Other processes are then started directly from the Zygote fork, so that each process has its own virtual machine, but that’s another story. The System process is a fork of the Zygote process during startup. It is a System process that is responsible for starting various core System services, such as AMS, PMS, and NMS, during startup.
Here’s how Zygote starts the NMS service step by step:
The Zygote process fork out the System process during startup. Procedure
/*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); . }... }Copy the code
The argv array in zygoteinit. main will contain the start-system-server field, indicating that Zygote needs to start the system process, where startSystemServer=true, The forkSystemServer method is executed next:
/*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 = 1001100 2100 3100 4100 5100 6100 7100 8100 9101 0101 8102 1102 3,"
+ "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", / / step 1: specify the System processes the entrance to the class for the com. Android. Server. The main method of SystemServer}; ZygoteArguments parsedArgs = null; int pid; try { ...... // Step 2: Pid = forkSystemServer(parsedargs. mUid, parsedargs. mGid, parsedargs. mGids, parsedArgs.mRuntimeFlags, null, parsedArgs.mPermittedCapabilities, parsedArgs.mEffectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } // Step 3: Pid = 0 indicates that the child process fork is successfulif (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
Copy the code
There are three main steps:
- 1. Specify
Com. Android. Server. The main function of SystemServer
forSystem
The program entry of a process - 2. By
The Zygote to fork System
Process, and return a process ID. We know that when fork returns an ID of 0, the child process fork succeeds, which is what step 3 executes - 3. When PID =0, the command output in Step 3 is executed
handleSystemServerProcess
Function, which is further completedSystem
The main work to go down is to go to the native layer, where tracing is no longer possible.
System process startup: SystemServer’s main function
As shown above, the Zygote process creates the System process and specifies the program entry as systemServer.main (). Let’s see what this entry function does:
- Direct call
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();
}
Copy the code
run
Method After various preparations are made, various system services are started. The NMS is started instartOtherServices()
Execute in a function
/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void run() {
try {
......
// Start services.
try {
traceBeginAndSlog("StartServices"); startBootstrapServices(); startCoreServices(); startOtherServices(); SystemServerInitThreadPool.shutdown(); }... }Copy the code
Through SystemServiceManager. StartService () start NMS service, SystemServiceManager is a dedicated to create, start, and manage the system service life cycle events management class
/*frameworks/base/services/java/com/android/server/SystemServer.java*/
private void startOtherServices() {... mSystemServiceManager.startService(NotificationManagerService.class); . }Copy the code
The content of the startService function is simple and ends up executing directly to the onStart function of the NMS service.
/*frameworks/base/services/core/java/com/android/server/SystemServiceManager.java*/ public void startService(@NonNull final SystemService service) { mServices.add(service); try { service.onStart(); }... }Copy the code
The NMS service is a System service that lives in the System process and is pulled up during the startup process of the mobile phone System.
How to obtain the NMS service
In this section, we will look at the general functions and implementation of AN NMS service from the perspective of the framework.
- 1.
INotificationManager.aidl
Defines the various interfaces that the system notification service expects to expose to other clients; - 2.
NotificationManagerService
To achieve theINotificationManager.aidl
This interface and willBinder
The proxy object is registeredServiceManager
To enable other services to be invoked with applications such asNotificationManager
Related classes are as follows:
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
Copy the code
The following analysis, we mentioned above, the system at the time of start NMS service, calls the NotificationManagerService. OnStart () function, this is a system notification service entrance, the function is mainly completed:
- 1.
NotificationManagerService
Assignment to a series of member variables (byinit(...)
Method), such asAMS, PMS,
Class, the creation of various secondary class instances, and so on - 2. Register all kinds of broadcasts and listen to the required status, such as on and off screen broadcasts, user switch broadcasts, application add and delete broadcasts, etc
- 3. Implement one
INotificationManager.aidl
Binder proxy object for the interfacemService
Registered toServiceManager
Above mentioned many times INotificationManager. The aidl interface file, we look at the interface: the file is mainly, so several types of interfaces are defined:
/ * frameworks/base/core/Java/android/app/INotificationManager aidl * / - notification to add (including updates), delete, namely we previously ` notify, cancel `, such as the implementation of the interface, Such as ` enqueueNotificationWithTag (...). '- Setting and judging notification properties, such as whether to allow notification of an application to be displayed or whether to allow notification dots (the corner mark on the upper right corner of the desktop icon) to be displayed, such as'setShowBadge (String PKG, int uid, Boolean ShowBadge) notify ` ` - channel ` add and delete, such as ` createNotificationChannels (...). - Notification list such as' StatusBarNotification[] getActivenotifcommunications (String callingPkg) '- Notification status listening on the relevant interface, such as' registerListener(in INotificationListener listener, in ComponentName component, int userid)`
- ......
Copy the code
The content of 1, 2 point does not speak, children’s shoes directly interested in watching the onStart method of the NMS, here we point 3, let’s take a look at INotificationManager. The implementation of an aidl and registration process:
NMS realization 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 ...... }Copy the code
Register the Binder proxy object with the ServiceManager:
/*frameworks/base/services/core/java/com/android/server/notification/NotificationManagerService.java*/
@Override
public void onStart() {// Initialize the member variables and register the various broadcast listeners...... // Register the 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);
}
Copy the code
Where the value of NOTIFICATION_SERVICE is “notification”, The INotificationManager Binder proxy object named Notification can then be acquired by the ServiceManager for other services or applications to interact with. For example, The entry class NotificationManager for developers to operate on notifications, 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;
}
Copy the code
You can see that NotificationManager directly obtains the Binder object whose name is Notification in The ServiceManager by querying. The Binder object on the server is converted to an object of the AIDL interface type required by the client through the asInterface method, which is then stored in the member variable sService for subsequent invocation.
It should be noted that the service registered in ServiceManager does not support the common application to obtain, as we know, when we need to send notification, send the following entry:
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notiTag, notiId, notification);
Copy the code
Here getSystemService(String name) is an Activity method, not provided by ServiceManager, Android in order to avoid these system services directly with the user to deal with, unified provides a proxy class for users to obtain services.
Like a proxy class for the NotificationManager NotificationManagerService user-oriented, ActivityManagerService user-oriented proxy class for ActivityManager, The proxy class has been registered in a class called SystemServiceRegistry management (code path frameworks/base/core/Java/android/app/SystemServiceRegistry. Java), When we call the getSystemService(String name) method on the Activity to get the system service, we will eventually get the corresponding proxy class in the SystemServiceRegistry. We can then use these proxy classes to indirectly interact with various system services.