本篇针对Surface模块进行分析,从Java层的Activity创建开始,到ViewRoot、WindowsManagerService,再到JNI层和Native层。

首先推荐一个Android源码查看的网站:http://androidxref.com/

Surface的创建涉及三个部分:

  1. App 进程
    App需要将自己的内容显示在屏幕上,所以App负责发起Surface创建请求,创建好Surface后, 就可以直接可以在canvas上画图等,最终都会保存到Surface里的buffer里,最后由SurfaceFlinger合成并显示。

  2. System_Server进程
    主要是其中的WindowManagerService, 负责接收APP请求,向SurfaceFlinger发起具体的请求创建Surface, 且WMS需要创建Surface的辅助管理类,如SurfaceControl。

  3. SurfaceFlinger
    为App进程创建具体的Surface, 在SurfaceFlinger里对应成Layer, 然后负责管理、合成显示。

总体流程(参考《深入理解Android》,源码较旧):

Surface创建过程:
ActivityThread.java
调用handleLaunchActivity
调用handleResumeActivity函数
addView调用到LocalWindowManager.java的addView函数
然后调用WindowManagerImpl.java的addView函数
创建ViewRoot(分成两个分支):
、执行ViewRoot的构造函数,创建mSurface(!实现ViewRoot的Surface创建)(创建IWindow) 、调用ViewRoot的setView函数(分成两个分支):
、setView调用WMS的add函数(IWindowSession)
调用WMS的addWindow函数
调用WMS.java::WindowState的attach函数
调用WMS.java::Session的windowAddedLocked函数,创建SurfaceSession(!实现WMS的SurfaceSession创建)
执行SurfaceSession的构造器,调用native函数init
JNI层实现init函数,创建一个SurfaceComposerClient(分成两步):
、SurfaceComposerClient构造函数调用SurfaceFlinger的createConnection(!和SF建立交互通道)
创建Client(创建共享内存)(一个Client最多支持31个显示层)
Client构造函数创建SharedClient对象
SharedClient定义SharedBufferStack数组对象(有31个元素)
创建BClient(接受客户端请求,将处理提交给SF)
、再调用_init(初始化SurfaceComposerClient一些成员变量) 、调用requestLayout函数,向ViewRoot发送DO_TRAVERSAL消息
调用handleMessage函数
调用performTraversal函数(分成两个分支):
、调用ViewRoot的relayoutWindow函数(调用IWindowSession的relayout函数)
调用createSurfaceControl创建一个SurfaceControl
?在SurfaceComposerClient的createSurface创建一个SurfaceControl(请求端)
?SurfaceComposerClient调用createSurface创建一个Surface(SurfaceControl类型)
? 调用SurfaceControl的writeToParcel将信息写入Parcel包中
? 在readFromParcel中通过Parcel信息构造一个Surface对象,保存到mSurface
? ViewRoot获得一个Native的Surface对象 调用WMS.java::Session的relayout函数(!此和上这两步跨进程)(分成三步):
、在IWindowSession.adil的Bn端调用onTransact,writeToParcel写入信息
、在IWindowSession.adil的Bp端,relayout中传入outSurface,readFormParcel读取信息填充outSurface 、调用WMS的relayoutWindow
》》调用WMS.java::WindowState的createSurfaceLocked,创建本地Surface(SurfaceSession)
》》调用copyForm,将本地surface信息拷贝到outSurface(即mSurface)
、调用draw()函数开始绘制(lockCanvas、调用draw、unlockCanvasAndPost)
调用DecorView的draw函数(!实现UI绘制)

概述


Surface和APP的关系:

  Surface像是UI的画布,APP就像是在Surface上作画,通过i使用Skia绘制二维图像,或是用OpenGL绘制三维图像,最终APP和Surfacea都要进行交互。

SUrface和SurfaceFlinger(SF)的关系:

  surface向SF提供数据,SF进行混合数据。

Activity的显示(Java层)


1、应用程序的显示和surface有关,而应用程序的外表通过Activity展示的,那么Activity如何创建的呢?

  App对应的进程,它的入口函数是ActivityThread类的main函数。

  ActivityThread类中有一个handleLaunchActivity函数(创建Activity),代码如下:

private void handleLaunchActivity(ActivityClientRecord r
, Intent customIntent
, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
...
handleResumeActivity(r.token
, false
, r.isForward
,!r.activity.mFinished && !r.startsNotResumed
, r.lastProcessedSeq, reason);
//Activity创建成功就往onResume()走了!
...
}
}

  这个函数涉及了两个关键函数:

(1)performLaunchActivity
    返回一个activity(即App中的Activity),该方法 创建了Activity:
private Activity performLaunchActivity(ActivityClientRecord r
, Intent customIntent) {
...
// newActivity函数根据Activity的类名通过Java反射机制创建对应的Activity
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
Application app = r.packageInfo.makeApplication(false
, mInstrumentation);
//在获取Application
...
activity.attach(appContext
, this
, getInstrumentation()
, r.token
,.ident
, app
, r.intent
, r.activityInfo
, title
, r.parent
, r.embeddedID
, r.lastNonConfigurationInstances
, config
,r.referrer
, r.voiceInteractor
, window);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(
activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state); //调用Activity的onCreate函数
}
...
}

  因此,performLaunchActivity的作用如下:

  • 根据类名以java反射机制的方法创建一个Activity
  • 调用Activity的onCreate函数,开始Activity 的生命周期
(2)handleResumeActivity
    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
... // 与调用Activity的onResume相关
ActivityClientRecord r = performResumeActivity(token, clearHide); ...
// PhoneWindow
r.window = r.activity.getWindow();
// 获取Activity的DecorView
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
// WindowManagerImpl,其实就是LocalWindowManager
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l); // 将刚才的dector对象加入到ViewManagerg中
} ...
}

 

    > 在Activity.java中Activity在onCreate函数中通过setContentView设置UI界面。

  Activity.java部分代码:

public  void  setContentView(View view) {
getWindow().setContentView(view); // 传入一个view
} public Window getWindow() {
return mWindow; //返回一个类型为Window的对象
}

  > 分析出现的两个和UI相关的类:

Window:一个抽象基类,用于控制顶层窗口的外观和行为。职能可能是绘制背景、标题栏、默认的按键处理等。

     它将作为一个顶层的view加入到Window  Manager中。

View:一个基本的UI单元,占据屏幕的一块矩形区域,可用于绘制,能处理事件。(设置的view其实只是DecorView的子view,DecorView还处理了标题栏显示等一系列操作)

也可以看做:

  > 分析addView,wm类型实际上是LocalWindowManager,查看LocalWindowManager.java的addView函数:

public  final void addView(View view , ViewGroup.LayoutParams params) {
..............
mWindowManager.addView(view, params); // mWindowManager对象实际是WindowManagerImpl类型
}

  接着查看WindowManagerImpl.java类的addView函数:

private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
{
...
ViewRoot root;
...
root = new ViewRoot(view.getContext()); // 创建viewRoot
...
root.setView(view, wparams, panelParentView); // view即刚刚介绍的DectorView

2、 viewRoot: viewRoot实现了ViewParent接口,ViewParent不处理绘画,因为它没有onDraw函数(所以和Android基本绘画单元的view不太一样)

//查看ViewRoot.java::ViewRoot定义
public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks // 从Handler 派生
{
private final Suface mSurface = new Surface(); // 创建了一个Surface 对象
Final W mWindow;
View mView;
}
 分析得出ViewRoot的作用:
  • ViewRoot继承Handler类,能够处理消息,重写了handleMessage函数
  • ViewRoot有一个成员变量mSurface,是Surface类型
  • ViewRoot有一个W类型的mWinow和一个View类型的mView变量(W是ViewRoot定义的e静态内部类 static class W extends IWindow.Stub,将参与和Binder的通信) 

View、DectorView是UI单元,绘画工作在OnDraw函数中完成。如果onDraw是画图过程,那么画布就是Surface。

Surface:有一块Raw Buffer,Surface操作这块Raw Buffer,Screen Compositor(即SurfaceFlinger)管理这块Raw Buffer。

结论:

  • ViewRoot的成员变量mSurface(aSurfce类型),他和一块Raw Buffer有关联
  • ViewRoot是一个ViewParent,他的子View的绘画操作,是在画布Surface上展开的
  • Surface和SurfaceFlinger交互

①的setView中,调用的时ViewRoot.java的setView函数:

public void setView(View view, WindowManager.LayoutParams attrs,
View panelParentView) {
...
...
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
...
}

 实现了:

  • 保存传入的View(即DectorView,从ActivityThread层层传入)
  • 调用requestLayout(往handler中发送一个消息,因为ViewRoot是从handlera派生的,所以这个消息最后会由ViewRoot自己处理)
  • 调用IWindowSession的add函数(一个跨进程的Binder通信,第一个参数是mWindow,他是W类型,由IWindow.stub派生)


3、requestLayout会向ViewRoot发送一个消息,进入ViewRoot.java的handleMessage函数,调用performTraversals函数。

进入 performTraversals函数:

private void performTraversals() {
final View host = mView; //即最初的DectorView
...
  try{
    relayoutResult = relayoutWindow(params, viewVisiblity, insetPending);
}
...
host.measure(childWidthMeasureSpec, childHeightMeasureSpec); ...
host.layout(, , host.mMeasuredWidth, host.mMeasuredHeight);
...
...
draw(fullRedrawNeeded);
...
}

(1)relayoutWindow函数:会调用IWindowSession的Relayout函数;

(2)draw函数:从mSurface(Surface)中lock一块Canvas(画布),调用DecorView的draw函数,然后交给mView绘画,最后unlockCanvasAndPost释放这块Canvas


总结:

1、大致涉及的方法、类的大体流程(回车表示前一方法内调用):

ActivityThread.java
调用handleLaunchActivity
调用performLaunchActivity函数(创建Activity、调用onCreate)
onCreate调用setContentView函数设置UI界面,传入view,返回Window
调用handleResumeActivity函数
addView调用到LocalWindowManager.java的addView函数
然后调用WindowManagerImpl.java的addView函数
创建ViewRoot,调用ViewRoot的setView函数 ViewRoot.java(继承Handler、实现ViewParent)
构造函数创建一个Surface对象mSurface
setView函数实现:
保存传入的view为mView
调用requestLayout
调用IWindowSession的add函数
        WIndowManagerServce.java::session的add函数
          调用WMS.java的addWindow
            调用WMS.java::WIndowState的attach函数
              调用windowAnddedLocked函数并创建一个SurfaceSession对象 
requestLayout(向ViewRoot发送一个消息)
进入ViewRoot.java的handleMessage函数
调用performTraversals函数
调用relayoutWindow函数
调用IWindowSession的Relayout函数
调用draw函数(从mSurface中lock一块Canvas)
调用DecorView的draw函数,交给mView绘画
最后unlockCanvasAndPost释放Canvas

2、要点:

(1)整个Activity的绘图流程就是从mSurface中lock一块Canvas,然后交给mView去绘画,最后unlockCanvasAndPost释放这块Canvas ;

(2)Activity的顶层view是DecotView,而onCreate函数中setContentView设置的View是这个DecorView的一部分。DecorView是一个FrameLayout类型的ViewGroup;

(3)Activity和UI有关,包含window(真实类型是phoneWIndow)和一个WindowManger(真实类型是LocalWindowManager)对象。这两个对象控制整个Activity的显示;

(4)LocalWindowManager使用了WindowManagerImpl.java(其中addView有一个ViewRoot对象)作为最终处理对象;

(5)ViewRoot实现了ViewParent接口,有两个变量:

    mView,指向Activity顶层UI单元的DecorView

    mSurface,包含一个Canvas

  此外,ViewRoot还通过Binder系统和dWinowManagerService进行跨进程交互;

(6)ViewRoot能够处理Handler的消息,Activity的显示就是由ViwRoot在他的performTraversals函数中完成;


Surface(Java层)


通过上面一节的分析可知:

ViewRoot的构造函数里面会创建一个Surface;

而ViewRoot通过IWindowSession和WMS交互时,WMS调用的attach函数会构造一个SurfaceSession;

ViewRoot在prformTransval的处理过程中会调用IWindowSession的relayout函数。(WMS由SYsytem_server进程启动,SF服务也在这个进程中)

  两个部分的Surface看似是毫无关系,但是实际上,在使用createSurfaceLocked() 的时候,会将creaeSurfaceLocked 创建的Surface copy到ViewRoot层的Surface中。也就是这样,将底层的Surface对象传到上层,供Activity的界面部分使用,用来绘图。整个流程大概是:

RootView.relayoutWindow,调用方,调用relayout将mSurface传进去

->  WindowManagerService.Session.relayout调用外部类对象的relayoutWindow

->  WindowManagerService.relayoutWindow,调用createSurfaceLocked

->  WindowManagerService.createSurfaceLocked(),将SurfaceSession拷贝到创建的新对象Surface

->  outSurface.copyFrom(surface),将本地Surface 的信息(即SurfaceSession)拷贝到outSurface中

最后一步是将WindowManagerService的surface与ViewRoot 的outSurface联系起来的关键点,outSurface是作为参数,从RootView传到WindowManagerService的。

ViewRoot其实是通过Binder与WindowManagerService进行跨进程调用通信的。


Surface(JNI层)


1、在JNI层,首先被调用的时Surface的无参构造函数,代码:

// Surface.java
Public Surface() {
...
mCanvas = new CompatibleCanvas(); // CompatibleCanvaso从Canvas类派生
}

 Canvas:

  画图需要:

  • Bitmap,用于存储像素(即画布,可以当作是一块数据存储区域);
  • Canvas,用于记载画图的动作(例如画一个矩形),Canvas提供了这些基本操作的绘图函数;
  • Drawing primitive:绘图基本元素,例如矩形、圆等;
  • Paint:用来描述h绘画时使用的颜色、虚实线等;

一般情况下,Canvas会封装一块Bitmap。

2、SurfaceSession的构造

// SurfaceSession.java
public SurfaceSession(){
init(); //这是一个native函数
}

init函数的实现在JNI的android_view_Surface.cpp中:

static void SurfaceSession_init(JNIEnv* env,jobject clazz)
{
     //创建一个SurfaceComposerClient对象
   sp<SurfaceComposerClient> client = new SurfaceComposerClient;
client->incStrong(clazz);
//在Java对象中保存这个client对象的指针,类型为SurfaceComposerClient
   env->SetIntField(clazz, sso.client, (int)client.get());
}

3、Surface的有参构造函数:

//    Surface.java
    publicSurface(SurfaceSession s,//传入一个SurfaceSession对象
           int pid, String name, int display, int w, int h, int format, int flags)
       throws OutOfResourcesException {
        ......
       mCanvas = new CompatibleCanvas();
      //又一个native函数,注意传递的参数:display以后再说,w,h代表绘图区域的宽高值
       init(s,pid,name,display,w,h,format,flags);
       mName = name;
    }

Surface的init函数实现在JNI层:

static void Surface_init(

        JNIEnv*env, jobject clazz,
       jobject session,
       jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags)
{
   //从SurfaceSession对象中取出之前创建的那个SurfaceComposerClient对象
SurfaceComposerClient* client =
           (SurfaceComposerClient*)env->GetIntField(session, sso.client);    sp<SurfaceControl> surface;//注意它的类型是SurfaceControl
if (jname == NULL) {
    /*
调用SurfaceComposerClient的createSurface函数,返回的surface是一个
SurfaceControl类型。
*/
       surface = client->createSurface(pid, dpy, w, h, format, flags);
    } else{
      ......
}
   //把这个surfaceControl对象设置到Java层的Surface对象中,对这个函数就不再分析了
   setSurfaceControl(env, clazz, surface);
}

4、copyForm分析

上一节中,outSurface.copyFrom(surface),将本地Surface 的信息(即SurfaceSession)拷贝到outSurface中

他是一个native函数,代码如下:

static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other)
{
   //根据JNI函数的规则,clazz是copyFrom的调用对象,而other是copyFrom的参数。
   //目标对象此时还没有设置SurfaceControl,而源对象在前面已经创建了SurfaceControl
   constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
   constsp<SurfaceControl>& rhs = getSurfaceControl(env, other); if (!SurfaceControl::isSameSurface(surface, rhs)) {
        //把源SurfaceControl对象设置到目标Surface中。
       setSurfaceControl(env, clazz, rhs);
    }
}

5、writeToParcel和readFromParcel分析

这两个函数调用发生在ViewRoot调用IWindowSession的relayout函数中,它发生在IWindowSession.adil(通过aidl -l ...编译成java文件可查看到relayout方法中和onTransactg中)

//  android_view_Surface.cpp
static void Surface_writeToParcel(JNIEnv* env,jobject clazz,
jobject argParcel, jint flags)
{
   Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); //clazz就是Surface对象,从这个Surface对象中取出保存的SurfaceControl对象
const sp<SurfaceControl>&control(getSurfaceControl(env, clazz));
/*
把SurfaceControl中的信息写到Parcel包中,然后利用Binder通信传递到对端,
对端通过readFromParcel来处理Parcel包。
*/
   SurfaceControl::writeSurfaceToParcel(control, parcel); if (flags & PARCELABLE_WRITE_RETURN_VALUE) {        //lags的值就等于PARCELABLE_WRITE_RETURN_VALUE
       //所以本地Surface对象的SurfaceControl值被置空了
       setSurfaceControl(env, clazz, );
    }
}
--------------------- // android_view_Surface.cpp static void Surface_readFromParcel(
       JNIEnv* env, jobject clazz, jobject argParcel)
{
   Parcel* parcel = (Parcel*)env->GetIntField( argParcel,no.native_parcel);
   //注意下面定义的变量类型是Surface,而不是SurfaceControl
   const sp<Surface>&control(getSurface(env, clazz));    //根据服务端传递的Parcel包来构造一个新的surface。
   sp<Surface> rhs = new Surface(*parcel); if (!Surface::isSameSurface(control, rhs)) {
//把这个新surface赋给ViewRoot中的mSurface对象
      setSurface(env,clazz, rhs);
    }
}

小结

在JNIe层创建了三个对象:SurfaceComposerClient、SurfceControl、Surface

大致流程:

(1)创建一个SurfaceComposerClient

(2)调用SurfaceComposerClient的createSurface得到一个SurfceControl对象

(3)调用SurfaceControl的writeToParcel,将一些信息写入Parcel包中

(4)根据Parcel包的信息z构造一个Surface对象,将其保存到Java层的mSurface中

(5)因此,ViewRoot得到一个Native的Surface对象

 Surface和画图Canvas:

在ViewRoot的draw()函数里面(前面有提到),有两个和Surface相关的函数调用:

  (1)lockCanvas:先获得一块存储区域,然后将它和Canvas绑定到一起,这样,UI绘画的结果就记录在这块存储区域里了,如此进Canvas进行UI画图就会有画布了;

  (2)unlockCanvasAndPost:一个native函数,取出Native的Surface对象,调用Surface的unlockAndPost函数。

调用流程总结:

  

总结

1、一个Activity一般都会对应到一个Window, 对应了一个DecorView, ViewRoot 
2、ViewRoot中有一个Surface, 就是App可以用于绘制UI的Surface了,在Native层也对应了一个Surface, 在SurfaceFlinger对应的是一个Layer,通过Layer中的Producer可以真正的申请Buffer用于绘制。App中通过Surface中的Canvas的类似lockcanvas接口触发dequeue buffer流程。 
3、 一个ViewRoot在WMS端对应了一个WindowState, WindowState又通过一系列引用关联到一个SurfaceControl, Native层也有一个SurfaceControl。这个可以用于控制窗口的一些属性。 
4、 WMS native层的SurfaceComposerClient与SurfaceFlinger之间通过ISurfaceComposerClient建立联系。一个App在SurfaceFlinger端对应了一个Client,用于处理该App layer的创建等请求。

5、当ViewRootImpl请求WMS relayout时,会将ViewSurface中的Surface交给WMS初始化。在WMS中,对应每个WindowState对象,在relayout窗口时,同样会创建一个Surface,wms中的这个Surface会真正的初始化,然后再将这个WMS Surface复制给ViewRootImpl中的Surface。这么实现的目的就是保证ViewRootImpl和WMS共享同一个Surface。ViewRootImpl对Surface进行绘制,WMS对这个Surface进行初始化及管理。

ActivityThread.java
调用handleLaunchActivity
调用performLaunchActivity函数(创建Activity、调用onCreate)
onCreate调用setContentView函数设置UI界面,传入view,返回Window
调用handleResumeActivity函数
addView调用到LocalWindowManager.java的addView函数
然后调用WindowManagerImpl.java的addView函数
创建ViewRoot,调用ViewRoot的setView函数 ViewRoot.java(继承Handler、实现ViewParent)
构造函数创建一个Surface对象mSurface
setView函数实现:
保存传入的view为mView
调用requestLayout
调用IWindowSession的add函数
        WIndowManagerServce.java::session的add函数
          调用WMS.java的addWindow
            调用WMS.java::WIndowState的attach函数
              调用windowAnddedLocked函数并创建一个SurfaceSession对象  requestLayout(向ViewRoot发送一个消息)
进入ViewRoot.java的handleMessage函数
调用performTraversals函数
调用relayoutWindow函数
调用IWindowSession的Relayout函数
调用draw函数(从mSurface中lock一块Canvas)
调用DecorView的draw函数,交给mView绘画
最后unlockCanvasAndPost释放Canvas

创建Surface的整体流程:

1.1 viewrootImpl.java

在应用启动时,会通过WindowManagerGlobal去添加view,添加view时会去创建viewRootImpl,然后进行设置view。

viewRootImpl.setView() —> requestLayout()申请布局—>scheduleTraversals()—>doTraversal()–>performTraversals()

利用IWindowSession和Session通信,调用relayout,注意,这里mSurface是ViewRootImpl的成员变量,开始调用了无参的构造函数,IWindowSession.aidl文件中,参数mSurface是被out修饰,用来接受在server端创建Surface,然后再binder返回给ViewRootImpl。

1.2 Session.java

 public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outConfig, outSurface);
return res;
}

1.3 WindowManagerService.java

 public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { //新建一个SurfaceControl
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
}

1.4 WindowStateAnimator.java

首先创建一个SurfaceControl:

SurfaceControl createSurfaceLocked() {

            mSurfaceControl = new SurfaceControl(
mSession.mSurfaceSession,
attrs.getTitle().toString(),
w, h, format, flags);
} public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
//session就是SurfaceComposerClient在java层的代表
//mNativeObject是native层SurfaceControl的指针
mNativeObject = nativeCreate(session, name, w, h, format, flags);
}

1.5 android_view_SurfaceControl.cpp

static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
//从上层取到SurfaceComposerClient的指针,还原一个SurfaceComposerClient
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
//调用createSurface,返回的是一个SurfaceControl对象,注意不是surface
sp<SurfaceControl> surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);
if (surface == NULL) {
jniThrowException(env, OutOfResourcesException, NULL);
return ;
}
surface->incStrong((void *)nativeCreate);
//返回给java层SurfaceControl的指针
return int(surface.get());
}

1.6 SurfaceComposerClient.cpp

sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
status_t err = mClient->createSurface(name, w, h, format, flags,
&handle, &gbp);
//gbp就是surfacefligner中Layer的mBufferQueue的client端(IGraphicBufferProducer)
if (err == NO_ERROR) {
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}

1.7 Client.cpp

通过ISurfaceComposerClient的binder通信,调用服务端对应client对象的方法createSurface()

status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
/*
* createSurface must be called from the GL thread so that it can
* have access to the GL context.
*/ class MessageCreateLayer : public MessageBase {
SurfaceFlinger* flinger;
Client* client;
sp<IBinder>* handle;
sp<IGraphicBufferProducer>* gbp;
status_t result;
const String8& name;
uint32_t w, h;
PixelFormat format;
uint32_t flags;
public:
MessageCreateLayer(SurfaceFlinger* flinger,
const String8& name, Client* client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
: flinger(flinger), client(client),
handle(handle), gbp(gbp),
name(name), w(w), h(h), format(format), flags(flags) {
}
status_t getResult() const { return result; }
//MessageQueue.cpp 中方法回调MessageBase::handleMessage
virtual bool handler() {
result = flinger->createLayer(name, client, w, h, format, flags,
handle, gbp);
return true;
}
}; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
name, this, w, h, format, flags, handle, gbp);
mFlinger->postMessageSync(msg);
return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

 上述可看出,将创建layer消息放入队列,如下所示:

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
nsecs_t reltime, uint32_t /* flags */) {
status_t res = mEventQueue.postMessage(msg, reltime);
if (res == NO_ERROR) {
//阻塞等待消息处理完成
msg->wait();
}
return res;
}

1.8 Layer.cpp

创建layer的消息被处理时,就会回调上述MessageCreateLayer类中的handler方法。handler方法中调用flinger.createLayer(),第一次还会执行Layer.onFirstRef()

status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
//ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
if (int32_t(w|h) < ) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
return BAD_VALUE;
} status_t result = NO_ERROR; sp<Layer> layer; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createNormalLayer(client,
name, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceDim:
result = createDimLayer(client,
name, w, h, flags,
handle, gbp, &layer);
break;
default:
result = BAD_VALUE;
break;
} if (result != NO_ERROR) {
return result;
} result = addClientLayer(client, *handle, *gbp, layer);
if (result != NO_ERROR) {
return result;
} setTransactionFlags(eTransactionNeeded);
return result;
}

在执行Layer::onFirstRef()会新建一个缓冲区队列的消费者与客户端APP的生产者对应:

void Layer::onFirstRef()

//surfaceflinger中新建一个缓冲区队列的消费者
mBufferQueue = new SurfaceTextureLayer(mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage());
mSurfaceFlingerConsumer->setFrameAvailableListener(this);
mSurfaceFlingerConsumer->setName(mName); #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
#warning "disabling triple buffering"
mSurfaceFlingerConsumer->setDefaultMaxBufferCount();
#else
mSurfaceFlingerConsumer->setDefaultMaxBufferCount();
#endif const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
updateTransformHint(hw);

Surface(Native层)


(1)FrameBuffer(帧缓冲,存储图形、图像的缓冲):

  Frame:帧,就是指一幅图像。在屏幕a上看到的一幅图像就是一帧。

  Buffer:缓冲,就是一段存储区域(存储的是帧) 。

(2) PageFlipping(画面交换),用于图像、图形数据的生产和消费

  操作过程:

    1、分配一个能容纳两帧数据的缓冲Buffer,前面一个缓冲叫FrontBuffer,后一个叫BackBuffer;

    2、消费者使用FontBuffer中的旧数据,而生产者使用新数据填充BackBuffer,二者互不干扰;

    3、当需要更新显示时,BackBuffer变成oFrontBuffer,FrontBuffer变成BackBuffer。如此循环。

「Android」 Surface分析的更多相关文章

  1. 「Android」SurfaceFlinger分析

    本篇针对surfaceFlinger模块进行分析,目录如下: 1.SurfaceFlinger功能 1.1.BufferQueue原理(native/libs/gui模块) 1.2   layer显示 ...

  2. 「Android」消息驱动Looper和Handler类分析

    Android系统中的消息驱动工作原理: 1.有一个消息队列,可以往这个消息队列中投递消息; 2.有一个消息循环,不断的从消息队列中取得消息,然后处理. 工作流程: 1.事件源将待处理的消息加入到消息 ...

  3. 「Android」adb调试源码(针对dumpsys SurfceFlinger、trace.txt获取)

    首先对ADB作简单的阐述,接下来对adb shell dumpsys SurfaceFlinger服务的dump信息的查看.以及ANR问题如何获取trace文件并简单分析. -×*********** ...

  4. 「Android」 基于Binder通信的C/S架构体系认知

    C/S架构(Client/Server,即客户机/服务器模式)分为客户机和服务器两层:第一层是在客户机系统上结合了表示与业务逻辑,第二层是通过网络结合了数据库服务器.简单的说就是第一层是用户表示层,第 ...

  5. 「Android」GreenDao

    译文 版本:greenDAO 3.2.2 官网:http://greenrobot.org/greendao/ GitHub:https://github.com/greenrobot/greenDA ...

  6. 「Android」系统架构概述

    目录: 1.Android系统架构 2.Android类库 3.四大组件 --------------------------------------------------------------- ...

  7. 「Android」单例的五种写法

    单例 发现博客园可以很好的设置自己的博客文章的展示,很开心,然后特此发一篇 其实这几种写法大家应该都会的,就权当拿来记录一下吧,以后复习巩固也比较方便. 这篇文章中的代码,来自一篇视频(我想找视频贴上 ...

  8. LOJ 3184: 「CEOI2018」斐波那契表示法

    题目传送门:LOJ #3184. 题意简述: 题目说得很清楚了. 题解: 首先需要了解「斐波那契数系」为何物. 按照题目中定义的斐波那契数列 \(F_n\),可以证明,每个非负整数 \(n\) 都能够 ...

  9. Android逆向之旅---静态方式分析破解视频编辑应用「Vue」水印问题

    一.故事背景 现在很多人都喜欢玩文艺,特别是我身边的UI们,拍照一分钟修图半小时.就是为了能够在朋友圈显得逼格高,不过的确是挺好看的,修图的软件太多了就不多说了,而且一般都没有水印啥的.相比较短视频有 ...

随机推荐

  1. 利用 ELK 搭建 Docker 容器化应用日志中心

    利用 ELK 搭建 Docker 容器化应用日志中心 概述 应用一旦容器化以后,需要考虑的就是如何采集位于 Docker 容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 ...

  2. Linux编程 17 文件权限(权限设置chmod,改变文件属主属组关系chown,chgrp)

    一. 概述 如果创建了一个目录或文件,有时会需要改变它的安全性设置,在linux系统上有一些工具可以完成这任务,包括使用chmod命令改变已有默认权限,分别能对属主,属组,其它用户的权限的控制分别以读 ...

  3. [Jenkins][Git]ssh原理以及与https的区别

    -------------------------------------------------------------------- 本文参考多篇文章结合自身情况完成,可自由转载,需保留本文出处! ...

  4. LearnOpenGL学习笔记(五)——纹理

    在设计物体表面时,很多时候我们不满足于一种颜色或者几种简单颜色,我们希望是丰富多彩的图案,或者说我们提供给它的图片.这样一个顶点一个顶点的去指定那是行不通了,我们不可能把所有顶点用数字去表达出来,必须 ...

  5. Vc数据库编程基础MySql数据库的常见库命令.跟表操作命令

    Vc数据库编程基础MySql数据库的常见操作 一丶数据库常见的库操作 1.1查看全部数据库 命令:  show databases 1.2 创建数据库 命令: Create database 数据库名 ...

  6. #if 与 #ifdef 之间的区别

    先来看个例子: #define TARGET_LITTLE_ENDINA 1 #define TARGET_BIG_ENDINA 0 #ifdef TARGET_LITTLE_ENDINA call ...

  7. 连接MySQL的10060错误:Can't connect to MySQL server on '*.*.*.*'(10060)

    使用MySQL的图形界面管理工具Navicat for MySQL连接Mysql数据库时提示错误:Can't connect to MySQL server (10060) [出现该问题可能的原因:] ...

  8. Web网站配置Gzip,压缩js css文件

    启用apache的gzip 找到httpd.conf,打开文件找到对mod_deflate的注释 #LoadModule deflate_module modules/mod_deflate.so 去 ...

  9. 博客使用base64编码图片测试

    为了解决发博客时需要先要上传,所以查了一下这个方法 1.把本地图片转为base64编码的字符串, 网上有很多提供这个功能的网站,转换后像这样 data:image/jpeg;base64,/9j/4A ...

  10. php获取服务器信息常用方法(零碎知识记忆)

    突然整理下零碎小知识.......加深下印象: $info = array( '操作系统'=>PHP_OS, '运行环境'=>$_SERVER["SERVER_SOFTWARE& ...