Android NDK传感器向事件队列报告奇怪的时间间隔

6
我尝试从NDK访问加速度计。到目前为止,它可以正常工作。但是将事件写入事件队列的方式似乎有点奇怪。
请参阅以下代码:
ASensorManager* AcquireASensorManagerInstance(void) {
    typedef ASensorManager *(*PF_GETINSTANCEFORPACKAGE)(const char *name);
    void* androidHandle = dlopen("libandroid.so", RTLD_NOW);
    PF_GETINSTANCEFORPACKAGE getInstanceForPackageFunc = (PF_GETINSTANCEFORPACKAGE) dlsym(androidHandle, "ASensorManager_getInstanceForPackage");
    if (getInstanceForPackageFunc) {
        return getInstanceForPackageFunc(kPackageName);
    }

    typedef ASensorManager *(*PF_GETINSTANCE)();
    PF_GETINSTANCE getInstanceFunc = (PF_GETINSTANCE) dlsym(androidHandle, "ASensorManager_getInstance");

    return getInstanceFunc();
}

void init() {
    sensorManager = AcquireASensorManagerInstance();
    accelerometer = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER);

    looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);

    accelerometerEventQueue = ASensorManager_createEventQueue(sensorManager, looper, LOOPER_ID_USER, NULL, NULL);

    auto status = ASensorEventQueue_enableSensor(accelerometerEventQueue,
                                                 accelerometer);
    status = ASensorEventQueue_setEventRate(accelerometerEventQueue,
                                            accelerometer,
                                            SENSOR_REFRESH_PERIOD_US);
}

这是我初始化所有内容的方式。我的SENSOR_REFRESH_PERIOD_US为100,000,因此每秒刷新10次。现在我有以下方法来接收事件队列中的事件。

vector<sensorEvent> update() {
    ALooper_pollAll(0, NULL, NULL, NULL);

    vector<sensorEvent> listEvents;
    ASensorEvent event;

    while (ASensorEventQueue_getEvents(accelerometerEventQueue, &event, 1) > 0) {
        listEvents.push_back(sensorEvent{event.acceleration.x, event.acceleration.y, event.acceleration.z, (long long) event.timestamp});
    }

    return listEvents;
}

sensorEvent 这里是我使用的一个自定义结构体。这个 update 方法会通过 JNI 从 Android 调用,在每个来自 IntentService 的 10 秒钟中运行一次(即使应用程序已经被杀死)。现在,我希望能够收到 100 个数值(每秒 10 次 * 10 秒)。在不同的测试中,我收到了大约 130 个数值,即使有点偏差也完全可以接受。然后,我在 ASensorEventQueue_setEventRate 的文档中读到,它并不强制遵循给定的刷新周期。因此,如果我得到的数值比我想要的更多,那么完全没问题。

但现在问题来了:有时我在 10 秒内只收到了 13 个值,当我在 10 秒后继续调用 update 时,我会得到 130 个值 + 上一次丢失的 117 个值。这种情况完全是随机出现的,有时候不是下一次运行就是第四次之后才出现这种情况。

如果我获得了更多的值而与刷新周期有所偏差,那我完全可以接受。但是否有人能解释一下为什么会有这么多的值丢失,而它们会在下一次运行时出现?或者是否有方法可以确保我在期望的运行中收到这些值?


为什么要使用NDK访问传感器,与SensorManager代码相比有什么优势?我只是出于好奇而问。 - Thracian
1
一些传感器具有FIFO批处理缓冲区,但并非每个供应商都为SDK实现它。我发现通过NDK访问它时,可以使用此FIFO缓冲区并且能够大大降低能量消耗。 - Phil
1个回答

0

您的代码是正确的,我看到只有一个原因可能会导致这种行为。这是Android系统的问题,为了避免电池耗尽,在应用程序进入后台或设备休眠一段时间后,陀螺仪事件流的频率会降低。

您需要检查所有与陀螺仪相关的逻辑,并根据Doze and App Standby进行优化。

此外,您可以尝试在前台服务中使用陀螺仪。


感谢您的回答。 不幸的是,这种行为在 Android 5.1 上也是可重现的,而那里并不存在 Doze 模式,所以我认为这不可能是问题的原因。 - Phil
也许这正是你需要的内容? https://source.android.com/devices/sensors/suspend-mode. https://source.android.com/devices/sensors/batching.html - Onix

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接