补充《sensor service的初始化》中提到的onFirstRef
主要是在Android的HAL层对底层驱动封装
frameworks/native/services/sensorservice/SensorDevice.cpp
SensorDevice::SensorDevice()
: mSensorDevice(0),
mSensorModule(0)
{
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
ALOGE_IF(err, "couldn't load %s module (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorModule) {
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
ALOGE_IF(err, "couldn't open device for module %s (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorDevice) {
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
Info model;
for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list[i].handle, model);
mSensorDevice->activate(
reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
list[i].handle, 0);
}
}
}
}
hardware/libhardware/include/hardware/sensors.h
#define SENSORS_HARDWARE_MODULE_ID "sensors"
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
struct sensors_module_t {
struct hw_module_t common;
/**
* Enumerate all available sensors. The list is returned in "list".
* @return number of sensors in the list
*/
int (*get_sensors_list)(struct sensors_module_t* module,
struct sensor_t const** list);
};
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, (struct hw_device_t**)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, (struct hw_device_t**)device);
}
static inline int sensors_close_1(sensors_poll_device_1_t* device) {
return device->common.close(&device->common);
}
hardware/libhardware/hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
int status;
int i;
const struct hw_module_t *hmi = NULL;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new copy of the library).
* We also assume that dlopen() is thread-safe.
*/
/* Loop through the configuration variants looking for a module */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
if (i < HAL_VARIANT_KEYS_COUNT) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH2, name);
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
}
}
status = -ENOENT;
if (i < HAL_VARIANT_KEYS_COUNT+1) {
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
status = load(class_id, path, module);
}
return status;
}
/**
* There are a set of variant filename for modules. The form of the filename
* is "<MODULE_ID>.variant.so" so for the led module the Dream variants
* of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
*
* led.trout.so
* led.msm7k.so
* led.ARMV6.so
* led.default.so
*/
static const char *variant_keys[] = {
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
/** Base path of the hal modules */
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
/**
* Load the file defined by the variant and if successful
* return the dlopen handle and the hmi.
* @return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
hardware/libhardware/include/hardware/hardware.h
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
uint16_t module_api_version;
#define version_major module_api_version
uint16_t hal_api_version;
#define version_minor hal_api_version
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_t;
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
uint32_t version;
/** reference to the module this device belongs to */
struct hw_module_t* module;
/** padding reserved for future use */
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
#define HAL_MODULE_INFO_SYM HMI
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
以device/samsung/manta/libsensors/sensors.cpp实现为例
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Samsung Sensor module",
author: "Samsung Electronic Company",
methods: &sensors_module_methods,
dso: 0,
reserved: {},
},
get_sensors_list: sensors__get_sensors_list,
};
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors
};
/** Open a new instance of a sensor device using name */
static int open_sensors(const struct hw_module_t* module, const char* id,
struct hw_device_t** device)
{
FUNC_LOG;
int status = -EINVAL;
sensors_poll_context_t *dev = new sensors_poll_context_t();
if (!dev->isValid()) {
ALOGE("Failed to open the sensors");
return status;
}
memset(&dev->device, 0, sizeof(sensors_poll_device_t));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
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;
*device = &dev->device.common;
status = 0;
return status;
}
struct sensors_poll_context_t {
struct sensors_poll_device_t device; // must be first
sensors_poll_context_t();
~sensors_poll_context_t();
int activate(int handle, int enabled);
int setDelay(int handle, int64_t ns);
int pollEvents(sensors_event_t* data, int count);
// Will return true if the constructor completed
bool isValid() { return mInitialized; };
private:
// Will be true if the constructor completed
bool mInitialized;
enum {
mpl = 0,
compass,
#ifdef ENABLE_DMP_DISPL_ORIENT_FEAT
dmpOrient,
#endif
light,
pressure,
numSensorDrivers, // wake pipe goes here
numFds,
};
static const size_t wake = numFds - 1;
static const char WAKE_MESSAGE = 'W';
struct pollfd mPollFds[numFds];
int mWritePipeFd;
SensorBase* mSensors[numSensorDrivers];
int handleToDriver(int handle) const {
switch (handle) {
case ID_RV:
case ID_LA:
case ID_GR:
case ID_GY:
case ID_RG:
case ID_A:
case ID_M:
case ID_O:
return mpl;
#ifdef ENABLE_DMP_DISPL_ORIENT_FEAT
case ID_SO:
return dmpOrient;
#endif
case ID_L:
return light;
case ID_PR:
return pressure;
}
return -EINVAL;
}
};
sensors_poll_context_t::sensors_poll_context_t()
{
FUNC_LOG;
CompassSensor *p_compasssensor = new CompassSensor();
MPLSensor *p_mplsen = new MPLSensor(p_compasssensor);
mInitialized = false;
// Must clean this up early or else the destructor will make a mess.
memset(mSensors, 0, sizeof(mSensors));
setCallbackObject(p_mplsen); //setup the callback object for handing mpl callbacks
numSensors =
LOCAL_SENSORS +
p_mplsen->populateSensorList(sSensorList + LOCAL_SENSORS,
sizeof(sSensorList[0]) * (ARRAY_SIZE(sSensorList) - LOCAL_SENSORS));
mSensors[mpl] = p_mplsen;
mPollFds[mpl].fd = mSensors[mpl]->getFd();
mPollFds[mpl].events = POLLIN;
mPollFds[mpl].revents = 0;
mSensors[compass] = p_mplsen;
mPollFds[compass].fd = ((MPLSensor*)mSensors[mpl])->getCompassFd();
mPollFds[compass].events = POLLIN;
mPollFds[compass].revents = 0;
#ifdef ENABLE_DMP_DISPL_ORIENT_FEAT
mPollFds[dmpOrient].fd = ((MPLSensor*)mSensors[mpl])->getDmpOrientFd();
mPollFds[dmpOrient].events = POLLPRI;
mPollFds[dmpOrient].revents = 0;
#endif
mSensors[light] = new LightSensor();
mPollFds[light].fd = mSensors[light]->getFd();
mPollFds[light].events = POLLIN;
mPollFds[light].revents = 0;
mSensors[pressure] = new PressureSensor();
mPollFds[pressure].fd = mSensors[pressure]->getFd();
mPollFds[pressure].events = POLLIN;
mPollFds[pressure].revents = 0;
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[wake].fd = wakeFds[0];
mPollFds[wake].events = POLLIN;
mPollFds[wake].revents = 0;
mInitialized = true;
}
hardware/libhardware/include/hardware/sensors.h
/*
* sensors_poll_device_t is used with SENSORS_DEVICE_API_VERSION_0_1
* and is present for backward binary and source compatibility.
* (see documentation of the hooks in struct sensors_poll_device_1 below)
*/
struct sensors_poll_device_t {
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 ns);
int (*poll)(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count);
};
/*
* struct sensors_poll_device_1 is used with SENSORS_DEVICE_API_VERSION_1_0
*/
typedef struct sensors_poll_device_1 {
union {
/* sensors_poll_device_1 is compatible with sensors_poll_device_t,
* and can be down-cast to it
*/
struct sensors_poll_device_t v0;
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);
} sensors_poll_device_1_t;
device/samsung/manta/libsensors/sensors.cpp
/* The SENSORS Module */
#define LOCAL_SENSORS 2
static struct sensor_t sSensorList[LOCAL_SENSORS + MPLSensor::numSensors] = {
{ "BH1721fvc Light sensor",
"Rohm",
1, SENSORS_LIGHT_HANDLE,
SENSOR_TYPE_LIGHT, 65528.0f, 1.0f, 0.20f, 16000, 0, 0, { } },
{ "BMP182 Pressure sensor",
"Bosch",
1, SENSORS_PRESSURE_HANDLE,
SENSOR_TYPE_PRESSURE, 1100.0f, 0.01f, 0.06f, 50000, 0, 0, { } },
};
static int numSensors = LOCAL_SENSORS;
#define SENSORS_ROTATION_VECTOR_HANDLE (ID_RV)
#define SENSORS_LINEAR_ACCEL_HANDLE (ID_LA)
#define SENSORS_GRAVITY_HANDLE (ID_GR)
#define SENSORS_GYROSCOPE_HANDLE (ID_GY)
#define SENSORS_RAW_GYROSCOPE_HANDLE (ID_RG)
#define SENSORS_ACCELERATION_HANDLE (ID_A)
#define SENSORS_MAGNETIC_FIELD_HANDLE (ID_M)
#define SENSORS_ORIENTATION_HANDLE (ID_O)
#define SENSORS_LIGHT_HANDLE (ID_L)
#define SENSORS_PROXIMITY_HANDLE (ID_P)
#define SENSORS_PRESSURE_HANDLE (ID_PR)
static int sensors__get_sensors_list(struct sensors_module_t* module,
struct sensor_t const** list)
{
*list = sSensorList;
return numSensors;
}
SensorDevice的方法,其具体的实现全部由mSensorDevice 封装的设备操作接口函数实现,这些设备操作接口在HAL层实现,其实SensorDevice只是SensorService的设备操作对象,封装了设备的操作,而这些操作实际“干活的”的是HAL层代码。
更多sensors可以参考cubieboard2的android代码:
device/softwinner/common/hardware/libsensors/{AccelSensor.cpp,GyroSensor.cpp,LightSensor.cpp,MagnetoSensor.cpp,MagSensor.cpp,PressSensor.cpp,ProximitySensor.cpp,TempSensor.cpp}
以及模拟器的实现:
development/tools/emulator/system/sensors/sensors_qemu.c
sdk/emulator/sensors/sensors_qemu.c
device/generic/goldfish/sensors/sensors_qemu.c
android版本不同,可能位于上面3个位置