Android个层次调用流程概述

转自:http://blog.chinaunix.net/uid-25150360-id-3180053.html
Android的硬件抽象层:

    简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节。

    也就是说,把对硬件的支持分成了两层,

           一层放在用户空间(User Space),(硬件抽象层)

           一层放在内核空间(Kernel Space),(Linux内核驱动程序)

下面这个图阐述了硬件抽象层在Android系统中的位置,以及它和其它层的关系:

二,简单的总结

进入到Android源代码工程的external目录,创建hello目录:

cd external

mkdir hello

在hello目录中新建Android.mk文件:

  LOCAL_PATH := $(call my-dir)

  include $(CLEAR_VARS)

  LOCAL_MODULE_TAGS := optional

  LOCAL_MODULE := hello

  LOCAL_SRC_FILES := $(call all-subdir-c-files)

  include $(BUILD_EXECUTABLE)

注意,BUILD_EXECUTABLE表示我们要编译的是可执行程序。

使用mmm命令进行编译:

  mmm ./external/hello

  编译成功后,就可以在out/target/product/gerneric/system/bin目录下,看到可执行文件hello了。

重新打包Android系统文件system.img:

  make snod

  这样,重新打包后的system.img文件就包含刚才编译好的hello可执行文件了。



  七. 运行模拟器,使用/system/bin/hello可执行程序来访问Linux内核驱动程序。

  emulator -kernel ./kernel/common/arch/arm/boot/zImage &

  adb shell

       cd system/bin

      ./hello

三,编写硬件抽象层

   进入到在hardware/libhardware/include/hardware目录,新建hello.h文件:



  cd hardware/libhardware/include/hardware

  vi hello.h

  hello.h文件的内容如下:

ifndef ANDROID_HELLO_INTERFACE_H

define ANDROID_HELLO_INTERFACE_H

include

__BEGIN_DECLS

/定义模块ID/

define HELLO_HARDWARE_MODULE_ID “hello”

/硬件模块结构体/

struct hello_module_t {

  struct   hw_module_t   common;

};

/硬件接口结构体/

struct hello_device_t {

  struct hw_device_t   common;

  int fd;         // 设备文件描述符

  int (*set_val)(struct hello_device_t* dev, int val);        // 为该HAL对上提供的函数接口

  int (*get_val)(struct hello_device_t* dev, int* val);

};

__END_DECLS

endif

进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件。 hello.c的内容较多,我们分段来看。

  首先是包含相关头文件和定义相关结构:

define LOG_TAG “HelloStub”

include

include

include

include

include

include

define DEVICE_NAME “/dev/hello”

define MODULE_NAME “Hello”

define MODULE_AUTHOR “shyluo@gmail.com”

/设备打开和关闭接口/

static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);

static int hello_device_close(struct hw_device_t* device);

/设备访问接口/

static int hello_set_val(struct hello_device_t* dev, int val);

static int hello_get_val(struct hello_device_t* dev, int* val);

/模块方法表/

static struct hw_module_methods_t hello_module_methods = {

open: hello_device_open  

};

/模块实例变量/

struct hello_module_t HAL_MODULE_INFO_SYM = {

common: {  

    tag: HARDWARE_MODULE_TAG,  

    version_major: 1,  

    version_minor: 0,  

    id: HELLO_HARDWARE_MODULE_ID,  

    name: MODULE_NAME,  

    author: MODULE_AUTHOR,  

    methods: &hello_module_methods,  

}  

};

include “jni.h”

include “JNIHelp.h”

include “android_runtime/AndroidRuntime.h”

include

include

include

include

include

/* 接着定义hello_init、hello_getVal和hello_setVal三个JNI方法:*/

namespace android

{

/*在硬件抽象层中定义的硬件访问结构体,参考*/ 

    struct hello_device_t*  hello_device = NULL;  

/*通过硬件抽象层定义的硬件访问接口设置硬件寄存器val的值*/  

    static void hello_setVal (JNIEnv* env,   jobject clazz,   jint value) {  

    int val = value;  

    LOGI("Hello JNI: set value %d to device.", val);  

    if(!hello_device) {  

        LOGI("Hello JNI: device is not open.");  

        return;  

    }  

    hello_device->set_val(hello_device, val);          // 在抽象层的open中定义

}  

   /*通过硬件抽象层定义的硬件访问接口读取硬件寄存器val的值*/  

static jint hello_getVal(JNIEnv* env,   jobject clazz) {   

    int val = 0;  

    if(!hello_device) {  

        LOGI("Hello JNI: device is not open.");  

        return val;  

    }  

    hello_device->get_val(hello_device, &val);  

    LOGI("Hello JNI: get value %d from device.", val);  

    return val;  

}  


   /*通过硬件抽象层定义的硬件模块打开接口  打开硬件设备*/  

static inline int  hello_device_open (const hw_module_t* module, struct hello_device_t** device) {  

    return  module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);  

}  


    /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/  

static jboolean  hello_init (JNIEnv* env, jclass clazz) {  

    hello_module_t* module;  



    LOGI("Hello JNI: initializing......");  

        /* 加载模块ID为HELLO_HARDWARE_MODULE_ID的硬件抽象层模块,  Android硬件抽象层会根据HELLO_HARDWARE_MODULE_ID的值

         * 在Android系统的/system/lib/hw目录中找到相应的模块,然后加载起来,并且返回hw_module_t接口给调用者使用。

         */

    if ( hw_get_module ( HELLO_HARDWARE_MODULE_ID,   (const struct hw_module_t**)&module ) == 0 )  {  

        LOGI("Hello JNI: hello Stub found.");  

        if(hello_device_open(&(module->common), &hello_device) == 0) {  

            LOGI("Hello JNI: hello device is open.");  

            return 0;  

        }  

        LOGE("Hello JNI: failed to open hello device.");  

        return -1;  

   }  

    LOGE("Hello JNI: failed to get hello stub module.");  

    return -1;        

}

   /*JNI方法表*/  

static const   JNINativeMethod   method_table[ ] = {  

    {"init_native",           "()Z",          (void*)hello_init},  

    {"setVal_native",     "(I)V",         (void*)hello_setVal},  

    {"getVal_native",      "()I",          (void*)hello_getVal},  

};  

    /*注册JNI方法*/  

int  register_android_server_HelloService(JNIEnv *env) {  

        return  jniRegisterNativeMethods(env,   "com/android/server/HelloService",   method_table,   NELEM(method_table) );  

                                                                             // 必须对应HelloService所在的包的路径

}  

};

在Android系统初始化时,使其自动加载该JNI方法调用表


  修改同目录下的onload.cpp文件,

  (1)在namespace android增加 register_android_server_HelloService函数声明:



  namespace android {

  ..............................................................................................

  int  register_android_server_HelloService(JNIEnv *env);

  };



  (2)在JNI_onLoad 增加 register_android_server_HelloService函数调用:

  extern "C" jint JNI_onLoad(JavaVM* vm, void* reserved)

  {

   .................................................................................................

   register_android_server_HelloService(env);

   .................................................................................................

  }



  (3)修改同目录下的Android.mk文件,在 LOCAL_SRC_FILES变量 中增加一行:

 LOCAL_SRC_FILES:= \

  com_android_server_AlarmManagerService.cpp \

  com_android_server_BatteryService.cpp \

  com_android_server_InputManager.cpp \

  com_android_server_LightsService.cpp \

  com_android_server_PowerManagerService.cpp \

  com_android_server_SystemServer.cpp \

  com_android_server_UsbService.cpp \

  com_android_server_VibratorService.cpp \

  com_android_server_location_GpsLocationProvider.cpp \

  com_android_server_HelloService.cpp /

  onload.cpp


   最后编译

  mmm frameworks/base/services/jni

  make snod

  这样,重新打包的system.img镜像文件就包含我们刚才编写的JNI方法了,

  我们可以通过Android系统的Application Frameworks层提供的硬件服务HelloService来调用这些JNI方法,进而调用低层的硬件抽象层接口去访问硬件了。

五:提供Java访问硬件服务接口

     Linux内核层、硬件抽象层和运行时库层提供的自定义硬件服务接口,这些接口都是通过C或者C++语言来实现的。

     以下,我们将介绍如何在Android系统的Application Frameworks层提供Java接口的硬件服务。

(为什么用代理?)

    在Android系统中,硬件服务一般是运行在一个独立的进程中为各种应用程序提供服务。因此,调用这些硬件服务的应用程序与这些硬件服务之间的通信需要通过代理来进行。为此,我们要先定义好通信接口。

(1)进入到frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件:

  cd   frameworks/base/core/java/android/os

  vi    IHelloService.aidl

IHelloService.aidl定义了IHelloService接口:

  package android.os;  

  interface  IHelloService{  

      void setVal (int val);  

      int    getVal ( );  

  }  

该接口主要提供了设备获取硬件寄存器val的值的功能,分别通过setVal和getVal两个函数来实现。

(2)返回到frameworks/base目录,打开Android.mk文件,修改LOCAL_SRC_FILES变量的值,增加IHelloService.aidl源文件:

core/java/android/os/IHelloService.aidl /

(3)编译IHelloService.aidl接口:

mmm frameworks/base

这样,就会根据IHelloService.aidl生成相应的IHelloService.Stub接口。

(4)进入到frameworks/base/services/java/com/android/server目录,新增HelloService.java文件:

package com.android.server;

import android.content.Context;

import android.os.IHelloService;

import android.util.Slog;

public class HelloService extends IHelloService . Stub {

private static final String TAG = "HelloService";  

HelloService() {  

    init_native();  

}  

public void  setVal(int val) {  

    setVal_native(val);  

}     

public int  getVal() {  

    return getVal_native();  

}  


 /* HelloService主要是通过调用JNI方法init_native、setVal_native和getVal_native来提供硬件服务 */

private static native boolean   init_native();  

private static native void         setVal_native(int val);  

private static native int            getVal_native();  

};

(5) 修改同目录的SystemServer.java文件,在ServerThread::run函数中增加加载HelloService的代码:

 @Override

 public void run() {

 ....................................................................................

        try {

              Slog.i(TAG, "Hello Service");

              ServiceManager. addService("hello", new HelloService());

        } catch (Throwable e) {

              Slog.e(TAG, "Failure starting Hello Service", e);

        }

 ......................................................................................

 }      

(6)编译HelloService和重新打包system.img:

 mmm frameworks/base/services/java

 make snod



 这样,重新打包后的system.img系统镜像文件就在Application Frameworks层中包含了我们自定义的硬件服务HelloService了,并且会在系统启动的时候,自动加载HelloService。

 这时,应用程序就可以通过Java接口来访问Hello硬件服务了。

六:Java调用实例

public class Hello extends Activityimplements OnClickListener {

private final static String LOG_TAG =”shy.luo.renju.Hello”;

private IHelloService helloService = null;

private EditText valueText = null;

private Button readButton = null;

private Button writeButton = null;

private Button clearButton = null;

/* Called when the activity is first created. /

@Override

public void onCreate(Bundle savedInstanceState) {

   super.onCreate(savedInstanceState); 

   setContentView(R.layout.main);  


             // IHelloService接口定义在android.os.IHelloService中,

helloService= IHelloService.Stub.asInterface( // 转换为IHelloService接口

   ServiceManager.getService("hello"));  // 获得HelloService

                           // 服务名字“hello”是系统启动时加载HelloService时指定


   valueText = (EditText)findViewById(R.id.edit_value);  

   readButton = (Button)findViewById(R.id.button_read);  

   writeButton = (Button)findViewById(R.id.button_write);  

   clearButton = (Button)findViewById(R.id.button_clear);  

readButton.setOnClickListener(this);

writeButton.setOnClickListener(this);

clearButton.setOnClickListener(this);

   Log.i(LOG_TAG, "Hello Activity Created");  

}

@Override

public void onClick(View v) {

   if(v.equals(readButton)) {  

   try {  

            int val =helloService.getVal();  

            String text = String.valueOf(val);  

            valueText.setText(text);  

   } catch (RemoteException e) {  

        Log.e(LOG_TAG, "RemoteException while reading value from device.");  

   }         

   }  

   else if(v.equals(writeButton)) {  

   try {  

            String text =valueText.getText().toString();  

            int val =Integer.parseInt(text);  

       helloService.setVal(val);  

   } catch (RemoteException e) {  

        Log.e(LOG_TAG, "RemoteException while writing value to device.");  

   }  

   }  

   else if(v.equals(clearButton)) {  

        String text = "";  

        valueText.setText(text);  

   }  

}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值