一、为什么需要Framwork?
Framework实际上是⼀个应⽤程序的框架,提供了很多服务:
1、丰富⽽⼜可扩展的视图(Views),
可以⽤来构建应⽤程序,它包括列表(lists),⽹格(grids),⽂本框(text boxes),按钮(buttons),甚⾄可嵌⼊的web浏览器。
2、内容提供器(Content Providers)
使得应⽤程序可以访问另⼀个应⽤程序的数据(如联系⼈数据库),或者共享它们⾃⼰的数据
3、资源管理器(Resource Manager)
提供⾮代码资源的访问,如本地字符串,图形,和布局⽂件(layout files)。
4、通知管理器(Notification Manager)
使得应⽤程序可以在状态栏中显⽰⾃定义的提⽰信息。
5、活动管理器(Activity Manager)
⽤来管理应⽤程序⽣命周期并提供常⽤的导航回退功能。
二、应用层访问硬件,如何自定义系统Service?
1、应用层如何访问硬件
(1)Linux
对于Linux来说的话,就比较简单,应用层的APP直接通过open一类的接口直接访问我们底层的驱动文件
(2)Android
对于Android来说的话,它就会有多种方式去访问,
1) APP ----- JNI ----- Kernel:
这种就很直接明了,上层app访问JNI,再去访问kernel
2)APP ----- Service ----- JNI ----- Kernel:
当我们要往系统里添加一个硬件的话,我们更希望把它封装为一个系统的服务,就可以以这种方式去访问到底层
3)APP ----- Service ----- JNI ----- HAL ----- Kernel:
一些驱动厂商的一个源码呢他是不希望开放给我们的一个开发者是吧,但是他们又依赖着Android的开源框架,所以就有一种比较好的方法,既不需要公开源码,又可以实现同样的功能。就是把它封装成库,这样可以让厂家去提供一个现成的库,然后我们直接去使用,他就不用开放这一层的源码,这就是HAL层的存在意义。
为什么需要JNI?
应⽤使⽤java编写,驱动⼀般使⽤c/cpp编写,提供⼀种Java访问c/cpp的⽅法。也就是Java代码可通过JNI接⼝调⽤C/C++⽅法。
JNI开发流程的步骤:
1)编写JNI⽅法表并注册
2)实现JNI的.c⽂件
2、自定义系统Service
Framework还有一个很重要的功能,就是系统server。所有的硬件呢都是通过我们的系统server去进行管理,那我们怎样为我们的硬件接口去添加一个自定义的系统serve呢?
(1)建立aidl通信接口;
(2)在system_server中注册service到servicemanager;
(3)实现service,对应aidl中的接口函数。
(4)client向servicemanager请求service,成功后,调用aidl接口函数,建立client进程和service进程的通信关系。
总结来说就是:
1)system_server完成注册功能;
2)servicemanager完成服务管理功能;
3)aidl完成通讯功能;
(1)建立aidl通信接口
在frameworks/base/core/java/android/os/路径下新建对应名称的一个aidl文件
下面我们以顾凯歌的一个蓝牙模块的服务为大家举例:
路径:frameworks/base/core/java/android/os/IGocsdkService.aidl:
(因为他是Interface的一个接口,所有在前面加个 "I")
+ package android.os;
+ interface IEmbededService {
+ interface IFmService {
+
+ //蓝牙状态回调注册去注销
+ void registerCallback(IGocsdkCallback callback);
+ // 注销蓝牙状态
+ void unregisterCallback(IGocsdkCallback callback);
+
+ //注释后面带的为操作后相应的回调回复
+ //蓝牙协议软复位 ---》 onInitSucceed()
+ void restBluetooth();
+
+ //获取本地蓝牙名称 ---》onCurrentDeviceName()
+ void getLocalName();
+
+ //设置本地蓝牙名称 ---》onCurrentDeviceName()
+ void setLocalName(String name);
+ ..................//等等一些,都为接口函数,会在下面实现
}
编译到系统
路径:frameworks/base/Android.mk
diff --git a/android/frameworks/base/Android.bp b/android/frameworks/base/Android.bp
old mode 100644
new mode 100755
index d8a7f06..953759c
--- a/android/frameworks/base/Android.bp
+++ b/android/frameworks/base/Android.bp
@@ -265,6 +265,11 @@ java_defaults {
"core/java/android/os/IRecoverySystemProgressListener.aidl",
"core/java/android/os/IRemoteCallback.aidl",
"core/java/android/os/ISchedulingPolicyService.aidl",
+ "core/java/android/os/IGocsdkService.aidl",
":statsd_aidl",
"core/java/android/os/ISystemUpdateManager.aidl",
"core/java/android/os/IThermalEventListener.aidl",
(2)在system_server中注册EmbededServicer到servicemanager
路径:frameworks/base/services/java/com/android/server/SystemServer.java
使用ServiceManager.addService添加我们自定义的server
@@ -1097,6 +1097,13 @@ public final class SystemServer {
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ try {
+ Slog.i(TAG, "IGocsdkService");
+ ServiceManager.addService("gocsdkService ", new GocsdkService());
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failure starting Gocsdk Service", e);
+ }
(3)实现EmbededService,对应aidl中的接⼝函数
路径:frameworks/base/services/java/com/android/server/EmbededService.java
package com.android.server;
import android.content.Context;
import android.os.IGocsdkService;
import android.util.Slog;
public class GocsdkService extends IGocsdkService.Stub {
private static final String TAG = "GocsdkService";
GocsdkService(){
Slog.i(TAG,"GocsdkService init");
}
public void registerCallback(IGocsdkCallback callback){
return xxx;
}
public void unregisterCallback(IGocsdkCallback callback){
return xxx;
}
public void getLocalName(){
return xxx;
}
.......................
}
(4)在app中使⽤IEmbededService的大致流程如下
很好理解吧,把我们对应的一个服务导入,然后去初始化一个类,然后通过ServiceManager去找到我们自定义的这个server,然后使用自定义服务的函数获取数据。
import android.os.IGocsdkService; //导入
private IGocsdkService mGocsdkService = null; //初始化类
mGocsdkService = IGocsdkService .Stub.asInterface(
ServiceManager.getService("gocsdkService"));
int version= mEmbededService.getLocalName();
String text = String.value(localName);
(5)编译service,烧录
直接全sdk编译,防止有遗漏
(6)验证
使⽤service list查看是否有EmbededService
xxx:/ $ service list | grep gocsdkService
gocsdkService: [android.os.IGocsdkService]
三、为什么需要Android HAL?
Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件⼚商为了保护⾃⼰硬件⽅⾯的各项参数不被外泄,⽽⼀个设备的驱动程序包含了硬件的⼀些重要参数,所以驱动的开源势必会使硬件⼚商蒙受损失,Google为了保护硬件⼚商的利益,所以在Android系统中加⼊了HAL层,在HAL层中不必遵循GPL协议,所以代码可以封闭。
所以如果硬件驱动开源的写在Kernel⾥,Framework直接调⽤,⽽不愿意开源的就写在HAL层⾥,实现闭源。也就是说,编写驱动分为两个部分,⼀个是HAL层的驱动代码,⼀个是Kernel层的驱动代码。
1、内核实现HAL驱动的⽅法有两种:
(1)采⽤直接调⽤so动态链接库⽅式
采⽤共享库形式,在编译时会调⽤到。由于采⽤function call形式调⽤,因此可被多个进程使⽤,但会被mapping到多个进程空间中,造成浪费,同时需要考虑代码能否安全重⼊的问题。
(2)采⽤Stub代理⽅式调⽤
采⽤HAL module和HAL stub结合形式,HAL stub不是⼀个share library,编译时
上层只拥有访问HAL stub的函数指针,并不需要HAL stub。上层通过HAL module提供的统⼀接⼝获取并操作HAL stub,so⽂件只会被mapping到⼀个进程,也不存在重复mapping和重⼊问题。
2、如何编写HAL层驱动
我们现在一般都是采用第二种方式,基于HAL框架提供了三个结构体,分别为hw_device_t、hw_module_t、hw_module_methods_t,编写HAL层驱动则是依据这三个结构体作扩展,我们创建⾃⼰驱动的device_t,module_t代码,并且写hw_module_methods_t这个结构体中⽅法的实现代码,最后JNI层通过hw_get_module调⽤。
(1)在 android/hardware/libhardware/modules/xxx 路径下创建我们的HAL文件夹,例如LED:
mkdirhardware/libhardware/modules/led
path:hardware/libhardware/include/hardware/led_hal.h
path:hardware/libhardware/modules/embeded/led_hal.c
(1)led_hal.c:
#define LOG_TAG "dLed"
#include <hardware/hardware.h>
#include <hardware/led_hal.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#define DEVICE_NAME "sys/led/embeded_blue_led"
#define MODULE_NAME "EmLed"
/*设备打开和关闭接⼝*/
static int embededled_device_open(const struct hw_module_t* module, const
char* name, struct hw_device_t** device);
static int embededled_device_close(struct hw_device_t* device);
/*设备访问接⼝*/
static int embededled_set_val(struct embededled_device_t* dev, int val);
static int embededled_get_val(struct embededled_device_t* dev, int* val);
static int embededled_device_open(const struct hw_module_t* module, const
char* name, struct hw_device_t** device) {
struct embededled_device_t* dev;dev = (struct
embededled_device_t*)malloc(sizeof(struct embededled_device_t));
if(!dev) {
ALOGI("embededled Stub: failed to alloc space");
return -EFAULT;
}
memset(dev, 0, sizeof(struct embededled_device_t));
//初始化设备相关信息,实现访问接⼝函数
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = embededled_device_close;
dev->set_val = embededled_set_val;
dev->get_val = embededled_get_val;
if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
ALOGI("embededled Stub: failed to open
sys/embededled/embeded_blue_led -- %s.", strerror(errno));free(dev);
return -EFAULT;
}
int status = 0;
write(dev->fd, &status, sizeof(status));
*device = &(dev->common);
ALOGI("embededled Stub: open sys/embededled/embeded_blue_led
successfully.");
return 0;
}
static int embededled_device_close(struct hw_device_t* device) {
struct embededled_device_t* embededled_device = (struct
embededled_device_t*)device;
if(embededled_device) {
close(embededled_device->fd);
free(embededled_device);
}
return 0;
}
static int embededled_set_val(struct embededled_device_t* dev, int val) {
ALOGI("embededled Stub: set value %d to device.", val);
write(dev->fd, &val, sizeof(val));
return 0;
}
static int embededled_get_val(struct embededled_device_t* dev, int* val) {
if(!val) {
ALOGI("embededled Stub: error val pointer");
return -EFAULT;
}
read(dev->fd, val, sizeof(*val));
ALOGI("embededled Stub: get value %d from device", *val);
return 0;
}
/*模块⽅法表*/
static struct hw_module_methods_t embededled_module_methods = {
open: embededled_device_open
};
/*模块实例变量*/
struct embededled_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: EMBEDEDLED_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &embededled_module_methods,
}
};
led_hal.h:
path:hardware/libhardware/include/hardware/led_hal.h
#ifndef ANDROID_LED_INTERFACE_H
#define ANDROID_LED_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
/*定义模块ID*/
#define EMBEDEDLED_HARDWARE_MODULE_ID "led_hal"
/*硬件模块结构体*/
struct led_module_t {
struct hw_module_t common;
};
/*硬件接⼝结构体*/
struct embededled_device_t {
struct hw_device_t common;
int fd;
int (*set_val)(struct led_device_t* dev, int val);
int (*get_val)(struct led_device_t* dev, int* val);
};
__END_DECLS
#endif
四、JNI层添加
JNI开发流程的步骤:
里面呢就是我们要实现的三个函数,然后再把对应的方法注册到我们的server里面去
1 diff --git a/frameworks/base/services/core/jni/Android.mk
b/frameworks/base/services/core/jni/Android.mk
2 index 0f0124bd46..305773298a 100644
3 --- a/frameworks/base/services/core/jni/Android.mk
4 +++ b/frameworks/base/services/core/jni/Android.mk
5 @@ -36,6 +36,7 @@ LOCAL_SRC_FILES += \
6 $(LOCAL_REL_DIR)/com_android_server_UsbHostManager.cpp \
7 $(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
8 $(LOCAL_REL_DIR)/com_android_server_PersistentDataBlockService.cpp \
9 + $(LOCAL_REL_DIR)/com_android_server_EmbededLedService.cpp \
10 $(LOCAL_REL_DIR)/onload.cpp
11
12 LOCAL_SRC_FILES += \
1 diff --git a/frameworks/base/services/core/jni/onload.cpp
b/frameworks/base/services/core/jni/onload.cpp
2 index d5861f8c41..b52f7917fd 100644
3 --- a/frameworks/base/services/core/jni/onload.cpp
4 +++ b/frameworks/base/services/core/jni/onload.cpp
5 @@ -47,6 +47,7 @@ int
register_android_server_PersistentDataBlockService(JNIEnv* env);
6 int register_android_server_Watchdog(JNIEnv* env);
7 int register_android_server_HardwarePropertiesManagerService(JNIEnv* env);
8 int register_com_android_server_rkdisplay_RkDisplayModes(JNIEnv* env);
9 +int register_android_server_EmbededLedService(JNIEnv* env);
10 };
11
12 using namespace android;
13 @@ -89,7 +90,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
14 register_android_server_Watchdog(env);
15 register_android_server_HardwarePropertiesManagerService(env);
16 register_com_android_server_rkdisplay_RkDisplayModes(env);
17 -
18 -
19 + register_android_server_EmbededLedService(env);
20 return JNI_VERSION_1_4;
21 }
1、AIDL:
1 package android.os;
2
3 interface IEmbededLedService {
4 void setVal(int val);
5 int getVal();
6 }
1 diff --git a/frameworks/base/Android.mk b/frameworks/base/Android.mk
2 index b9692de0e1..c426a3cd99 100755
3 --- a/frameworks/base/Android.mk
4 +++ b/frameworks/base/Android.mk
5 @@ -240,6 +240,7 @@ LOCAL_SRC_FILES += \
6 core/java/android/os/IUpdateLock.aidl \
7 core/java/android/os/IUserManager.aidl \
8 core/java/android/os/IVibratorService.aidl \
9 + core/java/android/os/IEmbededLedService.aidl \
10 core/java/android/os/IDisplayDeviceManagementService.aidl \
11 core/java/android/os/IRkDisplayDeviceManagementService.aidl \
12 core/java/android/security/IKeystoreService.aidl \
2、Service
1 package com.android.server;
2 import android.content.Context;
3 import android.os.IEmbededLedService;
4 import android.util.Slog;
5 public class EmbededLedService extends IEmbededLedService.Stub {
6 private static final String TAG = "EmbededLedService";
7 EmbededLedService() {
8
9 boolean status = init_native();
10 Slog.i(TAG,"EmbededLedService Stub init"+status);
11 }
12 public void setVal(int val) {
13 setVal_native(val);
14 }
15 public int getVal() {
16 return getVal_native();
17 }
18
19 //JNI⽅法
20 private static native boolean init_native();
21 private static native void setVal_native(int val);
22 private static native int getVal_native();
23 };
3、添加Service到System启动
1 diff --git
a/frameworks/base/services/java/com/android/server/SystemServer.java
b/frameworks/base/services/java/com/android/server/SystemServer.java
2 index cc6f1850e6..b22ecda734 100644
3 --- a/frameworks/base/services/java/com/android/server/SystemServer.java
4 +++ b/frameworks/base/services/java/com/android/server/SystemServer.java
5 @@ -1086,6 +1086,15 @@ public final class SystemServer {
6 } catch (Throwable e) {
7 reportWtf("starting DiskStats Service", e);
8 }
9 +
10 + try {
11 + Slog.i(TAG, "Embededled Service");
12 + ServiceManager.addService("embededled", new
EmbededLedService());
13 + } catch (Throwable e) {
14 + Slog.e(TAG, "Failure starting Embededled Service", e);
15 + }
16 +
17 +
18 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
19
20 if (!disableSamplingProfiler) {