Android Treble Architecture: Part 3 - Changes for Treble[Binder & ServiceManager]


Introduction.

We saw in the earlier tutorial an overview of the changes done as part of Project Treble. We also understood how decoupling the Vendor HAL implementation from the core system framework avoids re-working on the HAL.




In this tutorial let us start looking at the core differences in detail. During the analysis we will also learn the core components and the major how to do’s for being Treble compliant.

Binder Changes.

For Treble to work and decouple the HAL’s from the core framework, A lot of changes were done to the existing binder infrastructure. Some of these are.

1.     support multiple /dev instances.
2.     Support multiple selinux contexts for these owners of the binders dev.

The binder.devices parameter is a comma-separated list of strings that specifies the names of the binder device nodes that will be created. Each binder device has its own context manager, and is therefore logically separated from the other devices.



The 3 new /dev/ interfaces in binder now decouple the need to have the HAL in the same process context.

Prior to OREO there was only one service manager which would use /dev/binder and talk to the HAL’s, However Android now has various service managers for
1.     Framework->Framework
2.     Framework->Vendor
3.     Vendor->Vendor communications.


Binder communication changes.

The Treble architecture above shows just how important is the Binder communication infrastructure.
All the cross process communications are achieved using the binder interface. This might look transparent to the developer and it feels like a local function call. However, a lot goes in achieving this transparency.

To implement the decoupling of the framework and the HAL infrastructure binders plays a very important role. The binder communication is still used between Framework and HAL, and the communication interface is defined by HIDL[We will discuss Hardware Interface Description Language aka HIDL in details later].

In Treble, multiple binder domains have been introduced and multiple binder devices have been added. The core implementation principle of the binder driver has not changed however.

Since the Android framework and HAL now use Binder to communicate with each other. This communication greatly increases the Binder traffic.

To effectively split the Binder traffic between the framework (device-independent) and the vendor (device-specific) code, Android O introduces the concept of "Binder context".
Each Binder context has its own device node and context (service) manager. You can only access it through the device node to which the context manager belongs, and when a Binder node is passed through a specific context, the context manager can only be accessed from the same context by another process, ensuring that these domains are completely isolated from each other.

For example, In order to display /dev/vndbinder, we need to make sure the kernel configuration CONFIG_ANDROID_BINDER_DEVICES is set to "binder, hwbinder, vndbinder".

From the following link for kernel 4.4

  


All the nodes from the configuration gets passed as the parameters.
  



All the nodes get created and initialized.
  

We can see from above all the 3 nodes, /dev/binder, /dev/hwbinder & /dev/vndbinder are initialized and a context gets associated with them.


 As shown above, These different binder nodes are used for achieving framework->app,framework->vendor & vendor->vendor IPC.

Since both vndbinder and binder use the libbinder.so librarywe need to pass the node to be used in this case.
For an Example: We can see the mediacodecservice uses the vndbinder


For more details on the changes done in binder driver for supporting HIDL or Treble please see the following.



ServiceManager Changes [Extensions].

To achieve the proper decoupling of HAL and framework, Treble also extends the existing ServiceManager framework by adding two more such managers.

So in total we now have 3 different ServiceManagers which uses these different binder nodes for IPC and achieve process decoupling. They are the following

1.     ServiceManager:
2.     HwServiceManager:
3.     VndServiceManager:

As seen above since we have 3 nodes in the binder interface, The 3 servicemanagers use these for all IPC.


Let us see these managers and their interactions with the binder architecture.

ServiceManager uses /dev/binder.


HwServiceManager uses /dev/hwbinder.


vndServiceManager uses /dev/vndbinder.




Since both vndbinder and binder use the libbinder.so library, when opening the binder device, we need to call:
ProcessState::initWithDriver("/dev/vndbinder"); to specify which open binder device to open.

Let us see these Managers one by one.

ServiceManager.

The ServiceManager has not gone too many changes apart from the fact that now it uses Android.bp [Read blueprint- Android’s new way of building things using soong and the GO language].

However the most important point to note is that the same code gets duplicated as vndservicemanager based on the VENDORSERVICEMANAGER compilation flag [We will come to vndservicemanager later below].




Let us have a look at the Makefile, servicemanager.rc is used to start the servicemanager during startup.


servicemanager.rc

Note, we have already covered the ServiceManager startup and registration of a service code details in an earlier tutorial. Please see this link for a revisit.


Vndservicemanager.

In the earlier versions of Android, All services were registered using servicemanager [as shown above], They were obtained by a typical call to “sm->getService(“name of the service”)” by the processes needing their services.

Starting Android O, The servicemanager is now only dedicated to frameworks and application processes which are no longer accessible to vendor processes.

However, vendor services can now use vndservicemanager, a new instance of servicemanager that uses /dev/vndbinder instead of /dev/binder.

The vendor process communicates with vndservicemanager without changes in the core concepts of service_manager, The only exception being the new binder node.

Servicemanager and vndservicemanager both use the same code compiled from service_manager.c. The main difference been the following.

1.     Macro definition of VENDORSERVICEMANAGER to indicate the code for vndservicemanager gets compiled.
2.     Use of /dev/vndbinder as an extra argument to the vndservicemanager executable.
3.     Use of a separate selinux handle for labelling [Quite understandable given that the processes using them are different]

  


The Makefile which sets the MACRO and the related .rc file. 



The vndservicemanager.rc which adds extra parameter of /dev/vndbinder for use.




One important point of difference between the vndservicemanager and servicemanager is the use of different sepolicy context[Apart from the binder node difference].

These differences can be easily found by comparing the contents of following files.


 vs


The salient one’s being.
1.     The selinux policy files used by servicemanager and vndservicemanager are different
a.      Servicemanager uses /system/etc/selinux/plat_service_contexts
b.      Vndservicemanager uses /vendor/etc/selinux/vndservice_contexts
2.     The labelling of the resources are different eg:
a.      Servicemanager uses service list
b.      Vndservicemanager uses vndservice list


Let us see some other ones as well.






HwServiceManager.

Probably the most important and differentiating component in the servicemanager list would be the HwServiceManager.

Since It uses the HIDL [Hardware Interface Description Language aka AIDL for the HAL] a lot of changes are required and hence it cannot re-use the servicemanager source unlike the vndservicemanager.


The code for the HwServicemanager is in system/hwservicemanager [ https://android.googlesource.com/platform/system/hwservicemanager/+/android-8.1.0_r9 ].
  

The HwserviceManager gets started during boot through the hwservicemanager.rc file. 

 


Let us look at the Android.bp file for the hwservicemanager.
  


Also, see that somewhere above we saw that both servicemanager & vndservicemanager both use libbinder [With a difference in the node], However hwservicemanager uses libhwbinder.


The following table shows the main contents of both the libraries. It is important to see the files which are same/similar across. 


libhwbinder
location: system/libhwbinder/
libbinder
location: frameworks/native/libs/binder/
Android.bp
aidl
Binder.cpp
Android.bp
BpHwBinder.cpp
AppOpsManager.cpp
BufferedTextOutput.cpp
Binder.cpp
.clang-format
BpBinder.cpp
Debug.cpp
BufferedTextOutput.cpp
IInterface.cpp
Debug.cpp
include/
IActivityManager.cpp
IPCThreadState.cpp
IAppOpsCallback.cpp
IAppOpsService.cpp
IMediaResourceMonitor.cpp
IBatteryStats.cpp
IMemory.cpp
IInterface.cpp
include
Parcel.cpp
IPCThreadState.cpp
PREUPLOAD.cfg
IPermissionController.cpp
ProcessState.cpp
IpPrefix.cpp
Static.cpp
IProcessInfoService.cpp
TextOutput.cpp
IResultReceiver.cpp
vts/
IServiceManager.cpp

IShellCallback.cpp

MemoryBase.cpp

MemoryDealer.cpp

MemoryHeapBase.cpp

Parcel.cpp

PermissionCache.cpp

PersistableBundle.cpp

ProcessInfoService.cpp

ProcessState.cpp

Static.cpp

Status.cpp

tests

TextOutput.cpp

Value.cpp



We will get into more into the binder library details at a later stage.


We now have fair idea on the key differences between the version of Android with and without the Treble feature.

We will continue our analysis in the next tutorials.

Comments

Post a Comment

Popular posts from this blog

Android Audio Tutorial [Part Three] : AudioFlinger Introduction and Initialization

Android External Storage Support: Volume Daemon (vold) Architecture

Android Audio Tutorial [Part One] : Introduction