android系统服务的添加(android系统添加自定义服务)

android如何添加自定义服务?

    • 1. 原因
    • 2. 环境:
    • 3. 网上资料:
    • 4. adil设计接口
    • 5. TestService源码编写
    • 6. 系统service添加
    • 7. 将新增的service添加到system server.
    • 8. 注册服务
    • 9. 其他地方修改
    • 10.编译
    • 11. 查看运行结果:

android service
android系统服务
android自定义服务添加
安卓系统服务添加、
自己的服务进程添加

1. 原因

这时间的工作,涉及到androd framework层的问题,客户总是有各种奇葩问题已经各自服务要求。
虽然在系统启动最初此,init.rc的时候,我们加入我们自己的config程序(一个c写层可执行程序,跟着系统一起编译到系统中),可以做一些c语言的配置或者做成服务后台一直运行。
但是,毕竟只是一个可执行程序,而且是c写的,即便做成服务,和java framework层通信也诸多不便。
于是我想直接在android做一个service。刚刚好这两天有点时间,赶紧做起来。

2. 环境:

我的平台和环境是:

	rk3399, 
	android 7.1
	ubuntu 14.04 deskop

3. 网上资料:

先在网上搜索一下相关资料:

https://blog.csdn.net/qq_32072451/article/details/78140251

这个仁兄写的就非常明晰,而且做过androi,刚刚接触framework的一看就基本了解。下面开始参考他的做法做一遍。

4. adil设计接口

在/frameworks/base目录下新建一个文件夹wqservice,在wqservice目录下新建Android.mk和/java/android/wqmodule/test,可以根据自己的需要命名。
在/frameworks/base/wqservice/java/android/wqmodule/test目录下存放封装接口的java文件和对应的aidl文件。也就是java文件和aidl文件都丢那里就可以了。

先在/frameworks/base/wqservice/目录下的新建一个makefile文件:Android.mk,这个是最简单的内容,如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, java)
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_MODULE := wqmodule
include $(BUILD_JAVA_LIBRARY)

下面就是写这个接口,android的接口描述是aidl文件:
关于aidl文件,如不了解,请参考:

 https://www.jianshu.com/p/d1fac6ccee98

在/frameworks/base/wqservice/java/android/wqmodule/test下新建一个aidl文件,命名为ITestManager.aidl,我这里就写一个测试的方法,没什么实际意义,内容为:

package android.wqmodule.test;
/**
 * {@hide}
 */
interface ITestManager {
    void testMethod();
}

5. TestService源码编写

对应的TestManager.java,TestManager只是一个操作类,真正的实现是在TestService.java, 所以在同样的文件夹下面,新建一个TestService.java,内容如下:

package android.wqmodule.test;
import android.util.Slog;
import android.os.RemoteException;

public class TestManager {

    private final ITestManager mService;

    public TestManager(ITestManager mService) {
        //这里把ITestManager传进来,可以看看系统其它service,都是这样写的
        this.mService = mService;
    }

    public void testMethod() {
        try {
            mService.testMethod();
            Slog.i("add_service_test", "TestManager testMethod");
        } catch (RemoteException ex) {
            ex.printStackTrace();
        }        
    }
}

6. 系统service添加

在frameworks/base/services/core/java/com/android/server/文件夹创建一个TestService.java,这个文件夹有很多的其它service,像BatteryService

package com.android.server;
import android.content.Context;
import android.util.Slog;
import android.wqmodule.test.ITestManager;
//这里的ITestManager.Stub是固定写法
public class TestService extends ITestManager.Stub {
    private final Context mContext;

    public TestService(Context context) {
        super();
        mContext = context;
    }
    public void testMethod() {
        // 测试方法,为了测试执行情况,在这里加log
        Slog.i("add_service_test", "TestService testMethod");
    }
 }

由于我们在frameworks/base目录下增加了一个新的目录/wqservice, 所以需要在/build/core/pathmap.mk中增加到FRAMEWORKS_BASE_SUBDIRS,注意最后一句,原先是没有的,需要我们自己加:

FRAMEWORKS_BASE_SUBDIRS := \
    $(addsuffix /java, \
        core \
        graphics \
        location \
        media \
        media/mca/effect \
        media/mca/filterfw \
        media/mca/filterpacks \
        drm \
        opengl \
        sax \
        telecomm \
        telephony \
        wifi \
        keystore \
        rs \
        wqservice \
     )

/frameworks/base/Android.mk也要修改, 注意增加的这两句(红色字体):


wqservice/java/android/wqmodule/test/ITestManager.aidl \
android/wqmodule/test

LOCAL_SRC_FILES +=
core/java/android/service/quicksettings/IQSTileService.aidl
telephony/java/com/mediatek/internal/telephony/ITelephonyEx.aidl
telephony/java/com/mediatek/internal/telephony/ISetDefaultSubResultCallback.aidl
wqservice/java/android/wqmodule/test/ITestManager.aidl



packages_to_document :=
android
javax/microedition/khronos
org/apache/http/conn
org/apache/http/params
org/apache/http/params
android/wqmodule/test


我加了这里后,编译是没有问题的,但是整体编译时却没有把jar包编出来。

还需要修改build/target/product/base.mk 和 alps/build/target/product/generic_no_telephony.mk,把要编译的模块名写进去,跟自己定义的Android.mk中保持一致:


— a/alps/build/target/product/generic_no_telephony.mk
+++ b/alps/build/target/product/generic_no_telephony.mk
@@ -28,7 +28,8 @@ PRODUCT_PACKAGES :=
Provision
SystemUI
EasterEgg \

  • WallpaperCropper
  • WallpaperCropper
    + wqmodule

PRODUCT_PACKAGES +=
20-dns.conf
95-configured


wm
+ wqmodule

把这里加进去,整体编译就没问题了。


7. 将新增的service添加到system server.

在/framework/base/services/java/com/android/server/SystemServer.java,wqService,像这样:

--- a/alps/frameworks/base/services/java/com/android/server/SystemServer.java
+++ b/alps/frameworks/base/services/java/com/android/server/SystemServer.java
@@ -683,6 +683,12 @@ public final class SystemServer {
             Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);

             mSystemServiceManager.startService(TelecomLoaderService.class);
+             TestService test = new TestService(context);      
+             ServiceManager.addService(Context.TEST_SERVICE, test); 
+             Slog.i("add_service_test", "SystemServer add service");

             traceBeginAndSlog("StartTelephonyRegistry");

这里的Context.TEST_SERVICE ,当然要自己在Context中添加。

gedit ./system/sepolicy/service_contexts
添加如下定义,决定系统中看到的服务名称:

public static final String TEST_SERVICE= “test”;

8. 注册服务

另外,还要在SystemServiceRegistry中注册这一service,注意7.0的代码是这个类,7.0以下的代码可能是ContextImpl这个类:

--- a/alps/frameworks/base/core/java/android/app/SystemServiceRegistry.java
+++ b/alps/frameworks/base/core/java/android/app/SystemServiceRegistry.java

//注意,在要引入头类和包,路径名称如下:


+ import android.wqmodule.test.TestManager;
+ import android.wqmodule.test.ITestManager;
...
...
...

@@ -158,6 +158,11 @@ import com.mediatek.usp.UspManager;

 /**
  * Manages all of the system services that can be returned by {@link Context#getSystemService}.
  * Used by {@link ContextImpl}.
@@ -177,6 +182,17 @@ final class SystemServiceRegistry {
     private SystemServiceRegistry() { }

     static {
+                registerService(Context.TEST_SERVICE,TestManager.class,  
+                new CachedServiceFetcher(){  
+            @Override   
+            public TestManager createService(ContextImpl ctx)  
+            {  
+                IBinder b = ServiceManager.getService(Context.TEST_SERVICE);  
+                Log.i("add_service_test","SystemServiceRegistry registerService method");  
+                return new TestManager(ITestManager.Stub.asInterface(b));  
+            }});  

9. 其他地方修改

特别注意,如果没有下面这两个修改,编译完了之后,不能正常开机,从log中看到是什么安全问题。
这里的命名跟Context中自己添加的保持一致,把大写改成小写。这个文件在不同的代码中位置可能不一样,有些在device目录下。
将服务加入到源码中,编译备份/alps/system/sepolicy/service.te

--- a/alps/system/sepolicy/service.te
+++ b/alps/system/sepolicy/service.te
@@ -119,3 +119,4 @@ type wifip2p_service, app_api_service, system_server_service, service_manager_ty
 type wifiscanner_service, system_api_service, system_server_service, service_manager_type;
 type wifi_service, app_api_service, system_server_service, service_manager_type;
 type window_service, system_api_service, system_server_service, service_manager_type;
+type test_service, system_api_service, system_server_service, service_manager_type;  

给服务权限:
gedit /external/sepolicy/service_contexts
或者:
gedit ./system/sepolicy/service_contexts

上面的文件路径可能二选一,因为有些版本的android系统,不是相同路径,我的android 7.1路径是system/sepolicy/service_contexts。

--- a/alps/system/sepolicy/service_contexts
+++ b/alps/system/sepolicy/service_contexts
@@ -144,4 +144,5 @@ wifip2p                                   u:object_r:wifip2p_service:s0
 wifiscanner                               u:object_r:wifiscanner_service:s0
 wifi                                      u:object_r:wifi_service:s0
 window                                    u:object_r:window_service:s0
+test                                      u:object_r:test_service:s0 

在文件最底下,加入下面的test服务,这个test后面可以在adb shell中看到,名字就是test。

至此,添加系统service的代码就写完了,剩下的就是编译了。

10.编译

回到anndroid源码根目录下,先执行make update-api,不能直接make,否则编译不能通过。
重新编译一席android的时间很长,可以。先编译framework.jar,然后编译service.jar,最后编译自己加wqmodule。可以用mm/mmm命令编译,没问题后再整编,由于是不是库也不是可执行文件,不能adb push去更新文件验证,每次都只能刷整包验证。

11. 查看运行结果:

查看logcat,是否运行:

logcat|grep "add_service_test"

用service list命令查看:

service list|grep wq[ 1949.320288]
test: [android.wqmodule.test.ITestManager]

从上面的信息可以知道,我们已经成功的在android系统中写入字节的服务程序,名字为test,service已经在后台运行,我们可以愉快的进行服务操作或者对各种客户需求进行定制修改了。

你可能感兴趣的:(技术心得以及事项,安卓service,服务添加,自定义服务,service)