surface在android4.2和4.4系统中本地service里使用上的差异

surface在android4.2跟4.4系统中本地service里使用上的差异

surface在android4.2跟4.4系统中本地service里使用上的差异

 

       了解android的人都知道,android的应用是java写的,运行的效率应该比C/C++要低一些,这是不争的事实。为了提高运行效率,运算量大的任务大多都是采用本地service的形式存在,比如我们比较熟悉的audiofliger、surfacefliger,都是采用本地service的形式做的。笔者的研发项目中,使用到了视频输入,鉴于一些运算量运行效率考虑,也是采用本地service的形式来完成的,我们暂且认为这个本地service的名字就是“media.tvd”吧。

   在“media.tvd”中肯定需要做一下surface相关的传递,以供视频数据能够跟这个surface的window挂上钩,再通过surfacefliger显示出来。笔者在4.2上使用的这个相关接口如下:

status_t     setPreviewDisplay(constsp<Surface>& surface);

我们在creatSurface后会得到一个surface的对象,如果是app调用这个接口就是通过JNIcall下来的,JNI传递surface是没有问题。

/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/edsam49原创,转载请注明出处,谢谢!
/*****************************************************************************************************/

   我们先来回顾一下android4.2surface里面有两个非常重要的接口,也就是下面这个两个;

    static status_t writeToParcel(const sp<Surface>& control, Parcel* parcel);

    static sp<Surface> readFromParcel(const Parcel& data);

      所以在4.2系统里,如果要传surface,我们可以通过这两个接口就完成了client到server的传递。但是到4.4系统surface已经发生了很大变化,已经没有这两个接口了,那怎么完成client到server的传递呢?

      笔者刚开始也很郁闷,4.2都用得好好的,移植到4.4编译都过不了,哎!有什么办法呢,工作总是要继续的,生活也是要继续的。在网上也找了一些资料看了,基本上没有找到什么有价值的东西,所以笔者还是从源码中来,到源码中去,静下心来看看4.4系统的相关源码。笔者首先想到了camera系统也是一个本地service,那它同样也存在同样的需求吧。Camera这一块的代码也不少啊!不熟悉的话,也是要折腾一下的。

      上周晚上笔者自己在家看源码,晚上11点多了,把camera相关的看了后,得到了启发,信心立马上来了,解决问题有戏了。如果把“media.tvd”写成lib的形式,当然也是可以的,这样做得好会牺牲一些效率,关键是也要裁剪代码,调试,也不那么方便了,所以笔者还是先坚持用“media.tvd”本地service的形式继续推进。

      在android4.4系统中,确实不能直接传surface了,但是新增了一个好东西,也就是IGraphicBufferProducer,按意思也就是图形buffer的生产者了。笔者把以前穿surface的地方都改成传IGraphicBufferProducer就行了。当然在client调用的使用要从surface转一下到IGraphicBufferProducer,surface里面有这样的接口,如下:

sp<IGraphicBufferProducer>  gbp

gbp =mFlingerSurface->getIGraphicBufferProducer();

     这样就把这个gbp传递下去就是了,那么到service实体部分,需要做一些变通,反正后面的目的就是得到一个ANativeWindow的对象,代码如下:

+status_t TVDecoderService::setPreviewDisplay(const sp<IGraphicBufferProducer>& bufferProducer)
 {
     int ret = OK;
  //   sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
-    sp<ANativeWindow> window(surface);
+ ALOGD("setPreviewTarget(%p) (pid %d)", bufferProducer.get(),
+		 getCallingPid());
+ 
+ sp<IBinder> binder;
+ sp<ANativeWindow> window;
+ if (bufferProducer != 0) {
+	 binder = bufferProducer->asBinder();
+	 // Using controlledByApp flag to ensure that the buffer queue remains in
+	 // async mode for the old camera API, where many applications depend
+	 // on that behavior.
+	 window = new Surface(bufferProducer, /*controlledByApp*/ true);
+ }
+
+//    sp<ANativeWindow> window(surface);
     mPreviewWindow = window;

    中间的一些部分传递都是比较简单的,笔者就不介绍了,重要的就是找到这么一条通路。每次android系统版本的升级,都会带来很多已经完成的工作重新研究实现的问题,这也是做android比较累的地方,当然想要android的好,得包容android的累!