AOSP – Adding a Native Daemon

Android is a great OS for many devices and not mobile only. You can even use Android on devices without display (headless). The most important thing about Android is the fact that it is open source and you can build everything from source.

Android structure:

The lower layer is Linux kernel with some changes (little)

The Native Layer is built above the kernel and hosts the C library, other system libraries, and many daemons

The Application Framework layer hosts all the Android services used by Android Applications

In this post, we will build a Native Daemon in the native layer, make it run on system startup and using system property and build application to communicate with our daemon.

 

Create a directory in device/generic/goldfish/bin/mylogger

Add mylogger.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
int main() {
    int fd=open("/data/data1",O_RDWR|O_CREAT,0660);
    char buffer[100];
    struct sockaddr_in addr = {0};
    size_t addrlen, n;
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    
    addr.sin_family = AF_INET;
    addr.sin_port = htons(2000);
    addr.sin_addr.s_addr = INADDR_ANY;
    bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));
    
    addrlen = sizeof(addr);
    while(1)
    {
        n = recvfrom(sockfd, (void*)buffer, 100, 0,
		(struct sockaddr*)&addr, (unsigned int *) &addrlen);
        buffer[n] = '\n';
        write(fd,buffer,n+1);
    }
    close(fd);
    return 0;
}

Add Android.mk file

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:=\
	mylogger.c

LOCAL_CFLAGS:=-O2 -g
#LOCAL_CFLAGS+=-DLINUX

LOCAL_MODULE_TAGS := eng

LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)

LOCAL_MODULE:=mylogger

# gold in binutils 2.22 will warn about the usage of mktemp
LOCAL_LDFLAGS += -Wl,--no-fatal-warnings

include $(BUILD_EXECUTABLE)

 

If we add the service definition to init.rc file without a security label we will get:

service mylogger does not have a SELinux domain defined

So we define the security label for it:

on property:myprop.test=1 
    start mylogger

on property:myprop.test=0
    stop mylogger

service mylogger /system/xbin/mylogger
    user root
    group root
    seclabel u:r:su:s0

We need to define the system property for SE Android. Add the following line to property_contexts file:

myprop.test		u:object_r:system_prop:s0

 

Writing Client Application

We can write a client application using Android Studio. Simply add a button and write a click handler, use a thread to send a UDP message to the daemon:

public class MainActivity extends AppCompatActivity {
    void sendonemsg()
    {
        DatagramSocket s;
        try {
            s = new DatagramSocket();
            InetAddress local = InetAddress.getByName("127.0.0.1");
            String str="hello service";
            int msg_length = str.length();
            DatagramPacket p = new DatagramPacket(str.getBytes(), msg_length, local, 2000);
            s.send(p);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button b=(Button)findViewById(R.id.button);
        b.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Thread t=new Thread(new Runnable(){

                    @Override
                    public void run() {
                        sendonemsg();;
                    }
                });
                t.start();
            }
        });

    }

Add INTERNET permission request to AndroidManifest.xml file

To set the system property we need to write a system application with C++ code:

static void setService(JNIEnv *env, jclass clazz, jboolean s) {
        if(s)
            property_set("myprop.test", "1");
        else
            property_set("myprop.test", "0");

}

To use property_set function you need to add libcutils to Android.mk:

LOCAL_SHARED_LIBRARIES := \
	libutils liblog libcutils

The last thing to do is add an allow rule to system_app to set the property:

Add the following rule to system_app.te

allow system_app system_prop:property_service { set };

Now setting the system property is triggering start and stop and using the client application we can send messages to the daemon. To see the result cat the file data1:

generic_x86:/ # cat /data/data1                                                                                          
hello service
hello service
hello service

 

Tagged , ,

7 thoughts on “AOSP – Adding a Native Daemon

  1. How will the system property be set? From Settings UI?

  2. “A client app calling a Native daemon’s Socket” –
    Is this possible WHEN trebLe is enabled?

  3. …to be more specific in my previous question:
    Is it possible for a vendor service created socket be accessed by a system PRIV app or an installed app, when treble is enabled?

  4. Thanks for this simple yet informative guide.
    I am having same question as Rayen. Wondering how treble will affect this design, along with the changes in Android P.

  5. Where setService method is called from?

  6. Hello!

    Thanks for the example
    Where should the init.rc and the policy go?

  7. Hi, how can I develop and debug my service project (ie mylogger.c) with a IDEsuch as Eclipse or VS Code?

Comments are closed.