GVKun编程网logo

Android SensorEvent时间戳常量(android 获取时间戳)

11

在本文中,我们将给您介绍关于AndroidSensorEvent时间戳常量的详细内容,并且为您解答android获取时间戳的相关问题,此外,我们还将为您提供关于(OK)android-5.0senso

在本文中,我们将给您介绍关于Android SensorEvent时间戳常量的详细内容,并且为您解答android 获取时间戳的相关问题,此外,我们还将为您提供关于(OK) android-5.0 sensor 工作原理 —sensorservice 的启动 (一)、(OK) android-5.0 sensor工作原理—sensorservice的启动(二)、Android Firebase addListenerForSingleValueEvent不起作用、Android NDK and OpenCV Development With Android Studio的知识。

本文目录一览:

Android SensorEvent时间戳常量(android 获取时间戳)

Android SensorEvent时间戳常量(android 获取时间戳)

@H_301_4@ 我正在编写一个简单的 Android应用程序来计算设备imu的偏差.在这样做时,我遇到了event.timestamp值的问题

使用代码:

float dT = (event.timestamp-accel_timestamp)*NS2S;

从Android Reference Guide的例子中计算四元数的旋转矩阵.

当我使用galaxy nexus-s运行代码时,我在测量之间得到0.06~0.07秒的dT但是当我在LG Nexus 4或Nexus 7上运行相同的代码时,dT总是为0.我知道这个问题,Android SensorEvent timestamp issue,Nexus 7时间戳是一个unix时间戳,但连续测量之间的差异不应总是为零. Nexus 4和Nexus 7都有相同的IMU,这可能是IMU如何创建时间戳的错误?

解决方法

哇,好吧这肯定是个错误!

正在覆盖每个SensorEvent的时间戳,就像它是一个静态变量一样……

当我在事件发生时记录时间戳的字符串时,所有值都不同.

事件以不变的方式存储在数组中.

数组中的每个SensorEvent现在都具有相同的时间戳,但值数组仍然不同(即,它们不是同一个对象并包含不同的信息…时间戳除外).

Google / HTC,请返回我生命中的3个小时!

除非有人能解释这种行为,否则我将提交错误报告.它肯定没有记录在API中.

在此期间,尝试这个解决方案:

import android.hardware.Sensor;
import android.hardware.SensorEvent;

public class UnbrokenSensorEvent {
    public long timestamp;
    public float[] values;
    public Sensor sensor;

    public UnbrokenSensorEvent(SensorEvent event){
        this.timestamp = event.timestamp;
        this.values = event.values;
        this.sensor = event.sensor;
    }
}

然后在你的听众中做这样的事情:

ArrayList<UnbrokenSensorEvent> results = new ArrayList<UnbrokenSensorEvent>();

public void onSensorChanged(SensorEvent event) {
    results.add(new UnbrokenSensorEvent(event));
}

重构应该非常简单,因为SensorEvent和UnbrokenSensorEvent具有相同的公共字段.如果您需要使用其他SensorEvent功能,请继续将其放入Unbroken版本中.

这是hacky,但恕我直言快速黑客总是比等待API更新更好!

(OK) android-5.0 sensor 工作原理 —sensorservice 的启动 (一)

(OK) android-5.0 sensor 工作原理 —sensorservice 的启动 (一)


http://blog.csdn.net/zsj100213/article/details/48179655


sensorservice 的启动:

1. systemserver.Java 的 run 函数:

[html] view plain copy
  1.  private void run() {  
  2.   
  3. ……  
  4.   
  5.         // Initialize native services.  
  6.         System.loadLibrary("android_servers");  
  7.         nativeInit();  
  8.   
  9. ……  
  10.   
  11. }  

   Android 在启动之后通过 Zygote 来管理和启动 android server,他首先会运行 SystemServer.java 里面的 run 函数,这里主要是 load android_server.so 库,然后调用 nativeInit () 来启动 sensorservice。


2. nativeInit () 是本地方法,上层 Java 调用本地 C++ 方法,需要通过 JNI 层的转化,在 com_android_server_SystemServer.cpp 中:

[html] view plain copy
  1. static void android_server_SystemServer_nativeInit(JNIEnv* env, jobject clazz) {  
  2.     char propBuf[PROPERTY_VALUE_MAX];  
  3.     property_get("system_init.startsensorservice", propBuf, "1");  
  4.     if (strcmp(propBuf, "1") == 0) {  
  5.         // Start the sensor service  
  6.         SensorService::instantiate();  
  7.     }  
  8. }  
  9.   
  10. /*  
  11.  * JNI registration.  
  12.  */  
  13. static JNINativeMethod gMethods[] = {  
  14.     /* name, signature, funcPtr */  
  15.     { "nativeInit", "()V", (void*) android_server_SystemServer_nativeInit },  
  16. };  
  17.   
  18. int register_android_server_SystemServer(JNIEnv* env)  
  19. {  
  20.     return jniRegisterNativeMethods(env, "com/android/server/SystemServer",  
  21.             gMethods, NELEM(gMethods));  
  22. }  

首先建立 nativeInit () 方法对本地方法 android_server_SystemServer_nativeInit () 的映射,然后 jniRegisterNativeMethods 注册该方法,在上层调用 nativeInit () 方法就可以调用本地方法 android_server_SystemServer_nativeInit () 通过 SensorService::instantiate (); 来实例化 sensorservice,主要是向 servicemanager 注册 sensorservice。

[html] view plain copy
  1.   static status_t publish(bool allowIsolated = false) {  
  2.       sp<IServiceManager> sm(defaultServiceManager());  
  3.       return sm->addService(  
  4.               String16(SERVICE::getServiceName()),  
  5.               new SERVICE(), allowIsolated);  
  6.   }  
  7. static void instantiate() { publish(); }  

addservice () 方法主要是完成向 servicemanager 注册 sensorservice 服务,原型如下:

[html] view plain copy
  1. virtual status_t            addService( const String16& name,  
  2.                                            const sp<IBinder>& service,  
  3.                                            bool allowIsolated = false) = 0;  

其第二个参数也就是 new SERVICE () 是强引用 sp sensorservice,所以会调用到 SensorService::onFirstRef (),这样就开始了 sensorservice 的一系列初始化工作。

3. SensorService::onFirstRef()

[cpp] view plain copy
  1. void SensorService::onFirstRef()  
  2. {  
  3.     ALOGD("nuSensorService starting...");  
  4.   
  5.     SensorDevice& dev(SensorDevice::getInstance());  
  6.   
  7.     if (dev.initCheck() == NO_ERROR) {  
  8.         sensor_t const* list;  
  9.         ssize_t count = dev.getSensorList(&list);  
  10.         if (count > 0) {  
  11.             ssize_t orientationIndex = -1;  
  12.             bool hasGyro = false;  
  13.             uint32_t virtualSensorsNeeds =  
  14.                     (1<<SENSOR_TYPE_GRAVITY) |  
  15.                     (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |  
  16.                     (1<<SENSOR_TYPE_ROTATION_VECTOR);  
  17.   
  18.             mLastEventSeen.setCapacity(count);  
  19.             for (ssize_t i=0 ; i<count ; i++) {  
  20.                 registerSensor( new HardwareSensor(list[i]) );  
  21.                 switch (list[i].type) {  
  22.                     case SENSOR_TYPE_ORIENTATION:  
  23.                         orientationIndex = i;  
  24.                         break;  
  25.                     case SENSOR_TYPE_GYROSCOPE:  
  26.                     case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:  
  27.                         hasGyro = true;  
  28.                         break;  
  29.                     case SENSOR_TYPE_GRAVITY:  
  30.                     case SENSOR_TYPE_LINEAR_ACCELERATION:  
  31.                     case SENSOR_TYPE_ROTATION_VECTOR:  
  32.                         virtualSensorsNeeds &= ~(1<<list[i].type);  
  33.                         break;  
  34.                 }  
  35.             }  
  36.   
  37.             // it''s safe to instantiate the SensorFusion object here  
  38.             // (it wants to be instantiated after h/w sensors have been  
  39.             // registered)  
  40.             const SensorFusion& fusion(SensorFusion::getInstance());  
  41.   
  42.             // build the sensor list returned to users  
  43.             mUserSensorList = mSensorList;  
  44.   
  45.             if (hasGyro) {  
  46.                 Sensor aSensor;  
  47.   
  48.                 // Add Android virtual sensors if they''re not already  
  49.                 // available in the HAL  
  50.   
  51.                 aSensor = registerVirtualSensor( new RotationVectorSensor() );  
  52.                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {  
  53.                     mUserSensorList.add(aSensor);  
  54.                 }  
  55.   
  56.                 aSensor = registerVirtualSensor( new GravitySensor(list, count) );  
  57.                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {  
  58.                     mUserSensorList.add(aSensor);  
  59.                 }  
  60.   
  61.                 aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );  
  62.                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {  
  63.                     mUserSensorList.add(aSensor);  
  64.                 }  
  65.   
  66.                 aSensor = registerVirtualSensor( new OrientationSensor() );  
  67.                 if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {  
  68.                     // if we are doing our own rotation-vector, also add  
  69.                     // the orientation sensor and remove the HAL provided one.  
  70.                     mUserSensorList.replaceAt(aSensor, orientationIndex);  
  71.                 }  
  72.   
  73.                 // virtual debugging sensors are not added to mUserSensorList  
  74.                 registerVirtualSensor( new CorrectedGyroSensor(list, count) );  
  75.                 registerVirtualSensor( new GyroDriftSensor() );  
  76.             }  
  77.   
  78.             // debugging sensor list  
  79.             mUserSensorListDebug = mSensorList;  
  80.   
  81.             // Check if the device really supports batching by looking at the FIFO event  
  82.             // counts for each sensor.  
  83.             bool batchingSupported = false;  
  84.             for (int i = 0; i < mSensorList.size(); ++i) {  
  85.                 if (mSensorList[i].getFifoMaxEventCount() > 0) {  
  86.                     batchingSupported = true;  
  87.                     break;  
  88.                 }  
  89.             }  
  90.   
  91.             if (batchingSupported) {  
  92.                 // Increase socket buffer size to a max of 100 KB for batching capabilities.  
  93.                 mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;  
  94.             } else {  
  95.                 mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;  
  96.             }  
  97.   
  98.             // Compare the socketBufferSize value against the system limits and limit  
  99.             // it to maxSystemSocketBufferSize if necessary.  
  100.             FILE *fp = fopen("/proc/sys/net/core/wmem_max""r");  
  101.             char line[128];  
  102.             if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {  
  103.                 line[sizeof(line) - 1] = ''\0'';  
  104.                 size_t maxSystemSocketBufferSize;  
  105.                 sscanf(line, "%zu", &maxSystemSocketBufferSize);  
  106.                 if (mSocketBufferSize > maxSystemSocketBufferSize) {  
  107.                     mSocketBufferSize = maxSystemSocketBufferSize;  
  108.                 }  
  109.             }  
  110.             if (fp) {  
  111.                 fclose(fp);  
  112.             }  
  113.   
  114.             mWakeLockAcquired = false;  
  115.             mLooper = new Looper(false);  
  116.             const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;  
  117.             mSensorEventBuffer = new sensors_event_t[minBufferSize];  
  118.             mSensorEventScratch = new sensors_event_t[minBufferSize];  
  119.             mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];  
  120.   
  121.             mInitCheck = NO_ERROR;  
  122.             run("SensorService", PRIORITY_URGENT_DISPLAY);  
  123.         }  
  124.     }  
  125. }  
3.1 首先是 sensorDevice 的实例化:

[cpp] view plain copy
  1. SensorDevice::SensorDevice()  
  2.     :  mSensorDevice(0),  
  3.        mSensorModule(0)  
  4. {  
  5.     status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,  
  6.             (hw_module_t const**)&mSensorModule);  
  7.     ALOGE_IF(err, "couldn''t load %s module (%s)",  
  8.             SENSORS_HARDWARE_MODULE_ID, strerror(-err));  
  9.   
  10.     if (mSensorModule) {  
  11.         err = sensors_open_1(&mSensorModule->common, &mSensorDevice);  
  12.   
  13.         ALOGE_IF(err, "couldn''t open device for module %s (%s)",  
  14.                 SENSORS_HARDWARE_MODULE_ID, strerror(-err));  
  15.   
  16.         if (mSensorDevice) {  
  17.             if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 ||  
  18.                 mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) {  
  19.                 ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3");  
  20.             }  
  21.   
  22.             sensor_t const* list;  
  23.             ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);  
  24.             mActivationCount.setCapacity(count);  
  25.             Info model;  
  26.             for (size_t i=0 ; i<size_t(count) ; i++) {  
  27.                 mActivationCount.add(list[i].handle, model);  
  28.                 mSensorDevice->activate(  
  29.                         reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),  
  30.                         list[i].handle, 0);  
  31.             }  
  32.         }  
  33.     }  
  34. }  

sensorDevice 的实例化主要完成以下三项工作:

3.1.1. 主要是为了从 /system/lib/hw 或者 /vendor/lib/hw 路径 load 一个 sensors.(platform).so 的库文件,如 sensors.mt6753.so,第一个参数是我们所获取的 hardware 模块的名字,第二个参数是我们所要获得的 hw_module_t。

[cpp] view plain copy
  1. hw_get_module(SENSORS_HARDWARE_MODULE_ID,  
  2.             (hw_module_t const**)&mSensorModule);  

load () 首先是通过 dlopen () 函数载入前面获取的 path 的动态链接库,如 sensors.mt6753.so,然后使用 dlsym () 函数来获取.so 文件中的符号 HMI 的地址,最后 dlsym () 函数返回 hw_module_t 的地址 hmi,最后将 hmi 的值赋给参数 * pHmi。load () 函数的代码如下:

[cpp] view plain copy
  1. /** 
  2.  * Name of the hal_module_info 
  3.  */  
  4. #define HAL_MODULE_INFO_SYM         HMI  
  5.   
  6. /** 
  7.  * Name of the hal_module_info as a string 
  8.  */  
  9. #define HAL_MODULE_INFO_SYM_AS_STR  "HMI"     // 获取符号 HMI 的地址,然后 dlsym () 函数返回的是 hw_module_t () 的  


[cpp] view plain copy
  1. static int load(const char *id,  
  2.         const char *path,  
  3.         const struct hw_module_t **pHmi)  
  4. {  
  5.     int status;  
  6.     void *handle;  
  7.     struct hw_module_t *hmi;  
  8.   
  9.     /* 
  10.      * load the symbols resolving undefined symbols before 
  11.      * dlopen returns. Since RTLD_GLOBAL is not or''d in with 
  12.      * RTLD_NOW the external symbols will not be global 
  13.      */  
  14.     handle = dlopen(path, RTLD_NOW);  
  15.     if (handle == NULL) {  
  16.         char const *err_str = dlerror();  
  17.         ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");  
  18.         status = -EINVAL;  
  19.         goto done;  
  20.     }  
  21.   
  22.     /* Get the address of the struct hal_module_info. */  
  23.     const char *sym = HAL_MODULE_INFO_SYM_AS_STR;  
  24.     hmi = (struct hw_module_t *)dlsym(handle, sym);  
  25.     if (hmi == NULL) {  
  26.         ALOGE("load: couldn''t find symbol %s", sym);  
  27.         status = -EINVAL;  
  28.         goto done;  
  29.     }  
  30.   
  31.     /* Check that the id matches */  
  32.     if (strcmp(id, hmi->id) != 0) {  
  33.         ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);  
  34.         status = -EINVAL;  
  35.         goto done;  
  36.     }  
  37.   
  38.     hmi->dso = handle;  
  39.   
  40.     /* success */  
  41.     status = 0;  
  42.   
  43.     done:  
  44.     if (status != 0) {  
  45.         hmi = NULL;  
  46.         if (handle != NULL) {  
  47.             dlclose(handle);  
  48.             handle = NULL;  
  49.         }  
  50.     } else {  
  51.         ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",  
  52.                 id, path, *pHmi, handle);  
  53.     }  
  54.   
  55.     *pHmi = hmi;  
  56.   
  57.     return status;  
  58. }  

此处的 hw_get_module () 最后返回的 sensors_module_t 是经过封装的 hw_module_t,他除了包含一个 hw_module_t 还包含一个获取 sensorlist 的 API 这个结构体主要是几个 API 接口的定义,hw_module_t 结构体的定义如下:
[cpp] view plain copy
  1. struct sensors_module_t HAL_MODULE_INFO_SYM = {  
  2.         common:{  
  3.                 tag: HARDWARE_MODULE_TAG,  
  4.                 version_major: 1,  
  5.                 version_minor: 0,  
  6.                 id: SENSORS_HARDWARE_MODULE_ID,  
  7.                 name: "SPRD Sensor module",  
  8.                 author: "Spreadtrum",  
  9.                 methods: &sensors_module_methods,  
  10.                 dso: 0,  
  11.                 reserved:{},  
  12.         },  
  13.         get_sensors_list:sensors__get_sensors_list,  
  14. };  
  15.   
  16. static struct hw_module_methods_t sensors_module_methods = {  
  17. open:    open_sensors  
  18. };  
  19.   
  20. static int sensors__get_sensors_list(struct sensors_module_t *module,  
  21.                      struct sensor_t const **list)  
  22. {  
  23.     *list = sSensorList;  
  24.     return numSensors;  
  25. }  

3.1.2. 通过 sensors_open_1 (&mSensorModule->common, &mSensorDevice) 函数新建并初始化系统所有的 sensor。
[cpp] view plain copy
  1. static inline int sensors_open_1(const struct hw_module_t* module,  
  2.         sensors_poll_device_1_t** device) {  
  3.     return module->methods->open(module,  
  4.             SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);  
  5. }  

这里的 open 函数就是上一步 hw_get_module () 获取的 sensors_module_t 所定义的 sensors_module_methods 的 open_sensors 接口,open_sensors 接口的代码如下:

[cpp] view plain copy
  1. static int open_sensors(const struct hw_module_t* module, const char* id,  
  2.                         struct hw_device_t** device)  
  3. {  
  4.         int status = -EINVAL;  
  5.         sensors_poll_context_t *dev = new sensors_poll_context_t();  
  6.   
  7.         memset(&dev->device, 0, sizeof(sensors_poll_device_t));  
  8.   
  9.         dev->device.common.tag = HARDWARE_DEVICE_TAG;  
  10.         dev->device.common.version  = 0;  
  11.         dev->device.common.module   = const_cast<hw_module_t*>(module);  
  12.         dev->device.common.close    = poll__close;  
  13.         dev->device.activate        = poll__activate;  
  14.         dev->device.setDelay        = poll__setDelay;  
  15.         dev->device.poll            = poll__poll;  
  16.   
  17.         *device = &dev->device.common;  
  18.         status = 0;  
  19.   
  20.         return status;  
  21. }  

函数首先是通过 sensors_poll_context_t () 方法新建并初始化系统所有的 sensor:
[cpp] view plain copy
  1. sensors_poll_context_t::sensors_poll_context_t()  
  2. {  
  3. #ifndef ACC_NULL  
  4.     mSensors[acc] = new AccSensor();  
  5.     numSensors +=  
  6.         mSensors[acc]->populateSensorList(sSensorList + numSensors);  
  7.     mPollFds[acc].fd = mSensors[acc]->getFd();  
  8.     mPollFds[acc].events = POLLIN;  
  9.     mPollFds[acc].revents = 0;  
  10.     ALOGD("AnumSensors=%d; %d", numSensors, AccSensor::numSensors);  
  11. #endif  
  12. #ifndef ORI_NULL  
  13.     mSensors[ori] = new OriSensor();  
  14.     numSensors +=  
  15.         mSensors[ori]->populateSensorList(sSensorList + numSensors);  
  16.     mPollFds[ori].fd = mSensors[ori]->getFd();  
  17.     mPollFds[ori].events = POLLIN;  
  18.     mPollFds[ori].revents = 0;  
  19.     ALOGD("OnumSensors=%d; %d", numSensors, OriSensor::numSensors);  
  20. #endif  
  21. #ifdef SENSORHAL_PROXIMITY_STK  
  22.     mSensors[stk_als] = <span style="color:#FF0000;">new STKLightSensor();</span>  
  23.     numSensors +=  
  24.         mSensors[stk_als]->populateSensorList(sSensorList + numSensors);  
  25.     mPollFds[stk_als].fd = mSensors[stk_als]->getFd();  
  26.     mPollFds[stk_als].events = POLLIN;  
  27.     mPollFds[stk_als].revents = 0;  
  28.       
  29.     mSensors[stk_ps] = new STKProximitySensor();  
  30.     numSensors +=  
  31.         mSensors[stk_ps]->populateSensorList(sSensorList + numSensors);  
  32.     mPollFds[stk_ps].fd = mSensors[stk_ps]->getFd();  
  33.     mPollFds[stk_ps].events = POLLIN;  
  34.     mPollFds[stk_ps].revents = 0;  
  35. #else  
  36. #ifndef PLS_NULL  
  37.     mSensors[pls] = new PlsSensor();  
  38.     numSensors +=  
  39.         mSensors[pls]->populateSensorList(sSensorList + numSensors);  
  40.     mPollFds[pls].fd = mSensors[pls]->getFd();  
  41.     mPollFds[pls].events = POLLIN;  
  42.     mPollFds[pls].revents = 0;  
  43.     ALOGD("PnumSensors=%d; %d", numSensors, PlsSensor::numSensors);  
  44. #endif  
  45. #endif  
  46.     int wakeFds[2];  
  47.     int result = pipe(wakeFds);  
  48.     ALOGE_IF(result < 0, "error creating wake pipe (%s)", strerror(errno));  
  49.     fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);  
  50.     fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);  
  51.     mWritePipeFd = wakeFds[1];  
  52.   
  53.     mPollFds[wake].fd = wakeFds[0];  
  54.     mPollFds[wake].events = POLLIN;  
  55.     mPollFds[wake].revents = 0;  
  56. }  

例如在 new STKLightSensor () 中主要定义了数据读取环形缓冲区的大小,sensor_event_t 的初始化,以及 input 子系统上报事件所保存的路径。STKLightSensor () 代码如下:
[cpp] view plain copy
  1. STKLightSensor::STKLightSensor()  
  2.     : SensorBase(NULL, "lightsensor-level"),  
  3.       mEnabled(0),  
  4.       mInputReader(4),  
  5.       mHasPendingEvent(false) {  
  6.     mPendingEvent.version = sizeof(sensors_event_t);  
  7.     mPendingEvent.sensor = ID_L;  
  8.     mPendingEvent.type = SENSOR_TYPE_LIGHT;  
  9.     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));  
  10.   
  11.     if (data_fd) {  
  12. #if 1         
  13.         strcpy(input_sysfs_path, "/sys/class/input/");  
  14.         strcat(input_sysfs_path, input_name);  
  15.         strcat(input_sysfs_path, "/device/driver/");               // 此项目初始化文件节点所在文件夹目录为:/sys/class/input/input*/device/driver/  
  16.         input_sysfs_path_len = strlen(input_sysfs_path);  
  17. #else         
  18.         strcpy(input_sysfs_path, INPUT_SYSFS_PATH_ALS);  
  19. #endif  
  20.         input_sysfs_path_len = strlen(input_sysfs_path);  
  21.         LOGD("%s: input=%s", __func__, input_name);  
  22.         LOGD("%s: input_sysfs_path = %s\n", __func__, input_sysfs_path);  
  23.     }  
  24.       
  25. }  

open_sensors 第二步是对 sensors_poll_device_t 结构体的初始化,主要是对 sensor 打开,关闭,以及数据获取的 API 借口的定义,这几个 API 接口将在后面详细描述。

3.1.3.  mSensorModule->get_sensors_list (mSensorModule, &list) 这个是前面获取的 sensors_module_t 中定义的 get_sensor_list 方法。他最终获取的是 HAL 层初始化好的 sensor 的列表,并返回 sensor 的数量,active 方法打开 sensor,

[cpp] view plain copy
  1. mSensorDevice->activate(  
  2.                         reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),  
  3.                         list[i].handle, 0);  
mSensorDevice->activate () 调用 HAL 层 activate () 方法,最后调用 HAL 层 sensor 厂商添加的 setEnable () 方法来打开对应 sensor。通过 open 函数获取 sensor 在 sysfs 对应的文件节点,然后使用 write 函数往文件节点里面写 1 即可。

[cpp] view plain copy
  1. static int poll__activate(struct sensors_poll_device_t *dev,  
  2.               int handle, int enabled)  
  3. {  
  4.     sensors_poll_context_t *ctx = (sensors_poll_context_t *) dev;  
  5.     return ctx->activate(handle, enabled);  
  6. }  
  7.   
  8. int sensors_poll_context_t::activate(int handle, int enabled)  
  9. {  
  10.     int drv = handleToDriver(handle);                       // 获取 sensor 的类型  
  11.     int err;  
  12.   
  13.     switch (handle) {  
  14.     case ID_A:  
  15.     case ID_M:  
  16.     case ID_L:  
  17.     case ID_P:  
  18.         /* No dependencies */  
  19.         break;  
  20.   
  21.     case ID_O:  
  22.         /* These sensors depend on ID_A and ID_M */  
  23.         mSensors[handleToDriver(ID_A)]->setEnable(ID_A, enabled);  
  24.         mSensors[handleToDriver(ID_M)]->setEnable(ID_M, enabled);  
  25.         break;  
  26.   
  27.     default:  
  28.         return -EINVAL;  
  29.     }  
  30.   
  31.     ALOGD("activate handle=%d; drv=%d", handle, drv);  
  32.   
  33.     err = mSensors[drv]->setEnable(handle, enabled);                      // 使用对应的 sensor 的 setEnable 方法  
  34.   
  35.     if (enabled && !err) {  
  36.         const char wakeMessage(WAKE_MESSAGE);  
  37.         int result = write(mWritePipeFd, &wakeMessage, 1);  
  38.         ALOGE_IF(result < 0, "error sending wake message (%s)",  
  39.              strerror(errno));  
  40.     }  
  41.     return err;  
  42. }  
  43.   
  44. int STKLightSensor::setEnable(int32_t, int en) {  
  45.    int flags = en ? 1 : 0;  
  46.     if (flags != mEnabled) {  
  47.         int fd;  
  48.         strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); // 初始化的 input_sysfs_path 是 /sys/class/input/input*/device/driver/,此项目的文件节点是  
  49. /sys/class/input/input*/device/driver/enable,所以使用 strcpy 在 input_sysfs_path 后面添加了 enable 节点。  
  50.         fd = open(input_sysfs_path, O_RDWR);                        // 打开对应的 sysfs 目录下的文件节点  
  51.         LOGE("STKLightSensor enable path %s fd %d", input_sysfs_path, fd);  
  52.         if (fd >= 0) {  
  53.             char buf[2];  
  54.             buf[1] = 0;  
  55.             if (flags) {  
  56.                 buf[0] = ''1'';  
  57.             } else {  
  58.                 buf[0] = ''0'';  
  59.             }  
  60.             write(fd, buf, sizeof(buf));                         // 将 buf 的值写到 sysfs 的目录下面 sensor 对应的文件节点  
  61.             close(fd);  
  62.             mEnabled = flags;  
  63.             if(flags)  
  64.                 setInitialState();                        // 处理 sensor 开启后的第一笔数据  
  65.             return 0;  
  66.         }  
  67.         return -1;  
  68.     }  
  69.     return 0;   
  70. }  


如果打开了 sensor,则会调用 setInitialState () 通过 ioctl 来从 data_fd 中获取数据,然后将是否有待处理数据设置为 “true”,在 poll 后面将要讲到的 poll 数据时会直接先处理这个数据。这里获取的数据个人理解是在 sensor 开启之后的第一笔数据。

[cpp] view plain copy
  1. int STKLightSensor::setInitialState() {  
  2.     struct input_absinfo absinfo;  
  3.     if (!ioctl(data_fd, EVIOCGABS(ABS_MISC), &absinfo)) {  
  4.         mPendingEvent.light = (float)absinfo.value;  
  5.         mHasPendingEvent = true;  
  6.     }  
  7.     else  
  8.         ALOGE("%s:ioctl failed!", __func__);          
  9.     return 0;  
  10. }  



至此,sensorDevice 的实例化就完成了。下一篇将继续讲

(OK) android-5.0 sensor工作原理—sensorservice的启动(二)

(OK) android-5.0 sensor工作原理—sensorservice的启动(二)


http://blog.csdn.net/zsj100213/article/details/48287023


3.2 dev.getSensorList(&list);获取厂商在HAL层初始化的sensor_t类型结构体的sSensorList,并返回sensor device的数目。

3.3 registerSensor( new HardwareSensor(list[i]) );在for循环中注册这些sensor。根据硬件sensor_t创建HardwareSensor,然后加入mSensorList(Sensor) 和mSensorMap(HardwareSensor)中,后面的switch是判断是否存在电子罗盘,GYRO以及GYRO对应所需要的对应的一些所对应的一些虚拟sensor

[cpp] view plain copy
  1. for (ssize_t i=0 ; i<count ; i++) {  
  2.                registerSensor( new HardwareSensor(list[i]) );  
  3.                switch (list[i].type) {  
  4.                    case SENSOR_TYPE_ORIENTATION:  
  5.                        orientationIndex = i;  
  6.                        break;  
  7.                    case SENSOR_TYPE_GYROSCOPE:  
  8.                    case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:  
  9.                        hasGyro = true;  
  10.                        break;  
  11.                    case SENSOR_TYPE_GRAVITY:  
  12.                    case SENSOR_TYPE_LINEAR_ACCELERATION:  
  13.                    case SENSOR_TYPE_ROTATION_VECTOR:  
  14.                        virtualSensorsNeeds &= ~(1<<list[i].type);  
  15.                        break;  
  16.                }  

[cpp] view plain copy
  1. Sensor SensorService::registerSensor(SensorInterface* s)  
  2. {  
  3.     sensors_event_t event;  
  4.     memset(&event, 0, sizeof(event));  
  5.   
  6.     const Sensor sensor(s->getSensor());  
  7.     // add to the sensor list (returned to clients)  
  8.     mSensorList.add(sensor);  
  9.     // add to our handle->SensorInterface mapping  
  10.     mSensorMap.add(sensor.getHandle(), s);  
  11.     // create an entry in the mLastEventSeen array  
  12.     mLastEventSeen.add(sensor.getHandle(), event);  
  13.   
  14.     return sensor;  
  15. }  

3.4 mUserSensorList = mSensorList;将mSensorList传感器列表赋值给mUserSensorList,mSensorList是由registerSensor初始化的,mUserSensorList是要提交给Java框架层的传感器列表。


3.5 如果有GYRO就注册这样一些上面提到的三种虚拟sensor来实现GYRO的功能,此处我是这么理解的。

[cpp] view plain copy
  1. if (hasGyro) {  
  2.                Sensor aSensor;  
  3.   
  4.                // Add Android virtual sensors if they''re not already  
  5.                // available in the HAL  
  6.   
  7.                aSensor = registerVirtualSensor( new RotationVectorSensor() );  
  8.                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {  
  9.                    mUserSensorList.add(aSensor);  
  10.                }  
  11.   
  12.                aSensor = registerVirtualSensor( new GravitySensor(list, count) );  
  13.                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {  
  14.                    mUserSensorList.add(aSensor);  
  15.                }  
  16.   
  17.                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );  
  18.                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {  
  19.                    mUserSensorList.add(aSensor);  
  20.                }  
  21.   
  22.                aSensor = registerVirtualSensor( new OrientationSensor() );  
  23.                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {  
  24.                    // if we are doing our own rotation-vector, also add  
  25.                    // the orientation sensor and remove the HAL provided one.  
  26.                    mUserSensorList.replaceAt(aSensor, orientationIndex);  
  27.                }  
  28.   
  29.                // virtual debugging sensors are not added to mUserSensorList  
  30.                registerVirtualSensor( new CorrectedGyroSensor(list, count) );  
  31.                registerVirtualSensor( new GyroDriftSensor() );  
  32.            }  

3.6 run("SensorService", PRIORITY_URGENT_DISPLAY);启动sensorService线程,sensorService父类有一个Thread线程,调用run方法会创建线程并调用threadLoop方法。
[cpp] view plain copy
  1. bool SensorService::threadLoop()  
  2. {  
  3.     ALOGD("nuSensorService thread starting...");  
  4.   
  5.     // each virtual sensor could generate an event per "real" event, that''s why we need  
  6.     // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.  
  7.     // in practice, this is too aggressive, but guaranteed to be enough.  
  8.     const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;  
  9.     const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());  
  10.   
  11.     SensorDevice& device(SensorDevice::getInstance());  
  12.     const size_t vcount = mVirtualSensorList.size();  
  13.   
  14.     SensorEventAckReceiver sender(this);  
  15.     sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);  
  16.     const int halVersion = device.getHalDeviceVersion();  
  17.     do {  
  18.         ssize_t count = device.poll(mSensorEventBuffer, numEventMax);  
  19.         if (count < 0) {  
  20.             ALOGE("sensor poll failed (%s)", strerror(-count));  
  21.             break;  
  22.         }  
  23.   
  24.         // Reset sensors_event_t.flags to zero for all events in the buffer.  
  25.         for (int i = 0; i < count; i++) {  
  26.              mSensorEventBuffer[i].flags = 0;  
  27.         }  
  28.   
  29.         // Make a copy of the connection vector as some connections may be removed during the  
  30.         // course of this loop (especially when one-shot sensor events are present in the  
  31.         // sensor_event buffer). Promote all connections to StrongPointers before the lock is  
  32.         // acquired. If the destructor of the sp gets called when the lock is acquired, it may  
  33.         // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for  
  34.         // cleanup. So copy all the strongPointers to a vector before the lock is acquired.  
  35.         SortedVector< sp<SensorEventConnection> > activeConnections;  
  36.         {  
  37.             Mutex::Autolock _l(mLock);  
  38.             for (size_t i=0 ; i < mActiveConnections.size(); ++i) {  
  39.                 sp<SensorEventConnection> connection(mActiveConnections[i].promote());  
  40.                 if (connection != 0) {  
  41.                     activeConnections.add(connection);  
  42.                 }  
  43.             }  
  44.         }  
  45.   
  46.         Mutex::Autolock _l(mLock);  
  47.         // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The  
  48.         // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,  
  49.         // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should  
  50.         // not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and  
  51.         // releasing the wakelock.  
  52.         bool bufferHasWakeUpEvent = false;  
  53.         for (int i = 0; i < count; i++) {  
  54.             if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {  
  55.                 bufferHasWakeUpEvent = true;  
  56.                 break;  
  57.             }  
  58.         }  
  59.   
  60.         if (bufferHasWakeUpEvent && !mWakeLockAcquired) {  
  61.             acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);  
  62.             mWakeLockAcquired = true;  
  63.         }  
  64.         recordLastValueLocked(mSensorEventBuffer, count);  
  65.   
  66.         // handle virtual sensors  
  67.         if (count && vcount) {  
  68.             sensors_event_t const * const event = mSensorEventBuffer;  
  69.             const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();  
  70.             if (activeVirtualSensorCount) {  
  71.                 size_t k = 0;  
  72.                 SensorFusion& fusion(SensorFusion::getInstance());  
  73.                 if (fusion.isEnabled()) {  
  74.                     for (size_t i=0 ; i<size_t(count) ; i++) {  
  75.                         fusion.process(event[i]);  
  76.                     }  
  77.                 }  
  78.                 for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {  
  79.                     for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {  
  80.                         if (count + k >= minBufferSize) {  
  81.                             ALOGE("buffer too small to hold all events: "  
  82.                                     "count=%zd, k=%zu, size=%zu",  
  83.                                     count, k, minBufferSize);  
  84.                             break;  
  85.                         }  
  86.                         sensors_event_t out;  
  87.                         SensorInterface* si = mActiveVirtualSensors.valueAt(j);  
  88.                         if (si->process(&out, event[i])) {  
  89.                             mSensorEventBuffer[count + k] = out;  
  90.                             k++;  
  91.                         }  
  92.                     }  
  93.                 }  
  94.                 if (k) {  
  95.                     // record the last synthesized values  
  96.                     recordLastValueLocked(&mSensorEventBuffer[count], k);  
  97.                     count += k;  
  98.                     // sort the buffer by time-stamps  
  99.                     sortEventBuffer(mSensorEventBuffer, count);  
  100.                 }  
  101.             }  
  102.         }  
  103.   
  104.         // handle backward compatibility for RotationVector sensor  
  105.         if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {  
  106.             for (int i = 0; i < count; i++) {  
  107.                 if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {  
  108.                     // All the 4 components of the quaternion should be available  
  109.                     // No heading accuracy. Set it to -1  
  110.                     mSensorEventBuffer[i].data[4] = -1;  
  111.                 }  
  112.             }  
  113.         }  
  114.   
  115.         // Map flush_complete_events in the buffer to SensorEventConnections which called  
  116.         // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the  
  117.         // SensorEventConnection mapped to the corresponding flush_complete_event in  
  118.         // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).  
  119.         for (int i = 0; i < count; ++i) {  
  120.             mMapFlushEventsToConnections[i] = NULL;  
  121.             if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {  
  122.                 const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;  
  123.                 SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);  
  124.                 if (rec != NULL) {  
  125.                     mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();  
  126.                     rec->removeFirstPendingFlushConnection();  
  127.                 }  
  128.             }  
  129.         }  
  130.   
  131.         // Send our events to clients. Check the state of wake lock for each client and release the  
  132.         // lock if none of the clients need it.  
  133.         bool needsWakeLock = false;  
  134.         size_t numConnections = activeConnections.size();  
  135.         for (size_t i=0 ; i < numConnections; ++i) {  
  136.             if (activeConnections[i] != 0) {  
  137.                 activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,  
  138.                         mMapFlushEventsToConnections);  
  139.                 needsWakeLock |= activeConnections[i]->needsWakeLock();  
  140.                 // If the connection has one-shot sensors, it may be cleaned up after first trigger.  
  141.                 // Early check for one-shot sensors.  
  142.                 if (activeConnections[i]->hasOneShotSensors()) {  
  143.                     cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,  
  144.                             count);  
  145.                 }  
  146.             }  
  147.         }  
  148.   
  149.         if (mWakeLockAcquired && !needsWakeLock) {  
  150.             release_wake_lock(WAKE_LOCK_NAME);  
  151.             mWakeLockAcquired = false;  
  152.         }  
  153.     } while (!Thread::exitPending());  
  154.   
  155.     ALOGW("Exiting SensorService::threadLoop => aborting...");  
  156.     abort();  
  157.     return false;  
  158. }  

3.6.1 首先是调用device.poll(mSensorEventBuffer, numEventMax);来获取sensor数据。这里调用的是前面open_sensors函数初始化的 dev->device.poll            = poll__poll;
[cpp] view plain copy
  1. static int poll__poll(struct sensors_poll_device_t *dev,  
  2.         sensors_event_t* data, int count) {  
  3.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  4.     return ctx->pollEvents(data, count);  
  5. }  

可以看到最后调用的是pollEvents函数:
[cpp] view plain copy
  1. int sensors_poll_context_t::pollEvents(sensors_event_t * data, int count)  
  2. {  
  3.     int nbEvents = 0;  
  4.     int n = 0;  
  5.     int polltime = -1;  
  6.   
  7.     do {  
  8.         // see if we have some leftover from the last poll()  
  9.         for (int i = 0; count && i < numSensorDrivers; i++) {  
  10.             SensorBase *const sensor(mSensors[i]);  
  11.             if ((mPollFds[i].revents & POLLIN)  
  12.                 || (sensor->hasPendingEvents())) {  
  13.                 int nb = sensor->readEvents(data, count);  
  14.                 if (nb < count) {  
  15.                     // no more data for this sensor  
  16.                     mPollFds[i].revents = 0;  
  17.                 }  
  18. #ifndef ORI_NULL  
  19.                 if ((0 != nb) && (acc == i)) {  
  20.                     ((OriSensor *) (mSensors[ori]))->  
  21.                         setAccel(&data[nb - 1]);  
  22.                 }  
  23. #endif  
  24.                 count -= nb;  
  25.                 nbEvents += nb;  
  26.                 data += nb;  
  27.             }  
  28.         }  
  29.   
  30.         if (count) {  
  31.             // we still have some room, so try to see if we can get  
  32.             // some events immediately or just wait if we don''t have  
  33.             // anything to return  
  34.             do {  
  35.                 n = poll(mPollFds, numFds,  
  36.                      nbEvents ? 0 : polltime);  
  37.             } while (n < 0 && errno == EINTR);  
  38.             if (n < 0) {  
  39.                 ALOGE("poll() failed (%s)", strerror(errno));  
  40.                 return -errno;  
  41.             }  
  42.             if (mPollFds[wake].revents & POLLIN) {  
  43.                 char msg;  
  44.                 int result = read(mPollFds[wake].fd, &msg, 1);  
  45.                 ALOGE_IF(result < 0,  
  46.                      "error reading from wake pipe (%s)",  
  47.                      strerror(errno));  
  48.                 ALOGE_IF(msg != WAKE_MESSAGE,  
  49.                      "unknown message on wake queue (0x%02x)",  
  50.                      int (msg));  
  51.                 mPollFds[wake].revents = 0;  
  52.             }  
  53.         }  
  54.         // if we have events and space, go read them  
  55.     } while (n && count);  
  56.   
  57.     return nbEvents;  
  58. }  

这里首先调用的是sensor->readEvents(data, count);也就是各个sensor对应的读取sensor event的方法。readEvents()函数先调用fill函数将所要读的sensor的input_event事件读取到一个环形缓冲区,然后在while循环中mInputReader.readEvent(&event)读取当前指针所指向的事件,mInputReader.next();将指针指向环形队列下一条事件来读取下一条事件。

[cpp] view plain copy
  1. int STKLightSensor::readEvents(sensors_event_t* data, int count){  
  2.     if (count < 1)  
  3.         return -EINVAL;  
  4.   
  5.     if (mHasPendingEvent) {  
  6.         mHasPendingEvent = false;  
  7.         mPendingEvent.timestamp = getTimestamp();  
  8.         *data = mPendingEvent;  
  9.         return mEnabled ? 1 : 0;  
  10.     }  
  11.   
  12.     ssize_t n = mInputReader.fill(data_fd);  
  13.     if (n < 0)  
  14.         return n;  
  15.   
  16.     int numEventReceived = 0;  
  17.     input_event const* event;  
  18.   
  19.     while (count && mInputReader.readEvent(&event)) {  
  20.         int type = event->type;  
  21.         if (type == EV_ABS) {  
  22.             if (event->code == ABS_MISC) {  
  23.                 mPendingEvent.light = (float)event->value;  
  24.             }  
  25.         } else if (type == EV_SYN) {  
  26.             mPendingEvent.timestamp = timevalToNano(event->time);  
  27.             if (mEnabled) {  
  28.                 *data++ = mPendingEvent;  
  29.                 count--;  
  30.                 numEventReceived++;  
  31.             }  
  32.         } else {  
  33.             ALOGE("STKLightSensor: unknown event (type=%d, code=%d)",  
  34.                     type, event->code);  
  35.         }  
  36.         mInputReader.next();  
  37.     }  
  38.   
  39.     return numEventReceived;  
  40. }  

fill函数的参数data_fd是在前面sensors_poll_context_t()函数中的new STKLightSensor();进行初始化的,其主要是SensorBase(NULL, "lightsensor-level"),这里主要是openInput动作来获得一个fd从而从这个fd的文件中获取sensor event。


[cpp] view plain copy
  1. ssize_t InputEventCircularReader::fill(int fd)  
  2. {  
  3.     size_t numEventsRead = 0;  
  4.     if (mFreeSpace) {  
  5.         const ssize_t nread =  
  6.             read(fd, mHead, mFreeSpace * sizeof(input_event));  
  7.         if (nread < 0 || nread % sizeof(input_event)) {  
  8.             // we got a partial event!!  
  9.             return nread < 0 ? -errno : -EINVAL;  
  10.         }  
  11.   
  12.         numEventsRead = nread / sizeof(input_event);  
  13.         if (numEventsRead) {  
  14.             mHead += numEventsRead;  
  15.             mFreeSpace -= numEventsRead;  
  16.             if (mHead > mBufferEnd) {  
  17.                 size_t s = mHead - mBufferEnd;  
  18.                 memcpy(mBuffer, mBufferEnd,  
  19.                        s * sizeof(input_event));  
  20.                 mHead = mBuffer + s;  
  21.             }  
  22.         }  
  23.     }  
  24.   
  25.     return numEventsRead;  
  26. }  
  27.   
  28. ssize_t InputEventCircularReader::readEvent(input_event const **events)  
  29. {  
  30.     *events = mCurr;  
  31.     ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;  
  32.     return available ? 1 : 0;  
  33. }  
  34.   
  35. void InputEventCircularReader::next()  
  36. {  
  37.     mCurr++;  
  38.     mFreeSpace++;  
  39.     if (mCurr >= mBufferEnd) {  
  40.         mCurr = mBuffer;  
  41.     }  
  42. }  

[cpp] view plain copy
  1. SensorBase::SensorBase(  
  2.         const char* dev_name,  
  3.         const char* data_name)  
  4.     : dev_name(dev_name), data_name(data_name),  
  5.       dev_fd(-1), data_fd(-1)  
  6. {  
  7.     if (data_name) {  
  8.         data_fd = openInput(data_name);  
  9.     }  
  10. }  


openInput()实际上是打开各个sensor对应于/dev/input/event*文件节点最后返回的是sensor对应文件节点的fd,也就是上面fill函数的参数data_fd,在adb shell,然后getevent命令也是获取位于/dev/input/下所有的event事件。


[cpp] view plain copy
  1. int SensorBase::openInput(const char* inputName) {  
  2.     int fd = -1;  
  3.     const char *dirname = "/dev/input";  
  4.     char devname[PATH_MAX];  
  5.     char *filename;  
  6.     DIR *dir;  
  7.     struct dirent *de;  
  8.     dir = opendir(dirname);  
  9.     if(dir == NULL)  
  10.         return -1;  
  11.     strcpy(devname, dirname);  
  12.     filename = devname + strlen(devname);  
  13.     *filename++ = ''/'';  
  14.     while((de = readdir(dir))) {  
  15.         if(de->d_name[0] == ''.'' &&  
  16.                 (de->d_name[1] == ''\0'' ||  
  17.                         (de->d_name[1] == ''.'' && de->d_name[2] == ''\0'')))  
  18.             continue;  
  19.         strcpy(filename, de->d_name);  
  20.         fd = open(devname, O_RDONLY);  
  21.         if (fd>=0) {  
  22.             char name[80];  
  23.             if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {  
  24.                 name[0] = ''\0'';  
  25.             }  
  26.             if (!strcmp(name, inputName)) {  
  27.                 strcpy(input_name, filename);  
  28.                 break;  
  29.             } else {  
  30.                 close(fd);  
  31.                 fd = -1;  
  32.             }  
  33.         }  
  34.     }  
  35.     closedir(dir);  
  36.     ALOGE_IF(fd<0, "couldn''t find ''%s'' input device", inputName);  
  37.     return fd;  

在获取完数据之后就要通过 activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,mMapFlushEventsToConnections);调用write函数将数据放到一个管道里面,sensor APP将数据取走。

[cpp] view plain copy
  1. ssize_t size = SensorEventQueue::write(mChannel,  
  2.                                 reinterpret_cast<ASensorEvent const*>(scratch), count);  

至此sensorservice的启动就讲完了,下一篇将从sensor APP端讲述sensor APP的工作流程。

Android Firebase addListenerForSingleValueEvent不起作用

Android Firebase addListenerForSingleValueEvent不起作用

我知道这已被问了很多,但我仍然可以让它工作.这是我的代码:

private int test;

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userRef = rootRef.child("Users");

test = 0;
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
   @Override
   public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.hasChild(userID))
            test = 1;
        else
            test = 2;
   }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

Log.d(TAG, "Test = " + test);

这是Firebase上的内容:

> appname-e545e

>用户

> userID

我不知道为什么但变量“test”总是返回值0,这意味着addListenerForSingleValueEvent不起作用.感谢您提前帮助

解决方法:

数据是从Firebase异步加载的.到日志测试时,onDataChange还没有运行.

要查看此操作,请在onDataChange中添加更多日志记录:

私人int测试;

test = 0;
userRef.addListenerForSingleValueEvent(new ValueEventListener() {
   @Override
   public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.hasChild(userID)) {
            test = 1;
        }
        else {
            test = 2;
        }
        Log.d(TAG, "Test2 = " + test);
   }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException(); // Don't ignore errors
    }
});

Log.d(TAG, "Test = " + test);

现在你先看到:

Test = 0

然后一旦数据加载并调用onDataChange:

Test = 1

要么

Test = 2

因此,您应始终在onDataChange()中放置(或调用)需要数据库数据的代码.

Android NDK and OpenCV Development With Android Studio

Android NDK and OpenCV Development With Android Studio

---------------- If you do NOT know Chinese, you can just skip this part ----------------

一直打算将原来的XFace进行改进,最近终于有了些时间可以动手了,改进计划如下:开发上使用Android Studio作为新的开发环境,配上新的构建系统Gradle;应用上将修改原来的UI设计,内部代码也将有很大的变化,可能会用上ContentProvider和Service等略高级内容;算法上打算让应用扩展性增强以适应不同的算法,并结合强大的Android Studio和Gradle让这个项目变得更加丰富。说了一堆废话,言归正传,本文的重点是介绍如何在Android Studio中进行NDK开发(目前它还不完全支持NDK开发),难点是NDK中还包含OpenCV的动态库。最后的最后,本文剩下部分将使用英文,因为它要成为我在StackOverflow上的处女答,么么哒 ~O(∩_∩)O~

---------------------------- Here is the right stuff you may need --------------------------------

This post shows how to develop an Android NDK application with OpenCV included using Android Studio and Gradle. If you''re working on migrating your original Eclipse Project to Android Studio, you may find this post is what exactly you want!

OK,Let''s start!

Section 1: Three things you must know

1.Firstly, if you are not familiar with Android Studio and Gradle, you may find these links useful. (if you already know these well, skip this part)

①Creating a new Project with Android Studio

②Building Your Project with Gradle

③Gradle Plugin User Guide or you may want to read a Chinese commented version in my blog here.

2.Secondly, if your android ndk project is not that complicated(for example, having no opencv included), you may wanna see ph0b ''s introduction here, it''s quite a nice job with a video recorded! (you can also follow Section 2 in this post to get a simple Android NDK demo application)

ph0b''s post: ANDROID STUDIO, GRADLE AND NDK INTEGRATION

3.Thirdly, if those above two do not meet your needs, then I think you may want to customize the Android.mk with Gradle in Android Studio. Thanks to Gaku Ueda , he had made a great job explaining how to achieve that goal. Actually I have found another nicer solution without adding that many codes and also achieve that goal. :-) Find it out in the next sections.

Gaku Ueda''s post: Using custom Android.mk with Gradle/Android Studio

OK, I will cover all above and give another nice solution in the end, have fun!

Section 2: A simple Android NDK demo application

This section shows creating a simple Android NDK demo application, if you already know, you can directly go the section 3.

1.Create a new Android project named NDKDemo with a blank Activity in AS(=Android Studio).

2.Give an id to the TextView in activity_my.xml such as android:id="@+id/textview", then add these codes in MyActivity.java.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_my);

    TextView textView = (TextView) findViewById(R.id.textview);
    textView.setText(hello());
}

static {
    System.loadLibrary("hello");
}

public native String hello();

3.Create a new directory jni in folder app/src/main, then you have java, jni and res in this folder.

4.This step is very important! You can add a external tool to run the javah command without typing that much code!

Open AS''s Preferences, then find External Tools in IDE Settings, click + to add one tool with the following configurations. (Make sure you have add JDK tools in your system path, if you don''t know how, click here)

image

With the help of this tool, each time we right click on a class file, then choose Android Tools -> javah to run this tool, it will automatically generate a C head file for us in the target folder $ModuleFileDir$/src/main/jni , in this case, it is app/src/main/jni. Try this on MyActivity.java file now! The console will print out a log like:

/usr/bin/javah -v -jni -d /Users/hujiawei/AndroidStudioProjects/NDKDemo/app/src/main/jni com.android.hacks.ndkdemo.MyActivity [Creating file RegularFileObject[/Users/hujiawei/AndroidStudioProjects/NDKDemo/app/src/main/jni/ com_android_hacks_ndkdemo_MyActivity.h]]

Then you get a com_android_hacks_ndkdemo_MyActivity.h file in jni folder with the following content.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_android_hacks_ndkdemo_MyActivity */

#ifndef _Included_com_android_hacks_ndkdemo_MyActivity
#define _Included_com_android_hacks_ndkdemo_MyActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_android_hacks_ndkdemo_MyActivity
 * Method:    hello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_android_hacks_ndkdemo_MyActivity_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

5.Write a simple C implementation file named main.c in jni folder

#include <jni.h>
#include "com_android_hacks_ndkdemo_MyActivity.h"

JNIEXPORT jstring JNICALL Java_com_android_hacks_ndkdemo_MyActivity_hello
  (JNIEnv * env, jobject obj){
    return (*env)->NewStringUTF(env, "Hello from JNI");
  }

6.In the build.gradle file under app module, add the following codes to configure ndk in defaultConfig element, here we just give the uni module a name hello, you can find other configurations in Gradle Plugin User Guide.

defaultConfig {
    applicationId "com.android.hacks.ndkdemo"
    minSdkVersion 16
    targetSdkVersion 20
    versionCode 1
    versionName "1.0"

    ndk{
        moduleName "hello"
    }
}

7.In order to let Gradle run ndk-build command (in some task, maybe NdkCompile task), we should configure the ndk.dir in local.properties file in Project root.

sdk.dir=/Volumes/hujiawei/Users/hujiawei/Android/android_sdk
ndk.dir=/Volumes/hujiawei/Users/hujiawei/Android/android_ndk

8.OK, everything is ready, click Run to give it a try, you will see the result like

image

All right, so what''s happening inside?

Since you have a jni folder, Gradle will consider it as a default native code folder. When Gradle builds the app, it will run ndk-build command(since you have configured ndk.dir, Gradle knows where to find it) with a generated Android.mk file(locates in app/build/intermediates/ndk/debug/Android.mk), after compiling the native codes, it will generate the libs and obj folder into folder app/build/intermediates/ndk/debug/. Gradle will then package the libs into final apk file in folder app/build/outputs/apk/app-debug.apk(you can unarchive this file to check whether libs is contained)

app/build/intermediates/ndk/debug (lib and obj folders)

image

app/build/outputs/apk/app-debug.apk (and files within it)

image

Secontion 3: Using OpenCV

If your project do not use OpenCV, then the section 2 is just enough. But what if you wanna use OpenCV to do other stuff? Of course, we want to use OpenCV for Android instead of JavaCV here, and Of course, we need to package OpenCV library for Android into our application''s APK file (then users who use this app does not have to install OpenCV Manager). So, how can we achieve these goals?

The simplest way has been posted by TGMCians on Stack Overflow here, that is, let the main app include the OpenCV library as a dependency, and copy all <abi>/*.so files in OpenCV for Android SDK to jniLibs folder under app/src/main/, Gradle will automatically package these <abi>/*.so files into libs folder within the final APK file. Of course, this method will work, but it has a few backwards: (1) Unless you only copy the needed *.so files, you will always have a large APK due to this reason; (2) How about the building of the jni files? How to run ndk-build if these files contain opencv related codes?

So, here comes to our Using custom Android.mk with Gradle and Android Studio part. For testing, we first creat an Android.mk and an Application.mk file under jni folder.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS += -llog
LOCAL_MODULE := hello

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_ABI := armeabi
APP_PLATFORM := android-16

Thanks to Gaku Ueda, he had made a great job explaining how to achieve that goal with this post. The core idea of his method is to run ndk-build command in some task, then zip the <abi>/*.so files under the output app/build/libs/ folder into a jar file which is finally put in app/build/libs/ folder, then add a compile dependency to this jar file. The key code for his method listed below

Notice 1: When using custom Android.mk, we should first disable Gradle to build the jni folder as before, and sourceSets.main.jni.srcDirs = [] just does this job!

Notice 2: The code is not exactly the same with Gaku Ueda''s code: tasks.withType(Compile) to tasks.withType(JavaCompile), because Compile is deprecated.

Notice 3: You can get $ndkDir variable with project.plugins.findPlugin(''com.android.application'').getNdkFolder() or you can define it in grade.properties file under Project root, so you need to add ndkDir=path/to/your/ndk in that file, if the file is not created, simply create a new one.

android{
    ...
    sourceSets.main.jni.srcDirs = []

    task ndkBuild(type: Exec, description: ''Compile JNI source via NDK'') {
        ndkDir = project.plugins.findPlugin(''com.android.application'').getNdkFolder()
        commandLine "$ndkDir/ndk-build",
                ''NDK_PROJECT_PATH=build'',
                ''APP_BUILD_SCRIPT=src/main/jni/Android.mk'',
                ''NDK_APPLICATION_MK=src/main/jni/Application.mk''
    }

    task ndkLibsToJar(type: Zip, dependsOn: ''ndkBuild'', description: ''Create a JAR of the native libs'') {
        destinationDir new File(buildDir, ''libs'')
        baseName ''ndk-libs''
        extension ''jar''
        from(new File(buildDir, ''libs'')) { include ''**/*.so'' }
        into ''lib/''
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkLibsToJar
    }
    ...
}

dependencies {
    compile fileTree(dir: ''libs'', include: [''*.jar''])
    // add begin
    compile fileTree(dir: new File(buildDir, ''libs''), include: ''*.jar'')
    // add end
}

But we can still do a little improvements here. We have already know that Gradle will take jniLibs folder as its default native libraries folder, so we can simply output the libs/<abi>/*.so files generated by ndk-build command into jniLibs folder, so there''s no need to zip these *.so files into a jar file.

The final build.gradle file under app module

apply plugin: ''com.android.application''

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.android.hacks.ndkdemo"
        minSdkVersion 16
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }

    // add begin
    sourceSets.main.jni.srcDirs = []

    task ndkBuild(type: Exec, description: ''Compile JNI source via NDK'') {
        ndkDir = project.plugins.findPlugin(''com.android.application'').getNdkFolder()
        commandLine "$ndkDir/ndk-build",
                ''NDK_PROJECT_PATH=build/intermediates/ndk'',
                ''NDK_LIBS_OUT=src/main/jniLibs'',
                ''APP_BUILD_SCRIPT=src/main/jni/Android.mk'',
                ''NDK_APPLICATION_MK=src/main/jni/Application.mk''
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }
    // add end

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile(''proguard-android.txt''), ''proguard-rules.pro''
        }
    }
}

dependencies {
    compile fileTree(dir: ''libs'', include: [''*.jar''])
}

So simple, right? ''NDK_LIBS_OUT=src/main/jniLibs'' helps us do the right job!

For testing, you can also add some lines relating with OpenCV in your Android.mk file and some line in your main.c to check whether everything is readlly working. For example, add #include <opencv2/core/core.hpp> in main.c file, and change Android.mk to

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#opencv
OPENCVROOT:= /Volumes/hujiawei/Users/hujiawei/Android/opencv_sdk
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk

LOCAL_SRC_FILES := main.c
LOCAL_LDLIBS += -llog
LOCAL_MODULE := hello

include $(BUILD_SHARED_LIBRARY)

In Gradle Console window, you can see these similar lines

image

*.so files relating with OpenCV has been packaged into the final APK

image

One More Thing

Of course, maybe you don''t want to change your build.grale file with that much code, and Of course, you also don''t want to run ndk-build outside the IDE, then copy the <abi>/*.so files into jniLibs folder each time you want to rebuild the native codes!

At last, I came out another nicer solution, if you like, that is to create a ndk-build external tool in Android Studio, and every time you want to rebuild the native codes, simply run the external tool, then it automatically generates the libs/<abi>/*.so files into jniLibs folder, so everything is ready to run this app, :-)

The configuration is simple

Parameters: NDK_PROJECT_PATH=$ModuleFileDir$/build/intermediates/ndk NDK_LIBS_OUT=$ModuleFileDir$/src/main/jniLibs NDK_APPLICATION_MK=$ModuleFileDir$/src/main/jni/Application.mk APP_BUILD_SCRIPT=$ModuleFileDir$/src/main/jni/Android.mk V=1

image

OK, I hope it is helpful. Let me know if it is really helpful, or tell me what''s your problem. :-)

关于Android SensorEvent时间戳常量android 获取时间戳的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于(OK) android-5.0 sensor 工作原理 —sensorservice 的启动 (一)、(OK) android-5.0 sensor工作原理—sensorservice的启动(二)、Android Firebase addListenerForSingleValueEvent不起作用、Android NDK and OpenCV Development With Android Studio的相关知识,请在本站寻找。

本文标签: