今天来跟一下Monado Runtime从ipc_server启动到device端获取3DoF数据的源码,
个人理解,可能会有纰漏
开始吧。
注释:src\xrt\targets\service-lib\service_target.cpp
runtime client端通过jni函数call runtime server
extern "C" void
Java_org_freedesktop_monado_ipc_MonadoImpl_nativeStartServer(JNIEnv *env, jobject thiz)
{
jni::init(env);
jni::Object monadoImpl(thiz);
U_LOG_D("service: Called nativeStartServer");
IpcServerHelper::instance().startServer();
}
注释:service_target.cpp中定义的IpcServerHelper结构体中startServer()
void
startServer()
{
std::unique_lock lock(server_mutex);
if (!server && !server_thread) {
server_thread = std::make_unique<std::thread>(
[&]() { ipc_server_main_android(&server, signalStartupCompleteTrampoline, this); });
}
}
注释:src\xrt\ipc\server\ipc_server_process.c
中定义了ipc_server_main_android(...)函数。
#ifdef XRT_OS_ANDROID
int
ipc_server_main_android(struct ipc_server **ps, void (*startup_complete_callback)(void *data), void *data)
{
struct ipc_server *s = U_TYPED_CALLOC(struct ipc_server);
U_LOG_D("Created IPC server!");
int ret = init_all(s);
if (ret < 0) {
free(s);
return ret;
}
init_server_state(s);
*ps = s;
startup_complete_callback(data);
ret = main_loop(s);
teardown_all(s);
free(s);
U_LOG_I("Server exiting '%i'!", ret);
return ret;
}
#endif // XRT_OS_ANDROID
同时定义的还有非android系统的ipc_server_main(int argc, char **argv)
ipc_server_main(...)在最初启动与android有所不同,
它是在 src\xrt\targets\service\main.c 中启动:
int
ipc_server_main(int argc, char *argv[]);
int
main(int argc, char *argv[])
{
u_trace_marker_init();
return ipc_server_main(argc, argv);
}
非android的runtime server除了启动这里有些差异,接下来的流程和android都是成套出现,是一样的,我们接下来只关注android流程。
上面ipc_server_main_android(...)函数中调用了
int ret = init_all(s);
static int init_all(struct ipc_server *s)函数定义仍然在ipc_server_process.c中
其参数是 ipc_server 结构体指针
init_all(...)函数会做很多初始化的事情,其中就包括对 ipc_server结构体中 xrt_instance结构体的创建
static int
init_all(struct ipc_server *s)
{
...
...
int ret = xrt_instance_create(NULL, &s->xinst);
if (ret < 0) {
IPC_ERROR(s, "Failed to create instance!");
teardown_all(s);
return ret;
}
...
...
return 0;
}
xrt_instance_create(...)函数在
src\xrt\targets\common\target_instance_no_comp.c 中被定义
注释:src\xrt\targets\common\target_instance_no_comp.c
int
xrt_instance_create(struct xrt_instance_info *i_info, struct xrt_instance **out_xinst)
{
struct xrt_prober *xp = NULL;
int ret = xrt_prober_create_with_lists(&xp, &target_lists);
if (ret < 0) {
return ret;
}
struct t_instance *tinst = U_TYPED_CALLOC(struct t_instance);
tinst->base.select = t_instance_select;
tinst->base.create_system_compositor = t_instance_create_system_compositor_stub;
tinst->base.get_prober = t_instance_get_prober;
tinst->base.destroy = t_instance_destroy;
tinst->xp = xp;
*out_xinst = &tinst->base;
return 0;
}
关注其中的参数 &target_lists引用
这是 xrt_prober_entry_lists 结构体的引用
在src\xrt\targets\common\target_lists.c中被定义
struct xrt_prober_entry_lists target_lists = {
target_entry_lists,
target_auto_list,
NULL,
};
其中成员 target_auto_list 是一个xrt_auto_prober_creator数组
xrt_auto_prober_creator target_auto_list[] = {...}
xrt_auto_prober_creator 无法找到定义,有可能是封装在了共享库中
先看 target_auto_list[] 数组,其中通过不同平台的宏声明了这些平台相关探针的函数指针成员:
xrt_auto_prober_creator target_auto_list[] = {
...
#ifdef XRT_BUILD_DRIVER_ANDROID
android_create_auto_prober,
#endif
...
NULL, // Terminate
};
android_create_auto_prober()函数在
src\xrt\drivers\android\android_proper.c 中被定义
struct xrt_auto_prober *
android_create_auto_prober()
{
struct android_prober *p = U_TYPED_CALLOC(struct android_prober);
p->base.name = "Android";
p->base.destroy = android_prober_destroy;
p->base.lelo_dallas_autoprobe = android_prober_autoprobe;
return &p->base;
}
android_create_auto_prober()函数中获取到了 android_prober_autoprobe 函数指针
它们在同文件中定义
static int
android_prober_autoprobe(struct xrt_auto_prober *xap,
cJSON *attached_data,
bool no_hmds,
struct xrt_prober *xp,
struct xrt_device **out_xdevs)
{
struct android_device *dd = android_device_create();
out_xdevs[0] = &dd->base;
return 1;
}
android_device_create()函数在
src\xrt\drivers\android\android_sensors.c 中定义
struct android_device *
android_device_create()
{
enum u_device_alloc_flags flags =
(enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE);
struct android_device *d = U_DEVICE_ALLOCATE(struct android_device, flags, 1, 0);
d->base.name = XRT_DEVICE_GENERIC_HMD;
d->base.destroy = android_device_destroy;
d->base.update_inputs = android_device_update_inputs;
d->base.get_tracked_pose = android_device_get_tracked_pose;
d->base.get_view_poses = android_device_get_view_poses;
d->base.compute_distortion = android_device_compute_distortion;
d->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE;
d->base.device_type = XRT_DEVICE_TYPE_HMD;
snprintf(d->base.str, XRT_DEVICE_NAME_LEN, "Android Sensors");
snprintf(d->base.serial, XRT_DEVICE_NAME_LEN, "Android Sensors");
d->log_level = debug_get_log_option_android_log();
m_imu_3dof_init(&d->fusion, M_IMU_3DOF_USE_GRAVITY_DUR_20MS);
// Everything done, finally start the thread.
int ret = os_thread_helper_start(&d->oth, android_run_thread, d);
if (ret != 0) {
ANDROID_ERROR(d, "Failed to start thread!");
android_device_destroy(&d->base);
return NULL;
}
struct xrt_android_display_metrics metrics;
if (!android_custom_surface_get_display_metrics(android_globals_get_vm(), android_globals_get_activity(),
&metrics)) {
U_LOG_E("Could not get Android display metrics.");
/* Fallback to default values (Pixel 3) */
metrics.width_pixels = 2960;
metrics.height_pixels = 1440;
metrics.density_dpi = 572;
metrics.refresh_rate = 60.0f;
}
d->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / metrics.refresh_rate);
...
...
return d;
}
可以看到android_device_create()中获取到了VR设备层传递过来的各种事件,track、位姿数据等
以及设置各种显示参数等
track、位姿等数据,源码中是以3DoF模拟
关键的加速度传感和重力传感的数据是在
int ret = os_thread_helper_start(&d->oth, android_run_thread, d);
这一行语句中起了一个专门的线程来做。
线程android_run_thread(void *ptr)同样是在android_sensors.c中定义:
static void *
android_run_thread(void *ptr)
{
struct android_device *d = (struct android_device *)ptr;
const int32_t poll_rate_usec = android_get_sensor_poll_rate(d);
#if __ANDROID_API__ >= 26
d->sensor_manager = ASensorManager_getInstanceForPackage(XRT_ANDROID_PACKAGE);
#else
d->sensor_manager = ASensorManager_getInstance();
#endif
d->accelerometer = ASensorManager_getDefaultSensor(d->sensor_manager, ASENSOR_TYPE_ACCELEROMETER);
d->gyroscope = ASensorManager_getDefaultSensor(d->sensor_manager, ASENSOR_TYPE_GYROSCOPE);
ALooper *looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
d->event_queue = ASensorManager_createEventQueue(d->sensor_manager, looper, ALOOPER_POLL_CALLBACK,
android_sensor_callback, (void *)d);
// Start sensors in case this was not done already.
if (d->accelerometer != NULL) {
ASensorEventQueue_enableSensor(d->event_queue, d->accelerometer);
ASensorEventQueue_setEventRate(d->event_queue, d->accelerometer, poll_rate_usec);
}
if (d->gyroscope != NULL) {
ASensorEventQueue_enableSensor(d->event_queue, d->gyroscope);
ASensorEventQueue_setEventRate(d->event_queue, d->gyroscope, poll_rate_usec);
}
int ret = 0;
while (d->oth.running && ret != ALOOPER_POLL_ERROR) {
ret = ALooper_pollAll(0, NULL, NULL, NULL);
}
return NULL;
}
android_run_thread(void *ptr)函数中是通过 android_sensor_callback 获取到android_device的event_queue
android_sensor_callback 同样也是在android_sensors.c中定义
// Callback for the Android sensor event queue
static int
android_sensor_callback(int fd, int events, void *data)
{
struct android_device *d = (struct android_device *)data;
if (d->accelerometer == NULL || d->gyroscope == NULL)
return 1;
ASensorEvent event;
struct xrt_vec3 gyro;
struct xrt_vec3 accel;
while (ASensorEventQueue_getEvents(d->event_queue, &event, 1) > 0) {
switch (event.type) {
case ASENSOR_TYPE_ACCELEROMETER: {
accel.x = event.acceleration.y;
accel.y = -event.acceleration.x;
accel.z = event.acceleration.z;
ANDROID_TRACE(d, "accel %ld %.2f %.2f %.2f", event.timestamp, accel.x, accel.y, accel.z);
break;
}
case ASENSOR_TYPE_GYROSCOPE: {
gyro.x = -event.data[1];
gyro.y = event.data[0];
gyro.z = event.data[2];
ANDROID_TRACE(d, "gyro %ld %.2f %.2f %.2f", event.timestamp, gyro.x, gyro.y, gyro.z);
// TODO: Make filter handle accelerometer
struct xrt_vec3 null_accel;
// Lock last and the fusion.
os_mutex_lock(&d->lock);
m_imu_3dof_update(&d->fusion, event.timestamp, &null_accel, &gyro);
// Now done.
os_mutex_unlock(&d->lock);
}
default: ANDROID_TRACE(d, "Unhandled event type %d", event.type);
}
}
return 1;
}
这里就能很明显的看到,3DoF的角动量加速度传感和重力传感的数据链接了。
如果改为6DoF,或者传输别的数据,这里就需要硬件厂商去改动和适配了
例如,在前文的android_device_create()函数中,关于deivce input事件的函数定义
d->base.update_inputs = android_device_update_inputs;
android_device_update_inputs()函数在源码中就是空的,也是留给硬件设备端去实现的
static void
android_device_update_inputs(struct xrt_device *xdev)
{
// Empty
}