1,在 Froyo 的代码里面,传感器的硬件抽象层 A,抽象层的接口定义 Hardware/libhardware/include/hardware/sensor.h B,Hal 的 具体实现 Sdk/emulator/sensors/sensors_qemu.c android.mk 去编译一个动态连接库,mm 的方法编译 (具体见附录 a)会生成一个 sensors.goldfish.so , 2, 这个编译的 HAL 层是如何被调用的 简单的说就是通过 hw_get_module 来实现的 ,通过查找你之前定义的 module ID 来 实现具体的操作, 使用 readelf –s *.so 可以查看 so 的连接库的具体的介绍, 看到里面有一个 重要的 HMI 这样的 一个东西 作为他的入口 来实现 他的操作,同样的在他的硬件抽象层 可以实现,HAL_MODULE_INFO_SYM
3.Sensor 代码的调用操作; A,内核里面的驱动程序 B,HAL 的程序 C,JNI 的操作 D,Java 的操作 E,Java 的 manager 也叫框架 F,应用程序对 sensro 的使用 就概括为 app-manager-server(Java)-Server(JNI)-HAL-最底层的操作 4,整个 android 的框架 任何一个系统, 要去理解他, 觉得不是从代码入手, 代码只是我们验证猜想的一个工具, 要完全站在设计者的角度去理解整个系统, 而不是只站在开发者的角度, 这样对于以后我们 遇到的问题才可以迎认而解, 对于任何一个软件系统,他可以分出两条线,数据流 和控制流, 还有需要我们了解的是为什么会形成 android 这个系统,他复杂的系统框架一定有他的 历史原因,和他这样做的必要, (当然每个人都有他的具体的理解) (当然这样做的目的 只 是为了更好的站在 人的角度去思考问题) 5,关于代码怎样去调用的问题 使用 adb 的工具把 sdk 的*.so 文件替换掉 形成一个新的镜象文件,然后去做具体的实 验,在使用新的程序去进行操作,然后添加打印信息,看这个路径的调用过程,来验证,实 现自己的理解,然后去操作具体的整个过程,这样对整个结构有个完整而全面的认识 6,从看代码的阶段 ,去过度到去调试,去验证思想的阶段,发现还是有很多具体的操作需 要学习,这只是一种技巧 ,就是所谓的工作经验,如果去掉这些华丽的外衣,其实每个人 都是差不多的 从 froyo 的代码,过度到 sdk 的代码 ,对我来说是经过了很长时间的路,如果对我来 说可以把这些路 绕过去,将回是一个时间的巨大节省,但缺少的是那份乐趣,等理解了整 个框架之后 一切都是水到渠成的事,现在看起来一切都挺简单的 7,
每个进程,每个程序都是需要一个 vm 去支持他的操作,,因此 vm 是他和 l inux 之间唯一的接口,这个只是按他的思想来继承的东西,到底是不是这样 还 需要自己的验证
能不能用代码验证下虚拟机 这部分的实现 ,
研究下 打通三个层的这段代码看下整个层是怎样进行传输的 由应用程序慢慢的往上研究,看来不来及 去 Debug 些东西 去验证自己的猜想操作 现在回过头去看,JNI 的应用,来验证自己的想法是不是正确 ,就用他的 led module 来说 明,更加容易的去理解 JNI,so 及 server .mangger 之间的关系。 JNI 编译的代码 出来的库叫 libandroid_runtime.so (可以上网看下大致的介绍,可以有一个 整体上的影响,) Java 的 framework 编译出来的叫做 framework.jar 文件, 在由一个简单的 helloJNI 程序, 去研 究他到底是怎样操作的 从他的 JNI 技术说起,为什么要有这个技术,这个技术带来的好处是什么呢
第一 sensor 的描述; Sensor(传感器系统)已经越来越广泛被使用了, android 的传感器系统涉及 android 的各 个层次,android 支持多种传感器,本篇的主要目的是简要的介绍下 sensor 的传感器,的整 个框架,从应用到底层的调用关系,结合 android froyo 的代码,进行说明,使你能对 Sensor 的传感器系统,尽可能有较深的理解,方便在自己的 android 系统上很容易使用传感器
先从应用程序的角度出发,看下 android 是怎样使用 sensor 的 ,先有一个大致上的了解 应用的代码为(省去了一些画图的部分,保留了 sensor 的所有操作) :
public class hellowprd extends Activity { /** Tag string for our debug logs */ private static final String TAG = "Sensors"; private SensorManager mSensorManager; private class GraphView extends View implements SensorListener { public void onSensorChanged(int sensor, float[] values) { Log.d(TAG, "sensor: " + sensor + ", x: " + values[0] + ", y: " + values[1] + ", z: " + values[2]); synchronized (this) { if (mBitmap != null) { if (sensor == SensorManager.SENSOR_ORIENTATION) { for (int i=0 ; i<3 ; i++) { mOrientationValues[i] = values[i]; } } } public void onAccuracyChanged(int sensor, int accuracy) { // TODO Auto-generated method stub } } protected void onCreate(Bundle savedInstanceState) { mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); } protected void onResume() { super.onResume(); mSensorManager.registerListener(mGraphView, SensorManager.SENSOR_ACCELEROMETER | SensorManager.SENSOR_MAGNETIC_FIELD | SensorManager.SENSOR_ORIENTATION, SensorManager.SENSOR_DELAY_FASTEST); } @Override protected void onStop() {
mSensorManager.unregisterListener(mGraphView); super.onStop(); } }
从应用程序的角度出发,我们可以看到 getSystemService(SENSOR_SERVICE);
registerListener(mGraphView, SensorManager.SENSOR_ACCELEROMETER | SensorManager.SENSOR_MAGNETIC_FIELD | SensorManager.SENSOR_ORIENTATION, SensorManager.SENSOR_DELAY_FASTEST); onSensorChanged(); 这些操作后就可以获取数据,但这些操作到底是个怎样的关系呢,这将是我们所要搞明白的!
Sensor 的整体结构图:
Sensor 代码的调用操作; (从下到上 ,反过来看就可以) A,内核里面的驱动程序 B,HAL 的程序 C,JNI 的操作 D,Java 的操作 E,Java 的 manager 也叫框架 F,应用程序对 sensro 的使用 就概括为 app-manager-server(Java)-Server(JNI)-HAL-最底层的操作 任何一个系统,要去理解他,觉得不是从代码入手,代码只是我们验证猜想的一个工具,要 完全站在设计者的角度去理解整个系统, 而不是只站在开发者的角度, 这样对于以后我们遇 到的问题才可以迎认而解,
上面是从层的调用来说,下面我们从数据流和控制流的角度出发 对于任何一个软件系统,他可以分出两条线,数据流 和控制流, 对于 android 也不例外,至少对 Sensor 这个结构来说,这样理解比较容易一点
第二 Sensor 的代码分部 Java 层部分: frameworks\base\core\java\android\hardware Sensor.java, SensorEvent.java,SensorEventListen.java,SensorManager.java(Manager 层代 码) frameworks\base\services\java\com\android\server SensorService.java(Service 层代码) JNI 的层代码 frameworks\base\core\jni android_hardware_SensorManager.cpp (Manager 层代码) frameworks\base\services\jni\ com_android_server_SensorService.cpp (Service 层代码) HAL 层的代码 Hardware\Libhardware\Include\Hardware Sensor.h
在 Java 层 Sensor 的状态控制由 SensorService 来负责,它的 java 代码和 JNI 代码分别位于: frameworks/base/services/java/com/android/server/SensorService.java frameworks/base/services/jni/com_android_server_SensorService.cpp 在 Java 层 Sensor 的数据控制由 SensorManager 来负责,它的 java 代码和 JNI 代码分别位于: frameworks/base/core/java/android/hardware/SensorManager.java frameworks/base/core/jni/android_hardware_SensorManager.cpp 根据具体的列子去调用,去研究,调用的过程,及几个重要的数据结构 android framework 中与 sensor 通信的是 sensorService.java 和 sensorManager.java。 sensorService.java 的具体通信是通过 JNI 调用 com_android_server_SensorService.cpp 中的方 法实现的。 sensorManager.java 的具体通信是通过 JNI 调用 android_hardware_SensorManager.cpp 中的方 法实现的
数据流向图:
左半边表示控制流,右半边表示数据流 整体结构图:
注意 SensorEventListener 代替了 SensorListener sensor,,sensorListen,sensorEvent,sensorEventListener,sensorManager. 其 中 sensorEventListener 用来在 sensorManager 中注册需要监听的 sensor 类型。 sensorManager.java 提供 registrater(),unregistrater()接口供 sensorEventListener 使用。 sensorManager.java 不断轮询从 sensor.so 中取数据。取到数据后送给负责监听此类型 sensor 的 sensorEventListener.java。sensorEventListener.java 通过在 sensorManager.java 中注册可以 监听特定类型的 sensor 传来的数据
SensorServer 的具体调用流程:
sensorService.cpp 中相应的方法 android_int()会被执行。该函数会调用 hardware.c 中的方法 hw_get_module()此函数又通过调用 load()函数在 system/lib/hw 下查找 sensor.so 查找时会根据 harware.c 中定义好的 sensor.*.so 的扩展名的顺序查找,找到第一个匹配的时 候即停止, 并将该 sensor.so 中定义好的一个全局变量 HAL_MODULE_INFO_SYM 带回。 该 变量包含的一个 重要信息是它的一个成员结构变量中包含的一个函数指针 open,该指针所指函数会对一个 device 结构变量赋值,在这里是对 sensors_control_device_t 这个结构来操作, 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, 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; } (const
先用代码,在用流程图进行说明
SensorManager 的调用流程: 首先由 app 的 GetSystemService,根据 SENSOR 的类型开始调用 getSensorManager //获取一个 SensorManager 的实例 private SensorManager getSensorManager() { synchronized (mSync) { if (mSensorManager == null) { mSensorManager = new SensorManager(mMainThread.getHandler().getLooper()); } } return mSensorManager; } //在他的 Looper 里面 public SensorManager(Looper mainLooper) { mSensorService = ISensorService.Stub.asInterface( ServiceManager.getService(Context.SENSOR_SERVICE)); //就是把接 口转成 SENSOR_SERVICE 接口,个人觉得吧 在这主要是上电用(enableSensor) …… sensors_module_init(); …… } 在函数 sensors_module_init, 主要是获取 Sensor 的 一个 Module ID,同 SensorServer 的操作一 样 static jint sensors_module_init(JNIEnv *env, jclass clazz) { int err = 0; sensors_module_t const* module; err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (const hw_module_t **)&module); if (err == 0) sSensorModule = (sensors_module_t*)module; return err; } //在启动线程的时候调用 sensors_data_init SensorThread() { // this gets to the sensor module. We can have only one per process. sensors_data_init(); }
static sensors_data_device_t* sSensorDevice = 0;
sensors_data_init(JNIEnv *env, jclass clazz) { if (sSensorModule == NULL) return -1; int err = sensors_data_open(&sSensorModule->common, &sSensorDevice); return err; } 和 SensorServer 基本一样,不同的就是 Manager 会为每一个应用启动一个进程 ,在进程的 构 造 函 数 里 面 去 初 始 化 的 操 作 , 可 以 看 到 使 用 的 是 sensors_data_open , 对 sensors_data_device_t 进行赋值操作。因为他牵扯到 Sensor 的 data 操作,所以在线程里面 的 while 循环当中去 sensors_data_poll,获取传感器的数据
用流程图简要的说明下
关于几个比较重要的文件,他所实现的一些函数,总结了下,可更加容易看明白他么之间的 调用关系 Com_android_server_SensorService.cpp 里面主要包含的操作和函数为: 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 }, }; Android_hardware_SensorManager.cpp 提供的操作函数: static JNINativeMethod gMethods[] = { {"nativeClassInit", "()V", (void*)nativeClassInit }, {"sensors_module_init","()I", (void*)sensors_module_init }, {"sensors_module_get_next_sensor","(Landroid/hardware/Sensor;I)I", (void*)sensors_module_get_next_sensor }, {"sensors_data_init", "()I", (void*)sensors_data_init }, {"sensors_data_uninit", "()I", (void*)sensors_data_uninit }, {"sensors_data_open", "([Ljava/io/FileDescriptor;[I)I", (void*)sensors_data_open }, {"sensors_data_close", "()I", (void*)sensors_data_close }, {"sensors_data_poll", "([F[I[J)I", (void*)sensors_data_poll }, }; SensorManager.java 里面要使用的 Native 函数为: private static native void nativeClassInit(); private static native int sensors_module_init(); private static native int sensors_module_get_next_sensor(Sensor sensor, int next); // Used within this module from outside SensorManager, don't make private static native int sensors_data_init(); static native int sensors_data_uninit(); static native int sensors_data_open(FileDescriptor[] fds, int[] ints); static native int sensors_data_close(); static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
SensorService.java 里面需要使用的 函数为: 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(); 在那去调用这个 Sensor.h 里面提供的操作为:
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); }
整个 sensor 结构就这么会事,从数据流的角度又很好的理解了层的概念 附录 1: 因为在 Server 层 和 Manager 层之间 使用了 AIDL 文件来进程间通信 简要的介 绍下 AIDL 的操作方法 GetSystemService
AIDL 跨进程间的通信
1,声明一个接口类型的变量,该接口类型在.aidl 文件中定义。 package com.android.aidltest; import com.android.aidltest.ITaskCallback; interface ITaskBinder { boolean isTaskRunning(); void stopRunningTask(); void registerCallback(ITaskCallback cb); void unregisterCallback(ITaskCallback cb); } 2, 实现 ServiceConnection
private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = ITaskBinder.Stub.asInterface(service); try { mService.registerCallback(mCallback); }catch (RemoteException e) { } } public void onServiceDisconnected(ComponentName className) { mService = null; } }; 3, 调用 ApplicationContext.bindService(),并在 ServiceConnection 实现中进行传递. bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 4. 在 ServiceConnection.onServiceConnected()实现中,你会接收一个 IBinder 实例(被调用的 Service). 调用 YourInterfaceName.Stub.asInterface((IBinder)service)将参数转换为 YourInterface 类型。 mService = ITaskBinder.Stub.asInterface(service);//转换为mService 这个接 口为你使用的接口 5. 调用接口中定义的方法。 你总要检测到 DeadObjectException 异常, 该异常在连接断开时被 抛出。它只会被远程方法抛出。 6. 断开连接,调用接口实例中的 ApplicationContext.unbindService()
附录 2: 传感器几个轴的介绍,来源于 Sensor.h 文件(英文的 没做翻译) x<0 * * * * * * * * * * * * x>0 ^ | +-----------+--> | | | | | | | | | | | |/ O-----------+/ |[] [ ] []/ +----------/+ y>0
/ z<0 /
y<0
* / * / * |/ z>0 (toward the sky) * * O: Origin (x=0,y=0,z=0) * * * Orientation * ----------* * All values are angles in degrees. * * azimuth: angle between the magnetic north direction and the Y axis, around * the Z axis (0<=azimuth<360). * 0=North, 90=East, 180=South, 270=West * * pitch: Rotation around X axis (-180<=pitch<=180), with positive values when * the z-axis moves toward the y-axis. * * roll: Rotation around Y axis (-90<=roll<=90), with positive values when * the x-axis moves towards the z-axis. * * Note: For historical reasons the roll angle is positive in the clockwise * direction (mathematically speaking, it should be positive in the * counter-clockwise direction): * * Z * ^ * (+roll) .--> | * / | * | | roll: rotation around Y axis * X
* All values are in SI units (m/s^2) and measure the acceleration of the * device minus the force of gravity. * * x: Acceleration minus Gx on the x-axis * y: Acceleration minus Gy on the y-axis * z: Acceleration minus Gz on the z-axis * * Examples: * When the device lies flat on a table and is pushed on its left side * toward the right, the x acceleration value is positive. * * When the device lies flat on a table, the acceleration value is +9.81, * which correspond to the acceleration of the device (0 m/s^2) minus the * force of gravity (-9.81 m/s^2). * * When the device lies flat on a table and is pushed toward the sky, the * acceleration value is greater than +9.81, which correspond to the * acceleration of the device (+A m/s^2) minus the force of * gravity (-9.81 m/s^2). * * * Magnetic Field * -------------* * All values are in micro-Tesla (uT) and measure the ambient magnetic * field in the X, Y and Z axis. * * Proximity * --------* * The distance value is measured in centimeters. Note that some proximity * sensors only support a binary "close" or "far" measurement. In this case, * the sensor should report its maxRange value in the "far" state and a value * less than maxRange in the "near" state. * * Light * ----* * The light sensor value is returned in SI lux units.