Android sensorservice

sensorservice在systemserver进程中启动。
 private void startBootstrapServices() {
    ...
    startSensorService();
 }

startsensorService是一个native函数,其具体实现在com_android_server_SystemServer.cpp的android_server_SystemServer_startSensorService函数中。

static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }
}

SensorService::instantiate()instantiate函数定义在BinderService.h中,目的在于向ServiceManager注册SensorService组件。

static void instantiate() { publish(); }

static status_t publish(bool allowIsolated = false) {
        sp<IServiceManager> sm(defaultServiceManager());
        return sm->addService(
                String16(SERVICE::getServiceName()),
                new SERVICE(), allowIsolated);
    }
onFirstRef函数来自RefBase,在第一次被强指针引用时调用。

void SensorService::onFirstRef()
{
    ALOGD("nuSensorService starting...");
    SensorDevice& dev(SensorDevice::getInstance());

    if (dev.initCheck() == NO_ERROR) {
        sensor_t const* list;
        ssize_t count = dev.getSensorList(&list);
        if (count > 0) {
            ssize_t orientationIndex = -1;
            bool hasGyro = false, hasAccel = false, hasMag = false;
            uint32_t virtualSensorsNeeds =
                    (1<<SENSOR_TYPE_GRAVITY) |
                    (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
                    (1<<SENSOR_TYPE_ROTATION_VECTOR);

            mLastEventSeen.setCapacity(count);
            for (ssize_t i=0 ; i<count ; i++) {
                registerSensor( new HardwareSensor(list[i]) );
                switch (list[i].type) {
                    case SENSOR_TYPE_ACCELEROMETER:
                        hasAccel = true;
                        break;
                    case SENSOR_TYPE_MAGNETIC_FIELD:
                        hasMag = true;
                        break;
                    case SENSOR_TYPE_ORIENTATION:
                        orientationIndex = i;
                        break;
                    case SENSOR_TYPE_GYROSCOPE:
                    case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                        hasGyro = true;
                        break;
                    case SENSOR_TYPE_GRAVITY:
                    case SENSOR_TYPE_LINEAR_ACCELERATION:
                    case SENSOR_TYPE_ROTATION_VECTOR:
                        virtualSensorsNeeds &= ~(1<<list[i].type);
                        break;
                }
            }

            // it's safe to instantiate the SensorFusion object here
            // (it wants to be instantiated after h/w sensors have been
            // registered)
            const SensorFusion& fusion(SensorFusion::getInstance());

            // build the sensor list returned to users
            mUserSensorList = mSensorList;

            if (hasGyro && hasAccel && hasMag) {
                Sensor aSensor;

                // Add Android virtual sensors if they're not already
                // available in the HAL

                aSensor = registerVirtualSensor( new RotationVectorSensor() );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new GravitySensor(list, count) );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new OrientationSensor() );
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    // if we are doing our own rotation-vector, also add
                    // the orientation sensor and remove the HAL provided one.
                    mUserSensorList.replaceAt(aSensor, orientationIndex);
                }

                // virtual debugging sensors are not added to mUserSensorList
                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
                registerVirtualSensor( new GyroDriftSensor() );
            }

            // debugging sensor list
            mUserSensorListDebug = mSensorList;

            // Check if the device really supports batching by looking at the FIFO event
            // counts for each sensor.
            bool batchingSupported = false;
            for (size_t i = 0; i < mSensorList.size(); ++i) {
                if (mSensorList[i].getFifoMaxEventCount() > 0) {
                    batchingSupported = true;
                    break;
                }
            }

            if (batchingSupported) {
                // Increase socket buffer size to a max of 100 KB for batching capabilities.
                mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
            } else {
                mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
            }

            // Compare the socketBufferSize value against the system limits and limit
            // it to maxSystemSocketBufferSize if necessary.
            FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
            char line[128];
            if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
                line[sizeof(line) - 1] = '\0';
                size_t maxSystemSocketBufferSize;
                sscanf(line, "%zu", &maxSystemSocketBufferSize);
                if (mSocketBufferSize > maxSystemSocketBufferSize) {
                    mSocketBufferSize = maxSystemSocketBufferSize;
                }
            }
            if (fp) {
                fclose(fp);
            }

            mWakeLockAcquired = false;
            mLooper = new Looper(false);
            const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
            mSensorEventBuffer = new sensors_event_t[minBufferSize];
            mSensorEventScratch = new sensors_event_t[minBufferSize];
            mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
            mCurrentOperatingMode = NORMAL;

            mNextSensorRegIndex = 0;
            for (int i = 0; i < SENSOR_REGISTRATIONS_BUF_SIZE; ++i) {
                mLastNSensorRegistrations.push();
            }

            mInitCheck = NO_ERROR;
            mAckReceiver = new SensorEventAckReceiver(this);
            mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
            run("SensorService", PRIORITY_URGENT_DISPLAY);
        }
    }
}

首先获得一个SensorDevice单例对象,先看看SensorDevice的默认构造函数:

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) {
            if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||
                mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {
                ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3");
            }

            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);
            }
        }
    }
}

谷歌为Sensor提供了统一的HAL接口,方便厂商根据该接口完成具体的硬件抽象层,接口文件在/hardware/libhardware/include/hardware/Sensors.h中。首先将

sensors_poll_device_1*类型的mSensorDevice和sensors_module_t*类型的mSensorModule成员变量设为0,这两个类型定义在Sensor.h中。sensors_module_t类型是对

hw_module_t类型的封装外加一个get_sensors_list函数。sensors_poll_device_l是对hw_device_t类型的封装外加poll(多路监听方法),activate(设备激活方法)和

setDelay(设备延迟方法)。hw_get_module是jni层获取HAL层module的接口函数,原型为hareware.c中的:int hw_get_module(const char *id, const struct

 hw_module_t **module),第一个参数为硬件模块的id,第二个参数指向硬件模块对应的hw_module_t结构体地址(symbol地址)。

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;

            /* Activate/de-activate one sensor. Return 0 on success, negative
             *
             * sensor_handle is the handle of the sensor to change.
             * enabled set to 1 to enable, or 0 to disable the sensor.
             *
             * Return 0 on success, negative errno code otherwise.
             */
            int (*activate)(struct sensors_poll_device_t *dev,
                    int sensor_handle, int enabled);

            /**
             * Set the events's period in nanoseconds for a given sensor.
             * If sampling_period_ns > max_delay it will be truncated to
             * max_delay and if sampling_period_ns < min_delay it will be
             * replaced by min_delay.
             */
            int (*setDelay)(struct sensors_poll_device_t *dev,
                    int sensor_handle, int64_t sampling_period_ns);

            /**
             * Returns an array of sensor data.
             */
            int (*poll)(struct sensors_poll_device_t *dev,
                    sensors_event_t* data, int count);
        };
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);

    /**
     *  Place the module in a specific mode. The following modes are defined
     *
     *  0 - Normal operation. Default state of the module.
     *  1 - Loopback mode. Data is injected for the the supported
     *      sensors by the sensor service in this mode.
     * @return 0 on success
     *         -EINVAL if requested mode is not supported
     *         -EPERM if operation is not allowed
     */
    int (*set_operation_mode)(unsigned int mode);
};
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 i = 0;
    char prop[PATH_MAX] = {0};
    char path[PATH_MAX] = {0};
    char name[PATH_MAX] = {0};
    char prop_name[PATH_MAX] = {0};


    if (inst)
        snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
    else
        strlcpy(name, class_id, PATH_MAX);//class_id拷贝到name

    /*
     * 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.
     */

    /* First try a property specific to the class and possibly instance */
    snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);//prop为ro.hardware.(name)
    if (property_get(prop_name, prop, NULL) > 0) {//获取prop_name的属性值,保存在prop中
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {//path为/system/lib/hw/(name).(prop).so或者/vendor/lib/hw/(name).(prop).so
	{
            goto found;
        }
    }

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
        if (property_get(variant_keys[i], prop, NULL) == 0) {
            continue;
        }
        if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
            goto found;
        }
    }

    /* Nothing found, try the default */
    if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
        goto found;
    }

    return -ENOENT;

found:
    /* load the module, if this fails, we're doomed, and we should not try
     * to load a different variant. */
    return load(class_id, path, module);
}

编译好的模块文件位于out/target/product/generic/system/lib/hw(对应设备上的/system/lib/hw;/vendor/lib/hw保存设备厂商提供的HAL层模块接口文件。hw_module_exists

函数作用在于检查HAL模块接口文件是否存在。

static int load(const char *id,
        const char *path,
        const struct hw_module_t **pHmi)
{
    int status = -EINVAL;
    void *handle = NULL;
    struct hw_module_t *hmi = NULL;

    /*
     * 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;
}

HAL层模块文件实际上是.so文件。dlopen以指定模式打开动态库文件,RTLD_NOW 表示立即决定,返回前解除所有未决定的符号,返回一个句柄给进程。dlsym接收句柄

和符号两个参数,返回符号的地址,并使用load函数的第三个参数指向这个符号的地址。其中HAL_MODULE_INFO_SYM_AS_STR的值为“HMI",这样便从HMI的符号确定

hw_module_t结构体的指针。根据HAL模块的编写规范,每个HAL层模块都必须包含一个名为“HMI"的符号,而且这个符号的第一个成员变量的类型必须为hw_module_t。

经过上述的分析可以知道,SensorDevice加载了sensorHAL层的动态库。然后使用sensors_open_l打开设备:

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);
}

调用hw_module_t的methods成员的open成员函数打开设备。其中hw_module_t和hw_module_method_t定义如下:

typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    uint32_t tag;

    /**
     * The API version of the implemented module. The module owner is
     * responsible for updating the version when a module interface has
     * changed.
     *
     * The derived modules such as gralloc and audio own and manage this field.
     * The module user must interpret the version field to decide whether or
     * not to inter-operate with the supplied module implementation.
     * For example, SurfaceFlinger is responsible for making sure that
     * it knows how to manage different versions of the gralloc-module API,
     * and AudioFlinger must know how to do the same for audio-module API.
     *
     * The module API version should include a major and a minor component.
     * For example, version 1.0 could be represented as 0x0100. This format
     * implies that versions 0x0100-0x01ff are all API-compatible.
     *
     * In the future, libhardware will expose a hw_get_module_version()
     * (or equivalent) function that will take minimum/maximum supported
     * versions as arguments and would be able to reject modules with
     * versions outside of the supplied range.
     */
    uint16_t module_api_version;
#define version_major module_api_version
    /**
     * version_major/version_minor defines are supplied here for temporary
     * source code compatibility. They will be removed in the next version.
     * ALL clients must convert to the new version format.
     */

    /**
     * The API version of the HAL module interface. This is meant to
     * version the hw_module_t, hw_module_methods_t, and hw_device_t
     * structures and definitions.
     *
     * The HAL interface owns this field. Module users/implementations
     * must NOT rely on this value for version information.
     *
     * Presently, 0 is the only valid value.
     */
    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;

#ifdef __LP64__
    uint64_t reserved[32-7];
#else
    /** padding to 128 bytes, reserved for future use */
    uint32_t reserved[32-7];
#endif

} hw_module_t;

typedef struct hw_module_methods_t {
    /** Open a specific device */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

} hw_module_methods_t;

由于一个硬件抽象模块可能会包含多个硬件设备,因此在调用hw_module_method_t的open函数时需要指定硬件设备的id。sensors_open_l打开的设备id为

SENSORS_HARDWARE_POLL,在宏定义被定义成“poll",第三个参数device指向打开的设备对应的hw_device_t结构体指针。至此,mSensorModule保存了HAL模块对应

的hw_module_t结构体指针,mSensorDevice保存了hw_device_t指针。

在硬件抽象层模块的实现文件中(Sensors.cpp),有一个名字唯一的struct  sensor_module_t变量,名字为HAL_MODULE_INFO_SYM,以Mstar的Sensors.cpp(device目

录下)为例,实现如下。其中hw_module_t成员common的methods为sensors_module_methods指针,这个sensors_module_methods为struct hw_module_methods_t。

HAL_MODULE_INFO_SYM指定了HAL层函数get_sensors_list的本地实现为sensors__get_sensors_list。sensors_module_methods指定了HAL层函数open的本地实现为

open_sensors。

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 = "Nanosic Sensor module",
                .author = "Nanosic Tec 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
};


static int sensors__get_sensors_list(struct sensors_module_t* module,
                                     struct sensor_t const** list)
{
    UNUSE(module);
	LOGD("call sensors__get_sensors_list, numSensors = %d", numSensors);
    *list = sSensorList;
    return numSensors;
}
static struct sensor_t sSensorList[LOCAL_SENSORS] = {
	{ "Accelerometer Sensor",
	  "NGB TVOS",
	   1, SENSORS_ACCELERATION_HANDLE,
	   SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.3f, 0, 0, 0, 0, 0, 0, 0, {}},
	{ "Gyroscope Sensor",
	  "NGB TVOS",
	  1, SENSORS_GYROSCOPE_HANDLE,
	  SENSOR_TYPE_GYROSCOPE, RANGE_GYRO, CONVERT_GYRO, 6.1f, 0, 0, 0, 0, 0, 0, 0, {}},
};

来看下open_sensors的实现。首先new了一个struct sensors_poll_context_t的变量。structsensors_poll_context_t有一个struct sensors_poll_device_t的成员device。这里把

device进行初始化,主要是将HAL层的close,activate,setDelay和poll函数的本地实现指定为poll_close,poll_activate,poll_setDelay和poll_poll,使第二个参数指向

sensors_poll_context_t成员device的hw_device_t成员common。这样,sensors_poll_context_t的第一个成员是sensors_poll_device_t。sensors_poll_device_t的第一个成员是

hw_device_t,第二个参数保存的地址是hw_device_t的地址,也就是sensors_poll_device_t和sensors_poll_context_t的首地址。

static int open_sensors(const struct hw_module_t* module, const char* id,
                        struct hw_device_t** device)
{
    UNUSE(id);

    LOGD("open_sensors()");
    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  = SENSORS_DEVICE_API_VERSION_1_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; };


接着看下sensors_poll_context_t的构造函数。mSensors是一个SensorBase*指针数组,GamepadSensors,VirtualGamepadSensors均继承自SensorBase。这里就是

sensor放入到mSensors中,初始化三个pollfd,两个监听GamepadSensors和VirtualGamepadSensors的POLLIN事件。此外还创建了管道,监听管道的读端。

SendorBase除了将一些成员变量初始化外,还使用了openInput(mDataName)方法。以GamepadSensor为例,mDataName被初始化为”RealSensor"。openInput以

mDataName作为参数,查找/dev目录下名字带有“hidraw"的设备文件并打开。

 enum {
    	gamepad = 0,
		virtualGamepad,
        numSensorDrivers,       // wake pipe goes here
        numFds,
    };
int SensorBase::openInput(const char* inputName) {
    int fd = -1;
    mExtConnectedDevice = DeviceMax;
    if (std::string(REAL_SENSOR_NAME) == std::string(inputName)) {
        const char *dirname = "/dev";
        char devname[PATH_MAX];
        char *filename;
        DIR *dir;
        struct dirent *de;
        dir = opendir(dirname);
        if(dir == NULL)
            return -1;
        strcpy(devname, dirname);
        filename = devname + strlen(devname);
        *filename++ = '/';
        for (int i=0; i < DeviceMax; i++) {
            HidrawReportDescriptor *pRptDesc = &(sensorDataConfig[i].reportDescriptor);


            while((de = readdir(dir))) {
                if((de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0'))) ||
                        (std::string::npos == (std::string(de->d_name).find("hidraw"))))
                    continue;


                strcpy(filename, de->d_name);
                LOGD("devname = %s", devname);
                fd = open(devname, O_RDONLY);
                if (fd>=0) {
                    int desc_size = 0;
                    struct hidraw_report_descriptor rpt_desc;
                    memset(&rpt_desc, 0x0, sizeof(rpt_desc));
                    int res = ioctl(fd, HIDIOCGRDESCSIZE, &desc_size);
                    if (res < 0) {
                        close(fd);
                        fd = -1;
                        LOGD("!!!Failed: ioctl(fd, HIDIOCGRDESCSIZE, &desc_size)!!!");
                    } else {
                        rpt_desc.size = desc_size;
                        LOGD("success: ioctl(fd, HIDIOCGRDESCSIZE, &desc_size)");
                        if (rpt_desc.size <= 0) {
                            close(fd);
                            fd = -1;
                            LOGD("!!!rpt_desc.size <= 0!!!");
                            break;
                        }


                        res = ioctl(fd, HIDIOCGRDESC, &rpt_desc);
                        if (res < 0) {
                            close(fd);
                            fd = -1;
                            LOGD("!!!Failed: ioctl(fd, HIDIOCGRDESC, &rpt_desc)!!!");
                        } else {
                            LOGD("rpt_desc.size = %u", rpt_desc.size);
#if 0
                            printf("%s :rpt_desc.size = %u, rpt_desc.value: \n", devname, rpt_desc.size);
                            for (unsigned int j=0; j< rpt_desc.size; j++) {
                                printf("%2x ", rpt_desc.value[j]);
                            }
                            printf("\n");
#endif
                            ExtConnectedDevice extConnectedDevice = checkConnectedDeviceByReportDescriptor(rpt_desc);
                            if (extConnectedDevice < DeviceMax) {
                                mExtConnectedDevice = extConnectedDevice;
                                LOGD("______________________FIND REAL SENSOR______________________");
                                break;
                            } else {
                                close(fd);
                                fd = -1;
                                LOGD("!!!checkConnectedDeviceByReportDescriptor(rpt_desc) return not the Device we wanted!!!");
                            }
                        }
                    }
                } else {
                    LOGD("Failed: open(%s, O_RDONLY)", devname);
                }
            }


            if (mExtConnectedDevice < DeviceMax) {
                break;
            }
        }


        closedir(dir);
    }


	ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName);


	return fd;
}



sensors_poll_context_t::sensors_poll_context_t()
{
    LOGD("in sensors_poll_context_t()");

    mInitialized = false;

    // Must clean this up early or else the destructor will make a mess.
    memset(mSensors, 0, sizeof(mSensors));

    numSensors = LOCAL_SENSORS;

    mSensors[gamepad] = new GamepadSensors();
    mPollFds[gamepad].fd = mSensors[gamepad]->getFd();
    mPollFds[gamepad].events = POLLIN;
    mPollFds[gamepad].revents = 0;

    mSensors[virtualGamepad] = new VirtualGamepadSensors();
    mPollFds[virtualGamepad].fd = mSensors[virtualGamepad]->getFd();
    mPollFds[virtualGamepad].events = POLLIN;
    mPollFds[virtualGamepad].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;

    LOGD("out sensors_poll_context_t()");
}

static int poll__activate(struct sensors_poll_device_t *dev,
                          int handle, int enabled)
{
    FUNC_LOG;
    sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    return ctx->activate(handle, enabled);
}

get_sensors_list会获取所有可用的sensor设备,每个sensor设备都对应一个sensor_t结构体,函数返回sensor设备的数量。之后,依次激活这些可用的sensor设备。

SensorDevice的主要工作是与HAL层进行通信,打开senser设备,加载HAL层的so文件,获得支持的传感器列表并激活。setCapacity为DefaultKeyedVector分配空间。接着

activate这些设备。前面提到mSensorDevice保存的也就是sensors_poll_device_t的地址,open_sensors将sensors_poll_device_t的activate函数设为poll_activate函数。调用

activate函数也就是调用poll_activate函数,poll_activate转而去调用sensors_poll_context_t的activate函数。

int sensors_poll_context_t::activate(int handle, int enabled)
{
	LOGD("sensors_poll_context_t::activate");


    if (!mInitialized) return -EINVAL;
    int index = handleToDriver(handle);
    if (index < 0) return index;
    if(mSensors[index]->getState() == -1 && mSensors[index]->getDataName() != NULL)
    {
        int fd_t = mSensors[index]->getFd();
		if(fd_t >= 0) {
			mSensors[index]->setState(1);
		} else {
			mSensors[index]->setState(-1);
		}
	}


    int err =  mSensors[index]->enable(handle, enabled);


    if (!err) {
        const char wakeMessage(WAKE_MESSAGE);
        int result = write(mWritePipeFd, &wakeMessage, 1);
        ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
    }


    return err;
}

SensorBase::enable函数,这是一个纯虚函数,由子类重写。以GamepadSensor为例,enable实现中调用openDevice打开设备。openDevice打开名为“RealSensor"的

文件,mDevFd保存了文件描述符。回到activate函数,最后往管道里写入一个‘W',以唤醒等待POLLIN事件的休眠线程。

int GamepadSensors::enable(int32_t handle, int enabled)
{
	LOGD("GamepadSensors::enable(int32_t handle=%d, int enabled=%d)", handle, enabled);
	openDevice();
	return 0;
}

int SensorBase::openDevice() {
	LOGD("openDevice");

    if ((mDevFd < 0) && mDevName) {
        mDevFd = open(mDevName, O_RDONLY);
        LOGD("mDevFd = open(%s, O_RDONLY), mDevFd=%d", mDevName, mDevFd);
        ALOGE_IF(mDevFd < 0, "Couldn't open %s (%s)", mDevName, strerror(errno));
    }

    return 0;
}


回到onFirstRef函数中,接着对获得的sensor设备列表进行注册:

 for (ssize_t i=0 ; i<count ; i++) {
                registerSensor( new HardwareSensor(list[i]) );

Sensor SensorService::registerSensor(SensorInterface* s)
{
    sensors_event_t event;
    memset(&event, 0, sizeof(event));

    const Sensor sensor(s->getSensor());
    // add to the sensor list (returned to clients)
    mSensorList.add(sensor);
    // add to our handle->SensorInterface mapping
    mSensorMap.add(sensor.getHandle(), s);
    // create an entry in the mLastEventSeen array
    mLastEventSeen.add(sensor.getHandle(), NULL);

    return sensor;
}

注册虚拟传感器:

if (hasGyro && hasAccel && hasMag) {
                Sensor aSensor;

                // Add Android virtual sensors if they're not already
                // available in the HAL

                aSensor = registerVirtualSensor( new RotationVectorSensor() );// 虚拟旋转传感器
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new GravitySensor(list, count) );//虚拟重力传感器 
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );//虚拟加速器
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
                    mUserSensorList.add(aSensor);
                }

                aSensor = registerVirtualSensor( new OrientationSensor() );//虚拟方向传感器
                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
                    // if we are doing our own rotation-vector, also add
                    // the orientation sensor and remove the HAL provided one.
                    mUserSensorList.replaceAt(aSensor, orientationIndex);
                }

                // virtual debugging sensors are not added to mUserSensorList
                registerVirtualSensor( new CorrectedGyroSensor(list, count) );//真正陀螺仪 
                registerVirtualSensor( new GyroDriftSensor() );//虚拟陀螺测漂传感器
            }

SensorService继承自Thread,末尾使用run进入SensorService::threadLoop()方法。threadLoop是父类Thread的虚函数,由子类实现。

bool SensorService::threadLoop()
{
    ALOGD("nuSensorService thread starting...");

    // each virtual sensor could generate an event per "real" event, that's why we need
    // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.
    // in practice, this is too aggressive, but guaranteed to be enough.
    const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
    const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());

    SensorDevice& device(SensorDevice::getInstance());
    const size_t vcount = mVirtualSensorList.size();

    const int halVersion = device.getHalDeviceVersion();
    do {
        ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
        if (count < 0) {
            ALOGE("sensor poll failed (%s)", strerror(-count));
            break;
        }

        // Reset sensors_event_t.flags to zero for all events in the buffer.
        for (int i = 0; i < count; i++) {
             mSensorEventBuffer[i].flags = 0;
        }

        // Make a copy of the connection vector as some connections may be removed during the
        // course of this loop (especially when one-shot sensor events are present in the
        // sensor_event buffer). Promote all connections to StrongPointers before the lock is
        // acquired. If the destructor of the sp gets called when the lock is acquired, it may
        // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
        // cleanup. So copy all the strongPointers to a vector before the lock is acquired.
        SortedVector< sp<SensorEventConnection> > activeConnections;
        populateActiveConnections(&activeConnections);
        Mutex::Autolock _l(mLock);
        // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
        // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
        // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should
        // not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and
        // releasing the wakelock.
        bool bufferHasWakeUpEvent = false;
        for (int i = 0; i < count; i++) {
            if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {
                bufferHasWakeUpEvent = true;
                break;
            }
        }

        if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
            setWakeLockAcquiredLocked(true);
        }
        recordLastValueLocked(mSensorEventBuffer, count);

        // handle virtual sensors
        if (count && vcount) {
            sensors_event_t const * const event = mSensorEventBuffer;
            const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
            if (activeVirtualSensorCount) {
                size_t k = 0;
                SensorFusion& fusion(SensorFusion::getInstance());
                if (fusion.isEnabled()) {
                    for (size_t i=0 ; i<size_t(count) ; i++) {
                        fusion.process(event[i]);
                    }
                }
                for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
                        if (count + k >= minBufferSize) {
                            ALOGE("buffer too small to hold all events: "
                                    "count=%zd, k=%zu, size=%zu",
                                    count, k, minBufferSize);
                            break;
                        }
                        sensors_event_t out;
                        SensorInterface* si = mActiveVirtualSensors.valueAt(j);
                        if (si->process(&out, event[i])) {
                            mSensorEventBuffer[count + k] = out;
                            k++;
                        }
                    }
                }
                if (k) {
                    // record the last synthesized values
                    recordLastValueLocked(&mSensorEventBuffer[count], k);
                    count += k;
                    // sort the buffer by time-stamps
                    sortEventBuffer(mSensorEventBuffer, count);
                }
            }
        }

        // handle backward compatibility for RotationVector sensor
        if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
            for (int i = 0; i < count; i++) {
                if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {
                    // All the 4 components of the quaternion should be available
                    // No heading accuracy. Set it to -1
                    mSensorEventBuffer[i].data[4] = -1;
                }
            }
        }

        // Map flush_complete_events in the buffer to SensorEventConnections which called
        // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the
        // SensorEventConnection mapped to the corresponding flush_complete_event in
        // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
        for (int i = 0; i < count; ++i) {
            mMapFlushEventsToConnections[i] = NULL;
            if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
                const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
                SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);
                if (rec != NULL) {
                    mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();
                    rec->removeFirstPendingFlushConnection();
                }
            }
        }

        // Send our events to clients. Check the state of wake lock for each client and release the
        // lock if none of the clients need it.
        bool needsWakeLock = false;
        size_t numConnections = activeConnections.size();
        for (size_t i=0 ; i < numConnections; ++i) {
            if (activeConnections[i] != 0) {
                activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
                        mMapFlushEventsToConnections);
                needsWakeLock |= activeConnections[i]->needsWakeLock();
                // If the connection has one-shot sensors, it may be cleaned up after first trigger.
                // Early check for one-shot sensors.
                if (activeConnections[i]->hasOneShotSensors()) {
                    cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
                            count);
                }
            }
        }

        if (mWakeLockAcquired && !needsWakeLock) {
            setWakeLockAcquiredLocked(false);
        }
    } while (!Thread::exitPending());

    ALOGW("Exiting SensorService::threadLoop => aborting...");
    abort();
    return false;
}

ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
    if (!mSensorDevice) return NO_INIT;
    ssize_t c;
    do {
        c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
                                buffer, count);
    } while (c == -EINTR);
    return c;
}

SensorDevice的poll函数会调用到sensors_poll_device_1的poll函数,前面提到open_sensors将sensors_poll_device_1的poll函数设置为poll_poll函数,poll_poll函

数调用sensors_poll_context_t::pollEvents函数。

int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
    LOGD("---sensors_poll_context_t::pollEvents---");

    int nbEvents = 0;
    int n = 0;

    do {
        for (int i=0 ; count && i<numSensorDrivers ; i++) {
            SensorBase* const sensor(mSensors[i]);
			bool openFailed = false;
			bool hungUp = false;

			if (mSensors[i]->getFd() == -1) {
				openFailed = true;
				mSensors[i]->setState(-1);
				LOGD("failed: open %s!!!", sensorDeviceName[i]);
			} else {
				if (mPollFds[i].revents & (POLLHUP | POLLERR)) {
					hungUp = true;
					LOGD("%s POLLHUP or POLLERR !!!", sensorDeviceName[i]);
				}
			}

			if (hungUp) {
				close(mSensors[i]->getFd());
			}

			if (openFailed || hungUp) {
				int fd = -1;
				if (i == virtualGamepad) {
					fd = open(static_cast<VirtualGamepadSensors*>(mSensors[virtualGamepad])->getFifoName(), O_RDONLY | O_NONBLOCK);
				} else {
					fd = mSensors[i]->openInput(mSensors[i]->getDataName());
				}

				if (fd < 0) {
					mSensors[i]->setState(-1);
					LOGD("failed reopen %s !!!", sensorDeviceName[i]);
				} else {
					mSensors[i]->setState(1);
					LOGD("success reopen %s !!!", sensorDeviceName[i]);
				}

				mSensors[i]->setDataFd(fd);
				mPollFds[i].fd = mSensors[i]->getFd();
				mPollFds[i].events = POLLIN;
				mPollFds[i].revents = 0;
			}

			// See if we have some pending events from the last poll()
            if ((mPollFds[i].revents & (POLLIN | POLLPRI)) || (sensor->hasPendingEvents())) {
            	LOGD("true == ((mPollFds[%d].revents & (POLLIN | POLLPRI)) || (sensor->hasPendingEvents()))", i);

				int nb = sensor->readEvents(data, count);
				if (nb < 0) {
					LOGD("readEvents return  = %d",nb);
					return -errno;
				}

                if (nb < count) {
                    // no more data for this sensor
                    mPollFds[i].revents = 0;
                }

                count -= nb;
                nbEvents += nb;
                data += nb;
            }
        }

        if (count) {
            do {
                LOGD("before poll(mPollFds, numFds(%d), nbEvents(%d) ? 0 : -1)", numFds, nbEvents);
                n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
                LOGD("mPollFds[0].revents=%d, mPollFds[1].revents=%d", mPollFds[0].revents, mPollFds[1].revents);
                LOGD("%d = poll(mPollFds, numFds, nbEvents ? 0 : -1)", n);
            } while (n < 0 && errno == EINTR);

            if (n < 0) {
                ALOGE("poll() failed (%s)", strerror(errno));
                return -errno;
            }

            if (mPollFds[wake].revents & (POLLIN | POLLPRI)) {
            	LOGD("true == (mPollFds[wake].revents & (POLLIN | POLLPRI))");
                char msg;
                int result = read(mPollFds[wake].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[wake].revents = 0;
            }
        }

        LOGD("n=%d, count=%d", n, count);
        // if we have events and space, go read them
    } while (n && count);

    LOGD("---nbEvents=%d---", nbEvents);

    return nbEvents;
}

pollEvent末尾的do-while循环会调用poll使HAL层和kernel进行通信,以监听已被初始化的mPollFds的事件。函数中还遍历了所有的mpollFds,调用readEvents进行处

理。readEvents在SensorBase的子类实现,以GamepadSensor为例,之后就是解析Gyroscope和Accelerometer的数据。

int GamepadSensors::readEvents(sensors_event_t* data, int count)
{
    memset(mRawDataBuf, 0, sizeof(mRawDataBuf));
    ssize_t nbytes = read(mDataFd, mRawDataBuf, sizeof(mRawDataBuf));
    LOGD("%d = read(mDataFd, mRawDataBuf, sizeof(mRawDataBuf))", nbytes);

#if 1
    printf("mRawDataBuf: ");
    for (int i=0; i<nbytes; i++) {
        printf("%02X  ", mRawDataBuf[i]);
    }
    printf("\n");
#endif

    int numEventReceived = parseRawData(mRawDataBuf, nbytes, data, count);

    return numEventReceived;
}
readEvents函数从打开的InputDevice中读取数据到mRawDataBuf中,末尾调用parseRawData函数读取sensor配置参数。

int GamepadSensors::parseRawData(const char *rawDataBuf, const size_t bufSize,
            struct sensors_event_t* data, int count)
{
    if ((rawDataBuf == NULL) || (bufSize <= 0) || (data == NULL) || (count < 2)) {
            return -EINVAL;
    }

    ExtConnectedDevice extConnectedDevice= getConnectedDevice();
    if (extConnectedDevice >= DeviceMax) {
        return -EINVAL;
    }

    struct timeval t;
    int eventCount = 0;
    SensorDataConfig config;
    memset(&config, 0, sizeof(SensorDataConfig));
    int ret = chooseDataConfig(config, extConnectedDevice);
    if (ret < 0) {
        return -EINVAL;
    }//后面部分省略。。。

至此,Android Sensor的HAL层代码已基本分析完。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值