Android Sensor Input类型 (五) Sensor HAL NativeSensorManager
- Android Sensors 总览(基于高通android平台)
- Android Sensor Input类型 (一) 简介
- Android Sensor Input类型 (二) Device Driver
- Android Sensor Input类型 (三) Sensor Class
- Android Sensor Input类型 (四) Sensor HAL 实现
- Android Sensor Input类型 (五) Sensor HAL NativeSensorManager
NativeSensorManager
代码路径:
code/hardware/qcom/sensors/NativeSensorManager.cpp
code/hardware/qcom/sensors/NativeSensorManager.h
NativeSensorManager类定义
class NativeSensorManager : public Singleton<NativeSensorManager> {
friend class Singleton<NativeSensorManager>;
NativeSensorManager();
~NativeSensorManager();
struct sensor_t sensor_list[MAX_SENSORS]; //!< sensorlist数组 >! NoteBy: yujixuan
struct SensorContext context[MAX_SENSORS]; //!< context数组 >! NoteBy: yujixuan
struct SensorEventMap event_list[MAX_SENSORS]; //!< 用于上报的evnet 数组 >! NoteBy: yujixuan
static const struct SysfsMap node_map[]; //sysfs 设备节点名
static const struct sensor_t virtualSensorList[];
static char virtualSensorName[][SYSFS_MAXLEN]; //虚拟sensor相关
int mSensorCount;
bool mScanned;
int mEventCount;
DefaultKeyedVector<int32_t, struct SensorContext*> type_map;
DefaultKeyedVector<int32_t, struct SensorContext*> handle_map;
DefaultKeyedVector<int, struct SensorContext*> fd_map;
void compositeVirtualSensorName(const char *sensor_name, char *chip_name, int type);
int getNode(char *buf, char *path, const struct SysfsMap *map);
int getSensorListInner();
int getDataInfo();
int registerListener(struct SensorContext *hw, struct SensorContext *virt);
int initCalibrate(const SensorContext *list);
int initVirtualSensor(struct SensorContext *ctx, int handle, struct sensor_t info);
int addDependency(struct SensorContext *ctx, int handle);
int getEventPath(const char *sysfs_path, char *event_path);
int getEventPathOld(const struct SensorContext *list, char *event_path);
public:
int getSensorList(const sensor_t **list); //!< 获取sensor列表 >! NoteBy: yujixuan
inline SensorContext* getInfoByFd(int fd) { return fd_map.valueFor(fd); };
inline SensorContext* getInfoByHandle(int handle) { return handle_map.valueFor(handle); };
inline SensorContext* getInfoByType(int type) { return type_map.valueFor(type); };
int getSensorCount() {return mSensorCount;}
void dump();
int hasPendingEvents(int handle);
int activate(int handle, int enable);
int setDelay(int handle, int64_t ns);
int readEvents(int handle, sensors_event_t *data, int count); //!< 读取events >! NoteBy: yujixuan
int calibrate(int handle, struct cal_cmd_t *para);
int batch(int handle, int64_t sample_ns, int64_t latency_ns);
int flush(int handle);
};
class NativeSensorManager 继承了Singleton,单例模式,只存在一个实例对象,即在SensorHal 中被多次访问使用的sm;
通过NativeSensorManager class的定义可知 主要有以下内容:
- 定义维护了 在SensorHAL 中由 sensor_t 组成的 sensor_list 数组;
- 定义由SensorContext 组成的 Context数组;
- 定义了SensorEventMap 组成的 event_list 数组;
- 定义了用于记录sensor 在sys中设备节点路径的 SysfsMap;
SysfsMap node_map
struct SysfsMap {
int offset;
const char *node;
int type;
int required;
};
const struct SysfsMap NativeSensorManager::node_map[] = {
{offsetof(struct sensor_t, name), SYSFS_NAME, TYPE_STRING, 1},
{offsetof(struct sensor_t, vendor), SYSFS_VENDOR, TYPE_STRING, 1},
{offsetof(struct sensor_t, version), SYSFS_VERSION, TYPE_INTEGER, 1},
{offsetof(struct sensor_t, type), SYSFS_TYPE, TYPE_INTEGER, 1},
{offsetof(struct sensor_t, maxRange), SYSFS_MAXRANGE, TYPE_FLOAT, 1},
{offsetof(struct sensor_t, resolution), SYSFS_RESOLUTION, TYPE_FLOAT, 1},
{offsetof(struct sensor_t, power), SYSFS_POWER, TYPE_FLOAT, 1},
......
};
SensorEventMap
struct SensorEventMap {
char data_name[80];
char data_path[PATH_MAX];
};
继承Singleton 单例模式
前面可知,NativeSensorManager : public Singleton,集成了Sigleton, 是单例模式;
Singleton模板类,指定了 template
在NativeSensorManager.cpp的最开始,创建了实例;
ANDROID_SINGLETON_STATIC_INSTANCE(NativeSensorManager);
代码路径:system/core/include/utils/Singleton.h
template <typename TYPE>
class ANDROID_API Singleton
{
public:
static TYPE& getInstance() {
Mutex::Autolock _l(sLock);
TYPE* instance = sInstance;
if (instance == 0) {
instance = new TYPE();
sInstance = instance;
}
//如果实例对象不存在,实例化一个对象, 已存在直接返回;
//TYPE == NativeSensorManager
return *instance;
}
static bool hasInstance() {
Mutex::Autolock _l(sLock);
return sInstance != 0;
}
protected:
~Singleton() { };
Singleton() { };
private:
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Mutex sLock;
static TYPE* sInstance;
};
#define ANDROID_SINGLETON_STATIC_INSTANCE(TYPE) \
template<> ::android::Mutex \
(::android::Singleton< TYPE >::sLock)(::android::Mutex::PRIVATE); \
template<> TYPE* ::android::Singleton< TYPE >::sInstance(0); \
template class ::android::Singleton< TYPE >;
由上分析可知,NativeSensorManager未实例化在第一次调用时有 instance = new TYPE(); 即 new NativeSensorManager();
以下是 NativeSensorManager类构造器的实现:
NativeSensorManager::NativeSensorManager():
mSensorCount(0), mScanned(false), mEventCount(0), type_map(NULL), handle_map(NULL), fd_map(NULL)
{
int i;
memset(sensor_list, 0, sizeof(sensor_list));
memset(context, 0, sizeof(context));
type_map.setCapacity(MAX_SENSORS);
handle_map.setCapacity(MAX_SENSORS);
fd_map.setCapacity(MAX_SENSORS);
for (i = 0; i < MAX_SENSORS; i++) {
context[i].sensor = &sensor_list[i];
sensor_list[i].name = context[i].name;
sensor_list[i].vendor = context[i].vendor;
list_init(&context[i].listener);
list_init(&context[i].dep_list);
}
if(getDataInfo()) {
ALOGE("Get data info failed\n");
}
dump();
}
通过getDataInfo 初始化sensor list数组,sensor context数组,对NativeSensorManager 做实际的数据填充;
dump 显示当前NativeSensorManager的主要内容;
getDataInfo 填充数据
NativeSensorManager是管理sensor HAL 处理的核心,getDataInfo是对填充构建内部细节的实际实现,一下是其主要内容:
int NativeSensorManager::getDataInfo() {
int i, j;
struct SensorContext *list;
int has_acc = 0;
int has_compass = 0;
int has_gyro = 0;
int has_light = 0;
int has_proximity = 0;
struct sensor_t sensor_mag;
struct sensor_t sensor_acc;
struct sensor_t sensor_light;
struct sensor_t sensor_proximity;
struct sensor_t sensor_gyro;
mSensorCount = getSensorListInner();
//1:完成SensorContext list 获取和填充 包含sensor_t
for (i = 0; i < mSensorCount; i++) {
struct SensorRefMap *item;
list = &context[i];
list->is_virtual = false;
item = new struct SensorRefMap;
item->ctx = list;
/* hardware sensor depend on itself */
list_add_tail(&list->dep_list, &item->list);
if (strlen(list->data_path) != 0)
list->data_fd = open(list->data_path, O_RDONLY | O_CLOEXEC | O_NONBLOCK);
//open event 路径,获取文件描述符
if (list->data_fd > 0) {
fd_map.add(list->data_fd, list);
// DefaultKeyedVector<int, struct SensorContext*> fd_map;
// 添加到sm的fd_map中;
}
type_map.add(list->sensor->type, list);
// DefaultKeyedVector<int32_t, struct SensorContext*> type_map;
// 添加到sm的type_map中;
handle_map.add(list->sensor->handle, list);
// DefaultKeyedVector<int32_t, struct SensorContext*> handle_map;
// 添加到sm的handle_map中;
//根据不同的sensor type,创建不同的SensorBase子类实例;
switch (list->sensor->type) {
case SENSOR_TYPE_ACCELEROMETER:
has_acc = 1;
list->driver = new AccelSensor(list);
//假设,type是acc,new一个 AccelSensor; 一个SensorBase子类实例
sensor_acc = *(list->sensor);
break;
case SENSOR_TYPE_MAGNETIC_FIELD:
has_compass = 1;
list->driver = new CompassSensor(list);
sensor_mag = *(list->sensor);
break;
case SENSOR_TYPE_PROXIMITY:
has_proximity = 1;
//......
list->driver = new LightSensor(list);
sensor_light = *(list->sensor);
break;
//......
default:
list->driver = NULL;
ALOGE("No handle %d for this type sensor!", i);
break;
}
initCalibrate(list);
//校准相关
}
//virtual sensors
//......
}
校准相关,virtual sensor相关暂不分析; 通过以上代码,可知在getDataInfo 中主要实现了:
- 通过getSensorListInner 完成SensorContext list 获取和填充 包含sensor_t
- 通过for循环,对每一个sensor做处理,打开其event patch,记录得到的文件描述符fd到map中;
- 判断sensor type 根据返回的结果 创建基于SensorBase的sensor driver实例;
getSensorListInner获取
通过前面的blog可知,sensor kernel driver 注册了sensor class类,提供了若干api 用于往sensor class注册;
sensor driver的具体实现中注册了 input device;通过adb, 可以直观的相关的device node如下:
msm8909:/sys/class/sensors # ls
MPU6050-accel MPU6050-gyro mmc3416x-mag stk3x1x-light stk3x1x-proximity
msm8909:/sys/class/sensors/MPU6050-accel # ls
calibrate enable_wakeup flags max_delay min_delay power sensor_power uevent
device fifo_max_event_count flush max_latency name resolution subsystem vendor
enable fifo_reserved_event_count handle max_range poll_delay self_test type version
msm8909:/sys/class/sensors/MPU6050-accel/device # ls
MPU6050-accel capabilities enable id name poll_delay properties subsystem uniq
addr device event4 modalias phys power reg uevent write
msm8909:/sys/class/sensors/MPU6050-accel/device # cat uevent
PRODUCT=18/0/0/0
NAME="MPU6050-accel"
PROP=0
EV=9
ABS=100 7
MODALIAS=input:b0018v0000p0000e0000-e0,3,kra0,1,2,28,mlsfw
通过adb 可以直接与这些device node做交互,控制sensor,读取event数据等, 在sensor hal的代码中如何完成这些操作?
前面的内容提到,getDataInfo 填充NativeSensorManager,其中关键是getSensorListInner 完成SensorContext list 获取和填充,下面是它的具体实现:
int NativeSensorManager::getSensorListInner()
{
int number = 0;
int err = -1;
const char *dirname = SYSFS_CLASS;
//1: SYSFS_CLASS == "/sys/class/sensors/"
char devname[PATH_MAX];
char *filename;
char *nodename;
DIR *dir;
struct dirent *de;
struct SensorContext *list;
unsigned int i;
dir = opendir(dirname);
strlcpy(devname, dirname, PATH_MAX);
filename = devname + strlen(dirname);
//2:filename指针指在SYSFS_CLASS之后,即/sys/class/sensors/ 后
while ((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
//3:去掉. .. 等无关目录
list = &context[number];
//4:发现一个目标目录,实现一个list 元素;
strlcpy(filename, de->d_name, PATH_MAX - strlen(SYSFS_CLASS));
//5:把读到目录名赋值到file name指针的位置;即填充了 devname[PATH_MAX]中 /sys/class/sensors/ 后的内容
nodename = filename + strlen(de->d_name);
//6:同样的,nodename 指针指向 filename后的位置
*nodename++ = '/';
for (i = 0; i < ARRAY_SIZE(node_map); i++) {
strlcpy(nodename, node_map[i].node, PATH_MAX - strlen(SYSFS_CLASS) - strlen(de->d_name));
//7:把node_map中的 预设的name 传入
err = getNode((char*)(list->sensor), devname, &node_map[i]);
if (err) {
ALOGE("Get node for %s failed.\n", devname);
break;
}
//8;过程与上相同,获取每个node的具体路径
}
list->sensor->handle = SENSORS_HANDLE(number);
//#define SENSORS_HANDLE(x) (SENSORS_HANDLE_BASE + x + 1)
strlcpy(nodename, "", SYSFS_MAXLEN);
strlcpy(list->enable_path, devname, PATH_MAX);
/* initialize data path */
strlcpy(nodename, "device", SYSFS_MAXLEN);
//路径指向: /sys/class/sensors/MPU6050-accel/device
if (getEventPath(devname, list->data_path) == -ENODEV) {
getEventPathOld(list, list->data_path);
}
//9:获取event 节点路径,用来读取数据, 比如 MPU6050-accel, 注册的input event路径是:
///dev/input/event4
number++;
}
closedir(dir);
return number;
}
在/code/hardware/qcom/sensors/sensors.h 中已经预设了 若干信息,例如:
#define SYSFS_CLASS "/sys/class/sensors/"
#define SYSFS_NAME "name"
#define SYSFS_VENDOR "vendor"
#define SYSFS_VERSION "version"
getSensorListInner 完成对sys中sensor class下每一个sensor的处理;
通过getNode把每一个sensor下的节点数据获取到,并填充保存到相应的数据结构中;
通过getEventPatch 获取到sensor driver驱动中注册的 input device在 input 下的路径;
比如通过adb 可以看到/sys/class/sensors/MPU6050-accel/device
下event的编号是event4, 则记录input device的device node 是/dev/input/event4, 后续读取sensor data 则是通过这个路径。
以下是getNode的实现:
getNode
int NativeSensorManager::getNode(char *buf, char *path, const struct SysfsMap *map) {
char * fret;
ssize_t len = 0;
int fd;
char tmp[SYSFS_MAXLEN];
//......
memset(tmp, 0, sizeof(tmp));
fd = open(path, O_RDONLY);
//......
len = read(fd, tmp, sizeof(tmp) - 1);
//......
tmp[len - 1] = '\0';
if (tmp[strlen(tmp) - 1] == '\n')
tmp[strlen(tmp) - 1] = '\0';
//把p 指向sensor_t map->offset 的位置,以name为例,指向指向sensor_t 的name
if (map->type == TYPE_INTEGER) {
int *p = (int *)(buf + map->offset);
*p = atoi(tmp);
} else if (map->type == TYPE_STRING) {
char **p = (char **)(buf + map->offset);
strlcpy(*p, tmp, SYSFS_MAXLEN);
} else if (map->type == TYPE_FLOAT) {
float *p = (float*)(buf + map->offset);
*p = atof(tmp);
} else if (map->type == TYPE_INTEGER64) {
int64_t *p = (int64_t *)(buf + map->offset);
*p = atoll(tmp);
}
//read node中的内容,并根据node map中预设的类型 做好转换,把每个sesnor_t 的内容填充上
close(fd);
return 0;
}
getNode把每一个sensor下的节点数据获取到,根据map->type 做好指的转换并记录下;
node_map 前面提过,它是SysfsMap元素组成的 预设的数组
struct SysfsMap {
int offset;
const char *node;
int type;
int required;
};
const struct SysfsMap NativeSensorManager::node_map[] = {
{offsetof(struct sensor_t, name), SYSFS_NAME, TYPE_STRING, 1},
{offsetof(struct sensor_t, vendor), SYSFS_VENDOR, TYPE_STRING, 1},
{offsetof(struct sensor_t, version), SYSFS_VERSION, TYPE_INTEGER, 1},
{offsetof(struct sensor_t, type), SYSFS_TYPE, TYPE_INTEGER, 1},
{offsetof(struct sensor_t, maxRange), SYSFS_MAXRANGE, TYPE_FLOAT, 1},
{offsetof(struct sensor_t, resolution), SYSFS_RESOLUTION, TYPE_FLOAT, 1},
{offsetof(struct sensor_t, power), SYSFS_POWER, TYPE_FLOAT, 1},
{offsetof(struct sensor_t, minDelay), SYSFS_MINDELAY, TYPE_INTEGER, 1},
{offsetof(struct sensor_t, fifoReservedEventCount), SYSFS_FIFORESVCNT, TYPE_INTEGER, 0},
{offsetof(struct sensor_t, fifoMaxEventCount), SYSFS_FIFOMAXCNT, TYPE_INTEGER, 0},
#if defined(SENSORS_DEVICE_API_VERSION_1_3)
#if defined(__LP64__)
{offsetof(struct sensor_t, maxDelay), SYSFS_MAXDELAY, TYPE_INTEGER64, 0},
{offsetof(struct sensor_t, flags), SYSFS_FLAGS, TYPE_INTEGER64, 0},
#else
{offsetof(struct sensor_t, maxDelay), SYSFS_MAXDELAY, TYPE_INTEGER, 0},
{offsetof(struct sensor_t, flags), SYSFS_FLAGS, TYPE_INTEGER, 0},
#endif
#endif
};
SensorBase
在前面的getDataInfo处理过程中,其中判断sensor type 根据返回的结果 创建基于SensorBase的sensor driver实例是很关键的一步;
HAL中完成框架性的处理,实际操作需要根据每个sensor的特性对不同的sensor种类做不同的定义处理,以下是以acc为例:
在getDataInfo中,new了一个AccelSensor:
switch (list->sensor->type) {
case SENSOR_TYPE_ACCELEROMETER:
has_acc = 1;
list->driver = new AccelSensor(list);
AccelSensor类的定义如下:
class AccelSensor : public SensorBase {
InputEventCircularReader mInputReader;
sensors_event_t mPendingEvent;
bool mHasPendingEvent;
int64_t mEnabledTime;
int setInitialState();
public:
AccelSensor();
AccelSensor(char *name);
AccelSensor(struct SensorContext *context);
virtual ~AccelSensor();
virtual int readEvents(sensors_event_t* data, int count);
virtual bool hasPendingEvents() const;
virtual int setDelay(int32_t handle, int64_t ns);
virtual int enable(int32_t handle, int enabled);
virtual int calibrate(int32_t handle, struct cal_cmd_t *para,
struct cal_result_t *cal_result);
virtual int initCalibrate(int32_t handle, struct cal_result_t *cal_result);
};
它继承自SensorBase类, SensorBase也是各类sensor类的父类,以下是SensorBase的类的定义:
class SensorBase {
protected:
const char* dev_name;
const char* data_name;
const sensor_cal_algo_t* algo;
char input_name[PATH_MAX];
int dev_fd;
int data_fd;
int64_t report_time;
bool mUseAbsTimeStamp;
sensors_meta_data_event_t meta_data;
char input_sysfs_path[PATH_MAX];
int input_sysfs_path_len;
int mEnabled;
int mHasPendingMetadata;
int64_t sysclk_sync_offset;
int openInput(const char* inputName);
static int64_t getTimestamp();
static int64_t getClkOffset();
static int64_t timevalToNano(timeval const& t) {
return t.tv_sec*1000000000LL + t.tv_usec*1000;
}
int open_device();
int close_device();
public:
SensorBase(const char* dev_name, const char* data_name,
const struct SensorContext* context = NULL);
virtual ~SensorBase();
virtual int readEvents(sensors_event_t* data, int count) = 0;
virtual int injectEvents(sensors_event_t* data, int count);
virtual bool hasPendingEvents() const;
virtual int getFd() const;
virtual int setDelay(int32_t handle, int64_t ns);
virtual int enable(int32_t handle, int enabled) = 0;
virtual int calibrate(int32_t handle, struct cal_cmd_t *para, struct cal_result_t *cal_result);
virtual int initCalibrate(int32_t handle, struct cal_result_t *cal_result);
virtual int setLatency(int32_t handle, int64_t ns);
virtual int flush(int32_t handle);
};
SensorBase类中定义了如,readEvents,enable,flush等操作函数,AccelSensor继承了这些虚函数,并且完成了重写;
前文提到,读取poll_poll是调用了NativeSensorManager::readEvents,
list->driver->readEvents(data, count); 即是取出SensorBase指针指向的对象,调用它的readEvents函数;(note:多态的应用,通过指向父类类型对象,调用虚函数,实际调用到子类重写的具体的readEvents函数)
InputEventCircularReader
AccelSensor类定义的首个元素是:mInputReader,它是InputEventCircularReader 类对象;如其名称,输入事件循环读取,它主要用于对sensor event data的获取;
InputEventCircularReader 类定义如下:
class InputEventCircularReader
{
struct input_event* const mBuffer;
struct input_event* const mBufferEnd;
struct input_event* mHead;
struct input_event* mCurr;
ssize_t mFreeSpace;
public:
InputEventCircularReader(size_t numEvents);
~InputEventCircularReader();
ssize_t fill(int fd);
ssize_t readEvent(input_event const** events);
void next();
};
ssize_t InputEventCircularReader::fill(int fd)
{
size_t numEventsRead = 0;
if (mFreeSpace) {
const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
if (nread<0 || nread % sizeof(input_event)) {
// we got a partial event!!
return nread<0 ? -errno : -EINVAL;
}
numEventsRead = nread / sizeof(input_event);
if (numEventsRead) {
mHead += numEventsRead;
mFreeSpace -= numEventsRead;
if (mHead > mBufferEnd) {
size_t s = mHead - mBufferEnd;
memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
mHead = mBuffer + s;
}
}
}
return numEventsRead;
}
ssize_t InputEventCircularReader::readEvent(input_event const** events)
{
*events = mCurr;
ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
return available ? 1 : 0;
}
void InputEventCircularReader::next()
{
mCurr++;
mFreeSpace++;
if (mCurr >= mBufferEnd) {
mCurr = mBuffer;
}
}
InputEventCircularReader 提供了fill,和 readEvent函数;
AccelSensor中的readEvents函数是使用它们来完成;以下是 readEvents的实现,这也是 读取HAL读取event data的最终实现的部分;
int AccelSensor::readEvents(sensors_event_t* data, int count)
{
if (count < 1)
return -EINVAL;
if (mHasPendingEvent) {
mHasPendingEvent = false;
mPendingEvent.timestamp = getTimestamp();
*data = mPendingEvent;
return mEnabled ? 1 : 0;
}
if (mHasPendingMetadata) {
mHasPendingMetadata--;
meta_data.timestamp = getTimestamp();
*data = meta_data;
return mEnabled ? 1 : 0;
}
ssize_t n = mInputReader.fill(data_fd);
if (n < 0)
return n;
int numEventReceived = 0;
input_event const* event;
#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
while (count && mInputReader.readEvent(&event)) {
int type = event->type;
if (type == EV_ABS) {
float value = event->value;
if (event->code == EVENT_TYPE_ACCEL_X) {
mPendingEvent.data[0] = value * CONVERT_ACCEL_X;
} else if (event->code == EVENT_TYPE_ACCEL_Y) {
mPendingEvent.data[1] = value * CONVERT_ACCEL_Y;
} else if (event->code == EVENT_TYPE_ACCEL_Z) {
mPendingEvent.data[2] = value * CONVERT_ACCEL_Z;
}
} else if (type == EV_SYN) {
switch (event->code){
case SYN_TIME_SEC:
{
mUseAbsTimeStamp = true;
report_time = event->value*1000000000LL;
}
break;
case SYN_TIME_NSEC:
{
mUseAbsTimeStamp = true;
mPendingEvent.timestamp = report_time+event->value;
}
break;
case SYN_REPORT:
{
if(mUseAbsTimeStamp != true) {
mPendingEvent.timestamp = timevalToNano(event->time);
}
mPendingEvent.timestamp -= sysclk_sync_offset;
if (mEnabled) {
*data++ = mPendingEvent;
numEventReceived++;
count--;
}
}
break;
}
} else {
ALOGE("AccelSensor: unknown event (type=%d, code=%d)",
type, event->code);
}
mInputReader.next();
}
#if FETCH_FULL_EVENT_BEFORE_RETURN
/* if we didn't read a complete event, see if we can fill and
try again instead of returning with nothing and redoing poll. */
if (numEventReceived == 0 && mEnabled == 1) {
n = mInputReader.fill(data_fd);
if (n)
goto again;
}
#endif
return numEventReceived;
}