一 目的

本节的目的就是为了讲清楚 Android 中的 Surface 系统,大家耳熟能详的 SurfaceFlinger 到底是个什么东西,它的工作流程又是怎样的。当然,鉴于 SurfaceFlinger

一个 Activity

接着我们把其中的关键调用抽象在 Native 层,以这些函数调用为切入点来研究 SurfaceFlinger

二 Activity

最初的想法就是, Activity 获得一块显存,然后在上面绘图,最后交给设备去显示。这个道理是没错,但是 Android 的 SurfaceFlinger 是在 System Server 进程中创建的, Activity 一般另有线程,这之间是如何 ...

好吧,我们从

Activity
framework/base/core/java/android/app/ActivityThread.java 中,这里有个函数叫 handleLaunchActivity
[---->ActivityThread:: handleLaunchActivity()]
 
private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
       Activity a = performLaunchActivity(r, customIntent);
 
         if (a != null) {
             r.createdConfig = new Configuration(mConfiguration);
             Bundle oldState = r.state;
             handleResumeActivity(r.token, false, r.isForward);
----> 调用handleResumeActivity
}
 
handleLaunchActivity 中会调用 handleResumeActivity
[--->ActivityThread:: handleResumeActivity]
 
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
          boolean willBeVisible = !a.mStartedActivity;
           
if (r.window == null && !a.mFinished && willBeVisible) {
                 r.window = r.activity.getWindow();
                 View decor = r.window.getDecorView();
                 decor.setVisibility(View.INVISIBLE);
                 ViewManager wm = a.getWindowManager();
                 WindowManager.LayoutParams l = r.window.getAttributes();
                 a.mDecor = decor;
                 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                 if (a.mVisibleFromClient) {
                      a.mWindowAdded = true;
                     wm.addView(decor, l); //
                 }
 
上面 addView 那几行非常关键,它关系到咱们在 Activity 中 setContentView 后,整个 Window 到底都包含了些什么。我先告诉大家。所有你创建的 View 之上,还有一个 DecorView ,这是一个 FrameLayout ,另外还有一个 PhoneWindow
framework/Policies/Base/Phone/com/android/Internal/policy/impl 。这些隐藏的 View 的创建都是由你在 Acitivty 的 onCreate 中调用 setContentView
[---->PhoneWindow:: addContentView]
 
    public void addContentView(View view, ViewGroup.LayoutParams params) {
         if (mContentParent == null) {   // 刚创建的时候mContentParent
             installDecor();
         }
         mContentParent.addView(view, params);
         final Callback cb = getCallback();
         if (cb != null) {
             cb.onContentChanged();
         }
}
installDecor 将创建mDecor 和mContentParent 。mDecor 是DecorView
mContentParent 是ViewGroup
private void installDecor() {
         if (mDecor == null) {
             mDecor = generateDecor();
             mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
             mDecor.setIsRootNamespace(true);
         }
         if (mContentParent == null) {
             mContentParent = generateLayout(mDecor);
 
那么, ViewManager wm = a.getWindowManager()
PhoneWindow 从 Window 中派生, Acitivity 创建的时候会调用它的 setWindowManager 。而这个函数由 Window
代码在 framework/base/core/java/android/view/Window.java
 
public void setWindowManager(WindowManager wm,IBinder appToken, String appName) {
         mAppToken = appToken;
         mAppName = appName;
         if (wm == null) {
             wm = WindowManagerImpl.getDefault();
         }
         mWindowManager = new LocalWindowManager(wm);
     }
 
你看见没,分析 JAVA 代码这个东西真的很复杂。 mWindowManager 的实现是 LocalWindowManager ,但由通过 Bridge 模式把功能交给 WindowManagerImpl
真的很复杂!
好了,罗里罗嗦的,我们回到 wm.addView(decor, l) 。最终会由 WindowManagerImpl
addView
代码在 framework/base/core/java/android/view/WindowManagerImpl.java
[---->addView]
 
private void addView(View view, ViewGroup.LayoutParams params, boolean nest)
     {
           ViewRoot root; //ViewRoot
          synchronized (this) {
           root = new ViewRoot(view.getContext());
           root.mAddNesting = 1;
           view.setLayoutParams(wparams);
            
             if (mViews == null) {
                 index = 1;
                 mViews = new View[1];
                 mRoots = new ViewRoot[1];
                 mParams = new WindowManager.LayoutParams[1];
             } else {
            }
             index--;
             mViews[index] = view;
             mRoots[index] = root;
             mParams[index] = wparams;
         }
         root.setView(view, wparams, panelParentView);
}
 
ViewRoot 是整个显示系统中最为关键的东西,看起来这个东西好像和 View 有那么点关系,其实它根本和 View 等 UI 关系不大,它不过是一个 Handler 罢了,唯一有关系的就是它其中有一个变量为 Surface 类型。我们看看它的定义。 ViewRoot
framework/base/core/java/android/view/ViewRoot.java
 
public final class ViewRoot extends Handler implements ViewParent,
         View.AttachInfo.Callbacks
{
private final Surface mSurface = new Surface();
}
它竟然从handler 派生,而ViewParent
 
看到 Surface 直觉上感到它和 SurfaceFlinger
Surface 代码在 framework/base/core/java/android/view/Surface.java
 
public Surface() {
        mCanvas = new CompatibleCanvas(); // 就是创建一个Canvas
}
 
如果你有兴趣的话,看看 Surface 其他构造函数,最终都会调用 native 的实现,而这些 native 的实现将和 SurfaceFlinger 建立关系,但我们这里 ViewRoot 中的 mSurface 显然还没有到这一步。那它到底是怎么和 SurfaceFlinger
另外,为什么 ViewRoot 是主人公呢?因为 ViewRoot 建立了客户端和 SystemServer
 
public ViewRoot(Context context) {
         super();
        ....
        getWindowSession(context.getMainLooper());
}
getWindowsession 将建立和WindowManagerService
ublic static IWindowSession getWindowSession(Looper mainLooper) {
         synchronized (mStaticInit) {
             if (!mInitialized) {
                 try {
                 //sWindowSession 是通过Binder
                     InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
                     sWindowSession = IWindowManager.Stub.asInterface(
                             ServiceManager.getService("window"))
                             .openSession(imm.getClient(), imm.getInputContext());
                      mInitialized = true;
                 } catch (RemoteException e) {
                 }
             }
             return sWindowSession;
         }
     }
 
上面跨 Binder 的进程调用另一端是 WindowManagerService
framework/base/services/java/com/android/server/WindowManagerService.java
回过头来看看 ViewRoot
[-->ViewRoot::setView()]
 
public void setView(View view, WindowManager.LayoutParams attrs,
             View panelParentView) {
         synchronized (this) {
             requestLayout(); 
                 try {
                     res = sWindowSession.add(mWindow, mWindowAttributes,
                             getHostVisibility(), mAttachInfo.mContentInsets);
                 } 
}
 
requestLayout 实现很简单,就是往 handler
 
public void requestLayout() {
         checkThread();
         mLayoutRequested = true;
         scheduleTraversals(); // 发送DO_TRAVERSAL
} 
public void scheduleTraversals() {
         if (!mTraversalScheduled) {
              mTraversalScheduled = true;
             sendEmptyMessage(DO_TRAVERSAL);
         }
}
 
我们看看跨进程的那个调用。 sWindowSession.add 。它的最终实现在 WindowManagerService
[--->WindowSession::add()]
 
public int add(IWindow window, WindowManager.LayoutParams attrs,
                  int viewVisibility, Rect outContentInsets) {
             return addWindow(this, window, attrs, viewVisibility, outContentInsets);
         }
 
WindowSession 是个内部类,会调用外部类的 addWindow
这个函数巨复杂无比,但是我们的核心目标是找到创建显示相关的部分。所以,最后精简的话就简单了。
[--->WindowManagerService:: addWindow]
 
public int addWindow(Session session, IWindow client,
             WindowManager.LayoutParams attrs, int viewVisibility,
             Rect outContentInsets) {
         // 创建一个WindowState
               win = new WindowState(session, client, token,
                     attachedWindow, attrs, viewVisibility);
            win.attach();
            return res;
}
 
WindowState 类中有一个和 Surface 相关的成员变量,叫 SurfaceSession
attach 函数中被创建。 SurfaceSession 嘛,就和 SurfaceFlinger
好,我们知道 ViewRoot 创建及调用 add 后,我们客户端的 View 系统就和 WindowManagerService
另外,我们知道 ViewRoot 是一个 handler ,而且刚才我们调用了 requestLayout ,所以接下来消息循环下一个将调用的就是 ViewRoot 的 handleMessage
 
public void handleMessage(Message msg) {
         switch (msg.what) {
        case DO_TRAVERSAL:
             performTraversals();
 
performTraversals 更加复杂无比,经过我仔细挑选,目标锁定为下面几个函数。当然,后面我们还会回到 performTraversals ,不过我们现在更感兴趣的是 Surface
 
private void performTraversals() {
         // cache mView since it is used so much below...
         final View host = mView;
 
           boolean initialized = false;
             boolean contentInsetsChanged = false;
             boolean visibleInsetsChanged;
             try {
//ViewRoot 也有一个Surface 成员变量,叫mSurface ,这个就是代表SurfaceFlinger
//ViewRoot 在这个Surface 上作画,最后将由SurfaceFlinger 来合成显示。刚才说了mSurface
            relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
 
[---->ViewRoot:: relayoutWindow()]
 
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
             boolean insetsPending) throws RemoteException {
         
//relayOut 是跨进程调用,mSurface
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
                 (int) (mView.mMeasuredWidth * appScale + 0.5f),
                 (int) (mView.mMeasuredHeight * appScale + 0.5f),
                 viewVisibility, insetsPending, mWinFrame,
                 mPendingContentInsets, mPendingVisibleInsets,
                 mPendingConfiguration, mSurface); mSurface
        }
 
我们赶紧转到 WindowManagerService
 
public int relayoutWindow(Session session, IWindow client,
             WindowManager.LayoutParams attrs, int requestedWidth,
             int requestedHeight, int viewVisibility, boolean insetsPending,
             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
              Configuration outConfig, Surface outSurface){
                .....
           try {
            //
          // 其中win 是我们最初创建的WindowState
                     Surface surface = win.createSurfaceLocked();
                     if (surface != null) {
                   // 先创建一个本地surface ,然后把传入的参数outSurface copyFrom
                          outSurface.copyFrom(surface);
                         win.mReportDestroySurface = false;
                         win.mSurfacePendingDestroy = false;
                        } else {
                        outSurface.release();
                      }
                 }
}
 
[--->WindowState::createSurfaceLocked]
 
Surface createSurfaceLocked() {
          
                 try {
                     mSurface = new Surface(
                             mSession.mSurfaceSession, mSession.mPid,
                              mAttrs.getTitle().toString(),
                             0, w, h, mAttrs.format, flags);
                   } 
                 Surface.openTransaction();
 
这里使用了 Surface
 
     public Surface(SurfaceSession s,
             int pid, String name, int display, int w, int h, int format, int flags)
         throws OutOfResourcesException {
         mCanvas = new CompatibleCanvas();
         init(s,pid,name,display,w,h,format,flags); ----> 调用了native 的init
         mName = name;
}
 
到这里,不进入 JNI
l           add 中, new 了一个 SurfaceSession
l           创建 new 了一个 Surface
l           调用 copyFrom ,把本地 Surface 信息传到 outSurface
JNI
上面两个类的 JNI 实现都在 framework/base/core/jni/android_view_Surface.cpp
  [---->SurfaceSession:: SurfaceSession()]
 
public class SurfaceSession {
     /** Create a new connection with the surface flinger. */
     public SurfaceSession() {
         init();
}
 
它的 init
[--->SurfaceSession_init]
 
static void SurfaceSession_init(JNIEnv* env, jobject clazz)
{
    //SurfaceSession 对应为SurfaceComposerClient
     sp<SurfaceComposerClient> client = new SurfaceComposerClient;
client->incStrong(clazz);
//Google 常用做法,在JAVA 对象中保存C++
     env->SetIntField(clazz, sso.client, (int)client.get());
}
 
Surface 的 init
[--->Surface_init]
 
static void Surface_init(
         JNIEnv* env, jobject clazz, 
         jobject session,
         jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)
{
    SurfaceComposerClient* client =
             (SurfaceComposerClient*)env->GetIntField(session, sso.client);
 
     sp<SurfaceControl> surface;
if (jname == NULL) {