Android Sensor Input類型 (四) Sensor HAL 實現


msm8909 Sensor HAL

代碼路徑:code/hardware/qcom/sensors/

核心作用:封裝對 sensor的方法,不直接通過本地C庫直接訪問

點擊展開 全部文件

├── Accelerometer.cpp
├── AccelSensor.h
├── AkmSensor.cpp
├── AkmSensor.h
├── algo                
├── Android.mk
├── Bmp180.cpp
├── CalibrationManager.cpp
├── CalibrationManager.h
├── CalibrationModule.h
├── calmodule.cfg
├── CompassSensor.cpp
├── CompassSensor.h
├── Gyroscope.cpp
├── GyroSensor.h
├── InputEventReader.cpp
├── InputEventReader.h
├── LICENSE
├── LightSensor.cpp
├── LightSensor.h
├── NativeSensorManager.cpp
├── NativeSensorManager.h
├── PressureSensor.h
├── ProximitySensor.cpp
├── ProximitySensor.h
├── SensorBase.cpp
├── SensorBase.h
├── sensors.cpp
├── sensors_extension.h
├── sensors.h
├── sensors_XML.cpp
├── sensors_XML.h
├── SignificantMotion.cpp
├── SignificantMotion.h
├── VirtualSensor.cpp
└── VirtualSensor.h
  

重要文件有:

sensors.cpp

sensors.cpp 中提供數據機構架構,提供 hw_device_t 封裝; 讓其他層可以獲得這個結構,得以使用其中的方法;

通過實現的結構可以發現,所有的操作都使用了, NativeSensorManager用來做具體的操作

NativeSensorManager.cpp

Native SensorManager 是個class,繼承Singleton; 單例模式,只存在一個對象;

即被多次定義引用的對象 sm; 它的存在是統一管理sensor HAL的sensor訪問;

將存在的sensor統一存在數組里,不針對sensor具體類型; 是HAL的實際操作者;

SensorBase.cpp

VirtualSensor.cpp

sensors主要設備結構

sensor_t

struct sensor_t {
    const char*     name;
 //!< sensor名稱 By: jixuan
    const char*     vendor;
 //!< 廠商名 By: jixuan 
    int             version;
    int             handle
    int             type;
 //!< 類型標識 By: jixuan
    float           maxRange;
    float           resolution;
 //!< 解析度 即報告數值的最大差異范圍 By: jixuan 
    float           power;
    int32_t         minDelay;

    uint32_t        fifoReservedEventCount;
    uint32_t        fifoMaxEventCount;
 //!< 類型字符串 Note By: yujixuan 
    const char*    stringType;
 //!< 權限 Note By: yujixuan 
    const char*    requiredPermission;

    void*           reserved[2];
};

sensor_moudule_t

struct sensors_module_t {
    struct hw_module_t common;
 //!< hw_module_t 基礎結構 >! NoteBy: yujixuan 
    int (*get_sensors_list)(struct sensors_module_t* module,
            struct sensor_t const** list);
 //!< 拓展接口,獲取sensor 列表 >! NoteBy:yujixuan
    int (*set_operation_mode)(unsigned int mode);
 //!< 操作設置sensor mode >! NoteBy: yujixuan
};



//!< 定義 名為HMI的 hw_module_t 結構體(可以轉型為包含它的具體設備類型,首地址保持相同),get_module 獲取它 >! NoteBy: yujixuan
struct sensors_module_t HAL_MODULE_INFO_SYM = {
        common: {
                tag: HARDWARE_MODULE_TAG,  //!< 固定名 >! NoteBy: yujixuan
                version_major: 1,
                version_minor: 0,
                id: SENSORS_HARDWARE_MODULE_ID, 
                name: "Quic Sensor module",
                author: "Quic",
                methods: &sensors_module_methods,  //!< hw_module_t 必要填充的方法 >! NoteBy: yujixuan
                dso: NULL,
                reserved: {0},
        },
        get_sensors_list: sensors__get_sensors_list,  //!< sensor_module_t 拓展的方法 >! NoteBy: yujixuan
};
static struct hw_module_methods_t sensors_module_methods = {
        open: open_sensors  //!< 只有一個open函數,它的作用是返回具體的 device >! NoteBy: yujixuan
};
//!< 打開一個新的sensor 實例 填充具體的hw_device_t>! NoteBy: yujixuan

open函數實現:open_sensors

#define HAL_MODULE_INFO_SYM        HMI
#define HAL_MODULE_INFO_SYM_AS_STR  "HMI"


static int open_sensors(const struct hw_module_t* module, const char*,
						struct hw_device_t** device)
{
		int status = -EINVAL;
		sensors_poll_context_t *dev = new sensors_poll_context_t();
		NativeSensorManager& sm(NativeSensorManager::getInstance());

		memset(&dev->device, 0, sizeof(sensors_poll_device_1_ext_t));

		dev->device.common.tag = HARDWARE_DEVICE_TAG;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
		ALOGI("Sensors device API version 1.3 supported\n");
		dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
#else
		dev->device.common.version = SENSORS_DEVICE_API_VERSION_0_1;
#endif
		dev->device.common.module   = const_cast<hw_module_t*>(module);
		dev->device.common.close	= poll__close;
		dev->device.activate		= poll__activate;
		dev->device.setDelay		= poll__setDelay;
		dev->device.poll		= poll__poll;
		dev->device.calibrate		= poll_calibrate;
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
		dev->device.batch		= poll__batch;
		dev->device.flush		= poll__flush;
#endif

		*device = &dev->device.common;
		status = 0;

		return status;
}

open_sensors新的sensor 實例,首先new了一個sensors_poll_context_tdevice ,然后設置該device,並返回 給到調用者;

針對 sensors_poll_context_t 下面內容會做具體分析;

static int sensors__get_sensors_list(struct sensors_module_t*,
								 struct sensor_t const** list)
{
	NativeSensorManager& sm(NativeSensorManager::getInstance());

	return sm.getSensorList(list);
}

拓展的sensors_module_t 中添加了 get_sensor_list方法;

可以看到它是通過NativeSensorManger 來做具體的Hal層訪問;

Sensor服務用戶程序不能直接訪問,通過NativeSensorManager來訪問。 (note: nativeSensorManager是指在HAL中的管理sensor的設備結構,需要區別於Android Framework中的SensorManager)

里面使用了NativeSensorManagersensors__get_sensors_list函數中調用單例模式創建了一個實例sm,通過調用其中的成員函數獲取傳感器列表,並返回,返回值對應的sensor_t結構體;NativeSensorManager統一管理着所有的傳感器、物理和虛擬傳感器;

SensorHAL 解析

Native Sensor Hal框架中,最為主要的內容即是 open函數中對device的回調設置;簡單的可以理解為是上層函數與調用底層驅動的橋接;

所以在Hal這個層次應着重分析這塊內容;,由上可知,當前的代碼里是通過sensors_poll_context_t來定義一個device; 以下是 sensors_poll_context_t 的內容:

sensors_poll_context_t

struct sensors_poll_context_t {
	// extension for sensors_poll_device_1, must be first
	struct sensors_poll_device_1_ext_t device;// must be first
	 //!< 必須放在首個位置,它是個聯合體,首個屬性是 hw_device_t; >! NoteBy: yujixuan
	sensors_poll_context_t();
	~sensors_poll_context_t();
     //!<struct同樣有構造函數,析構函數,完成重要的初始化功能 >! NoteBy: yujixuan
	int activate(int handle, int enabled);
	int setDelay(int handle, int64_t ns);
	int pollEvents(sensors_event_t* data, int count);
	int calibrate(int handle, cal_cmd_t *para);
	int batch(int handle, int sample_ns, int latency_ns);
	int flush(int handle);

private:
	static const size_t wake = MAX_SENSORS;
	static const char WAKE_MESSAGE = 'W';
	struct pollfd mPollFds[MAX_SENSORS+1];
	int mWritePipeFd;
	SensorBase* mSensors[MAX_SENSORS];
	mutable Mutex mLock;
};

通過open函數返回的的是hw_device_t,實際是傳入的地址值;只要保證,包含此結構,且sensors_poll_device_1_ext_t放在首位,可以向上轉型回具體的sensor

設備device;

實際device的函數調用 都是拓展的;比如上面的 activate; setDelay; pollEvents;等;

struct sensors_poll_device_1_ext_t {
    union {

        struct sensors_poll_device_1 aosp;
        struct {
            struct hw_device_t common;
            int (*activate)(struct sensors_poll_device_t *dev,
                    int handle, int enabled);
            int (*setDelay)(struct sensors_poll_device_t *dev,
                    int handle, int64_t period_ns);
            int (*poll)(struct sensors_poll_device_t *dev,
                    sensors_event_t* data, int count);
            int (*batch)(struct sensors_poll_device_1* dev,
                    int handle, int flags, int64_t period_ns, int64_t timeout);
            int (*flush)(struct sensors_poll_device_1* dev, int handle);
            void (*reserved_procs[8])(void);
        };
    };

struct sensors_poll_device_t {
    struct hw_device_t common;
    int (*activate)(struct sensors_poll_device_t *dev,
            int sensor_handle, int enabled);
    int (*setDelay)(struct sensors_poll_device_t *dev,
            int sensor_handle, int64_t sampling_period_ns);
    int (*poll)(struct sensors_poll_device_t *dev,
            sensors_event_t* data, int count);
};

通過sensors_poll_device_1_ext_t也可以看出,實際sensors_poll_context_t 可以是sensors_poll_device_t

這是面向對象 多態的思想方式; 獲取到的device根據具體的類型,再轉換為具體的 device進行函數調用;

實際device的函數調用 都是拓展的;比如上面的 activate; setDelay; pollEvents;等;

在open函數中,new一個實例對象;sensors_poll_context_t會調用其構造函數完成最重要的初始化功能,如下:

sensors_poll_context_t::sensors_poll_context_t()
{
	int number;
	int i;
	const struct sensor_t *slist; 
	const struct SensorContext *context;
	NativeSensorManager& sm(NativeSensorManager::getInstance());

	number = sm.getSensorList(&slist);
    //!< 獲取sensor個數; 與sensor構成的鏈表list >! NoteBy: yujixuan
	/* use the dynamic sensor list */
	for (i = 0; i < number; i++) {
		context = sm.getInfoByHandle(slist[i].handle);

		mPollFds[i].fd = (context == NULL) ? -1 : context->data_fd;
		mPollFds[i].events = POLLIN;
		mPollFds[i].revents = 0;
	}

	ALOGI("The avaliable sensor handle number is %d",i);
	int wakeFds[2];
	int result = pipe(wakeFds);
	ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
	fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
	fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
	mWritePipeFd = wakeFds[1];

	mPollFds[number].fd = wakeFds[0];
	mPollFds[number].events = POLLIN;
	mPollFds[number].revents = 0;
}

構造函數中,通過NativeSensorManager 獲取了sensor 列表;

通過struct SensorContext *context;

context = sm.getInfoByHandle(slist[i].handle); 

維系記錄了handle對應的SensorContext對象指針的句柄;SensorContext 的結構如下:

SensorContext

struct SensorContext {
	char   name[SYSFS_MAXLEN]; // name of the sensor
	char   vendor[SYSFS_MAXLEN]; // vendor of the sensor
	char   enable_path[PATH_MAX]; // the control path of this sensor
	char   data_path[PATH_MAX]; // the data path to get sensor events

	struct sensor_t *sensor; // point to the sensor_t structure in the sensor list
	SensorBase     *driver; // point to the sensor driver instance

	int data_fd; // the file descriptor of the data device node
	int enable; // indicate if the sensor is enabled
	bool is_virtual; // indicate if this is a virtual sensor
	int64_t delay_ns; // the poll delay setting of this sensor
	int64_t latency_ns; // the max report latency of this sensor
	struct listnode dep_list; // the background sensor type needed for this sensor

	struct listnode listener; // the head of listeners of this sensor
};

從上可以看出: SensorContext中的 SensorBase *driver; 指向了具體的sensor實例;

在構造函數中,還完成了pollfd即mPollFds用來監聽senso時用的文件描述符;

open函數的后面的部分,也就是對sensors_poll_context_t 拓展的那些方法的鏈接;

比如:

        dev->device.common.close    = poll__close;
        dev->device.activate        = poll__activate;
        dev->device.setDelay        = poll__setDelay;
        dev->device.poll        = poll__poll;
        dev->device.calibrate        = poll_calibrate;

poll函數分析

這里分析下,最重要的一個函數 poll__poll;

static int poll__poll(struct sensors_poll_device_t *dev,
		sensors_event_t* data, int count) {
	sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
 //!< 這里就用到了 向上轉型;將sensor_poll_device_t 轉為 sensor_poll_context_t >! NoteBy: yujixuan
	return ctx->pollEvents(data, count);
 //!< 返回pollEvents >! NoteBy: yujixuan
}
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
	int nbEvents = 0;
	int n = 0;
	NativeSensorManager& sm(NativeSensorManager::getInstance());
	const sensor_t *slist;
	int number = sm.getSensorList(&slist);

	do {
		// see if we have some leftover from the last poll()
		for (int i = 0 ; count && i < number ; i++) {
			if ((mPollFds[i].revents & POLLIN) || (sm.hasPendingEvents(slist[i].handle))) {
				Mutex::Autolock _l(mLock);
				int nb = sm.readEvents(slist[i].handle, data, count);
				if (nb < 0) {
					ALOGE("readEvents failed.(%d)", errno);
					return nb;
				}
				if (nb <= count) {
					// no more data for this sensor
					mPollFds[i].revents = 0;
				}
				count -= nb;
				nbEvents += nb;
				data += nb;
			}
		}

		if (count) {
			// we still have some room, so try to see if we can get
			// some events immediately or just wait if we don't have
			// anything to return
			do {
				n = poll(mPollFds, number + 1, nbEvents ? 0 : -1);
			} while (n < 0 && errno == EINTR);
			if (n<0) {
				ALOGE("poll() failed (%s)", strerror(errno));
				return -errno;
			}
			if (mPollFds[number].revents & POLLIN) {
				char msg;
				int result = read(mPollFds[number].fd, &msg, 1);
				ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
				ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
				mPollFds[number].revents = 0;
			}
		}
		// if we have events and space, go read them
	} while (n && count);

	return nbEvents;
}

主要函數:sm.readEvents(slist[i].handle, data, count);

NativeSensorManager::readEvents中調用了:

nb = list->driver->readEvents(data, count);

list->driver是一個SensorBase結構體,SensorBase結構體的函數readEvents,

這里就需要聯合 nativesensormanger的實現來看具體的讀取流程;

nativesensormanger相關內容,在后續的內容中分析;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM