补充《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个位置