透过HAL(硬件抽象层)看顶层API是如何访问硬件

透过HAL(硬件抽象层)看顶层API是如何访问硬件

(2011-01-10 11:17:21)
标签:

杂谈

 

透过HAL(硬件抽象层)看顶层API是如何访问硬件

        文章导读:HAL硬件抽象层的实现及架构、Android API 与硬件平台的衔接、NDK的一些看法。

 

简介:Hardware Abstraction Layer 硬件抽象层是一个轻量级(lightweight)的的运行环境,提供了简单的设备驱动程序接口,应用程序使用设备驱动程序与底层硬件之间进行通信。HAL应用程序接口和ANSIC标准库结合在一起,这样用户可以使用C语言库函数来访问Android文件系统。下图是其直观的概念:

 

 

从图中,我们可以看到HAL是基于Linux KernelLibrariesAndroid Runtime之间。也就是说,HAL是底层硬件设备驱动程序暴露给Application Framework (也就是通常我们使用的Android API )的一个接口层。(可以浏览http://hi.baidu.com/aokikyon/blog/item/a66e0f87d8f55326c75cc32b.html HAL分析报告获得更详细的认识)

 

在网上也看到一些朋友写了重力感应器的api使用,那么以重力感应器Sensor为例子,看看重力感应器如何和Applications、Application Framework衔接。

1、下面Sensors.h的定义重力感应器对驱动程序部分的操作:

在源码./platform/hardware/Libardware /Include/Sensors.h目录下

 

C代码
  1. #include <...>  
#include <...>
C代码
  1. __BEGIN_DECLS  
  2.   
  3.   
  4. #define SENSORS_HARDWARE_MODULE_ID "sensors"  
  5.   
  6.   
  7. #define SENSORS_HARDWARE_CONTROL    "control"  
  8. #define SENSORS_HARDWARE_DATA       "data"  
  9.   
  10. .....  
  11.   
  12.   
  13.   
  14. static inline int sensors_control_open(const struct hw_module_t* module,   
  15.         struct sensors_control_device_t** device) {  
  16.     return module->methods->open(module,   
  17.             SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device);  
  18. }  
  19.   
  20. static inline int sensors_control_close(struct sensors_control_device_t* device) {  
  21.     return device->common.close(&device->common);  
  22. }  
  23.   
  24. static inline int sensors_data_open(const struct hw_module_t* module,   
  25.         struct sensors_data_device_t** device) {  
  26.     return module->methods->open(module,   
  27.             SENSORS_HARDWARE_DATA, (struct hw_device_t**)device);  
  28. }  
  29.   
  30. static inline int sensors_data_close(struct sensors_data_device_t* device) {  
  31.     return device->common.close(&device->common);  
  32. }  
  33.   
  34.   
  35. __END_DECLS  
  36.   
  37. #endif  // ANDROID_SENSORS_INTERFACE_H  
__BEGIN_DECLS #define SENSORS_HARDWARE_MODULE_ID "sensors" #define SENSORS_HARDWARE_CONTROL "control" #define SENSORS_HARDWARE_DATA "data" ..... static inline int sensors_control_open(const struct hw_module_t* module, struct sensors_control_device_t** device) { return module->methods->open(module, SENSORS_HARDWARE_CONTROL, (struct hw_device_t**)device); } static inline int sensors_control_close(struct sensors_control_device_t* device) { return device->common.close(&device->common); } static inline int sensors_data_open(const struct hw_module_t* module, struct sensors_data_device_t** device) { return module->methods->open(module, SENSORS_HARDWARE_DATA, (struct hw_device_t**)device); } static inline int sensors_data_close(struct sensors_data_device_t* device) { return device->common.close(&device->common); } __END_DECLS #endif // ANDROID_SENSORS_INTERFACE_H
  

 

 2、JNI部分代码

 

    加载该驱动的访问程序./framework/Jni/onLoad.cpp

 

Cpp代码
  1. #include "jni.h"  
  2. #include "utils/Log.h"  
  3. #include "utils/misc.h"  
  4. #include "JNIHelp.h"  
  5. namespace android {  
  6. ...  
  7. int register_android_server_SensorService(JNIEnv* env);  
  8. ...  
  9. };  
  10.   
  11. using namespace android;  
  12.   
  13. extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)  
  14. {  
  15.     JNIEnv* env = NULL;  
  16.     jint result = -1;  
  17.   
  18.     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  19.         LOGE("GetEnv failed!");  
  20.         return result;  
  21.     }  
  22.     LOG_ASSERT(env, "Could not retrieve the env!");  
  23.   
  24.     //注册SensorService  
  25.     register_android_server_SensorService(env);  
  26.     
  27.   
  28.     return JNI_VERSION_1_4;  
  29. }  
#include "jni.h" #include "utils/Log.h" #include "utils/misc.h" #include "JNIHelp.h" namespace android { ... int register_android_server_SensorService(JNIEnv* env); ... }; using namespace android; extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { LOGE("GetEnv failed!"); return result; } LOG_ASSERT(env, "Could not retrieve the env!"); //注册SensorService register_android_server_SensorService(env); return JNI_VERSION_1_4; }

 

    向Application Framework提供接口部分./framework/Jni/com_android_server_SensorService.cpp

 

 

 

Cpp代码
  1. #define LOG_TAG "SensorService"  
  2. #define LOG_NDEBUG 0  
  3. #include "utils/Log.h"  
  4. //加载sensor.h文件  
  5. <strong><span style="color: rgb(153, 204, 0);">#include <hardware/sensors.h></span></strong>  
  6.   
  7. #include "jni.h"  
  8. #include "JNIHelp.h"  
  9.   
  10. namespace android {  
  11.   
  12. static struct file_descriptor_offsets_t  
  13. {  
  14.     jclass mClass;  
  15.     jmethodID mConstructor;  
  16.     jfieldID mDescriptor;  
  17. } gFileDescriptorOffsets;  
  18.   
  19. static struct parcel_file_descriptor_offsets_t  
  20. {  
  21.     jclass mClass;  
  22.     jmethodID mConstructor;  
  23. } gParcelFileDescriptorOffsets;  
  24.   
  25. static struct bundle_descriptor_offsets_t  
  26. {  
  27.     jclass mClass;  
  28.     jmethodID mConstructor;  
  29.     jmethodID mPutIntArray;  
  30.     jmethodID mPutParcelableArray;  
  31. } gBundleOffsets;  
  32.   
  33.   
  34.   
  35. static sensors_control_device_t* sSensorDevice = 0;  
  36.   
  37. static jint  
  38. android_init(JNIEnv *env, jclass clazz)  
  39. {  
  40.     sensors_module_t* module;  
  41.     if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) {  
  42.         if (sensors_control_open(&module->common, &sSensorDevice) == 0) {  
  43.             const struct sensor_t* list;  
  44.             int count = module->get_sensors_list(module, &list);  
  45.             return count;  
  46.         }  
  47.     }  
  48.     return 0;  
  49. }  
  50.   
  51. static jobject  
  52. android_open(JNIEnv *env, jclass clazz)  
  53. {  
  54.     native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);  
  55.     if (!handle) {  
  56.         return NULL;  
  57.     }  
  58.   
  59.     // new Bundle()  
  60.     jobject bundle = env->NewObject(  
  61.             gBundleOffsets.mClass,  
  62.             gBundleOffsets.mConstructor);  
  63.   
  64.     if (handle->numFds > 0) {  
  65.         jobjectArray fdArray = env->NewObjectArray(handle->numFds,  
  66.                 gParcelFileDescriptorOffsets.mClass, NULL);  
  67.         for (int i = 0; i < handle->numFds; i++) {  
  68.             // new FileDescriptor()  
  69.             jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,  
  70.                     gFileDescriptorOffsets.mConstructor);  
  71.             env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);  
  72.             // new ParcelFileDescriptor()  
  73.             jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,  
  74.                     gParcelFileDescriptorOffsets.mConstructor, fd);  
  75.             env->SetObjectArrayElement(fdArray, i, pfd);  
  76.         }  
  77.         // bundle.putParcelableArray("fds", fdArray);  
  78.         env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,  
  79.                 env->NewStringUTF("fds"), fdArray);  
  80.     }  
  81.   
  82.     if (handle->numInts > 0) {  
  83.         jintArray intArray = env->NewIntArray(handle->numInts);  
  84.         env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);  
  85.         // bundle.putIntArray("ints", intArray);  
  86.         env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,  
  87.                 env->NewStringUTF("ints"), intArray);  
  88.     }  
  89.   
  90.     // delete the file handle, but don't close any file descriptors  
  91.     native_handle_delete(handle);  
  92.     return bundle;  
  93. }  
  94.   
  95. static jint  
  96. android_close(JNIEnv *env, jclass clazz)  
  97. {  
  98.     if (sSensorDevice->close_data_source)  
  99.         return sSensorDevice->close_data_source(sSensorDevice);  
  100.     else  
  101.         return 0;  
  102. }  
  103.   
  104. static jboolean  
  105. android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate)  
  106. {  
  107.     int active = sSensorDevice->activate(sSensorDevice, sensor, activate);  
  108.     return (active<0) ? false : true;  
  109. }  
  110.   
  111. static jint  
  112. android_set_delay(JNIEnv *env, jclass clazz, jint ms)  
  113. {  
  114.     return sSensorDevice->set_delay(sSensorDevice, ms);  
  115. }  
  116.   
  117. static jint  
  118. android_data_wake(JNIEnv *env, jclass clazz)  
  119. {  
  120.     int res = sSensorDevice->wake(sSensorDevice);  
  121.     return res;  
  122. }  
  123.   
  124. //提供给顶层实现的访问函数  
  125. static JNINativeMethod gMethods[] = {  
  126.   <span style="color: rgb(153, 204, 0);"> </span><strong><span style="color: rgb(153, 204, 0);"> {"_sensors_control_init",     "()I",   (void*) android_init },  
  127.     {"_sensors_control_open",     "()Landroid/os/Bundle;",  (void*) android_open },  
  128.     {"_sensors_control_close",     "()I",  (void*) android_close },  
  129.     {"_sensors_control_activate", "(IZ)Z", (void*) android_activate },  
  130.     {"_sensors_control_wake",     "()I", (void*) android_data_wake },  
  131.     {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },</span></strong>  
  132. };  
  133.   
  134. int register_android_server_SensorService(JNIEnv *env)  
  135. {  
  136.     jclass clazz;  
  137.   
  138.     clazz = env->FindClass("java/io/FileDescriptor");  
  139.     gFileDescriptorOffsets.mClass = (jclass)env->NewGlobalRef(clazz);  
  140.     gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");  
  141.     gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");  
  142.   
  143.     clazz = env->FindClass("android/os/ParcelFileDescriptor");  
  144.     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  145.     gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",  
  146.             "(Ljava/io/FileDescriptor;)V");  
  147.   
  148.     clazz = env->FindClass("android/os/Bundle");  
  149.     gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz);  
  150.     gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");  
  151.     gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V");  
  152.     gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray",  
  153.             "(Ljava/lang/String;[Landroid/os/Parcelable;)V");  
  154.   
  155.     return jniRegisterNativeMethods(env, "com/android/server/SensorService",  
  156.             gMethods, NELEM(gMethods));  
  157. }  
  158.   
  159. }; // namespace android  
#define LOG_TAG "SensorService" #define LOG_NDEBUG 0 #include "utils/Log.h" //加载sensor.h文件 #include <hardware/sensors.h> #include "jni.h" #include "JNIHelp.h" namespace android { static struct file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; jfieldID mDescriptor; } gFileDescriptorOffsets; static struct parcel_file_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; } gParcelFileDescriptorOffsets; static struct bundle_descriptor_offsets_t { jclass mClass; jmethodID mConstructor; jmethodID mPutIntArray; jmethodID mPutParcelableArray; } gBundleOffsets; static sensors_control_device_t* sSensorDevice = 0; static jint android_init(JNIEnv *env, jclass clazz) { sensors_module_t* module; if (hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t**)&module) == 0) { if (sensors_control_open(&module->common, &sSensorDevice) == 0) { const struct sensor_t* list; int count = module->get_sensors_list(module, &list); return count; } } return 0; } static jobject android_open(JNIEnv *env, jclass clazz) { native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice); if (!handle) { return NULL; } // new Bundle() jobject bundle = env->NewObject( gBundleOffsets.mClass, gBundleOffsets.mConstructor); if (handle->numFds > 0) { jobjectArray fdArray = env->NewObjectArray(handle->numFds, gParcelFileDescriptorOffsets.mClass, NULL); for (int i = 0; i < handle->numFds; i++) { // new FileDescriptor() jobject fd = env->NewObject(gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor); env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]); // new ParcelFileDescriptor() jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fd); env->SetObjectArrayElement(fdArray, i, pfd); } // bundle.putParcelableArray("fds", fdArray); env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray, env->NewStringUTF("fds"), fdArray); } if (handle->numInts > 0) { jintArray intArray = env->NewIntArray(handle->numInts); env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]); // bundle.putIntArray("ints", intArray); env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray, env->NewStringUTF("ints"), intArray); } // delete the file handle, but don't close any file descriptors native_handle_delete(handle); return bundle; } static jint android_close(JNIEnv *env, jclass clazz) { if (sSensorDevice->close_data_source) return sSensorDevice->close_data_source(sSensorDevice); else return 0; } static jboolean android_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate) { int active = sSensorDevice->activate(sSensorDevice, sensor, activate); return (active<0) ? false : true; } static jint android_set_delay(JNIEnv *env, jclass clazz, jint ms) { return sSensorDevice->set_delay(sSensorDevice, ms); } static jint android_data_wake(JNIEnv *env, jclass clazz) { int res = sSensorDevice->wake(sSensorDevice); return res; } //提供给顶层实现的访问函数 static JNINativeMethod gMethods[] = {  {"_sensors_control_init", "()I", (void*) android_init }, {"_sensors_control_open", "()Landroid/os/Bundle;", (void*) android_open }, {"_sensors_control_close", "()I", (void*) android_close }, {"_sensors_control_activate", "(IZ)Z", (void*) android_activate }, {"_sensors_control_wake", "()I", (void*) android_data_wake }, {"_sensors_control_set_delay","(I)I", (void*) android_set_delay }, }; int register_android_server_SensorService(JNIEnv *env) { jclass clazz; clazz = env->FindClass("java/io/FileDescriptor"); gFileDescriptorOffsets.mClass = (jclass)env->NewGlobalRef(clazz); gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V"); gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I"); clazz = env->FindClass("android/os/ParcelFileDescriptor"); gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V"); clazz = env->FindClass("android/os/Bundle"); gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz); gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V"); gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V"); gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray", "(Ljava/lang/String;[Landroid/os/Parcelable;)V"); return jniRegisterNativeMethods(env, "com/android/server/SensorService", gMethods, NELEM(gMethods)); } }; // namespace android

 

    到了这里文件系统中底层的部分算是完成了。对于下层类库而言,我们可以通过HAL的方式建立android Api 和硬件设备驱动连接的桥梁。针对不同的硬件平台需要用户自己编写这几个函数的实现方式并通过android kernel里的驱动(当然有部分驱动可能位于文件系统中)来控制硬件行为。对于上层而言,可以看做是给顶层Java实现Android API提供一个访问接口。由于该文件是编译成系统 的*.so库文件,这与NDK中的为系统加载一个*.so相似。

 

 3、Application Framework层是如何监听Sensor的物理数据

    到了这里,用NDK的编程经验,我们可以通过system.load("*.so")获得某个库的访问,并使用里面的函数,进行想要的操作。而Google为了方便用户操作,用Java语言提供一些便捷访问的Application Framework将底层的c/c++实现的驱动或者其他细节封装起来,也就是我们所说的API(/(^o^)/~个人理解)

    

    终于到了熟悉的Android API 层了。

    对于重力感应器,Android在./framework/base/service/java/com/android/server/SensorsService.java

 

Java代码
  1. import android.content.Context;  
  2. import android.hardware.ISensorService;  
  3. import android.os.Binder;  
  4. import android.os.Bundle;  
  5. import android.os.RemoteException;  
  6. import android.os.IBinder;  
  7. import android.util.Config;  
  8. import android.util.Slog;  
  9. import android.util.PrintWriterPrinter;  
  10. import android.util.Printer;  
  11.   
  12. import java.io.FileDescriptor;  
  13. import java.io.PrintWriter;  
  14. import java.util.ArrayList;  
  15.   
  16. import com.android.internal.app.IBatteryStats;  
  17. import com.android.server.am.BatteryStatsService;  
  18.   
  19.   
  20.   
  21.   
  22. class SensorService extends ISensorService.Stub {  
  23.     static final String TAG = SensorService.class.getSimpleName();  
  24.     private static final boolean DEBUG = false;  
  25.     private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;  
  26.     private static final int SENSOR_DISABLE = -1;  
  27.     private int mCurrentDelay = 0;  
  28.       
  29.       
  30.     final IBatteryStats mBatteryStats = BatteryStatsService.getService();  
  31.   
  32.     private final class Listener implements IBinder.DeathRecipient {  
  33.         final IBinder mToken;  
  34.         final int mUid;  
  35.   
  36.         int mSensors = 0;  
  37.         int mDelay = 0x7FFFFFFF;  
  38.           
  39.         Listener(IBinder token, int uid) {  
  40.             mToken = token;  
  41.             mUid = uid;  
  42.         }  
  43.           
  44.         void addSensor(int sensor, int delay) {  
  45.             mSensors |= (1<<sensor);  
  46.             if (delay < mDelay)  
  47.                 mDelay = delay;  
  48.         }  
  49.           
  50.         void removeSensor(int sensor) {  
  51.             mSensors &= ~(1<<sensor);  
  52.         }  
  53.   
  54.         boolean hasSensor(int sensor) {  
  55.             return ((mSensors & (1<<sensor)) != 0);  
  56.         }  
  57.   
  58.         public void binderDied() {  
  59.             if (localLOGV) Slog.d(TAG, "sensor listener died");  
  60.             synchronized(mListeners) {  
  61.                 mListeners.remove(this);  
  62.                 mToken.unlinkToDeath(this, 0);  
  63.                 // go through the lists of sensors used by the listener that   
  64.                 // died and deactivate them.  
  65.                 for (int sensor=0 ; sensor<32 && mSensors!=0 ; sensor++) {  
  66.                     if (hasSensor(sensor)) {  
  67.                         removeSensor(sensor);  
  68.                         deactivateIfUnusedLocked(sensor);  
  69.                         try {  
  70.                             mBatteryStats.noteStopSensor(mUid, sensor);  
  71.                         } catch (RemoteException e) {  
  72.                             // oops. not a big deal.  
  73.                         }  
  74.                     }  
  75.                 }  
  76.                 if (mListeners.size() == 0) {  
  77.                     _sensors_control_wake();  
  78.                     _sensors_control_close();  
  79.                 } else {  
  80.                     // TODO: we should recalculate the delay, since removing  
  81.                     // a listener may increase the overall rate.  
  82.                 }  
  83.                 mListeners.notify();  
  84.             }  
  85.         }  
  86.     }  
  87.   
  88.     @SuppressWarnings("unused")  
  89.     public SensorService(Context context) {  
  90.         if (localLOGV) Slog.d(TAG, "SensorService startup");  
  91.         _sensors_control_init();  
  92.     }  
  93.       
  94.     public Bundle getDataChannel() throws RemoteException {  
  95.         // synchronize so we do not require sensor HAL to be thread-safe.  
  96.         synchronized(mListeners) {  
  97.             return _sensors_control_open();  
  98.         }  
  99.     }  
  100.   
  101.     public boolean enableSensor(IBinder binder, String name, int sensor, int enable)  
  102.             throws RemoteException {  
  103.           
  104.         if (localLOGV) Slog.d(TAG, "enableSensor " + name + "(#" + sensor + ") " + enable);  
  105.   
  106.         if (binder == null) {  
  107.             Slog.e(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")");  
  108.             return false;  
  109.         }  
  110.   
  111.         if (enable < 0 && (enable != SENSOR_DISABLE)) {  
  112.             Slog.e(TAG, "invalid enable parameter (enable=" + enable +  
  113.                     ", sensor=" + name + ", id=" + sensor + ")");  
  114.             return false;  
  115.         }  
  116.   
  117.         boolean res;  
  118.         int uid = Binder.getCallingUid();  
  119.         synchronized(mListeners) {  
  120.             res = enableSensorInternalLocked(binder, uid, name, sensor, enable);  
  121.             if (res == true) {  
  122.                 // Inform battery statistics service of status change  
  123.                 long identity = Binder.clearCallingIdentity();  
  124.                 if (enable == SENSOR_DISABLE) {  
  125.                     mBatteryStats.noteStopSensor(uid, sensor);  
  126.                 } else {  
  127.                     mBatteryStats.noteStartSensor(uid, sensor);  
  128.                 }  
  129.                 Binder.restoreCallingIdentity(identity);  
  130.             }  
  131.         }  
  132.         return res;  
  133.     }  
  134.   
  135.     private boolean enableSensorInternalLocked(IBinder binder, int uid,  
  136.             String name, int sensor, int enable) throws RemoteException {  
  137.   
  138.         // check if we have this listener  
  139.         Listener l = null;  
  140.         for (Listener listener : mListeners) {  
  141.             if (binder == listener.mToken) {  
  142.                 l = listener;  
  143.                 break;  
  144.             }  
  145.         }  
  146.   
  147.         if (enable != SENSOR_DISABLE) {  
  148.             // Activate the requested sensor  
  149.             if (_sensors_control_activate(sensor, true) == false) {  
  150.                 Slog.w(TAG, "could not enable sensor " + sensor);  
  151.                 return false;  
  152.             }  
  153.   
  154.             if (l == null) {  
  155.                   
  156.                 l = new Listener(binder, uid);  
  157.                 binder.linkToDeath(l, 0);  
  158.                 mListeners.add(l);  
  159.                 mListeners.notify();  
  160.             }  
  161.   
  162.             // take note that this sensor is now used by this client  
  163.             l.addSensor(sensor, enable);  
  164.   
  165.         } else {  
  166.   
  167.             if (l == null) {  
  168.                   
  169.                 Slog.w(TAG, "listener with binder " + binder +  
  170.                         ", doesn't exist (sensor=" + name +  
  171.                         ", id=" + sensor + ")");  
  172.                 return false;  
  173.             }  
  174.   
  175.             // remove this sensor from this client  
  176.             l.removeSensor(sensor);  
  177.   
  178.             // see if we need to deactivate this sensors=  
  179.             deactivateIfUnusedLocked(sensor);  
  180.   
  181.             // if the listener doesn't have any more sensors active  
  182.             // we can get rid of it  
  183.             if (l.mSensors == 0) {  
  184.                 // we won't need this death notification anymore  
  185.                 binder.unlinkToDeath(l, 0);  
  186.                 // remove the listener from the list  
  187.                 mListeners.remove(l);  
  188.                 // and if the list is empty, turn off the whole sensor h/w  
  189.                 if (mListeners.size() == 0) {  
  190.                     _sensors_control_wake();  
  191.                     _sensors_control_close();  
  192.                 }  
  193.                 mListeners.notify();  
  194.             }  
  195.         }  
  196.   
  197.         // calculate and set the new delay  
  198.         int minDelay = 0x7FFFFFFF;  
  199.         for (Listener listener : mListeners) {  
  200.             if (listener.mDelay < minDelay)  
  201.                 minDelay = listener.mDelay;  
  202.         }  
  203.         if (minDelay != 0x7FFFFFFF) {  
  204.             mCurrentDelay = minDelay;  
  205.             _sensors_control_set_delay(minDelay);  
  206.         }  
  207.   
  208.         return true;  
  209.     }  
  210.   
  211.     private void deactivateIfUnusedLocked(int sensor) {  
  212.         int size = mListeners.size();  
  213.         for (int i=0 ; i<size ; i++) {  
  214.             if (mListeners.get(i).hasSensor(sensor)) {  
  215.                 // this sensor is still in use, don't turn it off  
  216.                 return;  
  217.             }  
  218.         }  
  219.         if (_sensors_control_activate(sensor, false) == false) {  
  220.             Slog.w(TAG, "could not disable sensor " + sensor);  
  221.         }  
  222.     }  
  223.   
  224.     @Override  
  225.     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {  
  226.         synchronized (mListeners) {  
  227.             Printer pr = new PrintWriterPrinter(pw);  
  228.             int c = 0;  
  229.             pr.println(mListeners.size() + " listener(s), delay=" + mCurrentDelay + " ms");  
  230.             for (Listener l : mListeners) {  
  231.                 pr.println("listener[" + c + "] " +  
  232.                         "sensors=0x" + Integer.toString(l.mSensors, 16) +  
  233.                         ", uid=" + l.mUid +  
  234.                         ", delay=" +  
  235.                         l.mDelay + " ms");  
  236.                 c++;  
  237.             }  
  238.         }  
  239.     }  
  240.   
  241.     private ArrayList<Listener> mListeners = new ArrayList<Listener>();  
  242.     //JNI提供的访问函数,将Application Framework和驱动衔接起来。  
  243.     private static native int _sensors_control_init();  
  244.     private static native Bundle _sensors_control_open();  
  245.     private static native int _sensors_control_close();  
  246.     private static native boolean _sensors_control_activate(int sensor, boolean activate);  
  247.     private static native int _sensors_control_set_delay(int ms);  
  248.     private static native int _sensors_control_wake();  
  249. }  
import android.content.Context; import android.hardware.ISensorService; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.IBinder; import android.util.Config; import android.util.Slog; import android.util.PrintWriterPrinter; import android.util.Printer; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import com.android.internal.app.IBatteryStats; import com.android.server.am.BatteryStatsService; class SensorService extends ISensorService.Stub { static final String TAG = SensorService.class.getSimpleName(); private static final boolean DEBUG = false; private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; private static final int SENSOR_DISABLE = -1; private int mCurrentDelay = 0; final IBatteryStats mBatteryStats = BatteryStatsService.getService(); private final class Listener implements IBinder.DeathRecipient { final IBinder mToken; final int mUid; int mSensors = 0; int mDelay = 0x7FFFFFFF; Listener(IBinder token, int uid) { mToken = token; mUid = uid; } void addSensor(int sensor, int delay) { mSensors |= (1<<sensor); if (delay < mDelay) mDelay = delay; } void removeSensor(int sensor) { mSensors &= ~(1<<sensor); } boolean hasSensor(int sensor) { return ((mSensors & (1<<sensor)) != 0); } public void binderDied() { if (localLOGV) Slog.d(TAG, "sensor listener died"); synchronized(mListeners) { mListeners.remove(this); mToken.unlinkToDeath(this, 0); // go through the lists of sensors used by the listener that // died and deactivate them. for (int sensor=0 ; sensor<32 && mSensors!=0 ; sensor++) { if (hasSensor(sensor)) { removeSensor(sensor); deactivateIfUnusedLocked(sensor); try { mBatteryStats.noteStopSensor(mUid, sensor); } catch (RemoteException e) { // oops. not a big deal. } } } if (mListeners.size() == 0) { _sensors_control_wake(); _sensors_control_close(); } else { // TODO: we should recalculate the delay, since removing // a listener may increase the overall rate. } mListeners.notify(); } } } @SuppressWarnings("unused") public SensorService(Context context) { if (localLOGV) Slog.d(TAG, "SensorService startup"); _sensors_control_init(); } public Bundle getDataChannel() throws RemoteException { // synchronize so we do not require sensor HAL to be thread-safe. synchronized(mListeners) { return _sensors_control_open(); } } public boolean enableSensor(IBinder binder, String name, int sensor, int enable) throws RemoteException { if (localLOGV) Slog.d(TAG, "enableSensor " + name + "(#" + sensor + ") " + enable); if (binder == null) { Slog.e(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")"); return false; } if (enable < 0 && (enable != SENSOR_DISABLE)) { Slog.e(TAG, "invalid enable parameter (enable=" + enable + ", sensor=" + name + ", id=" + sensor + ")"); return false; } boolean res; int uid = Binder.getCallingUid(); synchronized(mListeners) { res = enableSensorInternalLocked(binder, uid, name, sensor, enable); if (res == true) { // Inform battery statistics service of status change long identity = Binder.clearCallingIdentity(); if (enable == SENSOR_DISABLE) { mBatteryStats.noteStopSensor(uid, sensor); } else { mBatteryStats.noteStartSensor(uid, sensor); } Binder.restoreCallingIdentity(identity); } } return res; } private boolean enableSensorInternalLocked(IBinder binder, int uid, String name, int sensor, int enable) throws RemoteException { // check if we have this listener Listener l = null; for (Listener listener : mListeners) { if (binder == listener.mToken) { l = listener; break; } } if (enable != SENSOR_DISABLE) { // Activate the requested sensor if (_sensors_control_activate(sensor, true) == false) { Slog.w(TAG, "could not enable sensor " + sensor); return false; } if (l == null) { l = new Listener(binder, uid); binder.linkToDeath(l, 0); mListeners.add(l); mListeners.notify(); } // take note that this sensor is now used by this client l.addSensor(sensor, enable); } else { if (l == null) { Slog.w(TAG, "listener with binder " + binder + ", doesn't exist (sensor=" + name + ", id=" + sensor + ")"); return false; } // remove this sensor from this client l.removeSensor(sensor); // see if we need to deactivate this sensors= deactivateIfUnusedLocked(sensor); // if the listener doesn't have any more sensors active // we can get rid of it if (l.mSensors == 0) { // we won't need this death notification anymore binder.unlinkToDeath(l, 0); // remove the listener from the list mListeners.remove(l); // and if the list is empty, turn off the whole sensor h/w if (mListeners.size() == 0) { _sensors_control_wake(); _sensors_control_close(); } mListeners.notify(); } } // calculate and set the new delay int minDelay = 0x7FFFFFFF; for (Listener listener : mListeners) { if (listener.mDelay < minDelay) minDelay = listener.mDelay; } if (minDelay != 0x7FFFFFFF) { mCurrentDelay = minDelay; _sensors_control_set_delay(minDelay); } return true; } private void deactivateIfUnusedLocked(int sensor) { int size = mListeners.size(); for (int i=0 ; i<size ; i++) { if (mListeners.get(i).hasSensor(sensor)) { // this sensor is still in use, don't turn it off return; } } if (_sensors_control_activate(sensor, false) == false) { Slog.w(TAG, "could not disable sensor " + sensor); } } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { synchronized (mListeners) { Printer pr = new PrintWriterPrinter(pw); int c = 0; pr.println(mListeners.size() + " listener(s), delay=" + mCurrentDelay + " ms"); for (Listener l : mListeners) { pr.println("listener[" + c + "] " + "sensors=0x" + Integer.toString(l.mSensors, 16) + ", uid=" + l.mUid + ", delay=" + l.mDelay + " ms"); c++; } } } private ArrayList<Listener> mListeners = new ArrayList<Listener>(); //JNI提供的访问函数,将Application Framework和驱动衔接起来。 private static native int _sensors_control_init(); private static native Bundle _sensors_control_open(); private static native int _sensors_control_close(); private static native boolean _sensors_control_activate(int sensor, boolean activate); private static native int _sensors_control_set_delay(int ms); private static native int _sensors_control_wake(); }
 

   接下来就是Core提供给我们使用的API了,这部分不在详解。

   总结一下:对于NDK也不在啰唆,它和HAL一样,一个是提供商业保密程序,一个是google应厂商要求不希望公开源码。对于HAL的分析,我们也可以看到它大致的开发流程,也隐隐约约看到NDK的影子。若NDK涉及到硬件平台,它又该如何考虑夸平台呢?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: HAL(Hardware Abstraction Layer,硬件抽象)是一种软件设计模式,用于隐藏底硬件的细节,使上应用程序能够更加方便地访问硬件资源。在嵌入式系统中,HAL通常被用来提供一种统一的接口,使应用程序能够与不同的硬件设备进行通信,而无需了解底硬件的细节。 在MCU中,HAL通常由驱动程序实现。驱动程序负责与硬件设备进行通信,并将硬件操作封装在抽象的接口中,供应用程序使用。HAL位于驱动程序之上,负责提供更高次的抽象,将硬件资源进行分组,以便应用程序能够更加方便地访问这些资源。 在设计MCU中的HAL时,需要考虑以下几个方面: 1.接口设计:HAL应该提供一组清晰、简洁的接口,使应用程序能够方便地访问硬件资源。接口应该考虑到硬件资源的次结构和应用程序的需求,以便提供最佳的抽象次。 2.可移植性:HAL应该是可移植的,以便应用程序能够在不同的硬件平台上使用。HAL应该尽可能地隐藏底硬件的差异,以便应用程序能够在不同的硬件平台上重用。 3.性能:HAL应该尽可能地提供高性能的接口,以便应用程序能够快速地访问硬件资源。HAL应该避免不必要的中间,以避免影响系统的性能。 4.可扩展性:HAL应该是可扩展的,以便支持新的硬件设备。HAL应该尽可能地与硬件设备的接口相对应,以便支持新的硬件设备的添加。 总之,在MCU中设计HAL需要考虑到接口设计、可移植性、性能和可扩展性等方面,以提供一种方便、高效、可移植和可扩展的硬件抽象。 ### 回答2: MCU中的HAL硬件抽象)设计需要考虑以下几个方面: 1. 功能:HAL需要提供对MCU硬件功能的抽象接口,包括外设控制、中断管理、时钟控制、存储器访问等等。它应该能够对硬件功能进行抽象,使上应用可以独立于具体的硬件细节。 2. 可移植性:HAL需要设计成可移植的,能够适配多种不同的MCU芯片。这就要求HAL的接口设计应该与具体芯片无关,提供统一的API接口。 3. 灵活性:HAL需要提供灵活的配置选项,以适应各种应用的需求。比如外设的选择、时钟频率的配置等。这样用户可以根据具体需求进行配置,从而减少资源浪费。 4. 实时性:HAL需要具备实时性能,能够对外设进行实时响应。它应该提供合理的中断管理机制,允许用户编写中断服务程序,以处理外设的实时事件。 5. 易用性:HAL应该易于使用,它应该提供简洁、清晰的编程接口,使开发者能够快速理解使用方法。此外,提供示例代码和文档等辅助资料也可以增加其易用性。 6. 可扩展性:HAL设计应该考虑到MCU的发展与更新,允许用户进行自定义扩展。比如,添加新的外设模块、更新时钟配置等。 总之,设计MCU中的HAL需要综合考虑功能、可移植性、灵活性、实时性、易用性和可扩展性等方面,以提供一个高效可靠的抽象,简化硬件操作,促进应用开发。 ### 回答3: 在MCU中,HAL(Hardware Abstraction Layer)硬件抽象的设计是为了提供对底硬件的标准化接口,使上应用能够方便地访问和控制硬件资源。下面是关于HAL设计的几点思考: 首先,HAL应该提供一组统一的API函数,用于访问并控制各种硬件资源,包括IO口、中断控制、定时器、外设等。这些函数应该具有一致的命名规范和接口参数,以方便开发人员对不同的硬件资源进行编程。 其次,HAL应支持多种硬件平台和芯片系列。不同的MCU芯片之间可能存在硬件差异,例如寄存器的地址和功能可能不同。因此,HAL需要根据不同的硬件平台提供相应的实现,使得上应用无论在哪种硬件平台上运行,都能够使用统一的API。 此外,HAL还应提供对底硬件的初始化和配置功能。在启动时,HAL需要检测硬件的状态并进行相应的初始化,例如配置时钟、中断、IO口等,以确保硬件资源处于正确的状态。这样,上应用在调用HAL函数之前无需关注底硬件的配置过程。 最后,HAL应提供一定程度的可扩展性和灵活性。由于MCU中的硬件资源可能不断升级和改变,HAL需要提供接口和机制,使得开发人员能够方便地进行功能扩展和适配。例如,可以通过添加新的函数接口或修改配置文件来支持新的硬件功能。 综上所述,MCU中的HAL硬件抽象需要提供统一的API函数、多平台支持、初始化配置功能以及可扩展性和灵活性。通过这样的设计,可以提高上应用的开发效率和跨平台移植性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值