zoukankan      html  css  js  c++  java
  • HillCrest Sensor HAL

    1. 抽象定义

    Google为Sensor提供了统一的HAL接口,不同的硬件厂商需要根据该接口来实现并完成具体的硬件抽象层,Android中Sensor的HAL接口定义在:hardware/libhardware/include/hardware/sensors.h,

    其中定义了几个数据类型:

    • sensor_t - 包含传感器相关信息
    • sensors_module_t - 传感器硬件模块类型
    • sensors_event_t - 传感器事件
    • sensors_poll_device_t - 传感器抽象设备类型

    HAL实现必须完成下面的函数接口:

    • get_sensors_list - 返回所有传感器的列表
    • activate - 启动或停止传感器
    • batch - 设置传感器的参数,如采样率和最大报告延迟
    • setDelay - 仅用于 1.0 版本的 HAL,设置指定传感器的采样率
    • flush - 刷写指定传感器的 FIFO 并在完成后报告刷写完成事件
    • poll - 返回可用的传感器事件

    1.1 sensor type

    sensor type的定义如下:

    [sensors-base.h]
    enum {
        SENSOR_TYPE_META_DATA = 0,
        SENSOR_TYPE_ACCELEROMETER = 1,
        SENSOR_TYPE_MAGNETIC_FIELD = 2,
        SENSOR_TYPE_ORIENTATION = 3,
        SENSOR_TYPE_GYROSCOPE = 4,
        SENSOR_TYPE_LIGHT = 5,
        SENSOR_TYPE_PRESSURE = 6,
        SENSOR_TYPE_TEMPERATURE = 7,
        SENSOR_TYPE_PROXIMITY = 8,
        SENSOR_TYPE_GRAVITY = 9,
        ...
    }
    
    #define SENSOR_STRING_TYPE_ACCELEROMETER                "android.sensor.accelerometer"
    #define SENSOR_STRING_TYPE_MAGNETIC_FIELD               "android.sensor.magnetic_field"
    #define SENSOR_STRING_TYPE_ORIENTATION                  "android.sensor.orientation"
    #define SENSOR_STRING_TYPE_GYROSCOPE                    "android.sensor.gyroscope"
    #define SENSOR_STRING_TYPE_LIGHT                        "android.sensor.light"
    #define SENSOR_STRING_TYPE_PRESSURE                     "android.sensor.pressure"
    #define SENSOR_STRING_TYPE_TEMPERATURE                  "android.sensor.temperature"
    #define SENSOR_STRING_TYPE_PROXIMITY                    "android.sensor.proximity"
    

    1.2 sensor_t

    sensor_t 的定义如下

    [sensors.h]
    struct sensor_t {
    
        /* Name of this sensor.
         * All sensors of the same "type" must have a different "name".
         */
        const char*     name;
    
        /* vendor of the hardware part */
        const char*     vendor;
    
        /* version of the hardware part + driver. The value of this field
         * must increase when the driver is updated in a way that changes the
         * output of this sensor. This is important for fused sensors when the
         * fusion algorithm is updated.
         */
        int             version;
    
        /* handle that identifies this sensors. This handle is used to reference
         * this sensor throughout the HAL API.
         */
        int             handle;
    
        /* this sensor's type. */
        int             type;	//sensor type
    
        /* maximum range of this sensor's value in SI units */
        float           maxRange;
    
        /* smallest difference between two values reported by this sensor */
        float           resolution;
    
        /* rough estimate of this sensor's power consumption in mA */
        float           power;
    
        /* this value depends on the reporting mode:
         *
         *   continuous: minimum sample period allowed in microseconds
         *   on-change : 0
         *   one-shot  :-1
         *   special   : 0, unless otherwise noted
         */
        int32_t         minDelay;
    
        /* number of events reserved for this sensor in the batch mode FIFO.
         * If there is a dedicated FIFO for this sensor, then this is the
         * size of this FIFO. If the FIFO is shared with other sensors,
         * this is the size reserved for that sensor and it can be zero.
         */
        uint32_t        fifoReservedEventCount;
    
        /* maximum number of events of this sensor that could be batched.
         * This is especially relevant when the FIFO is shared between
         * several sensors; this value is then set to the size of that FIFO.
         */
        uint32_t        fifoMaxEventCount;
    
        /* type of this sensor as a string.
         *
         * If type is OEM specific or sensor manufacturer specific type
         * (>=SENSOR_TYPE_DEVICE_PRIVATE_BASE), this string must be defined with reserved domain of
         * vendor/OEM as a prefix, e.g. com.google.glass.onheaddetector
         *
         * For sensors of Android defined types, Android framework will override this value. It is ok to
         * leave it pointing to an empty string.
         */
        const char*    stringType;
    
        /* permission required to see this sensor, register to it and receive data.
         * Set to "" if no permission is required. Some sensor types like the
         * heart rate monitor have a mandatory require_permission.
         * For sensors that always require a specific permission, like the heart
         * rate monitor, the android framework might overwrite this string
         * automatically.
         */
        const char*    requiredPermission;
    
        /* This value is defined only for continuous mode and on-change sensors. It is the delay between
         * two sensor events corresponding to the lowest frequency that this sensor supports. When lower
         * frequencies are requested through batch()/setDelay() the events will be generated at this
         * frequency instead. It can be used by the framework or applications to estimate when the batch
         * FIFO may be full.
         *
         * NOTE: 1) period_ns is in nanoseconds where as maxDelay/minDelay are in microseconds.
         *              continuous, on-change: maximum sampling period allowed in microseconds.
         *              one-shot, special : 0
         *   2) maxDelay should always fit within a 32 bit signed integer. It is declared as 64 bit
         *      on 64 bit architectures only for binary compatibility reasons.
         * Availability: SENSORS_DEVICE_API_VERSION_1_3
         */
        #ifdef __LP64__
           int64_t maxDelay;
        #else
           int32_t maxDelay;
        #endif
    
        /* Flags for sensor. See SENSOR_FLAG_* above. Only the least significant 32 bits are used here.
         * It is declared as 64 bit on 64 bit architectures only for binary compatibility reasons.
         * Availability: SENSORS_DEVICE_API_VERSION_1_3
         */
        #ifdef __LP64__
           uint64_t flags;
        #else
           uint32_t flags;
        #endif
    
        /* reserved fields, must be zero */
        void*           reserved[2];
    };
    

    1.3 sensor_module_t

    该结构体实际上是对标准硬件模块hw_module_t的一个扩展,增加一个get_sensor_list函数,用于获取传感器的列表,以及set_operation_mode设置为相关的mode;

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

    1.4 sensors_poll_device_t

    sensors_poll_device_t 定义了以下方法

    [sensors.h]
    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);
    };
    

    2. 抽象方法

    2.1 get_sensors_list

    sensors_module_t 是用于为传感器创建 Android 硬件模块的类型。HAL 的实现必须定义一个该类型的对象 HAL_MODULE_INFO_SYM,以提供 get_sensors_list 函数。

    
    [HAL.cpp]
    struct sensors_module_t HAL_MODULE_INFO_SYM = {
    	.common = {
    		.tag = HARDWARE_MODULE_TAG,
    #ifdef SENSORS_MODULE_API_VERSION_0_1
    		.module_api_version = SENSORS_MODULE_API_VERSION_0_1,
    #else
    		.module_api_version = 0,
    #endif
    		.hal_api_version = 0,
    		.id = SENSORS_HARDWARE_MODULE_ID,
    		.name = "Freespace SensorHub Sensor Module",
    		.author = "Hillcrest Labs, Inc.",
    		.methods = &sensors_module_methods,
    		.dso = 0,
    		.reserved = {},
    	},
    	.get_sensors_list = get_sensors_list
    };
    

    get_sensors_list 提供由 HAL 实现的传感器列表,该函数返回列表中的传感器数量。
    调用单例模式实例化,然后调用对应方法获取传感器列表,返回对应的 sensor_t 结构体数组指针。

    static int get_sensors_list(struct sensors_module_t* module,
    		struct sensor_t const** list) {
    
    	if (getContext()) {
    		return getContext()->getSensorList(list);
    	}
    
    	return 0;
    }
    
    
    static Context * getContext() {
    	if (context_) {
    		return context_;
    	}
    
    	if (!HAL_ENABLED) {
    		return NULL;
    	}
    
    	context_ = new Context();
    #ifdef ENABLE_SOURCE_OBSERVER
    	if (OBS_ENABLED) {
    		hubServer_  = new HubServer(*context_, true);
    	}
    #endif
    	return context_;
    }
    

    2.2 open method

    打开 sensor 的实例化对象, 并填充 hw_device_t

    
    static struct hw_module_methods_t sensors_module_methods = {
    	.open = open_sensors
    };
    
    struct hcrest_sensors_device_t {
    #ifdef SENSORS_DEVICE_API_VERSION_1_1
    	struct sensors_poll_device_1 base; // must be first
    #else
    	struct sensors_poll_device_t base; // must be first
    #endif
    	unsigned int magic;
    	void * context;
    };
    
    static hcrest_sensors_device_t hwdevice_;
    
    static bool open_ = false;
    
    static int open_sensors(const struct hw_module_t* module, const char* name,
    		struct hw_device_t** device) {
    
    	LOGI("Freespace SensorHub HAL open");
    	LOGD("   open from: %s", name);
    	LOGI("   version:   " FS_SENSORHUB_HAL_VERSION);
    
    	if (open_) {
    		LOGE("Already open, refusing open_sensors");
    		return -EBUSY;
    	}
    
    	int rc;
    	*device = NULL;
    	Context * context = getContext();
    
    	if (context) {
    		hwdevice_.base.common.tag     = HARDWARE_DEVICE_TAG;
    #if defined(SENSORS_DEVICE_API_VERSION_1_3)
    		hwdevice_.base.common.version = SENSORS_DEVICE_API_VERSION_1_3;
    #elif defined(SENSORS_DEVICE_API_VERSION_1_2)
    		hwdevice_.base.common.version = SENSORS_DEVICE_API_VERSION_1_2;
    #elif defined(SENSORS_DEVICE_API_VERSION_1_1)
    		hwdevice_.base.common.version = SENSORS_DEVICE_API_VERSION_1_1;
    #elif defined(SENSORS_DEVICE_API_VERSION_1_0)
    		hwdevice_.base.common.version = SENSORS_DEVICE_API_VERSION_1_0;
    #else
    		hwdevice_.base.common.version = 0;
    #endif
    		hwdevice_.base.common.module  = const_cast<hw_module_t*>(module);
    
    		hwdevice_.base.common.close   = ctx_close;
    		hwdevice_.base.activate       = ctx_activate;
    		hwdevice_.base.setDelay       = ctx_setDelay;
    		hwdevice_.base.poll           = ctx_poll;
    
    #ifdef SENSORS_DEVICE_API_VERSION_1_1
    		hwdevice_.base.batch          = ctx_batch;
    		hwdevice_.base.flush          = ctx_flush;
    #endif
    		hwdevice_.magic               = HCREST_MAGIC;
    		hwdevice_.context             = context;
    
    		rc =  context->open();
    
    #ifdef ENABLE_SOURCE_OBSERVER
    		if (rc == 0 && OBS_ENABLED) {
    			LOGI("Initializing source server");
    			if ((rc = hubServer_->init())) {
    				LOGE("Failed initializing server");
    				freeContext();
    			}
    		}
    #endif
    		if (!rc) {
    			*device = &hwdevice_.base.common;
    		}
    	} else {
    		// Dummy context
    		*device = NULL;
    		rc = 0;
    		LOGD(">>> Dummy Sensors <<<");
    	}
    
    	LOGD("Freespace SensorHub HAL open = %s, device=%p ", rc ? strerror(-rc) : "Success", *device);
    	return rc;
    }
    

    先看下 context->open() , 打开挂在 SensorHub 上的所有 sensor,并设置 hcrest_sensors_device_t

    [Context.cpp]
    int Context::open() {
    	int rc;
    	quit_ = false;
    
    #ifdef CONTROL_INTERFACE
    	rc = ctrlIface_.init(this);
    	if (rc < 0) {
    		return rc;
    	}
    #endif
    
    	if ((rc = hub_.probe())) {
    		return rc;
    	}
    
    #ifdef EXTENSION_LIB
    	if ((rc = external_sensors_init(*this))) {
    		LOGW("Error from external_sensors_init() = %d; %s", rc, strerror(rc));
    	}
    #endif
    
    	return 0;
    }
    
    

    SensorHub::probe() 继续调用基类的 probeSensorHubDevice::probe 到这里浅尝辄止。

    [SensorHub.cpp]
    int SensorHub::probe() {
    	AutoLock _l(configLock_);
    	AutoLock _ll(pollLock_);
    
    	int rc = SensorHubDevice::probe();
    	if (rc < 0) {
    		return rc;
    	}
    
    	rc = frsDirector_.probe();
    	if (rc < 0) {
    		return rc;
    	}
    
    	ctx_.addFd(normal_.getFd(), POLLIN | POLLHUP | POLLERR, this);
    
    	if ((rc = initSensorsLocked())) {
    		return rc;
    	}
    
    	// switch to non-blocking
    	open_ = true;
    	return 0;
    }
    
    

    2.3 activate、setDelay、poll

    [HAL.cpp]
    static int ctx_activate(struct sensors_poll_device_t *dev, int handle, int enabled) {
    	return toContext(dev)->activate(handle, enabled);
    }
    
    static int ctx_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns) {
    	return toContext(dev)->setDelay(handle, ns);
    }
    
    static int ctx_poll(struct sensors_poll_device_t *dev, sensors_event_t* data, int count) {
    	return toContext(dev)->pollEvents(data, count);
    }
    
    #ifdef SENSORS_DEVICE_API_VERSION_1_1
    static int ctx_batch(struct sensors_poll_device_1 *dev, int sensor_handle, int flags,
         int64_t sampling_period_ns,
         int64_t max_report_latency_ns) {
    	return toContext(dev)->batch(sensor_handle, flags, sampling_period_ns, max_report_latency_ns);
    }
    
    static int ctx_flush(struct sensors_poll_device_1 *dev, int sensor_handle) {
     	return toContext(dev)->flush(sensor_handle);
    }
    #endif
    
    • activate 激活或禁用传感器

    int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int enabled);

    如果 enabled 为 1 且传感器已激活,则该函数是空操作且操作成功。
    如果 enabled 为 0 且传感器已禁用,则该函数是空操作且操作成功。
    如果操作成功了,则该函数返回 0;否则返回表示错误的负数。

    • poll 机制来轮询读取数据

    int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count);

    • batch 设置传感器的参数(包括采样率和最大报告延迟)

    int (*batch)( struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns);

    • flush 将刷新完成事件添加到指定传感器的硬件 FIFO末尾并刷新 FIFO

    int (*flush)(struct sensors_poll_device_t* dev, int sensor_handle);

    Sensor HAL的简单流程可以按照下面来理解:

    当设备启动时,调用 get_sensors_list。

    当传感器激活时,则先使用请求的参数调用 batch 函数,然后调用 activate(..., enable=1)。

    当激活状态下的传感器的请求特性发生变化时,会调用 batch 函数。

    可以随时调用 flush,甚至在未激活的传感器上也可以调用(在这种情况下,该函数必须返回 -EINVAL)

    当传感器禁用时,将调用 activate(..., enable=0)。

    在进行上述调用的同时,会反复调用 poll 函数来请求数据。甚至在没有传感器激活的情况下,也可以调用 poll。

    3. 框架流程

    当前方案AP并未直接对接 SensorHUB,而是将 SensorHUB 挂载在一颗 MCU 上,AP与MCU通过USB相连接,进行数据传输。

    基本框架如下图所示:

    • IMU App
      App 通过正常的 SDK 接口访问 Sensor 服务,获取 Sensor 数据。

    • Framewrok Java
      SensorManager 提供了 Java 层 Sensor 的接口,并通过 JNI 和 Native SensorManager 通信。
      代码位于 frameworks/base/core/java/android/hardware/SensorManage.java

    • Framework JNI
      提供机制,供 SensorManagerNative SensorManager 通信。
      代码位于 frameworks/base/core/jni/android_hardware_SensorManager.cpp

    • Native Service & Libs
      SensorManager 属于 NativeLibs,为 JNI 提供接口,获取 SensorService 的服务,从而获取 SensorEvent
      代码位于 frameworks/native/libs/sensor/SensorManager.cpp
      SensorService 属于 NativeService,向 SensorManager 注册服务,和 Sensor HAL 进行交互,控制 sensor 和获取 SensorEvent
      代码位于 frameworks/native/services/sensorservice/SensorService.cpp

    • HAL
      SensorHub HAL,向上为 Native SensorService 提供接口,向下和 Driver 进行交互。

    • Driver
      创建虚拟设备节点,并提供接口供 HAL 层获取 SensorEvent 和控制 Sensor

    4. 问题分析

    问题现象:
    IMU sensordump App 无法获取 Accelerometer Sensor 数据

    初步分析:
    通过 dumpsys sensorservice 获取相关信息,发现 Client 0 中 Accelerometer 的状态是 First flush pending, 并不是 active 的状态。

    2 active connections
    Connection Number: 0
    	Operating Mode: NORMAL
    	 org.cvpcs.android.sensordump.ASensor | WakeLockRefCount 0 | uid 10056 | cache size 0 | max cache size 984
    	 Rokid Glasses Accelerometer 0x00000001 | status: First flush pending | pending flush events 0
    	 events recvd: 0 | sent 0 | cache 0 | dropped 0 | total_acks_needed 0 | total_acks_recvd 0
    Connection Number: 1
    	Operating Mode: NORMAL
    	 com.android.server.policy.WindowOrientationListener | WakeLockRefCount 0 | uid 1000 | cache size 0 | max cache size 984
    	 Rokid Glasses Accelerometer 0x00000001 | status: active | pending flush events 0
    	 events recvd: 3976 | sent 3971 | cache 5 | dropped 0 | total_acks_needed 0 | total_acks_recvd 0
    

    根据 log 定位 sensorservice 代码的位置,确定 mFirstFlushPending 标志被设置为 true

    [SensorEventConnection.cpp]
    void SensorService::SensorEventConnection::dump(String8& result) {
        Mutex::Autolock _l(mConnectionLock);
        result.appendFormat("	Operating Mode: %s
    ",mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
        result.appendFormat("	 %s | WakeLockRefCount %d | uid %d | cache size %d | "
                "max cache size %d
    ", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
                mMaxCacheSize);
        for (size_t i = 0; i < mSensorInfo.size(); ++i) {
            const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
            result.appendFormat("	 %s 0x%08x | status: %s | pending flush events %d 
    ",
                                mService->getSensorName(mSensorInfo.keyAt(i)).string(),
                                mSensorInfo.keyAt(i),
                                flushInfo.mFirstFlushPending ? "First flush pending" :
                                                               "active",
                                flushInfo.mPendingFlushEventsToSend);
    

    这个标志在构造函数初始化列表中被初始化为 false,那么这个标志是在哪里被修改的呢?
    SensorEventConnection 类提供了 setFirstFlushPending 方法去设置这个标志,

    [SensorEventConnection.cpp]
    void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
                                    bool value) {
        Mutex::Autolock _l(mConnectionLock);
        ssize_t index = mSensorInfo.indexOfKey(handle);
        if (index >= 0) {
            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
            flushInfo.mFirstFlushPending = value;
        }
    }
    

    而这个方法在类 SensorServiceenable 方法中被调用。

    [SensorService.cpp]
    status_t SensorService::enable(const sp<SensorEventConnection>& connection,
            int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
            const String16& opPackageName) {
        ...
        if (err == NO_ERROR &&
                sensor->getSensor().getReportingMode() == AREPORTING_MODE_CONTINUOUS &&
                rec->getNumConnections() > 1) {
            connection->setFirstFlushPending(handle, true);
            status_t err_flush = sensor->flush(connection.get(), handle);
            // Flush may return error if the underlying h/w sensor uses an older HAL.
            if (err_flush == NO_ERROR) {
                rec->addPendingFlushConnection(connection.get());
            } else {
                connection->setFirstFlushPending(handle, false);
            }
        }
        ...    
    }   
    

    参考前面的 Sensor HAL 的流程分析,对比 enable 方法中的流程,先执行 batch 设置采样时间等参数,然后调用 flush 刷新 FIFO,最后调用 activcate 激活传感器。

    SensorService 继承于 Thread, 复写方法 threadLoop,不断的从 Sensor HAL 中读取数据

    [SensorService.cpp]
    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 vcount = mSensors.getVirtualSensors().size();
        const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
        const size_t numEventMax = minBufferSize / (1 + vcount);
    
        SensorDevice& device(SensorDevice::getInstance());
    
        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;
            }
    

    在读取完数据后,它会向所有连接的 Client 发送 SensorEvents

    [SensorService.cpp]
            // 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);
                    }
                }
            }
    

    SendEvents 的方法中,判断获取的数据流中类型是否存在 SENSOR_TYPE_META_DATA ,如果有且 flushInfo.mFirstFlushPending == true,设置该标志为 false,然后接收到的数据才能被送到 Client

    [SensorEventConnection.cpp]
    status_t SensorService::SensorEventConnection::sendEvents(
            sensors_event_t const* buffer, size_t numEvents,
            sensors_event_t* scratch,
            wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
        ...
        if (scratch) {
            size_t i=0;
            while (i<numEvents) {
                int32_t sensor_handle = buffer[i].sensor;
                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
                    ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
                            buffer[i].meta_data.sensor);
                    // Setting sensor_handle to the correct sensor to ensure the sensor events per
                    // connection are filtered correctly.  buffer[i].sensor is zero for meta_data
                    // events.
                    sensor_handle = buffer[i].meta_data.sensor;
                }
    
                ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
                // Check if this connection has registered for this sensor. If not continue to the
                // next sensor_event.
                if (index < 0) {
                    ++i;
                    continue;
                }
    
                FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
                // Check if there is a pending flush_complete event for this sensor on this connection.
                if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
                        mapFlushEventsToConnections[i] == this) {
                    flushInfo.mFirstFlushPending = false;
                    ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
                            buffer[i].meta_data.sensor);
                    ++i;
                    continue;
                }
            ...        
            }
            ...
        }
        ...
        // NOTE: ASensorEvent and sensors_event_t are the same type.
        ssize_t size = SensorEventQueue::write(mChannel,
                                        reinterpret_cast<ASensorEvent const*>(scratch), count);
        ...
    }
    

    到这里问题的原因基本可以定位了,结合 libsensors log 确定 SensorHUB HAL 没有上报 SENSOR_TYPE_META_DATA 类型的数据到 SensorService,导致数据无法发送到对应的 Client

    这里追查了代码,发现 SENSOR_TYPE_META_DATA 类型的数据的上报流程不能正常工作,因为 SensorHUB HAL 适配当前方案时,移除了部分代码。在修改了这部分流程后,顺利解决了这一问题。

    2 active connections
    Connection Number: 0
    	Operating Mode: NORMAL
    	 org.cvpcs.android.sensordump.ASensor | WakeLockRefCount 0 | uid 10056 | cache size 0 | max cache size 984
    	 Rokid Glasses Accelerometer 0x00000001 | status: active | pending flush events 0
    	 events recvd: 6168 | sent 4353 | cache 1815 | dropped 0 | total_acks_needed 0 | total_acks_recvd 0
    Connection Number: 1
    	Operating Mode: NORMAL
    	 com.android.server.policy.WindowOrientationListener | WakeLockRefCount 0 | uid 1000 | cache size 0 | max cache size 984
    	 Rokid Glasses Accelerometer 0x00000001 | status: active | pending flush events 0
    	 events recvd: 589106 | sent 588481 | cache 625 | dropped 0 | total_acks_needed 0 | total_acks_recvd 0
    0 direct connections
    
    Author: xujinlong Email: xyxujinlong@163.com
  • 相关阅读:
    Oracle 按一行里某个字段里的值分割成多行进行展示
    Property or method "openPageOffice" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by
    SpringBoot 项目启动 Failed to convert value of type 'java.lang.String' to required type 'cn.com.goldenwater.dcproj.dao.TacPageOfficePblmListDao';
    Maven 设置阿里镜像
    JS 日期格式化,留作参考
    JS 过滤数组里对象的某个属性
    原生JS实现简单富文本编辑器2
    Chrome控制台使用详解
    android权限(permission)大全
    不借助第三方网站四步实现手机网站转安卓APP
  • 原文地址:https://www.cnblogs.com/tinylaker/p/11426703.html
Copyright © 2011-2022 走看看