定制Android系统开发之三——跟着我实现系统服务

在这篇博文中,我将一步一步建立一个SystemService。

这个系统服务是用于控制收音机的,名字就叫做RadioManagerService。

新建IRadioManager.aidl;

framework/base/core/java/amdroid/os/中新建IRadioManager.aidl文件。文件的内容如下:

package android.os;

interface IRadioManager{
    void test();
}

aidl文件的语法规则可以网上查一下,这里就不做解释了。

将.adil文件名添加到Android.mk脚本中;

上面虽然新建了aidl文件,但是在编译的过程中并不会编译,只有在Android.mk中添加相关说明之后才会编译。

这个Android.mk文件的位置是:frameworks/base/Android.mk

LOCAL_SRC_FILES += \ 
    core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
    core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl \
    #…… 此处省略很多行
    com/java/android/os/IRadioManager.aidl

编写Service,实现xxx.stub;

frameworks/base/services/java/com/android/server/目录下新建RadioManagerService.java。其内容如下:

public class RadioManagerService extends IRadioManager.Stub implements IOnUartMsgListener {
    private static final String TAG = "TimothyRadioManagerService";
    private Context mContext;

    public RadioManagerService(Context context) {
        this.mContext = context;
    }

    @Override
    public void test() throws RemoteException {
        Log.d(TAG, "test() is called");
    }
}

实现Manager,调用Service;

framework/base/core/java/android/os/目录下新建RadioManager.java,内容如下:

public class RadioManager {
    private static final String TAG = "TimothyRadioManager";
    private Context mContext;
    private IRadioManager mService; // 要调用服务器的接口,首先就要保存服务器的对象。就好比只有知道了找人办事,首先得知道要找的人叫什么。

    public RadioManager(Context context, IRadioManager service) {
        mContext = context;
        mService = service;
    }
    public void test() {
        Log.d(TAG, "test() is called");
        mService.test(); // 调用客户端的test()函数,实际上调用的是服务器的test()函数。
    }
}

将自定义的服务注册到SystemServer;

framework/base/services/java/com/android/server/SystemServer.java的initAndLoop()函数里增加声明,并注册Service。

public void initAndLoop() {
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
        SystemClock.uptimeMillis());

    Looper.prepareMainLooper();

    // 此处省略很多行

    Installer installer = null;
    AccountManagerService accountManager = null;
    ContentService contentService = null;
    LightsService lights = null;
    PowerManagerService power = null;

    // 此处省略很多行

    com.android.server.RadioManagerService audioManagerService = null;

    // 此处省略很多行

    // 找个系统添加其他Service的地方加上下面这些
    try {
        Slog.i(TAG, "radio service");
        radioManagerService = new com.android.server.RadioManagerService(context);
        ServiceManager.addService(Context.RADIO_MANAGER_SERVICE, radioManagerService);
    } catch (Throwable e) {
        reportWtf("starting iflytek radio service", e);
    }
}

千万别忘了,在Context中增加RADIO_MANAGER_SERVICE这个常量的定义。

在ContextImpl.java中注册服务;

framework/base/core/java/android/app/ContextImpl.java中注册其他服务的地方加上下面的代码:

registerService(RADIO_MANAGER_SERVICE, new ServiceFetcher() {
    public Object createService(ContextImpl ctx) {
        IBinder b = ServiceManager.getService(RADIO_MANAGER_SERVICE);
        return new android.os.iflytek.RadioManager(ctx, IRadioManager.Stub.asInterface(b));
    }});

当你在使用Context.getSystemService()的时候,代码会走到这里。

结论

到这里,在Android APP中就能通过使用下面的代码调用系统服务:

RadioManager mRadioManager = (RadioManager)getSystemService(Context.RADIO_MANAGER_SERVICE);
mRadioManager.test();

因为改了framework中的代码,增加了接口,在编译的时候,需要先执行

make update-api

之后再make。

你可能感兴趣的:(android,系统服务,定制)