Android开发Android技术知识Android知识

Android N VR代码简析

2016-10-29  本文已影响0人  HuangTao_Zoey

虽然Google早在2016的IO大会上就说DayDream会随着Android N发布,但是从Android N的前几个版本的代码来看,都是没有集成的,直到Android-7.0.0_r14这个版本,才可以看到DayDream的一些简单代码,跟之前预见的一样,DayDream跟三星的GearVR采用的是同样的架构,都分离出来一个单独的VR SDK,比如三星的Oculus SDK,Google的Google VR SDK,应用基于他们的SDK开发应用程序,然后运行在支持这些SDK的Android系统上面。

单独分离出一个SDK,除了方便应用开发者之外,主要的目的是用来把VR的一些核心算法隐藏起来,比如用来减少延迟的ATW异步时间扭曲算法就是被封装在这里,是闭源不公开的,众所周知,在手机上面运行VR的时候一个最大的挑战就是延迟,当一副画面的延迟超过20MS,人就会感觉不舒服恶心,严重影响用户体验,一个好的VR产品都会尽量避免延迟。目前在Mobile VR上主要有以下几种方式来减少延迟:

1、 硬件层面的优化

2、 软件层面的优化

Android N的DayDream对硬件和软件的一些需求,其实都是根据上面这些优化手段提出来的,具体到Android N的代码来说,它提供了一个SDK,应该是解决了ATW算法和多分辨率渲染等优化问题,然后新增了一个系统服务VrManagerService和 vr HAL层, 应用通过VrManagerService来设置系统进入VR模式,VrManagerService又是通过vr HAL层去实现具体模式的切换的。

Implement this HAL to receive callbacks when a virtual reality (VR)
application is being used. VR applications characteristically have a number of special display and performance requirements, including:

In general, vendors implementing this HAL are expected to use set_vr_mode as a hint to enable VR-specific performance tuning needed for any of the above requirements, and to turn on any device features optimal for VR display modes. The set_vr_mode call may simply do nothing if no optimizations are available or necessary to meet the above requirements.
No methods in this HAL will be called concurrently from the Android framework.

 typedef struct vr_module {
    /**
     * Common methods of the  module.  This *must* be the first member of
     * vr_module as users of this structure may cast a hw_module_t to a
     * vr_module pointer in contexts where it's known that the hw_module_t
     * references a vr_module.
     */
    struct hw_module_t common;
    /**
     * Convenience method for the HAL implementation to set up any state 
     * needed
     * at runtime startup.  This is called once from the VrManagerService 
     * during
     * its boot phase.  No methods from this HAL will be called before init.
     */
    void (*init)(struct vr_module *module);

    /**
     * Set the VR mode state.  Possible states of the enabled parameter 
     * are:
     * false - VR mode is disabled, turn off all VR-specific settings.
     * true - VR mode is enabled, turn on all VR-specific settings.
     * This is called whenever the the Android system enters or leaves VR 
     * mode.
     * This will typically occur when the user switches to or from a VR 
     * application
     * that is doing stereoscopic rendering.
     */
    void (*set_vr_mode)(struct vr_module *module, bool enabled);
    /* Reserved for future use. Must be NULL. */
    void* reserved[8 - 2];
} vr_module_t;  

这个HAL层的实现是可选择的,毕竟不是每个Android N的手机都必须要支持DayDream平台。
VrManagerService是一个系统级别的服务,它的主要作用描述如下:

从描述来看,它是一个vr模式的控制中心,system_server里面的其他服务除了可以通过VrManagerInternal这个接口去控制vr模式,还可以通过VrStateListener接口注册一些vr状态变化的通知,它也是通过底层的vr HAL层去实际打开VR模式的。在system_server进程里面可以通过如下两种方式来访问到这个服务:

IVrManager vrManager = IVrManager.Stub.asInterface( ServiceManager.getService(VrManagerService.VR_MANAGER_BINDER_SERVICE));
 if (vrManager != null) {
      try {
          vrManager.registerListener(mVrStateCallbacks);
          mVrModeEnabled = vrManager.getVrModeState();
      } catch (RemoteException re) {
      }
  }
    mVrManagerInternal = getLocalService(VrManagerInternal.class);

在Android N上面Activity提供了一个新的接口setVrModeEnabled,这个函数会通过binder调用AMS的setVrmode接口,而在AMS的setVrmode最终调用的是VrManagerService的setVrmode函数,VrManagerService又是通过vr HAL层去打开这个VR模式,通过这样的一个调用链,使手机进入VR模式。

//enabled:true进入VR模式,false退出VR模式.
//requestedComponent 指定一个继承android.service.vr.VrListenerService 的服务,这个服务由VrManagerService来调用,如果没有指定,不会进入VR模式.
public void setVrModeEnabled(boolean enabled, @NonNull ComponentName requestedComponent)throws PackageManager.NameNotFoundException {
     try {
            if (ActivityManagerNative.getDefault().setVrMode(mToken, 
                enabled, requestedComponent)!= 0) {
                throw new PackageManager.NameNotFoundException(
                        requestedComponent.flattenToString());
            }
     } catch (RemoteException e) {
            // pass
     }
}

上面说过system_server进程里面的其他服务和其他进程可以通过VrStateListener的接口获知当前的VR模式变化信息,搜索了一下目前系统里面实现了VrStateListener接口的有以下几处代码:

Android N 实现了VrStateListener的地方

VR之所以被人喜欢,是因为能获得一种沉浸式体验,所以在VR模式下,人们是不喜欢被其他事情打扰的,PowerManagerService、BaseStatusBar等服务监听VR模式的变化就可以相应的改变逻辑行为,比如不显示通知信息等。

VrManagerService的另外一个重要功能是监听设置里面关于VR模式的开关状态,在VrManagerService.java的文件夹目录下面还有一个EnabledComponentsObserver,它继承了SettingChangeListener,所以可以获取设置中关于VR的开关状态变化,VrManagerService是在onBootPhase这个函数里面把自己加入到EnabledComponentsObserver的监控列表里面去的,以后只要开关状态有变化,那么VrManagerService就能获取到通知了。

@Override
public void onBootPhase(int phase) {
    if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
        synchronized (mLock) {
            Looper looper = Looper.getMainLooper();
            Handler handler = new Handler(looper);
            ArrayList<EnabledComponentChangeListener> listeners = new 
            ArrayList<>();
            listeners.add(this);
            mComponentObserver =  
               EnabledComponentsObserver.build(mContext, handler,
                   Settings.Secure.ENABLED_VR_LISTENERS, looper,
                   android.Manifest.permission.BIND_VR_LISTENER_SERVICE,
                   VrListenerService.SERVICE_INTERFACE, mLock, 
                   listeners);
                mComponentObserver.rebuildAll();
         }
     }
 }
上一篇下一篇

猜你喜欢

热点阅读