人们在日常生活中经常用到传感器,例如,楼宇的楼梯灯、马路上的路灯等。那么手机中的传感器尤其到什么作用呢?在Android 手机中提供了,加速传感器、磁场、方向、陀螺仪、光线、压力、温度等传感器。在Android 系统中。传感器的代码分布信息如下:
1) 传感器系统的 Java 部分,实现文件为 Sensor*.java.
代码路径: frameworks/base/include/core/java/android/hardware
2) 传感器系统的JNI 部分,此部分演示 android.hardware.Sensor.Manager 类的本质支持。
代码路径: frameworks/base/core/jni/android_hardware_SensorManager.cpp.
3) 传感器系统的 HAL 层,演示了传感器系统的硬件抽象层需要具体的实现。
头文件路径:hardware/libhardware/include/hardware/sensor.h
4) 驱动层
代码路径: kernel/driver/hwmon/$(PROJECT)/sensor
1、 HAL 层的Sensor 代码
1) 文件 Android.mk
HAL 层的 代码 都是 c/cpp 格式,一般保存路径是 hardware/$(PROJECT)/sensor/. 其中,文件Android.mk 的实现代码如下;
LOCAL_PATH : = $(call my-dir)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBARIES := libcutils libc liblog
LOCAL_SRC_FILES:= 适配文件
LOCAL_MODULE := sensors.$(PROJECT)
include $(BUILD_SHARED_LIBRARY)
注意 LOCAL_MODULE 的赋值,这里的模块名称都是预先定义好的,具体的可以参考 hardware/libhardware/hardware.c
这里我们可以看到加载的顺序,在加载 Sensor 时,一次去查找 这些 so 是否存在,然后就可以加载到对应适配。
2) 填充的结构体
在 HAL 层,需要特别注意下面几个填充结构体。
(1) 定义sensor 模块的代码如下:
struct sensor_module_t {
struct hw_module_t common;
int (*get_sensors_list) (struct sensors_module_t *module, struct sensor_t const**list);
};
其中,get_sensors_list() 用来表示获取传感器的列表。
(2) sensor_t 表示一个传感器的描述,具体代码如下:
struct sensor_t {
const char* name ; // 传感器名称
const char* vendor ; // 传感器的 vendor
int version; // 传感器的版本
int handle ; // 传感器的句柄
int type ; // 传感器类型
float maxRange; // 传感器的最大范围
float resolution; // 传感器的解析度
float power; // 传感器的耗能,代为 mA
void * reserved[9];
}
(3) 定义了结构体和联合体,具体代码如下:
typedef struct {
int sensor; // sensor 标志符
unio {
sensors_vec_t vector; // x,y,z 矢量
sensors_vec_t orientation; // 方向键,单位为角度
sensors_vec_t acceleration; // 加速度值,单位为 m/s2
sensors_vec_t magnetic ; // 磁矢量,单位为ut
float temperature; // 温度,单位 。c
float distance; // 距离, 单位 cm
float light; // 光线亮度, 单位 lux
}
int64_t time; //ns
uint32_t reserved;
} sensors_data_t;
3) 适配层 函数接口
在HAL 层中需要注意下面这个函数。
static int a_device_open(const struct hw_module_t* module,
const char* name,
struct hw_device_t** device)
其中特别要注意 下面的赋值:
if (!strcmp(name,SENSORS_HARDWARE_CONTROL)) { // 命令通路
···
dev->device.common.close = dev_control_close;
dev->device.open_data_source=open_data_source;
dev->device.activate=activate;
dev->device.set_delay=set_delay;
```
} else if (!strcmp(name, SENSORS_HARDWARE_DATA)) { // 数据通路
···
dev->device.common.close=dev_data_close;
dev->device.data_open=data_open;
dev->device.data_close=data_close;
dev->device.poll=poll;
```
}
在函数中,可以根据名称知道 JNI 应该采用 poll 方式来获取数据,也就是说,驱动中提供的带吗要实现 file_operation.
注意: 在驱动代码中获得的 Sensor 寄存器的数值并不一定是我们实际上报给应用的值,如g-sensor,则各个方向不应该大于 10,一定要注意也要考虑其他因素。
3) Sensor 编程的流程总结
Sensor 编程的流程如下:
(1)Sensor 编程的流程如下:
获取系统服务(SENSOR_SERVICE)返回一个 Sensormanager 对象。
sensormanager = (SensoerManager) getSystemSeriver (SENSOR_SERVICE);
(2)通过 SensorManager 对象获取相应的 Sensor 类型的对象。
sensorObject= sensormanager.getDefaultSensor(sensor Type);
(3)声明一个 SensorEventListener 对象用于监听 Sensor 事件,并重载onSensorChanged方法。
SensorEventListener sensorListener = new SensorEventListener() {};
(4) 注册相应的SensorService.
sensormanager.registerListener(sensorListener, sensorobject,Sensor TYPE);
(5) 销毁相应的 SensorService.
sensormanager.unregisterListener(sensorListener,sensorObject);
此处的SensorListener 接口是整个传感器应用的核心,他包括如下两个必须的方法。
- onSensorChanged(int sensor,float values[]); 此方法在传感器更改时调用,该方法只对受此应用程序监视的传感器调用。该方法包含如下两个参数:
一个整数,指示更改的传感器。
一个浮点数数组,表示传感器数据本身。
- onAccuracyChanged(int sensor,int accuracy); 当传感器的准确值更改时调用此函数,此方法包含两个整数,一个表示传感器,一个表示传感器额精确值。
2、分析Sensor 源码API层 和硬件平台的衔接
接下来我们依照重力感应器Sensor 为例,看重力感应器如何与Applications, Appliaction Framwork 实现交互。
1) 首先在 文件 platform/hardware/Libardware/Include/Sensors.h 中看定义重力感应器对驱动程序的操作,代码如下:
/hardware/libhardware/include/hardware/sensors.h
/** * The id of this module */ #define SENSORS_HARDWARE_MODULE_ID "sensors" /** * Name of the sensors device to open */ #define SENSORS_HARDWARE_POLL "poll"```````
/** convenience API for opening and closing a device */static inline int sensors_open(const struct hw_module_t* module,
struct sensors_poll_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, TO_HW_DEVICE_T_OPEN(device));
}static inline int sensors_close(struct sensors_poll_device_t* device) {
return device->common.close(&device->common);
}static inline int sensors_open_1(const struct hw_module_t* module,
sensors_poll_device_1_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, TO_HW_DEVICE_T_OPEN(device));
}static inline int sensors_close_1(sensors_poll_device_1_t* device) {
return device->common.close(&device->common);
}
(2) 文件 framwork/Jni/onLoad.cpp 用于加载该驱动的访问程序,具体代码如下:
/frameworks/base/services/core/jni/onload.cpp
int register_android_server_SerialService(JNIEnv* env);
(3) 文件 framwork/Jni/com_androidserver_SensorService.cpp 用于向 Application Framework 提供接口。具体代码如下:
/frameworks/base/services/core/jni/com_android_server_sensor_SensorService.cpp
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "NativeSensorService"
#include <android-base/properties.h>
#include <android_runtime/AndroidRuntime.h>
#include <core_jni_helpers.h>
#include <cutils/properties.h>
#include <jni.h>
#include <sensorservice/SensorService.h>
#include <utils/Log.h>
#include <utils/misc.h>
#include <mutex>
#define PROXIMITY_ACTIVE_CLASS \
"com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
namespace android {
static JavaVM* sJvm = nullptr;
static jmethodID sMethodIdOnProximityActive;
class NativeSensorService {
public:
NativeSensorService(JNIEnv* env, jobject listener);
void registerProximityActiveListener();
void unregisterProximityActiveListener();
private:
sp<SensorService> mService;
class ProximityActiveListenerDelegate : public SensorService::ProximityActiveListener {
public:
ProximityActiveListenerDelegate(JNIEnv* env, jobject listener);
~ProximityActiveListenerDelegate();
void onProximityActive(bool isActive) override;
private:
jobject mListener;
};
sp<ProximityActiveListenerDelegate> mProximityActiveListenerDelegate;
};
NativeSensorService::NativeSensorService(JNIEnv* env, jobject listener)
: mProximityActiveListenerDelegate(new ProximityActiveListenerDelegate(env, listener)) {
if (base::GetBoolProperty("system_init.startsensorservice", true)) {
sp<IServiceManager> sm(defaultServiceManager());
mService = new SensorService();
sm->addService(String16(SensorService::getServiceName()), mService,
false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
}
}
void NativeSensorService::registerProximityActiveListener() {
if (mService == nullptr) {
ALOGD("Dropping registerProximityActiveListener, sensor service not available.");
return;
}
mService->addProximityActiveListener(mProximityActiveListenerDelegate);
}
void NativeSensorService::unregisterProximityActiveListener() {
if (mService == nullptr) {
ALOGD("Dropping unregisterProximityActiveListener, sensor service not available.");
return;
}
mService->removeProximityActiveListener(mProximityActiveListenerDelegate);
}
NativeSensorService::ProximityActiveListenerDelegate::ProximityActiveListenerDelegate(
JNIEnv* env, jobject listener)
: mListener(env->NewGlobalRef(listener)) {}
NativeSensorService::ProximityActiveListenerDelegate::~ProximityActiveListenerDelegate() {
AndroidRuntime::getJNIEnv()->DeleteGlobalRef(mListener);
}
void NativeSensorService::ProximityActiveListenerDelegate::onProximityActive(bool isActive) {
auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
jniEnv->CallVoidMethod(mListener, sMethodIdOnProximityActive, static_cast<jboolean>(isActive));
}
static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
NativeSensorService* service = new NativeSensorService(env, listener);
return reinterpret_cast<jlong>(service);
}
static void registerProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
auto* service = reinterpret_cast<NativeSensorService*>(ptr);
service->registerProximityActiveListener();
}
static void unregisterProximityActiveListenerNative(JNIEnv* env, jclass, jlong ptr) {
auto* service = reinterpret_cast<NativeSensorService*>(ptr);
service->unregisterProximityActiveListener();
}
static const JNINativeMethod methods[] = {
{
"startSensorServiceNative", "(L" PROXIMITY_ACTIVE_CLASS ";)J",
reinterpret_cast<void*>(startSensorServiceNative)
},
{
"registerProximityActiveListenerNative", "(J)V",
reinterpret_cast<void*>(registerProximityActiveListenerNative)
},
{
"unregisterProximityActiveListenerNative", "(J)V",
reinterpret_cast<void*>(unregisterProximityActiveListenerNative)
},
};
int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env) {
sJvm = vm;
jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
NELEM(methods));
}
}; // namespace android
到目前为止,完成了文件系统中的底层部分功能,由此可以看出,对于下层类库来说,可以通过HAL 的方式建立Android API 和硬件设备驱动链接的桥梁。针对不同的硬件平台,需要编写上述函数的实现方式,并且通过 Android kernel 中驱动来控制硬件行为。对于上层来说,可以看成是给顶层Java 实现 Android API 提供一个访问接口。因为该文件是一个编译成系统的*.so 库文件,这和 DK 里面为系统加载一个 *.so 及其相似。
(4) 监听 Sensor 的物理数据,接下来看 Application Framwork 层怎样监听Sensor的物理数据,此时可以通过 system.load("*.so") 来获取对某个库的访问,并使用其中的函数进行我们想要的操作。Google 为了方便程序员操作,使用Java 语言提供了便捷访问的Application Framework , 他们将底层的 C/C++ 实现的驱动或其他细节封装起来,其实就是 API 的原型。
下面回到 Android API 层,文件 /frameworks/base/services/core/java/com/android/server/sensors/SensorService.java 的实现代码如下:
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.sensors;
import static com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
import android.annotation.NonNull;
import android.content.Context;
import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ConcurrentUtils;
import com.android.server.LocalServices;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.SystemService;
import com.android.server.utils.TimingsTraceAndSlog;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
/*
管理传感器装置的类
需要客户注册来激活传感器,传感器事件本身不播放这一服务
相反,一个文件描述符是提供给每一个客户的
*/
public class SensorService extends SystemService {
private static final String START_NATIVE_SENSOR_SERVICE = "StartNativeSensorService";
private final Object mLock = new Object();
@GuardedBy("mLock")
private final ArrayMap<ProximityActiveListener, ProximityListenerProxy> mProximityListeners =
new ArrayMap<>();
@GuardedBy("mLock")
private Future<?> mSensorServiceStart;
@GuardedBy("mLock")
private long mPtr;
/** Start the sensor service. This is a blocking call and can take time. */
private static native long startSensorServiceNative(ProximityActiveListener listener);
private static native void registerProximityActiveListenerNative(long ptr);
private static native void unregisterProximityActiveListenerNative(long ptr);
public SensorService(Context ctx) {
super(ctx);
synchronized (mLock) {
mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
traceLog.traceBegin(START_NATIVE_SENSOR_SERVICE);
long ptr = startSensorServiceNative(new ProximityListenerDelegate());
synchronized (mLock) {
mPtr = ptr;
}
traceLog.traceEnd();
}, START_NATIVE_SENSOR_SERVICE);
}
}
@Override
public void onStart() {
LocalServices.addService(SensorManagerInternal.class, new LocalService());
}
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE) {
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart,
START_NATIVE_SENSOR_SERVICE);
synchronized (mLock) {
mSensorServiceStart = null;
}
}
}
class LocalService extends SensorManagerInternal {
@Override
public void addProximityActiveListener(@NonNull Executor executor,
@NonNull ProximityActiveListener listener) {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(listener, "listener must not be null");
ProximityListenerProxy proxy = new ProximityListenerProxy(executor, listener);
synchronized (mLock) {
if (mProximityListeners.containsKey(listener)) {
throw new IllegalArgumentException("listener already registered");
}
mProximityListeners.put(listener, proxy);
if (mProximityListeners.size() == 1) {
registerProximityActiveListenerNative(mPtr);
}
}
}
@Override
public void removeProximityActiveListener(@NonNull ProximityActiveListener listener) {
Objects.requireNonNull(listener, "listener must not be null");
synchronized (mLock) {
ProximityListenerProxy proxy = mProximityListeners.remove(listener);
if (proxy == null) {
throw new IllegalArgumentException(
"listener was not registered with sensor service");
}
if (mProximityListeners.isEmpty()) {
unregisterProximityActiveListenerNative(mPtr);
}
}
}
}
private static class ProximityListenerProxy implements ProximityActiveListener {
private final Executor mExecutor;
private final ProximityActiveListener mListener;
ProximityListenerProxy(Executor executor, ProximityActiveListener listener) {
mExecutor = executor;
mListener = listener;
}
@Override
public void onProximityActive(boolean isActive) {
mExecutor.execute(() -> mListener.onProximityActive(isActive));
}
}
private class ProximityListenerDelegate implements ProximityActiveListener {
@Override
public void onProximityActive(boolean isActive) {
final ProximityListenerProxy[] listeners;
// We can't call out while holding the lock because clients might be calling into us
// while holding their own locks (e.g. when registering / unregistering their
// listeners).This would break lock ordering and create deadlocks. Instead, we need to
// copy the listeners out and then only invoke them once we've dropped the lock.
synchronized (mLock) {
listeners = mProximityListeners.values().toArray(new ProximityListenerProxy[0]);
}
for (ProximityListenerProxy listener : listeners) {
listener.onProximityActive(isActive);
}
}
}
}
最后的代码就是Core 提供给我们使用的 API 了,这里就不在详细列出。
其实在 Android 中 还可以直接调用 一个驱动,当然这针对的是比较简单的子系统,这些系统并没有存在硬件抽象层,也就是说,实现硬件抽象的功能部分不在单独的代码中。例如 由JNi 代码直接调用的驱动程序的设备节点或者使用SYS 文件系统。
文章摘自:
android底层接口可驱动开发技术详解资料