Introduction to Android system service

We often use a variety of system management services during Android development, such as window management service WindowManager for window related operations, power management service PowerManager for power related operations, and many other system management services, such as notification management service notificationmanager, vibration management service vibrator Battery management service batterymanagers... These managers provide many control interfaces to the system layer. For app developers, they only need to understand the use of these interfaces to easily control the system and obtain the information of various services of the system, without understanding the specific implementation of these interfaces. For framework developers, they need to understand the common implementation modes of these manager services, maintain these manager interfaces, expand these interfaces, or implement new managers.

Let's look at how a system service is established from a simple system service, vibrator service.

The vibrator service provides an interface to control the vibration of the mobile phone. The application can call the vibrator interface to make the mobile phone vibrate, so as to remind the user.

It can be seen from the official Android documentation that vibrator is only an abstract class with only four abstract interfaces:

The method of using vibration service in the application is also very simple, such as making the mobile phone vibrate for 500 milliseconds:

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);

Vibrator is easy to use. Let's see if it is also easy to implement.

It can be seen from the document that vibrator is only an abstract class defined in the android.os package. The location in the source code is frameworks / base / core / Java / Android / OS / vibrator.java. Which instance is actually used in the application? The vibrator instance used in the application is obtained through a method getsystemservice (context. Vibrator_service) of context, and the implementation of context is generally in contextimpl. Let's take a look at how contextimpl implements getsystemservice:

frameworks/base/core/java/android/app/ContextImpl.java

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this,name);
}

Frameworks / base / core / Java / Android / APP / systemserviceregistry.java (systemserviceregistry is only available after Android 6.0. There is no such class in the code before Android 6.0. The following code is written directly in contextimpl)

 public static Object getSystemService(ContextImpl ctx,String name) {
    ServiceFetcher<?> fetcher = SYstem_SERVICE_FETCHERS.get(name);
    return fetcher != null ? fetcher.getService(ctx) : null;
}

SYstem_ SERVICE_ Map is a HashMap. Take a servicefetcher from the HashMap through the name string of our service, and then return the servicefetcher's getservice(). What is a servicefetcher? What is its getservice()? Since he's from system_ SERVICE_ Map is obtained from the HashMap, so find out what the HashMap put.

The following code can be found by searching systemserviceregistry:

private static <T> void registerService(String serviceName,Class<T> serviceClass,ServiceFetcher<T> serviceFetcher) {
    SYstem_SERVICE_NAMES.put(serviceClass,serviceName);
    SYstem_SERVICE_FETCHERS.put(serviceName,serviceFetcher);
}

Here to system_ SERVICE_ A pair of key / value pairs composed of string and servicefetcher are put in the map. Where is registerservice () called? If you continue to search, you can find many codes similar to the following:

public class SystemVibrator extends Vibrator {
    ...
}

Let's look at how the vibration control of the system is realized from the systemvibrator. Taking hasvibrator () as an example, this is to query whether the current system can vibrate. In systemvibrator, its implementation is as follows:

public boolean hasVibrator() {
    ...
    try {
        return mService.hasVibrator();
    } catch (remoteexception e) {
    }
    ...
}

A mservice. Hasvibrator () is called directly here. What is mservice? Where did you come from? Search and find:

private final IVibratorService mService;
public SystemVibrator() {
    ...
    mService = IVibratorService.Stub.asInterface(
            ServiceManager.getService("vibrator"));
}

Mservice is an ivibratorservice. Let's not worry about ivibratorservice.stub.asinterface, but take a look at what ivibratorservice is. Search the code and find that this is not a java file, but an Aidl file:

frameworks/base/core/java/android/os/IVibratorService.aidl

Aidl (Android interface finalization language) is an interface definition file in Android, which provides a simple cross process communication method for the system.

Several interfaces are defined in ivibratorservice, which are also used in systemvibrator, including the hasvibrator () we just used

interface IVibratorService
{
    boolean hasVibrator();
    void vibrate(...);
    void vibratePattern(...);
    void cancelVibrate(IBinder token);
}

Here is only the interface definition. Where is the interface implementation? Through grep search in the frameworks / base directory or androidxref search, it can be found that the implementation of ivibratorservice interface is in frameworks / base / services / Java / COM / Android / server / vibratorservice.java

public class VibratorService extends IVibratorService.Stub

You can see that vibratorservice implements all the interfaces defined by ivibratorservice and calls to the native layer through JNI for lower level implementation. The lower level implementation is not the content discussed in this document. What we need to analyze is how vibratorservice becomes a system service. So how does vibratorservice register as a system service? In systemserver:

VibratorService vibrator = null;
...
//实例化VibratorService并添加到ServiceManager
traceBeginAndSlog("StartVibratorService");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator",vibrator);
Trace.traceEnd(Trace.TRACE_TAG_SYstem_SERVER);
...
//通知服务系统启动完成
Trace.traceBegin(Trace.TRACE_TAG_SYstem_SERVER,"MakeVibratorServiceReady");
try {
    vibrator.systemReady();
} catch (Throwable e) {
    reportWtf("making Vibrator Service ready",e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYstem_SERVER);

In this way, in systemvibrator, you can connect to the vibratorservice through the following code to communicate with the underlying system services:

IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator"));

Mservice is equivalent to an agent of ivibratorservice in the application layer. All implementations are still in the vibratorservice of system server.

When looking at the code, you can find that registerservice is called statically in the static code block, so each manager obtained by getsystemservcr is also a singleton.

From the above analysis, we can summarize the whole implementation process of vibrator service:

frameworks/base/core/java/android/os/Vibrator.java

frameworks/base/core/java/android/os/SystemVibrator.java

frameworks/base/core/java/android/os/IVibratorService.aidl

frameworks/base/services/java/com/android/server/VibratorService.java

frameworks/base/services/java/com/android/server/SystemServer.java

VibratorService vibrator = null;
...
//实例化VibratorService并添加到ServiceManager
Slog.i(TAG,"Vibrator Service");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator",vibrator);
...
//通知服务系统启动完成
try {
    vibrator.systemReady();
} catch (Throwable e) {
    reportWtf("making Vibrator Service ready",e);
}

frameworks/base/core/java/android/os/SystemVibrator.java

private final IVibratorService mService;
...
public SystemVibrator() {
    ...
    mService = IVibratorService.Stub.asInterface(
            ServiceManager.getService("vibrator"));
    ...
    public boolean hasVibrator() {
        ...
        try {
            return mService.hasVibrator();
        } catch (remoteexception e) {
        }
        ...
    }
}

frameworks/base/core/java/android/content/Context.java

public static final String VIBRATOR_SERVICE = "vibrator";

frameworks/base/core/java/android/app/ContextImpl.java

registerService(VIBRATOR_SERVICE,new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
    return new SystemVibrator(ctx);
}});  

Vibrator mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
mVibrator.vibrate(500);

frameworks/base/Android.mk

LOCAL_SRC_FILES += \
...
core/java/android/os/IVibratorService.aidl \

If we need to implement a new system service, we can extend a new service in the system according to the above steps and provide an interface to the application layer. If you want to add a new interface to the vibrator, you need the following 3 steps:

In this way, the new interface of vibrator can be used in the application.

In the above implementation, we only see that the interface of the system service is called from the application layer through the service agent. What should we do if we want to notify the application layer of the status of the system service?

We know that using broadcast broadcasting can realize cross process message transmission, and some system services also use this method. For example, when the battery management service batterymanagerservice receives the battery status change information reported by the bottom layer, it encapsulates the current battery status in an intent, and the action is android.intent.action.battery_ CHANGED。 As long as an application registers a corresponding broadcastreceiver, it can receive the battery status information sent by the battermanagerservice.

From the above, we can know that a set of interfaces are defined through Aidl, and the system server implements these interfaces. The application side can access the interface of the system service by using a corresponding agent. In turn, let the application side implement Aidl interface, and the system server uses an agent to call the interface of the application side? The answer is yes. Then the next question is how to make the system service get this agent. Let's take another example of locationmanager.

//获得定位服务
LocationManager locationManager = 
        (LocationManager) getSystemService(Context.LOCATION_SERVICE);

//定义定位监听器
LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
        //监听到位置信息
    }
    ...
};

//注册监听器
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,locationListener);

As can be seen from the above code, we created a location listener locationlistener and registered this listener in locationmanager. When the system locates the location of the system, it will call back onlocationchanged() of the listener to notify the listener of the location information. Locationlistener is an example of system service calling application layer interface. Let's study the implementation of locationlistener.

Let's start with how locationmanager registers locationlistener: Frameworks / base / location / Java / Android / location / locationmanager.java

private final ILocationManager mService;
...
private void requestLocationUpdates(LocationRequest request,LocationListener listener,Looper looper,PendingIntent intent) {
    ...
    // wrap the listener class
    ListenerTransport transport = wrapListener(listener,looper);
    try {
        mService.requestLocationUpdates(request,transport,intent,packageName);
   } catch (remoteexception e) {
       Log.e(TAG,"remoteexception",e);
   }
}

You can see that the locationlistener is re encapsulated into a listener transport and then passed to the ilocationmanager. From the previous analysis, you can guess that the ilocationmanager should be an agent of the locationmanagerservice. So what is listenertransport? Search locationmanager.java to find:

private class ListenerTransport extends ILocationListener.Stub {
    ...
    @Override
    public void onLocationChanged(Location location) {
        ...
    }
}

It was originally an inherited implementation of ilocationlister.stub, so ilocationlister should be an Aidl interface definition: Frameworks / base / location / Java / Android / location / ilocationlister.aidl

oneway interface ILocationListener
{
    void onLocationChanged(in Location location);
    ...
}

In locationmanagerservice, the message can be delivered to the application layer listener by calling the ilocationlistener method:

mListener.onLocationChanged(new Location(location));

One is that the application calling end needs to wait for the service implementation end to complete the processing and return the processing results. In this way, if the service end is blocked, the application end will also be blocked. Therefore, pay attention not to block when implementing the service end.

The other is that the calling end does not need to wait for the server to return the result, but directly returns void after the call is completed, so that the blocking of the server will not affect the application end. When defining such a one-way interface in Aidl, the oneway keyword needs to be added, such as:

oneway void statusBarVisibilityChanged(int visibility);

For the interfaces that need to be called on the server side and implemented on the application side, considering the stability and security of the system, they are generally designed as the second type above, that is, all interfaces in Aidl are one-way, such as ilocationlister above

oneway interface ILocationListener

There is only one instance of each system service in the system process, and the agent of the system service in the application is also a single instance. Moreover, the access of the application side uses independent threads to respond in the system process. Therefore, when accessing the interface of the same system service, multiple threads or multiple processes will access at the same time. In order to ensure the thread safety of system services, it is necessary to protect the process of system services from multi-threaded access. At present, there are two main methods to realize thread safety:

One is to lock an object instance (usually the service object itself) through the synchronization lock mechanism, so that the service can only respond to one access request at the same time, such as in locationmanagerservice:

public boolean callStatusChangedLocked(...) {
    ...
    synchronized (this) {
    ...
    }
}

Another method is to use the handler mechanism. This service generally creates a separate thread. When an application access request arrives, it will send a message to the handler of the service thread. Using the feature of single thread sequential execution, it ensures that all accesses are processed in order, but this method is only suitable for one-way access, Not suitable for two-way access that requires return.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>