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
7 thoughts on “AOSP – Adding a Native Daemon”
Comments are closed.
How will the system property be set? From Settings UI?
“A client app calling a Native daemon’s Socket” –
Is this possible WHEN trebLe is enabled?
…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?
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.
Where setService method is called from?
Hello!
Thanks for the example
Where should the init.rc and the policy go?
Hi, how can I develop and debug my service project (ie mylogger.c) with a IDEsuch as Eclipse or VS Code?