Android Framework系统服务详解

Android Framework系统服务详解
操作环境
系统:Linux (Ubuntu 12.04)
平台:高通
Android版本:5.1
PS: 符号...为省略N条代码

、大致原理分析
Android本身有很多系统服务,如:AlarmManagerService、PowerManagerService、AudioService等,这些服务在手机系统启动时就进行开启或监听状态,由ServiceManager负责实例化运行。系统服务与本地新增的服务属于两个不同进程,必须通过AIDL(Android Interface Definition Language :Android接口定义语言)进行跨进程通信

二、新增具体案例
2.1  创建AIDL接口文件
路径:frameworks/base/core/java/android/service/test/IMyTestManager.aidl
package android.service.test;

interface IMyTestManager {
    String sayHello();
    int priFunction();
}

2.2  将创建的AIDL加入编译中
路径:frameworks/base/Android.mk
## READ ME: ########################################################
##
## When updating this list of aidl files, consider if that aidl is
## part of the SDK API.  If it is, also add it to the list below that
## is preprocessed and distributed with the SDK.  This list should
## not contain any aidl files for parcelables, but the one below should
## if you intend for 3rd parties to be able to send those objects
## across process boundaries.
##
## READ ME: ########################################################
LOCAL_SRC_FILES += \
...
core/java/android/service/test/IMyTestManager.aidl \
...
2.2.1 注释的大概意思:
当更新这个文件列表时,如果考虑aidl是SDK API的一部分。如果它是,同时添加到下面的列表进行预处理和分布式的SDK。这个列表不包含任何aidl文件parcelables接口。但是如果你想让第三方能够在整个过程发送这些对象的话,你就应该下面有一个的目标
2.2.2 LOCAL_SRC_FILES += \ 这个宏是编译管理AIDL的,很多系统AIDL在此添加进行编译
2.2.3   frameworks/base/下用mm进行单编,把AIDL的java接口生成出来
编译完成后检查路径:
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/service/test/IMyTestManager.java

2.3 创建新的系统服务类
路径:frameworks/base/core/java/android/service/test/MyTestManagerService.java
public class MyTestManagerService extends IMyTestManager.Stub{

    private static final String TAG = "MyTestManagerService";

    private Context mContext;

    public MyTestManagerService(Context context) {
        mContext = context;
    }

    @Override
    public String sayHello() throws RemoteException {
        // TODO Auto-generated method stub
        Log.d(TAG, "sayHello()");
        return "Hello AIDL";
    }
    
    @Override
    public int priFunction() throws RemoteException {
        // TODO Auto-generated method stub
        Log.d(TAG, "priFunction()");
        return 0;
    }

}

2.4  创建系统服务公开接口管理类
路径:frameworks/base/core/java/android/service/test/MyTestManager.java
public class MyTestManager {

    private static final String TAG = "MyTestManager";

    private IMyTestManager mService;

    public MyTestManager(IMyTestManager service) {
        mService = service;
    }

    public String sayHello() throws RemoteException {
        Log.d(TAG, "sayHello()");
        return mService.sayHello();
    }
}
2.4.1 Android系统中很多系统服务API没有全部公开,都是在Frameworks层通过Manager类封装一层来进行管理公开接口。也就是说对Application层公开都是通过Manager封装来决定的,这里我只公开了sayHello()。priFunction()是我故意不公开的,方便理解

2.5   将创建的服务添加进ServiceManager
路径:frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    ...
    AudioService audioService = null;
    MyTestManagerService mTestService = null;
    ...
    if (!disableMedia && !"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
        try {
            Slog.i(TAG, "Audio Service");
            audioService = new AudioService(context);
            ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
        } catch (Throwable e) {
            reportWtf("starting Audio Service", e);
        }
    }
    ...
    try {
        Slog.i(TAG, "MyTestManager Service");
        mTestService = new MyTestManagerService(context);
        ServiceManager.addService(Context.MYTEST_SERVICE, mTestService);
    } catch (Throwable e) {
        reportWtf("starting MyTestManager", e);
    }
    ...
}
2.5.1   为了阅读思路清晰,我保留了AudioService的服务添加代码。至于if条件,我们也可以添加,java里面控制的话可以在config.xml中定义bool类型,一般是为了区分多个项目的差异。涉及到项目的overlay,可根据操作项目的具体需求来进行。驱动底层一般都是宏控,稍微提一下。
2.5.2 代码中的Context.MYTEST_SERVICE服务常量添加
路径:frameworks/base/core/java/android/content/Context.java
...
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.media.AudioManager} for handling management of volume,
* ringer modes and audio routing.
*
* @see #getSystemService
* @see android.media.AudioManager
*/
public static final String AUDIO_SERVICE = "audio";

public static final String MYTEST_SERVICE = "mytest";
...

2.6   注册服务
路径:frameworks/base/core/java/android/app/ContextImpl.java
static {
    ...
    registerService(AUDIO_SERVICE, new ServiceFetcher() {
        public Object createService(ContextImpl ctx) {
            return new AudioManager(ctx);
        }
    });
    
    registerService(MYTEST_SERVICE, new ServiceFetcher() {
        public Object createService(ContextImpl ctx) {
            IBinder iBinder = ServiceManager.getService(Context.MYTEST_SERVICE);
                if (iBinder == null) {
                    return null;
                }
                IMyTestManager service = IMyTestManager.Stub
                    .asInterface(iBinder);
                return new MyTestManager(service);
            }
    });
    ...
}
2.6.1   在这里可以看到明显的对比,有一个差异就是AudioManager在注册服务的时候并没有像我添加的一样将服务传给IBinder,再通过IBinder来进行接口对接获取到服务。其实,AudioManger已经在内部类做了这层封装,原理是一样的,也有很多系统服务采用我这种方式进行注册。附AudioManager部分源码:
路径:frameworks/base/media/java/android/media/AudioManager.java
public class AudioManager {
    ...
    private static IAudioService sService;

    /**
     * @hide
     */
    public AudioManager(Context context) {
        mContext = context;
        ...
    }

    private static IAudioService getService()
    {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        sService = IAudioService.Stub.asInterface(b);
        return sService;
    }
    ...
}

2.7   调用新增的系统服务
MyTestManager mTestManager = (MyTestManager) getSystemService(Context.MYTEST_SERVICE);
try {
    //这里调用不出priFunction(),MyTestManager没有对它进行再次封装
    mTestManager.sayHello();
} catch (RemoteException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值