The company plans to do customized development for Android system of the device. I have never done system development before, but I only know some basic knowledge, so now I am learning while doing.
System services are an important part of Android, such as ActivityManagerService (AMS), PackageManagerSersvice (PMS), WindowManagerService (WMS), These system services are key services in the Framework layer. This article takes a look at the complete process of adding a system service based on Android source code.
Write AIDL files
File location frameworks/base/core/Java/com/myservice /
IMyService.aidl
package android.myservice;
interface IMyService
{
void setState(int value);
void setName(String name);
void setWhiteList(in List<String> list);
}
Copy the code
AIDL only supports the transfer of primitive Java type data. To pass a custom class, you need to implement the Parcelable interface. In addition, if you pass an array of primitive types, you need to specify the in out keyword, such as void test(in byte[] input, Out byte[] output), use in if the array is passed as an argument to the called end, use out if the array is only used to receive data, and the actual data is filled by the called end.
After the file is written, add it to the compiled Android.mk after LOCAL_SRC_FILES:
frameworks/base/Android.mk
LOCAL_SRC_FILES += \ core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \ core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \ The core/Java/android/accounts/IAccountManager aidl \ code omitted... Core/Java/com/myservice IMyService aidl \ code omitted...Copy the code
Manager class
Android ManagerServices are not directly accessible, and need to be operated through their client proxy class. We also write a proxy class for our Service.
frameworks/base/core/java/com/myservice/MyManager.java
package android.myservice;
import android.myservice.IMyService;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
import java.util.List;
public class MyManager {
private final Context mContext;
private final IMyService mService;
public MyManager(Context context, IMyService sevice) {
mContext = context;
mService = sevice;
}
public void setState(int value){
try {
mService.setState(value);
} catch(RemoteException e) { e.printStackTrace(); }}public void setName(String name){
try {
mService.setName(name);
} catch(RemoteException e) { e.printStackTrace(); }}public void setWhiteList(List<String> list){
try {
mService.setWhiteList(list);
} catch(RemoteException e) { e.printStackTrace(); }}}Copy the code
Writing system services
frameworks/base/services/core/java/com/android/server/myservice/MyService.java
package com.android.server.myservice;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import java.util.List;
import android.myservice.MyManager;
import android.myservice.IMyService;
public class MyService extends IMyService.Stub {
private String TAG = "MyService";
private Context mContext;
public MyService(Context context) {
mContext = context;
}
@Override
public void setState(int value){
Log.d(TAG,"setState:"+value);
}
@Override
public void setName(String name){
Log.d(TAG,"setName:"+name);
}
@Override
public void setWhiteList(List<String> list){
for(int i = 0; i<list.size(); i++){ Log.d(TAG,"setWhiteList:"+list.get(i)); }}}Copy the code
Registration system Services
Add system service constants to Context
frameworks/base/core/java/android/content/Context.java
/ * *@hide* /
@StringDef({ POWER_SERVICE, WINDOW_SERVICE, LAYOUT_INFLATER_SERVICE, ... MY_SERVICE, //add ... HARDWARE_PROPERTIES_SERVICE, //@hide: SOUND_TRIGGER_SERVICE, SHORTCUT_SERVICE, //@hide: CONTEXTHUB_SERVICE, })
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
Copy the code
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.myservice.MyManager}.
* @hide
*
* @see #getSystemService
* @see android.myservice.MyManager
*/
public static final String MY_SERVICE = "myservice";
Copy the code
All system services run in a process called system_server, and we need to add the written services to it. There are many services in SystemServer, so we add our system services to the end
frameworks/base/services/java/com/android/server/SystemServer.java
import com.android.server.myservice.MyService;
private void startOtherServices(a) {
MyService myManagerService = null; .try{
myManagerService = new MyService(context);
Log.i("MyService"."In SystemServer, MyService add..");
ServiceManager.addService(Context.MY_SERVICE, myManagerService);
} catch (Throwable e) {
Log.i("MyService"."In SystemServer, MyService add err.."+e); }}Copy the code
This time to reboot the machine, will report the following error, no permission
E/SELinux: avc: denied { add } for service=myservice pid=1743 uid=1000 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager permissive=0
E/ServiceManager: add_service('myservice',5a) uid=1000 - PERMISSION DENIED
Copy the code
Add SELinux permissions
device/qcom/sepolicy/common/service.te
type myservice_service, app_api_service, system_server_service, service_manager_type;
Copy the code
device/qcom/sepolicy/common/service_contexts
enrichrcsservice u:object_r:radio_service:s0
myservice u:object_r:myservice_service:s0
Copy the code
Permissions can also be added to the system/sepolicy/service_contexts and system/sepolicy/service. The te, the effect is the same, but only can be added in one place, otherwise it will repeat.
Registration Manager
Context.getsystemservice () : context.getSystemService() : context.getSystemService() : context.getSystemService() : context.getSystemService() : context.getSystemService() : context.getSystemService() : context.getSystemService() : context.getSystemService(
frameworks/base/core/java/android/app/SystemServiceRegistry.java
import android.myservice.MyManager;
importandroid.myservice.IMyService; . registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class,new CachedServiceFetcher<ContextHubManager>() {
@Override
public ContextHubManager createService(ContextImpl ctx) {
return new ContextHubManager(ctx.getOuterContext(),
ctx.mMainThread.getHandler().getLooper());
}});
// add MyManager
registerService(Context.MY_SERVICE, MyManager.class,
new CachedServiceFetcher<MyManager>() {
@Override
public MyManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.MY_SERVICE);
IMyService service = IMyService.Stub.asInterface(b);
return new MyManager(ctx, service);
}});
Copy the code
OK, system code modification is complete!
Boot. img and system.img can be compiled separately, with permission control in boot.img and code modification in system.img
After system startup
1970-01-13 04:01:02.700 1550-1550/system_process I/MyService: In SystemServer, MyService add..
Copy the code
If no error is reported, the startup is successful!
App call
Use context.getSystemService(” myService “) to retrieve the MyManager object and call the method in myService.
Client App:
Service:
Done!