透过HAL(硬件抽象层)看顶层API是如何访问硬件
#include <...>
__BEGIN_DECLS/** * The id of this module */#define SENSORS_HARDWARE_MODULE_ID "sensors"/** * Name of the sensors device to open */#define SENSORS_HARDWARE_CONTROL "control"#define SENSORS_HARDWARE_DATA "data"...../** convenience API for opening and closing a device */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??#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
?
?
?
#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;/* * The method below are not thread-safe and not intended to be */static sensors_control_device_t* sSensorDevice = 0;static jintandroid_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 jobjectandroid_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 jintandroid_close(JNIEnv *env, jclass clazz){ if (sSensorDevice->close_data_source) return sSensorDevice->close_data_source(sSensorDevice); else return 0;}static jbooleanandroid_activate(JNIEnv *env, jclass clazz, jint sensor, jboolean activate){ int active = sSensorDevice->activate(sSensorDevice, sensor, activate); return (active<0) ? false : true;}static jintandroid_set_delay(JNIEnv *env, jclass clazz, jint ms){ return sSensorDevice->set_delay(sSensorDevice, ms);}static jintandroid_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相似。
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 that manages the device's sensors. It register clients and activate * the needed sensors. The sensor events themselves are not broadcasted from * this service, instead, a file descriptor is provided to each client they * can read events from. */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; /** * Battery statistics to be updated when sensors are enabled and disabled. */ 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) { /* * we don't have a listener for this binder yet, so * create a new one and add it to the list. */ 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) { /* * This client isn't in the list, this usually happens * when enabling the sensor failed, but the client * didn't handle the error and later tries to shut that * sensor off. */ 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();}?
是的。