Add system service in framework

前言:
准备记录一下自己的学习笔记,本文代码基于Android M 源码

1.编写AIDL

android/frameworks/base/core/java/android/os/ITestService.aidl

interface ITestService {
    test();
}

2.修改mk文件

android/frameworks/base/Android.mk

LOCAL_SRC_FILES += \
    core/java/android/os/ITestService.aidl

3.编写真正工作的服务类,继承ITestService.Stub类

(目前他并不是一个真正的服务,下面会通过SystemServer注册)
android/frameworks/base/services/core/java/com/android/server/TestService.java

public class TestService extends ITestService.Stub {
    //实现ITestService.aidl中定义的接口。
    test()  {
        //调用native方法
    }
}

4.编写一个TestService管理类,TestServiceManager,方便app调用

android/frameworks/base/core/java/android/os/TestServiceManager.java

public class TestServiceManager {
    private static final String TAG = "TestServiceManager";

    private final ITestService mService;

    public TestServiceManager() {
        mService = ITestService.Stub.asInterface(
                ServiceManager.getService("test"));
    }

    public TestServiceManager(Context context) {
        super(context);
        mService = ITestService.Stub.asInterface(
                ServiceManager.getService("test"));
    }

    public void test() {
        if (mService == null) {
            Log.w(TAG, "Failed");
            return;
        }
        try {
            mService.test();
        } catch (RemoteException e) {
            Log.w(TAG, "Failed.", e);
        }
    }
}

5.将自定义服务注册到SystemServer,使得开机过程中被添加。

android/frameworks/base/services/java/com/android/server/SystemServer.java
简单看一下流程,从main函数进入,会调用自身的run方法

public static void main(String[] args) {
      new SystemServer().run();
}

在run方法中,通过下面的方法启动:开机,核心,以及其他服务

private void run() {
    ...
    // Start services.
    try {
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
     } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    }
    ...
}

因此可以把自己创建的service 添加到startOtherServices中

public final class SystemServer {
    ....
    private void startOtherServices() {
        ....
        TestService test = null;
        ....
        Slog.i(TAG, "Test Service");
        test = new TestService(context);
        ServiceManager.addService("test", test);
        //ServiceManager.addService(Context.TEST_SERVICE, test);
        ....
        try {
            test.systemReady();
        } catch (Throwable e) {
            reportWtf("making Test Service ready", e);
        }
    }
    ....
}

:另外可以把"test"字段,定义在Context中,方便从app中获取service
android/frameworks/base/core/java/android/content/Context.java

    public static final String TEST_SERVICE = "test";

6.让app侧,可以通过getSystemService接口获得服务

android/frameworks/base/core/java/android/app/ContextImpl.java
通过查看getSystemService实现

@Override
public Object getSystemService(String name) {
    return SystemServiceRegistry.getSystemService(this, name);
}

实际是通过SystemServiceRegistry.getSystemService来获取具体的服务
android/frameworks/base/core/java/android/app/SystemServiceRegistry.java

public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
}
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
            new HashMap<String, ServiceFetcher<?>>();

获取系统服务是通过ServiceFetcher的getService来获取的,并且SYSTEM_SERVICE_FETCHERS就是一个Map实例,所以肯定是通过put方法为它赋值的, 通过registerService注册

private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}

所以在SystemServiceRegistry的static静态代码块中进行注册

static {
.....
        registerService(Context.VIBRATOR_SERVICE, TestServiceManager.class,
                new CachedServiceFetcher<TestServiceManager>() {
            @Override
            public Vibrator createService(ContextImpl ctx) {
                return new TestServiceManager(ctx);
            }});
.....
}

7.更新API

由于在工程中添加了自己定义的类及常量,系统的api没有更新,因此需要先在工程中make clean然后make update-api,执行完后会发现frameworks\base\api\current.xml文件中多出自己定义的一些东西。current.xml这个文件包含了所有系统所有能被应用层使用的类及其方法等。
之后再使用make编出来的固件及jar包就能包含自定义的接口。

最后:
在framework 添加自己的服务就算完了,向上为app提供接口,向下与HAL层交互。下一步准备学习一下framework与HAL层之间的桥梁JNI。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容