OpenXR+Runtime:Monado从ipc_server到device

今天来跟一下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(
            [&]() { 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
}

你可能感兴趣的:(xr)