今日跟着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
}