人们在日常生活中经常用到传感器,例如,楼宇的楼梯灯、马路上的路灯等。那么手机中的传感器尤其到什么作用呢?在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底层接口可驱动开发技术详解资料










