Analysis on Property service settings of the Android Property System

Source: Internet
Author: User

Analysis on Property service settings of the Android Property System

There is a registry in the Window, which can store key-value pairs similar to key: value. On the android platform, there is a similar mechanism called Property service for initialization, the adb shell command uses setprop and getprop to set, modify, and query functions.

Problem:
When the thread calls the readyToRun function after SurfaceFlinger is started, a property value is set:
Status_t SurfaceFlinger: readyToRun ()
{
LOGI ("SurfaceFlinger's main thread ready to run ."
"Initializing graphics H/W ...");
...
/*
* We're re now ready to accept clients...
*/


// Start boot animation
Property_set ("ctl. start", "bootanim ");

Return NO_ERROR;
}

How does one start the bootanim service? Bootanim is a separate process of the boot animation. in rc, service bootanim/system/bin/bootanimation is started as a service. To use the graphic system function, you must wait for the SurfaceFlinger to start before executing it. Here, Attribute service is used as a process synchronization method.

Let's take a simple look at this process:


1. Property client process

Property_set ("ctl. start", "bootanim"); this is the startup trigger point !!!
-->
Property_set @/system/core/libcutils/properties. c
Int property_set (const char * key, const char * value)
{
Msg. cmd = PROP_MSG_SETPROP;
Strcpy (char *) msg. name, key );
Strcpy (char *) msg. value, value );


Return send_prop_msg (& msg );
}
-->
Communication is implemented through a common TCP (SOCK_STREAM) socket.
Static int send_prop_msg (prop_msg * msg)
{
S = socket_local_client (PROP_SERVICE_NAME,
ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM );
If (s <0) return-1;

While (r = send (s, msg, sizeof (prop_msg), 0) <0 ){
If (errno = EINTR) | (errno = EAGAIN) continue;
Break;
}
Close (s );
Return r;
}

 

2. How does the server monitor and implement the injection process?

 


Main @/system/core/init. c
Int main (int argc, char ** argv)
{
Int property_set_fd =-1;

/* Read any property files on system or data and
* Fire up the property service. This must happen
* After the ro. foo properties are set above so
* That/data/local. prop cannot interfere with them.
*/
Property_set_fd = start_property_service ();

 

// Set property_set_fd to the poll listening queue

Ufds [0]. fd = device_fd;
Ufds [0]. events = POLLIN;
Ufds [1]. fd = property_set_fd;
Ufds [1]. events = POLLIN;
 
For (;;){
...
Nr = poll (ufds, fd_count, timeout );

// Listening to requests with properties to be processed
If (ufds [1]. revents = POLLIN)
Handle_property_set_fd (property_set_fd );
...
}
Return 0;
}


Let's take a look at how start_property_service is implemented?
Int start_property_service (void)
{
Int fd;

Load_properties_from_file (PROP_PATH_SYSTEM_BUILD );
Load_properties_from_file (PROP_PATH_SYSTEM_DEFAULT );
Load_properties_from_file (PROP_PATH_LOCAL_OVERRIDE );
/* Read persistent properties after all default values have been loaded .*/
Load_persistent_properties ();

Fd = create_socket (PROP_SERVICE_NAME, sosock_stream, 0666, 0, 0 );
If (fd <0) return-1;
Fcntl (fd, F_SETFD, FD_CLOEXEC );
Fcntl (fd, F_SETFL, O_NONBLOCK );

Listen (fd, 8 );
Return fd;

}

 


OK. Now, I have created a SOCK_STREAM socket and entered the listener listen status.

Handle_property_set_fd @/system/core/init/property_service.c

Void handle_property_set_fd (int fd)
{

// 1. Receive socket requests to connect to www.2cto.com
If (s = accept (fd, (struct sockaddr *) & addr, & addr_size) <0 ){
Return;
}

 

// 2. Number of property requests received

R = recv (s, & msg, sizeof (msg), 0 );

Close (s );

 

// 3. process the sensitive request data
Switch (msg. cmd ){
Case PROP_MSG_SETPROP:
...
If (memcmp (msg. name, "ctl.", 4) = 0 ){
If (check_control_perms (msg. value, cr. uid, cr. gid )){
Handle_control_message (char *) msg. name + 4, (char *) msg. value );
}
} Else {
If (check_perms (msg. name, cr. uid, cr. gid )){
Property_set (char *) msg. name, (char *) msg. value );
}
}
}
}


Because the request message is ctl. start, execute the handle_control_message function:
Handle_control_message @/system/core/init. c
Void handle_control_message (const char * msg, const char * arg)
{
If (! Strcmp (msg, "start ")){
Msg_start (arg );
} Else if (! Strcmp (msg, "stop ")){
Msg_stop (arg );
} Else {
ERROR ("unknown control msg '% s' \ n", msg );
}
}


Static void msg_start (const char * name)
{
Svc = service_find_by_name (name );
...
Service_start (svc, args );
}


Static void msg_stop (const char * name)
{
Struct service * svc = service_find_by_name (name );
Service_stop (svc );
}


Let's take a look at the above code. You should understand that it is to request the ServiceManager service to start or stop a service. This is the bootanim service.


Why does bootanim start in the init. rc Script without being started? See the init. rc Script:
Service bootanim/system/bin/bootanimation
User graphics
Group graphics
Disabled
Oneshot

No disabled is displayed. This keyword is used when added to the service_list double bond table:

# Define SVC_DISABLED 0x01/* do not autostart with class */
# Define SVC_ONESHOT 0x02/* do not restart on exit */
# Define SVC_RUNNING 0x04/* currently active */
# Define SVC_RESTARTING 0x08/* waiting to restart */
# Define SVC_CONSOLE 0x10/* requires console */
# Define SVC_CRITICAL 0x20/* will reboot into recovery if keeps crashing */

Static void parse_line_service (struct parse_state * state, int nargs, char ** args)
{
Kw = lookup_keyword (args [0]);
Switch (kw ){
Case K_disabled:
Svc-> flags | = SVC_DISABLED;
Break;
...
}

This flags value is determined when service_start and service_stop are executed:

Void service_stop (struct service * svc)
{
/* If the service has not yet started, prevent
* It from auto-starting with its class
*/
Svc-> flags | = SVC_DISABLED;
...
}

Initial Service start process:
Int do_class_start (int nargs, char ** args)
{
/* Starting a class does not start services
* Which are explicitly disabled. They must
* Be started individually.
*/
Service_for_each_class (args [1], service_start_if_not_disabled );
Return 0;
}


Static void service_start_if_not_disabled (struct service * svc)
{
If (! (Svc-> flags & SVC_DISABLED )){
Service_start (svc, NULL );
}
}


This will determine whether the Service is initially started and can be determined through the SVC_DISABLED flag.

 


There is also a supplementary explanation:

Ctr. start and ctr. stop system attributes?


Each service must be in/init. rc definition. when the Android system is started, the init daemon will parse the init. rc and start the property service. The property "ctl. start and ctl. stop is used to start and stop the service. Once you receive a request to set the "ctrl. start" attribute, the property service uses this attribute value as the service name to locate the service and start the service. The startup result of this service will be placed in the "init. svc. <service name>" attribute. The client application can poll the attribute value to determine the result.

 

 

Common Code Syntax:

Static const char DAEMON_NAME [] = "dhcpcd ";
Static const char DAEMON_PROP_NAME [] = "init. svc. dhcpcd ";

 

 

Int dhcp_stop (const char * interface)
{
Char result_prop_name [PROPERTY_KEY_MAX];
Const char * ctrl_prop = "ctl. stop ";
Const char * desired_status = "stopped ";


...

/* Stop the daemon and wait until it's reported to be stopped */
Property_set (ctrl_prop, DAEMON_NAME );
If (wait_for_property (DAEMON_PROP_NAME, desired_status, 5) <0 ){
Return-1;
}


}

 

From andyhuabing's column

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.