《Android 系统开发做什么?》写到 Android System Services 是专注于特定功能的模块化组件,应用框架 API 所提供的功能可与系统服务通信,以访问底层硬件。Android System Services 是如何写的?来以 DisplayManagerService 为例,具体来看看。
System Service 是如何写的?
应用调用
|
|
看下 getSystemService 方法,在 Context 类里。
Context#getSystemService
|
|
ContextImpl#getSystemService
|
|
继续跟 SystemServiceRegistry.getSystemServiceName。
SystemServiceRegistry#getSystemServiceName
|
|
什么时候 registerService 的?
|
|
结合上面的分析代码可以知道 getSystemService(DisplayManager.class)得到的是一个 DisplayManager 的实例。
接下来看 dm.setTemporaryBrightness 方法。
DisplayManager#setTemporaryBrightness
|
|
mGlobal 是 DisplayManagerGlobal 对象。
DisplayManagerGlobal#setTemporaryBrightness
|
|
mDm 是 IDisplayManager 对象,初始化在IDisplayManager.Stub.asInterface(ServiceManager.getService(Context.DISPLAY_SERVICE))
,看到 IDisplayManager 是一个 aidl 文件:frameworks/base/core/java/android/hardware/display/IDisplayManager.aidl,AIDL (Android Interface Definition Language) 是 Android 中的接口定义文件,为系统提供了一种简单跨进程通信方法,先不管 AIDL。
IDisplayManager
IDisplayManager 定义了包括 setTemporaryBrightness 的几个接口。
|
|
IDisplayManager 只是接口,需要找下哪里实现了它,搜索是在 BinderService,BinderService 是 DisplayManagerService 内部类。
|
|
mDisplayPowerController.setTemporaryBrightness(brightness)
后面经过一系列调用会到 LightsService#setLight_native,通过 JNI 调用到 native 层,调用底层进行背光调节,关于背光调节后面文章再细讲。
SystemServer
DisplayManagerService 是继承了 SystemService,DisplayManagerService 是怎么注册为系统服务的呢?在 SystemServer 里面:
|
|
看完 DisplayManagerService 是怎么写的,不妨模仿写个。
所谓看着代码,感觉还是挺简单的,实际操作起来,各种编译报错……
如何写个 System Service
先上图:
|
|
1.编写 AIDL 文件
新建 frameworks/base/core/java/android/hardware/wuxiaolong/IWuXiaolongManager.aidl,内容如下:
|
|
2.Context 定义变量
在 Context 里定义一个代表 wuxiaolong 服务的字符串
frameworks/base/core/java/android/content/Context.java
|
|
3.编写系统服务
frameworks/base/services/core/java/com/android/server/wuxiaolong/WuXiaolongManagerService.java
|
|
4.注册系统服务
frameworks/base/services/java/com/android/server/SystemServer.java
|
|
5.编写 Manager 类
frameworks/base/core/java/android/hardware/wuxiaolong/WuXiaolongManager.java
|
|
6.注册 Manager
frameworks/base/core/java/android/app/SystemServiceRegistry.java
|
|
7.应用调用
|
|
8.解决报错
编译报错
- 报错 1:
|
|
需要执行 make update-api,更新接口,会多出来:
frameworks/base/api/current.txt
|
|
frameworks/base/non-updatable-api/current.txt
|
|
- 报错 2:
|
|
编写 Manager 类需写成单例。
- 报错 3:
|
|
getName 方法加上@Nullable
注解。
运行报错
|
|
这里是缺少 SELinux 权限,可执行:
|
|
临时禁用掉 SELinux,功能就正常了,关于 SELinux 这里不说了,后面有机会写篇 SELinux 文章。
最后 Log 打印如下:
|
|
手写个 System Service 实践过后没那么简单,光 SELinux 权限够折腾半天了,这篇文章先就酱紫吧。